Auto merge of #21683 - servo:webgl, r=jdm

Properly support PACK_ALIGNMENT in WebGL 1

<!-- 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/21683)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-09-13 01:47:52 -04:00 committed by GitHub
commit 60b926ade4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 560 additions and 2847 deletions

View file

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use ::gl_context::GLContextFactory; use ::gl_context::GLContextFactory;
use ::webgl_thread::{WebGLExternalImageApi, WebGLExternalImageHandler, WebGLThreadObserver, WebGLThread};
use canvas_traits::webgl::{WebGLChan, WebGLContextId, WebGLMsg, WebGLPipeline, WebGLReceiver}; use canvas_traits::webgl::{WebGLChan, WebGLContextId, WebGLMsg, WebGLPipeline, WebGLReceiver};
use canvas_traits::webgl::{WebGLSender, WebVRCommand, WebVRRenderHandler}; use canvas_traits::webgl::{WebGLSender, WebVRCommand, WebVRRenderHandler};
use canvas_traits::webgl::DOMToTextureCommand; use canvas_traits::webgl::DOMToTextureCommand;
@ -12,8 +11,8 @@ use euclid::Size2D;
use fnv::FnvHashMap; use fnv::FnvHashMap;
use gleam::gl; use gleam::gl;
use servo_config::prefs::PREFS; use servo_config::prefs::PREFS;
use std::marker::PhantomData;
use std::rc::Rc; use std::rc::Rc;
use webgl_thread::{WebGLExternalImageApi, WebGLExternalImageHandler, WebGLThread};
use webrender; use webrender;
use webrender_api; use webrender_api;
@ -37,7 +36,6 @@ impl WebGLThreads {
gl_factory, gl_factory,
webrender_api_sender, webrender_api_sender,
webvr_compositor.map(|c| WebVRRenderWrapper(c)), webvr_compositor.map(|c| WebVRRenderWrapper(c)),
PhantomData,
); );
let output_handler = if PREFS.is_dom_to_texture_enabled() { let output_handler = if PREFS.is_dom_to_texture_enabled() {
Some(Box::new(OutputHandler::new( Some(Box::new(OutputHandler::new(
@ -112,27 +110,6 @@ impl WebGLExternalImageApi for WebGLExternalImages {
} }
} }
/// Custom observer used in a `WebGLThread`.
impl WebGLThreadObserver for PhantomData<()> {
fn on_context_create(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D<i32>) {
debug!(
"WebGLContext created (ctx_id: {:?} texture_id: {:?} size: {:?}",
ctx_id, texture_id, size
);
}
fn on_context_resize(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D<i32>) {
debug!(
"WebGLContext resized (ctx_id: {:?} texture_id: {:?} size: {:?}",
ctx_id, texture_id, size
);
}
fn on_context_delete(&mut self, ctx_id: WebGLContextId) {
debug!("WebGLContext deleted (ctx_id: {:?})", ctx_id);
}
}
/// Wrapper to send WebVR commands used in `WebGLThread`. /// Wrapper to send WebVR commands used in `WebGLThread`.
struct WebVRRenderWrapper(Box<WebVRRenderHandler>); struct WebVRRenderWrapper(Box<WebVRRenderHandler>);

View file

@ -47,7 +47,7 @@ impl Default for GLState {
/// A WebGLThread manages the life cycle and message multiplexing of /// A WebGLThread manages the life cycle and message multiplexing of
/// a set of WebGLContexts living in the same thread. /// a set of WebGLContexts living in the same thread.
pub struct WebGLThread<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> { pub struct WebGLThread<VR: WebVRRenderHandler + 'static> {
/// Factory used to create a new GLContext shared with the WR/Main thread. /// Factory used to create a new GLContext shared with the WR/Main thread.
gl_factory: GLContextFactory, gl_factory: GLContextFactory,
/// Channel used to generate/update or delete `webrender_api::ImageKey`s. /// Channel used to generate/update or delete `webrender_api::ImageKey`s.
@ -62,17 +62,16 @@ pub struct WebGLThread<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver
next_webgl_id: usize, next_webgl_id: usize,
/// Handler user to send WebVR commands. /// Handler user to send WebVR commands.
webvr_compositor: Option<VR>, webvr_compositor: Option<VR>,
/// Generic observer that listens WebGLContext creation, resize or removal events.
observer: OB,
/// Texture ids and sizes used in DOM to texture outputs. /// Texture ids and sizes used in DOM to texture outputs.
dom_outputs: FnvHashMap<webrender_api::PipelineId, DOMToTextureData>, dom_outputs: FnvHashMap<webrender_api::PipelineId, DOMToTextureData>,
} }
impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> WebGLThread<VR, OB> { impl<VR: WebVRRenderHandler + 'static> WebGLThread<VR> {
pub fn new(gl_factory: GLContextFactory, pub fn new(
webrender_api_sender: webrender_api::RenderApiSender, gl_factory: GLContextFactory,
webvr_compositor: Option<VR>, webrender_api_sender: webrender_api::RenderApiSender,
observer: OB) -> Self { webvr_compositor: Option<VR>,
) -> Self {
WebGLThread { WebGLThread {
gl_factory, gl_factory,
webrender_api: webrender_api_sender.create_api(), webrender_api: webrender_api_sender.create_api(),
@ -81,25 +80,25 @@ impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> WebGLThread<VR,
bound_context_id: None, bound_context_id: None,
next_webgl_id: 0, next_webgl_id: 0,
webvr_compositor, webvr_compositor,
observer: observer,
dom_outputs: Default::default(), dom_outputs: Default::default(),
} }
} }
/// Creates a new `WebGLThread` and returns a Sender to /// Creates a new `WebGLThread` and returns a Sender to
/// communicate with it. /// communicate with it.
pub fn start(gl_factory: GLContextFactory, pub fn start(
webrender_api_sender: webrender_api::RenderApiSender, gl_factory: GLContextFactory,
webvr_compositor: Option<VR>, webrender_api_sender: webrender_api::RenderApiSender,
observer: OB) webvr_compositor: Option<VR>,
-> WebGLSender<WebGLMsg> { ) -> WebGLSender<WebGLMsg> {
let (sender, receiver) = webgl_channel::<WebGLMsg>().unwrap(); let (sender, receiver) = webgl_channel::<WebGLMsg>().unwrap();
let result = sender.clone(); let result = sender.clone();
thread::Builder::new().name("WebGLThread".to_owned()).spawn(move || { thread::Builder::new().name("WebGLThread".to_owned()).spawn(move || {
let mut renderer = WebGLThread::new(gl_factory, let mut renderer = WebGLThread::new(
webrender_api_sender, gl_factory,
webvr_compositor, webrender_api_sender,
observer); webvr_compositor,
);
let webgl_chan = WebGLChan(sender); let webgl_chan = WebGLChan(sender);
loop { loop {
let msg = receiver.recv().unwrap(); let msg = receiver.recv().unwrap();
@ -248,8 +247,6 @@ impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> WebGLThread<VR,
gl_sync: None, gl_sync: None,
}); });
self.observer.on_context_create(id, texture_id, size);
Ok((id, limits, share_mode)) Ok((id, limits, share_mode))
}, },
Err(msg) => { Err(msg) => {
@ -271,8 +268,6 @@ impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> WebGLThread<VR,
match data.ctx.resize(size) { match data.ctx.resize(size) {
Ok(_) => { Ok(_) => {
let (real_size, texture_id, _) = data.ctx.get_info(); let (real_size, texture_id, _) = data.ctx.get_info();
self.observer.on_context_resize(context_id, texture_id, real_size);
let info = self.cached_context_info.get_mut(&context_id).unwrap(); let info = self.cached_context_info.get_mut(&context_id).unwrap();
// Update webgl texture size. Texture id may change too. // Update webgl texture size. Texture id may change too.
info.texture_id = texture_id; info.texture_id = texture_id;
@ -313,9 +308,7 @@ impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> WebGLThread<VR,
} }
// Release GL context. // Release GL context.
if self.contexts.remove(&context_id).is_some() { self.contexts.remove(&context_id);
self.observer.on_context_delete(context_id);
}
// Removing a GLContext may make the current bound context_id dirty. // Removing a GLContext may make the current bound context_id dirty.
self.bound_context_id = None; self.bound_context_id = None;
@ -581,7 +574,7 @@ impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> WebGLThread<VR,
} }
} }
impl<VR: WebVRRenderHandler + 'static, OB: WebGLThreadObserver> Drop for WebGLThread<VR, OB> { impl<VR: WebVRRenderHandler + 'static> Drop for WebGLThread<VR> {
fn drop(&mut self) { fn drop(&mut self) {
// Call remove_context functions in order to correctly delete WebRender image keys. // Call remove_context functions in order to correctly delete WebRender image keys.
let context_ids: Vec<WebGLContextId> = self.contexts.keys().map(|id| *id).collect(); let context_ids: Vec<WebGLContextId> = self.contexts.keys().map(|id| *id).collect();
@ -607,14 +600,6 @@ struct WebGLContextInfo {
gl_sync: Option<gl::GLsync>, gl_sync: Option<gl::GLsync>,
} }
/// Trait used to observe events in a WebGL Thread.
/// Used in webrender::ExternalImageHandler when multiple WebGL threads are used.
pub trait WebGLThreadObserver: Send + 'static {
fn on_context_create(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D<i32>);
fn on_context_resize(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D<i32>);
fn on_context_delete(&mut self, ctx_id: WebGLContextId);
}
/// This trait is used as a bridge between the `WebGLThreads` implementation and /// This trait is used as a bridge between the `WebGLThreads` implementation and
/// the WR ExternalImageHandler API implemented in the `WebGLExternalImageHandler` struct. /// the WR ExternalImageHandler API implemented in the `WebGLExternalImageHandler` struct.
/// `WebGLExternalImageHandler<T>` takes care of type conversions between WR and WebGL info (e.g keys, uvs). /// `WebGLExternalImageHandler<T>` takes care of type conversions between WR and WebGL info (e.g keys, uvs).

View file

@ -533,7 +533,6 @@ parameters! {
FrontFace = gl::FRONT_FACE, FrontFace = gl::FRONT_FACE,
GenerateMipmapHint = gl::GENERATE_MIPMAP_HINT, GenerateMipmapHint = gl::GENERATE_MIPMAP_HINT,
GreenBits = gl::GREEN_BITS, GreenBits = gl::GREEN_BITS,
PackAlignment = gl::PACK_ALIGNMENT,
RedBits = gl::RED_BITS, RedBits = gl::RED_BITS,
SampleBuffers = gl::SAMPLE_BUFFERS, SampleBuffers = gl::SAMPLE_BUFFERS,
Samples = gl::SAMPLES, Samples = gl::SAMPLES,
@ -554,7 +553,6 @@ parameters! {
StencilValueMask = gl::STENCIL_VALUE_MASK, StencilValueMask = gl::STENCIL_VALUE_MASK,
StencilWritemask = gl::STENCIL_WRITEMASK, StencilWritemask = gl::STENCIL_WRITEMASK,
SubpixelBits = gl::SUBPIXEL_BITS, SubpixelBits = gl::SUBPIXEL_BITS,
UnpackAlignment = gl::UNPACK_ALIGNMENT,
}), }),
Int2(ParameterInt2 { Int2(ParameterInt2 {
MaxViewportDims = gl::MAX_VIEWPORT_DIMS, MaxViewportDims = gl::MAX_VIEWPORT_DIMS,

View file

@ -149,7 +149,9 @@ pub struct WebGLRenderingContext {
canvas: Dom<HTMLCanvasElement>, canvas: Dom<HTMLCanvasElement>,
#[ignore_malloc_size_of = "Defined in canvas_traits"] #[ignore_malloc_size_of = "Defined in canvas_traits"]
last_error: Cell<Option<WebGLError>>, last_error: Cell<Option<WebGLError>>,
texture_packing_alignment: Cell<u8>,
texture_unpacking_settings: Cell<TextureUnpacking>, texture_unpacking_settings: Cell<TextureUnpacking>,
// TODO(nox): Should be Cell<u8>.
texture_unpacking_alignment: Cell<u32>, texture_unpacking_alignment: Cell<u32>,
bound_framebuffer: MutNullableDom<WebGLFramebuffer>, bound_framebuffer: MutNullableDom<WebGLFramebuffer>,
bound_renderbuffer: MutNullableDom<WebGLRenderbuffer>, bound_renderbuffer: MutNullableDom<WebGLRenderbuffer>,
@ -193,7 +195,7 @@ impl WebGLRenderingContext {
result.map(|ctx_data| { result.map(|ctx_data| {
let max_combined_texture_image_units = ctx_data.limits.max_combined_texture_image_units; let max_combined_texture_image_units = ctx_data.limits.max_combined_texture_image_units;
WebGLRenderingContext { Self {
reflector_: Reflector::new(), reflector_: Reflector::new(),
webgl_sender: ctx_data.sender, webgl_sender: ctx_data.sender,
webrender_image: Cell::new(None), webrender_image: Cell::new(None),
@ -203,6 +205,7 @@ impl WebGLRenderingContext {
limits: ctx_data.limits, limits: ctx_data.limits,
canvas: Dom::from_ref(canvas), canvas: Dom::from_ref(canvas),
last_error: Cell::new(None), last_error: Cell::new(None),
texture_packing_alignment: Cell::new(4),
texture_unpacking_settings: Cell::new(TextureUnpacking::CONVERT_COLORSPACE), texture_unpacking_settings: Cell::new(TextureUnpacking::CONVERT_COLORSPACE),
texture_unpacking_alignment: Cell::new(4), texture_unpacking_alignment: Cell::new(4),
bound_framebuffer: MutNullableDom::new(None), bound_framebuffer: MutNullableDom::new(None),
@ -1223,6 +1226,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
let unpack = self.texture_unpacking_settings.get(); let unpack = self.texture_unpacking_settings.get();
return BooleanValue(unpack.contains(TextureUnpacking::PREMULTIPLY_ALPHA)); return BooleanValue(unpack.contains(TextureUnpacking::PREMULTIPLY_ALPHA));
} }
constants::PACK_ALIGNMENT => {
return UInt32Value(self.texture_packing_alignment.get() as u32);
},
constants::UNPACK_ALIGNMENT => {
return UInt32Value(self.texture_unpacking_alignment.get());
},
_ => {} _ => {}
} }
@ -2517,39 +2526,20 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
let mut texture_settings = self.texture_unpacking_settings.get(); let mut texture_settings = self.texture_unpacking_settings.get();
match param_name { match param_name {
constants::UNPACK_FLIP_Y_WEBGL => { constants::UNPACK_FLIP_Y_WEBGL => {
if param_value != 0 { texture_settings.set(TextureUnpacking::FLIP_Y_AXIS, param_value != 0);
texture_settings.insert(TextureUnpacking::FLIP_Y_AXIS)
} else {
texture_settings.remove(TextureUnpacking::FLIP_Y_AXIS)
}
self.texture_unpacking_settings.set(texture_settings);
return;
}, },
constants::UNPACK_PREMULTIPLY_ALPHA_WEBGL => { constants::UNPACK_PREMULTIPLY_ALPHA_WEBGL => {
if param_value != 0 { texture_settings.set(TextureUnpacking::PREMULTIPLY_ALPHA, param_value != 0);
texture_settings.insert(TextureUnpacking::PREMULTIPLY_ALPHA)
} else {
texture_settings.remove(TextureUnpacking::PREMULTIPLY_ALPHA)
}
self.texture_unpacking_settings.set(texture_settings);
return;
}, },
constants::UNPACK_COLORSPACE_CONVERSION_WEBGL => { constants::UNPACK_COLORSPACE_CONVERSION_WEBGL => {
match param_value as u32 { let convert = match param_value as u32 {
constants::BROWSER_DEFAULT_WEBGL constants::BROWSER_DEFAULT_WEBGL => true,
=> texture_settings.insert(TextureUnpacking::CONVERT_COLORSPACE), constants::NONE => false,
constants::NONE
=> texture_settings.remove(TextureUnpacking::CONVERT_COLORSPACE),
_ => return self.webgl_error(InvalidEnum), _ => return self.webgl_error(InvalidEnum),
} };
texture_settings.set(TextureUnpacking::CONVERT_COLORSPACE, convert);
self.texture_unpacking_settings.set(texture_settings);
return;
}, },
constants::UNPACK_ALIGNMENT | constants::UNPACK_ALIGNMENT => {
constants::PACK_ALIGNMENT => {
match param_value { match param_value {
1 | 2 | 4 | 8 => (), 1 | 2 | 4 | 8 => (),
_ => return self.webgl_error(InvalidValue), _ => return self.webgl_error(InvalidValue),
@ -2557,8 +2547,20 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
self.texture_unpacking_alignment.set(param_value as u32); self.texture_unpacking_alignment.set(param_value as u32);
return; return;
}, },
constants::PACK_ALIGNMENT => {
match param_value {
1 | 2 | 4 | 8 => (),
_ => return self.webgl_error(InvalidValue),
}
// We never actually change the actual value on the GL side
// because it's better to receive the pixels without the padding
// and then write the result at the right place in ReadPixels.
self.texture_packing_alignment.set(param_value as u8);
return;
}
_ => return self.webgl_error(InvalidEnum), _ => return self.webgl_error(InvalidEnum),
} }
self.texture_unpacking_settings.set(texture_settings);
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
@ -2570,105 +2572,115 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn ReadPixels(&self, x: i32, y: i32, width: i32, height: i32, format: u32, pixel_type: u32, fn ReadPixels(&self, x: i32, y: i32, width: i32, height: i32, format: u32, pixel_type: u32,
mut pixels: CustomAutoRooterGuard<Option<ArrayBufferView>>) { mut pixels: CustomAutoRooterGuard<Option<ArrayBufferView>>) {
let (array_type, data) = match *pixels { let pixels = handle_potential_webgl_error!(
// Spec: If data is null then an INVALID_VALUE error is generated. self,
None => return self.webgl_error(InvalidValue), pixels.as_mut().ok_or(InvalidValue),
// The typed array is rooted and we should have a unique reference to it, return
// so retrieving its mutable slice is safe here );
Some(ref mut data) => (data.get_array_type(), unsafe { data.as_mut_slice() }),
};
handle_potential_webgl_error!(self, self.validate_framebuffer(), return);
match array_type {
Type::Uint8 => (),
_ => return self.webgl_error(InvalidOperation),
}
// From the WebGL specification, 5.14.12 Reading back pixels
//
// "Only two combinations of format and type are
// accepted. The first is format RGBA and type
// UNSIGNED_BYTE. The second is an implementation-chosen
// format. The values of format and type for this format
// may be determined by calling getParameter with the
// symbolic constants IMPLEMENTATION_COLOR_READ_FORMAT
// and IMPLEMENTATION_COLOR_READ_TYPE, respectively. The
// implementation-chosen format may vary depending on the
// format of the currently bound rendering
// surface. Unsupported combinations of format and type
// will generate an INVALID_OPERATION error."
//
// To avoid having to support general format packing math, we
// always report RGBA/UNSIGNED_BYTE as our only supported
// format.
if format != constants::RGBA || pixel_type != constants::UNSIGNED_BYTE {
return self.webgl_error(InvalidOperation);
}
let cpp = 4;
// "If pixels is non-null, but is not large enough to
// retrieve all of the pixels in the specified rectangle
// taking into account pixel store modes, an
// INVALID_OPERATION error is generated."
let stride = match width.checked_mul(cpp) {
Some(stride) => stride,
_ => return self.webgl_error(InvalidOperation),
};
match height.checked_mul(stride) {
Some(size) if size <= data.len() as i32 => {}
_ => return self.webgl_error(InvalidOperation),
}
// "For any pixel lying outside the frame buffer, the
// corresponding destination buffer range remains
// untouched; see Reading Pixels Outside the
// Framebuffer."
let mut x = x;
let mut y = y;
let mut width = width;
let mut height = height;
let mut dst_offset = 0;
if x < 0 {
dst_offset += cpp * -x;
width += x;
x = 0;
}
if y < 0 {
dst_offset += stride * -y;
height += y;
y = 0;
}
if width < 0 || height < 0 { if width < 0 || height < 0 {
return self.webgl_error(InvalidValue); return self.webgl_error(InvalidValue);
} }
match self.get_current_framebuffer_size() { if format != constants::RGBA || pixel_type != constants::UNSIGNED_BYTE {
Some((fb_width, fb_height)) => { return self.webgl_error(InvalidOperation);
if x + width > fb_width { }
width = fb_width - x;
} if pixels.get_array_type() != Type::Uint8 {
if y + height > fb_height { return self.webgl_error(InvalidOperation);
height = fb_height - y; }
}
} handle_potential_webgl_error!(self, self.validate_framebuffer(), return);
_ => return self.webgl_error(InvalidOperation), let (fb_width, fb_height) = handle_potential_webgl_error!(
self,
self.get_current_framebuffer_size().ok_or(InvalidOperation),
return
);
if width == 0 || height == 0 {
return;
}
let bytes_per_pixel = 4;
let row_len = handle_potential_webgl_error!(
self,
width.checked_mul(bytes_per_pixel).ok_or(InvalidOperation),
return
);
let pack_alignment = self.texture_packing_alignment.get() as i32;
let dest_padding = match row_len % pack_alignment {
0 => 0,
remainder => pack_alignment - remainder,
}; };
let dest_stride = row_len + dest_padding;
let full_rows_len = handle_potential_webgl_error!(
self,
dest_stride.checked_mul(height - 1).ok_or(InvalidOperation),
return
);
let required_dest_len = handle_potential_webgl_error!(
self,
full_rows_len.checked_add(row_len).ok_or(InvalidOperation),
return
);
let dest = unsafe { pixels.as_mut_slice() };
if dest.len() < required_dest_len as usize {
return self.webgl_error(InvalidOperation);
}
let mut src_x = x;
let mut src_y = y;
let mut src_width = width;
let mut src_height = height;
let mut dest_offset = 0;
if src_x < 0 {
if src_width <= -src_x {
return;
}
dest_offset += bytes_per_pixel * -src_x;
src_width += src_x;
src_x = 0;
}
if src_y < 0 {
if src_height <= -src_y {
return;
}
dest_offset += row_len * -src_y;
src_height += src_y;
src_y = 0;
}
if src_x + src_width > fb_width {
src_width = fb_width - src_x;
}
if src_y + src_height > fb_height {
src_height = fb_height - src_y;
}
let (sender, receiver) = ipc::bytes_channel().unwrap(); let (sender, receiver) = ipc::bytes_channel().unwrap();
self.send_command(WebGLCommand::ReadPixels(x, y, width, height, format, pixel_type, sender)); self.send_command(WebGLCommand::ReadPixels(
src_x,
src_y,
src_width,
src_height,
format,
pixel_type,
sender,
));
let result = receiver.recv().unwrap(); let src = receiver.recv().unwrap();
let src_row_len = (src_width * bytes_per_pixel) as usize;
for i in 0..height { for i in 0..src_height {
for j in 0..(width * cpp) { let dest_start = (dest_offset + i * dest_stride) as usize;
data[(dst_offset + i * stride + j) as usize] = let dest_end = dest_start + src_row_len;
result[(i * width * cpp + j) as usize]; let src_start = i as usize * src_row_len;
} let src_end = src_start + src_row_len;
dest[dest_start..dest_end].copy_from_slice(&src[src_start..src_end]);
} }
} }

View file

@ -1,7 +1,4 @@
[webgl1-idlharness.any.worker.html] [webgl1-idlharness.any.worker.html]
[webgl1-idlharness]
expected: FAIL
[WebGLRenderingContext interface: constant VERTEX_ATTRIB_ARRAY_ENABLED on interface prototype object] [WebGLRenderingContext interface: constant VERTEX_ATTRIB_ARRAY_ENABLED on interface prototype object]
expected: FAIL expected: FAIL
@ -2443,9 +2440,6 @@
[webgl1-idlharness.any.html] [webgl1-idlharness.any.html]
[webgl1-idlharness]
expected: FAIL
[WebGLRenderingContext interface: operation isContextLost()] [WebGLRenderingContext interface: operation isContextLost()]
expected: FAIL expected: FAIL

View file

@ -1,7 +0,0 @@
[webgl1-idlharness.window.html]
[webgl1-idlharness]
expected: FAIL
[WebGLRenderingContext interface: operation isContextLost()]
expected: FAIL

View file

@ -1,7 +1,4 @@
[webgl2-idlharness.any.html] [webgl2-idlharness.any.html]
[webgl2-idlharness]
expected: FAIL
[WebGL2RenderingContext interface: constant DRAW_BUFFER0 on interface prototype object] [WebGL2RenderingContext interface: constant DRAW_BUFFER0 on interface prototype object]
expected: FAIL expected: FAIL
@ -2086,9 +2083,6 @@
[webgl2-idlharness.any.worker.html] [webgl2-idlharness.any.worker.html]
[webgl2-idlharness]
expected: FAIL
[WebGL2RenderingContext interface: constant DRAW_BUFFER0 on interface prototype object] [WebGL2RenderingContext interface: constant DRAW_BUFFER0 on interface prototype object]
expected: FAIL expected: FAIL

File diff suppressed because it is too large Load diff

View file

@ -36364,7 +36364,7 @@
"testharness" "testharness"
], ],
"conformance/rendering/framebuffer-switch.html": [ "conformance/rendering/framebuffer-switch.html": [
"943f571b3b15f9794e2a9e3f89fcdadf1d49b6dd", "fc8c3dc5dac8a2ece2b286325bf8f1b227f3aee6",
"testharness" "testharness"
], ],
"conformance/rendering/framebuffer-texture-clear.html": [ "conformance/rendering/framebuffer-texture-clear.html": [
@ -36372,7 +36372,7 @@
"testharness" "testharness"
], ],
"conformance/rendering/framebuffer-texture-switch.html": [ "conformance/rendering/framebuffer-texture-switch.html": [
"5b677f79ad9378638624dab7c001f8381eed5e87", "04d03a0bc2e2f834762f0bb47e484a38323213f8",
"testharness" "testharness"
], ],
"conformance/rendering/gl-clear.html": [ "conformance/rendering/gl-clear.html": [

View file

@ -1,13 +0,0 @@
[read-pixels-pack-alignment.html]
[WebGL test #17: pixel should be 255,102,0,255. Was 0,0,0,0.]
expected: FAIL
[WebGL test #33: pixel should be 255,102,0,255. Was 0,0,0,0.]
expected: FAIL
[WebGL test #53: pixel should be 255,102,0,255. Was 0,0,0,0.]
expected: FAIL
[WebGL test #61: pixel should be 255,102,0,255. Was 0,0,0,0.]
expected: FAIL

View file

@ -1,3 +0,0 @@
[framebuffer-switch.html]
bug: https://github.com/servo/servo/issues/8984
expected: ERROR

View file

@ -1,3 +0,0 @@
[framebuffer-texture-switch.html]
bug: https://github.com/servo/servo/issues/8984
expected: ERROR

View file

@ -1,4 +1,5 @@
[out-of-bounds-index-buffers.html] [out-of-bounds-index-buffers.html]
bug: https://github.com/servo/servo/issues/20599
[WebGL test #2: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 0,0,255,255] [WebGL test #2: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 0,0,255,255]
expected: FAIL expected: FAIL

View file

@ -44,6 +44,7 @@
"use strict"; "use strict";
description("Test framebuffer switching. The test switches between two framebuffers, copying rendering results from one to the other."); description("Test framebuffer switching. The test switches between two framebuffers, copying rendering results from one to the other.");
var wtu = WebGLTestUtils; var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext("canvas"); var gl = wtu.create3DContext("canvas");
var program = wtu.setupTexturedQuad(gl); var program = wtu.setupTexturedQuad(gl);

View file

@ -44,6 +44,7 @@
"use strict"; "use strict";
description("Test framebuffer texture attachment switching. The test uses one framebuffer object and switches its color attachment."); description("Test framebuffer texture attachment switching. The test uses one framebuffer object and switches its color attachment.");
var wtu = WebGLTestUtils; var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext("canvas"); var gl = wtu.create3DContext("canvas");
var program = wtu.setupTexturedQuad(gl); var program = wtu.setupTexturedQuad(gl);