Make HTMLCanvasElement::fetch_all_data return a shared memory blob

This commit is contained in:
Anthony Ramine 2018-11-21 12:51:49 +01:00
parent 804d964b7d
commit 9a8d03a0f3
5 changed files with 21 additions and 23 deletions

View file

@ -13,9 +13,8 @@ use azure::azure_hl::{ExtendMode, GradientStop, LinearGradientPattern, RadialGra
use canvas_traits::canvas::*; use canvas_traits::canvas::*;
use cssparser::RGBA; use cssparser::RGBA;
use euclid::{Point2D, Rect, Size2D, Transform2D, Vector2D}; use euclid::{Point2D, Rect, Size2D, Transform2D, Vector2D};
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use serde_bytes::ByteBuf;
use std::mem; use std::mem;
use std::sync::Arc; use std::sync::Arc;
@ -451,15 +450,11 @@ impl<'a> CanvasData<'a> {
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn send_pixels(&mut self, chan: IpcSender<Option<ByteBuf>>) { pub fn send_pixels(&mut self, chan: IpcSender<IpcSharedMemory>) {
let data = unsafe { let data = IpcSharedMemory::from_bytes(unsafe {
self.drawtarget self.drawtarget.snapshot().get_data_surface().data()
.snapshot() });
.get_data_surface() chan.send(data).unwrap();
.data()
.to_vec()
};
chan.send(Some(data.into())).unwrap();
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]

View file

@ -4,7 +4,7 @@
use cssparser::RGBA; use cssparser::RGBA;
use euclid::{Point2D, Rect, Size2D, Transform2D}; use euclid::{Point2D, Rect, Size2D, Transform2D};
use ipc_channel::ipc::{IpcBytesReceiver, IpcBytesSender, IpcSender}; use ipc_channel::ipc::{IpcBytesReceiver, IpcBytesSender, IpcSender, IpcSharedMemory};
use serde_bytes::ByteBuf; use serde_bytes::ByteBuf;
use std::default::Default; use std::default::Default;
use std::str::FromStr; use std::str::FromStr;
@ -87,7 +87,7 @@ pub enum FromLayoutMsg {
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
pub enum FromScriptMsg { pub enum FromScriptMsg {
SendPixels(IpcSender<Option<ByteBuf>>), SendPixels(IpcSender<IpcSharedMemory>),
} }
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)] #[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]

View file

@ -1296,7 +1296,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
.ok_or(Error::InvalidState)? .ok_or(Error::InvalidState)?
}, },
CanvasImageSource::HTMLCanvasElement(ref canvas) => { CanvasImageSource::HTMLCanvasElement(ref canvas) => {
canvas.fetch_all_data().ok_or(Error::InvalidState)? let (data, size) = canvas.fetch_all_data().ok_or(Error::InvalidState)?;
let data = data
.map(|data| data.to_vec())
.unwrap_or_else(|| vec![0; size.area() as usize * 4]);
(data, size)
}, },
CanvasImageSource::CSSStyleValue(ref value) => value CanvasImageSource::CSSStyleValue(ref value) => value
.get_url(self.base_url.clone()) .get_url(self.base_url.clone())

View file

@ -36,6 +36,7 @@ use euclid::{Rect, Size2D};
use html5ever::{LocalName, Prefix}; use html5ever::{LocalName, Prefix};
use image::png::PNGEncoder; use image::png::PNGEncoder;
use image::ColorType; use image::ColorType;
use ipc_channel::ipc::IpcSharedMemory;
use js::error::throw_type_error; use js::error::throw_type_error;
use js::jsapi::JSContext; use js::jsapi::JSContext;
use js::rust::HandleValue; use js::rust::HandleValue;
@ -280,7 +281,7 @@ impl HTMLCanvasElement {
self.Height() != 0 && self.Width() != 0 self.Height() != 0 && self.Width() != 0
} }
pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<u32>)> { pub fn fetch_all_data(&self) -> Option<(Option<IpcSharedMemory>, Size2D<u32>)> {
let size = self.get_size(); let size = self.get_size();
if size.width == 0 || size.height == 0 { if size.width == 0 || size.height == 0 {
@ -297,7 +298,7 @@ impl HTMLCanvasElement {
); );
context.get_ipc_renderer().send(msg).unwrap(); context.get_ipc_renderer().send(msg).unwrap();
receiver.recv().unwrap()?.into() Some(receiver.recv().unwrap())
}, },
Some(&CanvasContext::WebGL(_)) => { Some(&CanvasContext::WebGL(_)) => {
// TODO: add a method in WebGLRenderingContext to get the pixels. // TODO: add a method in WebGLRenderingContext to get the pixels.
@ -307,7 +308,7 @@ impl HTMLCanvasElement {
// TODO: add a method in WebGL2RenderingContext to get the pixels. // TODO: add a method in WebGL2RenderingContext to get the pixels.
return None; return None;
}, },
None => vec![0; size.height as usize * size.width as usize * 4], None => None,
}; };
Some((data, size)) Some((data, size))

View file

@ -569,12 +569,10 @@ impl WebGLRenderingContext {
return Err(Error::Security); return Err(Error::Security);
} }
if let Some((data, size)) = canvas.fetch_all_data() { if let Some((data, size)) = canvas.fetch_all_data() {
TexPixels::new( let data = data.unwrap_or_else(|| {
IpcSharedMemory::from_bytes(&data), IpcSharedMemory::from_bytes(&vec![0; size.area() as usize * 4])
size, });
PixelFormat::BGRA8, TexPixels::new(data, size, PixelFormat::BGRA8, true)
true,
)
} else { } else {
return Ok(None); return Ok(None);
} }