mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
webgl: Do validation that the framebuffer is complete for FBO operations.
Given that we can't make a complete FBO yet, just return false from the status check.
This commit is contained in:
parent
b2c169274a
commit
87c9333abd
2 changed files with 63 additions and 0 deletions
|
@ -5,6 +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 canvas_traits::CanvasMsg;
|
use canvas_traits::CanvasMsg;
|
||||||
use dom::bindings::codegen::Bindings::WebGLFramebufferBinding;
|
use dom::bindings::codegen::Bindings::WebGLFramebufferBinding;
|
||||||
|
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||||
use dom::bindings::global::GlobalRef;
|
use dom::bindings::global::GlobalRef;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::bindings::reflector::reflect_dom_object;
|
use dom::bindings::reflector::reflect_dom_object;
|
||||||
|
@ -79,6 +80,12 @@ impl WebGLFramebuffer {
|
||||||
self.is_deleted.get()
|
self.is_deleted.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_status(&self) -> u32 {
|
||||||
|
// Until we build support for attaching renderbuffers or
|
||||||
|
// textures, all user FBOs are incomplete.
|
||||||
|
return constants::FRAMEBUFFER_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn target(&self) -> Option<u32> {
|
pub fn target(&self) -> Option<u32> {
|
||||||
self.target.get()
|
self.target.get()
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,38 @@ impl WebGLRenderingContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function for validating framebuffer completeness in
|
||||||
|
// calls touching the framebuffer. From the GLES 2.0.25 spec,
|
||||||
|
// page 119:
|
||||||
|
//
|
||||||
|
// "Effects of Framebuffer Completeness on Framebuffer
|
||||||
|
// Operations
|
||||||
|
//
|
||||||
|
// If the currently bound framebuffer is not framebuffer
|
||||||
|
// complete, then it is an error to attempt to use the
|
||||||
|
// framebuffer for writing or reading. This means that
|
||||||
|
// rendering commands such as DrawArrays and DrawElements, as
|
||||||
|
// well as commands that read the framebuffer such as
|
||||||
|
// ReadPixels and CopyTexSubImage, will generate the error
|
||||||
|
// INVALID_FRAMEBUFFER_OPERATION if called while the
|
||||||
|
// framebuffer is not framebuffer complete."
|
||||||
|
//
|
||||||
|
// The WebGL spec mentions a couple more operations that trigger
|
||||||
|
// this: clear() and getParameter(IMPLEMENTATION_COLOR_READ_*).
|
||||||
|
fn validate_framebuffer_complete(&self) -> bool {
|
||||||
|
match self.bound_framebuffer.get() {
|
||||||
|
Some(fb) => match fb.check_status() {
|
||||||
|
constants::FRAMEBUFFER_COMPLETE => return true,
|
||||||
|
_ => {
|
||||||
|
self.webgl_error(InvalidFramebufferOperation);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// The default framebuffer is always complete.
|
||||||
|
None => return true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn tex_parameter(&self, target: u32, name: u32, value: TexParameterValue) {
|
fn tex_parameter(&self, target: u32, name: u32, value: TexParameterValue) {
|
||||||
let texture = match target {
|
let texture = match target {
|
||||||
constants::TEXTURE_2D => self.bound_texture_2d.get(),
|
constants::TEXTURE_2D => self.bound_texture_2d.get(),
|
||||||
|
@ -886,6 +918,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
|
||||||
fn CopyTexImage2D(&self, target: u32, level: i32, internal_format: u32,
|
fn CopyTexImage2D(&self, target: u32, level: i32, internal_format: u32,
|
||||||
x: i32, y: i32, width: i32, height: i32, border: i32) {
|
x: i32, y: i32, width: i32, height: i32, border: i32) {
|
||||||
|
if !self.validate_framebuffer_complete() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let validator = CommonTexImage2DValidator::new(self, target, level,
|
let validator = CommonTexImage2DValidator::new(self, target, level,
|
||||||
internal_format, width,
|
internal_format, width,
|
||||||
height, border);
|
height, border);
|
||||||
|
@ -939,6 +975,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
|
||||||
fn CopyTexSubImage2D(&self, target: u32, level: i32, xoffset: i32, yoffset: i32,
|
fn CopyTexSubImage2D(&self, target: u32, level: i32, xoffset: i32, yoffset: i32,
|
||||||
x: i32, y: i32, width: i32, height: i32) {
|
x: i32, y: i32, width: i32, height: i32) {
|
||||||
|
if !self.validate_framebuffer_complete() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// NB: We use a dummy (valid) format and border in order to reuse the
|
// NB: We use a dummy (valid) format and border in order to reuse the
|
||||||
// common validations, but this should have its own validator.
|
// common validations, but this should have its own validator.
|
||||||
let validator = CommonTexImage2DValidator::new(self, target, level,
|
let validator = CommonTexImage2DValidator::new(self, target, level,
|
||||||
|
@ -978,6 +1018,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
|
||||||
fn Clear(&self, mask: u32) {
|
fn Clear(&self, mask: u32) {
|
||||||
|
if !self.validate_framebuffer_complete() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::Clear(mask))).unwrap();
|
self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::Clear(mask))).unwrap();
|
||||||
self.mark_as_dirty();
|
self.mark_as_dirty();
|
||||||
}
|
}
|
||||||
|
@ -1204,6 +1248,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
return self.webgl_error(InvalidValue);
|
return self.webgl_error(InvalidValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.validate_framebuffer_complete() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.ipc_renderer
|
self.ipc_renderer
|
||||||
.send(CanvasMsg::WebGL(WebGLCommand::DrawArrays(mode, first, count)))
|
.send(CanvasMsg::WebGL(WebGLCommand::DrawArrays(mode, first, count)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1240,6 +1288,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
return self.webgl_error(InvalidOperation);
|
return self.webgl_error(InvalidOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.validate_framebuffer_complete() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
match mode {
|
match mode {
|
||||||
constants::POINTS | constants::LINE_STRIP |
|
constants::POINTS | constants::LINE_STRIP |
|
||||||
constants::LINE_LOOP | constants::LINES |
|
constants::LINE_LOOP | constants::LINES |
|
||||||
|
@ -1508,6 +1560,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
None => return self.webgl_error(InvalidValue),
|
None => return self.webgl_error(InvalidValue),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !self.validate_framebuffer_complete() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
match unsafe { JS_GetArrayBufferViewType(pixels) } {
|
match unsafe { JS_GetArrayBufferViewType(pixels) } {
|
||||||
Type::Uint8 => (),
|
Type::Uint8 => (),
|
||||||
_ => return self.webgl_error(InvalidOperation)
|
_ => return self.webgl_error(InvalidOperation)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue