mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Store active uniforms on the DOM side
This commit is contained in:
parent
a5b800970a
commit
cbac5d05be
5 changed files with 79 additions and 55 deletions
|
@ -736,8 +736,6 @@ impl WebGLImpl {
|
||||||
ctx.gl().stencil_op(fail, zfail, zpass),
|
ctx.gl().stencil_op(fail, zfail, zpass),
|
||||||
WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass) =>
|
WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass) =>
|
||||||
ctx.gl().stencil_op_separate(face, fail, zfail, zpass),
|
ctx.gl().stencil_op_separate(face, fail, zfail, zpass),
|
||||||
WebGLCommand::GetActiveUniform(program_id, index, ref chan) =>
|
|
||||||
Self::active_uniform(ctx.gl(), program_id, index, chan),
|
|
||||||
WebGLCommand::GetRenderbufferParameter(target, pname, ref chan) =>
|
WebGLCommand::GetRenderbufferParameter(target, pname, ref chan) =>
|
||||||
Self::get_renderbuffer_parameter(ctx.gl(), target, pname, chan),
|
Self::get_renderbuffer_parameter(ctx.gl(), target, pname, chan),
|
||||||
WebGLCommand::GetFramebufferAttachmentParameter(target, attachment, pname, ref chan) =>
|
WebGLCommand::GetFramebufferAttachmentParameter(target, attachment, pname, ref chan) =>
|
||||||
|
@ -1001,6 +999,7 @@ impl WebGLImpl {
|
||||||
return ProgramLinkInfo {
|
return ProgramLinkInfo {
|
||||||
linked: false,
|
linked: false,
|
||||||
active_attribs: vec![].into(),
|
active_attribs: vec![].into(),
|
||||||
|
active_uniforms: vec![].into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1009,6 +1008,8 @@ impl WebGLImpl {
|
||||||
gl.get_program_iv(program.get(), gl::ACTIVE_ATTRIBUTES, &mut num_active_attribs);
|
gl.get_program_iv(program.get(), gl::ACTIVE_ATTRIBUTES, &mut num_active_attribs);
|
||||||
}
|
}
|
||||||
let active_attribs = (0..num_active_attribs[0] as u32).map(|i| {
|
let active_attribs = (0..num_active_attribs[0] as u32).map(|i| {
|
||||||
|
// FIXME(nox): This allocates strings sometimes for nothing
|
||||||
|
// and the gleam method keeps getting ACTIVE_ATTRIBUTE_MAX_LENGTH.
|
||||||
let (size, type_, name) = gl.get_active_attrib(program.get(), i);
|
let (size, type_, name) = gl.get_active_attrib(program.get(), i);
|
||||||
let location = if name.starts_with("gl_") {
|
let location = if name.starts_with("gl_") {
|
||||||
-1
|
-1
|
||||||
|
@ -1023,9 +1024,25 @@ impl WebGLImpl {
|
||||||
}
|
}
|
||||||
}).collect::<Vec<_>>().into();
|
}).collect::<Vec<_>>().into();
|
||||||
|
|
||||||
|
let mut num_active_uniforms = [0];
|
||||||
|
unsafe {
|
||||||
|
gl.get_program_iv(program.get(), gl::ACTIVE_UNIFORMS, &mut num_active_uniforms);
|
||||||
|
}
|
||||||
|
let active_uniforms = (0..num_active_uniforms[0] as u32).map(|i| {
|
||||||
|
// FIXME(nox): This allocates strings sometimes for nothing
|
||||||
|
// and the gleam method keeps getting ACTIVE_UNIFORM_MAX_LENGTH.
|
||||||
|
let (size, type_, name) = gl.get_active_uniform(program.get(), i);
|
||||||
|
ActiveUniformInfo {
|
||||||
|
name: from_name_in_compiled_shader(&name),
|
||||||
|
size,
|
||||||
|
type_,
|
||||||
|
}
|
||||||
|
}).collect::<Vec<_>>().into();
|
||||||
|
|
||||||
ProgramLinkInfo {
|
ProgramLinkInfo {
|
||||||
linked: true,
|
linked: true,
|
||||||
active_attribs,
|
active_attribs,
|
||||||
|
active_uniforms,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1043,23 +1060,6 @@ impl WebGLImpl {
|
||||||
chan.send(result.into()).unwrap()
|
chan.send(result.into()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
fn active_uniform(gl: &gl::Gl,
|
|
||||||
program_id: WebGLProgramId,
|
|
||||||
index: u32,
|
|
||||||
chan: &WebGLSender<WebGLResult<(i32, u32, String)>>) {
|
|
||||||
let mut max = [0];
|
|
||||||
unsafe {
|
|
||||||
gl.get_program_iv(program_id.get(), gl::ACTIVE_UNIFORMS, &mut max);
|
|
||||||
}
|
|
||||||
let result = if index >= max[0] as u32 {
|
|
||||||
Err(WebGLError::InvalidValue)
|
|
||||||
} else {
|
|
||||||
Ok(gl.get_active_uniform(program_id.get(), index))
|
|
||||||
};
|
|
||||||
chan.send(result).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn finish(gl: &gl::Gl, chan: &WebGLSender<()>) {
|
fn finish(gl: &gl::Gl, chan: &WebGLSender<()>) {
|
||||||
gl.finish();
|
gl.finish();
|
||||||
chan.send(()).unwrap();
|
chan.send(()).unwrap();
|
||||||
|
|
|
@ -207,7 +207,6 @@ pub enum WebGLCommand {
|
||||||
FramebufferTexture2D(u32, u32, u32, Option<WebGLTextureId>, i32),
|
FramebufferTexture2D(u32, u32, u32, Option<WebGLTextureId>, i32),
|
||||||
GetExtensions(WebGLSender<String>),
|
GetExtensions(WebGLSender<String>),
|
||||||
GetShaderPrecisionFormat(u32, u32, WebGLSender<(i32, i32, i32)>),
|
GetShaderPrecisionFormat(u32, u32, WebGLSender<(i32, i32, i32)>),
|
||||||
GetActiveUniform(WebGLProgramId, u32, WebGLSender<WebGLResult<(i32, u32, String)>>),
|
|
||||||
GetUniformLocation(WebGLProgramId, String, WebGLSender<Option<i32>>),
|
GetUniformLocation(WebGLProgramId, String, WebGLSender<Option<i32>>),
|
||||||
GetShaderInfoLog(WebGLShaderId, WebGLSender<String>),
|
GetShaderInfoLog(WebGLShaderId, WebGLSender<String>),
|
||||||
GetProgramInfoLog(WebGLProgramId, WebGLSender<String>),
|
GetProgramInfoLog(WebGLProgramId, WebGLSender<String>),
|
||||||
|
@ -424,6 +423,8 @@ pub struct ProgramLinkInfo {
|
||||||
pub linked: bool,
|
pub linked: bool,
|
||||||
/// The list of active attributes.
|
/// The list of active attributes.
|
||||||
pub active_attribs: Box<[ActiveAttribInfo]>,
|
pub active_attribs: Box<[ActiveAttribInfo]>,
|
||||||
|
/// The list of active uniforms.
|
||||||
|
pub active_uniforms: Box<[ActiveUniformInfo]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Description of a single active attribute.
|
/// Description of a single active attribute.
|
||||||
|
@ -439,6 +440,17 @@ pub struct ActiveAttribInfo {
|
||||||
pub location: i32,
|
pub location: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Description of a single active uniform.
|
||||||
|
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
|
||||||
|
pub struct ActiveUniformInfo {
|
||||||
|
/// The name of the uniform.
|
||||||
|
pub name: String,
|
||||||
|
/// The size of the uniform.
|
||||||
|
pub size: i32,
|
||||||
|
/// The type of the uniform.
|
||||||
|
pub type_: u32,
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! parameters {
|
macro_rules! parameters {
|
||||||
($name:ident { $(
|
($name:ident { $(
|
||||||
$variant:ident($kind:ident { $(
|
$variant:ident($kind:ident { $(
|
||||||
|
|
|
@ -32,10 +32,11 @@
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use canvas_traits::canvas::{CanvasGradientStop, CanvasId, LinearGradientStyle, RadialGradientStyle};
|
use canvas_traits::canvas::{CanvasGradientStop, CanvasId, LinearGradientStyle, RadialGradientStyle};
|
||||||
use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle};
|
use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle};
|
||||||
use canvas_traits::webgl::{ActiveAttribInfo, WebGLBufferId, WebGLFramebufferId, WebGLProgramId, WebGLRenderbufferId};
|
use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, WebGLBufferId, WebGLChan};
|
||||||
use canvas_traits::webgl::{WebGLChan, WebGLContextShareMode, WebGLError, WebGLPipeline, WebGLMsgSender};
|
use canvas_traits::webgl::{WebGLContextShareMode, WebGLError, WebGLFramebufferId, WebGLMsgSender};
|
||||||
use canvas_traits::webgl::{WebGLReceiver, WebGLSender, WebGLShaderId, WebGLTextureId, WebGLVertexArrayId};
|
use canvas_traits::webgl::{WebGLPipeline, WebGLProgramId, WebGLReceiver, WebGLRenderbufferId};
|
||||||
use canvas_traits::webgl::{WebGLSLVersion, WebGLVersion};
|
use canvas_traits::webgl::{WebGLSLVersion, WebGLSender, WebGLShaderId, WebGLTextureId};
|
||||||
|
use canvas_traits::webgl::{WebGLVersion, WebGLVertexArrayId};
|
||||||
use cssparser::RGBA;
|
use cssparser::RGBA;
|
||||||
use devtools_traits::{CSSError, TimelineMarkerType, WorkerId};
|
use devtools_traits::{CSSError, TimelineMarkerType, WorkerId};
|
||||||
use dom::abstractworker::SharedRt;
|
use dom::abstractworker::SharedRt;
|
||||||
|
@ -343,6 +344,7 @@ unsafe impl<A: JSTraceable, B: JSTraceable, C: JSTraceable> JSTraceable for (A,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_no_jsmanaged_fields!(ActiveAttribInfo);
|
unsafe_no_jsmanaged_fields!(ActiveAttribInfo);
|
||||||
|
unsafe_no_jsmanaged_fields!(ActiveUniformInfo);
|
||||||
unsafe_no_jsmanaged_fields!(bool, f32, f64, String, AtomicBool, AtomicUsize, Uuid, char);
|
unsafe_no_jsmanaged_fields!(bool, f32, f64, String, AtomicBool, AtomicUsize, Uuid, char);
|
||||||
unsafe_no_jsmanaged_fields!(usize, u8, u16, u32, u64);
|
unsafe_no_jsmanaged_fields!(usize, u8, u16, u32, u64);
|
||||||
unsafe_no_jsmanaged_fields!(isize, i8, i16, i32, i64);
|
unsafe_no_jsmanaged_fields!(isize, i8, i16, i32, i64);
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
// 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 canvas_traits::webgl::{ActiveAttribInfo, WebGLCommand, WebGLError, WebGLMsgSender};
|
use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, WebGLCommand, WebGLError, WebGLMsgSender};
|
||||||
use canvas_traits::webgl::{WebGLProgramId, WebGLResult, from_name_in_compiled_shader};
|
use canvas_traits::webgl::{WebGLProgramId, WebGLResult, to_name_in_compiled_shader, webgl_channel};
|
||||||
use canvas_traits::webgl::{to_name_in_compiled_shader, webgl_channel};
|
|
||||||
use dom::bindings::cell::DomRefCell;
|
use dom::bindings::cell::DomRefCell;
|
||||||
use dom::bindings::codegen::Bindings::WebGLProgramBinding;
|
use dom::bindings::codegen::Bindings::WebGLProgramBinding;
|
||||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||||
|
@ -33,6 +32,7 @@ pub struct WebGLProgram {
|
||||||
#[ignore_malloc_size_of = "Defined in ipc-channel"]
|
#[ignore_malloc_size_of = "Defined in ipc-channel"]
|
||||||
renderer: WebGLMsgSender,
|
renderer: WebGLMsgSender,
|
||||||
active_attribs: DomRefCell<Box<[ActiveAttribInfo]>>,
|
active_attribs: DomRefCell<Box<[ActiveAttribInfo]>>,
|
||||||
|
active_uniforms: DomRefCell<Box<[ActiveUniformInfo]>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebGLProgram {
|
impl WebGLProgram {
|
||||||
|
@ -49,6 +49,7 @@ impl WebGLProgram {
|
||||||
vertex_shader: Default::default(),
|
vertex_shader: Default::default(),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
active_attribs: DomRefCell::new(vec![].into()),
|
active_attribs: DomRefCell::new(vec![].into()),
|
||||||
|
active_uniforms: DomRefCell::new(vec![].into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,8 +124,9 @@ impl WebGLProgram {
|
||||||
self.renderer.send(WebGLCommand::LinkProgram(self.id, sender)).unwrap();
|
self.renderer.send(WebGLCommand::LinkProgram(self.id, sender)).unwrap();
|
||||||
let link_info = receiver.recv().unwrap();
|
let link_info = receiver.recv().unwrap();
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.31
|
{
|
||||||
let mut used_locs = FnvHashSet::default();
|
let mut used_locs = FnvHashSet::default();
|
||||||
|
let mut used_names = FnvHashSet::default();
|
||||||
for active_attrib in &*link_info.active_attribs {
|
for active_attrib in &*link_info.active_attribs {
|
||||||
if active_attrib.location == -1 {
|
if active_attrib.location == -1 {
|
||||||
continue;
|
continue;
|
||||||
|
@ -135,15 +137,25 @@ impl WebGLProgram {
|
||||||
constants::FLOAT_MAT4 => 4,
|
constants::FLOAT_MAT4 => 4,
|
||||||
_ => 1,
|
_ => 1,
|
||||||
};
|
};
|
||||||
|
assert!(used_names.insert(&*active_attrib.name));
|
||||||
for column in 0..columns {
|
for column in 0..columns {
|
||||||
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.31
|
||||||
if !used_locs.insert(active_attrib.location as u32 + column) {
|
if !used_locs.insert(active_attrib.location as u32 + column) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for active_uniform in &*link_info.active_uniforms {
|
||||||
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.41
|
||||||
|
if !used_names.insert(&*active_uniform.name) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.linked.set(link_info.linked);
|
self.linked.set(link_info.linked);
|
||||||
*self.active_attribs.borrow_mut() = link_info.active_attribs;
|
*self.active_attribs.borrow_mut() = link_info.active_attribs;
|
||||||
|
*self.active_uniforms.borrow_mut() = link_info.active_uniforms;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,6 +163,10 @@ impl WebGLProgram {
|
||||||
Ref::map(self.active_attribs.borrow(), |attribs| &**attribs)
|
Ref::map(self.active_attribs.borrow(), |attribs| &**attribs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn active_uniforms(&self) -> Ref<[ActiveUniformInfo]> {
|
||||||
|
Ref::map(self.active_uniforms.borrow(), |uniforms| &**uniforms)
|
||||||
|
}
|
||||||
|
|
||||||
/// glValidateProgram
|
/// glValidateProgram
|
||||||
pub fn validate(&self) -> WebGLResult<()> {
|
pub fn validate(&self) -> WebGLResult<()> {
|
||||||
if self.is_deleted() {
|
if self.is_deleted() {
|
||||||
|
@ -244,15 +260,14 @@ impl WebGLProgram {
|
||||||
if self.is_deleted() {
|
if self.is_deleted() {
|
||||||
return Err(WebGLError::InvalidValue);
|
return Err(WebGLError::InvalidValue);
|
||||||
}
|
}
|
||||||
let (sender, receiver) = webgl_channel().unwrap();
|
let uniforms = self.active_uniforms.borrow();
|
||||||
self.renderer
|
let data = uniforms.get(index as usize).ok_or(WebGLError::InvalidValue)?;
|
||||||
.send(WebGLCommand::GetActiveUniform(self.id, index, sender))
|
Ok(WebGLActiveInfo::new(
|
||||||
.unwrap();
|
self.global().as_window(),
|
||||||
|
data.size,
|
||||||
receiver.recv().unwrap().map(|(size, ty, name)| {
|
data.type_,
|
||||||
let name = DOMString::from(from_name_in_compiled_shader(&name));
|
data.name.clone().into(),
|
||||||
WebGLActiveInfo::new(self.global().as_window(), size, ty, name)
|
))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// glGetActiveAttrib
|
/// glGetActiveAttrib
|
||||||
|
|
|
@ -2693,12 +2693,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
Int32Value(program.attached_shaders().map(|shaders| shaders.len() as i32).unwrap_or(0))
|
Int32Value(program.attached_shaders().map(|shaders| shaders.len() as i32).unwrap_or(0))
|
||||||
}
|
}
|
||||||
constants::ACTIVE_ATTRIBUTES => Int32Value(program.active_attribs().len() as i32),
|
constants::ACTIVE_ATTRIBUTES => Int32Value(program.active_attribs().len() as i32),
|
||||||
constants::ACTIVE_UNIFORMS => {
|
constants::ACTIVE_UNIFORMS => Int32Value(program.active_uniforms().len() as i32),
|
||||||
// FIXME(nox): We'll need to cache that on the DOM side at some point.
|
|
||||||
let (sender, receiver) = webgl_channel().unwrap();
|
|
||||||
self.send_command(WebGLCommand::GetProgramActiveUniforms(program.id(), sender));
|
|
||||||
Int32Value(receiver.recv().unwrap())
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
self.webgl_error(InvalidEnum);
|
self.webgl_error(InvalidEnum);
|
||||||
NullValue()
|
NullValue()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue