0

viz: Skip direct composition underlays for non-opaque texture quads.

Texture quads are considered as "requires overlay" quads which means
that non-opaque occluded texture quads will be put into an overlay
without any possibility of blending. This is ok for video since overlay
compatible YUV video quads don't have any alpha, but texture quads can
have alpha. A totally transparent texture quad would show up as black.

This CL fixes that by applying the underlay validation check to texture
quads. Multiple texture quads are still promoted if possible, but a quad
could be skipped if it's occluded and non-opaque. This CL also adds a
pixel test for this scenario.

Bug: 1122638
Change-Id: I5c4f120d88ce8ad2bd340b7a4aa33d59fe1ef116
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2380161
Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Reviewed-by: Maggie Chen <magchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805096}
This commit is contained in:
Sunny Sachanandani
2020-09-08 21:55:58 +00:00
committed by Commit Bot
parent 3abe288b37
commit e8489b6e53
4 changed files with 87 additions and 22 deletions
components/viz/service/display
content/test

@ -213,19 +213,14 @@ void FromTextureQuad(const TextureDrawQuad* quad,
dc_layer->color_space = gfx::ColorSpace::CreateSRGB();
}
// TODO(magchen): Once software protected video is enabled for all GPUs and
// all configurations, RequiresOverlay() will be true for all protected video.
bool RequiresOverlay(const QuadList::Iterator& it) {
if (it->material == DrawQuad::Material::kYuvVideoContent &&
(YUVVideoDrawQuad::MaterialCast(*it)->protected_video_type ==
gfx::ProtectedVideoType::kHardwareProtected ||
YUVVideoDrawQuad::MaterialCast(*it)->protected_video_type ==
gfx::ProtectedVideoType::kSoftwareProtected)) {
return true;
} else if (it->material == DrawQuad::Material::kTextureContent) {
return true;
bool IsProtectedVideo(const QuadList::Iterator& it) {
if (it->material == DrawQuad::Material::kYuvVideoContent) {
const auto* yuv_quad = YUVVideoDrawQuad::MaterialCast(*it);
return yuv_quad->protected_video_type ==
gfx::ProtectedVideoType::kHardwareProtected ||
yuv_quad->protected_video_type ==
gfx::ProtectedVideoType::kSoftwareProtected;
}
return false;
}
@ -233,7 +228,7 @@ DCLayerResult IsUnderlayAllowed(const QuadList::Iterator& it) {
if (!base::FeatureList::IsEnabled(features::kDirectCompositionUnderlays)) {
return DC_LAYER_FAILED_OCCLUDED;
}
if (it->shared_quad_state->opacity < 1.0f) {
if (it->ShouldDrawWithBlending()) {
return DC_LAYER_FAILED_TRANSPARENT;
}
return DC_LAYER_SUCCESS;
@ -432,7 +427,7 @@ void DCLayerOverlayProcessor::Process(
// Used for whether overlay should be skipped
int yuv_quads_in_quad_list = 0;
bool has_required_overlays = false;
bool has_protected_video_or_texture_overlays = false;
for (auto it = quad_list->begin(); it != quad_list->end(); ++it, ++index) {
if (it->material == DrawQuad::Material::kAggregatedRenderPass) {
@ -465,9 +460,12 @@ void DCLayerOverlayProcessor::Process(
RecordDCLayerResult(result, it);
continue;
}
const bool requires_overlay = RequiresOverlay(it);
if (requires_overlay)
has_required_overlays = true;
const bool is_protected_video = IsProtectedVideo(it);
const bool is_texture_quad =
it->material == DrawQuad::Material::kTextureContent;
if (is_protected_video || is_texture_quad)
has_protected_video_or_texture_overlays = true;
if (candidate_index_list.size() == 0) {
prev_index = index;
@ -477,10 +475,11 @@ void DCLayerOverlayProcessor::Process(
candidate_index_list.push_back(index);
}
// We might not save power if there are more than one videos and only
// one is promoted to overlay. Skip overlay for this frame.
// We might not save power if there are more than one videos and only one is
// promoted to overlay. Skip overlays for this frame unless there are
// protected video or texture overlays.
if (candidate_index_list.size() > 0 && yuv_quads_in_quad_list > 1 &&
!has_required_overlays) {
!has_protected_video_or_texture_overlays) {
candidate_index_list.clear();
// In this case, there is only one candidate in the list.
RecordDCLayerResult(DC_LAYER_FAILED_TOO_MANY_OVERLAYS, prev_it);
@ -504,8 +503,9 @@ void DCLayerOverlayProcessor::Process(
const bool is_overlay = !HasOccludingQuads(
gfx::RectF(quad_rectangle_in_target_space), quad_list->begin(), it);
// This draw quad must be displayed through the hardware overlay path.
const bool requires_overlay = RequiresOverlay(it);
// Protected video is always put in an overlay, but texture quads can be
// skipped if they're not underlay compatible.
const bool requires_overlay = IsProtectedVideo(it);
// Skip quad if it's an underlay and underlays are not allowed.
if (!is_overlay && !requires_overlay) {

@ -0,0 +1,58 @@
<!DOCTYPE HTML>
<!-- READ BEFORE UPDATING:
If this test is updated make sure to increment the "revision" value of the
associated test in content/test/gpu/page_sets/pixel_tests.py. This will ensure
that the baseline images are regenerated on the next run.
-->
<html>
<head>
<title>Low Latency WebGL Canvas Test: Should render diagonal green and blue boxes over red background</title>
<style type="text/css">
.nomargin {
margin: 0px auto;
}
</style>
<script>
let g_swapsBeforeAck = 15;
let g_canvas;
let g_gl;
function main()
{
g_canvas = document.getElementById("c");
g_gl = g_canvas.getContext("webgl", {desynchronized: true, alpha: true});
requestAnimationFrame(draw);
}
function draw()
{
g_gl.clearColor(0, 0, 0, 0);
g_gl.clear(g_gl.COLOR_BUFFER_BIT);
g_gl.enable(g_gl.SCISSOR_TEST);
g_gl.scissor(0, 0, 50, 50);
g_gl.clearColor(0, 1, 0, 1);
g_gl.clear(g_gl.COLOR_BUFFER_BIT);
waitForFinish();
}
function waitForFinish()
{
if (g_swapsBeforeAck == 0) {
domAutomationController.send("SUCCESS");
} else {
g_swapsBeforeAck--;
window.requestAnimationFrame(waitForFinish);
}
}
</script>
</head>
<body onload="main()">
<div class="nomargin" style="position: absolute; top: 0px; left: 0px; height: 100px; width: 100px; background-color: red"></div>
<div id="container" style="position:absolute; top:0px; left:0px">
<canvas id="c" width="100" height="100" class="nomargin"></canvas>
</div>
<div class="nomargin" style="position: absolute; top: 0px; left: 50px; height: 50px; width: 50px; background-color: blue"></div>
</body>
</html>

@ -489,6 +489,10 @@ class PixelTestPages(object):
base_name + '_CanvasLowLatencyWebGLRoundedCorners',
test_rect=[0, 0, 100, 100],
other_args={'no_overlay': True}),
PixelTestPage('pixel_canvas_low_latency_webgl_occluded.html',
base_name + '_CanvasLowLatencyWebGLOccluded',
test_rect=[0, 0, 100, 100],
other_args={'no_overlay': True}),
]
# Only add these tests on platforms where SwiftShader is enabled.

@ -85,6 +85,7 @@ crbug.com/1084367 [ fuchsia no-use-skia-dawn ] Pixel_Video_VP9_DXVA [ Skip ]
crbug.com/1115673 [ fuchsia no-use-skia-dawn ] Pixel_WebGLCopyImage [ Skip ]
crbug.com/1115673 [ fuchsia ] Pixel_CanvasLowLatencyWebGLDrawImage [ Skip ]
crbug.com/1115673 [ fuchsia ] Pixel_CanvasLowLatencyWebGLRoundedCorners [ Skip ]
crbug.com/1115673 [ fuchsia ] Pixel_CanvasLowLatencyWebGLOccluded [ Skip ]
crbug.com/1096746 [ fuchsia no-use-skia-dawn ] Pixel_WebGL2_BlitFramebuffer_Result_Displayed [ Skip ]
crbug.com/1096746 [ fuchsia no-use-skia-dawn ] Pixel_WebGL2_ClearBufferfv_Result_Displayed [ Skip ]
crbug.com/1096746 [ fuchsia no-use-skia-dawn ] Pixel_CanvasLowLatencyWebGLAlphaFalse [ Skip ]
@ -287,6 +288,7 @@ crbug.com/1021566 [ linux use-skia-dawn ] Pixel_CanvasLowLatencyWebGL [ Skip ]
crbug.com/1021566 [ linux use-skia-dawn ] Pixel_CanvasLowLatencyWebGLAlphaFalse [ Skip ]
crbug.com/1021566 [ linux use-skia-dawn ] Pixel_CanvasLowLatencyWebGLDrawImage [ Skip ]
crbug.com/1021566 [ linux use-skia-dawn ] Pixel_CanvasLowLatencyWebGLRoundedCorners [ Skip ]
crbug.com/1021566 [ linux use-skia-dawn ] Pixel_CanvasLowLatencyWebGLOccluded [ Skip ]
crbug.com/1021566 [ linux use-skia-dawn ] Pixel_OffscreenCanvas2DResizeOnWorker [ Skip ]
crbug.com/1021566 [ linux use-skia-dawn ] Pixel_OffscreenCanvasTransferBeforeStyleResize [ Skip ]
crbug.com/1021566 [ linux use-skia-dawn ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ Skip ]
@ -307,6 +309,7 @@ crbug.com/1021566 [ win use-skia-dawn ] Pixel_CanvasLowLatencyWebGL [ Skip ]
crbug.com/1021566 [ win use-skia-dawn ] Pixel_CanvasLowLatencyWebGLAlphaFalse [ Skip ]
crbug.com/1021566 [ win use-skia-dawn ] Pixel_CanvasLowLatencyWebGLDrawImage [ Skip ]
crbug.com/1021566 [ win use-skia-dawn ] Pixel_CanvasLowLatencyWebGLRoundedCorners [ Skip ]
crbug.com/1021566 [ win use-skia-dawn ] Pixel_CanvasLowLatencyWebGLOccluded [ Skip ]
crbug.com/1021566 [ win use-skia-dawn ] Pixel_OffscreenCanvas2DResizeOnWorker [ Skip ]
crbug.com/1021566 [ win use-skia-dawn ] Pixel_OffscreenCanvasTransferBeforeStyleResize [ Skip ]
crbug.com/1021566 [ win use-skia-dawn ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ Skip ]