webgl: Make bind* calls more spec-compliant

This commit is contained in:
ecoal95 2015-06-15 00:22:15 +02:00
parent b1765c6882
commit 42bd43a696
8 changed files with 72 additions and 37 deletions

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use canvas_traits::{CanvasMsg, CanvasWebGLMsg, CanvasCommonMsg}; use canvas_traits::{CanvasMsg, CanvasWebGLMsg, CanvasCommonMsg, WebGLShaderParameter, WebGLFramebufferBindingRequest};
use euclid::size::Size2D; use euclid::size::Size2D;
use core::nonzero::NonZero; use core::nonzero::NonZero;
use gleam::gl; use gleam::gl;
@ -109,8 +109,8 @@ impl WebGLPaintTask {
self.delete_shader(id), self.delete_shader(id),
CanvasWebGLMsg::BindBuffer(target, id) => CanvasWebGLMsg::BindBuffer(target, id) =>
self.bind_buffer(target, id), self.bind_buffer(target, id),
CanvasWebGLMsg::BindFramebuffer(target, id) => CanvasWebGLMsg::BindFramebuffer(target, request) =>
self.bind_framebuffer(target, id), self.bind_framebuffer(target, request),
CanvasWebGLMsg::BindRenderbuffer(target, id) => CanvasWebGLMsg::BindRenderbuffer(target, id) =>
self.bind_renderbuffer(target, id), self.bind_renderbuffer(target, id),
CanvasWebGLMsg::BindTexture(target, id) => CanvasWebGLMsg::BindTexture(target, id) =>
@ -329,7 +329,13 @@ impl WebGLPaintTask {
} }
#[inline] #[inline]
fn bind_framebuffer(&self, target: u32, id: u32) { 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); gl::bind_framebuffer(target, id);
} }

View file

