webgl: Make the api return the context limits and use them for validations

This allows keeping the VertexAttrib* calls asynchronous.

Another option would be to do the validation in the apply() function,
but that'd require us passing an unnecessary channel around and add
extra synchronization.

The counterpart of this is that it has to be updated when the context
changes, but that's less problem.
This commit is contained in:
Emilio Cobos Álvarez 2016-03-27 16:08:52 +02:00 committed by Emilio Cobos Álvarez
parent 8d7ee15ace
commit 6fcc03c965
7 changed files with 44 additions and 25 deletions

View file

@ -6,7 +6,7 @@ use canvas_traits::{CanvasCommonMsg, CanvasMsg, CanvasPixelData, CanvasData, Fro
use euclid::size::Size2D;
use gleam::gl;
use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
use offscreen_gl_context::{ColorAttachmentType, GLContext, GLContextAttributes, NativeGLContext};
use offscreen_gl_context::{ColorAttachmentType, GLContext, GLLimits, GLContextAttributes, NativeGLContext};
use std::borrow::ToOwned;
use std::sync::mpsc::channel;
use util::thread::spawn_named;
@ -26,20 +26,24 @@ pub struct WebGLPaintThread {
impl WebGLPaintThread {
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 {
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
-> Result<(WebGLPaintThread, GLLimits), String> {
let (data, limits) = 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)
let (id, limits) = try!(webrender_api.request_webgl_context(&size, attrs));
(WebGLPaintTaskData::WebRender(webrender_api, id), limits)
} else {
let context = try!(GLContext::<NativeGLContext>::new(size, attrs, ColorAttachmentType::Texture, None));
WebGLPaintTaskData::Servo(context)
let limits = context.borrow_limits().clone();
(WebGLPaintTaskData::Servo(context), limits)
};
Ok(WebGLPaintThread {
let painter_object = WebGLPaintThread {
size: size,
data: data,
})
};
Ok((painter_object, limits))
}
pub fn handle_webgl_message(&self, message: webrender_traits::WebGLCommand) {
@ -59,13 +63,13 @@ impl WebGLPaintThread {
pub fn start(size: Size2D<i32>,
attrs: GLContextAttributes,
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
-> Result<IpcSender<CanvasMsg>, String> {
-> Result<(IpcSender<CanvasMsg>, GLLimits), String> {
let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap();
let (result_chan, result_port) = channel();
spawn_named("WebGLThread".to_owned(), move || {
let mut painter = match WebGLPaintThread::new(size, attrs, webrender_api_sender) {
Ok(thread) => {
result_chan.send(Ok(())).unwrap();
Ok((thread, limits)) => {
result_chan.send(Ok(limits)).unwrap();
thread
},
Err(e) => {
@ -95,8 +99,7 @@ impl WebGLPaintThread {
}
});
try!(result_port.recv().unwrap());
Ok(sender)
result_port.recv().unwrap().map(|limits| (sender, limits))
}
fn send_data(&mut self, chan: IpcSender<CanvasData>) {