aboutsummaryrefslogtreecommitdiffstats
path: root/components/canvas/webgl_paint_thread.rs
diff options
context:
space:
mode:
authorGlenn Watson <gw@intuitionlibrary.com>2016-02-18 07:57:31 +1000
committerGlenn Watson <gw@intuitionlibrary.com>2016-02-18 10:35:29 +1000
commitc0531c312fdb0783e4d121b4c2d7f15d4f5cdc1f (patch)
treeced94496eb3f3b4149f1c2d3b0b02422bb3b5471 /components/canvas/webgl_paint_thread.rs
parentf7f0eea47035f4316d09db26315bf8ebb72637c9 (diff)
downloadservo-c0531c312fdb0783e4d121b4c2d7f15d4f5cdc1f.tar.gz
servo-c0531c312fdb0783e4d121b4c2d7f15d4f5cdc1f.zip
Add WebRender integration to Servo.
WebRender is an experimental GPU accelerated rendering backend for Servo. The WebRender backend can be specified by running Servo with the -w option (otherwise the default rendering backend will be used). WebRender has many bugs, and missing features - but it is usable to browse most websites - please report any WebRender specific rendering bugs you encounter!
Diffstat (limited to 'components/canvas/webgl_paint_thread.rs')
-rw-r--r--components/canvas/webgl_paint_thread.rs565
1 files changed, 84 insertions, 481 deletions
diff --git a/components/canvas/webgl_paint_thread.rs b/components/canvas/webgl_paint_thread.rs
index 913ef1b33ce..271ba0e2052 100644
--- a/components/canvas/webgl_paint_thread.rs
+++ b/components/canvas/webgl_paint_thread.rs
@@ -2,9 +2,8 @@
* 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, CanvasMsg, CanvasWebGLMsg, FromLayoutMsg, FromPaintMsg};
-use canvas_traits::{WebGLError, WebGLFramebufferBindingRequest, WebGLParameter, WebGLResult};
-use core::nonzero::NonZero;
+use canvas_traits::{CanvasCommonMsg, CanvasMsg, CanvasPixelData, CanvasData, CanvasWebGLMsg};
+use canvas_traits::{FromLayoutMsg, FromPaintMsg};
use euclid::size::Size2D;
use gleam::gl;
use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
@@ -15,186 +14,59 @@ use std::borrow::ToOwned;
use std::sync::mpsc::{Sender, channel};
use util::thread::spawn_named;
use util::vec::byte_swap;
+use webrender_traits;
+
+enum WebGLPaintTaskData {
+ WebRender(webrender_traits::RenderApi, webrender_traits::WebGLContextId),
+ Servo(GLContext<NativeGLContext>),
+}
pub struct WebGLPaintThread {
size: Size2D<i32>,
- original_context_size: Size2D<i32>,
- gl_context: GLContext<NativeGLContext>,
+ data: WebGLPaintTaskData,
}
impl WebGLPaintThread {
- fn new(size: Size2D<i32>, attrs: GLContextAttributes) -> Result<WebGLPaintThread, &'static str> {
- let context = try!(GLContext::new(size, attrs, ColorAttachmentType::Texture, None));
-
- // NOTE: As of right now this is always equal to the size parameter,
- // but this doesn't have to be true. Firefox after failing with
- // the requested size, tries with the nearest powers of two, for example.
- let real_size = context.borrow_draw_buffer().unwrap().size();
+ fn new(size: Size2D<i32>,
+ attrs: GLContextAttributes,
+ webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Result<WebGLPaintThread, String> {
+ let data = if let Some(sender) = webrender_api_sender {
+ let webrender_api = sender.create_api();
+ let id = try!(webrender_api.request_webgl_context(&size, attrs));
+ WebGLPaintTaskData::WebRender(webrender_api, id)
+ } else {
+ let context = try!(GLContext::<NativeGLContext>::new(size, attrs, ColorAttachmentType::Texture, None));
+ WebGLPaintTaskData::Servo(context)
+ };
Ok(WebGLPaintThread {
- size: real_size,
- original_context_size: real_size,
- gl_context: context
+ size: size,
+ data: data,
})
}
- /// In this function the gl commands are called.
- /// Those messages that just involve a gl call have the call inlined,
- /// processing of messages that require extra work are moved to functions
- ///
- /// NB: Not gl-related validations (names, lengths, accepted parameters...) are
- /// done in the corresponding DOM interfaces
pub fn handle_webgl_message(&self, message: CanvasWebGLMsg) {
debug!("WebGL message: {:?}", message);
-
- match message {
- CanvasWebGLMsg::GetContextAttributes(sender) =>
- self.context_attributes(sender),
- CanvasWebGLMsg::ActiveTexture(target) =>
- gl::active_texture(target),
- CanvasWebGLMsg::AttachShader(program_id, shader_id) =>
- gl::attach_shader(program_id, shader_id),
- CanvasWebGLMsg::BindAttribLocation(program_id, index, name) =>
- gl::bind_attrib_location(program_id, index, &name),
- CanvasWebGLMsg::BlendColor(r, g, b, a) =>
- gl::blend_color(r, g, b, a),
- CanvasWebGLMsg::BlendEquation(mode) =>
- gl::blend_equation(mode),
- CanvasWebGLMsg::BlendEquationSeparate(mode_rgb, mode_alpha) =>
- gl::blend_equation_separate(mode_rgb, mode_alpha),
- CanvasWebGLMsg::BlendFunc(src, dest) =>
- gl::blend_func(src, dest),
- CanvasWebGLMsg::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha) =>
- gl::blend_func_separate(src_rgb, dest_rgb, src_alpha, dest_alpha),
- CanvasWebGLMsg::BufferData(buffer_type, data, usage) =>
- gl::buffer_data(buffer_type, &data, usage),
- CanvasWebGLMsg::BufferSubData(buffer_type, offset, data) =>
- gl::buffer_sub_data(buffer_type, offset, &data),
- CanvasWebGLMsg::Clear(mask) =>
- gl::clear(mask),
- CanvasWebGLMsg::ClearColor(r, g, b, a) =>
- gl::clear_color(r, g, b, a),
- CanvasWebGLMsg::ClearDepth(depth) =>
- gl::clear_depth(depth),
- CanvasWebGLMsg::ClearStencil(stencil) =>
- gl::clear_stencil(stencil),
- CanvasWebGLMsg::ColorMask(r, g, b, a) =>
- gl::color_mask(r, g, b, a),
- CanvasWebGLMsg::CullFace(mode) =>
- gl::cull_face(mode),
- CanvasWebGLMsg::DepthFunc(func) =>
- gl::depth_func(func),
- CanvasWebGLMsg::DepthMask(flag) =>
- gl::depth_mask(flag),
- CanvasWebGLMsg::DepthRange(near, far) =>
- gl::depth_range(near, far),
- CanvasWebGLMsg::Disable(cap) =>
- gl::disable(cap),
- CanvasWebGLMsg::Enable(cap) =>
- gl::enable(cap),
- CanvasWebGLMsg::FrontFace(mode) =>
- gl::front_face(mode),
- CanvasWebGLMsg::DrawArrays(mode, first, count) =>
- gl::draw_arrays(mode, first, count),
- CanvasWebGLMsg::DrawElements(mode, count, type_, offset) =>
- gl::draw_elements(mode, count, type_, offset as u32),
- CanvasWebGLMsg::Hint(name, val) =>
- gl::hint(name, val),
- CanvasWebGLMsg::LineWidth(width) =>
- gl::line_width(width),
- CanvasWebGLMsg::PixelStorei(name, val) =>
- gl::pixel_store_i(name, val),
- CanvasWebGLMsg::PolygonOffset(factor, units) =>
- gl::polygon_offset(factor, units),
- CanvasWebGLMsg::Scissor(x, y, width, height) =>
- gl::scissor(x, y, width, height),
- CanvasWebGLMsg::EnableVertexAttribArray(attrib_id) =>
- gl::enable_vertex_attrib_array(attrib_id),
- CanvasWebGLMsg::GetAttribLocation(program_id, name, chan) =>
- self.attrib_location(program_id, name, chan),
- CanvasWebGLMsg::GetBufferParameter(target, param_id, chan) =>
- self.buffer_parameter(target, param_id, chan),
- CanvasWebGLMsg::GetParameter(param_id, chan) =>
- self.parameter(param_id, chan),
- CanvasWebGLMsg::GetProgramParameter(program_id, param_id, chan) =>
- self.program_parameter(program_id, param_id, chan),
- CanvasWebGLMsg::GetShaderParameter(shader_id, param_id, chan) =>
- self.shader_parameter(shader_id, param_id, chan),
- CanvasWebGLMsg::GetUniformLocation(program_id, name, chan) =>
- self.uniform_location(program_id, name, chan),
- CanvasWebGLMsg::CompileShader(shader_id, source) =>
- self.compile_shader(shader_id, source),
- CanvasWebGLMsg::CreateBuffer(chan) =>
- self.create_buffer(chan),
- CanvasWebGLMsg::CreateFramebuffer(chan) =>
- self.create_framebuffer(chan),
- CanvasWebGLMsg::CreateRenderbuffer(chan) =>
- self.create_renderbuffer(chan),
- CanvasWebGLMsg::CreateTexture(chan) =>
- self.create_texture(chan),
- CanvasWebGLMsg::CreateProgram(chan) =>
- self.create_program(chan),
- CanvasWebGLMsg::CreateShader(shader_type, chan) =>
- self.create_shader(shader_type, chan),
- CanvasWebGLMsg::DeleteBuffer(id) =>
- gl::delete_buffers(&[id]),
- CanvasWebGLMsg::DeleteFramebuffer(id) =>
- gl::delete_framebuffers(&[id]),
- CanvasWebGLMsg::DeleteRenderbuffer(id) =>
- gl::delete_renderbuffers(&[id]),
- CanvasWebGLMsg::DeleteTexture(id) =>
- gl::delete_textures(&[id]),
- CanvasWebGLMsg::DeleteProgram(id) =>
- gl::delete_program(id),
- CanvasWebGLMsg::DeleteShader(id) =>
- gl::delete_shader(id),
- CanvasWebGLMsg::BindBuffer(target, id) =>
- gl::bind_buffer(target, id),
- CanvasWebGLMsg::BindFramebuffer(target, request) =>
- self.bind_framebuffer(target, request),
- CanvasWebGLMsg::BindRenderbuffer(target, id) =>
- gl::bind_renderbuffer(target, id),
- CanvasWebGLMsg::BindTexture(target, id) =>
- gl::bind_texture(target, id),
- CanvasWebGLMsg::LinkProgram(program_id) =>
- gl::link_program(program_id),
- CanvasWebGLMsg::Uniform1f(uniform_id, x) =>
- gl::uniform_1f(uniform_id, x),
- CanvasWebGLMsg::Uniform4f(uniform_id, x, y, z, w) =>
- gl::uniform_4f(uniform_id, x, y, z, w),
- CanvasWebGLMsg::UseProgram(program_id) =>
- gl::use_program(program_id),
- CanvasWebGLMsg::VertexAttrib(attrib_id, x, y, z, w) =>
- gl::vertex_attrib_4f(attrib_id, x, y, z, w),
- CanvasWebGLMsg::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset) =>
- gl::vertex_attrib_pointer_f32(attrib_id, size, normalized, stride, offset as u32),
- CanvasWebGLMsg::Viewport(x, y, width, height) =>
- gl::viewport(x, y, width, height),
- CanvasWebGLMsg::TexImage2D(target, level, internal, width, height, format, data_type, data) =>
- gl::tex_image_2d(target, level, internal, width, height, /*border*/0, format, data_type, Some(&data)),
- CanvasWebGLMsg::TexParameteri(target, name, value) =>
- gl::tex_parameter_i(target, name, value),
- CanvasWebGLMsg::TexParameterf(target, name, value) =>
- gl::tex_parameter_f(target, name, value),
- CanvasWebGLMsg::DrawingBufferWidth(sender) =>
- self.send_drawing_buffer_width(sender),
- CanvasWebGLMsg::DrawingBufferHeight(sender) =>
- self.send_drawing_buffer_height(sender),
+ match self.data {
+ WebGLPaintTaskData::WebRender(ref api, id) => {
+ api.send_webgl_command(id, message);
+ }
+ WebGLPaintTaskData::Servo(ref ctx) => {
+ message.apply(ctx);
+ }
}
-
- // FIXME: Use debug_assertions once tests are run with them
- let error = gl::get_error();
- assert!(error == gl::NO_ERROR, "Unexpected WebGL error: 0x{:x} ({})", error, error);
}
/// Creates a new `WebGLPaintThread` and returns the out-of-process sender and the in-process
/// sender for it.
- pub fn start(size: Size2D<i32>, attrs: GLContextAttributes)
- -> Result<(IpcSender<CanvasMsg>, Sender<CanvasMsg>), &'static str> {
+ pub fn start(size: Size2D<i32>,
+ attrs: GLContextAttributes,
+ webrender_api_sender: Option<webrender_traits::RenderApiSender>)
+ -> Result<(IpcSender<CanvasMsg>, Sender<CanvasMsg>), String> {
let (in_process_chan, in_process_port) = channel();
let (result_chan, result_port) = channel();
spawn_named("WebGLThread".to_owned(), move || {
- let mut painter = match WebGLPaintThread::new(size, attrs) {
+ let mut painter = match WebGLPaintThread::new(size, attrs, webrender_api_sender) {
Ok(thread) => {
result_chan.send(Ok(())).unwrap();
thread
@@ -217,8 +89,8 @@ impl WebGLPaintThread {
},
CanvasMsg::FromLayout(message) => {
match message {
- FromLayoutMsg::SendPixelContents(chan) =>
- painter.send_pixel_contents(chan),
+ FromLayoutMsg::SendData(chan) =>
+ painter.send_data(chan),
}
}
CanvasMsg::FromPaint(message) => {
@@ -239,319 +111,40 @@ impl WebGLPaintThread {
})
}
- #[inline]
- fn context_attributes(&self, sender: IpcSender<GLContextAttributes>) {
- sender.send(*self.gl_context.borrow_attributes()).unwrap()
- }
-
- #[inline]
- fn send_drawing_buffer_width(&self, sender: IpcSender<i32>) {
- sender.send(self.size.width).unwrap()
- }
-
- #[inline]
- fn send_drawing_buffer_height(&self, sender: IpcSender<i32>) {
- sender.send(self.size.height).unwrap()
- }
-
- fn create_buffer(&self, chan: IpcSender<Option<NonZero<u32>>>) {
- let buffer = gl::gen_buffers(1)[0];
- let buffer = if buffer == 0 {
- None
- } else {
- Some(unsafe { NonZero::new(buffer) })
- };
- chan.send(buffer).unwrap();
- }
-
- fn create_framebuffer(&self, chan: IpcSender<Option<NonZero<u32>>>) {
- let framebuffer = gl::gen_framebuffers(1)[0];
- let framebuffer = if framebuffer == 0 {
- None
- } else {
- Some(unsafe { NonZero::new(framebuffer) })
- };
- chan.send(framebuffer).unwrap();
- }
-
- fn create_renderbuffer(&self, chan: IpcSender<Option<NonZero<u32>>>) {
- let renderbuffer = gl::gen_renderbuffers(1)[0];
- let renderbuffer = if renderbuffer == 0 {
- None
- } else {
- Some(unsafe { NonZero::new(renderbuffer) })
- };
- chan.send(renderbuffer).unwrap();
- }
-
- fn create_texture(&self, chan: IpcSender<Option<NonZero<u32>>>) {
- let texture = gl::gen_framebuffers(1)[0];
- let texture = if texture == 0 {
- None
- } else {
- Some(unsafe { NonZero::new(texture) })
- };
- chan.send(texture).unwrap();
- }
-
- fn create_program(&self, chan: IpcSender<Option<NonZero<u32>>>) {
- let program = gl::create_program();
- let program = if program == 0 {
- None
- } else {
- Some(unsafe { NonZero::new(program) })
- };
-
- chan.send(program).unwrap();
- }
-
- fn create_shader(&self, shader_type: u32, chan: IpcSender<Option<NonZero<u32>>>) {
- let shader = gl::create_shader(shader_type);
- let shader = if shader == 0 {
- None
- } else {
- Some(unsafe { NonZero::new(shader) })
- };
- chan.send(shader).unwrap();
- }
-
- #[inline]
- fn bind_framebuffer(&self, target: u32, request: WebGLFramebufferBindingRequest) {
- let id = match request {
- WebGLFramebufferBindingRequest::Explicit(id) => id,
- WebGLFramebufferBindingRequest::Default =>
- self.gl_context.borrow_draw_buffer().unwrap().get_framebuffer(),
- };
-
- gl::bind_framebuffer(target, id);
- }
-
- #[inline]
- fn compile_shader(&self, shader_id: u32, source: String) {
- gl::shader_source(shader_id, &[source.as_bytes()]);
- gl::compile_shader(shader_id);
- }
-
- fn attrib_location(&self, program_id: u32, name: String, chan: IpcSender<Option<i32>> ) {
- let attrib_location = gl::get_attrib_location(program_id, &name);
-
- let attrib_location = if attrib_location == -1 {
- None
- } else {
- Some(attrib_location)
- };
-
- chan.send(attrib_location).unwrap();
- }
-
- fn parameter(&self,
- param_id: u32,
- chan: IpcSender<WebGLResult<WebGLParameter>>) {
- let result = match param_id {
- gl::ACTIVE_TEXTURE |
- //gl::ALPHA_BITS |
- gl::BLEND_DST_ALPHA |
- gl::BLEND_DST_RGB |
- gl::BLEND_EQUATION_ALPHA |
- gl::BLEND_EQUATION_RGB |
- gl::BLEND_SRC_ALPHA |
- gl::BLEND_SRC_RGB |
- //gl::BLUE_BITS |
- gl::CULL_FACE_MODE |
- //gl::DEPTH_BITS |
- gl::DEPTH_FUNC |
- gl::FRONT_FACE |
- //gl::GENERATE_MIPMAP_HINT |
- //gl::GREEN_BITS |
- //gl::IMPLEMENTATION_COLOR_READ_FORMAT |
- //gl::IMPLEMENTATION_COLOR_READ_TYPE |
- gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS |
- gl::MAX_CUBE_MAP_TEXTURE_SIZE |
- //gl::MAX_FRAGMENT_UNIFORM_VECTORS |
- gl::MAX_RENDERBUFFER_SIZE |
- gl::MAX_TEXTURE_IMAGE_UNITS |
- gl::MAX_TEXTURE_SIZE |
- //gl::MAX_VARYING_VECTORS |
- gl::MAX_VERTEX_ATTRIBS |
- gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS |
- //gl::MAX_VERTEX_UNIFORM_VECTORS |
- gl::PACK_ALIGNMENT |
- //gl::RED_BITS |
- gl::SAMPLE_BUFFERS |
- gl::SAMPLES |
- gl::STENCIL_BACK_FAIL |
- gl::STENCIL_BACK_FUNC |
- gl::STENCIL_BACK_PASS_DEPTH_FAIL |
- gl::STENCIL_BACK_PASS_DEPTH_PASS |
- gl::STENCIL_BACK_REF |
- gl::STENCIL_BACK_VALUE_MASK |
- gl::STENCIL_BACK_WRITEMASK |
- //gl::STENCIL_BITS |
- gl::STENCIL_CLEAR_VALUE |
- gl::STENCIL_FAIL |
- gl::STENCIL_FUNC |
- gl::STENCIL_PASS_DEPTH_FAIL |
- gl::STENCIL_PASS_DEPTH_PASS |
- gl::STENCIL_REF |
- gl::STENCIL_VALUE_MASK |
- gl::STENCIL_WRITEMASK |
- gl::SUBPIXEL_BITS |
- gl::UNPACK_ALIGNMENT =>
- //gl::UNPACK_COLORSPACE_CONVERSION_WEBGL =>
- Ok(WebGLParameter::Int(gl::get_integer_v(param_id))),
-
- gl::BLEND |
- gl::CULL_FACE |
- gl::DEPTH_TEST |
- gl::DEPTH_WRITEMASK |
- gl::DITHER |
- gl::POLYGON_OFFSET_FILL |
- gl::SAMPLE_COVERAGE_INVERT |
- gl::STENCIL_TEST =>
- //gl::UNPACK_FLIP_Y_WEBGL |
- //gl::UNPACK_PREMULTIPLY_ALPHA_WEBGL =>
- Ok(WebGLParameter::Bool(gl::get_boolean_v(param_id) != 0)),
-
- gl::DEPTH_CLEAR_VALUE |
- gl::LINE_WIDTH |
- gl::POLYGON_OFFSET_FACTOR |
- gl::POLYGON_OFFSET_UNITS |
- gl::SAMPLE_COVERAGE_VALUE =>
- Ok(WebGLParameter::Float(gl::get_float_v(param_id))),
-
- gl::VERSION => Ok(WebGLParameter::String("WebGL 1.0".to_owned())),
- gl::RENDERER |
- gl::VENDOR => Ok(WebGLParameter::String("Mozilla/Servo".to_owned())),
- gl::SHADING_LANGUAGE_VERSION => Ok(WebGLParameter::String("WebGL GLSL ES 1.0".to_owned())),
-
- // TODO(zbarsky, ecoal95): Implement support for the following valid parameters
- // Float32Array
- gl::ALIASED_LINE_WIDTH_RANGE |
- //gl::ALIASED_POINT_SIZE_RANGE |
- //gl::BLEND_COLOR |
- gl::COLOR_CLEAR_VALUE |
- gl::DEPTH_RANGE |
-
- // WebGLBuffer
- gl::ARRAY_BUFFER_BINDING |
- gl::ELEMENT_ARRAY_BUFFER_BINDING |
-
- // WebGLFrameBuffer
- gl::FRAMEBUFFER_BINDING |
-
- // WebGLRenderBuffer
- gl::RENDERBUFFER_BINDING |
-
- // WebGLProgram
- gl::CURRENT_PROGRAM |
-
- // WebGLTexture
- gl::TEXTURE_BINDING_2D |
- gl::TEXTURE_BINDING_CUBE_MAP |
-
- // sequence<GlBoolean>
- gl::COLOR_WRITEMASK |
-
- // Uint32Array
- gl::COMPRESSED_TEXTURE_FORMATS |
-
- // Int32Array
- gl::MAX_VIEWPORT_DIMS |
- gl::SCISSOR_BOX |
- gl::VIEWPORT => Err(WebGLError::InvalidEnum),
-
- // Invalid parameters
- _ => Err(WebGLError::InvalidEnum)
- };
-
- chan.send(result).unwrap();
- }
-
- fn buffer_parameter(&self,
- target: u32,
- param_id: u32,
- chan: IpcSender<WebGLResult<WebGLParameter>>) {
- let result = match param_id {
- gl::BUFFER_SIZE |
- gl::BUFFER_USAGE =>
- Ok(WebGLParameter::Int(gl::get_buffer_parameter_iv(target, param_id))),
- _ => Err(WebGLError::InvalidEnum),
- };
-
- chan.send(result).unwrap();
- }
-
- fn program_parameter(&self,
- program_id: u32,
- param_id: u32,
- chan: IpcSender<WebGLResult<WebGLParameter>>) {
- let result = match param_id {
- gl::DELETE_STATUS |
- gl::LINK_STATUS |
- gl::VALIDATE_STATUS =>
- Ok(WebGLParameter::Bool(gl::get_program_iv(program_id, param_id) != 0)),
- gl::ATTACHED_SHADERS |
- gl::ACTIVE_ATTRIBUTES |
- gl::ACTIVE_UNIFORMS =>
- Ok(WebGLParameter::Int(gl::get_program_iv(program_id, param_id))),
- _ => Err(WebGLError::InvalidEnum),
- };
-
- chan.send(result).unwrap();
- }
-
- fn shader_parameter(&self,
- shader_id: u32,
- param_id: u32,
- chan: IpcSender<WebGLResult<WebGLParameter>>) {
- let result = match param_id {
- gl::SHADER_TYPE =>
- Ok(WebGLParameter::Int(gl::get_shader_iv(shader_id, param_id))),
- gl::DELETE_STATUS |
- gl::COMPILE_STATUS =>
- Ok(WebGLParameter::Bool(gl::get_shader_iv(shader_id, param_id) != 0)),
- _ => Err(WebGLError::InvalidEnum),
- };
-
- chan.send(result).unwrap();
- }
-
- fn uniform_location(&self, program_id: u32, name: String, chan: IpcSender<Option<i32>>) {
- let location = gl::get_uniform_location(program_id, &name);
- let location = if location == -1 {
- None
- } else {
- Some(location)
- };
+ fn send_data(&mut self, chan: IpcSender<CanvasData>) {
+ match self.data {
+ WebGLPaintTaskData::Servo(_) => {
+ let width = self.size.width as usize;
+ let height = self.size.height as usize;
+
+ let mut pixels = gl::read_pixels(0, 0,
+ self.size.width as gl::GLsizei,
+ self.size.height as gl::GLsizei,
+ gl::RGBA, gl::UNSIGNED_BYTE);
+ // flip image vertically (texture is upside down)
+ let orig_pixels = pixels.clone();
+ let stride = width * 4;
+ for y in 0..height {
+ let dst_start = y * stride;
+ let src_start = (height - y - 1) * stride;
+ let src_slice = &orig_pixels[src_start .. src_start + stride];
+ (&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]);
+ }
- chan.send(location).unwrap();
- }
+ // rgba -> bgra
+ byte_swap(&mut pixels);
- fn send_pixel_contents(&mut self, chan: IpcSender<IpcSharedMemory>) {
- // FIXME(#5652, dmarcos) Instead of a readback strategy we have
- // to layerize the canvas.
- // TODO(pcwalton): We'd save a copy if we had an `IpcSharedMemoryBuilder` abstraction that
- // allowed you to mutate in-place before freezing the object for sending.
- let width = self.size.width as usize;
- let height = self.size.height as usize;
+ let pixel_data = CanvasPixelData {
+ image_data: IpcSharedMemory::from_bytes(&pixels[..]),
+ image_key: None,
+ };
- let mut pixels = gl::read_pixels(0, 0,
- self.size.width as gl::GLsizei,
- self.size.height as gl::GLsizei,
- gl::RGBA, gl::UNSIGNED_BYTE);
- // flip image vertically (texture is upside down)
- let orig_pixels = pixels.clone();
- let stride = width * 4;
- for y in 0..height {
- let dst_start = y * stride;
- let src_start = (height - y - 1) * stride;
- let src_slice = &orig_pixels[src_start .. src_start + stride];
- (&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]);
+ chan.send(CanvasData::Pixels(pixel_data)).unwrap();
+ }
+ WebGLPaintTaskData::WebRender(_, id) => {
+ chan.send(CanvasData::WebGL(id)).unwrap();
+ }
}
-
- // rgba -> bgra
- byte_swap(&mut pixels);
- chan.send(IpcSharedMemory::from_bytes(&pixels[..])).unwrap();
}
fn send_native_surface(&self, _: Sender<NativeSurface>) {
@@ -561,18 +154,28 @@ impl WebGLPaintThread {
}
fn recreate(&mut self, size: Size2D<i32>) -> Result<(), &'static str> {
- if size.width > self.original_context_size.width ||
- size.height > self.original_context_size.height {
- try!(self.gl_context.resize(size));
- self.size = self.gl_context.borrow_draw_buffer().unwrap().size();
- } else {
- self.size = size;
- unsafe { gl::Scissor(0, 0, size.width, size.height); }
+ match self.data {
+ WebGLPaintTaskData::Servo(ref mut context) => {
+ if size.width > self.size.width ||
+ size.height > self.size.height {
+ try!(context.resize(size));
+ self.size = context.borrow_draw_buffer().unwrap().size();
+ } else {
+ self.size = size;
+ unsafe { gl::Scissor(0, 0, size.width, size.height); }
+ }
+ }
+ WebGLPaintTaskData::WebRender(_, _) => {
+ // TODO
+ }
}
+
Ok(())
}
fn init(&mut self) {
- self.gl_context.make_current().unwrap();
+ if let WebGLPaintTaskData::Servo(ref context) = self.data {
+ context.make_current().unwrap();
+ }
}
}