diff --git a/gfx/wr/webrender/res/brush_mix_blend.glsl b/gfx/wr/webrender/res/brush_mix_blend.glsl index 7887ee197314..65bea2823e1c 100644 --- a/gfx/wr/webrender/res/brush_mix_blend.glsl +++ b/gfx/wr/webrender/res/brush_mix_blend.glsl @@ -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 diff --git a/gfx/wr/webrender/src/batch.rs b/gfx/wr/webrender/src/batch.rs index 2642deed4a71..9453d67523a6 100644 --- a/gfx/wr/webrender/src/batch.rs +++ b/gfx/wr/webrender/src/batch.rs @@ -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 diff --git a/gfx/wr/webrender/src/clip_scroll_tree.rs b/gfx/wr/webrender/src/clip_scroll_tree.rs index 5d423ce4814b..427a4b56ef3c 100644 --- a/gfx/wr/webrender/src/clip_scroll_tree.rs +++ b/gfx/wr/webrender/src/clip_scroll_tree.rs @@ -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; @@ -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 { - 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( diff --git a/gfx/wr/webrender/src/display_list_flattener.rs b/gfx/wr/webrender/src/display_list_flattener.rs index 2d2a9bf4589f..af68ae1257b2 100644 --- a/gfx/wr/webrender/src/display_list_flattener.rs +++ b/gfx/wr/webrender/src/display_list_flattener.rs @@ -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, - ) -> Option<(PictureIndex, PrimitiveInstance)> { - if self.primitives.is_empty() { + ) -> Option { + 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) } } diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs index 4f883d4ac73a..96fd5a1825ab 100644 --- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -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, - }, /// 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, }; diff --git a/gfx/wr/webrender/src/prim_store/picture.rs b/gfx/wr/webrender/src/prim_store/picture.rs index fd40faa171f6..beacf6e4dfc7 100644 --- a/gfx/wr/webrender/src/prim_store/picture.rs +++ b/gfx/wr/webrender/src/prim_store/picture.rs @@ -64,7 +64,7 @@ pub enum PictureCompositeKey { impl From> for PictureCompositeKey { fn from(mode: Option) -> 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> for PictureCompositeKey { Some(PictureCompositeMode::ComponentTransferFilter(handle)) => { PictureCompositeKey::ComponentTransfer(handle.uid()) } - Some(PictureCompositeMode::Puppet { .. }) | Some(PictureCompositeMode::Blit(_)) | Some(PictureCompositeMode::TileCache { .. }) | None => { diff --git a/gfx/wr/webrender/src/render_task.rs b/gfx/wr/webrender/src/render_task.rs index 928912500fdb..85fb936e2d11 100644 --- a/gfx/wr/webrender/src/render_task.rs +++ b/gfx/wr/webrender/src/render_task.rs @@ -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)); diff --git a/gfx/wr/webrender/src/renderer.rs b/gfx/wr/webrender/src/renderer.rs index 4649883e77d6..f451b6ed7708 100644 --- a/gfx/wr/webrender/src/renderer.rs +++ b/gfx/wr/webrender/src/renderer.rs @@ -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( diff --git a/gfx/wr/webrender/src/tiling.rs b/gfx/wr/webrender/src/tiling.rs index 3d239e33fe3e..026de7aedde6 100644 --- a/gfx/wr/webrender/src/tiling.rs +++ b/gfx/wr/webrender/src/tiling.rs @@ -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, pub horizontal_blurs: Vec, + pub readbacks: Vec, pub scalings: Vec, pub blits: Vec, // 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"); } diff --git a/gfx/wr/wrench/reftests/blend/multiply-3-ref.yaml b/gfx/wr/wrench/reftests/blend/multiply-2-ref.yaml similarity index 100% rename from gfx/wr/wrench/reftests/blend/multiply-3-ref.yaml rename to gfx/wr/wrench/reftests/blend/multiply-2-ref.yaml diff --git a/gfx/wr/wrench/reftests/blend/multiply-2.yaml b/gfx/wr/wrench/reftests/blend/multiply-2.yaml index a47bd0e162e7..354ee6c81fa2 100644 --- a/gfx/wr/wrench/reftests/blend/multiply-2.yaml +++ b/gfx/wr/wrench/reftests/blend/multiply-2.yaml @@ -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] diff --git a/gfx/wr/wrench/reftests/blend/multiply-3.yaml b/gfx/wr/wrench/reftests/blend/multiply-3.yaml index 354ee6c81fa2..057c22d57adf 100644 --- a/gfx/wr/wrench/reftests/blend/multiply-3.yaml +++ b/gfx/wr/wrench/reftests/blend/multiply-3.yaml @@ -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] diff --git a/gfx/wr/wrench/reftests/blend/multiply-4.yaml b/gfx/wr/wrench/reftests/blend/multiply-4.yaml deleted file mode 100644 index 057c22d57adf..000000000000 --- a/gfx/wr/wrench/reftests/blend/multiply-4.yaml +++ /dev/null @@ -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] diff --git a/gfx/wr/wrench/reftests/blend/reftest.list b/gfx/wr/wrench/reftests/blend/reftest.list index 659509294ea0..8677fb8618ea 100644 --- a/gfx/wr/wrench/reftests/blend/reftest.list +++ b/gfx/wr/wrench/reftests/blend/reftest.list @@ -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 diff --git a/gfx/wr/wrench/reftests/blend/transform-source-ref.yaml b/gfx/wr/wrench/reftests/blend/transform-source-ref.yaml deleted file mode 100644 index 3a25a27cf348..000000000000 --- a/gfx/wr/wrench/reftests/blend/transform-source-ref.yaml +++ /dev/null @@ -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 diff --git a/gfx/wr/wrench/reftests/blend/transform-source.yaml b/gfx/wr/wrench/reftests/blend/transform-source.yaml deleted file mode 100644 index f9ce59901ea2..000000000000 --- a/gfx/wr/wrench/reftests/blend/transform-source.yaml +++ /dev/null @@ -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 diff --git a/gfx/wr/wrench/src/main.rs b/gfx/wr/wrench/src/main.rs index 6604d27c4cfd..d31eaa316dc0 100644 --- a/gfx/wr/wrench/src/main.rs +++ b/gfx/wr/wrench/src/main.rs @@ -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::>()); 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, @@ -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(); } diff --git a/layout/reftests/css-blending/reftest.list b/layout/reftests/css-blending/reftest.list index 3cd09ead8bb6..fa4c2e73546e 100644 --- a/layout/reftests/css-blending/reftest.list +++ b/layout/reftests/css-blending/reftest.list @@ -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