canvas: Gate raqote backend behind feature (enabled for now) (#38312)

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>
This commit is contained in:
sagudev 2025-07-28 13:54:40 +02:00 committed by GitHub
parent 9da4c74a60
commit a67998b520
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 53 additions and 11 deletions

View file

@ -14,6 +14,7 @@ path = "lib.rs"
[features]
vello = ["dep:vello", "dep:pollster", "dep:futures-intrusive", "dep:peniko"]
vello_cpu = ["dep:vello_cpu", "dep:peniko"]
raqote = ["dep:raqote", "dep:font-kit"]
[dependencies]
app_units = { workspace = true }
@ -23,7 +24,7 @@ compositing_traits = { workspace = true }
crossbeam-channel = { workspace = true }
cssparser = { workspace = true }
euclid = { workspace = true }
font-kit = "0.14"
font-kit = { version = "0.14", optional = true }
fonts = { path = "../fonts" }
ipc-channel = { workspace = true }
kurbo = { workspace = true }
@ -32,7 +33,7 @@ net_traits = { workspace = true }
peniko = { workspace = true, optional = true }
pixels = { path = "../pixels" }
range = { path = "../range" }
raqote = "0.8.5"
raqote = { version = "0.8.5", optional = true }
servo_arc = { workspace = true }
stylo = { workspace = true }
unicode-script = { workspace = true }

View file

@ -3,6 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#![allow(clippy::too_many_arguments)]
#![allow(unreachable_patterns)]
use std::borrow::ToOwned;
use std::collections::HashMap;
@ -292,6 +293,7 @@ impl CanvasPaintThread {
#[allow(clippy::large_enum_variant)]
enum Canvas {
#[cfg(feature = "raqote")]
Raqote(CanvasData<raqote::DrawTarget>),
#[cfg(feature = "vello")]
Vello(CanvasData<crate::vello_backend::VelloDrawTarget>),
@ -309,19 +311,20 @@ impl Canvas {
.to_lowercase()
.as_str()
{
#[cfg(feature = "raqote")]
"" | "auto" | "raqote" => Some(Self::Raqote(CanvasData::new(
size,
compositor_api,
font_context,
))),
#[cfg(feature = "vello")]
"vello" => Some(Self::Vello(CanvasData::new(
"" | "auto" | "vello" => Some(Self::Vello(CanvasData::new(
size,
compositor_api,
font_context,
))),
#[cfg(feature = "vello_cpu")]
"vello_cpu" => Some(Self::VelloCPU(CanvasData::new(
size,
compositor_api,
font_context,
))),
"" | "auto" | "raqote" => Some(Self::Raqote(CanvasData::new(
"" | "auto" | "vello_cpu" => Some(Self::VelloCPU(CanvasData::new(
size,
compositor_api,
font_context,
@ -335,21 +338,25 @@ impl Canvas {
fn image_key(&self) -> ImageKey {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.image_key(),
#[cfg(feature = "vello")]
Canvas::Vello(canvas_data) => canvas_data.image_key(),
#[cfg(feature = "vello_cpu")]
Canvas::VelloCPU(canvas_data) => canvas_data.image_key(),
_ => unreachable!(),
}
}
fn pop_clip(&mut self) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.pop_clip(),
#[cfg(feature = "vello")]
Canvas::Vello(canvas_data) => canvas_data.pop_clip(),
#[cfg(feature = "vello_cpu")]
Canvas::VelloCPU(canvas_data) => canvas_data.pop_clip(),
_ => unreachable!(),
}
}
@ -367,6 +374,7 @@ impl Canvas {
transform: Transform2D<f32>,
) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.fill_text(
text,
x,
@ -405,6 +413,7 @@ impl Canvas {
composition_options,
transform,
),
_ => unreachable!(),
}
}
@ -417,6 +426,7 @@ impl Canvas {
transform: Transform2D<f32>,
) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => {
canvas_data.fill_rect(rect, style, shadow_options, composition_options, transform)
},
@ -428,6 +438,7 @@ impl Canvas {
Canvas::VelloCPU(canvas_data) => {
canvas_data.fill_rect(rect, style, shadow_options, composition_options, transform)
},
_ => unreachable!(),
}
}
@ -441,6 +452,7 @@ impl Canvas {
transform: Transform2D<f32>,
) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.stroke_rect(
rect,
style,
@ -467,6 +479,7 @@ impl Canvas {
composition_options,
transform,
),
_ => unreachable!(),
}
}
@ -480,6 +493,7 @@ impl Canvas {
transform: Transform2D<f32>,
) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.fill_path(
path,
fill_rule,
@ -506,6 +520,7 @@ impl Canvas {
composition_options,
transform,
),
_ => unreachable!(),
}
}
@ -519,6 +534,7 @@ impl Canvas {
transform: Transform2D<f32>,
) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.stroke_path(
path,
style,
@ -545,16 +561,19 @@ impl Canvas {
composition_options,
transform,
),
_ => unreachable!(),
}
}
fn clear_rect(&mut self, rect: &Rect<f32>, transform: Transform2D<f32>) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.clear_rect(rect, transform),
#[cfg(feature = "vello")]
Canvas::Vello(canvas_data) => canvas_data.clear_rect(rect, transform),
#[cfg(feature = "vello_cpu")]
Canvas::VelloCPU(canvas_data) => canvas_data.clear_rect(rect, transform),
_ => unreachable!(),
}
}
@ -569,6 +588,7 @@ impl Canvas {
transform: Transform2D<f32>,
) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.draw_image(
snapshot,
dest_rect,
@ -598,66 +618,79 @@ impl Canvas {
composition_options,
transform,
),
_ => unreachable!(),
}
}
fn read_pixels(&mut self, read_rect: Option<Rect<u32>>) -> Snapshot {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.read_pixels(read_rect),
#[cfg(feature = "vello")]
Canvas::Vello(canvas_data) => canvas_data.read_pixels(read_rect),
#[cfg(feature = "vello_cpu")]
Canvas::VelloCPU(canvas_data) => canvas_data.read_pixels(read_rect),
_ => unreachable!(),
}
}
fn measure_text(&mut self, text: String, text_options: TextOptions) -> TextMetrics {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.measure_text(text, text_options),
#[cfg(feature = "vello")]
Canvas::Vello(canvas_data) => canvas_data.measure_text(text, text_options),
#[cfg(feature = "vello_cpu")]
Canvas::VelloCPU(canvas_data) => canvas_data.measure_text(text, text_options),
_ => unreachable!(),
}
}
fn clip_path(&mut self, path: &Path, fill_rule: FillRule, transform: Transform2D<f32>) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.clip_path(path, fill_rule, transform),
#[cfg(feature = "vello")]
Canvas::Vello(canvas_data) => canvas_data.clip_path(path, fill_rule, transform),
#[cfg(feature = "vello_cpu")]
Canvas::VelloCPU(canvas_data) => canvas_data.clip_path(path, fill_rule, transform),
_ => unreachable!(),
}
}
fn put_image_data(&mut self, snapshot: Snapshot, rect: Rect<u32>) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.put_image_data(snapshot, rect),
#[cfg(feature = "vello")]
Canvas::Vello(canvas_data) => canvas_data.put_image_data(snapshot, rect),
#[cfg(feature = "vello_cpu")]
Canvas::VelloCPU(canvas_data) => canvas_data.put_image_data(snapshot, rect),
_ => unreachable!(),
}
}
fn update_image_rendering(&mut self) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.update_image_rendering(),
#[cfg(feature = "vello")]
Canvas::Vello(canvas_data) => canvas_data.update_image_rendering(),
#[cfg(feature = "vello_cpu")]
Canvas::VelloCPU(canvas_data) => canvas_data.update_image_rendering(),
_ => unreachable!(),
}
}
fn recreate(&mut self, size: Option<Size2D<u64>>) {
match self {
#[cfg(feature = "raqote")]
Canvas::Raqote(canvas_data) => canvas_data.recreate(size),
#[cfg(feature = "vello")]
Canvas::Vello(canvas_data) => canvas_data.recreate(size),
#[cfg(feature = "vello_cpu")]
Canvas::VelloCPU(canvas_data) => canvas_data.recreate(size),
_ => unreachable!(),
}
}
}

View file

@ -5,11 +5,16 @@
#![deny(unsafe_code)]
mod backend;
#[cfg(feature = "raqote")]
mod raqote_backend;
#[cfg(any(feature = "vello", feature = "vello_cpu"))]
mod peniko_conversions;
mod raqote_backend;
#[cfg(feature = "vello")]
mod vello_backend;
#[cfg(feature = "vello_cpu")]
mod vello_cpu_backend;