Auto merge of #13309 - anholt:webgl-fbo-prep, r=emilio

webgl: FBO support preparation

<!-- Please describe your changes on the following line: -->
Sending this PR now so that we can get the webrender patches merged.  This is prep for the webgl-fbo series, with one small fix for some conformance tests.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [X] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13309)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-09-20 19:19:21 -05:00 committed by GitHub
commit 7c0dfd07ad
13 changed files with 129 additions and 49 deletions

View file

@ -427,9 +427,12 @@ impl WebRenderDisplayItemConverter for DisplayItem {
if let Some(id) = item.webrender_image.key {
if item.stretch_size.width > Au(0) &&
item.stretch_size.height > Au(0) {
// TODO(gw): Pass through the tile spacing once the other
// changes related to this land (parsing etc).
builder.push_image(item.base.bounds.to_rectf(),
item.base.clip.to_clip_region(frame_builder),
item.stretch_size.to_sizef(),
Size2D::zero(),
item.image_rendering.to_image_rendering(),
id);
}

View file

@ -5,6 +5,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
use canvas_traits::CanvasMsg;
use dom::bindings::codegen::Bindings::WebGLFramebufferBinding;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
@ -79,6 +80,12 @@ impl WebGLFramebuffer {
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> {
self.target.get()
}

View file

@ -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) {
let texture = match target {
constants::TEXTURE_2D => self.bound_texture_2d.get(),
@ -591,6 +623,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
let error_code = if let Some(error) = self.last_error.get() {
match error {
WebGLError::InvalidEnum => constants::INVALID_ENUM,
WebGLError::InvalidFramebufferOperation => constants::INVALID_FRAMEBUFFER_OPERATION,
WebGLError::InvalidValue => constants::INVALID_VALUE,
WebGLError::InvalidOperation => constants::INVALID_OPERATION,
WebGLError::OutOfMemory => constants::OUT_OF_MEMORY,
@ -748,9 +781,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// case: Chromium currently unbinds, and Gecko silently
// returns. The conformance tests don't cover this case.
Some(renderbuffer) if !renderbuffer.is_deleted() => {
renderbuffer.bind(target)
self.bound_renderbuffer.set(Some(renderbuffer));
renderbuffer.bind(target);
}
_ => {
self.bound_renderbuffer.set(None);
// Unbind the currently bound renderbuffer
self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, None)))
@ -773,6 +808,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
Err(err) => return self.webgl_error(err),
}
} else {
slot.set(None);
// Unbind the currently bound texture
self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::BindTexture(target, None)))
@ -882,6 +918,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
fn CopyTexImage2D(&self, target: u32, level: i32, internal_format: u32,
x: i32, y: i32, width: i32, height: i32, border: i32) {
if !self.validate_framebuffer_complete() {
return;
}
let validator = CommonTexImage2DValidator::new(self, target, level,
internal_format, width,
height, border);
@ -935,6 +975,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
fn CopyTexSubImage2D(&self, target: u32, level: i32, xoffset: i32, yoffset: 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
// common validations, but this should have its own validator.
let validator = CommonTexImage2DValidator::new(self, target, level,
@ -974,6 +1018,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
fn Clear(&self, mask: u32) {
if !self.validate_framebuffer_complete() {
return;
}
self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::Clear(mask))).unwrap();
self.mark_as_dirty();
}
@ -1200,6 +1248,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidValue);
}
if !self.validate_framebuffer_complete() {
return;
}
self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::DrawArrays(mode, first, count)))
.unwrap();
@ -1236,6 +1288,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidOperation);
}
if !self.validate_framebuffer_complete() {
return;
}
match mode {
constants::POINTS | constants::LINE_STRIP |
constants::LINE_LOOP | constants::LINES |
@ -1504,6 +1560,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
None => return self.webgl_error(InvalidValue),
};
if !self.validate_framebuffer_complete() {
return;
}
match unsafe { JS_GetArrayBufferViewType(pixels) } {
Type::Uint8 => (),
_ => return self.webgl_error(InvalidOperation)

View file

@ -2643,7 +2643,7 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.5.1"
source = "git+https://github.com/servo/webrender#61b8f8bfefd472bd71dd9a06c1d16dab28c1fcc0"
source = "git+https://github.com/servo/webrender#58b9e983a5e74ac1670fcf67f9c2ba68740ab2cc"
dependencies = [
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2668,7 +2668,7 @@ dependencies = [
[[package]]
name = "webrender_traits"
version = "0.5.1"
source = "git+https://github.com/servo/webrender#61b8f8bfefd472bd71dd9a06c1d16dab28c1fcc0"
source = "git+https://github.com/servo/webrender#58b9e983a5e74ac1670fcf67f9c2ba68740ab2cc"
dependencies = [
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",