When rendering offscreen, we want the resulting image to use
premultiplied alpha, since the image will be stored in a texture.
However, when capturing an image in the exporter or test framework,
we want to use straight alpha, so that the resulting image can
be saved as a PNG.
Previously, we incorrectly used straight alpha everywhere, resulting
in incorrect output when using BitmapData.draw with transparency.
We now check if a BitmapData has been disposed by checking
for a zero width or height (which cannot happen otherwise).
As a result, we no longer need the 'disposed' field on the AVM1
BitmapData object.
* avm2: Implement `BitmapData.draw` for `wgpu` backend
This method requires us to have the ability to render directly to a
texture. Fortunately, the `wgpu` backend already supports this in
the form of `TextureTarget`. However, the rendering code required
some refactoring in order to avoid creating duplicate `wgpu` resources.
The current implementation blocks on copying the pixels back
from the GPU to the CPU, so that we can immediately set them in
the Ruffle `BitmapData`. This is likely very inefficient, but will
work for a first implementation.
In the future, we could explore allowing the CPU image data and GPU
texture to be out of sync, and only synchronized when explicitly
necessary (e.g. on `getPixel` or `setPixel` calls).
* Rename `with_offscreen_backend` to `render_offscreen` and use Bitmap
* Don't panic when backend doesn't implement `render_offscreen`
Fixes some issues with our winding # calculation which would cause
incorrect results for hitTest.
* The convention for handling an intersection at endpoints was
not the same between lines and bezier curves.
* The bezier curve winding # function was not properly handling
some cases where the curve was strictly y-monotonic.
* Simplify the code a bit so that ray-curve intersections are
returned in a consistent order based on upward/downward crossing.
It was only used to make structs `#[derive(gc_arena::Collect)]`, and
generally it doesn't make much sense that `render` needs to be GC-aware.
So instead annotate `render` fields in `core` with `#[collect(require_static)]`.
Reverts #7267
The image tests for the upcoming 'DisplayObject.stageRect' support
differ between Linux and Windows, so we need this support again.
To avoid the Linux filename churn that we previously encountered,
we now only include the platform and graphics backend in the filename
(e.g. `expected-linux-Vulkan`). This may result in some unexpected
'mismatched image' test failures if GHA updates to a version of Lavapipe
that changes rendering output, but this should be relatively easy to
notice.
Previously, the viewport height and width were stored in
both `Stage` and the `RenderBackend`. Any changes to the viewport
dimensions (e.g. due to window resizing) needed to be updated in both
places to keep our handling of the viewport consistent.
This PR adds a new `ViewportDimensions` type, which holds the
width, height, and scale factor. It is stored inside the
`RenderBackend` impl, and is retrieved using the newly added
method `RenderBackend.get_viewport_dimensions`. After a `Player`
has been constructed, any code that needes access to the viewport
dimensions will ultimate go through this method.
Unfortunately, `Stage` needs to use the viewport dimensions
in `build_matrices`. Therefore, any code modifying the viewport
dimensions should go through `player.set_viewport_dimensions`,
which ensures that the stage matrices are rebuilt after the render
backend is updated.
The captured WGPU texture uses premultiplied alpha.
This image gets saved as a PNG, so it should use straight alpha.
Note that all of our current image tests have 'alpha = 1.0' for all
of the pixels, so this currently has no effect.
Each render backend keeps track of a stack of BlenModes,
which are pushed and popped by 'core' as we render objects
in the displaay tree. For now, I've just implemented BlendMode.ADD,
which maps directly onto blend mode supported by each backend.
All other blend modes (besides 'NORMAL') will produce a warning
when we try to render using them. This may produce a very large amount
of log output, but it's simpler than emitting each warning only once,
and will help to point developers in the right direction when they
get otherwise inexplicable rendering issues (due to a blend mode
not being implemented).
The wgpu implementation is by far the most complicated, as we need
to construct a `RenderPipeline` for each possible
`(BlendMode, MaskState)`. I haven't been able to find any documentation
about the maximum supported number of (simultaneous) WebGPU render
pipelines - if this becomes an issue, we may need to register them
on-demand when a particular blend mode is requested.