Commit Graph

84 Commits

Author SHA1 Message Date
relrelb 89f3445d62 swf: Introduce and use `Rectangle::width()` and `Rectangle::height()` 2022-11-01 09:49:04 +02:00
Aaron Hill 68471723b3 core: Fix clippy format string lint 2022-10-27 08:49:39 +03:00
Aaron Hill 45515be0a3 render: Improve support for BitmapData.draw
This PR fixes a numbe of interconnected bugs:
* We weren't consistently uploading a dirty BitmapData to the render
  backend before drawing to/from it.
* BitmapData.draw should *not* add a fill color - it should draw over
  the current contents of the BitmapData
* After drawing to a non-transparent BitmapData, we need to manually
  set the opacity back to 255 for each pixel (the drawing process
  takes transparency into account, but the opacity information is
  thrown away at the end).
2022-10-17 12:53:38 -05:00
Aaron Hill 423d7e4cc4 render: Treat `update_texture` with invalid `BitmapHandle` as an error
This should be impossible to trigger from ActionScript, so
we shouldn't ignore it.
2022-09-16 22:03:15 -06:00
Nathan Adams 267ea0fd13 render: Introduced render commands, moved to a command list model instead of direct rendering 2022-09-11 09:07:53 +02:00
Aaron Hill 93607aa86e
avm2: Implement `BitmapData.draw` for `wgpu` backend (#7254)
* 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`
2022-09-06 16:38:48 -05:00
= 201ed60d67 canvas: Removed generic error, was never actually used - just an Option worked better 2022-08-25 23:43:21 +02:00
= 461c977be0 render: unregister_bitmap is infallible, removed error path 2022-08-25 23:43:21 +02:00
= 03eb769a33 render: Made render use a real Error enum and not generic box<error> 2022-08-25 23:43:21 +02:00
Aaron Hill 98c7f443ce core: Only store viewport dimensions in `RenderBackend`
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.
2022-08-22 13:44:30 -07:00
Mike Welsh 0861bc86eb canvas: Stub out more blend modes 2022-08-18 16:38:17 -07:00
Aaron Hill f7205a02a9 render: Add BlendMode infrastructure and implement BlendMode.ADD
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.
2022-08-18 16:38:17 -07:00
Nathan Adams e1f38b26c0 render: Removed ruffle_core dep from all renderers 2022-08-14 18:38:14 -07:00
Nathan Adams 824b4aa8d1 render: Moved render backend from core to render 2022-08-14 18:38:14 -07:00
Nathan Adams f088d8ac3a render: Moved color_transform from core to render 2022-08-14 18:38:14 -07:00
Nathan Adams 35082b687f render: Moved shape_utils from core to render 2022-08-14 18:38:14 -07:00
Nathan Adams 91a7047ebb render: Moved Matrix from core to render 2022-08-14 18:38:14 -07:00
Nathan Adams bc0c7cbccb render: Made new render crate, moved Bitmap stuff to it 2022-08-14 18:38:14 -07:00
Mike Welsh 6f142c21fa canvas: Fix transforming of gradient/bitmap strokes 2022-07-19 15:01:17 -07:00
Mike Welsh 1980d6f420 canvas: Scale stroke width based on shape transform 2022-07-19 15:01:17 -07:00
relrelb 115f15806e chore: Fix `needless_borrow` clippy lints
Though https://github.com/rust-lang/rust-clippy/pull/8355 has been
merged, it seems to still report false-positives on nightly channel.

For now just fix the instances reported by stable clippy, and keep
`needless_borrow` allowed.
2022-07-08 14:14:30 +03:00
Aaron Hill a79aa08f08
core: Free render backend resources on `BitmapData.dispose`
Currently, all three render backends hold on texture-related
resources indefinitely (`register_bitmap` pushes to a `Vec`,
and never removes anything). As a result, the resources used
by the render backend (which may include GPU memory) will grow
over time, even if the corresponding `BitmapData` has been deallocated.

This commit adds a new `unregister_bitmap` method, which is called from
`BitmapData.dispose`. All render backs are changed to now use an
`FnvHashMap<BitmapHandle, _>` instead of a `Vec`, allowing us to
remove individual entries.

Currently, we only call `unregister_bitmap in response to
`BitmapData.dispose` - when `BitmapData` is freed by the
garbage collector, `unregister_bitmap` is *not* called.
This will be addressed in a future PR.
2022-06-29 15:16:43 -07:00
relrelb 53ef80f514 render: Introduce `RenderBackend::register_bitmap`
Since all `RenderBackend::register_bitmap_*` implementations are
identical now, move them to the default implementation of `RenderBackend`.

Also, turn `RenderBackend::register_bitmap_raw` into `RenderBackend::register_bitmap`,
which accepts a single `Bitmap` parameter.
2022-06-02 15:27:29 -07:00
relrelb 34d5a8f9d4 canvas: Remove dead `srgb_to_linear` function
There's another similar function in `core/src/backend/render.rs`.
2022-05-31 21:48:11 +03:00
Mike Welsh 4f6959184b canvas: Remove `BitmapDataStorage` and fix lifetime of bitmap data
* Remove `BitmapDataStorage` as its no longer necessary, and store
   the bitmap canvas/context in `BitmapData` instead.
 * Store the `Bitmap` RBGA buffer in the canvas backend. Previously
   this was thrown away when converted to `ImageData`, but this
   causes the glitchy pixels mentioned in:
   https://github.com/ruffle-rs/ruffle/pull/6975#issuecomment-1127942520
   `ImageData` does not copy the buffer passed to it, so store it
   to keep it alive. See:
   https://github.com/rustwasm/wasm-bindgen/issues/2445
2022-05-22 05:47:46 -07:00
Mike Welsh ff3407cbe0 canvas: Use `DomMatrix` instead of `SvgMatrix` 2022-05-21 19:34:49 -07:00
Mike Welsh 169e86ceb4 canvas: Reimplement masking
Use `CanvasRenderingContext2d.clip` for masking instead of using
intermediate canvases.
2022-05-21 19:34:49 -07:00
Mike Welsh c503f78e13 canvas: Remove `pixelated_property_value`
This is no longer used with the removal of the SVG paths in #6975.
2022-05-19 16:12:54 -07:00
Mike Welsh a10c2ff9c7 canvas: Remove Firefox hack for additive alpha color transforms
This was added in fecb981 to workaround an issue with additive
alpha color transforms in Firefox. This seems to have been fixed
and is no longer necessary, so Firefox can use the normal code
path.
2022-05-19 16:12:54 -07:00
Mike Welsh 48f7ff5f4d core: Add `Bitmap::to_rgba` 2022-05-19 10:43:54 -07:00
Mike Welsh e710f3fa0e core: Clean up `render::Bitmap`
* Make `BitmapFormat` a fieldless enum and move `data` to its own
   field for ease of use.
 * Make `Bitmap` fields private.
2022-05-19 10:43:54 -07:00
Mike Welsh 6615ed17f9 core: Verify bitmap length after decoding
Guarantee bitmap data after decoding has the expected length for
the given width+height+format. This eases the burden from backends
to worry about this. Pad or truncate the data if it doesn't have
the expected size.
2022-05-19 10:43:54 -07:00
Mike Welsh 2f99d039cc canvas: Remove `BitmapDataStorage::ImageElement`
Remove the `ImageElement` data path for storing bitmaps, as the
asynciness of this is difficult to manage when we need to render
bitmaps immediately. This code path was only being used for JPEG
images that could be decoded by the browser (no alpha).

Instead, always use canvases for bitmap storage. This simplifies
the code and solves some issues with bitmaps not being rendered
properly, although it is likely a little slower toe decode these
JPEGs on the Rust side.
2022-05-16 17:13:48 -07:00
Mike Welsh d0aa7b4df2 canvas: Remove SVG rendering path
Remove `CanvasDrawCommand::DrawImage` and all associated machinery
that generates an SVG.
2022-05-16 17:13:48 -07:00
Mike Welsh ce044409e4 canvas: Use canvas drawing commands for gradients
Most gradients are "simply transformed" and can be rendered
directly using canvas commands. But even for complex transforms,
we can push the gradient's transform to the canvas, then
un-transform the path using the inverse of the gradient transform.
2022-05-16 17:13:48 -07:00
relrelb f6153ff7c1 chore: Appease clippy 2022-05-06 10:36:38 -07:00
Mike Welsh 3305ac69c4 web: Support wmode parameter 2022-04-17 08:33:51 -07:00
Mike Welsh e1fbcc70f8 canvas: Handle gradient/bitmap strokes 2022-04-11 22:50:40 -07:00
Mike Welsh 146b8adc68 swf: Clean up LineStyle
* Remove LineStyle::color, instead using fill_style with
   FillStyle::Color to indicate solid color.
 * Store `flags` in the struct instead of separate bools/values.
 * Add getters/setters for ease of use.
 * Add builder-style methods for setting LineStyle properties.
 * Fix misnamed ALLOW_CLOSE flag to NO_CLOSE.
2022-04-11 22:50:40 -07:00
relrelb e27240e434 canvas: Remove `clamped_u8_color` function
Since Rust 1.45, the `as` keyword performs a saturating cast when
casting from float to int. Therefore the `clamped_u8_color` function
is useless, and `as` can be simply used instead.
2022-03-28 14:33:32 -07:00
relrelb f8f2764ac7 chore: Stop using traits available in prelude
This commit does the same as 36353df7f7,
cleaning up any leftovers and new code added since.
2022-03-14 01:16:00 +02:00
relrelb b405870005 canvas: Clamp alpha values
Values outside the range of 0 and 1 are ignored in canvas, unlike
Flash that clamps them.
2021-12-21 08:34:47 +02:00
TÖRÖK Attila 4057332e6b web/canvas: Carry bitmap smoothing flag along with the pattern 2021-12-12 20:43:21 +01:00
TÖRÖK Attila bf470f8a78 web/canvas: Add some TODO and NOTE comments 2021-12-12 20:43:21 +01:00
TÖRÖK Attila 7389b2b9ce web/canvas: Convert CanvasPattern transformation matrix from Twips to regular numbers
The reason this did not cause problems so far was that it was far more
common to fall back to the SVG backend right before this piece of code.
2021-12-12 20:43:21 +01:00
TÖRÖK Attila 57838f882d web/canvas: Respect the smoothing flag when rendering bitmaps 2021-12-12 20:43:21 +01:00
TÖRÖK Attila d5df37afb3 web/canvas: Use a canvas element to store bitmaps from raw RGBA sources
To avoid PNG-encoding every frame of every video for example.

If it needs to be converted to a base64 "data:" URL anyway,
compute it lazily and cache it behind a RefCell.

Raw pixel manipulation can be done through temporary ImageData objects.
The potential to use an image element is retained, so the native JPEG
decoder of the browser can still be utilized.
2021-12-12 20:43:21 +01:00
relrelb 00accf3e2a render: Rename `register_bitmap_jpeg_3` to `register_bitmap_jpeg_3_or_4`
It's actually used by both DefineBitsJpeg3 and DefineBitsJpeg4 tags.
2021-12-04 21:32:16 +02:00
relrelb e2b821e92f chore: Replace `min` + `max` with `clamp`
`clamp` is a bit more efficient, in both runtime and size terms.
2021-11-26 20:54:48 +02:00
relrelb ff2ef47159 canvas: Fill using the even-odd rule
Flash always uses the even-odd fill rule, whereas canvas defaults to
nonzero.
Specify the fill rule explicitly in both `swf_shape_to_canvas_commands`
and `swf_shape_to_svg`.
2021-11-20 22:48:37 +02:00