Bug 1851508 - Fix rendering artifacts on clip masks with nested perspective r=gfx-reviewers,lsalzman
Add support for drawing clip masks in the same reference frame as the raster space without the perspective transform, which fixes some complex edge cases with nested complex perspective transforms. Differential Revision: https://phabricator.services.mozilla.com/D187864
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include ps_quad,ellipse
|
#include ps_quad,ellipse
|
||||||
|
|
||||||
varying highp vec2 vClipLocalPos;
|
varying highp vec4 vClipLocalPos;
|
||||||
|
|
||||||
#ifdef WR_FEATURE_FAST_PATH
|
#ifdef WR_FEATURE_FAST_PATH
|
||||||
flat varying highp vec3 v_clip_params; // xy = box size, z = radius
|
flat varying highp vec3 v_clip_params; // xy = box size, z = radius
|
||||||
|
@ -24,6 +24,9 @@ flat varying highp vec2 vClipMode;
|
||||||
|
|
||||||
PER_INSTANCE in ivec4 aClipData;
|
PER_INSTANCE in ivec4 aClipData;
|
||||||
|
|
||||||
|
#define CLIP_SPACE_RASTER 0
|
||||||
|
#define CLIP_SPACE_PRIMITIVE 1
|
||||||
|
|
||||||
struct Clip {
|
struct Clip {
|
||||||
RectWithEndpoint rect;
|
RectWithEndpoint rect;
|
||||||
#ifdef WR_FEATURE_FAST_PATH
|
#ifdef WR_FEATURE_FAST_PATH
|
||||||
|
@ -33,11 +36,14 @@ struct Clip {
|
||||||
vec4 radii_bottom;
|
vec4 radii_bottom;
|
||||||
#endif
|
#endif
|
||||||
float mode;
|
float mode;
|
||||||
|
int space;
|
||||||
};
|
};
|
||||||
|
|
||||||
Clip fetch_clip(int index) {
|
Clip fetch_clip(int index) {
|
||||||
Clip clip;
|
Clip clip;
|
||||||
|
|
||||||
|
clip.space = aClipData.z;
|
||||||
|
|
||||||
#ifdef WR_FEATURE_FAST_PATH
|
#ifdef WR_FEATURE_FAST_PATH
|
||||||
vec4 texels[3] = fetch_from_gpu_buffer_3(index);
|
vec4 texels[3] = fetch_from_gpu_buffer_3(index);
|
||||||
clip.rect = RectWithEndpoint(texels[0].xy, texels[0].zw);
|
clip.rect = RectWithEndpoint(texels[0].xy, texels[0].zw);
|
||||||
|
@ -58,16 +64,22 @@ void main(void) {
|
||||||
PrimitiveInfo prim_info = ps_quad_main();
|
PrimitiveInfo prim_info = ps_quad_main();
|
||||||
|
|
||||||
Clip clip = fetch_clip(aClipData.y);
|
Clip clip = fetch_clip(aClipData.y);
|
||||||
|
Transform clip_transform = fetch_transform(aClipData.x);
|
||||||
|
|
||||||
|
vClipLocalPos = clip_transform.m * vec4(prim_info.local_pos, 0.0, 1.0);
|
||||||
|
|
||||||
|
#ifndef WR_FEATURE_FAST_PATH
|
||||||
|
if (clip.space == CLIP_SPACE_RASTER) {
|
||||||
|
vTransformBounds = vec4(clip.rect.p0, clip.rect.p1);
|
||||||
|
} else {
|
||||||
RectWithEndpoint xf_bounds = RectWithEndpoint(
|
RectWithEndpoint xf_bounds = RectWithEndpoint(
|
||||||
max(clip.rect.p0, prim_info.local_clip_rect.p0),
|
max(clip.rect.p0, prim_info.local_clip_rect.p0),
|
||||||
min(clip.rect.p1, prim_info.local_clip_rect.p1)
|
min(clip.rect.p1, prim_info.local_clip_rect.p1)
|
||||||
);
|
);
|
||||||
vTransformBounds = vec4(xf_bounds.p0, xf_bounds.p1);
|
vTransformBounds = vec4(xf_bounds.p0, xf_bounds.p1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Transform clip_transform = fetch_transform(aClipData.x);
|
|
||||||
|
|
||||||
vClipLocalPos = (clip_transform.m * vec4(prim_info.local_pos, 0.0, 1.0)).xy;
|
|
||||||
vClipMode.x = clip.mode;
|
vClipMode.x = clip.mode;
|
||||||
|
|
||||||
#ifdef WR_FEATURE_FAST_PATH
|
#ifdef WR_FEATURE_FAST_PATH
|
||||||
|
@ -75,7 +87,7 @@ void main(void) {
|
||||||
// signed distance function to get a rounded rect clip.
|
// signed distance function to get a rounded rect clip.
|
||||||
vec2 half_size = 0.5 * (clip.rect.p1 - clip.rect.p0);
|
vec2 half_size = 0.5 * (clip.rect.p1 - clip.rect.p0);
|
||||||
float radius = clip.radii.x;
|
float radius = clip.radii.x;
|
||||||
vClipLocalPos -= (half_size + clip.rect.p0);
|
vClipLocalPos.xy -= (half_size + clip.rect.p0) * vClipLocalPos.w;
|
||||||
v_clip_params = vec3(half_size - vec2(radius), radius);
|
v_clip_params = vec3(half_size - vec2(radius), radius);
|
||||||
#else
|
#else
|
||||||
vec2 r_tl = clip.radii_top.xy;
|
vec2 r_tl = clip.radii_top.xy;
|
||||||
|
@ -135,13 +147,14 @@ float sd_rounded_box(in vec2 pos, in vec2 box_size, in float radius) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
float aa_range = compute_aa_range(vClipLocalPos);
|
vec2 clip_local_pos = vClipLocalPos.xy / vClipLocalPos.w;
|
||||||
|
float aa_range = compute_aa_range(clip_local_pos);
|
||||||
|
|
||||||
#ifdef WR_FEATURE_FAST_PATH
|
#ifdef WR_FEATURE_FAST_PATH
|
||||||
float dist = sd_rounded_box(vClipLocalPos, v_clip_params.xy, v_clip_params.z);
|
float dist = sd_rounded_box(clip_local_pos, v_clip_params.xy, v_clip_params.z);
|
||||||
#else
|
#else
|
||||||
float dist = distance_to_rounded_rect(
|
float dist = distance_to_rounded_rect(
|
||||||
vClipLocalPos,
|
clip_local_pos,
|
||||||
vClipPlane_TL,
|
vClipPlane_TL,
|
||||||
vClipCenter_Radius_TL,
|
vClipCenter_Radius_TL,
|
||||||
vClipPlane_TR,
|
vClipPlane_TR,
|
||||||
|
|
|
@ -583,6 +583,15 @@ pub struct QuadSegment {
|
||||||
pub task_id: RenderTaskId,
|
pub task_id: RenderTaskId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Debug, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum ClipSpace {
|
||||||
|
Raster = 0,
|
||||||
|
Primitive = 1,
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
|
@ -591,7 +600,8 @@ pub struct MaskInstance {
|
||||||
pub prim: PrimitiveInstanceData,
|
pub prim: PrimitiveInstanceData,
|
||||||
pub clip_transform_id: TransformPaletteId,
|
pub clip_transform_id: TransformPaletteId,
|
||||||
pub clip_address: i32,
|
pub clip_address: i32,
|
||||||
pub info: [i32; 2],
|
pub clip_space: ClipSpace,
|
||||||
|
pub unused: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1299,8 +1299,24 @@ fn prepare_interned_prim_for_render(
|
||||||
|
|
||||||
let content_origin = DevicePoint::new(x0, y0);
|
let content_origin = DevicePoint::new(x0, y0);
|
||||||
|
|
||||||
|
let pic_surface_index = pic.raster_config.as_ref().unwrap().surface_index;
|
||||||
|
let prim_local_rect = frame_state
|
||||||
|
.surfaces[pic_surface_index.0]
|
||||||
|
.clipped_local_rect
|
||||||
|
.cast_unit();
|
||||||
|
|
||||||
|
let main_prim_address = write_prim_blocks(
|
||||||
|
frame_state.frame_gpu_data,
|
||||||
|
prim_local_rect,
|
||||||
|
prim_instance.vis.clip_chain.local_clip_rect,
|
||||||
|
PremultipliedColorF::WHITE,
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
|
||||||
let masks = MaskSubPass {
|
let masks = MaskSubPass {
|
||||||
clip_node_range: prim_instance.vis.clip_chain.clips_range,
|
clip_node_range: prim_instance.vis.clip_chain.clips_range,
|
||||||
|
prim_spatial_node_index,
|
||||||
|
main_prim_address,
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent_task_id = if in_place_mask {
|
let parent_task_id = if in_place_mask {
|
||||||
|
@ -2121,6 +2137,8 @@ fn add_segment(
|
||||||
|
|
||||||
let masks = MaskSubPass {
|
let masks = MaskSubPass {
|
||||||
clip_node_range: prim_instance.vis.clip_chain.clips_range,
|
clip_node_range: prim_instance.vis.clip_chain.clips_range,
|
||||||
|
prim_spatial_node_index,
|
||||||
|
main_prim_address,
|
||||||
};
|
};
|
||||||
|
|
||||||
let task = frame_state.rg_builder.get_task_mut(task_id);
|
let task = frame_state.rg_builder.get_task_mut(task_id);
|
||||||
|
|
|
@ -10,13 +10,12 @@ use crate::batch::{ClipBatcher, BatchBuilder, INVALID_SEGMENT_INDEX, ClipMaskIns
|
||||||
use crate::command_buffer::{CommandBufferList, QuadFlags};
|
use crate::command_buffer::{CommandBufferList, QuadFlags};
|
||||||
use crate::segment::EdgeAaSegmentMask;
|
use crate::segment::EdgeAaSegmentMask;
|
||||||
use crate::spatial_tree::SpatialTree;
|
use crate::spatial_tree::SpatialTree;
|
||||||
use crate::space::SpaceMapper;
|
|
||||||
use crate::clip::{ClipStore, ClipItemKind};
|
use crate::clip::{ClipStore, ClipItemKind};
|
||||||
use crate::frame_builder::{FrameGlobalResources};
|
use crate::frame_builder::{FrameGlobalResources};
|
||||||
use crate::gpu_cache::{GpuCache, GpuCacheAddress};
|
use crate::gpu_cache::{GpuCache, GpuCacheAddress};
|
||||||
use crate::gpu_types::{BorderInstance, SvgFilterInstance, BlurDirection, BlurInstance, PrimitiveHeaders, ScalingInstance};
|
use crate::gpu_types::{BorderInstance, SvgFilterInstance, BlurDirection, BlurInstance, PrimitiveHeaders, ScalingInstance};
|
||||||
use crate::gpu_types::{TransformPalette, ZBufferIdGenerator, TransformPaletteId, MaskInstance};
|
use crate::gpu_types::{TransformPalette, ZBufferIdGenerator, MaskInstance, ClipSpace};
|
||||||
use crate::gpu_types::{ZBufferId, QuadSegment, PrimitiveInstanceData};
|
use crate::gpu_types::{ZBufferId, QuadSegment, PrimitiveInstanceData, TransformPaletteId};
|
||||||
use crate::internal_types::{FastHashMap, TextureSource, CacheTextureId};
|
use crate::internal_types::{FastHashMap, TextureSource, CacheTextureId};
|
||||||
use crate::picture::{SliceId, SurfaceInfo, ResolvedSurfaceTexture, TileCacheInstance};
|
use crate::picture::{SliceId, SurfaceInfo, ResolvedSurfaceTexture, TileCacheInstance};
|
||||||
use crate::prepare::write_prim_blocks;
|
use crate::prepare::write_prim_blocks;
|
||||||
|
@ -25,7 +24,7 @@ use crate::prim_store::gradient::{
|
||||||
FastLinearGradientInstance, LinearGradientInstance, RadialGradientInstance,
|
FastLinearGradientInstance, LinearGradientInstance, RadialGradientInstance,
|
||||||
ConicGradientInstance,
|
ConicGradientInstance,
|
||||||
};
|
};
|
||||||
use crate::renderer::{GpuBufferBuilder};
|
use crate::renderer::{GpuBufferBuilder, GpuBufferAddress};
|
||||||
use crate::render_backend::DataStores;
|
use crate::render_backend::DataStores;
|
||||||
use crate::render_task::{RenderTaskKind, RenderTaskAddress, SubPass};
|
use crate::render_task::{RenderTaskKind, RenderTaskAddress, SubPass};
|
||||||
use crate::render_task::{RenderTask, ScalingTask, SvgFilterInfo, MaskSubPass};
|
use crate::render_task::{RenderTask, ScalingTask, SvgFilterInfo, MaskSubPass};
|
||||||
|
@ -959,9 +958,10 @@ pub struct LineDecorationJob {
|
||||||
fn build_mask_tasks(
|
fn build_mask_tasks(
|
||||||
info: &MaskSubPass,
|
info: &MaskSubPass,
|
||||||
render_task_address: RenderTaskAddress,
|
render_task_address: RenderTaskAddress,
|
||||||
|
task_world_rect: WorldRect,
|
||||||
target_rect: DeviceIntRect,
|
target_rect: DeviceIntRect,
|
||||||
content_rect: DeviceRect,
|
main_prim_address: GpuBufferAddress,
|
||||||
device_pixel_scale: DevicePixelScale,
|
prim_spatial_node_index: SpatialNodeIndex,
|
||||||
raster_spatial_node_index: SpatialNodeIndex,
|
raster_spatial_node_index: SpatialNodeIndex,
|
||||||
clip_store: &ClipStore,
|
clip_store: &ClipStore,
|
||||||
data_stores: &DataStores,
|
data_stores: &DataStores,
|
||||||
|
@ -971,41 +971,11 @@ fn build_mask_tasks(
|
||||||
render_tasks: &RenderTaskGraph,
|
render_tasks: &RenderTaskGraph,
|
||||||
results: &mut ClipMaskInstanceList,
|
results: &mut ClipMaskInstanceList,
|
||||||
) {
|
) {
|
||||||
let task_world_rect = content_rect / device_pixel_scale;
|
|
||||||
|
|
||||||
for i in 0 .. info.clip_node_range.count {
|
for i in 0 .. info.clip_node_range.count {
|
||||||
let clip_instance = clip_store.get_instance_from_range(&info.clip_node_range, i);
|
let clip_instance = clip_store.get_instance_from_range(&info.clip_node_range, i);
|
||||||
let clip_node = &data_stores.clip[clip_instance.handle];
|
let clip_node = &data_stores.clip[clip_instance.handle];
|
||||||
|
|
||||||
let is_same_coord_system = spatial_tree.is_matching_coord_system(
|
let (clip_address, fast_path) = match clip_node.item.kind {
|
||||||
clip_node.item.spatial_node_index,
|
|
||||||
raster_spatial_node_index,
|
|
||||||
);
|
|
||||||
|
|
||||||
let clip_needs_scissor_rect = !is_same_coord_system;
|
|
||||||
let quad_flags = if is_same_coord_system {
|
|
||||||
QuadFlags::APPLY_DEVICE_CLIP
|
|
||||||
} else {
|
|
||||||
QuadFlags::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
let clip_transform_id = transforms.get_id(
|
|
||||||
clip_node.item.spatial_node_index,
|
|
||||||
raster_spatial_node_index,
|
|
||||||
spatial_tree,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Work out a local space rect for the clip that will ensure we write to every
|
|
||||||
// pixel covered by the primitive. For 2d cases, this will be exact. For complex
|
|
||||||
// perspective cases, it will be a conservative estimate.
|
|
||||||
let mapper = SpaceMapper::new_with_target(
|
|
||||||
raster_spatial_node_index,
|
|
||||||
clip_node.item.spatial_node_index,
|
|
||||||
task_world_rect,
|
|
||||||
spatial_tree,
|
|
||||||
);
|
|
||||||
|
|
||||||
let (clip_address, clip_rect, fast_path) = match clip_node.item.kind {
|
|
||||||
ClipItemKind::RoundedRectangle { rect, radius, mode } => {
|
ClipItemKind::RoundedRectangle { rect, radius, mode } => {
|
||||||
let (fast_path, clip_address) = if radius.is_uniform().is_some() {
|
let (fast_path, clip_address) = if radius.is_uniform().is_some() {
|
||||||
let mut writer = gpu_buffer_builder.write_blocks(3);
|
let mut writer = gpu_buffer_builder.write_blocks(3);
|
||||||
|
@ -1036,7 +1006,7 @@ fn build_mask_tasks(
|
||||||
(false, clip_address)
|
(false, clip_address)
|
||||||
};
|
};
|
||||||
|
|
||||||
(clip_address, rect, fast_path)
|
(clip_address, fast_path)
|
||||||
}
|
}
|
||||||
ClipItemKind::Rectangle { rect, mode, .. } => {
|
ClipItemKind::Rectangle { rect, mode, .. } => {
|
||||||
assert_eq!(mode, ClipMode::Clip);
|
assert_eq!(mode, ClipMode::Clip);
|
||||||
|
@ -1047,12 +1017,30 @@ fn build_mask_tasks(
|
||||||
writer.push_one([mode as i32 as f32, 0.0, 0.0, 0.0]);
|
writer.push_one([mode as i32 as f32, 0.0, 0.0, 0.0]);
|
||||||
let clip_address = writer.finish();
|
let clip_address = writer.finish();
|
||||||
|
|
||||||
(clip_address, rect, true)
|
(clip_address, true)
|
||||||
}
|
}
|
||||||
ClipItemKind::BoxShadow { .. } => {
|
ClipItemKind::BoxShadow { .. } => {
|
||||||
panic!("bug: box-shadow clips not expected on non-legacy rect/quads");
|
panic!("bug: box-shadow clips not expected on non-legacy rect/quads");
|
||||||
}
|
}
|
||||||
ClipItemKind::Image { rect, .. } => {
|
ClipItemKind::Image { rect, .. } => {
|
||||||
|
let clip_transform_id = transforms.get_id(
|
||||||
|
clip_node.item.spatial_node_index,
|
||||||
|
raster_spatial_node_index,
|
||||||
|
spatial_tree,
|
||||||
|
);
|
||||||
|
|
||||||
|
let is_same_coord_system = spatial_tree.is_matching_coord_system(
|
||||||
|
prim_spatial_node_index,
|
||||||
|
raster_spatial_node_index,
|
||||||
|
);
|
||||||
|
|
||||||
|
let clip_needs_scissor_rect = !is_same_coord_system;
|
||||||
|
let mut quad_flags = QuadFlags::SAMPLE_AS_MASK;
|
||||||
|
|
||||||
|
if is_same_coord_system {
|
||||||
|
quad_flags |= QuadFlags::APPLY_DEVICE_CLIP;
|
||||||
|
}
|
||||||
|
|
||||||
for tile in clip_store.visible_mask_tiles(&clip_instance) {
|
for tile in clip_store.visible_mask_tiles(&clip_instance) {
|
||||||
let clip_prim_address = write_prim_blocks(
|
let clip_prim_address = write_prim_blocks(
|
||||||
gpu_buffer_builder,
|
gpu_buffer_builder,
|
||||||
|
@ -1073,7 +1061,7 @@ fn build_mask_tasks(
|
||||||
render_task_address,
|
render_task_address,
|
||||||
clip_transform_id,
|
clip_transform_id,
|
||||||
clip_prim_address,
|
clip_prim_address,
|
||||||
quad_flags | QuadFlags::SAMPLE_AS_MASK,
|
quad_flags,
|
||||||
EdgeAaSegmentMask::empty(),
|
EdgeAaSegmentMask::empty(),
|
||||||
0,
|
0,
|
||||||
tile.task_id,
|
tile.task_id,
|
||||||
|
@ -1104,32 +1092,72 @@ fn build_mask_tasks(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let bounding_rect = match mapper.unmap(&task_world_rect) {
|
let prim_spatial_node = spatial_tree.get_spatial_node(prim_spatial_node_index);
|
||||||
Some(rect) => rect,
|
let clip_spatial_node = spatial_tree.get_spatial_node(clip_node.item.spatial_node_index);
|
||||||
None => {
|
let raster_spatial_node = spatial_tree.get_spatial_node(raster_spatial_node_index);
|
||||||
// TODO(gw): This doesn't seem right - it may need to be expanded to cover
|
let raster_clip = raster_spatial_node.coordinate_system_id == clip_spatial_node.coordinate_system_id;
|
||||||
// the primitive region. However, I cannot get any test cases to
|
|
||||||
// fail - let's see if we get any regressions here and work out
|
|
||||||
// the correct way to handle any cases that arise.
|
|
||||||
// Should also assert on coordinate system, perhaps?
|
|
||||||
clip_rect
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let clip_prim_address = write_prim_blocks(
|
let (clip_space, clip_transform_id, main_prim_address, prim_transform_id, is_same_coord_system) = if raster_clip {
|
||||||
|
let prim_transform_id = TransformPaletteId::IDENTITY;
|
||||||
|
|
||||||
|
let clip_transform_id = transforms.get_id(
|
||||||
|
raster_spatial_node_index,
|
||||||
|
clip_node.item.spatial_node_index,
|
||||||
|
spatial_tree,
|
||||||
|
);
|
||||||
|
|
||||||
|
let main_prim_address = write_prim_blocks(
|
||||||
gpu_buffer_builder,
|
gpu_buffer_builder,
|
||||||
bounding_rect,
|
task_world_rect.cast_unit(),
|
||||||
bounding_rect,
|
task_world_rect.cast_unit(),
|
||||||
PremultipliedColorF::WHITE,
|
PremultipliedColorF::WHITE,
|
||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
(ClipSpace::Raster, clip_transform_id, main_prim_address, prim_transform_id, true)
|
||||||
|
} else {
|
||||||
|
let prim_transform_id = transforms.get_id(
|
||||||
|
prim_spatial_node_index,
|
||||||
|
raster_spatial_node_index,
|
||||||
|
spatial_tree,
|
||||||
|
);
|
||||||
|
|
||||||
|
let clip_transform_id = if prim_spatial_node.coordinate_system_id < clip_spatial_node.coordinate_system_id {
|
||||||
|
transforms.get_id(
|
||||||
|
clip_node.item.spatial_node_index,
|
||||||
|
prim_spatial_node_index,
|
||||||
|
spatial_tree,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
transforms.get_id(
|
||||||
|
prim_spatial_node_index,
|
||||||
|
clip_node.item.spatial_node_index,
|
||||||
|
spatial_tree,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_same_coord_system = spatial_tree.is_matching_coord_system(
|
||||||
|
prim_spatial_node_index,
|
||||||
|
raster_spatial_node_index,
|
||||||
|
);
|
||||||
|
|
||||||
|
(ClipSpace::Primitive, clip_transform_id, main_prim_address, prim_transform_id, is_same_coord_system)
|
||||||
|
};
|
||||||
|
|
||||||
|
let clip_needs_scissor_rect = !is_same_coord_system;
|
||||||
|
|
||||||
|
let quad_flags = if is_same_coord_system {
|
||||||
|
QuadFlags::APPLY_DEVICE_CLIP
|
||||||
|
} else {
|
||||||
|
QuadFlags::empty()
|
||||||
|
};
|
||||||
|
|
||||||
add_quad_to_batch(
|
add_quad_to_batch(
|
||||||
render_task_address,
|
render_task_address,
|
||||||
clip_transform_id,
|
prim_transform_id,
|
||||||
clip_prim_address,
|
main_prim_address,
|
||||||
quad_flags,
|
quad_flags,
|
||||||
EdgeAaSegmentMask::empty(),
|
EdgeAaSegmentMask::all(),
|
||||||
INVALID_SEGMENT_INDEX as u8,
|
INVALID_SEGMENT_INDEX as u8,
|
||||||
RenderTaskId::INVALID,
|
RenderTaskId::INVALID,
|
||||||
ZBufferId(0),
|
ZBufferId(0),
|
||||||
|
@ -1137,9 +1165,10 @@ fn build_mask_tasks(
|
||||||
|_, prim| {
|
|_, prim| {
|
||||||
let instance = MaskInstance {
|
let instance = MaskInstance {
|
||||||
prim,
|
prim,
|
||||||
clip_transform_id: TransformPaletteId::IDENTITY,
|
clip_transform_id,
|
||||||
clip_address: clip_address.as_int(),
|
clip_address: clip_address.as_int(),
|
||||||
info: [0; 2],
|
clip_space,
|
||||||
|
unused: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if clip_needs_scissor_rect {
|
if clip_needs_scissor_rect {
|
||||||
|
@ -1204,9 +1233,10 @@ fn build_sub_pass(
|
||||||
build_mask_tasks(
|
build_mask_tasks(
|
||||||
masks,
|
masks,
|
||||||
render_task_address,
|
render_task_address,
|
||||||
|
content_rect / device_pixel_scale,
|
||||||
target_rect,
|
target_rect,
|
||||||
content_rect,
|
masks.main_prim_address,
|
||||||
device_pixel_scale,
|
masks.prim_spatial_node_index,
|
||||||
raster_spatial_node_index,
|
raster_spatial_node_index,
|
||||||
ctx.clip_store,
|
ctx.clip_store,
|
||||||
ctx.data_stores,
|
ctx.data_stores,
|
||||||
|
|
|
@ -882,6 +882,8 @@ pub type TaskDependencies = SmallVec<[RenderTaskId;2]>;
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
pub struct MaskSubPass {
|
pub struct MaskSubPass {
|
||||||
pub clip_node_range: ClipNodeRange,
|
pub clip_node_range: ClipNodeRange,
|
||||||
|
pub prim_spatial_node_index: SpatialNodeIndex,
|
||||||
|
pub main_prim_address: GpuBufferAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
|
|
|
@ -24,7 +24,7 @@ use peek_poke::PeekPoke;
|
||||||
/// coordinate system has an id and those ids will be shared when the coordinates
|
/// coordinate system has an id and those ids will be shared when the coordinates
|
||||||
/// system are the same or are in the same axis-aligned space. This allows
|
/// system are the same or are in the same axis-aligned space. This allows
|
||||||
/// for optimizing mask generation.
|
/// for optimizing mask generation.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||||
pub struct CoordinateSystemId(pub u32);
|
pub struct CoordinateSystemId(pub u32);
|
||||||
|
|
Двоичные данные
gfx/wr/wrench/reftests/blend/mix-blend-complex-transform.png
До Ширина: | Высота: | Размер: 34 KiB После Ширина: | Высота: | Размер: 34 KiB |
Двоичные данные
gfx/wr/wrench/reftests/clip/clip-2d-z-rotations.png
До Ширина: | Высота: | Размер: 2.0 KiB После Ширина: | Высота: | Размер: 2.2 KiB |
Двоичные данные
gfx/wr/wrench/reftests/clip/clip-45-degree-rotation-ref.png
До Ширина: | Высота: | Размер: 13 KiB После Ширина: | Высота: | Размер: 13 KiB |
Двоичные данные
gfx/wr/wrench/reftests/transforms/perspective-border-radius.png
До Ширина: | Высота: | Размер: 12 KiB После Ширина: | Высота: | Размер: 12 KiB |
Двоичные данные
gfx/wr/wrench/reftests/transforms/rotated-clip-large.png
До Ширина: | Высота: | Размер: 7.2 KiB После Ширина: | Высота: | Размер: 7.2 KiB |
Двоичные данные
gfx/wr/wrench/reftests/transforms/rotated-clip.png
До Ширина: | Высота: | Размер: 3.7 KiB После Ширина: | Высота: | Размер: 3.7 KiB |
|
@ -0,0 +1,3 @@
|
||||||
|
[offset-path-shape-circle-001.html]
|
||||||
|
fuzzy:
|
||||||
|
if swgl: maxDifference=255-255;totalPixels=117-117
|
|
@ -0,0 +1,3 @@
|
||||||
|
[offset-path-shape-circle-004.html]
|
||||||
|
fuzzy:
|
||||||
|
if swgl: maxDifference=255-255;totalPixels=303-303
|
|
@ -0,0 +1,3 @@
|
||||||
|
[offset-path-shape-ellipse-001.html]
|
||||||
|
fuzzy:
|
||||||
|
if swgl: maxDifference=255-255;totalPixels=109-109
|
|
@ -0,0 +1,3 @@
|
||||||
|
[offset-path-url-003.html]
|
||||||
|
fuzzy:
|
||||||
|
if swgl: maxDifference=255-255;totalPixels=70-70
|
|
@ -0,0 +1,3 @@
|
||||||
|
[offset-path-url-004.html]
|
||||||
|
fuzzy:
|
||||||
|
if swgl: maxDifference=255-255;totalPixels=60-60
|