Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

web: Deprecate 'canvas' backend #7459

Closed
wants to merge 1 commit into from

Conversation

Aaron1011
Copy link
Member

We currently have 3 render backends: 'canvas', 'webgl', and 'wgpu'.
Assuming that we eventually merge the SVG backend proposed in #1168,
we'll have to maintain 4 independent render backends.

I believe that we should be able to drop 'canvas' support, and
only rely on 'webgl' (and 'wgpu' in the future) for browser
support.

This PR doesn't actually remove anything yet - we just display
a click-through warning:
"Using deprecated canvas backend! Please file a bug report"
when the canvas backend is enabled.

If it turns out that no one ever hits this warning in practice,
we could move to disable the 'canvas' feature in the web
crate by default. If there are still no bug reports, we could
remove the backend entirely.

caniuse.com shows the following global availability percentages:

'HTML element: canvas': 97.25% (https://caniuse.com/mdn-html_elements_canvas)
'WebGL (version 1)': 98.02% (https://caniuse.com/webgl)
'Canvas (basic support)': 99.51% (https://caniuse.com/canvas)

Based on the data, dropping 'canvas' support would essentially only
impact users with WebGL support disabled. It's possible that some
browsers might do this for certain websites for privacy/security
reasons - however, we already require WebAssembly, so I doubt
that WebGL would ever be the only blocker for running Ruffle.

The biggest potential downside to this is implementing
'BitmapData.draw'. In order to support SWFs that perform rapid
'BitmapData.draw; BitmapData.getPixel' sequences, we're going
to need to perform CPU rendering to avoid blocking on copying
data back and forth from the GPU. Using the 'canvas' backend
for 'BitmapData.draw' would be one way to accomplish this - however,
we would still need a separate backend for the desktop.
I believe we could use the SVG backend on all platforms for implementing
'BitmapData.draw'. We'd need to add a dependency on an SVG renderer
for desktop, and abstract over web-sys vs the svg crate. However,
I think the result will be a large net reduction in code and maintenance
burden.

We currently have 3 render backends: 'canvas', 'webgl', and 'wgpu'.
Assuming that we eventually merge the SVG backend proposed in ruffle-rs#1168,
we'll have to maintain 4 independent render backends.

I believe that we should be able to drop 'canvas' support, and
only rely on 'webgl' (and 'wgpu' in the future) for browser
support.

This PR doesn't actually remove anything yet - we just display
a click-through warning:
"Using deprecated canvas backend! Please file a bug report"
when the canvas backend is enabled.

If it turns out that no one ever hits this warning in practice,
we could move to disable the 'canvas' feature in the `web`
crate by default. If there are still no bug reports, we could
remove the backend entirely.

caniuse.com shows the following global availability percentages:

'HTML element: canvas': 97.25% (https://caniuse.com/mdn-html_elements_canvas)
'WebGL (version 1)': 98.02% (https://caniuse.com/webgl)
'Canvas (basic support)': 99.51% (https://caniuse.com/canvas)

Based on the data, dropping 'canvas' support would essentially only
impact users with WebGL support disabled. It's possible that some
browsers might do this for certain websites for privacy/security
reasons - however, we already require WebAssembly, so I doubt
that WebGL would ever be the only blocker for running Ruffle.

The biggest potential downside to this is implementing
'BitmapData.draw'. In order to support SWFs that perform rapid
'BitmapData.draw; BitmapData.getPixel' sequences, we're going
to need to perform CPU rendering to avoid blocking on copying
data back and forth from the GPU. Using the 'canvas' backend
for 'BitmapData.draw' would be one way to accomplish this - however,
we would still need a separate backend for the desktop.
I believe we could use the SVG backend on all platforms for implementing
'BitmapData.draw'. We'd need to add a dependency on an SVG renderer
for desktop, and abstract over `web-sys` vs the `svg` crate. However,
I think the result will be a large net reduction in code and maintenance
burden.
@relrelb
Copy link
Contributor

relrelb commented Jul 23, 2022

Honestly I think the canvas backend is still useful. Apart from being helpful for testing stuff, it should be necessary for Ruffle to work on privacy browsers like Tor, which does support WebAssembly. Whether or not such support is important is arguable, though.
Maybe we can reconsider this once we have a fully-working SVG renderer backend, but at least now, it feels too early to me to start deprecating something we don't yet have a proper alternative for.

@Toad06
Copy link
Member

Toad06 commented Jul 23, 2022

I agree with relrel. There are also issues like #1905 that should be considered first imho because if there's no reliable way to fix these, we may need to fallback to the canvas render.

@Herschel
Copy link
Member

Herschel commented Jul 25, 2022

I can certainly sympathize with wanting to reduce the # of render backends, but I agree with the above -- the canvas backend has use, so I wouldn't want to deprecate it. There are a few users of it (privacy-aware browsers like Tor and Brave, #1992), and although we don't guarantee support for these, I don't mind trying to support these when it's not too hard. More importantly to me, the canvas backend is a nice reference backend for comparison with our GPU backends.

An SVG backend would be good for:

  • We could share code with desktop using an SVG rasterizer library, potentially eliminating a renderer backend.
  • There are some features that the Canvas2D API doesn't expose (gradient repeat modes, etc.), while SVG does.

But there are these issues:

  • Generating the SVG is an extra step, so I imagine the performance for spitting out SVG vs using the canvas API directly would be worse.
  • This would apply to an SVG backend on desktop as well; for example, if we were using skia, it'd be better to use its drawing API directly, instead of feeding it SVG.
  • In JavaScript, dealing with SVG tends to put you in async land. To draw an SVG to a canvas, you have to go through createImageBitmap, or load the SVG into an ImageElement, which are promises. This makes it difficult to deal with in our frame loop, which wants to render things synchronously, particularly in cases like the drawing API that draws things on demand. In fact, this was already a problem in our canvas renderer, which originally used SVG for complex cases. This led me to remove all the SVG code in the canvas renderer (canvas: Use canvas drawing commands for gradients #6975, see also canvas: Remove BitmapDataStorage and fix lifetime of bitmap data #7051). Possibly throwing the SVG directly on the DOM would work, or I've missed some simple ways of dealing with the above -- this would need some investigation.

I'm definitely okay if someone wants to take a stab at getting the SVG backend up and running on web. It'd also be neat to be able to take SVG screenshots. But it's all relatively low priority in my estimation. Personally, I didn't have plans of working on #1168 at this point. It was more useful when we were using SVG in the canvas backend already, but as I've found workarounds to use pure canvas in these cases, it seems less important.

@relrelb
Copy link
Contributor

relrelb commented Jul 28, 2022

Is there any work pending this PR? Sorry @Aaron1011, but I think we should close this without merging.

@Herschel
Copy link
Member

Yep, gonna close this one -- we can revisit if an SVG backend is fleshed out.

@Herschel Herschel closed this Jul 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants