diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-11-05 16:52:51 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-05 16:52:51 -0500 |
commit | afbcbf75eaa63ff0eec8fd3858e9155eb8dbadaa (patch) | |
tree | 8b0f5cf2b882ba3b7fc0fef8df49ac9a3a9d0e6a /components/script/dom/webglrenderingcontext.rs | |
parent | 593f8bd0f66d0c4a4f8f636a78337a7f029b9b8f (diff) | |
parent | 4050b7f9eca4c581d100fed778fa09f21d7e09dd (diff) | |
download | servo-afbcbf75eaa63ff0eec8fd3858e9155eb8dbadaa.tar.gz servo-afbcbf75eaa63ff0eec8fd3858e9155eb8dbadaa.zip |
Auto merge of #24473 - mmatyas:webgl_fns_buffer, r=jdm
Implement the basic WebGL2 buffer data operations
Adds support for the WebGL2 calls `bufferData`, `bufferSubData`, `copyBufferSubData` and `getBufferSubData`.
Reference: https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.3
---
<!-- Please describe your changes on the following line: -->
This patch depends on https://github.com/servo/sparkle/pull/8. Some tests cause a crash for me at the moment, as they depend on other, not yet implemented buffer calls and transform feedback objects.
As for the code, there are a few parts I'm not sure about:
- To get the element byte size of a TypedArray I've wrote a simple `match`, as the relevant field is not published in `rust-mozjs`. Is that okay or there's some other way to get this already?
- The WebGL1 BufferData implementations were copied into the WebGL2 code as a workaround, due to the difference in the available buffer slots (ie. `self.bound_buffer`). An alternative could be is to pass this function and self as parameters to an internal buffer data implementation function, but personally I found that code to be quite ugly.
cc @jdm @zakorgy
---
<!-- 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 (with the sparkle patch)
- [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 ___
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Diffstat (limited to 'components/script/dom/webglrenderingcontext.rs')
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 117 |
1 files changed, 74 insertions, 43 deletions
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index b5faecc7371..f0e4887858c 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -255,7 +255,7 @@ impl WebGLRenderingContext { &self.limits } - fn current_vao(&self) -> DomRoot<WebGLVertexArrayObjectOES> { + pub fn current_vao(&self) -> DomRoot<WebGLVertexArrayObjectOES> { self.current_vao.or_init(|| { DomRoot::from_ref( self.default_vao @@ -1004,6 +1004,10 @@ impl WebGLRenderingContext { self.bound_buffer_array.get() } + pub fn array_buffer_slot(&self) -> &MutNullableDom<WebGLBuffer> { + &self.bound_buffer_array + } + pub fn bound_buffer(&self, target: u32) -> WebGLResult<Option<DomRoot<WebGLBuffer>>> { match target { constants::ARRAY_BUFFER => Ok(self.bound_buffer_array.get()), @@ -1095,6 +1099,72 @@ impl WebGLRenderingContext { pub fn extension_manager(&self) -> &WebGLExtensions { &self.extension_manager } + + #[allow(unsafe_code)] + pub fn buffer_data( + &self, + target: u32, + data: Option<ArrayBufferViewOrArrayBuffer>, + usage: u32, + bound_buffer: Option<DomRoot<WebGLBuffer>>, + ) { + let data = handle_potential_webgl_error!(self, data.ok_or(InvalidValue), return); + let bound_buffer = + handle_potential_webgl_error!(self, bound_buffer.ok_or(InvalidOperation), return); + + let data = unsafe { + // Safe because we don't do anything with JS until the end of the method. + match data { + ArrayBufferViewOrArrayBuffer::ArrayBuffer(ref data) => data.as_slice(), + ArrayBufferViewOrArrayBuffer::ArrayBufferView(ref data) => data.as_slice(), + } + }; + handle_potential_webgl_error!(self, bound_buffer.buffer_data(target, data, usage)); + } + + pub fn buffer_data_( + &self, + target: u32, + size: i64, + usage: u32, + bound_buffer: Option<DomRoot<WebGLBuffer>>, + ) { + let bound_buffer = + handle_potential_webgl_error!(self, bound_buffer.ok_or(InvalidOperation), return); + + if size < 0 { + return self.webgl_error(InvalidValue); + } + + // FIXME: Allocating a buffer based on user-requested size is + // not great, but we don't have a fallible allocation to try. + let data = vec![0u8; size as usize]; + handle_potential_webgl_error!(self, bound_buffer.buffer_data(target, &data, usage)); + } + + pub fn bind_buffer_maybe( + &self, + slot: &MutNullableDom<WebGLBuffer>, + target: u32, + buffer: Option<&WebGLBuffer>, + ) { + if let Some(buffer) = buffer { + handle_potential_webgl_error!(self, self.validate_ownership(buffer), return); + + if buffer.is_marked_for_deletion() { + return self.webgl_error(InvalidOperation); + } + handle_potential_webgl_error!(self, buffer.set_target_maybe(target), return); + buffer.increment_attached_counter(); + } + + self.send_command(WebGLCommand::BindBuffer(target, buffer.map(|b| b.id()))); + if let Some(old) = slot.get() { + old.decrement_attached_counter(); + } + + slot.set(buffer); + } } #[cfg(not(feature = "webgl_backtrace"))] @@ -1585,10 +1655,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 fn BindBuffer(&self, target: u32, buffer: Option<&WebGLBuffer>) { - if let Some(buffer) = buffer { - handle_potential_webgl_error!(self, self.validate_ownership(buffer), return); - } - let current_vao; let slot = match target { constants::ARRAY_BUFFER => &self.bound_buffer_array, @@ -1598,19 +1664,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { }, _ => return self.webgl_error(InvalidEnum), }; - - if let Some(buffer) = buffer { - if buffer.is_marked_for_deletion() { - return self.webgl_error(InvalidOperation); - } - handle_potential_webgl_error!(self, buffer.set_target(target), return); - buffer.increment_attached_counter(); - } - self.send_command(WebGLCommand::BindBuffer(target, buffer.map(|b| b.id()))); - if let Some(old) = slot.get() { - old.decrement_attached_counter(); - } - slot.set(buffer); + self.bind_buffer_maybe(&slot, target, buffer); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 @@ -1701,38 +1755,15 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 - #[allow(unsafe_code)] fn BufferData(&self, target: u32, data: Option<ArrayBufferViewOrArrayBuffer>, usage: u32) { - let data = handle_potential_webgl_error!(self, data.ok_or(InvalidValue), return); - let bound_buffer = handle_potential_webgl_error!(self, self.bound_buffer(target), return); - let bound_buffer = - handle_potential_webgl_error!(self, bound_buffer.ok_or(InvalidOperation), return); - - let data = unsafe { - // Safe because we don't do anything with JS until the end of the method. - match data { - ArrayBufferViewOrArrayBuffer::ArrayBuffer(ref data) => data.as_slice(), - ArrayBufferViewOrArrayBuffer::ArrayBufferView(ref data) => data.as_slice(), - } - }; - handle_potential_webgl_error!(self, bound_buffer.buffer_data(data, usage)); + self.buffer_data(target, data, usage, bound_buffer) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 fn BufferData_(&self, target: u32, size: i64, usage: u32) { let bound_buffer = handle_potential_webgl_error!(self, self.bound_buffer(target), return); - let bound_buffer = - handle_potential_webgl_error!(self, bound_buffer.ok_or(InvalidOperation), return); - - if size < 0 { - return self.webgl_error(InvalidValue); - } - - // FIXME: Allocating a buffer based on user-requested size is - // not great, but we don't have a fallible allocation to try. - let data = vec![0u8; size as usize]; - handle_potential_webgl_error!(self, bound_buffer.buffer_data(&data, usage)); + self.buffer_data_(target, size, usage, bound_buffer) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 |