Skip to content

Commit

Permalink
Basic delegated compositing prototype for LaCros
Browse files Browse the repository at this point in the history
This is the initial submission to support delegate compositing for
LaCros. Here a custom overlay processor is used to forward texture and
tile quads through Wayland over to Ash. Overall this mechanism has and
will have significant parallels to CALayer on Apple.

The quality level of the code and implementation in
"overlay_processor_delegated.h/cc" is prototype and only activated by
the "DelegatedCompositing" flag and only for LaCros.


Flags required for this prototype to operate:
(set in /etc/chrome_dev.conf)
--lacros-chrome-additional-args=
--enable-gpu-memory-buffer-compositor-resources
####
--enable-features=DelegatedCompositing



Design doc for prototype details:
https://docs.google.com/document/d/
1o6a-JTx42jKN21JuvIeEaWuqkmNVGdo33ogTseUkTpk/
edit?usp=sharing&resourcekey=0-hTc9nPF2GiFPEqZjzBPpYg

Bug: 1203918
Change-Id: Ie455a51a13de1051b62f254a2c25051b702b4620
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2927343
Commit-Queue: Peter McNeeley <petermcneeley@google.com>
Reviewed-by: Robert Kroeger <rjkroege@chromium.org>
Reviewed-by: Kramer Ge <fangzhoug@chromium.org>
Reviewed-by: kylechar <kylechar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#891818}
  • Loading branch information
petermcneeleychromium authored and Chromium LUCI CQ committed Jun 11, 2021
1 parent d8acb06 commit a01c259
Show file tree
Hide file tree
Showing 12 changed files with 362 additions and 3 deletions.
7 changes: 7 additions & 0 deletions components/viz/common/features.cc
Expand Up @@ -35,6 +35,9 @@ const base::Feature kEnableOverlayPrioritization {
#endif
};

const base::Feature kDelegatedCompositing{"DelegatedCompositing",
base::FEATURE_DISABLED_BY_DEFAULT};

const base::Feature kSimpleFrameRateThrottling{
"SimpleFrameRateThrottling", base::FEATURE_DISABLED_BY_DEFAULT};

Expand Down Expand Up @@ -147,6 +150,10 @@ bool IsOverlayPrioritizationEnabled() {
return base::FeatureList::IsEnabled(kEnableOverlayPrioritization);
}

bool IsDelegatedCompositingEnabled() {
return base::FeatureList::IsEnabled(kDelegatedCompositing);
}

