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 upImage mask support #445
Image mask support #445
Conversation
|
@kvark Thanks! The general idea here seems good - the public API looks fine to me. In terms of implementation, I try to avoid using uniform variables whenever possible, to simplify how the batching code works and reduce batch breaks. Instead, what I'd suggest is adding fields to the Clip struct in tiling.rs, and modifying the code in prim_shared to fetch the data from there. That way, there shouldn't be any need to change the batching code at all. Let me know if that doesn't make sense or you foresee any issues with that :) |
|
@glennw thanks for taking a look! |
|
@kvark Yep, that's right - we put (almost) everything in an atlas, so it should batch together nicely :) |
|
|
|
Rebased now, the implementation follows the route you laid out - passing the clip rectangles via the batch data instead of uniforms. |
|
|
|
Looks pretty good, just a few minor issues / questions. I rebased it locally on my machine to test with, there was only a couple of minor conflicts to fix up. |
| @@ -5,6 +5,8 @@ | |||
|
|
|||
| flat varying vec4 vClipRect; | |||
| flat varying vec4 vClipRadius; | |||
| flat varying vec4 vClipMaskUvRect; | |||
| flat varying vec4 vClipMaskScreenRect; | |||
This comment has been minimized.
This comment has been minimized.
glennw
Oct 24, 2016
Member
We should probably rename this to be something like vClipMaskLocalRect, since (I think) it's in the local space of the primitive rectangle?
This comment has been minimized.
This comment has been minimized.
| return rect; | ||
| } | ||
|
|
||
| struct MaskRect { |
This comment has been minimized.
This comment has been minimized.
glennw
Oct 24, 2016
Member
Could we rename these fields to be a bit more descriptive? Perhaps uv_rect and local_mask_rect or something like that?
This comment has been minimized.
This comment has been minimized.
| @@ -206,12 +209,19 @@ impl ClipCorner { | |||
| } | |||
|
|
|||
| #[derive(Debug, Clone)] | |||
| pub struct MaskRect { | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| @@ -552,6 +553,11 @@ impl Renderer { | |||
| let data64_texture = VertexDataTexture::new(&mut device); | |||
| let data128_texture = VertexDataTexture::new(&mut device); | |||
|
|
|||
| let dummy_mask_texture = device.create_texture_ids(1)[0]; | |||
This comment has been minimized.
This comment has been minimized.
glennw
Oct 24, 2016
Member
I wonder if this will cause unnecessary batch breaks when there are clips that don't have masks. We could probably insert a dummy mask into the atlas instead of creating a separate texture. But that doesn't matter for now, we can do it as a follow up if it's an issue.
This comment has been minimized.
This comment has been minimized.
kvark
Oct 24, 2016
Author
Member
I had a hard time figuring out how to properly assign a default masking texture for this case. Ended up introducing DummyResources struct to store the white texture as well the opaque one (which were previously forgotten but still created). Let me know if there is a better solution please.
| @@ -702,6 +704,23 @@ impl RenderTask { | |||
| pub const SCREEN_TILE_SIZE: i32 = 64; | |||
| pub const RENDERABLE_CACHE_SIZE: DevicePixel = DevicePixel(2048); | |||
|
|
|||
| /// Per-batch clipping info merged with the mask image. | |||
| #[derive(Clone, Debug)] | |||
| pub struct MaskedClip { | |||
This comment has been minimized.
This comment has been minimized.
glennw
Oct 24, 2016
Member
Instead of introducing a new structure here, could we just add the fields/struct to the Clip structure? The Clip structure already handles simple / complex clips, it seems like it's probably reasonable to make the Clip structure able to handle any number of clip types. If we do that, we won't need to modify the API of all the FrameBuilder methods.
This comment has been minimized.
This comment has been minimized.
kvark
Oct 24, 2016
•
Author
Member
MaskedClip is a part of the Clip, so moving the fields in there directly would break the API as much regardless. The reason I even introduced this was to pack both rectangles into a single 32 byte gpu block, instead of having a 16 byte pad after each.
|
Nearly there! :) |
| vec2 local_pos = vPos; | ||
| #endif | ||
|
|
||
| alpha = min(alpha, do_clip(local_pos)); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| @@ -676,7 +693,7 @@ impl Renderer { | |||
| fn enable_msaa(&self, _: bool) { | |||
| } | |||
|
|
|||
| #[cfg(any(target_os = "windows", unix))] | |||
| #[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))] | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
|
||
| /// Per-batch clipping info merged with the mask image. | ||
| #[derive(Clone, Debug)] | ||
| pub struct MaskedClip { |
This comment has been minimized.
This comment has been minimized.
glennw
Oct 24, 2016
•
Member
I'm still not sure about having this struct. Could we have something like:
struct Clip {
// existing clip rect and corners
pub mask: Option<MaskImageSource>,
}
And then use that to construct the data to be put in the gpu blocks during prim prepare / cache?
I might be missing something as I haven't actually tried this - but it sounds like it might be a simpler API if it works.
This comment has been minimized.
This comment has been minimized.
kvark
Oct 25, 2016
Author
Member
I'm following the existing style in here. Clip structure (contrary to ClipRegion) is supposed to map semi-directly to the GPU. At least it seems it should, given that the shader side has the same structs (Clip, ClipRect, ClipCorner).
If I add Option<MaskImageSource>, that would make it inconsistent, since:
pub enum MaskImageSource {
User(ImageKey),
Renderer(TextureId),
}
This comment has been minimized.
This comment has been minimized.
glennw
Oct 25, 2016
Member
I can see your point about the consistency aspect of the structure internals, but I think having the public API type for FrameBuilder be called Clip is important. How about as a compromise we keep the structure layout as is, but rename Clip -> ClipGpu and make it private, and rename MaskedClip -> Clip?
This comment has been minimized.
This comment has been minimized.
| oFragColor = vColor * vec4(1, 1, 1, alpha); | ||
|
|
||
| #ifdef WR_FEATURE_TRANSFORM |
This comment has been minimized.
This comment has been minimized.
kvark
Oct 25, 2016
Author
Member
@glennw
Looks like we were multiplying the alpha twice. I assume this was a mistake.
|
@kvark Looks good! Let's squash and get this merged :) |
|
Do you want a single commit? Or 2-3?
|
|
@kvark The smallest number of commits that make sense as individual commits. 2-3 is fine if that makes sense. |
|
@bors-servo r+ |
|
|
Image mask support Closes #405 I'm not completely sure if this is the right approach, hoping to get some review/feedback to proceed. The API and logic works for me with `wr_sample`, although the implementation lacks a lot of features to support, like image repeating and layout transformations. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/445) <!-- Reviewable:end -->
|
|
kvark commentedOct 17, 2016
•
edited by larsbergstrom
Closes #405
I'm not completely sure if this is the right approach, hoping to get some review/feedback to proceed. The API and logic works for me with
wr_sample, although the implementation lacks a lot of features to support, like image repeating and layout transformations.This change is