aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorBrody Eastwood <baeastwo@ncsu.edu>2018-03-20 15:04:15 -0400
committerBrody-Eastwood <37410352+Brody-Eastwood@users.noreply.github.com>2018-04-02 22:02:22 -0400
commit8a1590efc6ab6690cd9aab5ec3d46f854b891b4f (patch)
tree7af85a05e05ea0290088122d41f25292fd81cb7d /components
parenta69eceefc92d011dc825cbcf7b408042ae607ecc (diff)
downloadservo-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.rs42
-rw-r--r--components/canvas_traits/canvas.rs15
-rw-r--r--components/constellation/constellation.rs12
-rw-r--r--components/layout/display_list/builder.rs3
-rw-r--r--components/layout/fragment.rs4
-rw-r--r--components/script/dom/bindings/trace.rs3
-rw-r--r--components/script/dom/canvasrenderingcontext2d.rs214
-rw-r--r--components/script/dom/htmlcanvaselement.rs18
-rw-r--r--components/script/dom/paintrenderingcontext2d.rs2
-rw-r--r--components/script_layout_interface/lib.rs3
-rw-r--r--components/script_traits/script_msg.rs4
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.