// If a synchronous IPC should used when destroying windows. This exists to test
// the impact of removing the sync IPC.
bool IsSyncWindowDestructionEnabled() {
Expand Down
1 change: 1 addition & 0 deletions components/viz/common/features.h
Expand Up @@ -48,6 +48,7 @@ VIZ_COMMON_EXPORT bool IsSimpleFrameRateThrottlingEnabled();
VIZ_COMMON_EXPORT bool IsDynamicColorGamutEnabled();
#endif
VIZ_COMMON_EXPORT bool IsOverlayPrioritizationEnabled();
VIZ_COMMON_EXPORT bool IsDelegatedCompositingEnabled();
VIZ_COMMON_EXPORT bool IsSyncWindowDestructionEnabled();
VIZ_COMMON_EXPORT bool IsUsingFastPathForSolidColorQuad();
VIZ_COMMON_EXPORT bool IsUsingSkiaRenderer();
Expand Down
2 changes: 2 additions & 0 deletions components/viz/service/BUILD.gn
Expand Up @@ -327,6 +327,8 @@ viz_component("service") {

if (use_ozone) {
sources += [
"display/overlay_processor_delegated.cc",
"display/overlay_processor_delegated.h",
"display/overlay_processor_ozone.cc",
"display/overlay_processor_ozone.h",
"display_embedder/software_output_device_ozone.cc",
Expand Down
5 changes: 5 additions & 0 deletions components/viz/service/display/display_resource_provider.cc
Expand Up @@ -15,6 +15,7 @@
#include "base/trace_event/trace_event.h"
#include "components/viz/common/resources/resource_sizes.h"
#include "gpu/command_buffer/common/shared_image_trace_utils.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/trace_util.h"

namespace viz {
Expand Down Expand Up @@ -150,6 +151,10 @@ bool DisplayResourceProvider::IsResourceSoftwareBacked(ResourceId id) {
return GetResource(id)->transferable.is_software;
}

const gfx::Size DisplayResourceProvider::GetResourceBackedSize(ResourceId id) {
return GetResource(id)->transferable.size;
}

gfx::BufferFormat DisplayResourceProvider::GetBufferFormat(ResourceId id) {
return BufferFormat(GetResourceFormat(id));
}
Expand Down
3 changes: 3 additions & 0 deletions components/viz/service/display/display_resource_provider.h
Expand Up @@ -79,6 +79,9 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
bool DoesResourceWantPromotionHint(ResourceId id);
#endif

// Returns the size in pixels of the underlying gpu mailbox/software bitmap.
const gfx::Size GetResourceBackedSize(ResourceId id);

bool IsResourceSoftwareBacked(ResourceId id);
// Return the format of the underlying buffer that can be used for scanout.
gfx::BufferFormat GetBufferFormat(ResourceId id);
Expand Down
41 changes: 40 additions & 1 deletion components/viz/service/display/overlay_candidate.cc
Expand Up @@ -18,10 +18,12 @@
#include "components/viz/common/quads/tile_draw_quad.h"
#include "components/viz/common/quads/video_hole_draw_quad.h"
#include "components/viz/common/quads/yuv_video_draw_quad.h"
#include "components/viz/service/debugger/viz_debugger.h"
#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/overlay_processor_interface.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/vector3d_f.h"
#include "ui/gfx/video_types.h"

Expand Down Expand Up @@ -133,7 +135,8 @@ bool OverlayCandidate::FromDrawQuad(
const SkMatrix44& output_color_matrix,
const DrawQuad* quad,
const gfx::RectF& primary_rect,
OverlayCandidate* candidate) {
OverlayCandidate* candidate,
bool allow_delegated_quads) {
// It is currently not possible to set a color conversion matrix on an HW
// overlay plane.
// TODO(https://crbug.com/792757): Remove this check once the bug is resolved.
Expand Down Expand Up @@ -169,6 +172,12 @@ bool OverlayCandidate::FromDrawQuad(
return FromStreamVideoQuad(resource_provider, surface_damage_rect_list,
StreamVideoDrawQuad::MaterialCast(quad),
candidate);
case DrawQuad::Material::kTiledContent:
if (!allow_delegated_quads)
return false;
return candidate->FromTileQuad(
resource_provider, surface_damage_rect_list,
TileDrawQuad::MaterialCast(quad), primary_rect, candidate);
default:
break;
}
Expand Down Expand Up @@ -355,6 +364,36 @@ bool OverlayCandidate::FromVideoHoleQuad(
return true;
}

bool OverlayCandidate::FromTileQuad(
DisplayResourceProvider* resource_provider,
SurfaceDamageRectList* surface_damage_rect_list,
const TileDrawQuad* quad,
const gfx::RectF& primary_rect,
OverlayCandidate* candidate) {
if (quad->nearest_neighbor)
return false;

if (!FromDrawQuadResource(resource_provider, surface_damage_rect_list, quad,
quad->resource_id(), false, candidate)) {
return false;
}

candidate->resource_size_in_pixels =
resource_provider->GetResourceBackedSize(quad->resource_id());

float x = quad->tex_coord_rect.origin().x() /
candidate->resource_size_in_pixels.width();
float xw = quad->tex_coord_rect.size().width() /
candidate->resource_size_in_pixels.width();
float y = quad->tex_coord_rect.origin().y() /
candidate->resource_size_in_pixels.height();
float yh = quad->tex_coord_rect.size().height() /
candidate->resource_size_in_pixels.height();
candidate->uv_rect = gfx::RectF(x, y, xw, yh);

return true;
}

// static
bool OverlayCandidate::FromTextureQuad(
DisplayResourceProvider* resource_provider,
Expand Down
10 changes: 9 additions & 1 deletion components/viz/service/display/overlay_candidate.h
Expand Up @@ -11,6 +11,7 @@
#include "base/containers/flat_map.h"
#include "build/build_config.h"
#include "components/viz/common/quads/aggregated_render_pass.h"
#include "components/viz/common/quads/tile_draw_quad.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/service/display/aggregated_frame.h"
#include "components/viz/service/viz_service_export.h"
Expand Down Expand Up @@ -43,7 +44,8 @@ class VIZ_SERVICE_EXPORT OverlayCandidate {
const SkMatrix44& output_color_matrix,
const DrawQuad* quad,
const gfx::RectF& primary_rect,
OverlayCandidate* candidate);
OverlayCandidate* candidate,
bool allow_delegated_quads = false);
// Returns true if |quad| will not block quads underneath from becoming
// an overlay.
static bool IsInvisibleQuad(const DrawQuad* quad);
Expand Down Expand Up @@ -154,6 +156,12 @@ class VIZ_SERVICE_EXPORT OverlayCandidate {
const TextureDrawQuad* quad,
const gfx::RectF& primary_rect,
OverlayCandidate* candidate);

static bool FromTileQuad(DisplayResourceProvider* resource_provider,
SurfaceDamageRectList* surface_damage_rect_list,
const TileDrawQuad* quad,
const gfx::RectF& primary_rect,
OverlayCandidate* candidate);
static bool FromStreamVideoQuad(
DisplayResourceProvider* resource_provider,
SurfaceDamageRectList* surface_damage_rect_list,
Expand Down
185 changes: 185 additions & 0 deletions components/viz/service/display/overlay_processor_delegated.cc
@@ -0,0 +1,185 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/viz/service/display/overlay_processor_delegated.h"

#include <algorithm>
#include <memory>
#include <set>
#include <utility>
#include <vector>

#include "base/feature_list.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/viz/common/features.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/service/debugger/viz_debugger.h"
#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/overlay_candidate.h"
#include "components/viz/service/display/overlay_processor_interface.h"
#include "components/viz/service/display/overlay_strategy_fullscreen.h"
#include "components/viz/service/display/overlay_strategy_single_on_top.h"
#include "components/viz/service/display/overlay_strategy_underlay.h"
#include "components/viz/service/display/overlay_strategy_underlay_cast.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/service/shared_image_manager.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gfx/transform.h"

#include "components/viz/common/quads/texture_draw_quad.h"

namespace viz {

OverlayProcessorDelegated::OverlayProcessorDelegated(
std::unique_ptr<ui::OverlayCandidatesOzone> overlay_candidates,
std::vector<OverlayStrategy> available_strategies,
gpu::SharedImageInterface* shared_image_interface)
: OverlayProcessorOzone(std::move(overlay_candidates),
available_strategies,
shared_image_interface) {}

OverlayProcessorDelegated::~OverlayProcessorDelegated() = default;

bool OverlayProcessorDelegated::AttemptWithStrategies(
const SkMatrix44& output_color_matrix,
const OverlayProcessorInterface::FilterOperationsMap&
render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
AggregatedRenderPassList* render_pass_list,
SurfaceDamageRectList* surface_damage_rect_list,
OverlayProcessorInterface::OutputSurfaceOverlayPlane* primary_plane,
OverlayCandidateList* candidates,
std::vector<gfx::Rect>* content_bounds) {
DCHECK(candidates->empty());

auto* render_pass = render_pass_list->back().get();
QuadList* quad_list = &render_pass->quad_list;
const bool allow_delegated_quads = true;

// Wayland overlay forwarding mechanism does not support putting the same
// buffer on multiple surfaces. We use this |candidate_ids| for best effort
// service and simply skip duplicate resource id quads.
std::set<ResourceId> candidate_ids;
std::vector<QuadList::Iterator> candidate_quads;
for (auto it = quad_list->begin(); it != quad_list->end(); ++it) {
OverlayCandidate candidate;
auto& transform = it->shared_quad_state->quad_to_target_transform;
auto display_rect = gfx::RectF(it->rect);
transform.TransformRect(&display_rect);
DBG_DRAW_TEXT(
"delegated.overlay.type",
gfx::Vector2dF(display_rect.origin().x(), display_rect.origin().y()),
base::StringPrintf("m=%d rid=%d", static_cast<int>(it->material),
it->resources.begin()->value()));
if (OverlayCandidate::FromDrawQuad(
resource_provider, surface_damage_rect_list, output_color_matrix,
*it, GetPrimaryPlaneDisplayRect(primary_plane), &candidate,
allow_delegated_quads)) {
// Setting the |uv_rect| will eventually result in setting the
// |crop_rect_| in wayland. If this results in an empty pixel scale the
// wayland connection will be terminated. See: wayland_surface.cc
// 'UpdateBufferDamageRegion'
auto viewport_src = gfx::ToEnclosedRect(gfx::ScaleRect(
candidate.uv_rect, candidate.resource_size_in_pixels.width(),
candidate.resource_size_in_pixels.height()));
// Because of the device scale factor (2) we check against a rounded empty
// rect.
// TODO(https://crbug.com/1218678) : Move and generalize this fix in
// wayland host.
if (viewport_src.width() <= 2 || viewport_src.height() <= 2) {
DBG_DRAW_RECT("delegated.overlay.subpixelskip", candidate.display_rect);
continue;
}

if (candidate_ids.find(candidate.resource_id) == candidate_ids.end()) {
candidate_ids.insert(candidate.resource_id);
DBG_DRAW_RECT("delegated.overlay.candidate", candidate.display_rect);
candidates->push_back(candidate);
candidate_quads.push_back(it);
} else {
DBG_DRAW_RECT("delegated.overlay.dupskip", candidate.display_rect);
}

} else {
DBG_DRAW_RECT("delegated.overlay.failed", display_rect);
}
}

if (candidates->empty())
return false;

int curr_plane_order = candidates->size();
for (auto&& each : *candidates) {
each.plane_z_order = curr_plane_order--;
}
// Check for support.
this->CheckOverlaySupport(primary_plane, candidates);

// Reverse iterate to avoid iterator invalidation of future elements.
auto quad_to_iter = candidate_quads.rbegin();
for (auto candidate = candidates->rbegin(); candidate != candidates->rend();
candidate++, quad_to_iter++) {
if (candidate->overlay_handled) {
quad_list->EraseAndInvalidateAllPointers(*quad_to_iter);
}
}

return true;
}

gfx::RectF OverlayProcessorDelegated::GetPrimaryPlaneDisplayRect(
const OverlayProcessorInterface::OutputSurfaceOverlayPlane* primary_plane) {
return primary_plane ? primary_plane->display_rect : gfx::RectF();
}

void OverlayProcessorDelegated::ProcessForOverlays(
DisplayResourceProvider* resource_provider,
AggregatedRenderPassList* render_passes,
const SkMatrix44& output_color_matrix,
const OverlayProcessorInterface::FilterOperationsMap& render_pass_filters,
const OverlayProcessorInterface::FilterOperationsMap&
render_pass_backdrop_filters,
SurfaceDamageRectList surface_damage_rect_list,
OutputSurfaceOverlayPlane* output_surface_plane,
CandidateList* candidates,
gfx::Rect* damage_rect,
std::vector<gfx::Rect>* content_bounds) {
DCHECK(candidates->empty());
auto* render_pass = render_passes->back().get();
bool success = false;

DBG_DRAW_RECT("delegated.incoming.damage", (*damage_rect));
for (auto&& each : surface_damage_rect_list) {
DBG_DRAW_RECT("delegated.surface.damage", each);
}

// If we have any copy requests, we can't remove any quads for overlays or
// CALayers because the framebuffer would be missing the removed quads'
// contents.
if (render_pass->copy_requests.empty()) {
success = AttemptWithStrategies(
output_color_matrix, render_pass_backdrop_filters, resource_provider,
render_passes, &surface_damage_rect_list, output_surface_plane,
candidates, content_bounds);
}

DCHECK(candidates->empty() || success);
// TODO(petermcneeley) : Actually modify the damage here. When all damaged
// quads are forwarded the damage here will be empty.
DBG_DRAW_RECT("delegated.outgoing.damage", (*damage_rect));

TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("viz.debug.overlay_planes"),
"Scheduled overlay planes", candidates->size());
}

} // namespace viz

0 comments on commit a01c259

Please sign in to comment.