Improve WebGL architecture.

This commit is contained in:
Imanol Fernandez 2017-08-15 16:05:22 +02:00
parent e9cbbc58cc
commit 703962fe61
54 changed files with 3154 additions and 1426 deletions

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use base64;
use canvas_traits::{CanvasMsg, FromScriptMsg};
use canvas_traits::canvas::{CanvasMsg, FromScriptMsg};
use dom::attr::Attr;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods;
@ -30,11 +30,11 @@ use euclid::Size2D;
use html5ever::{LocalName, Prefix};
use image::ColorType;
use image::png::PNGEncoder;
use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::ipc;
use js::error::throw_type_error;
use js::jsapi::{HandleValue, JSContext};
use offscreen_gl_context::GLContextAttributes;
use script_layout_interface::HTMLCanvasData;
use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource};
use std::iter::repeat;
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
@ -106,21 +106,22 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> {
fn data(&self) -> HTMLCanvasData {
unsafe {
let canvas = &*self.unsafe_get();
let ipc_renderer = canvas.context.borrow_for_layout().as_ref().map(|context| {
match *context {
CanvasContext::Context2d(ref context) => {
context.to_layout().get_ipc_renderer()
},
CanvasContext::WebGL(ref context) => {
context.to_layout().get_ipc_renderer()
},
let source = match canvas.context.borrow_for_layout().as_ref() {
Some(&CanvasContext::Context2d(ref context)) => {
HTMLCanvasDataSource::Image(Some(context.to_layout().get_ipc_renderer()))
},
Some(&CanvasContext::WebGL(ref context)) => {
context.to_layout().canvas_data_source()
},
None => {
HTMLCanvasDataSource::Image(None)
}
});
};
let width_attr = canvas.upcast::<Element>().get_attr_for_layout(&ns!(), &local_name!("width"));
let height_attr = canvas.upcast::<Element>().get_attr_for_layout(&ns!(), &local_name!("height"));
HTMLCanvasData {
ipc_renderer: ipc_renderer,
source: source,
width: width_attr.map_or(DEFAULT_WIDTH, |val| val.as_uint()),
height: height_attr.map_or(DEFAULT_HEIGHT, |val| val.as_uint()),
}
@ -150,15 +151,6 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> {
impl HTMLCanvasElement {
pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> {
self.context.borrow().as_ref().map(|context| {
match *context {
CanvasContext::Context2d(ref context) => context.ipc_renderer(),
CanvasContext::WebGL(ref context) => context.ipc_renderer(),
}
})
}
pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> {
if self.context.borrow().is_none() {
let window = window_from_node(self);
@ -221,22 +213,26 @@ impl HTMLCanvasElement {
return None
}
let data = if let Some(renderer) = self.ipc_renderer() {
let (sender, receiver) = ipc::channel().unwrap();
let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender));
renderer.send(msg).unwrap();
let data = match self.context.borrow().as_ref() {
Some(&CanvasContext::Context2d(ref context)) => {
let (sender, receiver) = ipc::channel().unwrap();
let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender));
context.get_ipc_renderer().send(msg).unwrap();
match receiver.recv().unwrap() {
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;
match receiver.recv().unwrap() {
Some(pixels) => pixels,
None => {
return None;
}
}
},
Some(&CanvasContext::WebGL(_)) => {
// TODO: add a method in WebGLRenderingContext to get the pixels.
return None;
},
None => {
repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect()
}
} else {
repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect()
};
Some((data, size))