mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
canvas: Remove Backend
trait (#38262)
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>
This commit is contained in:
parent
5cd57f9dba
commit
420a5a64a7
4 changed files with 46 additions and 77 deletions
|
@ -12,28 +12,25 @@ use webrender_api::ImageDescriptor;
|
||||||
|
|
||||||
use crate::canvas_data::{Filter, TextRun};
|
use crate::canvas_data::{Filter, TextRun};
|
||||||
|
|
||||||
pub(crate) trait Backend: Clone + Sized {
|
|
||||||
type DrawTarget: GenericDrawTarget<Self>;
|
|
||||||
type SourceSurface;
|
|
||||||
|
|
||||||
fn create_drawtarget(&self, size: Size2D<u64>) -> Self::DrawTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This defines required methods for a DrawTarget (currently only implemented for raqote). The
|
// This defines required methods for a DrawTarget (currently only implemented for raqote). The
|
||||||
// prototypes are derived from the now-removed Azure backend's methods.
|
// prototypes are derived from the now-removed Azure backend's methods.
|
||||||
pub(crate) trait GenericDrawTarget<B: Backend> {
|
pub(crate) trait GenericDrawTarget {
|
||||||
|
type SourceSurface;
|
||||||
|
|
||||||
|
fn new(size: Size2D<u32>) -> Self;
|
||||||
|
fn create_similar_draw_target(&self, size: &Size2D<i32>) -> Self;
|
||||||
|
|
||||||
fn clear_rect(&mut self, rect: &Rect<f32>, transform: Transform2D<f32>);
|
fn clear_rect(&mut self, rect: &Rect<f32>, transform: Transform2D<f32>);
|
||||||
fn copy_surface(
|
fn copy_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
surface: B::SourceSurface,
|
surface: Self::SourceSurface,
|
||||||
source: Rect<i32>,
|
source: Rect<i32>,
|
||||||
destination: Point2D<i32>,
|
destination: Point2D<i32>,
|
||||||
);
|
);
|
||||||
fn create_similar_draw_target(&self, size: &Size2D<i32>) -> Self;
|
fn create_source_surface_from_data(&self, data: Snapshot) -> Option<Self::SourceSurface>;
|
||||||
fn create_source_surface_from_data(&self, data: Snapshot) -> Option<B::SourceSurface>;
|
|
||||||
fn draw_surface(
|
fn draw_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
surface: B::SourceSurface,
|
surface: Self::SourceSurface,
|
||||||
dest: Rect<f64>,
|
dest: Rect<f64>,
|
||||||
source: Rect<f64>,
|
source: Rect<f64>,
|
||||||
filter: Filter,
|
filter: Filter,
|
||||||
|
@ -42,7 +39,7 @@ pub(crate) trait GenericDrawTarget<B: Backend> {
|
||||||
);
|
);
|
||||||
fn draw_surface_with_shadow(
|
fn draw_surface_with_shadow(
|
||||||
&self,
|
&self,
|
||||||
surface: B::SourceSurface,
|
surface: Self::SourceSurface,
|
||||||
dest: &Point2D<f32>,
|
dest: &Point2D<f32>,
|
||||||
shadow_options: ShadowOptions,
|
shadow_options: ShadowOptions,
|
||||||
composition_options: CompositionOptions,
|
composition_options: CompositionOptions,
|
||||||
|
@ -89,7 +86,7 @@ pub(crate) trait GenericDrawTarget<B: Backend> {
|
||||||
composition_options: CompositionOptions,
|
composition_options: CompositionOptions,
|
||||||
transform: Transform2D<f32>,
|
transform: Transform2D<f32>,
|
||||||
);
|
);
|
||||||
fn surface(&self) -> B::SourceSurface;
|
fn surface(&self) -> Self::SourceSurface;
|
||||||
fn image_descriptor_and_serializable_data(&self) -> (ImageDescriptor, SerializableImageData);
|
fn image_descriptor_and_serializable_data(&self) -> (ImageDescriptor, SerializableImageData);
|
||||||
fn snapshot(&self) -> Snapshot;
|
fn snapshot(&self) -> Snapshot;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ use range::Range;
|
||||||
use unicode_script::Script;
|
use unicode_script::Script;
|
||||||
use webrender_api::ImageKey;
|
use webrender_api::ImageKey;
|
||||||
|
|
||||||
use crate::backend::{Backend, GenericDrawTarget as _};
|
use crate::backend::GenericDrawTarget;
|
||||||
|
|
||||||
// Asserts on WR texture cache update for zero sized image with raw data.
|
// Asserts on WR texture cache update for zero sized image with raw data.
|
||||||
// https://github.com/servo/webrender/blob/main/webrender/src/texture_cache.rs#L1475
|
// https://github.com/servo/webrender/blob/main/webrender/src/texture_cache.rs#L1475
|
||||||
|
@ -102,28 +102,25 @@ pub(crate) enum Filter {
|
||||||
Nearest,
|
Nearest,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct CanvasData<B: Backend> {
|
pub(crate) struct CanvasData<DrawTarget: GenericDrawTarget> {
|
||||||
backend: B,
|
drawtarget: DrawTarget,
|
||||||
drawtarget: B::DrawTarget,
|
|
||||||
compositor_api: CrossProcessCompositorApi,
|
compositor_api: CrossProcessCompositorApi,
|
||||||
image_key: ImageKey,
|
image_key: ImageKey,
|
||||||
font_context: Arc<FontContext>,
|
font_context: Arc<FontContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Backend> CanvasData<B> {
|
impl<DrawTarget: GenericDrawTarget> CanvasData<DrawTarget> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
size: Size2D<u64>,
|
size: Size2D<u64>,
|
||||||
compositor_api: CrossProcessCompositorApi,
|
compositor_api: CrossProcessCompositorApi,
|
||||||
font_context: Arc<FontContext>,
|
font_context: Arc<FontContext>,
|
||||||
backend: B,
|
) -> CanvasData<DrawTarget> {
|
||||||
) -> CanvasData<B> {
|
|
||||||
let size = size.max(MIN_WR_IMAGE_SIZE);
|
let size = size.max(MIN_WR_IMAGE_SIZE);
|
||||||
let draw_target = backend.create_drawtarget(size);
|
let draw_target = DrawTarget::new(size.cast());
|
||||||
let image_key = compositor_api.generate_image_key_blocking().unwrap();
|
let image_key = compositor_api.generate_image_key_blocking().unwrap();
|
||||||
let (descriptor, data) = draw_target.image_descriptor_and_serializable_data();
|
let (descriptor, data) = draw_target.image_descriptor_and_serializable_data();
|
||||||
compositor_api.add_image(image_key, descriptor, data);
|
compositor_api.add_image(image_key, descriptor, data);
|
||||||
CanvasData {
|
CanvasData {
|
||||||
backend,
|
|
||||||
drawtarget: draw_target,
|
drawtarget: draw_target,
|
||||||
compositor_api,
|
compositor_api,
|
||||||
image_key,
|
image_key,
|
||||||
|
@ -155,8 +152,8 @@ impl<B: Backend> CanvasData<B> {
|
||||||
snapshot
|
snapshot
|
||||||
};
|
};
|
||||||
|
|
||||||
let writer = |draw_target: &mut B::DrawTarget, transform| {
|
let writer = |draw_target: &mut DrawTarget, transform| {
|
||||||
write_image::<B>(
|
write_image::<DrawTarget>(
|
||||||
draw_target,
|
draw_target,
|
||||||
snapshot,
|
snapshot,
|
||||||
dest_rect,
|
dest_rect,
|
||||||
|
@ -496,7 +493,7 @@ impl<B: Backend> CanvasData<B> {
|
||||||
shadow_options,
|
shadow_options,
|
||||||
composition_options,
|
composition_options,
|
||||||
transform,
|
transform,
|
||||||
|new_draw_target: &mut B::DrawTarget, transform| {
|
|new_draw_target, transform| {
|
||||||
new_draw_target.fill_rect(rect, style, composition_options, transform);
|
new_draw_target.fill_rect(rect, style, composition_options, transform);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -538,7 +535,7 @@ impl<B: Backend> CanvasData<B> {
|
||||||
shadow_options,
|
shadow_options,
|
||||||
composition_options,
|
composition_options,
|
||||||
transform,
|
transform,
|
||||||
|new_draw_target: &mut B::DrawTarget, transform| {
|
|new_draw_target, transform| {
|
||||||
new_draw_target.stroke_rect(
|
new_draw_target.stroke_rect(
|
||||||
rect,
|
rect,
|
||||||
style,
|
style,
|
||||||
|
@ -629,9 +626,7 @@ impl<B: Backend> CanvasData<B> {
|
||||||
.max(MIN_WR_IMAGE_SIZE);
|
.max(MIN_WR_IMAGE_SIZE);
|
||||||
|
|
||||||
// Step 1. Clear canvas's bitmap to transparent black.
|
// Step 1. Clear canvas's bitmap to transparent black.
|
||||||
self.drawtarget = self
|
self.drawtarget = DrawTarget::new(Size2D::new(size.width, size.height).cast());
|
||||||
.backend
|
|
||||||
.create_drawtarget(Size2D::new(size.width, size.height));
|
|
||||||
|
|
||||||
self.update_image_rendering();
|
self.update_image_rendering();
|
||||||
}
|
}
|
||||||
|
@ -658,7 +653,7 @@ impl<B: Backend> CanvasData<B> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_draw_target_for_shadow(&self, source_rect: &Rect<f32>) -> B::DrawTarget {
|
fn create_draw_target_for_shadow(&self, source_rect: &Rect<f32>) -> DrawTarget {
|
||||||
self.drawtarget.create_similar_draw_target(&Size2D::new(
|
self.drawtarget.create_similar_draw_target(&Size2D::new(
|
||||||
source_rect.size.width as i32,
|
source_rect.size.width as i32,
|
||||||
source_rect.size.height as i32,
|
source_rect.size.height as i32,
|
||||||
|
@ -673,7 +668,7 @@ impl<B: Backend> CanvasData<B> {
|
||||||
transform: Transform2D<f32>,
|
transform: Transform2D<f32>,
|
||||||
draw_shadow_source: F,
|
draw_shadow_source: F,
|
||||||
) where
|
) where
|
||||||
F: FnOnce(&mut B::DrawTarget, Transform2D<f32>),
|
F: FnOnce(&mut DrawTarget, Transform2D<f32>),
|
||||||
{
|
{
|
||||||
let shadow_src_rect = transform.outer_transformed_rect(rect);
|
let shadow_src_rect = transform.outer_transformed_rect(rect);
|
||||||
let mut new_draw_target = self.create_draw_target_for_shadow(&shadow_src_rect);
|
let mut new_draw_target = self.create_draw_target_for_shadow(&shadow_src_rect);
|
||||||
|
@ -755,7 +750,7 @@ impl<B: Backend> CanvasData<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Backend> Drop for CanvasData<B> {
|
impl<D: GenericDrawTarget> Drop for CanvasData<D> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.compositor_api.delete_image(self.image_key);
|
self.compositor_api.delete_image(self.image_key);
|
||||||
}
|
}
|
||||||
|
@ -771,8 +766,8 @@ const IDEOGRAPHIC_BASELINE_DEFAULT: f32 = 0.5;
|
||||||
/// dest_rect: Area of the destination target where the pixels will be copied
|
/// dest_rect: Area of the destination target where the pixels will be copied
|
||||||
/// smoothing_enabled: It determines if smoothing is applied to the image result
|
/// smoothing_enabled: It determines if smoothing is applied to the image result
|
||||||
/// premultiply: Determines whenever the image data should be premultiplied or not
|
/// premultiply: Determines whenever the image data should be premultiplied or not
|
||||||
fn write_image<B: Backend>(
|
fn write_image<DrawTarget: GenericDrawTarget>(
|
||||||
draw_target: &mut B::DrawTarget,
|
draw_target: &mut DrawTarget,
|
||||||
snapshot: Snapshot,
|
snapshot: Snapshot,
|
||||||
dest_rect: Rect<f64>,
|
dest_rect: Rect<f64>,
|
||||||
smoothing_enabled: bool,
|
smoothing_enabled: bool,
|
||||||
|
|
|
@ -23,7 +23,6 @@ use pixels::Snapshot;
|
||||||
use webrender_api::ImageKey;
|
use webrender_api::ImageKey;
|
||||||
|
|
||||||
use crate::canvas_data::*;
|
use crate::canvas_data::*;
|
||||||
use crate::raqote_backend::RaqoteBackend;
|
|
||||||
|
|
||||||
pub struct CanvasPaintThread {
|
pub struct CanvasPaintThread {
|
||||||
canvases: HashMap<CanvasId, Canvas>,
|
canvases: HashMap<CanvasId, Canvas>,
|
||||||
|
@ -120,12 +119,8 @@ impl CanvasPaintThread {
|
||||||
let canvas_id = self.next_canvas_id;
|
let canvas_id = self.next_canvas_id;
|
||||||
self.next_canvas_id.0 += 1;
|
self.next_canvas_id.0 += 1;
|
||||||
|
|
||||||
let canvas_data = CanvasData::new(
|
let canvas_data =
|
||||||
size,
|
CanvasData::new(size, self.compositor_api.clone(), self.font_context.clone());
|
||||||
self.compositor_api.clone(),
|
|
||||||
self.font_context.clone(),
|
|
||||||
RaqoteBackend,
|
|
||||||
);
|
|
||||||
let image_key = canvas_data.image_key();
|
let image_key = canvas_data.image_key();
|
||||||
self.canvases.insert(canvas_id, Canvas::Raqote(canvas_data));
|
self.canvases.insert(canvas_id, Canvas::Raqote(canvas_data));
|
||||||
|
|
||||||
|
@ -301,7 +296,7 @@ impl CanvasPaintThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Canvas {
|
enum Canvas {
|
||||||
Raqote(CanvasData<RaqoteBackend>),
|
Raqote(CanvasData<raqote::DrawTarget>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Canvas {
|
impl Canvas {
|
||||||
|
|
|
@ -19,7 +19,7 @@ use raqote::{DrawOptions, PathBuilder, StrokeStyle};
|
||||||
use style::color::AbsoluteColor;
|
use style::color::AbsoluteColor;
|
||||||
use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat};
|
use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat};
|
||||||
|
|
||||||
use crate::backend::{Backend, GenericDrawTarget};
|
use crate::backend::GenericDrawTarget;
|
||||||
use crate::canvas_data::{Filter, TextRun};
|
use crate::canvas_data::{Filter, TextRun};
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
|
@ -30,18 +30,6 @@ thread_local! {
|
||||||
static SHARED_FONT_CACHE: RefCell<HashMap<FontIdentifier, Font>> = RefCell::default();
|
static SHARED_FONT_CACHE: RefCell<HashMap<FontIdentifier, Font>> = RefCell::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
|
||||||
pub(crate) struct RaqoteBackend;
|
|
||||||
|
|
||||||
impl Backend for RaqoteBackend {
|
|
||||||
type DrawTarget = raqote::DrawTarget;
|
|
||||||
type SourceSurface = Vec<u8>; // TODO: See if we can avoid the alloc (probably?)
|
|
||||||
|
|
||||||
fn create_drawtarget(&self, size: Size2D<u64>) -> Self::DrawTarget {
|
|
||||||
raqote::DrawTarget::new(size.width as i32, size.height as i32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Pattern {
|
pub enum Pattern {
|
||||||
// argb
|
// argb
|
||||||
|
@ -199,9 +187,15 @@ fn create_gradient_stops(gradient_stops: Vec<CanvasGradientStop>) -> Vec<raqote:
|
||||||
stops
|
stops
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
impl GenericDrawTarget for raqote::DrawTarget {
|
||||||
|
type SourceSurface = Vec<u8>; // TODO: See if we can avoid the alloc (probably?)
|
||||||
|
|
||||||
|
fn new(size: Size2D<u32>) -> Self {
|
||||||
|
raqote::DrawTarget::new(size.width as i32, size.height as i32)
|
||||||
|
}
|
||||||
|
|
||||||
fn clear_rect(&mut self, rect: &Rect<f32>, transform: Transform2D<f32>) {
|
fn clear_rect(&mut self, rect: &Rect<f32>, transform: Transform2D<f32>) {
|
||||||
<Self as GenericDrawTarget<RaqoteBackend>>::fill_rect(
|
<Self as GenericDrawTarget>::fill_rect(
|
||||||
self,
|
self,
|
||||||
rect,
|
rect,
|
||||||
FillOrStrokeStyle::Color(AbsoluteColor::TRANSPARENT_BLACK),
|
FillOrStrokeStyle::Color(AbsoluteColor::TRANSPARENT_BLACK),
|
||||||
|
@ -215,7 +209,7 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn copy_surface(
|
fn copy_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
surface: <RaqoteBackend as Backend>::SourceSurface,
|
surface: Self::SourceSurface,
|
||||||
source: Rect<i32>,
|
source: Rect<i32>,
|
||||||
destination: Point2D<i32>,
|
destination: Point2D<i32>,
|
||||||
) {
|
) {
|
||||||
|
@ -226,16 +220,10 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
||||||
raqote::DrawTarget::copy_surface(self, &dt, source.to_box2d(), destination);
|
raqote::DrawTarget::copy_surface(self, &dt, source.to_box2d(), destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_similar_draw_target(
|
fn create_similar_draw_target(&self, size: &Size2D<i32>) -> Self {
|
||||||
&self,
|
|
||||||
size: &Size2D<i32>,
|
|
||||||
) -> <RaqoteBackend as Backend>::DrawTarget {
|
|
||||||
raqote::DrawTarget::new(size.width, size.height)
|
raqote::DrawTarget::new(size.width, size.height)
|
||||||
}
|
}
|
||||||
fn create_source_surface_from_data(
|
fn create_source_surface_from_data(&self, data: Snapshot) -> Option<Self::SourceSurface> {
|
||||||
&self,
|
|
||||||
data: Snapshot,
|
|
||||||
) -> Option<<RaqoteBackend as Backend>::SourceSurface> {
|
|
||||||
Some(
|
Some(
|
||||||
data.to_vec(
|
data.to_vec(
|
||||||
Some(SnapshotAlphaMode::Transparent {
|
Some(SnapshotAlphaMode::Transparent {
|
||||||
|
@ -249,7 +237,7 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn draw_surface(
|
fn draw_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
surface: <RaqoteBackend as Backend>::SourceSurface,
|
surface: Self::SourceSurface,
|
||||||
dest: Rect<f64>,
|
dest: Rect<f64>,
|
||||||
src: Rect<f64>,
|
src: Rect<f64>,
|
||||||
filter: Filter,
|
filter: Filter,
|
||||||
|
@ -297,7 +285,7 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
||||||
}
|
}
|
||||||
fn draw_surface_with_shadow(
|
fn draw_surface_with_shadow(
|
||||||
&self,
|
&self,
|
||||||
_surface: <RaqoteBackend as Backend>::SourceSurface,
|
_surface: Self::SourceSurface,
|
||||||
_dest: &Point2D<f32>,
|
_dest: &Point2D<f32>,
|
||||||
_shadow_options: ShadowOptions,
|
_shadow_options: ShadowOptions,
|
||||||
_composition_options: CompositionOptions,
|
_composition_options: CompositionOptions,
|
||||||
|
@ -398,13 +386,7 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
||||||
rect.size.height,
|
rect.size.height,
|
||||||
);
|
);
|
||||||
|
|
||||||
<Self as GenericDrawTarget<RaqoteBackend>>::fill(
|
<Self as GenericDrawTarget>::fill(self, &pb, style, composition_options, transform);
|
||||||
self,
|
|
||||||
&pb,
|
|
||||||
style,
|
|
||||||
composition_options,
|
|
||||||
transform,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
fn get_size(&self) -> Size2D<i32> {
|
fn get_size(&self) -> Size2D<i32> {
|
||||||
Size2D::new(self.width(), self.height())
|
Size2D::new(self.width(), self.height())
|
||||||
|
@ -419,7 +401,7 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
||||||
fn push_clip_rect(&mut self, rect: &Rect<i32>) {
|
fn push_clip_rect(&mut self, rect: &Rect<i32>) {
|
||||||
self.push_clip_rect(rect.to_box2d());
|
self.push_clip_rect(rect.to_box2d());
|
||||||
}
|
}
|
||||||
fn surface(&self) -> <RaqoteBackend as Backend>::SourceSurface {
|
fn surface(&self) -> Self::SourceSurface {
|
||||||
self.get_data_u8().to_vec()
|
self.get_data_u8().to_vec()
|
||||||
}
|
}
|
||||||
fn stroke(
|
fn stroke(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue