Skip to content

Commit efba6f2

Browse files
author
bors-servo
authored
Auto merge of #3569 - moz-gfx:__wrlastsync, r=moz-gfx
Sync changes from mozilla-central <!-- 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/3569) <!-- Reviewable:end -->
2 parents d47bd44 + b482f53 commit efba6f2

17 files changed

+403
-359
lines changed

webrender/res/brush_mix_blend.glsl

Lines changed: 98 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66

77
#include shared,prim_shared,brush
88

9-
varying vec3 vSrcUv;
10-
varying vec3 vBackdropUv;
11-
flat varying int vOp;
9+
varying vec4 vSourceAndBackdropUv;
10+
flat varying ivec4 vSourceUvBounds;
11+
flat varying ivec4 vBackdropUvBounds;
12+
flat varying ivec3 vOpAndLayers;
1213

1314
#ifdef WR_VERTEX_SHADER
1415

@@ -17,6 +18,10 @@ vec2 snap_device_pos(VertexInfo vi, float device_pixel_scale) {
1718
return vi.world_pos.xy * device_pixel_scale / max(0.0, vi.world_pos.w) + vi.snap_offset;
1819
}
1920

21+
ivec4 rect_to_ivec(RectWithSize rect) {
22+
return ivec4(rect.p0, rect.p0 + rect.size - 1.0);
23+
}
24+
2025
void brush_vs(
2126
VertexInfo vi,
2227
int prim_address,
@@ -29,20 +34,25 @@ void brush_vs(
2934
vec4 unused
3035
) {
3136
vec2 snapped_device_pos = snap_device_pos(vi, pic_task.device_pixel_scale);
32-
vec2 texture_size = vec2(textureSize(sPrevPassColor, 0));
33-
vOp = user_data.x;
3437

3538
PictureTask src_task = fetch_picture_task(user_data.z);
39+
PictureTask backdrop_task = fetch_picture_task(user_data.y);
40+
3641
vec2 src_uv = snapped_device_pos +
3742
src_task.common_data.task_rect.p0 -
3843
src_task.content_origin;
39-
vSrcUv = vec3(src_uv / texture_size, src_task.common_data.texture_layer_index);
40-
41-
RenderTaskCommonData backdrop_task = fetch_render_task_common_data(user_data.y);
4244
vec2 backdrop_uv = snapped_device_pos +
43-
backdrop_task.task_rect.p0 -
44-
src_task.content_origin;
45-
vBackdropUv = vec3(backdrop_uv / texture_size, backdrop_task.texture_layer_index);
45+
backdrop_task.common_data.task_rect.p0 -
46+
backdrop_task.content_origin;
47+
48+
vSourceAndBackdropUv = vec4(src_uv, backdrop_uv);
49+
vSourceUvBounds = rect_to_ivec(src_task.common_data.task_rect);
50+
vBackdropUvBounds = rect_to_ivec(backdrop_task.common_data.task_rect);
51+
vOpAndLayers = ivec3(
52+
user_data.x,
53+
int(src_task.common_data.texture_layer_index),
54+
int(backdrop_task.common_data.texture_layer_index)
55+
);
4656
}
4757
#endif
4858

@@ -205,81 +215,88 @@ const int MixBlendMode_Color = 14;
205215
const int MixBlendMode_Luminosity = 15;
206216

207217
Fragment brush_fs() {
208-
vec4 Cb = textureLod(sPrevPassColor, vBackdropUv, 0.0);
209-
vec4 Cs = textureLod(sPrevPassColor, vSrcUv, 0.0);
210-
211-
// The mix-blend-mode functions assume no premultiplied alpha
212-
if (Cb.a != 0.0) {
213-
Cb.rgb /= Cb.a;
214-
}
215-
216-
if (Cs.a != 0.0) {
217-
Cs.rgb /= Cs.a;
218-
}
219-
220218
// Return yellow if none of the branches match (shouldn't happen).
221219
vec4 result = vec4(1.0, 1.0, 0.0, 1.0);
222220

223-
switch (vOp) {
224-
case MixBlendMode_Multiply:
225-
result.rgb = Multiply(Cb.rgb, Cs.rgb);
226-
break;
227-
case MixBlendMode_Screen:
228-
result.rgb = Screen(Cb.rgb, Cs.rgb);
229-
break;
230-
case MixBlendMode_Overlay:
231-
// Overlay is inverse of Hardlight
232-
result.rgb = HardLight(Cs.rgb, Cb.rgb);
233-
break;
234-
case MixBlendMode_Darken:
235-
result.rgb = min(Cs.rgb, Cb.rgb);
236-
break;
237-
case MixBlendMode_Lighten:
238-
result.rgb = max(Cs.rgb, Cb.rgb);
239-
break;
240-
case MixBlendMode_ColorDodge:
241-
result.r = ColorDodge(Cb.r, Cs.r);
242-
result.g = ColorDodge(Cb.g, Cs.g);
243-
result.b = ColorDodge(Cb.b, Cs.b);
244-
break;
245-
case MixBlendMode_ColorBurn:
246-
result.r = ColorBurn(Cb.r, Cs.r);
247-
result.g = ColorBurn(Cb.g, Cs.g);
248-
result.b = ColorBurn(Cb.b, Cs.b);
249-
break;
250-
case MixBlendMode_HardLight:
251-
result.rgb = HardLight(Cb.rgb, Cs.rgb);
252-
break;
253-
case MixBlendMode_SoftLight:
254-
result.r = SoftLight(Cb.r, Cs.r);
255-
result.g = SoftLight(Cb.g, Cs.g);
256-
result.b = SoftLight(Cb.b, Cs.b);
257-
break;
258-
case MixBlendMode_Difference:
259-
result.rgb = Difference(Cb.rgb, Cs.rgb);
260-
break;
261-
case MixBlendMode_Exclusion:
262-
result.rgb = Exclusion(Cb.rgb, Cs.rgb);
263-
break;
264-
case MixBlendMode_Hue:
265-
result.rgb = Hue(Cb.rgb, Cs.rgb);
266-
break;
267-
case MixBlendMode_Saturation:
268-
result.rgb = Saturation(Cb.rgb, Cs.rgb);
269-
break;
270-
case MixBlendMode_Color:
271-
result.rgb = Color(Cb.rgb, Cs.rgb);
272-
break;
273-
case MixBlendMode_Luminosity:
274-
result.rgb = Luminosity(Cb.rgb, Cs.rgb);
275-
break;
276-
default: break;
277-
}
221+
ivec2 source_uv = ivec2(floor(vSourceAndBackdropUv.xy));
222+
vec4 Cs = source_uv == clamp(source_uv, vSourceUvBounds.xy, vSourceUvBounds.zw) ?
223+
texelFetch(sPrevPassColor, ivec3(source_uv, vOpAndLayers.y), 0) :
224+
vec4(0.0);
225+
ivec2 backdrop_uv = ivec2(floor(vSourceAndBackdropUv.zw));
226+
vec4 Cb = backdrop_uv == clamp(backdrop_uv, vBackdropUvBounds.xy, vBackdropUvBounds.zw) ?
227+
texelFetch(sPrevPassColor, ivec3(backdrop_uv, vOpAndLayers.z), 0) :
228+
vec4(0.0);
229+
230+
if (Cs.a == 0.0) {
231+
result = Cb;
232+
} else if (Cb.a == 0.0) {
233+
result = Cs;
234+
} else {
235+
vec3 original_backdrop = Cb.rgb;
236+
// The mix-blend-mode functions assume no premultiplied alpha
237+
Cs.rgb /= Cs.a;
238+
Cb.rgb /= Cb.a;
278239

279-
result.rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
280-
result.a = Cs.a;
240+
switch (vOpAndLayers.x) {
241+
case MixBlendMode_Multiply:
242+
result.rgb = Multiply(Cb.rgb, Cs.rgb);
243+
break;
244+
case MixBlendMode_Screen:
245+
result.rgb = Screen(Cb.rgb, Cs.rgb);
246+
break;
247+
case MixBlendMode_Overlay:
248+
// Overlay is inverse of Hardlight
249+
result.rgb = HardLight(Cs.rgb, Cb.rgb);
250+
break;
251+
case MixBlendMode_Darken:
252+
result.rgb = min(Cs.rgb, Cb.rgb);
253+
break;
254+
case MixBlendMode_Lighten:
255+
result.rgb = max(Cs.rgb, Cb.rgb);
256+
break;
257+
case MixBlendMode_ColorDodge:
258+
result.r = ColorDodge(Cb.r, Cs.r);
259+
result.g = ColorDodge(Cb.g, Cs.g);
260+
result.b = ColorDodge(Cb.b, Cs.b);
261+
break;
262+
case MixBlendMode_ColorBurn:
263+
result.r = ColorBurn(Cb.r, Cs.r);
264+
result.g = ColorBurn(Cb.g, Cs.g);
265+
result.b = ColorBurn(Cb.b, Cs.b);
266+
break;
267+
case MixBlendMode_HardLight:
268+
result.rgb = HardLight(Cb.rgb, Cs.rgb);
269+
break;
270+
case MixBlendMode_SoftLight:
271+
result.r = SoftLight(Cb.r, Cs.r);
272+
result.g = SoftLight(Cb.g, Cs.g);
273+
result.b = SoftLight(Cb.b, Cs.b);
274+
break;
275+
case MixBlendMode_Difference:
276+
result.rgb = Difference(Cb.rgb, Cs.rgb);
277+
break;
278+
case MixBlendMode_Exclusion:
279+
result.rgb = Exclusion(Cb.rgb, Cs.rgb);
280+
break;
281+
case MixBlendMode_Hue:
282+
result.rgb = Hue(Cb.rgb, Cs.rgb);
283+
break;
284+
case MixBlendMode_Saturation:
285+
result.rgb = Saturation(Cb.rgb, Cs.rgb);
286+
break;
287+
case MixBlendMode_Color:
288+
result.rgb = Color(Cb.rgb, Cs.rgb);
289+
break;
290+
case MixBlendMode_Luminosity:
291+
result.rgb = Luminosity(Cb.rgb, Cs.rgb);
292+
break;
293+
default: break;
294+
}
281295

282-
result.rgb *= result.a;
296+
vec3 rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
297+
// simulate alpha-blending with the backdrop
298+
result = mix(vec4(original_backdrop, Cb.a), vec4(rgb, 1.0), Cs.a);
299+
}
283300

284301
return Fragment(result);
285302
}

webrender/src/batch.rs

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use scene::FilterOpHelpers;
2929
use smallvec::SmallVec;
3030
use std::{f32, i32, usize};
3131
use tiling::{RenderTargetContext};
32-
use util::{project_rect, TransformedRectKind};
32+
use util::{project_rect, MaxRect, TransformedRectKind};
3333

3434
// Special sentinel value recognized by the shader. It is considered to be
3535
// a dummy task that doesn't mask out anything.
@@ -979,10 +979,10 @@ impl AlphaBatchBuilder {
979979
// Convert all children of the 3D hierarchy root into batches.
980980
Picture3DContext::In { root_data: Some(ref list), .. } => {
981981
for child in list {
982-
let prim_instance = &picture.prim_list.prim_instances[child.anchor];
983-
let prim_info = &ctx.scratch.prim_info[prim_instance.visibility_info.0 as usize];
982+
let child_prim_instance = &picture.prim_list.prim_instances[child.anchor];
983+
let child_prim_info = &ctx.scratch.prim_info[child_prim_instance.visibility_info.0 as usize];
984984

985-
let child_pic_index = match prim_instance.kind {
985+
let child_pic_index = match child_prim_instance.kind {
986986
PrimitiveInstanceKind::Picture { pic_index, .. } => pic_index,
987987
PrimitiveInstanceKind::LineDecoration { .. } |
988988
PrimitiveInstanceKind::TextRun { .. } |
@@ -1003,14 +1003,14 @@ impl AlphaBatchBuilder {
10031003
// Get clip task, if set, for the picture primitive.
10041004
let clip_task_address = get_clip_task_address(
10051005
&ctx.scratch.clip_mask_instances,
1006-
prim_info.clip_task_index,
1006+
child_prim_info.clip_task_index,
10071007
0,
10081008
render_tasks,
10091009
).unwrap_or(OPAQUE_TASK_ADDRESS);
10101010

1011-
let prim_header = PrimitiveHeader {
1011+
let child_header = PrimitiveHeader {
10121012
local_rect: pic.local_rect,
1013-
local_clip_rect: prim_info.combined_local_clip_rect,
1013+
local_clip_rect: child_prim_info.combined_local_clip_rect,
10141014
task_address,
10151015
specific_prim_address: GpuCacheAddress::invalid(),
10161016
clip_task_address,
@@ -1037,7 +1037,7 @@ impl AlphaBatchBuilder {
10371037
gpu_cache,
10381038
);
10391039

1040-
let prim_header_index = prim_headers.push(&prim_header, z_id, [
1040+
let prim_header_index = prim_headers.push(&child_header, z_id, [
10411041
uv_rect_address.as_int(),
10421042
if raster_config.establishes_raster_root { 1 } else { 0 },
10431043
0,
@@ -1057,7 +1057,7 @@ impl AlphaBatchBuilder {
10571057

10581058
self.current_batch_list().push_single_instance(
10591059
key,
1060-
&prim_info.clip_chain.pic_clip_rect,
1060+
&child_prim_info.clip_chain.pic_clip_rect,
10611061
z_id,
10621062
PrimitiveInstanceData::from(instance),
10631063
);
@@ -1127,7 +1127,7 @@ impl AlphaBatchBuilder {
11271127
// Get the local rect of the tile.
11281128
let tile_rect = tile.local_rect;
11291129

1130-
let prim_header = PrimitiveHeader {
1130+
let tile_header = PrimitiveHeader {
11311131
local_rect: tile_rect,
11321132
local_clip_rect,
11331133
task_address,
@@ -1136,7 +1136,7 @@ impl AlphaBatchBuilder {
11361136
transform_id,
11371137
};
11381138

1139-
let prim_header_index = prim_headers.push(&prim_header, z_id, [
1139+
let prim_header_index = prim_headers.push(&tile_header, z_id, [
11401140
ShaderColorMode::Image as i32 | ((AlphaType::PremultipliedAlpha as i32) << 16),
11411141
RasterizationSpace::Local as i32,
11421142
get_shader_opacity(1.0),
@@ -1452,28 +1452,71 @@ impl AlphaBatchBuilder {
14521452
}
14531453
}
14541454
}
1455-
PictureCompositeMode::MixBlend(mode) => {
1456-
let surface = ctx.surfaces[raster_config.surface_index.0]
1455+
PictureCompositeMode::Puppet { master: Some(source) } if ctx.is_picture_surface_visible(source) => return,
1456+
PictureCompositeMode::MixBlend { mode, backdrop } if ctx.is_picture_surface_visible(backdrop) => {
1457+
let backdrop_picture = &ctx.prim_store.pictures[backdrop.0];
1458+
1459+
let source_id = ctx
1460+
.surfaces[raster_config.surface_index.0]
14571461
.surface
14581462
.as_ref()
1459-
.expect("bug: surface must be allocated by now");
1460-
let cache_task_id = surface.resolve_render_task_id();
1461-
let backdrop_id = picture.secondary_render_task_id.expect("no backdrop!?");
1463+
.expect("bug: source surface must be allocated by now")
1464+
.resolve_render_task_id();
1465+
let backdrop_surface_id = backdrop_picture.raster_config
1466+
.as_ref()
1467+
.unwrap()
1468+
.surface_index;
1469+
let backdrop_id = ctx.surfaces[backdrop_surface_id.0]
1470+
.surface
1471+
.as_ref()
1472+
.expect("bug: backdrop surface must be allocated by now")
1473+
.resolve_render_task_id();
14621474

14631475
let key = BatchKey::new(
14641476
BatchKind::Brush(
14651477
BrushBatchKind::MixBlend {
14661478
task_id,
1467-
source_id: cache_task_id,
1479+
source_id,
14681480
backdrop_id,
14691481
},
14701482
),
1471-
BlendMode::PremultipliedAlpha,
1483+
non_segmented_blend_mode,
14721484
BatchTextures::no_texture(),
14731485
);
1486+
1487+
// The trick here is to draw the picture in the space of the backdrop,
1488+
// since the source can be attached to a child spatial node.
1489+
let expanded_header = PrimitiveHeader {
1490+
local_rect: ctx.clip_scroll_tree
1491+
.map_rect_to_parent_space(
1492+
prim_header.local_rect,
1493+
picture.spatial_node_index,
1494+
backdrop_picture.spatial_node_index,
1495+
&backdrop_picture.local_rect, //Note: this shouldn't be used
1496+
)
1497+
.unwrap_or_else(LayoutRect::zero)
1498+
.union(&backdrop_picture.local_rect),
1499+
local_clip_rect: ctx.clip_scroll_tree
1500+
.map_rect_to_parent_space(
1501+
prim_header.local_clip_rect,
1502+
picture.spatial_node_index,
1503+
backdrop_picture.spatial_node_index,
1504+
&backdrop_picture.local_clip_rect, //Note: this shouldn't be used
1505+
)
1506+
.unwrap_or_else(LayoutRect::zero)
1507+
.union(&backdrop_picture.local_clip_rect),
1508+
transform_id: transforms
1509+
.get_id(
1510+
backdrop_picture.spatial_node_index,
1511+
root_spatial_node_index,
1512+
ctx.clip_scroll_tree,
1513+
),
1514+
..prim_header
1515+
};
1516+
14741517
let backdrop_task_address = render_tasks.get_task_address(backdrop_id);
1475-
let source_task_address = render_tasks.get_task_address(cache_task_id);
1476-
let prim_header_index = prim_headers.push(&prim_header, z_id, [
1518+
let source_task_address = render_tasks.get_task_address(source_id);
1519+
let prim_header_index = prim_headers.push(&expanded_header, z_id, [
14771520
mode as u32 as i32,
14781521
backdrop_task_address.0 as i32,
14791522
source_task_address.0 as i32,
@@ -1487,14 +1530,20 @@ impl AlphaBatchBuilder {
14871530
brush_flags,
14881531
user_data: 0,
14891532
};
1533+
//TODO: investigate if we can do better. We can't use the `bounding_rect`
1534+
// here because we effectively merge the call with the backdrop,
1535+
// and the instance for the backdrop isn't available here.
1536+
let conservative_bounding_rect = PictureRect::max_rect();
14901537

14911538
self.current_batch_list().push_single_instance(
14921539
key,
1493-
bounding_rect,
1540+
&conservative_bounding_rect,
14941541
z_id,
14951542
PrimitiveInstanceData::from(instance),
14961543
);
14971544
}
1545+
PictureCompositeMode::Puppet { .. } |
1546+
PictureCompositeMode::MixBlend { .. } |
14981547
PictureCompositeMode::Blit(_) => {
14991548
let surface = ctx.surfaces[raster_config.surface_index.0]
15001549
.surface

0 commit comments

Comments
 (0)