зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1519718 - Revert the mix-blend rewrite r=jrmuizel
https://phabricator.services.mozilla.com/D20608 Caused problems in Servo https://github.com/servo/servo/pull/22973 and MotionMark - https://bugzilla.mozilla.org/show_bug.cgi?id=1519718 Differential Revision: https://phabricator.services.mozilla.com/D23318 --HG-- rename : gfx/wr/wrench/reftests/blend/multiply-3-ref.yaml => gfx/wr/wrench/reftests/blend/multiply-2-ref.yaml extra : moz-landing-system : lando
This commit is contained in:
Родитель
6e3dc3044f
Коммит
97423c7bca
|
@ -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,29 +205,22 @@ 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) {
|
||||
switch (vOp) {
|
||||
case MixBlendMode_Multiply:
|
||||
result.rgb = Multiply(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
|
@ -293,10 +276,10 @@ Fragment brush_fs() {
|
|||
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);
|
||||
}
|
||||
result.rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
|
||||
result.a = Cs.a;
|
||||
|
||||
result.rgb *= result.a;
|
||||
|
||||
return Fragment(result);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -984,10 +984,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 { .. } |
|
||||
|
@ -1008,14 +1008,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,
|
||||
|
@ -1042,7 +1042,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,
|
||||
|
@ -1062,7 +1062,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),
|
||||
);
|
||||
|
@ -1139,7 +1139,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,
|
||||
|
@ -1148,7 +1148,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),
|
||||
|
@ -1520,71 +1520,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,
|
||||
|
@ -1598,20 +1555,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
|
||||
|
|
|
@ -12,7 +12,7 @@ use print_tree::{PrintableTree, PrintTree, PrintTreePrinter};
|
|||
use scene::SceneProperties;
|
||||
use spatial_node::{ScrollFrameInfo, SpatialNode, SpatialNodeType, StickyFrameInfo, ScrollFrameKind};
|
||||
use std::{ops, u32};
|
||||
use util::{project_rect, LayoutToWorldFastTransform, MatrixHelpers, ScaleOffset};
|
||||
use util::{LayoutToWorldFastTransform, MatrixHelpers, ScaleOffset};
|
||||
|
||||
pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>;
|
||||
|
||||
|
@ -229,35 +229,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(
|
||||
|
|
|
@ -22,7 +22,7 @@ use image::simplify_repeated_primitive;
|
|||
use intern::Interner;
|
||||
use internal_types::{FastHashMap, FastHashSet};
|
||||
use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureOptions};
|
||||
use picture::{BlitReason, OrderedPictureChild, PrimitiveList, TileCache};
|
||||
use picture::{BlitReason, PrimitiveList, TileCache};
|
||||
use prim_store::{PrimitiveInstance, PrimitiveSceneData};
|
||||
use prim_store::{PrimitiveInstanceKind, NinePatchDescriptor, PrimitiveStore};
|
||||
use prim_store::{ScrollNodeAndClipChain, PictureIndex};
|
||||
|
@ -1343,44 +1343,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);
|
||||
}
|
||||
|
||||
|
@ -1418,13 +1397,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.
|
||||
|
@ -1437,7 +1414,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
clip_chain_id,
|
||||
frame_output_pipeline_id,
|
||||
composite_ops,
|
||||
backdrop_picture,
|
||||
blit_reason,
|
||||
transform_style,
|
||||
context_3d,
|
||||
|
@ -1457,7 +1433,8 @@ 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() {
|
||||
let parent_is_empty = match self.sc_stack.last_mut() {
|
||||
Some(parent_sc) => {
|
||||
if stacking_context.is_redundant(
|
||||
parent_sc,
|
||||
self.clip_scroll_tree,
|
||||
|
@ -1472,7 +1449,10 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
parent_sc.primitives.is_empty()
|
||||
},
|
||||
None => true,
|
||||
};
|
||||
|
||||
if stacking_context.create_tile_cache {
|
||||
self.setup_picture_caching(
|
||||
|
@ -1488,16 +1468,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,
|
||||
|
@ -1505,17 +1476,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()
|
||||
|
@ -1523,10 +1502,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,
|
||||
|
@ -1667,7 +1649,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
|
||||
|
@ -1678,15 +1661,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()
|
||||
|
@ -1708,14 +1684,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,
|
||||
|
@ -1724,9 +1695,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.
|
||||
|
@ -1741,6 +1715,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
|
||||
}
|
||||
|
@ -2730,9 +2711,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,
|
||||
|
@ -2775,8 +2753,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;
|
||||
}
|
||||
|
||||
|
@ -2814,24 +2791,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,
|
||||
|
@ -2856,7 +2838,7 @@ impl FlattenedStackingContext {
|
|||
interners,
|
||||
);
|
||||
|
||||
Some((pic_index, prim_instance))
|
||||
Some(prim_instance)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1867,10 +1867,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1880,20 +1882,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.
|
||||
|
@ -3074,6 +3064,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);
|
||||
frame_state.surfaces[surface_index.0].tasks.push(readback_task_id);
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||
frame_state.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) {
|
||||
|
@ -3133,8 +3154,6 @@ 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.
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -418,6 +418,7 @@ pub enum RenderTaskKind {
|
|||
HorizontalBlur(BlurTask),
|
||||
#[allow(dead_code)]
|
||||
Glyph(GlyphTask),
|
||||
Readback(DeviceIntRect),
|
||||
Scaling(ScalingTask),
|
||||
Blit(BlitTask),
|
||||
Border(BorderTask),
|
||||
|
@ -527,6 +528,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,
|
||||
|
@ -877,7 +887,8 @@ impl RenderTask {
|
|||
|
||||
fn uv_rect_kind(&self) -> UvRectKind {
|
||||
match self.kind {
|
||||
RenderTaskKind::CacheMask(..) => {
|
||||
RenderTaskKind::CacheMask(..) |
|
||||
RenderTaskKind::Readback(..) => {
|
||||
unreachable!("bug: unexpected render task");
|
||||
}
|
||||
|
||||
|
@ -951,6 +962,7 @@ impl RenderTask {
|
|||
RenderTaskKind::Glyph(_) => {
|
||||
[0.0, 1.0, 0.0]
|
||||
}
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) |
|
||||
RenderTaskKind::Border(..) |
|
||||
RenderTaskKind::LineDecoration(..) |
|
||||
|
@ -992,6 +1004,7 @@ impl RenderTask {
|
|||
gpu_cache.get_address(&info.uv_rect_handle)
|
||||
}
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) |
|
||||
RenderTaskKind::Blit(..) |
|
||||
RenderTaskKind::Border(..) |
|
||||
|
@ -1045,6 +1058,8 @@ impl RenderTask {
|
|||
|
||||
pub fn target_kind(&self) -> RenderTargetKind {
|
||||
match self.kind {
|
||||
RenderTaskKind::Readback(..) => RenderTargetKind::Color,
|
||||
|
||||
RenderTaskKind::LineDecoration(..) => RenderTargetKind::Color,
|
||||
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
|
@ -1098,6 +1113,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(..) |
|
||||
|
@ -1149,6 +1165,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));
|
||||
|
|
|
@ -56,7 +56,7 @@ use device::{ShaderError, TextureFilter, TextureFlags,
|
|||
use device::{ProgramCache, ReadPixelsFormat};
|
||||
use device::query::GpuTimer;
|
||||
use euclid::rect;
|
||||
use euclid::Transform3D;
|
||||
use euclid::{Transform3D, TypedScale};
|
||||
use frame_builder::{ChasePrimitive, FrameBuilderConfig};
|
||||
use gleam::gl;
|
||||
use glyph_rasterizer::{GlyphFormat, GlyphRasterizer};
|
||||
|
@ -82,7 +82,7 @@ use render_backend::{FrameId, RenderBackend};
|
|||
use scene_builder::{SceneBuilder, LowPrioritySceneBuilder};
|
||||
use shade::{Shaders, WrShaders};
|
||||
use smallvec::SmallVec;
|
||||
use render_task::{RenderTaskData, RenderTaskTree};
|
||||
use render_task::{RenderTask, RenderTaskData, RenderTaskKind, RenderTaskTree};
|
||||
use resource_cache::ResourceCache;
|
||||
use util::drain_filter;
|
||||
|
||||
|
@ -2409,6 +2409,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",
|
||||
|
@ -3152,6 +3157,79 @@ 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,
|
||||
};
|
||||
|
||||
let mut src = DeviceIntRect::new(
|
||||
source_screen_origin + (backdrop_rect.origin - backdrop_screen_origin),
|
||||
readback_rect.size,
|
||||
);
|
||||
let mut dest = readback_rect.to_i32();
|
||||
let device_to_framebuffer = TypedScale::new(1i32);
|
||||
|
||||
// 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.blit_render_target(
|
||||
draw_target.into(),
|
||||
src * device_to_framebuffer,
|
||||
cache_draw_target,
|
||||
dest * device_to_framebuffer,
|
||||
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(
|
||||
|
@ -3484,6 +3562,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(
|
||||
|
|
|
@ -21,7 +21,7 @@ use internal_types::{CacheTextureId, FastHashMap, SavedTargetIndex, TextureSourc
|
|||
use pathfinder_partitioner::mesh::Mesh;
|
||||
use picture::{RecordedDirtyRegion, SurfaceInfo};
|
||||
use prim_store::gradient::GRADIENT_FP_STOPS;
|
||||
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};
|
||||
|
@ -63,18 +63,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
|
||||
|
@ -372,6 +360,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.
|
||||
|
@ -393,6 +382,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(),
|
||||
|
@ -525,6 +515,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),
|
||||
|
@ -657,6 +650,7 @@ impl RenderTarget for AlphaRenderTarget {
|
|||
}
|
||||
|
||||
match task.kind {
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Picture(..) |
|
||||
RenderTaskKind::Blit(..) |
|
||||
RenderTaskKind::Border(..) |
|
||||
|
@ -863,6 +857,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]
|
||||
|
|
|
@ -4,6 +4,10 @@ root:
|
|||
- 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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче