Skip to content
Permalink
Browse files

Implement various WebGL functions

  • Loading branch information
dzbarsky committed Dec 14, 2015
1 parent a1fb126 commit 0f4d6d58aa994b14ac70cc098099ac68b6269631
@@ -38,5 +38,5 @@ git = "https://github.com/servo/ipc-channel"
cssparser = { version = "0.4", features = [ "serde-serialization" ] }
log = "0.3"
num = "0.1.24"
gleam = "0.1"
gleam = "0.2"
euclid = {version = "0.4", features = ["plugins"]}
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use canvas_traits::{CanvasCommonMsg, CanvasMsg, CanvasWebGLMsg, FromLayoutMsg, FromPaintMsg};
use canvas_traits::{WebGLFramebufferBindingRequest, WebGLShaderParameter};
use canvas_traits::{WebGLError, WebGLFramebufferBindingRequest, WebGLParameter, WebGLResult};
use core::nonzero::NonZero;
use euclid::size::Size2D;
use gleam::gl;
@@ -57,6 +57,10 @@ impl WebGLPaintTask {
self.context_attributes(sender),
CanvasWebGLMsg::ActiveTexture(target) =>
gl::active_texture(target),
CanvasWebGLMsg::AttachShader(program_id, shader_id) =>
gl::attach_shader(program_id, shader_id),
CanvasWebGLMsg::BindAttribLocation(program_id, index, name) =>
gl::bind_attrib_location(program_id, index, &name),
CanvasWebGLMsg::BlendColor(r, g, b, a) =>
gl::blend_color(r, g, b, a),
CanvasWebGLMsg::BlendEquation(mode) =>
@@ -67,8 +71,6 @@ impl WebGLPaintTask {
gl::blend_func(src, dest),
CanvasWebGLMsg::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha) =>
gl::blend_func_separate(src_rgb, dest_rgb, src_alpha, dest_alpha),
CanvasWebGLMsg::AttachShader(program_id, shader_id) =>
gl::attach_shader(program_id, shader_id),
CanvasWebGLMsg::BufferData(buffer_type, data, usage) =>
gl::buffer_data(buffer_type, &data, usage),
CanvasWebGLMsg::BufferSubData(buffer_type, offset, data) =>
@@ -99,6 +101,8 @@ impl WebGLPaintTask {
gl::front_face(mode),
CanvasWebGLMsg::DrawArrays(mode, first, count) =>
gl::draw_arrays(mode, first, count),
CanvasWebGLMsg::DrawElements(mode, count, type_, offset) =>
gl::draw_elements(mode, count, type_, offset as u32),
CanvasWebGLMsg::Hint(name, val) =>
gl::hint(name, val),
CanvasWebGLMsg::LineWidth(width) =>
@@ -111,6 +115,12 @@ impl WebGLPaintTask {
gl::enable_vertex_attrib_array(attrib_id),
CanvasWebGLMsg::GetAttribLocation(program_id, name, chan) =>
self.attrib_location(program_id, name, chan),
CanvasWebGLMsg::GetBufferParameter(target, param_id, chan) =>
self.buffer_parameter(target, param_id, chan),
CanvasWebGLMsg::GetParameter(param_id, chan) =>
self.parameter(param_id, chan),
CanvasWebGLMsg::GetProgramParameter(program_id, param_id, chan) =>
self.program_parameter(program_id, param_id, chan),
CanvasWebGLMsg::GetShaderParameter(shader_id, param_id, chan) =>
self.shader_parameter(shader_id, param_id, chan),
CanvasWebGLMsg::GetUniformLocation(program_id, name, chan) =>
@@ -155,6 +165,8 @@ impl WebGLPaintTask {
gl::uniform_4f(uniform_id, data[0], data[1], data[2], data[3]),
CanvasWebGLMsg::UseProgram(program_id) =>
gl::use_program(program_id),
CanvasWebGLMsg::VertexAttrib(attrib_id, x, y, z, w) =>
gl::vertex_attrib_4f(attrib_id, x, y, z, w),
CanvasWebGLMsg::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset) =>
gl::vertex_attrib_pointer_f32(attrib_id, size, normalized, stride, offset as u32),
CanvasWebGLMsg::Viewport(x, y, width, height) =>
@@ -319,16 +331,173 @@ impl WebGLPaintTask {
chan.send(attrib_location).unwrap();
}

fn parameter(&self,
param_id: u32,
chan: IpcSender<WebGLResult<WebGLParameter>>) {
let result = match param_id {
gl::ACTIVE_TEXTURE |
gl::ALPHA_BITS |
gl::BLEND_DST_ALPHA |
gl::BLEND_DST_RGB |
gl::BLEND_EQUATION_ALPHA |
gl::BLEND_EQUATION_RGB |
gl::BLEND_SRC_ALPHA |
gl::BLEND_SRC_RGB |
gl::BLUE_BITS |
gl::CULL_FACE_MODE |
gl::DEPTH_BITS |
gl::DEPTH_FUNC |
gl::FRONT_FACE |
gl::GENERATE_MIPMAP_HINT |
gl::GREEN_BITS |
//gl::IMPLEMENTATION_COLOR_READ_FORMAT |
//gl::IMPLEMENTATION_COLOR_READ_TYPE |
gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS |
gl::MAX_CUBE_MAP_TEXTURE_SIZE |
//gl::MAX_FRAGMENT_UNIFORM_VECTORS |
gl::MAX_RENDERBUFFER_SIZE |
gl::MAX_TEXTURE_IMAGE_UNITS |
gl::MAX_TEXTURE_SIZE |
//gl::MAX_VARYING_VECTORS |
gl::MAX_VERTEX_ATTRIBS |
gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS |
//gl::MAX_VERTEX_UNIFORM_VECTORS |
gl::PACK_ALIGNMENT |
gl::RED_BITS |
gl::SAMPLE_BUFFERS |
gl::SAMPLES |
gl::STENCIL_BACK_FAIL |
gl::STENCIL_BACK_FUNC |
gl::STENCIL_BACK_PASS_DEPTH_FAIL |
gl::STENCIL_BACK_PASS_DEPTH_PASS |
gl::STENCIL_BACK_REF |
gl::STENCIL_BACK_VALUE_MASK |
gl::STENCIL_BACK_WRITEMASK |
gl::STENCIL_BITS |
gl::STENCIL_CLEAR_VALUE |
gl::STENCIL_FAIL |
gl::STENCIL_FUNC |
gl::STENCIL_PASS_DEPTH_FAIL |
gl::STENCIL_PASS_DEPTH_PASS |
gl::STENCIL_REF |
gl::STENCIL_VALUE_MASK |
gl::STENCIL_WRITEMASK |
gl::SUBPIXEL_BITS |
gl::UNPACK_ALIGNMENT =>
//gl::UNPACK_COLORSPACE_CONVERSION_WEBGL =>
Ok(WebGLParameter::Int(gl::get_integer_v(param_id))),

gl::BLEND |
gl::CULL_FACE |
gl::DEPTH_TEST |
gl::DEPTH_WRITEMASK |
gl::DITHER |
gl::POLYGON_OFFSET_FILL |
gl::SAMPLE_COVERAGE_INVERT |
gl::STENCIL_TEST =>
//gl::UNPACK_FLIP_Y_WEBGL |
//gl::UNPACK_PREMULTIPLY_ALPHA_WEBGL =>
Ok(WebGLParameter::Bool(gl::get_boolean_v(param_id) != 0)),

gl::DEPTH_CLEAR_VALUE |
gl::LINE_WIDTH |
gl::POLYGON_OFFSET_FACTOR |
gl::POLYGON_OFFSET_UNITS |
gl::SAMPLE_COVERAGE_VALUE =>
Ok(WebGLParameter::Float(gl::get_float_v(param_id))),

gl::VERSION => Ok(WebGLParameter::String("WebGL 1.0".to_owned())),
gl::RENDERER |
gl::VENDOR => Ok(WebGLParameter::String("Mozilla/Servo".to_owned())),
gl::SHADING_LANGUAGE_VERSION => Ok(WebGLParameter::String("WebGL GLSL ES 1.0".to_owned())),

// TODO(zbarsky, ecoal95): Implement support for the following valid parameters
// Float32Array
gl::ALIASED_LINE_WIDTH_RANGE |
gl::ALIASED_POINT_SIZE_RANGE |
//gl::BLEND_COLOR |
gl::COLOR_CLEAR_VALUE |
gl::DEPTH_RANGE |

// WebGLBuffer
gl::ARRAY_BUFFER_BINDING |
gl::ELEMENT_ARRAY_BUFFER_BINDING |

// WebGLFrameBuffer
gl::FRAMEBUFFER_BINDING |

// WebGLRenderBuffer
gl::RENDERBUFFER_BINDING |

// WebGLProgram
gl::CURRENT_PROGRAM |

// WebGLTexture
gl::TEXTURE_BINDING_2D |
gl::TEXTURE_BINDING_CUBE_MAP |

// sequence<GlBoolean>
gl::COLOR_WRITEMASK |

// Uint32Array
gl::COMPRESSED_TEXTURE_FORMATS |

// Int32Array
gl::MAX_VIEWPORT_DIMS |
gl::SCISSOR_BOX |
gl::VIEWPORT => Err(WebGLError::InvalidEnum),

// Invalid parameters
_ => Err(WebGLError::InvalidEnum)
};

chan.send(result).unwrap();
}

fn buffer_parameter(&self,
target: u32,
param_id: u32,
chan: IpcSender<WebGLResult<WebGLParameter>>) {
let result = match param_id {
gl::BUFFER_SIZE |
gl::BUFFER_USAGE =>
Ok(WebGLParameter::Int(gl::get_buffer_parameter_iv(target, param_id))),
_ => Err(WebGLError::InvalidEnum),
};

chan.send(result).unwrap();
}

fn program_parameter(&self,
program_id: u32,
param_id: u32,
chan: IpcSender<WebGLResult<WebGLParameter>>) {
let result = match param_id {
gl::DELETE_STATUS |
gl::LINK_STATUS |
gl::VALIDATE_STATUS =>
Ok(WebGLParameter::Bool(gl::get_program_iv(program_id, param_id) != 0)),
gl::ATTACHED_SHADERS |
gl::ACTIVE_ATTRIBUTES |
gl::ACTIVE_UNIFORMS =>
Ok(WebGLParameter::Int(gl::get_program_iv(program_id, param_id))),
_ => Err(WebGLError::InvalidEnum),
};

chan.send(result).unwrap();
}

fn shader_parameter(&self,
shader_id: u32,
param_id: u32,
chan: IpcSender<WebGLShaderParameter>) {
shader_id: u32,
param_id: u32,
chan: IpcSender<WebGLResult<WebGLParameter>>) {
let result = match param_id {
gl::SHADER_TYPE =>
WebGLShaderParameter::Int(gl::get_shader_iv(shader_id, param_id)),
gl::DELETE_STATUS | gl::COMPILE_STATUS =>
WebGLShaderParameter::Bool(gl::get_shader_iv(shader_id, param_id) != 0),
_ => panic!("Unexpected shader parameter type"),
Ok(WebGLParameter::Int(gl::get_shader_iv(shader_id, param_id))),
gl::DELETE_STATUS |
gl::COMPILE_STATUS =>
Ok(WebGLParameter::Bool(gl::get_shader_iv(shader_id, param_id) != 0)),
_ => Err(WebGLError::InvalidEnum),
};

chan.send(result).unwrap();
@@ -133,7 +133,8 @@ pub enum CanvasWebGLMsg {
BlendFunc(u32, u32),
BlendFuncSeparate(u32, u32, u32, u32),
AttachShader(u32, u32),
BufferData(u32, Vec<u8>, u32),
BindAttribLocation(u32, u32, String),
BufferData(u32, Vec<f32>, u32),
BufferSubData(u32, isize, Vec<u8>),
Clear(u32),
ClearColor(f32, f32, f32, f32),
@@ -165,8 +166,12 @@ pub enum CanvasWebGLMsg {
BindRenderbuffer(u32, u32),
BindTexture(u32, u32),
DrawArrays(u32, i32, i32),
DrawElements(u32, i32, u32, i64),
EnableVertexAttribArray(u32),
GetShaderParameter(u32, u32, IpcSender<WebGLShaderParameter>),
GetBufferParameter(u32, u32, IpcSender<WebGLResult<WebGLParameter>>),
GetParameter(u32, IpcSender<WebGLResult<WebGLParameter>>),
GetProgramParameter(u32, u32, IpcSender<WebGLResult<WebGLParameter>>),
GetShaderParameter(u32, u32, IpcSender<WebGLResult<WebGLParameter>>),
GetAttribLocation(u32, String, IpcSender<Option<i32>>),
GetUniformLocation(u32, String, IpcSender<Option<i32>>),
PolygonOffset(f32, f32),
@@ -176,6 +181,7 @@ pub enum CanvasWebGLMsg {
LinkProgram(u32),
Uniform4fv(i32, Vec<f32>),
UseProgram(u32),
VertexAttrib(u32, f32, f32, f32, f32),
VertexAttribPointer2f(u32, i32, bool, i32, u32),
Viewport(i32, i32, i32, i32),
TexImage2D(u32, i32, i32, i32, i32, u32, u32, Vec<u8>),
@@ -203,9 +209,11 @@ pub enum WebGLFramebufferBindingRequest {
}

#[derive(Clone, Deserialize, Serialize)]
pub enum WebGLShaderParameter {
pub enum WebGLParameter {
Int(i32),
Bool(bool),
String(String),
Float(f32),
Invalid,
}

@@ -74,7 +74,7 @@ libc = "0.2"
log = "0.3"
num = "0.1.24"
time = "0.1.17"
gleam = "0.1"
gleam = "0.2"
euclid = {version = "0.4", features = ["plugins"]}
serde = "0.6"
serde_macros = "0.6"
@@ -3,7 +3,7 @@
* 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 canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLError, WebGLResult, WebGLParameter};
use dom::bindings::codegen::Bindings::WebGLProgramBinding;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use dom::bindings::global::GlobalRef;
@@ -94,6 +94,23 @@ impl WebGLProgram {
Ok(())
}

/// glBindAttribLocation
pub fn bind_attrib_location(&self, index: u32, name: DOMString) -> WebGLResult<()> {
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 Err(WebGLError::InvalidOperation);
}

self.renderer
.send(CanvasMsg::WebGL(CanvasWebGLMsg::BindAttribLocation(self.id, index, String::from(name))))
.unwrap();
Ok(())
}

/// glGetAttribLocation
pub fn get_attrib_location(&self, name: DOMString) -> WebGLResult<Option<i32>> {
if name.len() > MAX_UNIFORM_AND_ATTRIBUTE_LEN {
@@ -129,6 +146,13 @@ impl WebGLProgram {
.unwrap();
Ok(receiver.recv().unwrap())
}

/// glGetProgramParameter
pub fn parameter(&self, param_id: u32) -> WebGLResult<WebGLParameter> {
let (sender, receiver) = ipc::channel().unwrap();
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::GetProgramParameter(self.id, param_id, sender))).unwrap();
receiver.recv().unwrap()
}
}

impl Drop for WebGLProgram {

0 comments on commit 0f4d6d5

Please sign in to comment.
You can’t perform that action at this time.