@ -37,6 +37,14 @@ pub enum CanvasMsg {
WebGL(CanvasWebGLMsg), WebGL(CanvasWebGLMsg),
} }
#[derive(Clone)]
pub enum CanvasCommonMsg {
Close,
Recreate(Size2D<i32>),
SendPixelContents(Sender<Vec<u8>>),
SendNativeSurface(Sender<NativeSurface>),
}
#[derive(Clone)] #[derive(Clone)]
pub enum Canvas2dMsg { pub enum Canvas2dMsg {
Arc(Point2D<f32>, f32, f32, f32, bool), Arc(Point2D<f32>, f32, f32, f32, bool),
@ -102,7 +110,7 @@ pub enum CanvasWebGLMsg {
DeleteProgram(u32), DeleteProgram(u32),
DeleteShader(u32), DeleteShader(u32),
BindBuffer(u32, u32), BindBuffer(u32, u32),
BindFramebuffer(u32, u32), BindFramebuffer(u32, WebGLFramebufferBindingRequest),
BindRenderbuffer(u32, u32), BindRenderbuffer(u32, u32),
BindTexture(u32, u32), BindTexture(u32, u32),
DrawArrays(u32, i32, i32), DrawArrays(u32, i32, i32),
@ -132,6 +140,12 @@ pub enum WebGLError {
pub type WebGLResult<T> = Result<T, WebGLError>; pub type WebGLResult<T> = Result<T, WebGLError>;
#[derive(Clone)]
pub enum WebGLFramebufferBindingRequest {
Explicit(u32),
Default,
}
#[derive(Clone)] #[derive(Clone)]
pub enum WebGLShaderParameter { pub enum WebGLShaderParameter {
Int(i32), Int(i32),
@ -139,15 +153,6 @@ pub enum WebGLShaderParameter {
Invalid, Invalid,
} }
#[derive(Clone)]
pub enum CanvasCommonMsg {
Close,
Recreate(Size2D<i32>),
SendPixelContents(Sender<Vec<u8>>),
SendNativeSurface(Sender<NativeSurface>),
}
#[derive(Clone)] #[derive(Clone)]
pub struct CanvasGradientStop { pub struct CanvasGradientStop {
pub offset: f64, pub offset: f64,

View file

@ -5,7 +5,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
use dom::bindings::codegen::Bindings::WebGLBufferBinding; use dom::bindings::codegen::Bindings::WebGLBufferBinding;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{Temporary, JSRef}; use dom::bindings::js::Root;
use dom::bindings::utils::reflect_dom_object; use dom::bindings::utils::reflect_dom_object;
use dom::webglobject::WebGLObject; use dom::webglobject::WebGLObject;
@ -44,9 +44,9 @@ impl WebGLBuffer {
} }
pub trait WebGLBufferHelpers { pub trait WebGLBufferHelpers {
fn id(&self) -> u32; fn id(self) -> u32;
fn bind(&self, target: u32); fn bind(self, target: u32);
fn delete(&self); fn delete(self);
} }
impl<'a> WebGLBufferHelpers for &'a WebGLBuffer { impl<'a> WebGLBufferHelpers for &'a WebGLBuffer {

View file

@ -9,7 +9,7 @@ use dom::bindings::js::Root;
use dom::bindings::utils::reflect_dom_object; use dom::bindings::utils::reflect_dom_object;
use dom::webglobject::WebGLObject; use dom::webglobject::WebGLObject;
use canvas_traits::{CanvasMsg, CanvasWebGLMsg}; use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLFramebufferBindingRequest};
use std::sync::mpsc::{channel, Sender}; use std::sync::mpsc::{channel, Sender};
use std::cell::Cell; use std::cell::Cell;
@ -49,13 +49,15 @@ pub trait WebGLFramebufferHelpers {
fn delete(self); fn delete(self);
} }
impl<'a> WebGLFramebufferHelpers for JSRef<'a, WebGLFramebuffer> { impl<'a> WebGLFramebufferHelpers for &'a WebGLFramebuffer {
fn id(self) -> u32 { fn id(self) -> u32 {
self.id self.id
} }
fn bind(self, target: u32) { fn bind(self, target: u32) {
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::BindFramebuffer(target, self.id))).unwrap(); self.renderer.send(
CanvasMsg::WebGL(
CanvasWebGLMsg::BindFramebuffer(target, WebGLFramebufferBindingRequest::Explicit(self.id)))).unwrap();
} }
fn delete(self) { fn delete(self) {

View file

@ -5,9 +5,17 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
use dom::bindings::codegen::Bindings::WebGLProgramBinding; use dom::bindings::codegen::Bindings::WebGLProgramBinding;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root; use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::utils::reflect_dom_object; use dom::bindings::utils::reflect_dom_object;
use dom::webglobject::WebGLObject; use dom::webglobject::WebGLObject;
use dom::webglshader::{WebGLShader, WebGLShaderHelpers};
use dom::webglrenderingcontext::MAX_UNIFORM_AND_ATTRIBUTE_LEN;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLResult, WebGLError};
use std::sync::mpsc::{channel, Sender};
use std::cell::Cell;
#[dom_struct] #[dom_struct]
pub struct WebGLProgram { pub struct WebGLProgram {
@ -47,7 +55,7 @@ pub trait WebGLProgramHelpers {
fn delete(self); fn delete(self);
fn link(self); fn link(self);
fn use_program(self); fn use_program(self);
fn attach_shader(self, shader: JSRef<WebGLShader>) -> WebGLResult<()>; fn attach_shader(self, shader: &WebGLShader) -> WebGLResult<()>;
fn get_attrib_location(self, name: String) -> WebGLResult<Option<i32>>; fn get_attrib_location(self, name: String) -> WebGLResult<Option<i32>>;
fn get_uniform_location(self, name: String) -> WebGLResult<Option<i32>>; fn get_uniform_location(self, name: String) -> WebGLResult<Option<i32>>;
} }
@ -72,7 +80,7 @@ impl<'a> WebGLProgramHelpers for &'a WebGLProgram {
} }
/// glAttachShader /// glAttachShader
fn attach_shader(self, shader: &'a WebGLShader) -> WebGLResult<()> { fn attach_shader(self, shader: &WebGLShader) -> WebGLResult<()> {
let shader_slot = match shader.gl_type() { let shader_slot = match shader.gl_type() {
constants::FRAGMENT_SHADER => &self.fragment_shader, constants::FRAGMENT_SHADER => &self.fragment_shader,
constants::VERTEX_SHADER => &self.vertex_shader, constants::VERTEX_SHADER => &self.vertex_shader,
@ -85,7 +93,7 @@ impl<'a> WebGLProgramHelpers for &'a WebGLProgram {
return Err(WebGLError::InvalidOperation); return Err(WebGLError::InvalidOperation);
} }
shader_slot.set(Some(JS::from_rooted(shader))); shader_slot.set(Some(JS::from_ref(shader)));
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::AttachShader(self.id, shader.id()))).unwrap(); self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::AttachShader(self.id, shader.id()))).unwrap();

View file

@ -3,10 +3,13 @@
* 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 canvas::webgl_paint_task::WebGLPaintTask; use canvas::webgl_paint_task::WebGLPaintTask;
use canvas_traits::{CanvasMsg, CanvasWebGLMsg, CanvasCommonMsg}; use canvas_traits::
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding; {CanvasMsg, CanvasWebGLMsg, CanvasCommonMsg, WebGLError,
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{ WebGLShaderParameter, WebGLFramebufferBindingRequest};
WebGLContextAttributes, WebGLRenderingContextMethods, WebGLRenderingContextConstants}; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::
{self, WebGLContextAttributes, WebGLRenderingContextMethods};
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, LayoutJS, Root}; use dom::bindings::js::{JS, LayoutJS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
@ -22,7 +25,7 @@ use dom::webgluniformlocation::{WebGLUniformLocation, WebGLUniformLocationHelper
use euclid::size::Size2D; use euclid::size::Size2D;
use js::jsapi::{JSContext, JSObject, RootedValue}; use js::jsapi::{JSContext, JSObject, RootedValue};
use js::jsapi::{JS_GetFloat32ArrayData, JS_GetObjectAsArrayBufferView}; use js::jsapi::{JS_GetFloat32ArrayData, JS_GetObjectAsArrayBufferView};
use js::jsval::{JSVal, UndefinedValue, NullValue, Int32Value}; use js::jsval::{JSVal, UndefinedValue, NullValue, Int32Value, BooleanValue};
use std::mem; use std::mem;
use std::ptr; use std::ptr;
use std::slice; use std::slice;
@ -116,10 +119,10 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext {
// TODO(ecoal95): Implement the missing parameters from the spec // TODO(ecoal95): Implement the missing parameters from the spec
let mut rval = RootedValue::new(cx, UndefinedValue()); let mut rval = RootedValue::new(cx, UndefinedValue());
match parameter { match parameter {
WebGLRenderingContextConstants::VERSION => constants::VERSION =>
"WebGL 1.0".to_jsval(cx, rval.handle_mut()), "WebGL 1.0".to_jsval(cx, rval.handle_mut()),
WebGLRenderingContextConstants::RENDERER | constants::RENDERER |
WebGLRenderingContextConstants::VENDOR => constants::VENDOR =>
"Mozilla/Servo".to_jsval(cx, rval.handle_mut()), "Mozilla/Servo".to_jsval(cx, rval.handle_mut()),
_ => rval.ptr = NullValue(), _ => rval.ptr = NullValue(),
} }
@ -199,6 +202,9 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext {
fn BindBuffer(self, target: u32, buffer: Option<&WebGLBuffer>) { fn BindBuffer(self, target: u32, buffer: Option<&WebGLBuffer>) {
if let Some(buffer) = buffer { if let Some(buffer) = buffer {
buffer.bind(target) buffer.bind(target)
} else {
// Unbind the current buffer
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::BindBuffer(target, 0))).unwrap()
} }
} }
@ -206,6 +212,11 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext {
fn BindFramebuffer(self, target: u32, framebuffer: Option<&WebGLFramebuffer>) { fn BindFramebuffer(self, target: u32, framebuffer: Option<&WebGLFramebuffer>) {
if let Some(framebuffer) = framebuffer { if let Some(framebuffer) = framebuffer {
framebuffer.bind(target) framebuffer.bind(target)
} else {
// Bind the default framebuffer
self.renderer.send(
CanvasMsg::WebGL(
CanvasWebGLMsg::BindFramebuffer(target, WebGLFramebufferBindingRequest::Default))).unwrap()
} }
} }
@ -213,6 +224,9 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext {
fn BindRenderbuffer(self, target: u32, renderbuffer: Option<&WebGLRenderbuffer>) { fn BindRenderbuffer(self, target: u32, renderbuffer: Option<&WebGLRenderbuffer>) {
if let Some(renderbuffer) = renderbuffer { if let Some(renderbuffer) = renderbuffer {
renderbuffer.bind(target) renderbuffer.bind(target)
} else {
// Unbind the currently bound renderbuffer
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::BindRenderbuffer(target, 0))).unwrap()
} }
} }
@ -225,7 +239,7 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn BufferData(self, cx: *mut JSContext, target: u32, data: Option<*mut JSObject>, usage: u32) { fn BufferData(self, _cx: *mut JSContext, target: u32, data: Option<*mut JSObject>, usage: u32) {
let data = match data { let data = match data {
Some(data) => data, Some(data) => data,
None => return, None => return,
@ -447,7 +461,7 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext {
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) {
match data_type { match data_type {
WebGLRenderingContextConstants::FLOAT => { constants::FLOAT => {
let msg = CanvasMsg::WebGL( let msg = CanvasMsg::WebGL(
CanvasWebGLMsg::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset)); CanvasWebGLMsg::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset));
self.renderer.send(msg).unwrap() self.renderer.send(msg).unwrap()

View file

@ -69,7 +69,7 @@ pub trait WebGLShaderHelpers {
fn set_source(self, src: String); fn set_source(self, src: String);
} }
impl<'a> WebGLShaderHelpers for JSRef<'a, WebGLShader> { impl<'a> WebGLShaderHelpers for &'a WebGLShader {
fn id(self) -> u32 { fn id(self) -> u32 {
self.id self.id
} }

View file

@ -50,7 +50,7 @@ pub trait WebGLTextureHelpers {
} }
impl<'a> WebGLTextureHelpers for &'a WebGLTexture { impl<'a> WebGLTextureHelpers for &'a WebGLTexture {
fn id(&self) -> u32 { fn id(self) -> u32 {
self.id self.id
} }