Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for some more WebGL2 renderbuffer functions #25904

Merged
merged 2 commits into from Mar 13, 2020
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

Add support for some more WebGL2 renderbuffer functions

Adds support for the following WebGL2 calls:

- `RenderbufferStorageMultisample`
- `GetInternalFormativ`

See: https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.5
  • Loading branch information
mmatyas authored and jdm committed Mar 13, 2020
commit 5eaa9ef8cb552063df2645847a4ab3793c3ebcd6
@@ -13,6 +13,7 @@ use canvas_traits::webgl::DOMToTextureCommand;
use canvas_traits::webgl::GLContextAttributes;
use canvas_traits::webgl::GLLimits;
use canvas_traits::webgl::GlType;
use canvas_traits::webgl::InternalFormatIntVec;
use canvas_traits::webgl::ProgramLinkInfo;
use canvas_traits::webgl::SwapChainId;
use canvas_traits::webgl::TexDataType;
@@ -1211,6 +1212,13 @@ impl WebGLImpl {
WebGLCommand::RenderbufferStorage(target, format, width, height) => {
gl.renderbuffer_storage(target, format, width, height)
},
WebGLCommand::RenderbufferStorageMultisample(
target,
samples,
format,
width,
height,
) => gl.renderbuffer_storage_multisample(target, samples, format, width, height),
WebGLCommand::SampleCoverage(value, invert) => gl.sample_coverage(value, invert),
WebGLCommand::Scissor(x, y, width, height) => {
// FIXME(nox): Kinda unfortunate that some u32 values could
@@ -1666,6 +1674,29 @@ impl WebGLImpl {
.send(gl.get_tex_parameter_iv(target, param as u32))
.unwrap();
},
WebGLCommand::GetInternalFormatIntVec(target, internal_format, param, ref sender) => {
match param {
InternalFormatIntVec::Samples => {
let mut count = [0; 1];
gl.get_internal_format_iv(
target,
internal_format,
gl::NUM_SAMPLE_COUNTS,
&mut count,
);
assert!(count[0] >= 0);

let mut values = vec![0; count[0] as usize];
gl.get_internal_format_iv(
target,
internal_format,
param as u32,
&mut values,
);
sender.send(values).unwrap()
},
}
},
WebGLCommand::TexParameteri(target, param, value) => {
gl.tex_parameter_i(target, param as u32, value)
},
@@ -330,6 +330,7 @@ pub enum WebGLCommand {
TransformFeedbackVaryings(WebGLProgramId, Vec<String>, u32),
PolygonOffset(f32, f32),
RenderbufferStorage(u32, u32, i32, i32),
RenderbufferStorageMultisample(u32, i32, u32, i32, i32),
ReadPixels(Rect<u32>, u32, u32, IpcBytesSender),
ReadPixelsPP(Rect<i32>, u32, u32, usize),
SampleCoverage(f32, bool),
@@ -458,6 +459,7 @@ pub enum WebGLCommand {
GetCurrentVertexAttrib(u32, WebGLSender<[f32; 4]>),
GetTexParameterFloat(u32, TexParameterFloat, WebGLSender<f32>),
GetTexParameterInt(u32, TexParameterInt, WebGLSender<i32>),
GetInternalFormatIntVec(u32, u32, InternalFormatIntVec, WebGLSender<Vec<i32>>),
TexParameteri(u32, u32, i32),
TexParameterf(u32, u32, f32),
DrawArrays {
@@ -913,6 +915,14 @@ parameters! {
}
}

parameters! {
InternalFormatParameter {
IntVec(InternalFormatIntVec {
Samples = gl::SAMPLES,
}),
}
}

#[macro_export]
macro_rules! gl_enums {
($(pub enum $name:ident { $($variant:ident = $mod:ident::$constant:ident,)+ })*) => {
@@ -42,7 +42,8 @@ use crate::js::conversions::ToJSValConvertible;
use crate::script_runtime::JSContext;
use canvas_traits::webgl::WebGLError::*;
use canvas_traits::webgl::{
webgl_channel, GLContextAttributes, WebGLCommand, WebGLResult, WebGLVersion,
webgl_channel, GLContextAttributes, InternalFormatParameter, WebGLCommand, WebGLResult,
WebGLVersion,
};
use dom_struct::dom_struct;
use euclid::default::{Point2D, Rect, Size2D};
@@ -51,7 +52,7 @@ use js::jsapi::{JSObject, Type};
use js::jsval::{BooleanValue, DoubleValue, Int32Value, UInt32Value};
use js::jsval::{JSVal, NullValue, ObjectValue, UndefinedValue};
use js::rust::CustomAutoRooterGuard;
use js::typedarray::{ArrayBufferView, CreateWith, Float32, Uint32, Uint32Array};
use js::typedarray::{ArrayBufferView, CreateWith, Float32, Int32Array, Uint32, Uint32Array};
use script_layout_interface::HTMLCanvasDataSource;
use std::cell::Cell;
use std::cmp;
@@ -3753,6 +3754,60 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
None => self.base.webgl_error(InvalidOperation),
}
}

/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.5
#[allow(unsafe_code)]
fn GetInternalformatParameter(
&self,
cx: JSContext,
target: u32,
internal_format: u32,
pname: u32,
) -> JSVal {
if target != constants::RENDERBUFFER {
self.base.webgl_error(InvalidEnum);
return NullValue();
}

match handle_potential_webgl_error!(
self.base,
InternalFormatParameter::from_u32(pname),
return NullValue()
) {
InternalFormatParameter::IntVec(param) => unsafe {
let (sender, receiver) = webgl_channel().unwrap();
self.base
.send_command(WebGLCommand::GetInternalFormatIntVec(
target,
internal_format,
param,
sender,
));

rooted!(in(*cx) let mut rval = ptr::null_mut::<JSObject>());
let _ = Int32Array::create(
*cx,
CreateWith::Slice(&receiver.recv().unwrap()),
rval.handle_mut(),
)
.unwrap();
ObjectValue(rval.get())
},
}
}

/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.5
fn RenderbufferStorageMultisample(
&self,
target: u32,
samples: i32,
internal_format: u32,
width: i32,
height: i32,
) {
self.base
.renderbuffer_storage(target, samples, internal_format, width, height)
}
}

impl LayoutCanvasWebGLRenderingContextHelpers for LayoutDom<WebGL2RenderingContext> {
@@ -14,7 +14,8 @@ use crate::dom::webglframebuffer::WebGLFramebuffer;
use crate::dom::webglobject::WebGLObject;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
use canvas_traits::webgl::{
webgl_channel, GlType, WebGLCommand, WebGLError, WebGLRenderbufferId, WebGLResult, WebGLVersion,
webgl_channel, GlType, InternalFormatIntVec, WebGLCommand, WebGLError, WebGLRenderbufferId,
WebGLResult, WebGLVersion,
};
use dom_struct::dom_struct;
use std::cell::Cell;
@@ -133,11 +134,13 @@ impl WebGLRenderbuffer {
pub fn storage(
&self,
api_type: GlType,
sample_count: i32,
internal_format: u32,
width: i32,
height: i32,
) -> WebGLResult<()> {
let is_gles = api_type == GlType::Gles;
let webgl_version = self.upcast().context().webgl_version();

// Validate the internal_format, and save it for completeness
// validation.
@@ -173,7 +176,7 @@ impl WebGLRenderbuffer {
constants::DEPTH_COMPONENT24 |
constants::DEPTH_COMPONENT32F |
constants::DEPTH24_STENCIL8 |
constants::DEPTH32F_STENCIL8 => match self.upcast().context().webgl_version() {
constants::DEPTH32F_STENCIL8 => match webgl_version {
WebGLVersion::WebGL1 => return Err(WebGLError::InvalidEnum),
_ => internal_format,
},
@@ -221,24 +224,47 @@ impl WebGLRenderbuffer {
_ => return Err(WebGLError::InvalidEnum),
};

if webgl_version != WebGLVersion::WebGL1 {
let (sender, receiver) = webgl_channel().unwrap();
self.upcast::<WebGLObject>().context().send_command(
WebGLCommand::GetInternalFormatIntVec(
constants::RENDERBUFFER,
internal_format,
InternalFormatIntVec::Samples,
sender,
),
);
let samples = receiver.recv().unwrap();
if sample_count < 0 || sample_count as usize > samples.len() {
return Err(WebGLError::InvalidOperation);
}
}

self.internal_format.set(Some(internal_format));
self.is_initialized.set(false);

if let Some(fb) = self.attached_framebuffer.get() {
fb.update_status();
}

self.upcast::<WebGLObject>()
.context()
.send_command(WebGLCommand::RenderbufferStorage(
let command = match sample_count {
0 => WebGLCommand::RenderbufferStorage(
constants::RENDERBUFFER,
actual_format,
width,
height,
));
),
_ => WebGLCommand::RenderbufferStorageMultisample(
constants::RENDERBUFFER,
sample_count,
actual_format,
width,
height,
),
};
self.upcast::<WebGLObject>().context().send_command(command);

self.size.set(Some((width, height)));

Ok(())
}

@@ -1476,6 +1476,40 @@ impl WebGLRenderingContext {
}
slot.set(framebuffer);
}

pub fn renderbuffer_storage(
&self,
target: u32,
samples: i32,
internal_format: u32,
width: i32,
height: i32,
) {
if target != constants::RENDERBUFFER {
return self.webgl_error(InvalidEnum);
}

let max = self.limits.max_renderbuffer_size;

if samples < 0 || width < 0 || width as u32 > max || height < 0 || height as u32 > max {
return self.webgl_error(InvalidValue);
}

let rb = handle_potential_webgl_error!(
self,
self.bound_renderbuffer.get().ok_or(InvalidOperation),
return
);
handle_potential_webgl_error!(
self,
rb.storage(self.api_type, samples, internal_format, width, height)
);
if let Some(fb) = self.bound_draw_framebuffer.get() {
fb.invalidate_renderbuffer(&*rb);
}

// FIXME: https://github.com/servo/servo/issues/13710
}
}

#[cfg(not(feature = "webgl_backtrace"))]
@@ -4336,30 +4370,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {

// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7
fn RenderbufferStorage(&self, target: u32, internal_format: u32, width: i32, height: i32) {
if target != constants::RENDERBUFFER {
return self.webgl_error(InvalidEnum);
}

let max = self.limits.max_renderbuffer_size;

if width < 0 || width as u32 > max || height < 0 || height as u32 > max {
return self.webgl_error(InvalidValue);
}

let rb = handle_potential_webgl_error!(
self,
self.bound_renderbuffer.get().ok_or(InvalidOperation),
return
);
handle_potential_webgl_error!(
self,
rb.storage(self.api_type, internal_format, width, height)
);
if let Some(fb) = self.bound_draw_framebuffer.get() {
fb.invalidate_renderbuffer(&*rb);
}

// FIXME: https://github.com/servo/servo/issues/13710
self.renderbuffer_storage(target, 0, internal_format, width, height)
}

// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6
@@ -316,9 +316,9 @@ interface mixin WebGL2RenderingContextBase
// void readBuffer(GLenum src);

/* Renderbuffer objects */
// any getInternalformatParameter(GLenum target, GLenum internalformat, GLenum pname);
// void renderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat,
// GLsizei width, GLsizei height);
any getInternalformatParameter(GLenum target, GLenum internalformat, GLenum pname);
void renderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat,
GLsizei width, GLsizei height);

/* Texture objects */
// void texStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.