Additionally also improve the warning message if the routed receiver
disconnects and exit the thread.
If the routed receiver disconnects, we can't receive any canvas messages
anymore, and any control messages can't remedy that, so we might as well
exit.
Testing: Channel changes are covered by existing tests. Exiting the
canvas thread if the routed thread disconnects is not tested, and needs
reviewer attention.
Part of https://github.com/servo/servo/issues/38912
Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
This moves more of HashMap/FnvHashMap to FxHashmap. Again we only
changed instances that do not look security related and have small keys.
Additionally, allocator used the fnv feature which did not seem to be
used.
Testing: Unit Tests and WPT should cover this and functionality change
is highly unlikely.
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Adds epoch to each WR image op command that is sent to compositor. The
renderer now has a `FrameDelayer` data structure that is responsible for
tracking when a frame is ready to be displayed. When asking canvases to
update their rendering, they are given an optional `Epoch` which denotes
the `Document`'s canvas epoch. When all image updates for that `Epoch`
are seen in the renderer, the frame can be displayed.
Testing: Existing WPT tests
Fixes: #35733
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Instead of doing font selection and text shaping in `canvas`, move this
to `script`. This allows canvas to use the shared `Document`
`FontContext`, which has access to web fonts. In addition, ensure that
there is a font style accessible for `OffscreenCanvas` in workers.
Testing: This causes a number of WPT tests to start to pass as web fonts
are
supported on canvas again. In addition, some start to fail as they
expose other
issues:
- The lack of support for the `Context2D.fontStretch` property
- Issues with zerosize gradient interpolation.
- Differences between quoted and unquoted font family names. This seems
like
a timing issue with the way we are handling web fonts. The test seems to
be
expecting Local fonts to be available immediately (without waiting for
them
to load). This isn't how Servo works ATM. Seems like an issue with the
test.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
In general, `raqote` is essentially umaintained and has issues with
quality (for instance text rendering has lots of issues) and removing it
finally lets us remove our dependency on `font-kit`. Although,
`vello_cpu` performance is not yet equal to raqote, rendering quality is
a lot better. It's expected that `vello` and `vello_cpu` performance
will keep improving.
Testing: This is covered by existing WPT tests.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
We really want to remove font-kit from dep tree, so this is the first
step into removing raqote from servo. While vello_cpu is not perfect
replacement, I am confident that we will resolve all issues eventually:
https://github.com/servo/servo/issues/38345 (most important ones already
have PRs).
Reviewable per commit.
Testing: Existing WPT tests.
Try run: https://github.com/sagudev/servo/actions/runs/17138369290
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Move `allow(too_many_arguments)` to the functions that have that issue
and remove `allow(unreachable_pattern)`. Since the `Canvas` enum is also
using conditional compilation the default pattern is not necessary.
Testing: This should not change any behavior and thus is covered by
existing tests.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Bumps `vello`, `vello_cpu`,`skrifa`, and `read-fonts` dependencies.
Notes:
- The primary motivation for this is so that our version of `read-fonts`
matches the version used by current releases of `harfrust`
- `vello_cpu` now defaults to `RenderMode::OptimizeSpeed` so we don't
need to pass this explicitly.
Signed-off-by: Nico Burns <nico@nicoburns.com>
# Objective
Ensure that functionality which uses the raw font data (such as
rendering text to canvas) works correctly on macOS when the specified
font is a system font that lives in an OpenType Collection (`.ttc`)
file.
## Changes made
- The `read_data_from_file` in each backend now returns a `index: u32`
in addition to `data: Vec<u8>`
- The `data` field on the `Font` type has been renamed to `raw` and the
`data` method on the `Font` type has been renamed to `raw_font`. This
allows the index to be cached as computing is moderately expensive on
macOS (on the order of 100 microseconds).
- Both of the above now store/return a `struct RawFont` instead of a
`FontData` where `RawFont` is defined as `struct RawFont { data:
FontData, index: u32 }`.
- The users of the `data` method have been updated to use the cached
index from `data` rather than calling `.index()` each time.
---------
Signed-off-by: Nico Burns <nico@nicoburns.com>
This shows up sometimes in code reviews, so it makes sense that tidy
enforces it. `rustfmt` supports this via comment normalization, but it
does many other things and is still an unstable feature (with bugs).
Testing: There are new tidy tests for this change.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Add some tracing/instrumenting for canvas messages processing.
Testing: We have not tests for tracing code.
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
I mostly did dumb replacement so please check that this is correct. In
addition, `canvas_data::draw_with_shadow` needs some a bit of a closer
look.
Testing: This is covered by existing tests, and it is likely that WPT
tests are unaffected by the precision of the transform, even though it
is technically more correct.
Fixes: #38256
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
When restoring context/state we need to pop all clips from current
state, before we just poped one (even if there was none).
Testing: Added new WPT tests
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
In this PR we moved global alpha handling using temporary layers to
mutation of paint in vello_cpu (we were already doing this in vello
classic). This + not using temporary layer for SrcOver (default and most
common composition operation) allows us to remove most temporary layers
from `with_composition`.
This slightly improves performance of vello backend, but drastically
improves performance of vello_cpu. We are now able to render bunnymark
(100 bunnies) with 60 FPS.
In the future we could cache current layer and change it when
compositing operation changes, although that would complicate clips, so
improvement is questionable.
Testing: Existing WPT tests for functionality, but we do not have any
performance tests.
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
According to my tests `OptimizeSpeed` slight improves performance and it
does NOT affect WPT results in negative way.
Testing: Tested by existing WPT tests.
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
As noted in #38345, vello scenes only grow. While we can reset them when
clearing viewport (#38356) that is not enough. We need to reset scene on
each render (~each frame) and providing old frame as backdrop to new
scene. Be do this lazily so multiple rendering without any changes
should be cheaper, we still do GPUBuffer mapping, because that would
require more complex work.
Testing: Code functionality is covered by existing WPT tests, but we do
not have any performance test.
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Vello scene only ever grows, so we need to clear it as soon as it's
possible (in clear rect). This PR also adds ignore_clips to
vello_backend (already exists in vello_cpu_backend).
Testing: Behavior is verified by existing tests, as this is mainly a
change for performance. There are currently no performance tests. This
makes bunnymark actually playable (from 3 FPS to 20 FPS on vello_cpu).
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
`create_similar_draw_target` is more performant then creating completely
new target (this creates new wgpu device in vello backend).
Testing: This change does not modify test results, but should increase
performance.
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
We want to eventually remove raqote backend, but for now we can gate it
behind a feature (still enabled by default in servoshell) like the rest
of backends. `dom_canvas_backend=auto` will select first available
backend. Builds on top of https://github.com/servo/servo/pull/38310 to
support cases where no backend is available.
Testing: It compiles with or without feature
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Before script just crashed in those cases because IPCSender was dropped,
now we send `None` to tell script about the failure and fail getContext
or registerPainter accordingly.
This PR also unifies `dom_canvas_{backends}_enabled` prefs into
`dom_canvas_backend` which is more flexible in multi-backends scenarios.
Reviewable per commit.
Testing: Added servo specific WPT test.
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
vello_cpu does not have any tests timeouts, because we do not need
download stuff from GPU as all work happens on CPU. So performance wise
it's better then classic vello at least for our usecase. There are some
vello bugs, but I think we will be able to sort them out within
upstream, eventually. Interestingly enough there are no new PASS like
they were with classic vello.
Difference with raqote can be observed here:
https://github.com/sagudev/servo/actions/runs/16549241085/attempts/1#summary-46802486798
## Known vello problems:
- https://github.com/linebender/vello/issues/1119
- https://github.com/linebender/vello/issues/1056
-
`/html/canvas/element/fill-and-stroke-styles/2d.gradient.interpolate.coloralpha.html`
- `kurbo::Cap::Butt` is defect (only visible with big lineWidth)
https://github.com/linebender/vello/issues/1063
- `/html/canvas/element/line-styles/2d.line.cross.html`
- `/html/canvas/element/line-styles/2d.line.miter.acute.html`
- other lack of strong correct problems
(https://github.com/linebender/vello/issues/1063#issuecomment-2998084736):
- `/html/canvas/element/path-objects/2d.path.rect.selfintersect.html`
- `putImageData(getImageData(...), ...)` is lossy (precision problems,
might be due to ImageData being unmultiplied)
-
`/html/canvas/element/pixel-manipulation/2d.imageData.put.unchanged.html`
Testing: Tested using vello_cpu_canvas subsuite
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
We just need to pass user provided FillRule via IPC to canvas paint
thread, then pass it all down to backend, which will handle it.
Testing: Added WPT tests.
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This PR changes surface type from `Vec<u8>` to `Vec<u32>` as this is
native type of raqote's backend. We used unsafe for `Vec<u8>` <->
`Vec<u32>` casting that is replaced with bytemuck. Bytemuck is already
in cargo lock.
Testing: Existing WPT tests.
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This will allow reusing those conversions in vello_cpu backend.
Testing: Just refactor
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Add vello backend by implementing Backend traits in canvas crate (so
this lives in canvas_paint_thread - embedded process). Current
implementation uses normal wgpu, so we block on GPU work. Vello backend
is gated behind `vello` feature and `dom_canvas_vello_enabled` pref.
Feature-wise this backend is on on par with raqote (sometimes better
sometimes worse), but performance wise it's worse.
## Known vello problems:
- image roundtrip does not work (fixed in
https://github.com/linebender/vello/pull/974)
- https://github.com/linebender/vello/issues/1066 (fixed)
- clip layers are not working properly:
https://github.com/linebender/vello/issues/1061
- `/html/canvas/element/pixel-manipulation/2d.imageData.put.*`
- `/html/canvas/element/path-objects/2d.path.clip.intersect.html`
- https://github.com/linebender/vello/issues/1056
-
`/html/canvas/element/fill-and-stroke-styles/2d.gradient.interpolate.coloralpha.html`
- `kurbo::Cap::Butt` is defect (only visible with big lineWidth)
https://github.com/linebender/vello/issues/1063
- `/html/canvas/element/line-styles/2d.line.cross.html`
- `/html/canvas/element/line-styles/2d.line.miter.acute.html`
- other lack of strong correct problems
(https://github.com/linebender/vello/issues/1063#issuecomment-2998084736):
- `/html/canvas/element/path-objects/2d.path.rect.selfintersect.html`
- There is currently no way to do put image properly in vello as we
would need to ignore all clips and other stuff (we try to work around
this on best effort basis)
https://github.com/linebender/vello/issues/1088
- `/html/canvas/element/pixel-manipulation/2d.imageData.put.*`
- precision problems
- `/html/canvas/element/path-objects/2d.path.stroke.scale2.html`
- `/html/canvas/element/path-objects/2d.path.arc.scale.1.html`
## Known servo problems
- bad performance due to blocking on GPU work
- some get/put intensive tests `TIMEOUT`
- proper shadow support (non-blocker as we already are living without it
now)
- support for rect shadow is there but unimplemented currently as that's
the state in raqote
Testing: `mach try vello` will run normal WPT (with raqote) +
vello_canvas subsuite that runs only on `/html/canvas/element`. All
subsuite expectations are stored separately.
Fixes: #36823Fixes: #35230
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Currently we had `GetImageData` and `SendPixels` to obtain pixels from
script thread. This PR unifies those into single `GetImageData` that
does not need canvas size and has optional rect (for obtaining sub
image).
Testing: Existing WPT tests
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This will be needed for vello_cpu. While we could wrap it in RefCell for
inner mut, but that would be less ergonomic and performant.
Testing: Just refactoring, but the code is covered by WPT tests.
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
After #38214 `Backend` trait is only used as DrawTarget builder and as
type holder. By moving types and DrawTarget creation into
`GenericDrawTarget` trait, we can completely remove `Backend` trait.
Testing: Just refactor, but code is covered by WPT tests.
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
I think this simplifies canvas backends greatly. Before there were many
(needless) hoops from abstract to concrete (backend) and back, now we
can do most stuff on abstract types.
Testing: Existing WPT tests
Fixes: #38022
try run: https://github.com/sagudev/servo/actions/runs/16450978211
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Remove unused `Cargo.toml` dependency to reduce binary size.
Testing: Can still compile in different platforms.
Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
This PR removes all `Set*` commands as we will send needed options on
each request. This will allow us to remove most of state handling from
canvas paint thread (currently it's still stateful).
Testing: Existing WPT tests
work towards #38022
try run: https://github.com/sagudev/servo/actions/runs/16413823963
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This PR moves current path handling from canvas paint thread to script's
`CanvasState`. Because we used manual impl for arcto and some prechecks
for early fail before sending IPC we also needed to fix some bugs in
Path impl.
Testing: Existing WPT tests
work towards #38022
try run: https://github.com/sagudev/servo/actions/runs/16316090028
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
We already store transform in context state, so let's just use this when
querying instead of using IPC to ask canvas paint thread.
Testing: Existing WPT tests
work towards #38022
try run: https://github.com/sagudev/servo/actions/runs/16299182583
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Before we stored path in user or device space and do conversions as
needed, but that complicated things.
So we got two options:
1. store path in device space: here we would need to add
`Option<Transform>` to each path command, and before each usage we need
to invert current transform (as current transform is already applied by
stroke/fill and we cannot just pass I, because we need scaling to make
lines thicker)
2. store path in user space and do transform whenever we change the
transform. There is no need to do inverse on uses.
I chose option 2. because it's less complicated and will probably
benefit performance (set transform typically called more rarely than
path building/fill/stroke).
In follow up PR I will move all of this to script, that's why
PathBuilderRef was not removed yet.
Testing: Existing WPT tests
work towards #38022
try run: https://github.com/sagudev/servo/actions/runs/16304221495
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This PR removes existing path(segment) abstractions in favor of
`kurbo::BezPath`, well actually wrapped `kurbo::BezPath`, to ensure
building of valid paths. This allows us better Path2D building in script
and doing all validation and segmentation there and also allows us
remove blocking is_point_in_path on Path2D as we can now do this in
script. Current path is still done on canvas thread side as it will be
harder to move to script (will be done as a follow up), but it now uses
this new path abstraction.
Using kurbo also allows us to ditch our manual svgpath parser with the
one provided by kurbo.
Same code is stolen from: https://github.com/servo/servo/pull/36821.
Testing: Existing WPT tests
Fixes: #37904
wpt run: https://github.com/sagudev/servo/actions/runs/16172191716
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Before we only handled no-repeat for rect, this means we rendered
https://sagudev.github.io/briefcase/no-repeat.html incorrectly (like
firefox). Now if one of the axis is bounded (does not repeat) we clip it
and let other axis be unbounded (technically we clip it to end of
canvas).
This is also needed for vello backend.
Testing: Tests in WPT exists and another test is added.
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This removes assumption about pixel format from backend abstraction to
actual backend implementation. This is important for vello.
Testing: WPT tests
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Dealing with both path and builder makes code complicated and this is
backend internal specific anyway (we often do conversions between the
two just so we get specific functionality). Now I joined both into
single abstractions `Path`, that has all what one needs and let raqote
backend deal with path/pathbuilder coversions.
Motivation: Simplification and in Vello there is only
[BezPath](https://docs.rs/kurbo/0.11.2/kurbo/struct.BezPath.html) so we
use it as both path and pathbuilder.
Reviewable per commit.
Testing: Existing WPT tests
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
I introduced snapshot in #36119 to pack raw bytes and metadata together,
now we take the next step and require for user to always specify what
kind of byte data they want when calling `as_bytes` or `to_vec`
(basically joining transform and data). There are also valid usages when
one might require just one property of bytes (textures can generally
handle both RGBA and BGRA). There are also valid usages of using just
raw bytes (when cropping). This PR tries to make such usages more
obvious.
This will make it easier to fix stuff around 2d canvas (we do not want
to assume any bytes properties in abstraction).
Testing: Code is covered by WPT tests.
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This creates a new method in shared/compositing/lib to generate image
keys that are send over the webview. This does not immediately return
the keys but goes over the constellation to receive the keys from the
IOCompositor. To make this more efficient, we now cache the keys in
image_cache in a simple FIFO order. The old blocking method stays intact
for now but got renamed to make the blocking clear.
The blocking calls that are left are in:
- `components/canvas/canvas_data.rs`
- `components/script/dom/htmlmediaelement.rs`
Testing: WPT tests should cover this as this doesn't change any
functionality.
Fixes: Was mentioned in
https://github.com/servo/servo/issues/37161#issuecomment-2915750051 and
part of https://github.com/servo/servo/issues/37086
---------
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Co-authored-by: gterzian <2792687+gterzian@users.noreply.github.com>
While raqote does already passes this test, but small line is still
visible and this PR will fix this. Vello will not work correctly without
this.

Testing: `/html/canvas/element/path-objects/2d.path.arc.twopie.1.html`
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Before we only offered helper to add single image (no update or delete)
that got special IPC message, now we simplify this by offering all ops
helpers for dealing with single image (that happens most of the time),
that simply uses `update_images` under the hood. We also optimize for
this use case by using `SmallVec<[ImageUpdate; 1]>` to avoid alloc.
Testing: Just refactor, but code is covered by WPT tests
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Follow the HTML canvas specification and add missing
'setTransform(transform)' method to CanvasPattern interface.
https://html.spec.whatwg.org/multipage/#dom-canvaspattern-settransform
Testing: Improvements in the tests
- html/canvas/element/fill-and-stroke-styles/2d.pattern.transform*
- html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.transform*
Signed-off-by: Andrei Volykhin <andrei.volykhin@gmail.com>
This causes wrong rendering on vello. Current backends already handle
one dim zero correctly by themself (this was probably needed for azure),
but if we ever needed this, it should be implemented inside faulty
backend.
Testing: Existing WPT tests
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This makes it easier to add variants, I also added some spec links and
reordered enum variants to match the spec.
Testing: Just refactor, but the code is covered by WPT tests.
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Follow the HTML canvas specification and empty the list of subpaths
in context's current default path (step 2) on canvas context reseting
(reset() or set bitmap dimestion).
https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state
Testing: Improvements in the tests
- html/canvas/element/canvas-host/2d.canvas.host.initial.reset.path.html
- html/canvas/offscreen/canvas-host/2d.canvas.host.initial.reset.path*
Signed-off-by: Andrei Volykhin <andrei.volykhin@gmail.com>