Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upwebgl: premultiplication, y flipping, and format conversion #15122
Conversation
highfive
commented
Jan 20, 2017
|
Looks great! Only minor comments, thanks for doing this! |
| // implementation. If a packed pixel format is specified | ||
| // which would imply loss of bits of precision from the image | ||
| // data, this loss of precision must occur." | ||
| fn rgba8_image_to_tex_image_data(&self, |
This comment has been minimized.
This comment has been minimized.
| fn rgba8_image_to_tex_image_data(&self, | ||
| format: TexFormat, | ||
| data_type: TexDataType, | ||
| pixels: Vec<u8> ) -> Vec<u8> { |
This comment has been minimized.
This comment has been minimized.
| // into an enum yet so there's a default case here. All | ||
| // WebGL types are 4 bytes per pixel or smaller, so just | ||
| // return the incoming RGBA8 pixels in this path. | ||
| _ => pixels |
This comment has been minimized.
This comment has been minimized.
emilio
Jan 20, 2017
Member
Maybe asserting (at least in debug builds), or marking as unreachable! would help catch errors?
This comment has been minimized.
This comment has been minimized.
anholt
Jan 20, 2017
Author
Contributor
OK, looks like unreachable!() should always panic. I thought I'd seen something in my other debugging that suggested that it didn't panic.
| internal_format: TexFormat, | ||
| data_type: TexDataType, | ||
| width: usize, | ||
| height: usize) -> Vec<u8> { |
This comment has been minimized.
This comment has been minimized.
emilio
Jan 20, 2017
Member
Since this only creates a vector of the same capacity as pixels, seems like we could flip in place? the logic would be a bit more complicated though, maybe mentioning it with a comment?
This comment has been minimized.
This comment has been minimized.
anholt
Jan 20, 2017
Author
Contributor
We're passed in a non-mut Vec at the top of the tex_image()s since we shouldn't be rewriting the JS's array. We could potentially see that we're going to be chaining more than one of these fixups and use a single mut Vec that we operate on, but that sounded messy.
| format: TexFormat, | ||
| data_type: TexDataType, | ||
| pixels: Vec<u8>) -> Vec<u8> { | ||
| if !(self.texture_unpacking_settings.get().contains(PREMULTIPLY_ALPHA)) { |
This comment has been minimized.
This comment has been minimized.
| fn premultiply_pixels(&self, | ||
| format: TexFormat, | ||
| data_type: TexDataType, | ||
| pixels: Vec<u8>) -> Vec<u8> { |
This comment has been minimized.
This comment has been minimized.
emilio
Jan 20, 2017
Member
Just as above, this only returns a vector of the same size as pixels, right?
If that's the case, probably we should also premultiply in-place, either using &mut [u8], or mut pixels: Vec<u8>.
Mind at least mentioning it here (and filing a followup maybe?)
| [WebGL test #1095: at (0, 4) expected: 0,0,0,255 was 0,0,255,255] | ||
| expected: FAIL | ||
|
|
||
| [WebGL test #1097: at (0, 8) expected: 0,0,0,255 was 0,255,0,255] |
This comment has been minimized.
This comment has been minimized.
emilio
Jan 20, 2017
Member
Wow, poor test, I was wondering where the diffstat came from, awesome! :)
| @@ -112,6 +112,11 @@ fn has_invalid_blend_constants(arg1: u32, arg2: u32) -> bool { | |||
| (_, _) => false | |||
| } | |||
| } | |||
|
|
|||
| fn multiply_u8_pixel(a: u8, b: u8) -> u8 { | |||
This comment has been minimized.
This comment has been minimized.
emilio
Jan 20, 2017
Member
nit: We have code for premultiplication in components/canvas_traits/lib.rs. They contain code similar to this, you may consider putting it there (or even all the premultiplication subroutines? Though that's not great because they aren't used anywhere else).
Anyway, your choice :)
This comment has been minimized.
This comment has been minimized.
anholt
Jan 20, 2017
Author
Contributor
I had noticed that, but I didn't imagine that that code would want to grow some sort of format enum for handling different GL formats.
| // is coherent with the image. | ||
| // | ||
| // RGB8 should be easy to support too | ||
| // TODO(anholt): What other incoming formats do we |
This comment has been minimized.
This comment has been minimized.
emilio
Jan 20, 2017
Member
I think for now Servo stores all its images internally as RGBA8, so we don't need to worry about it I think.
| premul | ||
| } | ||
|
|
||
| _ => pixels |
This comment has been minimized.
This comment has been minimized.
emilio
Jan 20, 2017
Member
Is this also unreachable? If not, consider commenting which cases do we expect? Otherwise, mark as such?
|
Regarding casting |
|
Perhaps https://docs.rs/byteorder/1.0.0/byteorder/ would help. |
|
r=me, thanks Eric :) |
|
@bors-servo r+ |
|
|
|
|
webgl: premultiplication, y flipping, and format conversion <!-- Please describe your changes on the following line: --> This series implements a bunch of the texture unpack path features for WebGL. There are known issues with big-endian systems noted in the comments, but I don't know of a clean way to cast from `Vec<u16>` to `Vec<u8>` (which, if we had one, would make this code much cleaner anyway). --- <!-- 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/15122) <!-- Reviewable:end -->
|
|
|
OK, I think I know the cause of that Mac failure: not having unpack alignment support. |
|
We could mark those as failing on mac if you want, I think this is worth landing |
This fixes a couple of tests doing RGBA/ubyte image uploads with flipping. Other tests with flipping get their expectations changed, because some other feature is missing (premultiplication or ImageData/canvas format conversion)
The code was returning RGBA8 data from the non-raw sources (HTML canvas elements, JS ImageData, etc.), but we then validated and passed that rgba8 data as if it was whatever format/datatype was specified in TexImage2D/TexSubImage2D, so the pixels would come out as garbage. It would seem like we could just rewrite the passed in format/datatype for the TexImage call to be RGBA/UNSIGNED_BYTE, but that would leave incorrect levels of precision if the internalformat didn't match the format/datatype (and older desktop implementations often ignore the internalformat in choosing their internal format, anyway).
Now the affected testcase only fails due to unpack alignment.
|
I'm actually testing the unpack fix now. |
We were setting it to whatever value from {1,2,4,8} the user requested
and otherwise ignoring it. There were two problems there:
1) Validation ignored it, so GL could read outside of the user's array
in TexImage() or TexSubImage() if the aligment was greater than
cpp.
2) TexImage()/TexSubImage() from image/canvas sources wasn't packing
its data according to the unpack alignment.
To fix this, start tracking the user-requested alignment in the DOM
side of the context. Set the GL's alignment to 1 for image/canvas
sources or the user's value for array sources, and pass the user's
alignment in to validation so that it can figure out the correct size
of image that the GL will ready.
|
As a uber-nit, |
| let expected_byte_length = width * height * element_size * components / components_per_element; | ||
| return Ok(expected_byte_length); | ||
| if height == 0 { | ||
| return Ok(0); |
This comment has been minimized.
This comment has been minimized.
emilio
Feb 3, 2017
Member
nit: Since you early-return, there's no need for the else branch, but not a big deal.
|
@bors-servo r+ Thanks! |
|
|
webgl: premultiplication, y flipping, and format conversion <!-- Please describe your changes on the following line: --> This series implements a bunch of the texture unpack path features for WebGL. There are known issues with big-endian systems noted in the comments, but I don't know of a clean way to cast from `Vec<u16>` to `Vec<u8>` (which, if we had one, would make this code much cleaner anyway). --- <!-- 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/15122) <!-- Reviewable:end -->
|
|
anholt commentedJan 20, 2017
•
edited by larsbergstrom
This series implements a bunch of the texture unpack path features for WebGL. There are known issues with big-endian systems noted in the comments, but I don't know of a clean way to cast from
Vec<u16>toVec<u8>(which, if we had one, would make this code much cleaner anyway)../mach build -ddoes not report any errors./mach test-tidydoes not report any errorsThis change is