diff options
author | Ennui Langeweile <85590273+EnnuiL@users.noreply.github.com> | 2023-10-18 10:39:58 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-18 13:39:58 +0000 |
commit | 2d7dfb06c0f7228ed311de9ba1eb36c871b10c87 (patch) | |
tree | 89e17f03f33b5cdebcbf67403accc6cb23bc2e15 | |
parent | 66258bfbbd240e0de6cddddf72aa00b3ba85e100 (diff) | |
download | servo-2d7dfb06c0f7228ed311de9ba1eb36c871b10c87.tar.gz servo-2d7dfb06c0f7228ed311de9ba1eb36c871b10c87.zip |
Use `IpcSharedMemory` for `Canvas2dMsg::DrawImage` (#30544)
* Use `IpcSharedMemory` for `Canvas2DMsg::DrawImage`
* Fix `Canvas2dMsg::DrawEmptyImage` crashes
* Do not premultiply canvas image data
* Move `image_data` back to its original position
-rw-r--r-- | components/canvas/canvas_data.rs | 13 | ||||
-rw-r--r-- | components/canvas/canvas_paint_thread.rs | 24 | ||||
-rw-r--r-- | components/canvas_traits/canvas.rs | 3 | ||||
-rw-r--r-- | components/script/canvas_state.rs | 22 |
4 files changed, 37 insertions, 25 deletions
diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 778851524ba..38d84f2d00c 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -446,11 +446,12 @@ impl<'a> CanvasData<'a> { pub fn draw_image( &mut self, - image_data: Vec<u8>, + image_data: &[u8], image_size: Size2D<f64>, dest_rect: Rect<f64>, source_rect: Rect<f64>, smoothing_enabled: bool, + premultiply: bool, ) { // We round up the floating pixel values to draw the pixels let source_rect = source_rect.ceil(); @@ -469,6 +470,7 @@ impl<'a> CanvasData<'a> { source_rect.size, dest_rect, smoothing_enabled, + premultiply, &draw_options, ); }; @@ -1306,17 +1308,24 @@ pub struct CanvasPaintState<'a> { /// image_size: The size of the image to be written /// 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 +/// premultiply: Determines whenever the image data should be premultiplied or not fn write_image( draw_target: &mut dyn GenericDrawTarget, - image_data: Vec<u8>, + mut image_data: Vec<u8>, image_size: Size2D<f64>, dest_rect: Rect<f64>, smoothing_enabled: bool, + premultiply: bool, draw_options: &DrawOptions, ) { if image_data.is_empty() { return; } + + if premultiply { + pixels::rgba8_premultiply_inplace(&mut image_data); + } + let image_rect = Rect::new(Point2D::zero(), image_size); // From spec https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index 7234aaed4ab..808714b14e8 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -175,22 +175,27 @@ impl<'a> CanvasPaintThread<'a> { .canvas(canvas_id) .is_point_in_path(x, y, fill_rule, chan), Canvas2dMsg::DrawImage( - imagedata, + ref image_data, image_size, dest_rect, source_rect, smoothing_enabled, - ) => { - let data = imagedata.map_or_else( - || vec![0; image_size.width as usize * image_size.height as usize * 4], - |bytes| bytes.into_vec(), - ); + ) => self.canvas(canvas_id).draw_image( + &*image_data, + image_size, + dest_rect, + source_rect, + smoothing_enabled, + true, + ), + Canvas2dMsg::DrawEmptyImage(image_size, dest_rect, source_rect) => { self.canvas(canvas_id).draw_image( - data, + &vec![0; image_size.area() as usize * 4], image_size, dest_rect, source_rect, - smoothing_enabled, + false, + false, ) }, Canvas2dMsg::DrawImageInOther( @@ -204,11 +209,12 @@ impl<'a> CanvasPaintThread<'a> { .canvas(canvas_id) .read_pixels(source_rect.to_u64(), image_size.to_u64()); self.canvas(other_canvas_id).draw_image( - image_data.into(), + &image_data, source_rect.size, dest_rect, source_rect, smoothing, + false, ); }, Canvas2dMsg::MoveTo(ref point) => self.canvas(canvas_id).move_to(point), diff --git a/components/canvas_traits/canvas.rs b/components/canvas_traits/canvas.rs index ee29d440efb..0ed7faed559 100644 --- a/components/canvas_traits/canvas.rs +++ b/components/canvas_traits/canvas.rs @@ -41,7 +41,8 @@ pub struct CanvasImageData { pub enum Canvas2dMsg { Arc(Point2D<f32>, f32, f32, f32, bool), ArcTo(Point2D<f32>, Point2D<f32>, f32), - DrawImage(Option<ByteBuf>, Size2D<f64>, Rect<f64>, Rect<f64>, bool), + DrawImage(IpcSharedMemory, Size2D<f64>, Rect<f64>, Rect<f64>, bool), + DrawEmptyImage(Size2D<f64>, Rect<f64>, Rect<f64>), DrawImageInOther(CanvasId, Size2D<f64>, Rect<f64>, Rect<f64>, bool), BeginPath, BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>), diff --git a/components/script/canvas_state.rs b/components/script/canvas_state.rs index 646e8601b1e..9d1bc10d5e6 100644 --- a/components/script/canvas_state.rs +++ b/components/script/canvas_state.rs @@ -15,13 +15,12 @@ use canvas_traits::canvas::{ use cssparser::{Color as CSSColor, Parser, ParserInput, RGBA}; use euclid::default::{Point2D, Rect, Size2D, Transform2D}; use euclid::vec2; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory}; use net_traits::image_cache::{ImageCache, ImageResponse}; use net_traits::request::CorsSettings; use pixels::PixelFormat; use profile_traits::ipc as profiled_ipc; use script_traits::ScriptMsg; -use serde_bytes::ByteBuf; use servo_url::{ImmutableOrigin, ServoUrl}; use style::properties::longhands::font_variant_caps::computed_value::T as FontVariantCaps; use style::properties::style_structs::Font; @@ -260,7 +259,7 @@ impl CanvasState { &self, url: ServoUrl, cors_setting: Option<CorsSettings>, - ) -> Option<(Vec<u8>, Size2D<u32>)> { + ) -> Option<(IpcSharedMemory, Size2D<u32>)> { let img = match self.request_image_from_cache(url, cors_setting) { ImageResponse::Loaded(img, _) => img, ImageResponse::PlaceholderLoaded(_, _) | @@ -272,7 +271,7 @@ impl CanvasState { let image_size = Size2D::new(img.width, img.height); let image_data = match img.format { - PixelFormat::BGRA8 => img.bytes.to_vec(), + PixelFormat::BGRA8 => img.bytes.clone(), pixel_format => unimplemented!("unsupported pixel format ({:?})", pixel_format), }; @@ -492,12 +491,10 @@ impl CanvasState { }, } } else { - self.send_canvas_2d_msg(Canvas2dMsg::DrawImage( - None, + self.send_canvas_2d_msg(Canvas2dMsg::DrawEmptyImage( image_size, dest_rect, source_rect, - smoothing_enabled, )); } @@ -554,12 +551,10 @@ impl CanvasState { _ => return Err(Error::InvalidState), } } else { - self.send_canvas_2d_msg(Canvas2dMsg::DrawImage( - None, + self.send_canvas_2d_msg(Canvas2dMsg::DrawEmptyImage( image_size, dest_rect, source_rect, - smoothing_enabled, )); } @@ -582,10 +577,9 @@ impl CanvasState { dh: Option<f64>, ) -> ErrorResult { debug!("Fetching image {}.", url); - let (mut image_data, image_size) = self + let (image_data, image_size) = self .fetch_image_data(url, cors_setting) .ok_or(Error::InvalidState)?; - pixels::rgba8_premultiply_inplace(&mut image_data); let image_size = image_size.to_f64(); let dw = dw.unwrap_or(image_size.width); @@ -603,7 +597,7 @@ impl CanvasState { let smoothing_enabled = self.state.borrow().image_smoothing_enabled; self.send_canvas_2d_msg(Canvas2dMsg::DrawImage( - Some(ByteBuf::from(image_data)), + image_data, image_size, dest_rect, source_rect, @@ -916,6 +910,7 @@ impl CanvasState { .and_then(|url| { self.fetch_image_data(url, cors_setting_for_element(image.upcast())) }) + .map(|data| (data.0.to_vec(), data.1)) .ok_or(Error::InvalidState)? }, CanvasImageSource::HTMLCanvasElement(ref canvas) => { @@ -935,6 +930,7 @@ impl CanvasState { CanvasImageSource::CSSStyleValue(ref value) => value .get_url(self.base_url.clone()) .and_then(|url| self.fetch_image_data(url, None)) + .map(|data| (data.0.to_vec(), data.1)) .ok_or(Error::InvalidState)?, }; |