fune/servo/components/script/dom/webglprogram.rs
Emilio Cobos Álvarez 8641baaa51 servo: Merge #8291 - Add destructors to some WebGL objects, remove duplicated glutin dependency and try to enable the webgl reftests (from emilio:webgl-drop); r=jdm
The first commit allows to cleanup the gl resources of the webgl task earlier if they aren't being used.
Right now all resources were cleaned up when the context was destroyed, so I think this is
a slightly better approach.

The second commit bumps rust-offscreen-rendering-context to remove the duplicated glutin dependency.

The third one tries to reenable the webgl reftests.
Since the errored builds are deleted, It's the only way I can try to troubleshoot it.

Source-Repo: https://github.com/servo/servo
Source-Revision: 3282174a9941ec1f8d8821dfac44b850b77e7668
2015-11-02 18:23:33 +05:01

133 lines
4.6 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLError, WebGLResult};
use dom::bindings::codegen::Bindings::WebGLProgramBinding;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::utils::reflect_dom_object;
use dom::webglobject::WebGLObject;
use dom::webglrenderingcontext::MAX_UNIFORM_AND_ATTRIBUTE_LEN;
use dom::webglshader::WebGLShader;
use ipc_channel::ipc::{self, IpcSender};
use std::cell::Cell;
#[dom_struct]
pub struct WebGLProgram {
webgl_object: WebGLObject,
id: u32,
is_deleted: Cell<bool>,
fragment_shader: MutNullableHeap<JS<WebGLShader>>,
vertex_shader: MutNullableHeap<JS<WebGLShader>>,
#[ignore_heap_size_of = "Defined in ipc-channel"]
renderer: IpcSender<CanvasMsg>,
}
impl WebGLProgram {
fn new_inherited(renderer: IpcSender<CanvasMsg>, id: u32) -> WebGLProgram {
WebGLProgram {
webgl_object: WebGLObject::new_inherited(),
id: id,
is_deleted: Cell::new(false),
fragment_shader: Default::default(),
vertex_shader: Default::default(),
renderer: renderer,
}
}
pub fn maybe_new(global: GlobalRef, renderer: IpcSender<CanvasMsg>)
-> Option<Root<WebGLProgram>> {
let (sender, receiver) = ipc::channel().unwrap();
renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateProgram(sender))).unwrap();
let result = receiver.recv().unwrap();
result.map(|program_id| WebGLProgram::new(global, renderer, *program_id))
}
pub fn new(global: GlobalRef, renderer: IpcSender<CanvasMsg>, id: u32) -> Root<WebGLProgram> {
reflect_dom_object(box WebGLProgram::new_inherited(renderer, id), global, WebGLProgramBinding::Wrap)
}
}
impl WebGLProgram {
/// glDeleteProgram
pub fn delete(&self) {
if !self.is_deleted.get() {
self.is_deleted.set(true);
let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteProgram(self.id)));
}
}
/// glLinkProgram
pub fn link(&self) {
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::LinkProgram(self.id))).unwrap();
}
/// glUseProgram
pub fn use_program(&self) {
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::UseProgram(self.id))).unwrap();
}
/// glAttachShader
pub fn attach_shader(&self, shader: &WebGLShader) -> WebGLResult<()> {
let shader_slot = match shader.gl_type() {
constants::FRAGMENT_SHADER => &self.fragment_shader,
constants::VERTEX_SHADER => &self.vertex_shader,
_ => return Err(WebGLError::InvalidOperation),
};
// TODO(ecoal95): Differentiate between same shader already assigned and other previous
// shader.
if shader_slot.get().is_some() {
return Err(WebGLError::InvalidOperation);
}
shader_slot.set(Some(shader));
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::AttachShader(self.id, shader.id()))).unwrap();
Ok(())
}
/// glGetAttribLocation
pub fn get_attrib_location(&self, name: String) -> WebGLResult<Option<i32>> {
if name.len() > MAX_UNIFORM_AND_ATTRIBUTE_LEN {
return Err(WebGLError::InvalidValue);
}
// Check if the name is reserved
if name.starts_with("webgl") || name.starts_with("_webgl_") {
return Ok(None);
}
let (sender, receiver) = ipc::channel().unwrap();
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::GetAttribLocation(self.id, name, sender))).unwrap();
Ok(receiver.recv().unwrap())
}
/// glGetUniformLocation
pub fn get_uniform_location(&self, name: String) -> WebGLResult<Option<i32>> {
if name.len() > MAX_UNIFORM_AND_ATTRIBUTE_LEN {
return Err(WebGLError::InvalidValue);
}
// Check if the name is reserved
if name.starts_with("webgl") || name.starts_with("_webgl_") {
return Ok(None);
}
let (sender, receiver) = ipc::channel().unwrap();
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::GetUniformLocation(self.id, name, sender))).unwrap();
Ok(receiver.recv().unwrap())
}
}
impl Drop for WebGLProgram {
fn drop(&mut self) {
self.delete();
}
}