зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1519718) for performance regression (bug 1530611) on a CLOSED TREE.
Backed out changeset 9bae35dc1471 (bug 1519718) Backed out changeset 640e731ed52e (bug 1519718) --HG-- extra : rebase_source : ee2bc4503c84e709f7cd2265b4b6286960c20d4a
This commit is contained in:
Родитель
5faca7b5a1
Коммит
0e6a425f79
|
@ -6,10 +6,9 @@
|
|||
|
||||
#include shared,prim_shared,brush
|
||||
|
||||
varying vec4 vSourceAndBackdropUv;
|
||||
flat varying ivec4 vSourceUvBounds;
|
||||
flat varying ivec4 vBackdropUvBounds;
|
||||
flat varying ivec3 vOpAndLayers;
|
||||
varying vec3 vSrcUv;
|
||||
varying vec3 vBackdropUv;
|
||||
flat varying int vOp;
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
|
@ -18,10 +17,6 @@ vec2 snap_device_pos(VertexInfo vi, float device_pixel_scale) {
|
|||
return vi.world_pos.xy * device_pixel_scale / max(0.0, vi.world_pos.w) + vi.snap_offset;
|
||||
}
|
||||
|
||||
ivec4 rect_to_ivec(RectWithSize rect) {
|
||||
return ivec4(rect.p0, rect.p0 + rect.size - 1.0);
|
||||
}
|
||||
|
||||
void brush_vs(
|
||||
VertexInfo vi,
|
||||
int prim_address,
|
||||
|
@ -34,25 +29,20 @@ void brush_vs(
|
|||
vec4 unused
|
||||
) {
|
||||
vec2 snapped_device_pos = snap_device_pos(vi, pic_task.device_pixel_scale);
|
||||
vec2 texture_size = vec2(textureSize(sPrevPassColor, 0));
|
||||
vOp = user_data.x;
|
||||
|
||||
PictureTask src_task = fetch_picture_task(user_data.z);
|
||||
PictureTask backdrop_task = fetch_picture_task(user_data.y);
|
||||
|
||||
vec2 src_uv = snapped_device_pos +
|
||||
src_task.common_data.task_rect.p0 -
|
||||
src_task.content_origin;
|
||||
vec2 backdrop_uv = snapped_device_pos +
|
||||
backdrop_task.common_data.task_rect.p0 -
|
||||
backdrop_task.content_origin;
|
||||
vSrcUv = vec3(src_uv / texture_size, src_task.common_data.texture_layer_index);
|
||||
|
||||
vSourceAndBackdropUv = vec4(src_uv, backdrop_uv);
|
||||
vSourceUvBounds = rect_to_ivec(src_task.common_data.task_rect);
|
||||
vBackdropUvBounds = rect_to_ivec(backdrop_task.common_data.task_rect);
|
||||
vOpAndLayers = ivec3(
|
||||
user_data.x,
|
||||
int(src_task.common_data.texture_layer_index),
|
||||
int(backdrop_task.common_data.texture_layer_index)
|
||||
);
|
||||
RenderTaskCommonData backdrop_task = fetch_render_task_common_data(user_data.y);
|
||||
vec2 backdrop_uv = snapped_device_pos +
|
||||
backdrop_task.task_rect.p0 -
|
||||
src_task.content_origin;
|
||||
vBackdropUv = vec3(backdrop_uv / texture_size, backdrop_task.texture_layer_index);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -215,89 +205,82 @@ const int MixBlendMode_Color = 14;
|
|||
const int MixBlendMode_Luminosity = 15;
|
||||
|
||||
Fragment brush_fs() {
|
||||
vec4 Cb = textureLod(sPrevPassColor, vBackdropUv, 0.0);
|
||||
vec4 Cs = textureLod(sPrevPassColor, vSrcUv, 0.0);
|
||||
|
||||
// The mix-blend-mode functions assume no premultiplied alpha
|
||||
if (Cb.a != 0.0) {
|
||||
Cb.rgb /= Cb.a;
|
||||
}
|
||||
|
||||
if (Cs.a != 0.0) {
|
||||
Cs.rgb /= Cs.a;
|
||||
}
|
||||
|
||||
// Return yellow if none of the branches match (shouldn't happen).
|
||||
vec4 result = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
|
||||
ivec2 source_uv = ivec2(floor(vSourceAndBackdropUv.xy));
|
||||
vec4 Cs = source_uv == clamp(source_uv, vSourceUvBounds.xy, vSourceUvBounds.zw) ?
|
||||
texelFetch(sPrevPassColor, ivec3(source_uv, vOpAndLayers.y), 0) :
|
||||
vec4(0.0);
|
||||
ivec2 backdrop_uv = ivec2(floor(vSourceAndBackdropUv.zw));
|
||||
vec4 Cb = backdrop_uv == clamp(backdrop_uv, vBackdropUvBounds.xy, vBackdropUvBounds.zw) ?
|
||||
texelFetch(sPrevPassColor, ivec3(backdrop_uv, vOpAndLayers.z), 0) :
|
||||
vec4(0.0);
|
||||
|
||||
if (Cs.a == 0.0) {
|
||||
result = Cb;
|
||||
} else if (Cb.a == 0.0) {
|
||||
result = Cs;
|
||||
} else {
|
||||
vec3 original_backdrop = Cb.rgb;
|
||||
// The mix-blend-mode functions assume no premultiplied alpha
|
||||
Cs.rgb /= Cs.a;
|
||||
Cb.rgb /= Cb.a;
|
||||
|
||||
switch (vOpAndLayers.x) {
|
||||
case MixBlendMode_Multiply:
|
||||
result.rgb = Multiply(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Screen:
|
||||
result.rgb = Screen(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Overlay:
|
||||
// Overlay is inverse of Hardlight
|
||||
result.rgb = HardLight(Cs.rgb, Cb.rgb);
|
||||
break;
|
||||
case MixBlendMode_Darken:
|
||||
result.rgb = min(Cs.rgb, Cb.rgb);
|
||||
break;
|
||||
case MixBlendMode_Lighten:
|
||||
result.rgb = max(Cs.rgb, Cb.rgb);
|
||||
break;
|
||||
case MixBlendMode_ColorDodge:
|
||||
result.r = ColorDodge(Cb.r, Cs.r);
|
||||
result.g = ColorDodge(Cb.g, Cs.g);
|
||||
result.b = ColorDodge(Cb.b, Cs.b);
|
||||
break;
|
||||
case MixBlendMode_ColorBurn:
|
||||
result.r = ColorBurn(Cb.r, Cs.r);
|
||||
result.g = ColorBurn(Cb.g, Cs.g);
|
||||
result.b = ColorBurn(Cb.b, Cs.b);
|
||||
break;
|
||||
case MixBlendMode_HardLight:
|
||||
result.rgb = HardLight(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_SoftLight:
|
||||
result.r = SoftLight(Cb.r, Cs.r);
|
||||
result.g = SoftLight(Cb.g, Cs.g);
|
||||
result.b = SoftLight(Cb.b, Cs.b);
|
||||
break;
|
||||
case MixBlendMode_Difference:
|
||||
result.rgb = Difference(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Exclusion:
|
||||
result.rgb = Exclusion(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Hue:
|
||||
result.rgb = Hue(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Saturation:
|
||||
result.rgb = Saturation(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Color:
|
||||
result.rgb = Color(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Luminosity:
|
||||
result.rgb = Luminosity(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
vec3 rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
|
||||
// simulate alpha-blending with the backdrop
|
||||
result = mix(vec4(original_backdrop, Cb.a), vec4(rgb, 1.0), Cs.a);
|
||||
switch (vOp) {
|
||||
case MixBlendMode_Multiply:
|
||||
result.rgb = Multiply(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Screen:
|
||||
result.rgb = Screen(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Overlay:
|
||||
// Overlay is inverse of Hardlight
|
||||
result.rgb = HardLight(Cs.rgb, Cb.rgb);
|
||||
break;
|
||||
case MixBlendMode_Darken:
|
||||
result.rgb = min(Cs.rgb, Cb.rgb);
|
||||
break;
|
||||
case MixBlendMode_Lighten:
|
||||
result.rgb = max(Cs.rgb, Cb.rgb);
|
||||
break;
|
||||
case MixBlendMode_ColorDodge:
|
||||
result.r = ColorDodge(Cb.r, Cs.r);
|
||||
result.g = ColorDodge(Cb.g, Cs.g);
|
||||
result.b = ColorDodge(Cb.b, Cs.b);
|
||||
break;
|
||||
case MixBlendMode_ColorBurn:
|
||||
result.r = ColorBurn(Cb.r, Cs.r);
|
||||
result.g = ColorBurn(Cb.g, Cs.g);
|
||||
result.b = ColorBurn(Cb.b, Cs.b);
|
||||
break;
|
||||
case MixBlendMode_HardLight:
|
||||
result.rgb = HardLight(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_SoftLight:
|
||||
result.r = SoftLight(Cb.r, Cs.r);
|
||||
result.g = SoftLight(Cb.g, Cs.g);
|
||||
result.b = SoftLight(Cb.b, Cs.b);
|
||||
break;
|
||||
case MixBlendMode_Difference:
|
||||
result.rgb = Difference(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Exclusion:
|
||||
result.rgb = Exclusion(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Hue:
|
||||
result.rgb = Hue(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Saturation:
|
||||
result.rgb = Saturation(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Color:
|
||||
result.rgb = Color(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case MixBlendMode_Luminosity:
|
||||
result.rgb = Luminosity(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
result.rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
|
||||
result.a = Cs.a;
|
||||
|
||||
result.rgb *= result.a;
|
||||
|
||||
return Fragment(result);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,7 @@ use scene::FilterOpHelpers;
|
|||
use smallvec::SmallVec;
|
||||
use std::{f32, i32, usize};
|
||||
use tiling::{RenderTargetContext};
|
||||
use util::{project_rect, MaxRect, TransformedRectKind};
|
||||
use util::{project_rect, TransformedRectKind};
|
||||
|
||||
// Special sentinel value recognized by the shader. It is considered to be
|
||||
// a dummy task that doesn't mask out anything.
|
||||
|
@ -979,10 +979,10 @@ impl AlphaBatchBuilder {
|
|||
// Convert all children of the 3D hierarchy root into batches.
|
||||
Picture3DContext::In { root_data: Some(ref list), .. } => {
|
||||
for child in list {
|
||||
let child_prim_instance = &picture.prim_list.prim_instances[child.anchor];
|
||||
let child_prim_info = &ctx.scratch.prim_info[child_prim_instance.visibility_info.0 as usize];
|
||||
let prim_instance = &picture.prim_list.prim_instances[child.anchor];
|
||||
let prim_info = &ctx.scratch.prim_info[prim_instance.visibility_info.0 as usize];
|
||||
|
||||
let child_pic_index = match child_prim_instance.kind {
|
||||
let child_pic_index = match prim_instance.kind {
|
||||
PrimitiveInstanceKind::Picture { pic_index, .. } => pic_index,
|
||||
PrimitiveInstanceKind::LineDecoration { .. } |
|
||||
PrimitiveInstanceKind::TextRun { .. } |
|
||||
|
@ -1003,14 +1003,14 @@ impl AlphaBatchBuilder {
|
|||
// Get clip task, if set, for the picture primitive.
|
||||
let clip_task_address = get_clip_task_address(
|
||||
&ctx.scratch.clip_mask_instances,
|
||||
child_prim_info.clip_task_index,
|
||||
prim_info.clip_task_index,
|
||||
0,
|
||||
render_tasks,
|
||||
).unwrap_or(OPAQUE_TASK_ADDRESS);
|
||||
|
||||
let child_header = PrimitiveHeader {
|
||||
let prim_header = PrimitiveHeader {
|
||||
local_rect: pic.local_rect,
|
||||
local_clip_rect: child_prim_info.combined_local_clip_rect,
|
||||
local_clip_rect: prim_info.combined_local_clip_rect,
|
||||
task_address,
|
||||
specific_prim_address: GpuCacheAddress::invalid(),
|
||||
clip_task_address,
|
||||
|
@ -1037,7 +1037,7 @@ impl AlphaBatchBuilder {
|
|||
gpu_cache,
|
||||
);
|
||||
|
||||
let prim_header_index = prim_headers.push(&child_header, z_id, [
|
||||
let prim_header_index = prim_headers.push(&prim_header, z_id, [
|
||||
uv_rect_address.as_int(),
|
||||
if raster_config.establishes_raster_root { 1 } else { 0 },
|
||||
0,
|
||||
|
@ -1057,7 +1057,7 @@ impl AlphaBatchBuilder {
|
|||
|
||||
self.current_batch_list().push_single_instance(
|
||||
key,
|
||||
&child_prim_info.clip_chain.pic_clip_rect,
|
||||
&prim_info.clip_chain.pic_clip_rect,
|
||||
z_id,
|
||||
PrimitiveInstanceData::from(instance),
|
||||
);
|
||||
|
@ -1134,7 +1134,7 @@ impl AlphaBatchBuilder {
|
|||
// Get the local rect of the tile.
|
||||
let tile_rect = tile.local_rect;
|
||||
|
||||
let tile_header = PrimitiveHeader {
|
||||
let prim_header = PrimitiveHeader {
|
||||
local_rect: tile_rect,
|
||||
local_clip_rect,
|
||||
task_address,
|
||||
|
@ -1143,7 +1143,7 @@ impl AlphaBatchBuilder {
|
|||
transform_id,
|
||||
};
|
||||
|
||||
let prim_header_index = prim_headers.push(&tile_header, z_id, [
|
||||
let prim_header_index = prim_headers.push(&prim_header, z_id, [
|
||||
ShaderColorMode::Image as i32 | ((AlphaType::PremultipliedAlpha as i32) << 16),
|
||||
RasterizationSpace::Local as i32,
|
||||
get_shader_opacity(1.0),
|
||||
|
@ -1515,71 +1515,28 @@ impl AlphaBatchBuilder {
|
|||
PrimitiveInstanceData::from(instance),
|
||||
);
|
||||
}
|
||||
PictureCompositeMode::Puppet { master: Some(source) } if ctx.is_picture_surface_visible(source) => return,
|
||||
PictureCompositeMode::MixBlend { mode, backdrop } if ctx.is_picture_surface_visible(backdrop) => {
|
||||
let backdrop_picture = &ctx.prim_store.pictures[backdrop.0];
|
||||
|
||||
let source_id = ctx
|
||||
.surfaces[raster_config.surface_index.0]
|
||||
PictureCompositeMode::MixBlend(mode) => {
|
||||
let surface = ctx.surfaces[raster_config.surface_index.0]
|
||||
.surface
|
||||
.as_ref()
|
||||
.expect("bug: source surface must be allocated by now")
|
||||
.resolve_render_task_id();
|
||||
let backdrop_surface_id = backdrop_picture.raster_config
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.surface_index;
|
||||
let backdrop_id = ctx.surfaces[backdrop_surface_id.0]
|
||||
.surface
|
||||
.as_ref()
|
||||
.expect("bug: backdrop surface must be allocated by now")
|
||||
.resolve_render_task_id();
|
||||
.expect("bug: surface must be allocated by now");
|
||||
let cache_task_id = surface.resolve_render_task_id();
|
||||
let backdrop_id = picture.secondary_render_task_id.expect("no backdrop!?");
|
||||
|
||||
let key = BatchKey::new(
|
||||
BatchKind::Brush(
|
||||
BrushBatchKind::MixBlend {
|
||||
task_id,
|
||||
source_id,
|
||||
source_id: cache_task_id,
|
||||
backdrop_id,
|
||||
},
|
||||
),
|
||||
non_segmented_blend_mode,
|
||||
BlendMode::PremultipliedAlpha,
|
||||
BatchTextures::no_texture(),
|
||||
);
|
||||
|
||||
// The trick here is to draw the picture in the space of the backdrop,
|
||||
// since the source can be attached to a child spatial node.
|
||||
let expanded_header = PrimitiveHeader {
|
||||
local_rect: ctx.clip_scroll_tree
|
||||
.map_rect_to_parent_space(
|
||||
prim_header.local_rect,
|
||||
picture.spatial_node_index,
|
||||
backdrop_picture.spatial_node_index,
|
||||
&backdrop_picture.local_rect, //Note: this shouldn't be used
|
||||
)
|
||||
.unwrap_or_else(LayoutRect::zero)
|
||||
.union(&backdrop_picture.local_rect),
|
||||
local_clip_rect: ctx.clip_scroll_tree
|
||||
.map_rect_to_parent_space(
|
||||
prim_header.local_clip_rect,
|
||||
picture.spatial_node_index,
|
||||
backdrop_picture.spatial_node_index,
|
||||
&backdrop_picture.local_clip_rect, //Note: this shouldn't be used
|
||||
)
|
||||
.unwrap_or_else(LayoutRect::zero)
|
||||
.union(&backdrop_picture.local_clip_rect),
|
||||
transform_id: transforms
|
||||
.get_id(
|
||||
backdrop_picture.spatial_node_index,
|
||||
root_spatial_node_index,
|
||||
ctx.clip_scroll_tree,
|
||||
),
|
||||
..prim_header
|
||||
};
|
||||
|
||||
let backdrop_task_address = render_tasks.get_task_address(backdrop_id);
|
||||
let source_task_address = render_tasks.get_task_address(source_id);
|
||||
let prim_header_index = prim_headers.push(&expanded_header, z_id, [
|
||||
let source_task_address = render_tasks.get_task_address(cache_task_id);
|
||||
let prim_header_index = prim_headers.push(&prim_header, z_id, [
|
||||
mode as u32 as i32,
|
||||
backdrop_task_address.0 as i32,
|
||||
source_task_address.0 as i32,
|
||||
|
@ -1593,20 +1550,14 @@ impl AlphaBatchBuilder {
|
|||
brush_flags,
|
||||
user_data: 0,
|
||||
};
|
||||
//TODO: investigate if we can do better. We can't use the `bounding_rect`
|
||||
// here because we effectively merge the call with the backdrop,
|
||||
// and the instance for the backdrop isn't available here.
|
||||
let conservative_bounding_rect = PictureRect::max_rect();
|
||||
|
||||
self.current_batch_list().push_single_instance(
|
||||
key,
|
||||
&conservative_bounding_rect,
|
||||
bounding_rect,
|
||||
z_id,
|
||||
PrimitiveInstanceData::from(instance),
|
||||
);
|
||||
}
|
||||
PictureCompositeMode::Puppet { .. } |
|
||||
PictureCompositeMode::MixBlend { .. } |
|
||||
PictureCompositeMode::Blit(_) => {
|
||||
let surface = ctx.surfaces[raster_config.surface_index.0]
|
||||
.surface
|
||||
|
|
|
@ -11,7 +11,7 @@ use print_tree::{PrintableTree, PrintTree, PrintTreePrinter};
|
|||
use scene::SceneProperties;
|
||||
use spatial_node::{ScrollFrameInfo, SpatialNode, SpatialNodeType, StickyFrameInfo, ScrollFrameKind};
|
||||
use std::ops;
|
||||
use util::{project_rect, LayoutToWorldFastTransform, MatrixHelpers, ScaleOffset};
|
||||
use util::{LayoutToWorldFastTransform, MatrixHelpers, ScaleOffset};
|
||||
|
||||
pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>;
|
||||
|
||||
|
@ -211,35 +211,6 @@ impl ClipScrollTree {
|
|||
})
|
||||
}
|
||||
|
||||
/// Map a rectangle in some child space to a parent.
|
||||
/// Doesn't handle preserve-3d islands.
|
||||
pub fn map_rect_to_parent_space(
|
||||
&self,
|
||||
mut rect: LayoutRect,
|
||||
child_index: SpatialNodeIndex,
|
||||
parent_index: SpatialNodeIndex,
|
||||
parent_bounds: &LayoutRect,
|
||||
) -> Option<LayoutRect> {
|
||||
if child_index == parent_index {
|
||||
return Some(rect);
|
||||
}
|
||||
assert!(child_index.0 > parent_index.0);
|
||||
|
||||
let child = &self.spatial_nodes[child_index.0 as usize];
|
||||
let parent = &self.spatial_nodes[parent_index.0 as usize];
|
||||
|
||||
let mut coordinate_system_id = child.coordinate_system_id;
|
||||
rect = child.coordinate_system_relative_scale_offset.map_rect(&rect);
|
||||
|
||||
while coordinate_system_id != parent.coordinate_system_id {
|
||||
let coord_system = &self.coord_systems[coordinate_system_id.0 as usize];
|
||||
coordinate_system_id = coord_system.parent.expect("invalid parent!");
|
||||
rect = project_rect(&coord_system.transform, &rect, parent_bounds)?;
|
||||
}
|
||||
|
||||
Some(parent.coordinate_system_relative_scale_offset.unmap_rect(&rect))
|
||||
}
|
||||
|
||||
/// Returns true if the spatial node is the same as the parent, or is
|
||||
/// a child of the parent.
|
||||
pub fn is_same_or_child_of(
|
||||
|
|
|
@ -1326,44 +1326,23 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
None
|
||||
};
|
||||
|
||||
// Figure out if the parent is in 3D context,
|
||||
// Get the transform-style of the parent stacking context,
|
||||
// which determines if we *might* need to draw this on
|
||||
// an intermediate surface for plane splitting purposes.
|
||||
let (parent_is_3d, extra_3d_picture, backdrop_picture) = match self.sc_stack.last_mut() {
|
||||
Some(ref mut sc) if composite_ops.mix_blend_mode.is_some() => {
|
||||
// Cut the sequence of children before starting a mix-blend stacking context,
|
||||
// so that we have a source picture for applying the blending operator.
|
||||
let backdrop_picture = sc.cut_item_sequence(
|
||||
&mut self.prim_store,
|
||||
&mut self.interners,
|
||||
PictureCompositeMode::Puppet { master: None },
|
||||
Picture3DContext::Out,
|
||||
);
|
||||
(false, None, backdrop_picture)
|
||||
}
|
||||
Some(ref mut sc) if sc.is_3d() => {
|
||||
let flat_items_context_3d = match sc.context_3d {
|
||||
Picture3DContext::In { ancestor_index, .. } => Picture3DContext::In {
|
||||
root_data: None,
|
||||
ancestor_index,
|
||||
},
|
||||
Picture3DContext::Out => panic!("Unexpected out of 3D context"),
|
||||
};
|
||||
let (parent_is_3d, extra_3d_instance) = match self.sc_stack.last_mut() {
|
||||
Some(sc) => {
|
||||
// Cut the sequence of flat children before starting a child stacking context,
|
||||
// so that the relative order between them and our current SC is preserved.
|
||||
let extra_picture = sc.cut_item_sequence(
|
||||
let extra_instance = sc.cut_flat_item_sequence(
|
||||
&mut self.prim_store,
|
||||
&mut self.interners,
|
||||
PictureCompositeMode::Blit(BlitReason::PRESERVE3D),
|
||||
flat_items_context_3d,
|
||||
);
|
||||
|
||||
(true, extra_picture, None)
|
||||
}
|
||||
Some(_) | None => (false, None, None),
|
||||
(sc.is_3d(), extra_instance)
|
||||
},
|
||||
None => (false, None),
|
||||
};
|
||||
|
||||
if let Some((_picture_index, instance)) = extra_3d_picture {
|
||||
if let Some(instance) = extra_3d_instance {
|
||||
self.add_primitive_instance_to_3d_root(instance);
|
||||
}
|
||||
|
||||
|
@ -1401,13 +1380,11 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// has a clip node. In the future, we may decide during
|
||||
// prepare step to skip the intermediate surface if the
|
||||
// clip node doesn't affect the stacking context rect.
|
||||
let mut blit_reason = BlitReason::empty();
|
||||
if clip_chain_id != ClipChainId::NONE {
|
||||
blit_reason |= BlitReason::CLIP
|
||||
}
|
||||
if participating_in_3d_context {
|
||||
blit_reason |= BlitReason::PRESERVE3D;
|
||||
}
|
||||
let blit_reason = if clip_chain_id == ClipChainId::NONE {
|
||||
BlitReason::empty()
|
||||
} else {
|
||||
BlitReason::CLIP
|
||||
};
|
||||
|
||||
// Push the SC onto the stack, so we know how to handle things in
|
||||
// pop_stacking_context.
|
||||
|
@ -1420,7 +1397,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
clip_chain_id,
|
||||
frame_output_pipeline_id,
|
||||
composite_ops,
|
||||
backdrop_picture,
|
||||
blit_reason,
|
||||
transform_style,
|
||||
context_3d,
|
||||
|
@ -1440,22 +1416,26 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// (b) It's useful for the initial version of picture caching in gecko, by enabling
|
||||
// is to just look for interesting scroll roots on the root stacking context,
|
||||
// without having to consider cuts at stacking context boundaries.
|
||||
if let Some(parent_sc) = self.sc_stack.last_mut() {
|
||||
if stacking_context.is_redundant(
|
||||
parent_sc,
|
||||
self.clip_scroll_tree,
|
||||
) {
|
||||
// If the parent context primitives list is empty, it's faster
|
||||
// to assign the storage of the popped context instead of paying
|
||||
// the copying cost for extend.
|
||||
if parent_sc.primitives.is_empty() {
|
||||
parent_sc.primitives = stacking_context.primitives;
|
||||
} else {
|
||||
parent_sc.primitives.extend(stacking_context.primitives);
|
||||
let parent_is_empty = match self.sc_stack.last_mut() {
|
||||
Some(parent_sc) => {
|
||||
if stacking_context.is_redundant(
|
||||
parent_sc,
|
||||
self.clip_scroll_tree,
|
||||
) {
|
||||
// If the parent context primitives list is empty, it's faster
|
||||
// to assign the storage of the popped context instead of paying
|
||||
// the copying cost for extend.
|
||||
if parent_sc.primitives.is_empty() {
|
||||
parent_sc.primitives = stacking_context.primitives;
|
||||
} else {
|
||||
parent_sc.primitives.extend(stacking_context.primitives);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
parent_sc.primitives.is_empty()
|
||||
},
|
||||
None => true,
|
||||
};
|
||||
|
||||
if stacking_context.create_tile_cache {
|
||||
self.setup_picture_caching(
|
||||
|
@ -1471,16 +1451,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// to correctly handle some CSS cases (see #1957).
|
||||
let max_clip = LayoutRect::max_rect();
|
||||
|
||||
let leaf_composite_mode = if stacking_context.blit_reason.is_empty() {
|
||||
// By default, this picture will be collapsed into
|
||||
// the owning target.
|
||||
None
|
||||
} else {
|
||||
// Add a dummy composite filter if the SC has to be isolated.
|
||||
Some(PictureCompositeMode::Blit(stacking_context.blit_reason))
|
||||
};
|
||||
|
||||
let leaf_context_3d = match stacking_context.context_3d {
|
||||
let (leaf_context_3d, leaf_composite_mode, leaf_output_pipeline_id) = match stacking_context.context_3d {
|
||||
// TODO(gw): For now, as soon as this picture is in
|
||||
// a 3D context, we draw it to an intermediate
|
||||
// surface and apply plane splitting. However,
|
||||
|
@ -1488,17 +1459,25 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// During culling, we can check if there is actually
|
||||
// perspective present, and skip the plane splitting
|
||||
// completely when that is not the case.
|
||||
Picture3DContext::In { ancestor_index, .. } => {
|
||||
assert!(!leaf_composite_mode.is_none());
|
||||
Picture3DContext::In { root_data: None, ancestor_index }
|
||||
}
|
||||
Picture3DContext::Out => Picture3DContext::Out,
|
||||
Picture3DContext::In { ancestor_index, .. } => (
|
||||
Picture3DContext::In { root_data: None, ancestor_index },
|
||||
Some(PictureCompositeMode::Blit(BlitReason::PRESERVE3D | stacking_context.blit_reason)),
|
||||
None,
|
||||
),
|
||||
Picture3DContext::Out => (
|
||||
Picture3DContext::Out,
|
||||
if stacking_context.blit_reason.is_empty() {
|
||||
// By default, this picture will be collapsed into
|
||||
// the owning target.
|
||||
None
|
||||
} else {
|
||||
// Add a dummy composite filter if the SC has to be isolated.
|
||||
Some(PictureCompositeMode::Blit(stacking_context.blit_reason))
|
||||
},
|
||||
stacking_context.frame_output_pipeline_id
|
||||
),
|
||||
};
|
||||
|
||||
let leaf_prim_list = PrimitiveList::new(
|
||||
stacking_context.primitives,
|
||||
&self.interners,
|
||||
);
|
||||
// Add picture for this actual stacking context contents to render into.
|
||||
let leaf_pic_index = PictureIndex(self.prim_store.pictures
|
||||
.alloc()
|
||||
|
@ -1506,10 +1485,13 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
leaf_composite_mode,
|
||||
leaf_context_3d,
|
||||
stacking_context.pipeline_id,
|
||||
stacking_context.frame_output_pipeline_id,
|
||||
leaf_output_pipeline_id,
|
||||
true,
|
||||
stacking_context.requested_raster_space,
|
||||
leaf_prim_list,
|
||||
PrimitiveList::new(
|
||||
stacking_context.primitives,
|
||||
&self.interners,
|
||||
),
|
||||
stacking_context.spatial_node_index,
|
||||
max_clip,
|
||||
None,
|
||||
|
@ -1650,7 +1632,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
self.prim_store.optimize_picture_if_possible(current_pic_index);
|
||||
}
|
||||
|
||||
// Same for mix-blend-mode, except we can skip if the backdrop doesn't have any primitives.
|
||||
// Same for mix-blend-mode, except we can skip if this primitive is the first in the parent
|
||||
// stacking context.
|
||||
// From https://drafts.fxtf.org/compositing-1/#generalformula, the formula for blending is:
|
||||
// Cs = (1 - ab) x Cs + ab x Blend(Cb, Cs)
|
||||
// where
|
||||
|
@ -1661,15 +1644,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// If we're the first primitive within a stacking context, then we can guarantee that the
|
||||
// backdrop alpha will be 0, and then the blend equation collapses to just
|
||||
// Cs = Cs, and the blend mode isn't taken into account at all.
|
||||
if let (Some(mode), Some((backdrop, backdrop_instance))) = (stacking_context.composite_ops.mix_blend_mode, stacking_context.backdrop_picture.take()) {
|
||||
let composite_mode = Some(PictureCompositeMode::MixBlend { mode, backdrop });
|
||||
|
||||
// We need to make the backdrop picture to be at the same level as the content,
|
||||
// to be available as a source for composition...
|
||||
if let Some(parent_sc) = self.sc_stack.last_mut() {
|
||||
// Not actually rendered, due to `PictureCompositeMode::Puppet`, unless the blend picture is culled.
|
||||
parent_sc.primitives.push(backdrop_instance);
|
||||
}
|
||||
let has_mix_blend = if let (Some(mix_blend_mode), false) = (stacking_context.composite_ops.mix_blend_mode, parent_is_empty) {
|
||||
let composite_mode = Some(PictureCompositeMode::MixBlend(mix_blend_mode));
|
||||
|
||||
let blend_pic_index = PictureIndex(self.prim_store.pictures
|
||||
.alloc()
|
||||
|
@ -1691,14 +1667,9 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
))
|
||||
);
|
||||
|
||||
// Assoiate the backdrop picture with the blend.
|
||||
self.prim_store.pictures[backdrop.0].requested_composite_mode = Some(PictureCompositeMode::Puppet {
|
||||
master: Some(blend_pic_index),
|
||||
});
|
||||
|
||||
current_pic_index = blend_pic_index;
|
||||
cur_instance = create_prim_instance(
|
||||
current_pic_index,
|
||||
blend_pic_index,
|
||||
composite_mode.into(),
|
||||
stacking_context.is_backface_visible,
|
||||
ClipChainId::NONE,
|
||||
|
@ -1707,9 +1678,12 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
);
|
||||
|
||||
if cur_instance.is_chased() {
|
||||
println!("\tis a mix-blend picture for a stacking context with {:?}", mode);
|
||||
println!("\tis a mix-blend picture for a stacking context with {:?}", mix_blend_mode);
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Set the stacking context clip on the outermost picture in the chain,
|
||||
// unless we already set it on the leaf picture.
|
||||
|
@ -1724,6 +1698,13 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
}
|
||||
// Regular parenting path
|
||||
Some(ref mut parent_sc) => {
|
||||
// If we have a mix-blend-mode, the stacking context needs to be isolated
|
||||
// to blend correctly as per the CSS spec.
|
||||
// If not already isolated for some other reason,
|
||||
// make this picture as isolated.
|
||||
if has_mix_blend {
|
||||
parent_sc.blit_reason |= BlitReason::ISOLATE;
|
||||
}
|
||||
parent_sc.primitives.push(cur_instance);
|
||||
None
|
||||
}
|
||||
|
@ -2713,9 +2694,6 @@ struct FlattenedStackingContext {
|
|||
/// stacking context.
|
||||
composite_ops: CompositeOps,
|
||||
|
||||
/// For a mix-blend stacking context, specify the picture index for backdrop.
|
||||
backdrop_picture: Option<(PictureIndex, PrimitiveInstance)>,
|
||||
|
||||
/// Bitfield of reasons this stacking context needs to
|
||||
/// be an offscreen surface.
|
||||
blit_reason: BlitReason,
|
||||
|
@ -2758,8 +2736,7 @@ impl FlattenedStackingContext {
|
|||
// We can skip mix-blend modes if they are the first primitive in a stacking context,
|
||||
// see pop_stacking_context for a full explanation.
|
||||
if !self.composite_ops.mix_blend_mode.is_none() &&
|
||||
!self.backdrop_picture.is_none()
|
||||
{
|
||||
!parent.primitives.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2797,24 +2774,29 @@ impl FlattenedStackingContext {
|
|||
true
|
||||
}
|
||||
|
||||
/// Cut the sequence of the immediate children of a stacking context
|
||||
/// For a Preserve3D context, cut the sequence of the immediate flat children
|
||||
/// recorded so far and generate a picture from them.
|
||||
fn cut_item_sequence(
|
||||
pub fn cut_flat_item_sequence(
|
||||
&mut self,
|
||||
prim_store: &mut PrimitiveStore,
|
||||
interners: &mut Interners,
|
||||
composite_mode: PictureCompositeMode,
|
||||
context_3d: Picture3DContext<OrderedPictureChild>,
|
||||
) -> Option<(PictureIndex, PrimitiveInstance)> {
|
||||
if self.primitives.is_empty() {
|
||||
) -> Option<PrimitiveInstance> {
|
||||
if !self.is_3d() || self.primitives.is_empty() {
|
||||
return None
|
||||
}
|
||||
let flat_items_context_3d = match self.context_3d {
|
||||
Picture3DContext::In { ancestor_index, .. } => Picture3DContext::In {
|
||||
root_data: None,
|
||||
ancestor_index,
|
||||
},
|
||||
Picture3DContext::Out => panic!("Unexpected out of 3D context"),
|
||||
};
|
||||
|
||||
let pic_index = PictureIndex(prim_store.pictures
|
||||
.alloc()
|
||||
.init(PicturePrimitive::new_image(
|
||||
Some(composite_mode),
|
||||
context_3d,
|
||||
Some(PictureCompositeMode::Blit(BlitReason::PRESERVE3D)),
|
||||
flat_items_context_3d,
|
||||
self.pipeline_id,
|
||||
None,
|
||||
true,
|
||||
|
@ -2839,7 +2821,7 @@ impl FlattenedStackingContext {
|
|||
interners,
|
||||
);
|
||||
|
||||
Some((pic_index, prim_instance))
|
||||
Some(prim_instance)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1873,10 +1873,12 @@ bitflags! {
|
|||
/// A set of flags describing why a picture may need a backing surface.
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
pub struct BlitReason: u32 {
|
||||
/// Mix-blend-mode on a child that requires isolation.
|
||||
const ISOLATE = 1;
|
||||
/// Clip node that _might_ require a surface.
|
||||
const CLIP = 1;
|
||||
const CLIP = 2;
|
||||
/// Preserve-3D requires a surface for plane-splitting.
|
||||
const PRESERVE3D = 2;
|
||||
const PRESERVE3D = 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1886,20 +1888,8 @@ bitflags! {
|
|||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
pub enum PictureCompositeMode {
|
||||
/// Don't composite this picture in a standard way,
|
||||
/// can be used for pictures that need to be isolated but used
|
||||
/// manually, e.g. for the backdrop of mix-blend pictures.
|
||||
Puppet {
|
||||
/// The master picture that actually handles compositing
|
||||
/// of this one. If that picture turns out to be invisible,
|
||||
/// the puppet mode becomes a regular blit.
|
||||
master: Option<PictureIndex>,
|
||||
},
|
||||
/// Apply CSS mix-blend-mode effect.
|
||||
MixBlend {
|
||||
mode: MixBlendMode,
|
||||
backdrop: PictureIndex,
|
||||
},
|
||||
MixBlend(MixBlendMode),
|
||||
/// Apply a CSS filter (except component transfer).
|
||||
Filter(FilterOp),
|
||||
/// Apply a component transfer filter.
|
||||
|
@ -3081,6 +3071,37 @@ impl PicturePrimitive {
|
|||
|
||||
PictureSurface::RenderTask(render_task_id)
|
||||
}
|
||||
PictureCompositeMode::MixBlend(..) => {
|
||||
let uv_rect_kind = calculate_uv_rect_kind(
|
||||
&pic_rect,
|
||||
&transform,
|
||||
&clipped,
|
||||
device_pixel_scale,
|
||||
true,
|
||||
);
|
||||
|
||||
let picture_task = RenderTask::new_picture(
|
||||
RenderTaskLocation::Dynamic(None, clipped.size),
|
||||
unclipped.size,
|
||||
pic_index,
|
||||
clipped.origin,
|
||||
child_tasks,
|
||||
uv_rect_kind,
|
||||
pic_context.raster_spatial_node_index,
|
||||
device_pixel_scale,
|
||||
);
|
||||
|
||||
let readback_task_id = frame_state.render_tasks.add(
|
||||
RenderTask::new_readback(clipped)
|
||||
);
|
||||
|
||||
self.secondary_render_task_id = Some(readback_task_id);
|
||||
surfaces[surface_index.0].tasks.push(readback_task_id);
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||
surfaces[surface_index.0].tasks.push(render_task_id);
|
||||
PictureSurface::RenderTask(render_task_id)
|
||||
}
|
||||
PictureCompositeMode::Filter(filter) => {
|
||||
if let FilterOp::ColorMatrix(m) = filter {
|
||||
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
|
||||
|
@ -3140,13 +3161,11 @@ impl PicturePrimitive {
|
|||
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
|
||||
PictureSurface::RenderTask(render_task_id)
|
||||
}
|
||||
PictureCompositeMode::Puppet { .. } |
|
||||
PictureCompositeMode::MixBlend { .. } |
|
||||
PictureCompositeMode::Blit(_) => {
|
||||
// The SplitComposite shader used for 3d contexts doesn't snap
|
||||
// to pixels, so we shouldn't snap our uv coordinates either.
|
||||
let supports_snapping = match self.context_3d {
|
||||
Picture3DContext::In { .. } => false,
|
||||
Picture3DContext::In{ .. } => false,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ pub enum PictureCompositeKey {
|
|||
impl From<Option<PictureCompositeMode>> for PictureCompositeKey {
|
||||
fn from(mode: Option<PictureCompositeMode>) -> Self {
|
||||
match mode {
|
||||
Some(PictureCompositeMode::MixBlend { mode, .. }) => {
|
||||
Some(PictureCompositeMode::MixBlend(mode)) => {
|
||||
match mode {
|
||||
MixBlendMode::Normal => PictureCompositeKey::Identity,
|
||||
MixBlendMode::Multiply => PictureCompositeKey::Multiply,
|
||||
|
@ -123,7 +123,6 @@ impl From<Option<PictureCompositeMode>> for PictureCompositeKey {
|
|||
Some(PictureCompositeMode::ComponentTransferFilter(handle)) => {
|
||||
PictureCompositeKey::ComponentTransfer(handle.uid())
|
||||
}
|
||||
Some(PictureCompositeMode::Puppet { .. }) |
|
||||
Some(PictureCompositeMode::Blit(_)) |
|
||||
Some(PictureCompositeMode::TileCache { .. }) |
|
||||
None => {
|
||||
|
|
|
@ -407,6 +407,7 @@ pub enum RenderTaskKind {
|
|||
HorizontalBlur(BlurTask),
|
||||
#[allow(dead_code)]
|
||||
Glyph(GlyphTask),
|
||||
Readback(DeviceIntRect),
|
||||
Scaling(ScalingTask),
|
||||
Blit(BlitTask),
|
||||
Border(BorderTask),
|
||||
|
@ -495,6 +496,15 @@ impl RenderTask {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_readback(screen_rect: DeviceIntRect) -> Self {
|
||||
RenderTask::with_dynamic_location(
|
||||
screen_rect.size,
|
||||
Vec::new(),
|
||||
RenderTaskKind::Readback(screen_rect),
|
||||
ClearMode::Transparent,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_blit(
|
||||
size: DeviceIntSize,
|
||||
source: BlitSource,
|
||||
|
@ -845,7 +855,8 @@ impl RenderTask {
|
|||
|
||||
fn uv_rect_kind(&self) -> UvRectKind {
|
||||
match self.kind {
|
||||
RenderTaskKind::CacheMask(..) => {
|
||||
RenderTaskKind::CacheMask(..) |
|
||||
RenderTaskKind::Readback(..) => {
|
||||
unreachable!("bug: unexpected render task");
|
||||
}
|
||||
|
||||
|
@ -918,6 +929,7 @@ impl RenderTask {
|
|||
RenderTaskKind::Glyph(_) => {
|
||||
[0.0, 1.0, 0.0]
|
||||
}
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) |
|
||||
RenderTaskKind::Border(..) |
|
||||
RenderTaskKind::LineDecoration(..) |
|
||||
|
@ -958,6 +970,7 @@ impl RenderTask {
|
|||
gpu_cache.get_address(&info.uv_rect_handle)
|
||||
}
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) |
|
||||
RenderTaskKind::Blit(..) |
|
||||
RenderTaskKind::Border(..) |
|
||||
|
@ -1010,6 +1023,8 @@ impl RenderTask {
|
|||
|
||||
pub fn target_kind(&self) -> RenderTargetKind {
|
||||
match self.kind {
|
||||
RenderTaskKind::Readback(..) => RenderTargetKind::Color,
|
||||
|
||||
RenderTaskKind::LineDecoration(..) => RenderTargetKind::Color,
|
||||
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
|
@ -1062,6 +1077,7 @@ impl RenderTask {
|
|||
RenderTaskKind::Picture(ref mut info) => {
|
||||
(&mut info.uv_rect_handle, info.uv_rect_kind)
|
||||
}
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) |
|
||||
RenderTaskKind::Blit(..) |
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
|
@ -1112,6 +1128,10 @@ impl RenderTask {
|
|||
pt.new_level("HorizontalBlur".to_owned());
|
||||
task.print_with(pt);
|
||||
}
|
||||
RenderTaskKind::Readback(ref rect) => {
|
||||
pt.new_level("Readback".to_owned());
|
||||
pt.add_item(format!("rect: {:?}", rect));
|
||||
}
|
||||
RenderTaskKind::Scaling(ref kind) => {
|
||||
pt.new_level("Scaling".to_owned());
|
||||
pt.add_item(format!("kind: {:?}", kind));
|
||||
|
|
|
@ -82,7 +82,7 @@ use render_backend::{FrameId, RenderBackend};
|
|||
use scene_builder::{SceneBuilder, LowPrioritySceneBuilder};
|
||||
use shade::{Shaders, WrShaders};
|
||||
use smallvec::SmallVec;
|
||||
use render_task::RenderTaskTree;
|
||||
use render_task::{RenderTask, RenderTaskKind, RenderTaskTree};
|
||||
use resource_cache::ResourceCache;
|
||||
use util::drain_filter;
|
||||
|
||||
|
@ -2339,6 +2339,11 @@ impl Renderer {
|
|||
"Scalings",
|
||||
target.scalings.len(),
|
||||
);
|
||||
debug_target.add(
|
||||
debug_server::BatchKind::Cache,
|
||||
"Readbacks",
|
||||
target.readbacks.len(),
|
||||
);
|
||||
debug_target.add(
|
||||
debug_server::BatchKind::Cache,
|
||||
"Vertical Blur",
|
||||
|
@ -3080,6 +3085,74 @@ impl Renderer {
|
|||
self.profile_counters.vertices.add(6 * data.len());
|
||||
}
|
||||
|
||||
fn handle_readback_composite(
|
||||
&mut self,
|
||||
draw_target: DrawTarget,
|
||||
uses_scissor: bool,
|
||||
source: &RenderTask,
|
||||
backdrop: &RenderTask,
|
||||
readback: &RenderTask,
|
||||
) {
|
||||
if uses_scissor {
|
||||
self.device.disable_scissor();
|
||||
}
|
||||
|
||||
let cache_texture = self.texture_resolver
|
||||
.resolve(&TextureSource::PrevPassColor)
|
||||
.unwrap();
|
||||
|
||||
// Before submitting the composite batch, do the
|
||||
// framebuffer readbacks that are needed for each
|
||||
// composite operation in this batch.
|
||||
let (readback_rect, readback_layer) = readback.get_target_rect();
|
||||
let (backdrop_rect, _) = backdrop.get_target_rect();
|
||||
let backdrop_screen_origin = match backdrop.kind {
|
||||
RenderTaskKind::Picture(ref task_info) => task_info.content_origin,
|
||||
_ => panic!("bug: composite on non-picture?"),
|
||||
};
|
||||
let source_screen_origin = match source.kind {
|
||||
RenderTaskKind::Picture(ref task_info) => task_info.content_origin,
|
||||
_ => panic!("bug: composite on non-picture?"),
|
||||
};
|
||||
|
||||
// Bind the FBO to blit the backdrop to.
|
||||
// Called per-instance in case the layer (and therefore FBO)
|
||||
// changes. The device will skip the GL call if the requested
|
||||
// target is already bound.
|
||||
let cache_draw_target = DrawTarget::Texture {
|
||||
texture: cache_texture,
|
||||
layer: readback_layer.0 as usize,
|
||||
with_depth: false,
|
||||
};
|
||||
self.device.bind_draw_target(cache_draw_target);
|
||||
|
||||
let mut src = DeviceIntRect::new(
|
||||
source_screen_origin + (backdrop_rect.origin - backdrop_screen_origin),
|
||||
readback_rect.size,
|
||||
);
|
||||
let mut dest = readback_rect.to_i32();
|
||||
|
||||
// Need to invert the y coordinates and flip the image vertically when
|
||||
// reading back from the framebuffer.
|
||||
if draw_target.is_default() {
|
||||
src.origin.y = draw_target.dimensions().height as i32 - src.size.height - src.origin.y;
|
||||
dest.origin.y += dest.size.height;
|
||||
dest.size.height = -dest.size.height;
|
||||
}
|
||||
|
||||
self.device.bind_read_target(draw_target.into());
|
||||
self.device.blit_render_target(src, dest, TextureFilter::Linear);
|
||||
|
||||
// Restore draw target to current pass render target + layer, and reset
|
||||
// the read target.
|
||||
self.device.bind_draw_target(draw_target);
|
||||
self.device.reset_read_target();
|
||||
|
||||
if uses_scissor {
|
||||
self.device.enable_scissor();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: make this nicer. Currently we can't accept `&mut self` because the `DrawTarget` parameter
|
||||
// needs to borrow self.texture_resolver
|
||||
fn handle_blits(
|
||||
|
@ -3411,6 +3484,20 @@ impl Renderer {
|
|||
prev_blend_mode = batch.key.blend_mode;
|
||||
}
|
||||
|
||||
// Handle special case readback for composites.
|
||||
if let BatchKind::Brush(BrushBatchKind::MixBlend { task_id, source_id, backdrop_id }) = batch.key.kind {
|
||||
// composites can't be grouped together because
|
||||
// they may overlap and affect each other.
|
||||
debug_assert_eq!(batch.instances.len(), 1);
|
||||
self.handle_readback_composite(
|
||||
draw_target,
|
||||
uses_scissor,
|
||||
&render_tasks[source_id],
|
||||
&render_tasks[task_id],
|
||||
&render_tasks[backdrop_id],
|
||||
);
|
||||
}
|
||||
|
||||
let _timer = self.gpu_profile.start_timer(batch.key.kind.sampler_tag());
|
||||
|
||||
iterate_regions(
|
||||
|
|
|
@ -20,7 +20,7 @@ use internal_types::{CacheTextureId, FastHashMap, SavedTargetIndex, TextureSourc
|
|||
#[cfg(feature = "pathfinder")]
|
||||
use pathfinder_partitioner::mesh::Mesh;
|
||||
use picture::{RecordedDirtyRegion, SurfaceInfo};
|
||||
use prim_store::{PictureIndex, PrimitiveStore, DeferredResolve, PrimitiveScratchBuffer};
|
||||
use prim_store::{PrimitiveStore, DeferredResolve, PrimitiveScratchBuffer};
|
||||
use profiler::FrameProfileCounters;
|
||||
use render_backend::{DataStores, FrameId};
|
||||
use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
|
||||
|
@ -62,18 +62,6 @@ pub struct RenderTargetContext<'a, 'rc> {
|
|||
pub globals: &'a FrameGlobalResources,
|
||||
}
|
||||
|
||||
impl<'a, 'rc> RenderTargetContext<'a, 'rc> {
|
||||
/// Returns true if a picture has a surface that is visible.
|
||||
pub fn is_picture_surface_visible(&self, index: PictureIndex) -> bool {
|
||||
match self.prim_store.pictures[index.0].raster_config {
|
||||
Some(ref raster_config) => {
|
||||
self.surfaces[raster_config.surface_index.0].surface.is_some()
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a number of rendering operations on a surface.
|
||||
///
|
||||
/// In graphics parlance, a "render target" usually means "a surface (texture or
|
||||
|
@ -360,6 +348,7 @@ pub struct ColorRenderTarget {
|
|||
// List of blur operations to apply for this render target.
|
||||
pub vertical_blurs: Vec<BlurInstance>,
|
||||
pub horizontal_blurs: Vec<BlurInstance>,
|
||||
pub readbacks: Vec<DeviceIntRect>,
|
||||
pub scalings: Vec<ScalingInstance>,
|
||||
pub blits: Vec<BlitJob>,
|
||||
// List of frame buffer outputs for this render target.
|
||||
|
@ -381,6 +370,7 @@ impl RenderTarget for ColorRenderTarget {
|
|||
alpha_batch_containers: Vec::new(),
|
||||
vertical_blurs: Vec::new(),
|
||||
horizontal_blurs: Vec::new(),
|
||||
readbacks: Vec::new(),
|
||||
scalings: Vec::new(),
|
||||
blits: Vec::new(),
|
||||
outputs: Vec::new(),
|
||||
|
@ -512,6 +502,9 @@ impl RenderTarget for ColorRenderTarget {
|
|||
// FIXME(pcwalton): Support color glyphs.
|
||||
panic!("Glyphs should not be added to color target!");
|
||||
}
|
||||
RenderTaskKind::Readback(device_rect) => {
|
||||
self.readbacks.push(device_rect);
|
||||
}
|
||||
RenderTaskKind::Scaling(..) => {
|
||||
self.scalings.push(ScalingInstance {
|
||||
task_address: render_tasks.get_task_address(task_id),
|
||||
|
@ -644,6 +637,7 @@ impl RenderTarget for AlphaRenderTarget {
|
|||
}
|
||||
|
||||
match task.kind {
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Picture(..) |
|
||||
RenderTaskKind::Blit(..) |
|
||||
RenderTaskKind::Border(..) |
|
||||
|
@ -825,6 +819,7 @@ impl TextureCacheRenderTarget {
|
|||
RenderTaskKind::Picture(..) |
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
RenderTaskKind::CacheMask(..) |
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) => {
|
||||
panic!("BUG: unexpected task kind for texture cache target");
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
# test that we handle the backdrop size to be smaller than the source
|
||||
---
|
||||
root:
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [25, 25, 50, 50]
|
||||
color: green
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: [0, 255, 0]
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 100, 100]
|
||||
mix-blend-mode: multiply
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: green
|
||||
color: [255, 128, 0]
|
||||
|
|
|
@ -8,6 +8,10 @@ root:
|
|||
bounds: [0, 0, 100, 100]
|
||||
mix-blend-mode: multiply
|
||||
items:
|
||||
- type: rect
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: [255, 128, 0]
|
||||
mix-blend-mode: multiply
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: [255, 128, 0]
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
---
|
||||
root:
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: [0, 255, 0]
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 100, 100]
|
||||
mix-blend-mode: multiply
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 100, 100]
|
||||
mix-blend-mode: multiply
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: [255, 128, 0]
|
|
@ -1,7 +1,6 @@
|
|||
== multiply.yaml multiply-ref.yaml
|
||||
== multiply-2.yaml multiply-ref.yaml
|
||||
== multiply-3.yaml multiply-3-ref.yaml
|
||||
== color_targets(2) alpha_targets(0) multiply-4.yaml multiply-3-ref.yaml
|
||||
== multiply-2.yaml multiply-2-ref.yaml
|
||||
== color_targets(3) alpha_targets(0) multiply-3.yaml multiply-2-ref.yaml
|
||||
== difference.yaml difference-ref.yaml
|
||||
fuzzy(1,10000) == difference-transparent.yaml difference-transparent-ref.yaml
|
||||
== darken.yaml darken-ref.yaml
|
||||
|
@ -23,4 +22,3 @@ fuzzy(1,2502) == transparent-composite-1.yaml transparent-composite-1-ref.yaml
|
|||
fuzzy(1,2502) == transparent-composite-2.yaml transparent-composite-2-ref.yaml
|
||||
|
||||
== multi-mix-blend-mode.yaml multi-mix-blend-mode-ref.yaml
|
||||
fuzzy(50,8) == transform-source.yaml transform-source-ref.yaml
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
root:
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 0, 0]
|
||||
transform: rotate-z(60)
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [25, -100, 150, 150]
|
||||
color: blue
|
||||
- type: rect
|
||||
bounds: [25, 25, 100, 100]
|
||||
color: black
|
|
@ -1,15 +0,0 @@
|
|||
# test that we handle the source stacking context being transformed
|
||||
---
|
||||
root:
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [25, 25, 100, 100]
|
||||
color: green
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 0, 0]
|
||||
mix-blend-mode: multiply
|
||||
transform: rotate-z(60)
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [25, -100, 150, 150]
|
||||
color: blue
|
|
@ -549,10 +549,9 @@ fn render<'a>(
|
|||
subargs: &clap::ArgMatches<'a>,
|
||||
) {
|
||||
let input_path = subargs.value_of("INPUT").map(PathBuf::from).unwrap();
|
||||
let mut show_stats = false;
|
||||
|
||||
// If the input is a directory, we are looking at a capture.
|
||||
let mut thing = if input_path.is_dir() {
|
||||
let mut thing = if input_path.as_path().is_dir() {
|
||||
let mut documents = wrench.api.load_capture(input_path);
|
||||
println!("loaded {:?}", documents.iter().map(|cd| cd.document_id).collect::<Vec<_>>());
|
||||
let captured = documents.swap_remove(0);
|
||||
|
@ -567,7 +566,6 @@ fn render<'a>(
|
|||
.expect("Tried to render with an unknown file type.")
|
||||
.to_str()
|
||||
.expect("Tried to render with an unknown file type.");
|
||||
show_stats = true; // show when invoked on single files
|
||||
|
||||
match extension {
|
||||
"yaml" => Box::new(YamlFrameReader::new_from_args(subargs)) as Box<WrenchThing>,
|
||||
|
@ -774,14 +772,9 @@ fn render<'a>(
|
|||
wrench.show_onscreen_help();
|
||||
}
|
||||
|
||||
let results = wrench.render();
|
||||
wrench.render();
|
||||
window.swap_buffers();
|
||||
|
||||
if show_stats {
|
||||
show_stats = false;
|
||||
println!("{:#?}", results.stats);
|
||||
}
|
||||
|
||||
if do_loop {
|
||||
thing.next_frame();
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
== blend-canvas.html blend-canvas-ref.html
|
||||
== blend-constant-background-color.html blend-constant-background-color-ref.html
|
||||
fuzzy-if(webrender,1-3,1291-7888) == blend-gradient-background-color.html blend-gradient-background-color-ref.html
|
||||
fuzzy-if(webrender,1-3,1313-7888) == blend-gradient-background-color.html blend-gradient-background-color-ref.html
|
||||
== blend-image.html blend-image-ref.html
|
||||
== blend-difference-stacking.html blend-difference-stacking-ref.html
|
||||
|
||||
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-1,0-10000) fuzzy-if(skiaContent,0-1,0-30000) == background-blending-alpha.html background-blending-alpha-ref.html
|
||||
fuzzy-if(webrender,1-3,1291-7888) == background-blending-gradient-color.html background-blending-gradient-color-ref.html
|
||||
fuzzy-if(webrender,1-3,1313-7888) == background-blending-gradient-color.html background-blending-gradient-color-ref.html
|
||||
fuzzy-if(azureSkiaGL,0-3,0-7597) fuzzy-if(cocoaWidget,0-3,0-7597) fuzzy-if(d2d,0-1,0-3800) fuzzy-if(d3d11,0-1,0-4200) fuzzy-if(skiaContent,0-2,0-9450) fuzzy-if(webrender,1-5,3938-23925) == background-blending-gradient-gradient.html background-blending-gradient-gradient-ref.html
|
||||
fuzzy-if(azureSkiaGL,0-2,0-7174) fuzzy-if(webrender,1-3,1288-7888) == background-blending-gradient-image.html background-blending-gradient-color-ref.html
|
||||
fuzzy-if(azureSkia||d2d||gtkWidget,0-1,0-10000) == background-blending-image-color-jpg.html background-blending-image-color-ref.html
|
||||
|
|
Загрузка…
Ссылка в новой задаче