diff options
author | Brody Eastwood <baeastwo@ncsu.edu> | 2018-03-20 15:04:15 -0400 |
---|---|---|
committer | Brody-Eastwood <37410352+Brody-Eastwood@users.noreply.github.com> | 2018-04-02 22:02:22 -0400 |
commit | 8a1590efc6ab6690cd9aab5ec3d46f854b891b4f (patch) | |
tree | 7af85a05e05ea0290088122d41f25292fd81cb7d /components | |
parent | a69eceefc92d011dc825cbcf7b408042ae607ecc (diff) | |
download | servo-8a1590efc6ab6690cd9aab5ec3d46f854b891b4f.tar.gz servo-8a1590efc6ab6690cd9aab5ec3d46f854b891b4f.zip |
Add unique canvas IDs to all canvas operations.
Diffstat (limited to 'components')
-rw-r--r-- | components/canvas/canvas_paint_thread.rs | 42 | ||||
-rw-r--r-- | components/canvas_traits/canvas.rs | 15 | ||||
-rw-r--r-- | components/constellation/constellation.rs | 12 | ||||
-rw-r--r-- | components/layout/display_list/builder.rs | 3 | ||||
-rw-r--r-- | components/layout/fragment.rs | 4 | ||||
-rw-r--r-- | components/script/dom/bindings/trace.rs | 3 | ||||
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 214 | ||||
-rw-r--r-- | components/script/dom/htmlcanvaselement.rs | 18 | ||||
-rw-r--r-- | components/script/dom/paintrenderingcontext2d.rs | 2 | ||||
-rw-r--r-- | components/script_layout_interface/lib.rs | 3 | ||||
-rw-r--r-- | components/script_traits/script_msg.rs | 4 |
11 files changed, 167 insertions, 153 deletions
diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index d464f6488e5..cf1e3a79b62 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -64,6 +64,7 @@ pub struct CanvasPaintThread<'a> { old_image_key: Option<webrender_api::ImageKey>, /// An old webrender image key that can be deleted when the current epoch ends. very_old_image_key: Option<webrender_api::ImageKey>, + canvas_id: CanvasId, } #[derive(Clone)] @@ -99,7 +100,8 @@ impl<'a> CanvasPaintState<'a> { impl<'a> CanvasPaintThread<'a> { fn new(size: Size2D<i32>, webrender_api_sender: webrender_api::RenderApiSender, - antialias: AntialiasMode) -> CanvasPaintThread<'a> { + antialias: AntialiasMode, + canvas_id: CanvasId) -> CanvasPaintThread<'a> { let draw_target = CanvasPaintThread::create(size); let path_builder = draw_target.create_path_builder(); let webrender_api = webrender_api_sender.create_api(); @@ -112,6 +114,7 @@ impl<'a> CanvasPaintThread<'a> { image_key: None, old_image_key: None, very_old_image_key: None, + canvas_id: canvas_id, } } @@ -119,7 +122,8 @@ impl<'a> CanvasPaintThread<'a> { /// communicate with it. pub fn start(size: Size2D<i32>, webrender_api_sender: webrender_api::RenderApiSender, - antialias: bool) + antialias: bool, + canvas_id: CanvasId) -> IpcSender<CanvasMsg> { let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap(); let antialias = if antialias { @@ -128,11 +132,12 @@ impl<'a> CanvasPaintThread<'a> { AntialiasMode::None }; thread::Builder::new().name("CanvasThread".to_owned()).spawn(move || { - let mut painter = CanvasPaintThread::new(size, webrender_api_sender, antialias); + let mut painter = CanvasPaintThread::new(size, webrender_api_sender, antialias, canvas_id); loop { let msg = receiver.recv(); match msg.unwrap() { - CanvasMsg::Canvas2d(message) => { + CanvasMsg::Canvas2d(message, canvas_id) => { + assert!(canvas_id == painter.canvas_id); match message { Canvas2dMsg::FillText(text, x, y, max_width) => painter.fill_text(text, x, y, max_width), Canvas2dMsg::FillRect(ref rect) => painter.fill_rect(rect), @@ -165,10 +170,10 @@ impl<'a> CanvasPaintThread<'a> { painter.draw_image_self(image_size, dest_rect, source_rect, smoothing_enabled) } Canvas2dMsg::DrawImageInOther( - renderer, image_size, dest_rect, source_rect, smoothing, sender + renderer, other_canvas_id, image_size, dest_rect, source_rect, smoothing, sender ) => { painter.draw_image_in_other( - renderer, image_size, dest_rect, source_rect, smoothing, sender) + renderer, other_canvas_id, image_size, dest_rect, source_rect, smoothing, sender) } Canvas2dMsg::MoveTo(ref point) => painter.move_to(point), Canvas2dMsg::LineTo(ref point) => painter.line_to(point), @@ -220,22 +225,30 @@ impl<'a> CanvasPaintThread<'a> { Canvas2dMsg::SetShadowColor(ref color) => painter.set_shadow_color(color.to_azure_style()), } }, - CanvasMsg::Close => break, - CanvasMsg::Recreate(size) => painter.recreate(size), - CanvasMsg::FromScript(message) => { + CanvasMsg::Close(canvas_id) =>{ + assert!(canvas_id == painter.canvas_id); + break; + }, + CanvasMsg::Recreate(size, canvas_id) =>{ + assert!(canvas_id == painter.canvas_id); + painter.recreate(size); + }, + CanvasMsg::FromScript(message, canvas_id) => { + assert!(canvas_id == painter.canvas_id); match message { FromScriptMsg::SendPixels(chan) => { painter.send_pixels(chan) } } - } - CanvasMsg::FromLayout(message) => { + }, + CanvasMsg::FromLayout(message, canvas_id) => { + assert!(canvas_id == painter.canvas_id); match message { FromLayoutMsg::SendData(chan) => { painter.send_data(chan) } } - } + }, } } }).expect("Thread spawning failed"); @@ -415,6 +428,7 @@ impl<'a> CanvasPaintThread<'a> { fn draw_image_in_other(&self, renderer: IpcSender<CanvasMsg>, + other_canvas_id: CanvasId, image_size: Size2D<f64>, dest_rect: Rect<f64>, source_rect: Rect<f64>, @@ -430,7 +444,9 @@ impl<'a> CanvasPaintThread<'a> { dest_rect, source_rect, smoothing_enabled, - )); + ), + other_canvas_id, + ); renderer.send(msg).unwrap(); // We acknowledge to the caller here that the data was sent to the // other canvas so that if JS immediately afterwards try to get the diff --git a/components/canvas_traits/canvas.rs b/components/canvas_traits/canvas.rs index 8b9feb8dff2..a8cd79cae32 100644 --- a/components/canvas_traits/canvas.rs +++ b/components/canvas_traits/canvas.rs @@ -16,13 +16,16 @@ pub enum FillRule { Evenodd, } +#[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)] +pub struct CanvasId(pub u64); + #[derive(Clone, Deserialize, Serialize)] pub enum CanvasMsg { - Canvas2d(Canvas2dMsg), - FromLayout(FromLayoutMsg), - FromScript(FromScriptMsg), - Recreate(Size2D<i32>), - Close, + Canvas2d(Canvas2dMsg, CanvasId), + FromLayout(FromLayoutMsg, CanvasId), + FromScript(FromScriptMsg, CanvasId), + Recreate(Size2D<i32>, CanvasId), + Close(CanvasId), } #[derive(Clone, Deserialize, Serialize)] @@ -37,7 +40,7 @@ pub enum Canvas2dMsg { DrawImage(ByteBuf, Size2D<f64>, Rect<f64>, Rect<f64>, bool), DrawImageSelf(Size2D<f64>, Rect<f64>, Rect<f64>, bool), DrawImageInOther( - IpcSender<CanvasMsg>, Size2D<f64>, Rect<f64>, Rect<f64>, bool, IpcSender<()>), + IpcSender<CanvasMsg>, CanvasId, Size2D<f64>, Rect<f64>, Rect<f64>, bool, IpcSender<()>), BeginPath, BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>), ClearRect(Rect<f32>), diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 2da5835a2f9..033d79a5bdf 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -95,6 +95,7 @@ use browsingcontext::{BrowsingContext, SessionHistoryChange, SessionHistoryEntry use browsingcontext::{FullyActiveBrowsingContextsIterator, AllBrowsingContextsIterator}; use canvas::canvas_paint_thread::CanvasPaintThread; use canvas::webgl_thread::WebGLThreads; +use canvas_traits::canvas::CanvasId; use canvas_traits::canvas::CanvasMsg; use clipboard::{ClipboardContext, ClipboardProvider}; use compositing::SendableFrameTree; @@ -329,6 +330,9 @@ pub struct Constellation<Message, LTF, STF> { /// A channel through which messages can be sent to the webvr thread. webvr_chan: Option<IpcSender<WebVRMsg>>, + + /// An Id for the next canvas to use. + canvas_id: CanvasId, } /// State needed to construct a constellation. @@ -626,6 +630,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> }), webgl_threads: state.webgl_threads, webvr_chan: state.webvr_chan, + canvas_id: CanvasId(0), }; constellation.run(); @@ -2203,11 +2208,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> fn handle_create_canvas_paint_thread_msg( &mut self, size: &Size2D<i32>, - response_sender: IpcSender<IpcSender<CanvasMsg>>) { + response_sender: IpcSender<(IpcSender<CanvasMsg>, CanvasId)>) { + self.canvas_id.0 += 1; let webrender_api = self.webrender_api_sender.clone(); let sender = CanvasPaintThread::start(*size, webrender_api, - opts::get().enable_canvas_antialiasing); - if let Err(e) = response_sender.send(sender) { + opts::get().enable_canvas_antialiasing, self.canvas_id.clone()); + if let Err(e) = response_sender.send((sender, self.canvas_id.clone())) { warn!("Create canvas paint thread response failed ({})", e); } } diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs index 36e6cd6c58f..141bbb52b80 100644 --- a/components/layout/display_list/builder.rs +++ b/components/layout/display_list/builder.rs @@ -1800,7 +1800,8 @@ impl FragmentDisplayListBuilding for Fragment { let ipc_renderer = ipc_renderer.lock().unwrap(); let (sender, receiver) = ipc::channel().unwrap(); ipc_renderer - .send(CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender))) + .send(CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender), + canvas_fragment_info.canvas_id.clone())) .unwrap(); (receiver.recv().unwrap().image_key, PixelFormat::BGRA8) }, diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 68d5c7f6199..c4f90526785 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -8,7 +8,7 @@ use ServoArc; use app_units::Au; -use canvas_traits::canvas::CanvasMsg; +use canvas_traits::canvas::{CanvasMsg, CanvasId}; use context::{LayoutContext, with_thread_local_font_context}; use display_list::ToLayout; use euclid::{Point2D, Vector2D, Rect, Size2D}; @@ -345,6 +345,7 @@ pub struct CanvasFragmentInfo { pub source: CanvasFragmentSource, pub dom_width: Au, pub dom_height: Au, + pub canvas_id: CanvasId, } impl CanvasFragmentInfo { @@ -362,6 +363,7 @@ impl CanvasFragmentInfo { source: source, dom_width: Au::from_px(data.width as i32), dom_height: Au::from_px(data.height as i32), + canvas_id: data.canvas_id, } } } diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 0893d8e1a72..44369fef756 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -30,7 +30,7 @@ //! `JSTraceable` to a datatype. use app_units::Au; -use canvas_traits::canvas::{CanvasGradientStop, LinearGradientStyle, RadialGradientStyle}; +use canvas_traits::canvas::{CanvasGradientStop, CanvasId, LinearGradientStyle, RadialGradientStyle}; use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle}; use canvas_traits::webgl::{WebGLBufferId, WebGLFramebufferId, WebGLProgramId, WebGLRenderbufferId}; use canvas_traits::webgl::{WebGLChan, WebGLContextShareMode, WebGLError, WebGLPipeline, WebGLMsgSender}; @@ -423,6 +423,7 @@ unsafe_no_jsmanaged_fields!(WebVRGamepadHand); unsafe_no_jsmanaged_fields!(ScriptToConstellationChan); unsafe_no_jsmanaged_fields!(InteractiveMetrics); unsafe_no_jsmanaged_fields!(InteractiveWindow); +unsafe_no_jsmanaged_fields!(CanvasId); unsafe impl<'a> JSTraceable for &'a str { #[inline] diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 1e95ef3836a..ee101251635 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg}; +use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg, CanvasId}; use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; @@ -78,6 +78,7 @@ pub struct CanvasRenderingContext2D { state: DomRefCell<CanvasContextState>, saved_states: DomRefCell<Vec<CanvasContextState>>, origin_clean: Cell<bool>, + canvas_id: CanvasId, } #[must_root] @@ -133,7 +134,7 @@ impl CanvasRenderingContext2D { let script_to_constellation_chan = global.script_to_constellation_chan(); debug!("Asking constellation to create new canvas thread."); script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap(); - let ipc_renderer = receiver.recv().unwrap(); + let (ipc_renderer, canvas_id) = receiver.recv().unwrap(); debug!("Done."); CanvasRenderingContext2D { reflector_: Reflector::new(), @@ -145,6 +146,7 @@ impl CanvasRenderingContext2D { state: DomRefCell::new(CanvasContextState::new()), saved_states: DomRefCell::new(Vec::new()), origin_clean: Cell::new(true), + canvas_id: canvas_id, } } @@ -165,7 +167,7 @@ impl CanvasRenderingContext2D { pub fn set_bitmap_dimensions(&self, size: Size2D<i32>) { self.reset_to_initial_state(); self.ipc_renderer - .send(CanvasMsg::Recreate(size)) + .send(CanvasMsg::Recreate(size, self.get_canvas_id())) .unwrap(); } @@ -182,9 +184,7 @@ impl CanvasRenderingContext2D { } fn update_transform(&self) { - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetTransform(self.state.borrow().transform))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetTransform(self.state.borrow().transform)) } // It is used by DrawImage to calculate the size of the source and destination rectangles based @@ -363,9 +363,8 @@ impl CanvasRenderingContext2D { let smoothing_enabled = self.state.borrow().image_smoothing_enabled; if self.canvas.as_ref().map_or(false, |c| &**c == canvas) { - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageSelf( + self.send_canvas_2d_msg(Canvas2dMsg::DrawImageSelf( image_size, dest_rect, source_rect, smoothing_enabled)); - self.ipc_renderer.send(msg).unwrap(); } else { let context = match canvas.get_or_init_2d_context() { Some(context) => context, @@ -375,11 +374,13 @@ impl CanvasRenderingContext2D { let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageInOther( self.ipc_renderer.clone(), + self.get_canvas_id(), image_size, dest_rect, source_rect, smoothing_enabled, - sender)); + sender), + context.get_canvas_id()); let renderer = context.get_ipc_renderer(); renderer.send(msg).unwrap(); @@ -453,13 +454,13 @@ impl CanvasRenderingContext2D { } let smoothing_enabled = self.state.borrow().image_smoothing_enabled; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage( + self.send_canvas_2d_msg(Canvas2dMsg::DrawImage( image_data.into(), image_size, dest_rect, source_rect, smoothing_enabled, - ))).unwrap(); + )); self.mark_as_dirty(); Ok(()) } @@ -557,6 +558,14 @@ impl CanvasRenderingContext2D { } } + pub fn get_canvas_id(&self) -> CanvasId { + self.canvas_id.clone() + } + + pub fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) { + self.ipc_renderer.send(CanvasMsg::Canvas2d(msg, self.get_canvas_id())).unwrap() + } + pub fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> { self.ipc_renderer.clone() } @@ -573,6 +582,8 @@ impl CanvasRenderingContext2D { pub trait LayoutCanvasRenderingContext2DHelpers { #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg>; + #[allow(unsafe_code)] + unsafe fn get_canvas_id(&self) -> CanvasId; } impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<CanvasRenderingContext2D> { @@ -580,6 +591,11 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<CanvasRenderingContext2 unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> { (*self.unsafe_get()).ipc_renderer.clone() } + + #[allow(unsafe_code)] + unsafe fn get_canvas_id(&self) -> CanvasId { + (*self.unsafe_get()).canvas_id.clone() + } } // We add a guard to each of methods by the spec: @@ -602,7 +618,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-save fn Save(&self) { self.saved_states.borrow_mut().push(self.state.borrow().clone()); - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SaveContext)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SaveContext); } #[allow(unrooted_must_root)] @@ -611,7 +627,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let mut saved_states = self.saved_states.borrow_mut(); if let Some(state) = saved_states.pop() { self.state.borrow_mut().clone_from(&state); - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::RestoreContext)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::RestoreContext); } } @@ -696,9 +712,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } self.state.borrow_mut().global_alpha = alpha; - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetGlobalAlpha(alpha as f32))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalAlpha(alpha as f32)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation @@ -714,16 +728,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { fn SetGlobalCompositeOperation(&self, op_str: DOMString) { if let Ok(op) = CompositionOrBlending::from_str(&op_str) { self.state.borrow_mut().global_composition = op; - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetGlobalComposition(op))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalComposition(op)) } } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::FillRect(rect))).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::FillRect(rect)); self.mark_as_dirty(); } } @@ -731,9 +743,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::ClearRect(rect))) - .unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::ClearRect(rect)); self.mark_as_dirty(); } } @@ -741,40 +751,38 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::StrokeRect(rect))) - .unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect(rect)); self.mark_as_dirty(); } } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath fn BeginPath(&self) { - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::BeginPath)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::BeginPath); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath fn ClosePath(&self) { - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::ClosePath)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::ClosePath); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill fn Fill(&self, _: CanvasFillRule) { // TODO: Process fill rule - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Fill)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Fill); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke fn Stroke(&self) { - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Stroke)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Stroke); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip fn Clip(&self, _: CanvasFillRule) { // TODO: Process fill rule - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Clip)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Clip); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath @@ -784,16 +792,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { CanvasFillRule::Evenodd => FillRule::Evenodd, }; let (sender, receiver) = ipc::channel::<bool>(self.global().time_profiler_chan().clone()).unwrap(); - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender))) - .unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender)); receiver.recv().unwrap() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) { let parsed_text: String = text.into(); - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::FillText(parsed_text, x, y, max_width))).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::FillText(parsed_text, x, y, max_width)); self.mark_as_dirty(); } @@ -858,9 +864,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { if !(x.is_finite() && y.is_finite()) { return; } - - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::MoveTo(Point2D::new(x as f32, y as f32))); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::MoveTo(Point2D::new(x as f32, y as f32))); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto @@ -868,9 +872,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { if !(x.is_finite() && y.is_finite()) { return; } - - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::LineTo(Point2D::new(x as f32, y as f32))); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::LineTo(Point2D::new(x as f32, y as f32))); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-rect @@ -878,8 +880,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { if [x, y, width, height].iter().all(|val| val.is_finite()) { let rect = Rect::new(Point2D::new(x as f32, y as f32), Size2D::new(width as f32, height as f32)); - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::Rect(rect)); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Rect(rect)); } } @@ -888,12 +889,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { if !(cpx.is_finite() && cpy.is_finite() && x.is_finite() && y.is_finite()) { return; } - - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::QuadraticCurveTo(Point2D::new(cpx as f32, - cpy as f32), - Point2D::new(x as f32, - y as f32))); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::QuadraticCurveTo(Point2D::new(cpx as f32, + cpy as f32), + Point2D::new(x as f32, + y as f32))); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto @@ -902,13 +901,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { x.is_finite() && y.is_finite()) { return; } - - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::BezierCurveTo(Point2D::new(cp1x as f32, - cp1y as f32), - Point2D::new(cp2x as f32, - cp2y as f32), - Point2D::new(x as f32, y as f32))); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::BezierCurveTo(Point2D::new(cp1x as f32, + cp1y as f32), + Point2D::new(cp2x as f32, + cp2y as f32), + Point2D::new(x as f32, y as f32))); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc @@ -921,13 +918,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return Err(Error::IndexSize); } - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::Arc(Point2D::new(x as f32, y as f32), - r as f32, - start as f32, - end as f32, - ccw)); - - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Arc(Point2D::new(x as f32, y as f32), + r as f32, + start as f32, + end as f32, + ccw)); Ok(()) } @@ -940,10 +935,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return Err(Error::IndexSize); } - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::ArcTo(Point2D::new(cp1x as f32, cp1y as f32), - Point2D::new(cp2x as f32, cp2y as f32), - r as f32)); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::ArcTo(Point2D::new(cp1x as f32, cp1y as f32), + Point2D::new(cp2x as f32, cp2y as f32), + r as f32)); Ok(()) } @@ -956,14 +950,13 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return Err(Error::IndexSize); } - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::Ellipse(Point2D::new(x as f32, y as f32), - rx as f32, - ry as f32, - rotation as f32, - start as f32, - end as f32, - ccw)); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Ellipse(Point2D::new(x as f32, y as f32), + rx as f32, + ry as f32, + rotation as f32, + start as f32, + end as f32, + ccw)); Ok(()) } @@ -1001,25 +994,19 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { StringOrCanvasGradientOrCanvasPattern::String(string) => { if let Ok(rgba) = self.parse_color(&string) { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Color(rgba); - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetStrokeStyle( - FillOrStrokeStyle::Color(rgba)))) - .unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( + FillOrStrokeStyle::Color(rgba))); } }, StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - let msg = CanvasMsg::Canvas2d( - Canvas2dMsg::SetStrokeStyle(gradient.to_fill_or_stroke_style())); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(gradient.to_fill_or_stroke_style())); }, StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - let msg = CanvasMsg::Canvas2d( - Canvas2dMsg::SetStrokeStyle(pattern.to_fill_or_stroke_style())); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(pattern.to_fill_or_stroke_style())); if !pattern.origin_is_clean() { self.set_origin_unclean(); } @@ -1050,25 +1037,19 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { StringOrCanvasGradientOrCanvasPattern::String(string) => { if let Ok(rgba) = self.parse_color(&string) { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Color(rgba); - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetFillStyle( - FillOrStrokeStyle::Color(rgba)))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( + FillOrStrokeStyle::Color(rgba))) } } StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - let msg = CanvasMsg::Canvas2d( - Canvas2dMsg::SetFillStyle(gradient.to_fill_or_stroke_style())); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(gradient.to_fill_or_stroke_style())); } StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - let msg = CanvasMsg::Canvas2d( - Canvas2dMsg::SetFillStyle(pattern.to_fill_or_stroke_style())); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(pattern.to_fill_or_stroke_style())); if !pattern.origin_is_clean() { self.set_origin_unclean(); } @@ -1132,10 +1113,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { Size2D::new(sw as i32, sh as i32)); let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero()); let canvas_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64); - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender))) - .unwrap(); - let mut data = Vec::from(receiver.recv().unwrap()); + self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender)); + let mut data = receiver.recv().unwrap(); // Un-premultiply alpha for chunk in data.chunks_mut(4) { @@ -1145,7 +1124,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { chunk[2] = UNPREMULTIPLY_TABLE[256 * alpha + chunk[2] as usize]; } - ImageData::new(&self.global(), sw, sh, Some(data)) + ImageData::new(&self.global(), sw, sh, Some(data.to_vec())) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata @@ -1174,13 +1153,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let dirty_rect = Rect::new(Point2D::new(*dirty_x, *dirty_y), Size2D::new(*dirty_width, *dirty_height)); - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData( - data.into(), - offset, - image_data_size, - dirty_rect, - )); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(data.into(), + offset, + image_data_size, + dirty_rect)); self.mark_as_dirty(); } @@ -1282,9 +1258,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } self.state.borrow_mut().line_width = width; - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineWidth(width as f32))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetLineWidth(width as f32)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap @@ -1304,7 +1278,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { CanvasLineCap::Square => LineCapStyle::Square, }; self.state.borrow_mut().line_cap = line_cap; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineCap(line_cap))).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetLineCap(line_cap)); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin @@ -1324,7 +1298,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { CanvasLineJoin::Miter => LineJoinStyle::Miter, }; self.state.borrow_mut().line_join = line_join; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineJoin(line_join))).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetLineJoin(line_join)); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit @@ -1340,9 +1314,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } self.state.borrow_mut().miter_limit = limit; - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetMiterLimit(limit as f32))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetMiterLimit(limit as f32)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx @@ -1356,7 +1328,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return; } self.state.borrow_mut().shadow_offset_x = value; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowOffsetX(value))).unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetX(value)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety @@ -1370,7 +1342,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return; } self.state.borrow_mut().shadow_offset_y = value; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowOffsetY(value))).unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetY(value)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur @@ -1384,7 +1356,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return; } self.state.borrow_mut().shadow_blur = value; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowBlur(value))).unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowBlur(value)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor @@ -1398,16 +1370,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { fn SetShadowColor(&self, value: DOMString) { if let Ok(color) = parse_color(&value) { self.state.borrow_mut().shadow_color = color; - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowColor(color))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowColor(color)) } } } impl Drop for CanvasRenderingContext2D { fn drop(&mut self) { - if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close) { + if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close(self.get_canvas_id())) { warn!("Could not close canvas: {}", err) } } diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 8cfbccd5faa..3854b29967b 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use base64; -use canvas_traits::canvas::{CanvasMsg, FromScriptMsg}; +use canvas_traits::canvas::{CanvasMsg, CanvasId, FromScriptMsg}; use canvas_traits::webgl::WebGLVersion; use dom::attr::Attr; use dom::bindings::cell::DomRefCell; @@ -105,6 +105,7 @@ pub trait LayoutHTMLCanvasElementHelpers { fn data(&self) -> HTMLCanvasData; fn get_width(&self) -> LengthOrPercentageOrAuto; fn get_height(&self) -> LengthOrPercentageOrAuto; + fn get_canvas_id_for_layout(&self) -> CanvasId; } impl LayoutHTMLCanvasElementHelpers for LayoutDom<HTMLCanvasElement> { @@ -133,6 +134,7 @@ impl LayoutHTMLCanvasElementHelpers for LayoutDom<HTMLCanvasElement> { source: source, width: width_attr.map_or(DEFAULT_WIDTH, |val| val.as_uint()), height: height_attr.map_or(DEFAULT_HEIGHT, |val| val.as_uint()), + canvas_id: self.get_canvas_id_for_layout(), } } } @@ -156,6 +158,18 @@ impl LayoutHTMLCanvasElementHelpers for LayoutDom<HTMLCanvasElement> { .unwrap_or(LengthOrPercentageOrAuto::Auto) } } + + #[allow(unsafe_code)] + fn get_canvas_id_for_layout(&self) -> CanvasId { + unsafe { + let canvas = &*self.unsafe_get(); + if let &Some(CanvasContext::Context2d(ref context)) = canvas.context.borrow_for_layout() { + context.to_layout().get_canvas_id() + } else { + CanvasId(0) + } + } + } } @@ -261,7 +275,7 @@ impl HTMLCanvasElement { let data = match self.context.borrow().as_ref() { Some(&CanvasContext::Context2d(ref context)) => { let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); - let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender)); + let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender), context.get_canvas_id()); context.get_ipc_renderer().send(msg).unwrap(); receiver.recv().unwrap()?.into() diff --git a/components/script/dom/paintrenderingcontext2d.rs b/components/script/dom/paintrenderingcontext2d.rs index 85de76a3265..7413a37454e 100644 --- a/components/script/dom/paintrenderingcontext2d.rs +++ b/components/script/dom/paintrenderingcontext2d.rs @@ -59,7 +59,7 @@ impl PaintRenderingContext2D { } pub fn send_data(&self, sender: IpcSender<CanvasImageData>) { - let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender)); + let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender), self.context.get_canvas_id()); let _ = self.context.get_ipc_renderer().send(msg); } diff --git a/components/script_layout_interface/lib.rs b/components/script_layout_interface/lib.rs index dc2c6f515a7..36c2c2a57ca 100644 --- a/components/script_layout_interface/lib.rs +++ b/components/script_layout_interface/lib.rs @@ -41,7 +41,7 @@ pub mod rpc; pub mod wrapper_traits; use atomic_refcell::AtomicRefCell; -use canvas_traits::canvas::CanvasMsg; +use canvas_traits::canvas::{CanvasMsg, CanvasId}; use ipc_channel::ipc::IpcSender; use libc::c_void; use net_traits::image_cache::PendingImageId; @@ -133,6 +133,7 @@ pub struct HTMLCanvasData { pub source: HTMLCanvasDataSource, pub width: u32, pub height: u32, + pub canvas_id: CanvasId, } pub struct SVGSVGData { diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs index 6173f83a495..9c53052fa58 100644 --- a/components/script_traits/script_msg.rs +++ b/components/script_traits/script_msg.rs @@ -11,7 +11,7 @@ use LayoutControlMsg; use LoadData; use WorkerGlobalScopeInit; use WorkerScriptLoadOrigin; -use canvas_traits::canvas::CanvasMsg; +use canvas_traits::canvas::{CanvasMsg, CanvasId}; use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId}; use euclid::{Size2D, TypedSize2D}; use gfx_traits::Epoch; @@ -79,7 +79,7 @@ pub enum ScriptMsg { ChangeRunningAnimationsState(AnimationState), /// Requests that a new 2D canvas thread be created. (This is done in the constellation because /// 2D canvases may use the GPU and we don't want to give untrusted content access to the GPU.) - CreateCanvasPaintThread(Size2D<i32>, IpcSender<IpcSender<CanvasMsg>>), + CreateCanvasPaintThread(Size2D<i32>, IpcSender<(IpcSender<CanvasMsg>, CanvasId)>), /// Notifies the constellation that this frame has received focus. Focus, /// Forward an event that was sent to the parent window. |