diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index b87470f53c6d..26863482a991 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -12,7 +12,6 @@ use euclid::point::Point2D; use euclid::rect::Rect; use euclid::size::Size2D; use ipc_channel::ipc::{self, IpcSender}; -use ipc_channel::ipc::IpcSharedMemory; use num_traits::ToPrimitive; use std::borrow::ToOwned; use std::mem; @@ -195,6 +194,13 @@ impl<'a> CanvasPaintThread<'a> { CanvasCommonMsg::Recreate(size) => painter.recreate(size), } }, + CanvasMsg::FromScript(message) => { + match message { + FromScriptMsg::SendPixels(chan) => { + painter.send_pixels(chan) + } + } + } CanvasMsg::FromLayout(message) => { match message { FromLayoutMsg::SendData(chan) => { @@ -539,6 +545,12 @@ impl<'a> CanvasPaintThread<'a> { self.drawtarget = CanvasPaintThread::create(size); } + fn send_pixels(&mut self, chan: IpcSender>>) { + self.drawtarget.snapshot().get_data_surface().with_data(|element| { + chan.send(Some(element.into())).unwrap(); + }) + } + fn send_data(&mut self, chan: IpcSender) { self.drawtarget.snapshot().get_data_surface().with_data(|element| { let size = self.drawtarget.get_size(); @@ -548,11 +560,10 @@ impl<'a> CanvasPaintThread<'a> { webrender_traits::ImageFormat::RGBA8, element.into()); - let pixel_data = CanvasPixelData { - image_data: IpcSharedMemory::from_bytes(element), + let data = CanvasImageData { image_key: self.webrender_image_key, }; - chan.send(CanvasData::Pixels(pixel_data)).unwrap(); + chan.send(CanvasData::Image(data)).unwrap(); }) } diff --git a/components/canvas/webgl_paint_thread.rs b/components/canvas/webgl_paint_thread.rs index 88ab2080a818..13a69718f2d0 100644 --- a/components/canvas/webgl_paint_thread.rs +++ b/components/canvas/webgl_paint_thread.rs @@ -2,11 +2,11 @@ * 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::{CanvasCommonMsg, CanvasData, CanvasMsg, CanvasPixelData}; -use canvas_traits::{FromLayoutMsg, byte_swap}; +use canvas_traits::{CanvasCommonMsg, CanvasData, CanvasMsg, CanvasImageData}; +use canvas_traits::{FromLayoutMsg, FromScriptMsg, byte_swap}; use euclid::size::Size2D; use gleam::gl; -use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory}; +use ipc_channel::ipc::{self, IpcSender}; use offscreen_gl_context::{ColorAttachmentType, GLContext, GLLimits}; use offscreen_gl_context::{GLContextAttributes, NativeGLContext, OSMesaContext}; use std::borrow::ToOwned; @@ -173,6 +173,15 @@ impl WebGLPaintThread { CanvasCommonMsg::Recreate(size) => painter.recreate(size).unwrap(), } }, + CanvasMsg::FromScript(message) => { + match message { + FromScriptMsg::SendPixels(chan) =>{ + // Read the comment on + // HTMLCanvasElement::fetch_all_data. + chan.send(None).unwrap(); + } + } + } CanvasMsg::FromLayout(message) => { match message { FromLayoutMsg::SendData(chan) => @@ -218,12 +227,11 @@ impl WebGLPaintThread { webrender_traits::ImageFormat::RGBA8, pixels.clone()); - let pixel_data = CanvasPixelData { - image_data: IpcSharedMemory::from_bytes(&pixels[..]), + let image_data = CanvasImageData { image_key: image_key, }; - chan.send(CanvasData::Pixels(pixel_data)).unwrap(); + chan.send(CanvasData::Image(image_data)).unwrap(); } WebGLPaintTaskData::WebRender(_, id) => { chan.send(CanvasData::WebGL(id)).unwrap(); diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs index 5a1acc710d58..8269664cd467 100644 --- a/components/canvas_traits/lib.rs +++ b/components/canvas_traits/lib.rs @@ -31,7 +31,7 @@ use euclid::matrix2d::Matrix2D; use euclid::point::Point2D; use euclid::rect::Rect; use euclid::size::Size2D; -use ipc_channel::ipc::{IpcSender, IpcSharedMemory}; +use ipc_channel::ipc::IpcSender; use std::default::Default; use std::str::FromStr; use webrender_traits::{WebGLCommand, WebGLContextId}; @@ -47,6 +47,7 @@ pub enum CanvasMsg { Canvas2d(Canvas2dMsg), Common(CanvasCommonMsg), FromLayout(FromLayoutMsg), + FromScript(FromScriptMsg), WebGL(WebGLCommand), } @@ -58,13 +59,12 @@ pub enum CanvasCommonMsg { #[derive(Clone, Deserialize, Serialize)] pub enum CanvasData { - Pixels(CanvasPixelData), + Image(CanvasImageData), WebGL(WebGLContextId), } #[derive(Clone, Deserialize, Serialize)] -pub struct CanvasPixelData { - pub image_data: IpcSharedMemory, +pub struct CanvasImageData { pub image_key: webrender_traits::ImageKey, } @@ -73,6 +73,11 @@ pub enum FromLayoutMsg { SendData(IpcSender), } +#[derive(Clone, Deserialize, Serialize)] +pub enum FromScriptMsg { + SendPixels(IpcSender>>), +} + #[derive(Clone, Deserialize, Serialize)] pub enum Canvas2dMsg { Arc(Point2D, f32, f32, f32, bool), diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 17b3e07f7169..cbecdba41877 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -1436,16 +1436,16 @@ impl FragmentDisplayListBuilding for Fragment { self.style.get_cursor(Cursor::Default), DisplayListSection::Content); let display_item = match canvas_data { - CanvasData::Pixels(canvas_data) => { + CanvasData::Image(canvas_data) => { DisplayItem::Image(box ImageDisplayItem { base: base, - image_data: Some(Arc::new(canvas_data.image_data)), webrender_image: WebRenderImageInfo { width: computed_width as u32, height: computed_height as u32, format: PixelFormat::RGBA8, key: Some(canvas_data.image_key), }, + image_data: None, stretch_size: stacking_relative_content_box.size, tile_spacing: Size2D::zero(), image_rendering: image_rendering::T::auto, diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 60f6482a49f4..326b1804ddf7 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.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::{CanvasMsg, FromLayoutMsg, CanvasData}; +use canvas_traits::{CanvasMsg, FromScriptMsg}; use dom::attr::Attr; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; @@ -202,16 +202,17 @@ impl HTMLCanvasElement { let data = if let Some(renderer) = self.ipc_renderer() { let (sender, receiver) = ipc::channel().unwrap(); - let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender)); + let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender)); renderer.send(msg).unwrap(); match receiver.recv().unwrap() { - CanvasData::Pixels(pixel_data) - => pixel_data.image_data.to_vec(), - CanvasData::WebGL(_) - // TODO(emilio): Not sure if WebGL canvas is required for 2d spec, - // but I think it's not. - => return None, + Some(pixels) => pixels, + None => { + // TODO(emilio, #14109): Not sure if WebGL canvas is + // required for 2d spec, but I think it's not, if so, make + // this return a readback from the GL context. + return None; + } } } else { repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect()