Bug 1863688 - Fix translucent + opaque RGBA compositor surface overlays. r=gfx-reviewers,lsalzman

Differential Revision: https://phabricator.services.mozilla.com/D193713
This commit is contained in:
Glenn Watson 2023-11-16 22:08:39 +00:00
parent 1e673cf70f
commit 4cb33ca6a0
5 changed files with 58 additions and 25 deletions

View File

@ -27,7 +27,7 @@ use std::{ops, u64, os::raw::c_void};
/// Which method is being used to draw a requested compositor surface
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Debug, Copy, Clone, MallocSizeOf)]
#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)]
pub enum CompositorSurfaceKind {
/// Don't create a native compositor surface, blit it as a regular primitive
Blit,

View File

@ -2455,7 +2455,7 @@ impl TileCacheInstance {
prim_spatial_node_index: SpatialNodeIndex,
is_root_tile_cache: bool,
sub_slice_index: usize,
is_opaque: bool,
surface_kind: CompositorSurfaceKind,
frame_context: &FrameVisibilityContext,
) -> SurfacePromotionResult {
// Check if this primitive _wants_ to be promoted to a compositor surface.
@ -2464,7 +2464,7 @@ impl TileCacheInstance {
}
// For now, only support a small (arbitrary) number of compositor surfaces.
if !is_opaque {
if surface_kind == CompositorSurfaceKind::Overlay {
// Non-opaque compositor surfaces require sub-slices, as they are drawn
// as overlays.
if sub_slice_index == self.sub_slices.len() - 1 {
@ -2553,6 +2553,7 @@ impl TileCacheInstance {
composite_state,
image_rendering,
true,
CompositorSurfaceKind::Underlay,
)
}
@ -2572,6 +2573,7 @@ impl TileCacheInstance {
gpu_cache: &mut GpuCache,
image_rendering: ImageRendering,
is_opaque: bool,
surface_kind: CompositorSurfaceKind,
) -> bool {
let mut api_keys = [ImageKey::DUMMY; 3];
api_keys[0] = api_key;
@ -2606,6 +2608,7 @@ impl TileCacheInstance {
composite_state,
image_rendering,
is_opaque,
surface_kind,
)
}
@ -2626,6 +2629,7 @@ impl TileCacheInstance {
composite_state: &mut CompositeState,
image_rendering: ImageRendering,
is_opaque: bool,
surface_kind: CompositorSurfaceKind,
) -> bool {
let map_local_to_surface = SpaceMapper::new_with_target(
self.spatial_node_index,
@ -2823,20 +2827,24 @@ impl TileCacheInstance {
// If the surface is opaque, we can draw it an an underlay (which avoids
// additional sub-slice surfaces, and supports clip masks)
if is_opaque {
self.underlays.push(descriptor);
} else {
// For compositor surfaces, if we didn't find an earlier sub-slice to add to,
// we know we can append to the current slice.
assert!(sub_slice_index < self.sub_slices.len() - 1);
let sub_slice = &mut self.sub_slices[sub_slice_index];
match surface_kind {
CompositorSurfaceKind::Underlay => {
self.underlays.push(descriptor);
}
CompositorSurfaceKind::Overlay => {
// For compositor surfaces, if we didn't find an earlier sub-slice to add to,
// we know we can append to the current slice.
assert!(sub_slice_index < self.sub_slices.len() - 1);
let sub_slice = &mut self.sub_slices[sub_slice_index];
// Each compositor surface allocates a unique z-id
sub_slice.compositor_surfaces.push(CompositorSurface {
prohibited_rect: pic_coverage_rect,
is_opaque,
descriptor,
});
// Each compositor surface allocates a unique z-id
sub_slice.compositor_surfaces.push(CompositorSurface {
prohibited_rect: pic_coverage_rect,
is_opaque,
descriptor,
});
}
CompositorSurfaceKind::Blit => unreachable!(),
}
true
@ -3083,6 +3091,11 @@ impl TileCacheInstance {
PrimitiveInstanceKind::Image { data_handle, ref mut compositor_surface_kind, .. } => {
let image_key = &data_stores.image[data_handle];
let image_data = &image_key.kind;
// For now, assume that for compositor surface purposes, any RGBA image may be
// translucent. See the comment in `add_prim` in this source file for more
// details. We'll leave the `is_opaque` code branches here, but disabled, as
// in future we will want to support this case correctly.
let mut is_opaque = false;
if let Some(image_properties) = resource_cache.get_image_properties(image_data.key) {
@ -3112,7 +3125,7 @@ impl TileCacheInstance {
prim_spatial_node_index,
is_root_tile_cache,
sub_slice_index,
is_opaque,
CompositorSurfaceKind::Overlay,
frame_context) {
SurfacePromotionResult::Failed => {
}
@ -3146,17 +3159,14 @@ impl TileCacheInstance {
gpu_cache,
image_data.image_rendering,
is_opaque,
CompositorSurfaceKind::Overlay,
);
}
if promote_to_surface {
if is_opaque {
*compositor_surface_kind = CompositorSurfaceKind::Underlay;
} else {
*compositor_surface_kind = CompositorSurfaceKind::Overlay;
prim_instance.vis.state = VisibilityState::Culled;
return;
}
*compositor_surface_kind = CompositorSurfaceKind::Overlay;
prim_instance.vis.state = VisibilityState::Culled;
return;
} else {
*compositor_surface_kind = CompositorSurfaceKind::Blit;
@ -3174,7 +3184,7 @@ impl TileCacheInstance {
prim_spatial_node_index,
is_root_tile_cache,
sub_slice_index,
true,
CompositorSurfaceKind::Underlay,
frame_context) {
SurfacePromotionResult::Failed => false,
SurfacePromotionResult::Success => true,

View File

@ -6,3 +6,4 @@ fuzzy(2,1000) == mix-blend.yaml mix-blend-ref.yaml
fuzzy(2,2500) == filter-overlay.yaml filter-overlay-ref.yaml
platform(linux,mac) == mask.yaml mask.png
platform(linux) fuzzy(7,86000) == underlay.yaml underlay.png
fuzzy(2,2600) == transparent-opaque-image.yaml transparent-opaque-image-ref.yaml

View File

@ -0,0 +1,8 @@
---
root:
items:
- type: rect
bounds: [50, 50, 362, 362]
color: green
- image: checkerboard(2,16,16)
bounds: [100, 100, 262, 262]

View File

@ -0,0 +1,14 @@
# Verify that an RGBA compositor surface that is translucent, followed
# by an RGBA compositor surface that is opaque draws correctly.
---
root:
items:
- type: rect
bounds: [50, 50, 362, 362]
color: green
- image: transparent-checkerboard(2,16,16)
bounds: [100, 100, 262, 262]
prefer-compositor-surface: true
- image: checkerboard(2,16,16)
bounds: [100, 100, 262, 262]
prefer-compositor-surface: true