mirror of
https://github.com/servo/servo.git
synced 2025-06-19 14:48:59 +01:00
Auto merge of #21723 - servo:webgl, r=jdm
More drive-by WebGL and canvas fixes <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21723) <!-- Reviewable:end -->
This commit is contained in:
commit
82e94e3b67
22 changed files with 301 additions and 301 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -109,8 +109,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azure"
|
||||
version = "0.33.0"
|
||||
source = "git+https://github.com/servo/rust-azure#43e61bda11f26e8462cfa63affac17c43df53b84"
|
||||
version = "0.34.0"
|
||||
source = "git+https://github.com/servo/rust-azure#1536ca66954356ece017343e3cd30b293134dc3f"
|
||||
dependencies = [
|
||||
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -324,7 +324,7 @@ dependencies = [
|
|||
name = "canvas"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"azure 0.33.0 (git+https://github.com/servo/rust-azure)",
|
||||
"azure 0.34.0 (git+https://github.com/servo/rust-azure)",
|
||||
"canvas_traits 0.0.1",
|
||||
"compositing 0.0.1",
|
||||
"cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2851,7 +2851,7 @@ dependencies = [
|
|||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4335,7 +4335,7 @@ dependencies = [
|
|||
"checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
|
||||
"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
|
||||
"checksum audio-video-metadata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3c23600291b35b9cd381f5cfca636f5d7d75e7d7192eddf867de84a6732cad5c"
|
||||
"checksum azure 0.33.0 (git+https://github.com/servo/rust-azure)" = "<none>"
|
||||
"checksum azure 0.34.0 (git+https://github.com/servo/rust-azure)" = "<none>"
|
||||
"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76"
|
||||
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
|
||||
"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
|
||||
|
|
|
@ -85,21 +85,6 @@ impl<'a> CanvasData<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn draw_image_self(
|
||||
&self,
|
||||
image_size: Size2D<f64>,
|
||||
dest_rect: Rect<f64>,
|
||||
source_rect: Rect<f64>,
|
||||
smoothing_enabled: bool
|
||||
) {
|
||||
// Reads pixels from source image
|
||||
// In this case source and target are the same canvas
|
||||
let image_data = self.read_pixels(source_rect.to_i32(), image_size);
|
||||
|
||||
// The dimensions of image_data are source_rect.size
|
||||
self.draw_image(image_data, source_rect.size, dest_rect, source_rect, smoothing_enabled);
|
||||
}
|
||||
|
||||
pub fn save_context_state(&mut self) {
|
||||
self.saved_states.push(self.state.clone());
|
||||
}
|
||||
|
@ -405,14 +390,14 @@ impl<'a> CanvasData<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn send_pixels(&mut self, chan: IpcSender<Option<ByteBuf>>) {
|
||||
self.drawtarget.snapshot().get_data_surface().with_data(|element| {
|
||||
chan.send(Some(Vec::from(element).into())).unwrap();
|
||||
})
|
||||
let data = unsafe { self.drawtarget.snapshot().get_data_surface().data().to_vec() };
|
||||
chan.send(Some(data.into())).unwrap();
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn send_data(&mut self, chan: IpcSender<CanvasImageData>) {
|
||||
self.drawtarget.snapshot().get_data_surface().with_data(|element| {
|
||||
let size = self.drawtarget.get_size();
|
||||
|
||||
let descriptor = webrender_api::ImageDescriptor {
|
||||
|
@ -423,7 +408,9 @@ impl<'a> CanvasData<'a> {
|
|||
is_opaque: false,
|
||||
allow_mipmaps: false,
|
||||
};
|
||||
let data = webrender_api::ImageData::Raw(Arc::new(element.into()));
|
||||
let data = webrender_api::ImageData::Raw(Arc::new(
|
||||
unsafe { self.drawtarget.snapshot().get_data_surface().data().into() },
|
||||
));
|
||||
|
||||
let mut txn = webrender_api::Transaction::new();
|
||||
|
||||
|
@ -449,7 +436,6 @@ impl<'a> CanvasData<'a> {
|
|||
image_key: self.image_key.unwrap(),
|
||||
};
|
||||
chan.send(data).unwrap();
|
||||
})
|
||||
}
|
||||
|
||||
pub fn image_data(
|
||||
|
@ -606,23 +592,25 @@ impl<'a> CanvasData<'a> {
|
|||
/// It reads image data from the canvas
|
||||
/// canvas_size: The size of the canvas we're reading from
|
||||
/// read_rect: The area of the canvas we want to read from
|
||||
#[allow(unsafe_code)]
|
||||
pub fn read_pixels(&self, read_rect: Rect<i32>, canvas_size: Size2D<f64>) -> Vec<u8> {
|
||||
let canvas_size = canvas_size.to_i32();
|
||||
let canvas_rect = Rect::new(Point2D::new(0i32, 0i32), canvas_size);
|
||||
let src_read_rect = canvas_rect.intersection(&read_rect).unwrap_or(Rect::zero());
|
||||
|
||||
let mut image_data = vec![];
|
||||
if src_read_rect.is_empty() || canvas_size.width <= 0 && canvas_size.height <= 0 {
|
||||
return image_data;
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let data_surface = self.drawtarget.snapshot().get_data_surface();
|
||||
let mut src_data = Vec::new();
|
||||
data_surface.with_data(|element| { src_data = element.to_vec(); });
|
||||
let src_data = unsafe { data_surface.data() };
|
||||
let stride = data_surface.stride();
|
||||
|
||||
//start offset of the copyable rectangle
|
||||
let mut src = (src_read_rect.origin.y * stride + src_read_rect.origin.x * 4) as usize;
|
||||
let mut image_data = Vec::with_capacity(
|
||||
(src_read_rect.size.width * src_read_rect.size.height * 4) as usize,
|
||||
);
|
||||
//copy the data to the destination vector
|
||||
for _ in 0..src_read_rect.size.height {
|
||||
let row = &src_data[src .. src + (4 * src_read_rect.size.width) as usize];
|
||||
|
|
|
@ -132,32 +132,25 @@ impl<'a> CanvasPaintThread <'a> {
|
|||
self.canvas(canvas_id).is_point_in_path(x, y, fill_rule, chan)
|
||||
},
|
||||
Canvas2dMsg::DrawImage(
|
||||
mut imagedata,
|
||||
imagedata,
|
||||
image_size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing_enabled,
|
||||
) => {
|
||||
byte_swap(&mut imagedata);
|
||||
self.canvas(canvas_id).draw_image(
|
||||
imagedata.into(),
|
||||
image_size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing_enabled,
|
||||
)
|
||||
let data = match imagedata {
|
||||
None => vec![0; image_size.width as usize * image_size.height as usize * 4],
|
||||
Some(mut data) => {
|
||||
byte_swap(&mut data);
|
||||
data.into()
|
||||
},
|
||||
Canvas2dMsg::DrawImageSelf(
|
||||
};
|
||||
self.canvas(canvas_id).draw_image(
|
||||
data,
|
||||
image_size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing_enabled
|
||||
) => {
|
||||
self.canvas(canvas_id).draw_image_self(
|
||||
image_size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing_enabled
|
||||
smoothing_enabled,
|
||||
)
|
||||
},
|
||||
Canvas2dMsg::DrawImageInOther(
|
||||
|
@ -167,9 +160,10 @@ impl<'a> CanvasPaintThread <'a> {
|
|||
source_rect,
|
||||
smoothing
|
||||
) => {
|
||||
let mut image_data = self.canvas(canvas_id).read_pixels(
|
||||
let image_data = self.canvas(canvas_id).read_pixels(
|
||||
source_rect.to_i32(),
|
||||
image_size);
|
||||
image_size,
|
||||
);
|
||||
self.canvas(other_canvas_id).draw_image(
|
||||
image_data.into(),
|
||||
source_rect.size,
|
||||
|
|
|
@ -38,8 +38,7 @@ pub struct CanvasImageData {
|
|||
pub enum Canvas2dMsg {
|
||||
Arc(Point2D<f32>, f32, f32, f32, bool),
|
||||
ArcTo(Point2D<f32>, Point2D<f32>, f32),
|
||||
DrawImage(ByteBuf, Size2D<f64>, Rect<f64>, Rect<f64>, bool),
|
||||
DrawImageSelf(Size2D<f64>, Rect<f64>, Rect<f64>, bool),
|
||||
DrawImage(Option<ByteBuf>, Size2D<f64>, Rect<f64>, Rect<f64>, bool),
|
||||
DrawImageInOther(
|
||||
CanvasId, Size2D<f64>, Rect<f64>, Rect<f64>, bool),
|
||||
BeginPath,
|
||||
|
|
|
@ -27,7 +27,7 @@ use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeSty
|
|||
use dom::canvaspattern::CanvasPattern;
|
||||
use dom::element::Element;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::htmlcanvaselement::HTMLCanvasElement;
|
||||
use dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement};
|
||||
use dom::imagedata::ImageData;
|
||||
use dom::node::{Node, NodeDamage, window_from_node};
|
||||
use dom_struct::dom_struct;
|
||||
|
@ -247,8 +247,7 @@ impl CanvasRenderingContext2D {
|
|||
canvas.origin_is_clean()
|
||||
}
|
||||
CanvasImageSource::HTMLImageElement(image) => {
|
||||
let image_origin = image.get_origin().expect("Image's origin is missing");
|
||||
image_origin.same_origin(GlobalScope::entry().origin())
|
||||
image.same_origin(GlobalScope::entry().origin())
|
||||
}
|
||||
CanvasImageSource::CSSStyleValue(_) => true,
|
||||
}
|
||||
|
@ -315,7 +314,8 @@ impl CanvasRenderingContext2D {
|
|||
result
|
||||
}
|
||||
|
||||
fn draw_html_canvas_element(&self,
|
||||
fn draw_html_canvas_element(
|
||||
&self,
|
||||
canvas: &HTMLCanvasElement,
|
||||
sx: f64,
|
||||
sy: f64,
|
||||
|
@ -324,8 +324,8 @@ impl CanvasRenderingContext2D {
|
|||
dx: f64,
|
||||
dy: f64,
|
||||
dw: Option<f64>,
|
||||
dh: Option<f64>)
|
||||
-> ErrorResult {
|
||||
dh: Option<f64>,
|
||||
) -> ErrorResult {
|
||||
// 1. Check the usability of the image argument
|
||||
if !canvas.is_valid() {
|
||||
return Err(Error::InvalidState);
|
||||
|
@ -339,7 +339,8 @@ impl CanvasRenderingContext2D {
|
|||
|
||||
let image_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64);
|
||||
// 2. Establish the source and destination rectangles
|
||||
let (source_rect, dest_rect) = self.adjust_source_dest_rects(image_size,
|
||||
let (source_rect, dest_rect) = self.adjust_source_dest_rects(
|
||||
image_size,
|
||||
sx,
|
||||
sy,
|
||||
sw,
|
||||
|
@ -347,7 +348,8 @@ impl CanvasRenderingContext2D {
|
|||
dx,
|
||||
dy,
|
||||
dw,
|
||||
dh);
|
||||
dh,
|
||||
);
|
||||
|
||||
if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) {
|
||||
return Ok(());
|
||||
|
@ -355,29 +357,28 @@ impl CanvasRenderingContext2D {
|
|||
|
||||
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
|
||||
|
||||
if self.canvas.as_ref().map_or(false, |c| &**c == canvas) {
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::DrawImageSelf(
|
||||
image_size, dest_rect, source_rect, smoothing_enabled));
|
||||
} else {
|
||||
let context = match canvas.get_or_init_2d_context() {
|
||||
Some(context) => context,
|
||||
None => return Err(Error::InvalidState),
|
||||
};
|
||||
|
||||
let msg = CanvasMsg::Canvas2d(
|
||||
Canvas2dMsg::DrawImageInOther(
|
||||
if let Some(context) = canvas.context() {
|
||||
match *context {
|
||||
CanvasContext::Context2d(ref context) => {
|
||||
context.send_canvas_2d_msg(Canvas2dMsg::DrawImageInOther(
|
||||
self.get_canvas_id(),
|
||||
image_size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing_enabled
|
||||
),
|
||||
context.get_canvas_id()
|
||||
);
|
||||
|
||||
let renderer = context.get_ipc_renderer();
|
||||
renderer.send(msg).unwrap();
|
||||
};
|
||||
smoothing_enabled,
|
||||
));
|
||||
},
|
||||
_ => return Err(Error::InvalidState),
|
||||
}
|
||||
} else {
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::DrawImage(
|
||||
None,
|
||||
image_size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing_enabled,
|
||||
));
|
||||
}
|
||||
|
||||
self.mark_as_dirty();
|
||||
Ok(())
|
||||
|
@ -447,7 +448,7 @@ impl CanvasRenderingContext2D {
|
|||
|
||||
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::DrawImage(
|
||||
image_data.into(),
|
||||
Some(image_data.into()),
|
||||
image_size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
|
@ -1205,8 +1206,6 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
|||
.ok_or(Error::InvalidState)?
|
||||
},
|
||||
CanvasImageSource::HTMLCanvasElement(ref canvas) => {
|
||||
let _ = canvas.get_or_init_2d_context();
|
||||
|
||||
canvas.fetch_all_data().ok_or(Error::InvalidState)?
|
||||
},
|
||||
CanvasImageSource::CSSStyleValue(ref value) => {
|
||||
|
|
|
@ -37,9 +37,10 @@ use js::jsapi::JSContext;
|
|||
use js::rust::HandleValue;
|
||||
use offscreen_gl_context::GLContextAttributes;
|
||||
use profile_traits::ipc;
|
||||
use ref_filter_map;
|
||||
use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource};
|
||||
use servo_config::prefs::PREFS;
|
||||
use std::iter::repeat;
|
||||
use std::cell::Ref;
|
||||
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
|
||||
|
||||
const DEFAULT_WIDTH: u32 = 300;
|
||||
|
@ -174,42 +175,46 @@ impl LayoutHTMLCanvasElementHelpers for LayoutDom<HTMLCanvasElement> {
|
|||
|
||||
|
||||
impl HTMLCanvasElement {
|
||||
pub fn get_or_init_2d_context(&self) -> Option<DomRoot<CanvasRenderingContext2D>> {
|
||||
if self.context.borrow().is_none() {
|
||||
pub fn context(&self) -> Option<Ref<CanvasContext>> {
|
||||
ref_filter_map::ref_filter_map(self.context.borrow(), |ctx| ctx.as_ref())
|
||||
}
|
||||
|
||||
fn get_or_init_2d_context(&self) -> Option<DomRoot<CanvasRenderingContext2D>> {
|
||||
if let Some(ctx) = self.context() {
|
||||
return match *ctx {
|
||||
CanvasContext::Context2d(ref ctx) => Some(DomRoot::from_ref(ctx)),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
let window = window_from_node(self);
|
||||
let size = self.get_size();
|
||||
let context = CanvasRenderingContext2D::new(window.upcast::<GlobalScope>(), self, size);
|
||||
*self.context.borrow_mut() = Some(CanvasContext::Context2d(Dom::from_ref(&*context)));
|
||||
Some(context)
|
||||
}
|
||||
|
||||
match *self.context.borrow().as_ref().unwrap() {
|
||||
CanvasContext::Context2d(ref context) => Some(DomRoot::from_ref(&*context)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_or_init_webgl_context(
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn get_or_init_webgl_context(
|
||||
&self,
|
||||
cx: *mut JSContext,
|
||||
options: HandleValue,
|
||||
) -> Option<DomRoot<WebGLRenderingContext>> {
|
||||
if self.context.borrow().is_none() {
|
||||
if let Some(ctx) = self.context() {
|
||||
return match *ctx {
|
||||
CanvasContext::WebGL(ref ctx) => Some(DomRoot::from_ref(ctx)),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
let window = window_from_node(self);
|
||||
let size = self.get_size();
|
||||
let attrs = Self::get_gl_attributes(cx, options)?;
|
||||
let maybe_ctx = WebGLRenderingContext::new(&window, self, WebGLVersion::WebGL1, size, attrs);
|
||||
|
||||
*self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(Dom::from_ref(&*ctx)));
|
||||
let context = WebGLRenderingContext::new(&window, self, WebGLVersion::WebGL1, size, attrs)?;
|
||||
*self.context.borrow_mut() = Some(CanvasContext::WebGL(Dom::from_ref(&*context)));
|
||||
Some(context)
|
||||
}
|
||||
|
||||
if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() {
|
||||
Some(DomRoot::from_ref(&*context))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_or_init_webgl2_context(
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn get_or_init_webgl2_context(
|
||||
&self,
|
||||
cx: *mut JSContext,
|
||||
options: HandleValue,
|
||||
|
@ -217,20 +222,18 @@ impl HTMLCanvasElement {
|
|||
if !PREFS.is_webgl2_enabled() {
|
||||
return None
|
||||
}
|
||||
if self.context.borrow().is_none() {
|
||||
if let Some(ctx) = self.context() {
|
||||
return match *ctx {
|
||||
CanvasContext::WebGL2(ref ctx) => Some(DomRoot::from_ref(ctx)),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
let window = window_from_node(self);
|
||||
let size = self.get_size();
|
||||
let attrs = Self::get_gl_attributes(cx, options)?;
|
||||
let maybe_ctx = WebGL2RenderingContext::new(&window, self, size, attrs);
|
||||
|
||||
*self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL2(Dom::from_ref(&*ctx)));
|
||||
}
|
||||
|
||||
if let Some(CanvasContext::WebGL2(ref context)) = *self.context.borrow() {
|
||||
Some(DomRoot::from_ref(&*context))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let context = WebGL2RenderingContext::new(&window, self, size, attrs)?;
|
||||
*self.context.borrow_mut() = Some(CanvasContext::WebGL2(Dom::from_ref(&*context)));
|
||||
Some(context)
|
||||
}
|
||||
|
||||
/// Gets the base WebGLRenderingContext for WebGL or WebGL 2, if exists.
|
||||
|
@ -243,11 +246,14 @@ impl HTMLCanvasElement {
|
|||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn get_gl_attributes(cx: *mut JSContext, options: HandleValue) -> Option<GLContextAttributes> {
|
||||
match unsafe { WebGLContextAttributes::new(cx, options) } {
|
||||
unsafe fn get_gl_attributes(
|
||||
cx: *mut JSContext,
|
||||
options: HandleValue,
|
||||
) -> Option<GLContextAttributes> {
|
||||
match WebGLContextAttributes::new(cx, options) {
|
||||
Ok(ConversionResult::Success(ref attrs)) => Some(From::from(attrs)),
|
||||
Ok(ConversionResult::Failure(ref error)) => {
|
||||
unsafe { throw_type_error(cx, &error); }
|
||||
throw_type_error(cx, &error);
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
|
@ -284,9 +290,7 @@ impl HTMLCanvasElement {
|
|||
// TODO: add a method in WebGL2RenderingContext to get the pixels.
|
||||
return None;
|
||||
},
|
||||
None => {
|
||||
repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect()
|
||||
}
|
||||
None => vec![0; size.height as usize * size.width as usize * 4]
|
||||
};
|
||||
|
||||
Some((data, size))
|
||||
|
|
|
@ -55,7 +55,7 @@ use network_listener::{NetworkListener, PreInvoke};
|
|||
use num_traits::ToPrimitive;
|
||||
use script_thread::ScriptThread;
|
||||
use servo_url::ServoUrl;
|
||||
use servo_url::origin::ImmutableOrigin;
|
||||
use servo_url::origin::MutableOrigin;
|
||||
use std::cell::{Cell, RefMut};
|
||||
use std::char;
|
||||
use std::collections::HashSet;
|
||||
|
@ -1186,11 +1186,10 @@ impl HTMLImageElement {
|
|||
useMapElements.map(|mapElem| mapElem.get_area_elements())
|
||||
}
|
||||
|
||||
pub fn get_origin(&self) -> Option<ImmutableOrigin> {
|
||||
match self.current_request.borrow_mut().final_url {
|
||||
Some(ref url) => Some(url.origin()),
|
||||
None => None
|
||||
}
|
||||
pub fn same_origin(&self, origin: &MutableOrigin) -> bool {
|
||||
self.current_request.borrow_mut().final_url.as_ref().map_or(false, |url| {
|
||||
url.scheme() == "data" || url.origin().same_origin(origin)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,15 +13,16 @@ use canvas_traits::webgl::WebGLError::*;
|
|||
use dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants;
|
||||
use dom::bindings::codegen::Bindings::EXTBlendMinmaxBinding::EXTBlendMinmaxConstants;
|
||||
use dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::OESVertexArrayObjectConstants;
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes};
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding;
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::TexImageSource;
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes;
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
|
||||
use dom::bindings::codegen::UnionTypes::ArrayBufferViewOrArrayBuffer;
|
||||
use dom::bindings::codegen::UnionTypes::Float32ArrayOrUnrestrictedFloatSequence;
|
||||
use dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
|
||||
use dom::bindings::codegen::UnionTypes::Int32ArrayOrLongSequence;
|
||||
use dom::bindings::conversions::{DerivedFrom, ToJSValConvertible};
|
||||
use dom::bindings::error::{Error, ErrorResult};
|
||||
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::bindings::root::{Dom, DomOnceCell, DomRoot, LayoutDom, MutNullableDom};
|
||||
|
@ -30,7 +31,7 @@ use dom::event::{Event, EventBubbles, EventCancelable};
|
|||
use dom::htmlcanvaselement::HTMLCanvasElement;
|
||||
use dom::htmlcanvaselement::utils as canvas_utils;
|
||||
use dom::htmliframeelement::HTMLIFrameElement;
|
||||
use dom::node::{Node, NodeDamage, window_from_node};
|
||||
use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
|
||||
use dom::webgl_extensions::WebGLExtensions;
|
||||
use dom::webgl_validations::WebGLValidator;
|
||||
use dom::webgl_validations::tex_image_2d::{CommonTexImage2DValidator, CommonTexImage2DValidatorResult};
|
||||
|
@ -76,7 +77,6 @@ pub fn is_gles() -> bool {
|
|||
cfg!(any(target_os = "android", target_os = "ios"))
|
||||
}
|
||||
|
||||
type ImagePixelResult = Result<(Vec<u8>, Size2D<i32>, bool), ()>;
|
||||
pub const MAX_UNIFORM_AND_ATTRIBUTE_LEN: usize = 256;
|
||||
|
||||
// From the GLES 2.0.25 spec, page 85:
|
||||
|
@ -490,21 +490,21 @@ impl WebGLRenderingContext {
|
|||
|
||||
fn get_image_pixels(
|
||||
&self,
|
||||
source: ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement,
|
||||
) -> ImagePixelResult {
|
||||
// NOTE: Getting the pixels probably can be short-circuited if some
|
||||
// parameter is invalid.
|
||||
//
|
||||
// Nontheless, since it's the error case, I'm not totally sure the
|
||||
// complexity is worth it.
|
||||
let (pixels, size, premultiplied) = match source {
|
||||
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::ImageData(image_data) => {
|
||||
source: TexImageSource,
|
||||
) -> Fallible<Option<(Vec<u8>, Size2D<i32>, bool)>> {
|
||||
Ok(Some(match source {
|
||||
TexImageSource::ImageData(image_data) => {
|
||||
(image_data.get_data_array(), image_data.get_size(), false)
|
||||
},
|
||||
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLImageElement(image) => {
|
||||
TexImageSource::HTMLImageElement(image) => {
|
||||
let document = document_from_node(&*self.canvas);
|
||||
if !image.same_origin(document.origin()) {
|
||||
return Err(Error::Security);
|
||||
}
|
||||
|
||||
let img_url = match image.get_url() {
|
||||
Some(url) => url,
|
||||
None => return Err(()),
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let window = window_from_node(&*self.canvas);
|
||||
|
@ -513,7 +513,7 @@ impl WebGLRenderingContext {
|
|||
ImageResponse::Loaded(img, _) => img,
|
||||
ImageResponse::PlaceholderLoaded(_, _) | ImageResponse::None |
|
||||
ImageResponse::MetadataLoaded(_)
|
||||
=> return Err(()),
|
||||
=> return Ok(None),
|
||||
};
|
||||
|
||||
let size = Size2D::new(img.width as i32, img.height as i32);
|
||||
|
@ -531,22 +531,23 @@ impl WebGLRenderingContext {
|
|||
// TODO(emilio): Getting canvas data is implemented in CanvasRenderingContext2D,
|
||||
// but we need to refactor it moving it to `HTMLCanvasElement` and support
|
||||
// WebGLContext (probably via GetPixels()).
|
||||
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLCanvasElement(canvas) => {
|
||||
TexImageSource::HTMLCanvasElement(canvas) => {
|
||||
if !canvas.origin_is_clean() {
|
||||
return Err(Error::Security);
|
||||
}
|
||||
if let Some((mut data, size)) = canvas.fetch_all_data() {
|
||||
// Pixels got from Canvas have already alpha premultiplied
|
||||
byte_swap(&mut data);
|
||||
(data, size, true)
|
||||
} else {
|
||||
return Err(());
|
||||
return Ok(None);
|
||||
}
|
||||
},
|
||||
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLVideoElement(_) => {
|
||||
TexImageSource::HTMLVideoElement(_) => {
|
||||
// TODO: https://github.com/servo/servo/issues/6711
|
||||
return Err(());
|
||||
return Ok(None);
|
||||
}
|
||||
};
|
||||
|
||||
return Ok((pixels, size, premultiplied));
|
||||
}))
|
||||
}
|
||||
|
||||
// TODO(emilio): Move this logic to a validator.
|
||||
|
@ -1234,7 +1235,15 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
constants::UNPACK_ALIGNMENT => {
|
||||
return UInt32Value(self.texture_unpacking_alignment.get());
|
||||
},
|
||||
_ => {}
|
||||
constants::UNPACK_COLORSPACE_CONVERSION_WEBGL => {
|
||||
let unpack = self.texture_unpacking_settings.get();
|
||||
return UInt32Value(if unpack.contains(TextureUnpacking::CONVERT_COLORSPACE) {
|
||||
constants::BROWSER_DEFAULT_WEBGL
|
||||
} else {
|
||||
constants::NONE
|
||||
});
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
// Handle any MAX_ parameters by retrieving the limits that were stored
|
||||
|
@ -3520,16 +3529,15 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
internal_format: u32,
|
||||
format: u32,
|
||||
data_type: u32,
|
||||
source: ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement,
|
||||
source: TexImageSource,
|
||||
) -> ErrorResult {
|
||||
if !self.extension_manager.is_tex_type_enabled(data_type) {
|
||||
return Ok(self.webgl_error(InvalidEnum));
|
||||
}
|
||||
|
||||
// Get pixels from image source
|
||||
let (pixels, size, premultiplied) = match self.get_image_pixels(source) {
|
||||
Ok((pixels, size, premultiplied)) => (pixels, size, premultiplied),
|
||||
Err(_) => return Ok(()),
|
||||
let (pixels, size, premultiplied) = match self.get_image_pixels(source)? {
|
||||
Some(triple) => triple,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let validator = TexImage2DValidator::new(self,
|
||||
|
@ -3613,7 +3621,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
height: i32,
|
||||
format: u32,
|
||||
data_type: u32,
|
||||
mut pixels: CustomAutoRooterGuard<Option<ArrayBufferView>>,
|
||||
pixels: CustomAutoRooterGuard<Option<ArrayBufferView>>,
|
||||
) -> ErrorResult {
|
||||
let validator = TexImage2DValidator::new(self, target, level,
|
||||
format, width, height,
|
||||
|
@ -3644,10 +3652,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
|
||||
// If data is null, a buffer of sufficient size
|
||||
// initialized to 0 is passed.
|
||||
let buff = match *pixels {
|
||||
None => vec![0u8; expected_byte_length as usize],
|
||||
Some(ref mut data) => data.to_vec(),
|
||||
};
|
||||
let buff = handle_potential_webgl_error!(
|
||||
self,
|
||||
pixels.as_ref().map(|p| p.to_vec()).ok_or(InvalidValue),
|
||||
return Ok(())
|
||||
);
|
||||
|
||||
// From the WebGL spec:
|
||||
//
|
||||
|
@ -3677,11 +3686,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
yoffset: i32,
|
||||
format: u32,
|
||||
data_type: u32,
|
||||
source: ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement,
|
||||
source: TexImageSource,
|
||||
) -> ErrorResult {
|
||||
let (pixels, size, premultiplied) = match self.get_image_pixels(source) {
|
||||
Ok((pixels, size, premultiplied)) => (pixels, size, premultiplied),
|
||||
Err(_) => return Ok(()),
|
||||
let (pixels, size, premultiplied) = match self.get_image_pixels(source)? {
|
||||
Some(triple) => triple,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let validator = TexImage2DValidator::new(self, target, level, format,
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[security.dataURI.html]
|
||||
type: testharness
|
||||
[data: URIs do not count as different-origin, and do not taint the canvas]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[toDataURL.jpeg.primarycolours.html]
|
||||
type: testharness
|
||||
[toDataURL with JPEG handles simple colours correctly]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[toDataURL.png.complexcolours.html]
|
||||
type: testharness
|
||||
[toDataURL with PNG handles non-primary and non-solid colours correctly]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[toDataURL.png.primarycolours.html]
|
||||
type: testharness
|
||||
[toDataURL with PNG handles simple colours correctly]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[data-url.html]
|
||||
type: testharness
|
||||
[data URL image]
|
||||
expected: FAIL
|
||||
|
|
@ -1,3 +1,91 @@
|
|||
[to-data-url-test.html]
|
||||
bug: https://github.com/servo/servo/issues/21132
|
||||
expected: ERROR
|
||||
[WebGL test #12: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #18: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #1: should be 255,0,0,255\nat (0, 8) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #4: should be 255,0,0,255\nat (0, 8) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #34: should be 255,0,0,255\nat (0, 256) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #24: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #31: should be 255,0,0,255\nat (0, 256) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #10: should be 255,0,0,255\nat (0, 8) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #25: should be 255,0,0,255\nat (0, 128) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #40: should be 255,0,0,255\nat (0, 256) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #19: should be 255,0,0,255\nat (0, 128) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #9: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #3: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #43: should be 255,0,0,255\nat (0, 257) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #15: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #16: should be 255,0,0,255\nat (0, 128) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #21: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #33: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #0: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #30: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #22: should be 255,0,0,255\nat (0, 128) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #39: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #28: should be 255,0,0,255\nat (0, 129) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #7: should be 255,0,0,255\nat (0, 8) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #36: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #42: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #27: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #13: should be 255,0,0,255\nat (0, 9) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #37: should be 255,0,0,255\nat (0, 256) expected: 255,0,0,255 was 0,255,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #6: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 255,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
[webgl-specific.html]
|
||||
bug: https://github.com/servo/servo/issues/20552
|
||||
[WebGL test #25: getError expected: NO_ERROR. Was INVALID_ENUM : set/get UNPACK_COLORSPACE_CONVERSION_WEBGL should generate no error]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #23: gl.getParameter(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL) should be 37444 (of type number). Was null (of type object).]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #24: gl.getParameter(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL) should be 0 (of type number). Was null (of type object).]
|
||||
expected: FAIL
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
[readPixelsBadArgs.html]
|
||||
bug: https://github.com/servo/servo/issues/21522
|
||||
[WebGL test #1: testReadPixelsSOPIMG]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #2: testReadPixelsSOPCanvas]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[texImage2DHTML.html]
|
||||
bug: https://github.com/servo/servo/issues/21522
|
||||
[WebGL test #1: testTexImage2DNonSOP]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[texSubImage2DHTML.html]
|
||||
bug: https://github.com/servo/servo/issues/21522
|
||||
[WebGL test #1: testTexImage2DNonSOP]
|
||||
expected: FAIL
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
[origin-clean-conformance.html]
|
||||
[WebGL test #3: texSubImage2D with cross-origin image should throw exception.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #8: texSubImage2D with NON origin clean canvas should throw exception.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #2: texImage2D with cross-origin image should throw exception.]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #7: texImage2D with NON origin clean canvas should throw exception.]
|
||||
expected: FAIL
|
||||
|
|
@ -11,6 +11,3 @@
|
|||
[WebGL test #34: getError expected: INVALID_OPERATION. Was NO_ERROR : colorBufferFormat: RGB565 internalFormat: RGBA target: TEXTURE_2D border: 0]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #37: getError expected: NO_ERROR. Was INVALID_OPERATION : colorBufferFormat: RGB565 internalFormat: RGB target: TEXTURE_2D border: 0]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
[tex-sub-image-2d-bad-args.html]
|
||||
[WebGL test #9: getError expected: INVALID_VALUE. Was NO_ERROR : null pixels]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #0: getError expected: INVALID_OPERATION. Was INVALID_VALUE : no previously defined texture image]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
[texture-attachment-formats.html]
|
||||
[WebGL test #14: should be 63,63,63,255 with tolerance 2,2,2,0\nat (0, 0) expected: 63,63,63,255 was 64,0,0,255]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #16: should be 63,63,63,63 with tolerance 2,2,2,2\nat (0, 0) expected: 63,63,63,63 was 64,0,0,64]
|
||||
expected: FAIL
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue