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>
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>
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>
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>
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>
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>
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>
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>
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>
1. The `shared` directory is for the "_traits" crates, which will likely
be moved out of this directly at some point and renamed "_api". These
crates expose the API of crates to avoid circular dependencies.
`Snapshot` isn't really this.
2. `Snapshot` is essentially a specialied kind of `Image` so it makes
sense that it is grouped with other image-related things in `pixels`.
Testing: This should not change any behavior so is covered by existing
tests.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Replaces uses of `euclid::default::Size2D<u64>` with
`euclid::default::Size2D<u32>` for the canvas/context/snapshot.
This PR includes changes to the following components:
- canvas
- pixels
- script
- script_bindings
- shared/canvas
- shared/snapshot
Testing: https://github.com/hashcatHitman/servo/actions/runs/15426115391
(as of 892edc0048)
Fixes: #36706
---------
Signed-off-by: hashcatHitman <155700084+hashcatHitman@users.noreply.github.com>
The canvas thread might need access to the system font service before it
shuts down. Ensure that it finishes shutting down before triggering the
shutdown of the system font service. This should avoid issues where
canvas tries to access fonts right before shutting down.
Fixes: #36849.
Testing: Since this fixes a flaky crash on shutdown, there isn't a good
way to write a test for it.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Current abstraction was leaky and very hard to understand/impl because
it was so intervened with actual implementation.
Now we generalize both `CanvasState` and `CanvasData` over `B: Beckend`,
meaning that every type/method must be part of trait interface (that
lives in `beckend.rs`). Using associated trait types instead of `Box<dyn
>` allows us too remove the need for wrapper types (and `to_raquote()`
methods) as we can implement helper traits on (foreign) raquote types.
The only time we actually do dispatch (by enum) is at `Canvas` methods.
Implementation now only need to implement all backend traits and
helpers. I tried to restrain myself from actually cleaning abstraction
(where possible), to keep this change as much mechanical as possible,
but we should absolutely do that as a follow up.
Testing: Rust as we only do refactor, but there are also WPT tests
try run: https://github.com/sagudev/servo/actions/runs/14760658522
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Each canvas context returns snapshot instead of just raw bytes. This
allows as to hold off conversions (BGRA <-> RGBA, (un)premultiply) to
when/if they are actually needed. For example when loading snapshot into
webgl we can load both RGBA and BGRA so no conversion is really needed.
Currently whole thing is designed to be able to be extend on
https://github.com/servo/ipc-channel/pull/356, to make less copies.
Hence some commented out code.
Fixes#35759
There are tests for these changes in WPT
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
These two traits both exposed different parts of the compositing API,
but now that the compositor doesn't depend directly on `script` any
longer and the `script_traits` crate has been split into the
`constellation_traits` crate, this can be finally be cleaned up without
causing circular dependencies. In addition, some unit tests for the
`IOPCompositor`'s scroll node tree are also moved into
`compositing_traits` as well.
Testing: This just combines two crates, so no new tests are necessary.
Fixes: #35984.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
* Create `update_rendering` in `CanvasState` instead of manually updating in layout
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
* Mark as dirty and do flushes
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
* fixup rebase
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
* Update components/script/dom/htmlcanvaselement.rs
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
* Use 2024 style edition
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
* Reformat all code
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
---------
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
- Move options configuring antialiasing and WebRender shader precache to
the `Preferences` to group them with other related WebRender and DOM
settings.
- Remove the option to disable antialiasing for canvases. This was
unused.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Instead of exposing many different kinds of messages to the compositor
that are routed through the constellation, expose a single message type
which can be sent across IPC channels. In addition, this IPC channel and
the route to the crossbeam channel with the compositor is created along
with the `CompositorProxy`, simplifying what needs to be passed around
during pipeline initialization.
Previously, some image updates (from video) were sent over IPC with a
special serialization routine and some were sent via crossbeam channels
(canvas). Now all updates go over the IPC channel `IpcSharedMemory` is
used to avoid serialization penalties. This should improve performance
and reduce copies for video, but add a memory copy overhead for canvas.
This will improve in the future when canvas renders directly into a
texture.
All-in-all this is a simplification which opens the path toward having a
standard compositor API and reduces the number of duplicate messages and
proxying that had to happen in libservo.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Instead of exposing many different kinds of messages to the compositor
that are routed through the constellation, expose a single message type
which can be sent across IPC channels. In addition, this IPC channel and
the route to the crossbeam channel with the compositor is created along
with the `CompositorProxy`, simplifying what needs to be passed around
during pipeline initialization.
Previously, some image updates (from video) were sent over IPC with a
special serialization routine and some were sent via crossbeam channels
(canvas). Now all updates go over the IPC channel `IpcSharedMemory` is
used to avoid serialization penalties. This should improve performance
and reduce copies for video, but add a memory copy overhead for canvas.
This will improve in the future when canvas renders directly into a
texture.
All-in-all this is a simplification which opens the path toward having a
standard compositor API and reduces the number of duplicate messages and
proxying that had to happen in libservo.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This is done by no longer forwarding compositor-bound messages through
SystemFontService and making `FontContext` non-generic:
- Messages from the `FontContext` to the `Compositor` no longer need to be
forwarded through the `SystemFontService`. Instead send these messages
directly through the script IPC channel to the `Compositor`.
- Instead of adding a mock `SystemFontServiceProxy`, simply implement a
mock `SystemFontService` on the other side of an IPC channel in the
`font_context` unit test. This allows making `FontContext`
non-generic, greatly simplifying the code. The extra complexity moves
into the unit test.
These changes necessitate adding a new kind of `FontIdentifier`,
`FontIdentifier::Mock` due to the fact that local fonts have
platform-specific identifiers. This avoids having to pretend like the
system font service can have web fonts -- which was always a bit of a
hack.
These two changes are combined into one PR because they both require
extensive and similar chages in the font_context unit test which
dependended on the details of both of them.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This changes modifes the way that font data is sent over IPC channels.
Instead of serializing the data or sending it via IPC byte senders, font
data is copied into shared memory and a copy of the handle is sent over
the channel.
There is also the idea of sending the file handle of the on disk data of
system fonts. This could be implemented as a further followup once there
is an abstraction in `ipc-channel` over file handles.
To accomplish this, a `FontData` abstraction is added, which also allows
caching an in-memory shared `Arc<Vec<u8>>` version of the data (neeeded
by some APIs). This could also be a place for caching font tables in the
future.
Finally, the `FontCacheThread` is renamed to the `SystemFontService`
while the proxy for this is now named `SystemFontServiceProxy`.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This crate only takes care of fonts now as graphics related things are
split into other crates. In addition, this exposes data structures at
the top of the crate, hiding the implementation details and making it
simpler to import them.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This moves mangement of web fonts to the per-Layout `FontContext`,
preventing web fonts from being available in different Documents.
Fixes#12920.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
* Move WebRender related types to `webrender_traits`
This refactor moves several WebRender related types
from `compositing_traits`, `script_traits` and `net_traits`
crates to the `webrender_traits` crate.
This change also moves the `Image` type and associated
function out of `net_traits` and into the `pixels` crate.
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
* Move `script_traits::WebrenderIpcSender` to `webrender_traits::WebRenderScriptApi`
---------
Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This allows sharing font templates, fonts, and platform fonts across
layout threads. It's the first step toward storing web fonts in the
layout versus the shared `FontCacheThread`. Now fonts and font groups
have some locking (especially on FreeType), which will probably affect
performance. On the other hand, we measured memory usage and this saves
roughly 40 megabytes of memory when loading servo.org based on data from
the memory profiler.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
* clippy: fix `result_unit_err` warnings
* feat: fix result warnings in script
* doc: document `generate_key` return type
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
* feat: add back result to RangeRequestBounds::get_final
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
---------
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
* Use `IpcSharedMemory` for `Canvas2DMsg::DrawImage`
* Fix `Canvas2dMsg::DrawEmptyImage` crashes
* Do not premultiply canvas image data
* Move `image_data` back to its original position