mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
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:
parent
8d7ee15ace
commit
6fcc03c965
7 changed files with 44 additions and 25 deletions
|
@ -6,7 +6,7 @@ use canvas_traits::{CanvasCommonMsg, CanvasMsg, CanvasPixelData, CanvasData, Fro
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
use gleam::gl;
|
use gleam::gl;
|
||||||
use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
|
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::borrow::ToOwned;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use util::thread::spawn_named;
|
use util::thread::spawn_named;
|
||||||
|
@ -26,20 +26,24 @@ pub struct WebGLPaintThread {
|
||||||
impl WebGLPaintThread {
|
impl WebGLPaintThread {
|
||||||
fn new(size: Size2D<i32>,
|
fn new(size: Size2D<i32>,
|
||||||
attrs: GLContextAttributes,
|
attrs: GLContextAttributes,
|
||||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Result<WebGLPaintThread, String> {
|
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
||||||
let data = if let Some(sender) = webrender_api_sender {
|
-> Result<(WebGLPaintThread, GLLimits), String> {
|
||||||
|
let (data, limits) = if let Some(sender) = webrender_api_sender {
|
||||||
let webrender_api = sender.create_api();
|
let webrender_api = sender.create_api();
|
||||||
let (id, _) = try!(webrender_api.request_webgl_context(&size, attrs));
|
let (id, limits) = try!(webrender_api.request_webgl_context(&size, attrs));
|
||||||
WebGLPaintTaskData::WebRender(webrender_api, id)
|
(WebGLPaintTaskData::WebRender(webrender_api, id), limits)
|
||||||
} else {
|
} else {
|
||||||
let context = try!(GLContext::<NativeGLContext>::new(size, attrs, ColorAttachmentType::Texture, None));
|
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,
|
size: size,
|
||||||
data: data,
|
data: data,
|
||||||
})
|
};
|
||||||
|
|
||||||
|
Ok((painter_object, limits))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_webgl_message(&self, message: webrender_traits::WebGLCommand) {
|
pub fn handle_webgl_message(&self, message: webrender_traits::WebGLCommand) {
|
||||||
|
@ -59,13 +63,13 @@ impl WebGLPaintThread {
|
||||||
pub fn start(size: Size2D<i32>,
|
pub fn start(size: Size2D<i32>,
|
||||||
attrs: GLContextAttributes,
|
attrs: GLContextAttributes,
|
||||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
||||||
-> Result<IpcSender<CanvasMsg>, String> {
|
-> Result<(IpcSender<CanvasMsg>, GLLimits), String> {
|
||||||
let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap();
|
let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap();
|
||||||
let (result_chan, result_port) = channel();
|
let (result_chan, result_port) = channel();
|
||||||
spawn_named("WebGLThread".to_owned(), move || {
|
spawn_named("WebGLThread".to_owned(), move || {
|
||||||
let mut painter = match WebGLPaintThread::new(size, attrs, webrender_api_sender) {
|
let mut painter = match WebGLPaintThread::new(size, attrs, webrender_api_sender) {
|
||||||
Ok(thread) => {
|
Ok((thread, limits)) => {
|
||||||
result_chan.send(Ok(())).unwrap();
|
result_chan.send(Ok(limits)).unwrap();
|
||||||
thread
|
thread
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -95,8 +99,7 @@ impl WebGLPaintThread {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
try!(result_port.recv().unwrap());
|
result_port.recv().unwrap().map(|limits| (sender, limits))
|
||||||
Ok(sender)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_data(&mut self, chan: IpcSender<CanvasData>) {
|
fn send_data(&mut self, chan: IpcSender<CanvasData>) {
|
||||||
|
|
|
@ -39,7 +39,7 @@ use msg::webdriver_msg;
|
||||||
use net_traits::image_cache_thread::ImageCacheThread;
|
use net_traits::image_cache_thread::ImageCacheThread;
|
||||||
use net_traits::storage_thread::{StorageThread, StorageThreadMsg};
|
use net_traits::storage_thread::{StorageThread, StorageThreadMsg};
|
||||||
use net_traits::{self, ResourceThread};
|
use net_traits::{self, ResourceThread};
|
||||||
use offscreen_gl_context::GLContextAttributes;
|
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
||||||
use pipeline::{CompositionPipeline, InitialPipelineState, Pipeline, UnprivilegedPipelineContent};
|
use pipeline::{CompositionPipeline, InitialPipelineState, Pipeline, UnprivilegedPipelineContent};
|
||||||
use profile_traits::mem;
|
use profile_traits::mem;
|
||||||
use profile_traits::time;
|
use profile_traits::time;
|
||||||
|
@ -1349,11 +1349,11 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
||||||
&mut self,
|
&mut self,
|
||||||
size: &Size2D<i32>,
|
size: &Size2D<i32>,
|
||||||
attributes: GLContextAttributes,
|
attributes: GLContextAttributes,
|
||||||
response_sender: IpcSender<Result<IpcSender<CanvasMsg>, String>>) {
|
response_sender: IpcSender<Result<(IpcSender<CanvasMsg>, GLLimits), String>>) {
|
||||||
let webrender_api = self.webrender_api_sender.clone();
|
let webrender_api = self.webrender_api_sender.clone();
|
||||||
let sender = WebGLPaintThread::start(*size, attributes, webrender_api);
|
let response = WebGLPaintThread::start(*size, attributes, webrender_api);
|
||||||
|
|
||||||
response_sender.send(sender)
|
response_sender.send(response)
|
||||||
.unwrap_or_else(|e| debug!("Create WebGL paint thread response failed ({})", e))
|
.unwrap_or_else(|e| debug!("Create WebGL paint thread response failed ({})", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ use net_traits::image::base::{Image, ImageMetadata};
|
||||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
|
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
|
||||||
use net_traits::response::HttpsState;
|
use net_traits::response::HttpsState;
|
||||||
use net_traits::storage_thread::StorageType;
|
use net_traits::storage_thread::StorageType;
|
||||||
|
use offscreen_gl_context::GLLimits;
|
||||||
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
||||||
use profile_traits::time::ProfilerChan as TimeProfilerChan;
|
use profile_traits::time::ProfilerChan as TimeProfilerChan;
|
||||||
use script_thread::ScriptChan;
|
use script_thread::ScriptChan;
|
||||||
|
@ -307,7 +308,7 @@ no_jsmanaged_fields!(StorageType);
|
||||||
no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle);
|
no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle);
|
||||||
no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending);
|
no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending);
|
||||||
no_jsmanaged_fields!(RepetitionStyle);
|
no_jsmanaged_fields!(RepetitionStyle);
|
||||||
no_jsmanaged_fields!(WebGLError);
|
no_jsmanaged_fields!(WebGLError, GLLimits);
|
||||||
no_jsmanaged_fields!(TimeProfilerChan);
|
no_jsmanaged_fields!(TimeProfilerChan);
|
||||||
no_jsmanaged_fields!(MemProfilerChan);
|
no_jsmanaged_fields!(MemProfilerChan);
|
||||||
no_jsmanaged_fields!(PseudoElement);
|
no_jsmanaged_fields!(PseudoElement);
|
||||||
|
|
|
@ -30,7 +30,7 @@ use js::jsapi::{JSContext, JSObject, RootedValue};
|
||||||
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue};
|
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue};
|
||||||
use net_traits::image::base::PixelFormat;
|
use net_traits::image::base::PixelFormat;
|
||||||
use net_traits::image_cache_thread::ImageResponse;
|
use net_traits::image_cache_thread::ImageResponse;
|
||||||
use offscreen_gl_context::GLContextAttributes;
|
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
||||||
use script_traits::ScriptMsg as ConstellationMsg;
|
use script_traits::ScriptMsg as ConstellationMsg;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
@ -70,6 +70,8 @@ pub struct WebGLRenderingContext {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
||||||
ipc_renderer: IpcSender<CanvasMsg>,
|
ipc_renderer: IpcSender<CanvasMsg>,
|
||||||
|
#[ignore_heap_size_of = "Defined in offscreen_gl_context"]
|
||||||
|
limits: GLLimits,
|
||||||
canvas: JS<HTMLCanvasElement>,
|
canvas: JS<HTMLCanvasElement>,
|
||||||
#[ignore_heap_size_of = "Defined in webrender_traits"]
|
#[ignore_heap_size_of = "Defined in webrender_traits"]
|
||||||
last_error: Cell<Option<WebGLError>>,
|
last_error: Cell<Option<WebGLError>>,
|
||||||
|
@ -94,10 +96,11 @@ impl WebGLRenderingContext {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let result = receiver.recv().unwrap();
|
let result = receiver.recv().unwrap();
|
||||||
|
|
||||||
result.map(|ipc_renderer| {
|
result.map(|(ipc_renderer, context_limits)| {
|
||||||
WebGLRenderingContext {
|
WebGLRenderingContext {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
ipc_renderer: ipc_renderer,
|
ipc_renderer: ipc_renderer,
|
||||||
|
limits: context_limits,
|
||||||
canvas: JS::from_ref(canvas),
|
canvas: JS::from_ref(canvas),
|
||||||
last_error: Cell::new(None),
|
last_error: Cell::new(None),
|
||||||
texture_unpacking_settings: Cell::new(CONVERT_COLORSPACE),
|
texture_unpacking_settings: Cell::new(CONVERT_COLORSPACE),
|
||||||
|
@ -166,6 +169,10 @@ impl WebGLRenderingContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vertex_attrib(&self, indx: u32, x: f32, y: f32, z: f32, w: f32) {
|
fn vertex_attrib(&self, indx: u32, x: f32, y: f32, z: f32, w: f32) {
|
||||||
|
if indx > self.limits.max_vertex_attribs {
|
||||||
|
return self.webgl_error(InvalidValue);
|
||||||
|
}
|
||||||
|
|
||||||
self.ipc_renderer
|
self.ipc_renderer
|
||||||
.send(CanvasMsg::WebGL(WebGLCommand::VertexAttrib(indx, x, y, z, w)))
|
.send(CanvasMsg::WebGL(WebGLCommand::VertexAttrib(indx, x, y, z, w)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -799,6 +806,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn EnableVertexAttribArray(&self, attrib_id: u32) {
|
fn EnableVertexAttribArray(&self, attrib_id: u32) {
|
||||||
|
if attrib_id > self.limits.max_vertex_attribs {
|
||||||
|
return self.webgl_error(InvalidValue);
|
||||||
|
}
|
||||||
|
|
||||||
self.ipc_renderer
|
self.ipc_renderer
|
||||||
.send(CanvasMsg::WebGL(WebGLCommand::EnableVertexAttribArray(attrib_id)))
|
.send(CanvasMsg::WebGL(WebGLCommand::EnableVertexAttribArray(attrib_id)))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -1084,7 +1095,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
self.vertex_attrib(indx, x, 0f32, 0f32, 1f32)
|
self.vertex_attrib(indx, x, 0f32, 0f32, 1f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn VertexAttrib1fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) {
|
fn VertexAttrib1fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) {
|
||||||
if let Some(data_vec) = array_buffer_view_to_vec_checked::<f32>(data) {
|
if let Some(data_vec) = array_buffer_view_to_vec_checked::<f32>(data) {
|
||||||
|
@ -1102,7 +1112,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
self.vertex_attrib(indx, x, y, 0f32, 1f32)
|
self.vertex_attrib(indx, x, y, 0f32, 1f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn VertexAttrib2fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) {
|
fn VertexAttrib2fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) {
|
||||||
if let Some(data_vec) = array_buffer_view_to_vec_checked::<f32>(data) {
|
if let Some(data_vec) = array_buffer_view_to_vec_checked::<f32>(data) {
|
||||||
|
@ -1153,6 +1162,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||||
fn VertexAttribPointer(&self, attrib_id: u32, size: i32, data_type: u32,
|
fn VertexAttribPointer(&self, attrib_id: u32, size: i32, data_type: u32,
|
||||||
normalized: bool, stride: i32, offset: i64) {
|
normalized: bool, stride: i32, offset: i64) {
|
||||||
|
if attrib_id > self.limits.max_vertex_attribs {
|
||||||
|
return self.webgl_error(InvalidValue);
|
||||||
|
}
|
||||||
|
|
||||||
if let constants::FLOAT = data_type {
|
if let constants::FLOAT = data_type {
|
||||||
let msg = CanvasMsg::WebGL(
|
let msg = CanvasMsg::WebGL(
|
||||||
WebGLCommand::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset as u32));
|
WebGLCommand::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset as u32));
|
||||||
|
|
|
@ -101,6 +101,7 @@ impl WebGLShader {
|
||||||
&BuiltInResources::default()).unwrap();
|
&BuiltInResources::default()).unwrap();
|
||||||
match validator.compile_and_translate(&[source]) {
|
match validator.compile_and_translate(&[source]) {
|
||||||
Ok(translated_source) => {
|
Ok(translated_source) => {
|
||||||
|
debug!("Shader translated: {}", translated_source);
|
||||||
// NOTE: At this point we should be pretty sure that the compilation in the paint thread
|
// NOTE: At this point we should be pretty sure that the compilation in the paint thread
|
||||||
// will succeed.
|
// will succeed.
|
||||||
// It could be interesting to retrieve the info log from the paint thread though
|
// It could be interesting to retrieve the info log from the paint thread though
|
||||||
|
|
|
@ -14,7 +14,7 @@ use euclid::size::Size2D;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use msg::constellation_msg::{Failure, NavigationDirection, PipelineId};
|
use msg::constellation_msg::{Failure, NavigationDirection, PipelineId};
|
||||||
use msg::constellation_msg::{LoadData, SubpageId};
|
use msg::constellation_msg::{LoadData, SubpageId};
|
||||||
use offscreen_gl_context::GLContextAttributes;
|
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
||||||
use style_traits::cursor::Cursor;
|
use style_traits::cursor::Cursor;
|
||||||
use style_traits::viewport::ViewportConstraints;
|
use style_traits::viewport::ViewportConstraints;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -44,7 +44,7 @@ pub enum ScriptMsg {
|
||||||
/// WebGL uses the GPU and we don't want to give untrusted content access to the GPU.)
|
/// WebGL uses the GPU and we don't want to give untrusted content access to the GPU.)
|
||||||
CreateWebGLPaintThread(Size2D<i32>,
|
CreateWebGLPaintThread(Size2D<i32>,
|
||||||
GLContextAttributes,
|
GLContextAttributes,
|
||||||
IpcSender<Result<IpcSender<CanvasMsg>, String>>),
|
IpcSender<Result<(IpcSender<CanvasMsg>, GLLimits), String>>),
|
||||||
/// Dispatched after the DOM load event has fired on a document
|
/// Dispatched after the DOM load event has fired on a document
|
||||||
/// Causes a `load` event to be dispatched to any enclosing frame context element
|
/// Causes a `load` event to be dispatched to any enclosing frame context element
|
||||||
/// for the given pipeline.
|
/// for the given pipeline.
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
gl.vertexAttribPointer(program.aVertexPosition, itemSize, gl.FLOAT, false, 0, 0);
|
gl.vertexAttribPointer(program.aVertexPosition, itemSize, gl.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
program.aColour = gl.getAttribLocation(program, "aColour");
|
program.aColour = gl.getAttribLocation(program, "aColour");
|
||||||
|
console.log("aColour: " + program.aColour);
|
||||||
gl.enableVertexAttribArray(program.aColour);
|
gl.enableVertexAttribArray(program.aColour);
|
||||||
gl.vertexAttribPointer(program.aColour, 4, gl.FLOAT, false, 0, 24);
|
gl.vertexAttribPointer(program.aColour, 4, gl.FLOAT, false, 0, 24);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue