blob: d111caf9b1779a59b5fd529831586040dac61d97 [file] [log] [blame]
// 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_interface.h"
#include <utility>
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/features.h"
#include "components/viz/service/display/overlay_processor_stub.h"
#if defined(OS_APPLE)
#include "components/viz/service/display/overlay_processor_mac.h"
#elif defined(OS_WIN)
#include "components/viz/service/display/overlay_processor_win.h"
#elif defined(OS_ANDROID)
#include "components/viz/service/display/overlay_processor_android.h"
#include "components/viz/service/display/overlay_processor_surface_control.h"
#elif defined(USE_OZONE)
#include "components/viz/service/display/overlay_processor_ozone.h"
#include "ui/base/ui_base_features.h"
#include "ui/ozone/public/overlay_manager_ozone.h"
#include "ui/ozone/public/ozone_platform.h"
#endif
namespace viz {
namespace {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class UnderlayDamage {
kZeroDamageRect,
kNonOccludingDamageOnly,
kOccludingDamageOnly,
kOccludingAndNonOccludingDamages,
kMaxValue = kOccludingAndNonOccludingDamages,
};
} // namespace
// Record UMA histograms for overlays
// 1. Underlay vs. Overlay
// 2. Full screen mode vs. Non Full screen (Windows) mode
// 3. Overlay zero damage rect vs. non zero damage rect
// 4. Underlay zero damage rect, non-zero damage rect with non-occluding damage
// only, non-zero damage rect with occluding damage, and non-zero damage rect
// with both damages
// static
void OverlayProcessorInterface::RecordOverlayDamageRectHistograms(
bool is_overlay,
bool has_occluding_surface_damage,
bool zero_damage_rect,
bool occluding_damage_equal_to_damage_rect) {
if (is_overlay) {
UMA_HISTOGRAM_BOOLEAN("Viz.DisplayCompositor.RootDamageRect.Overlay",
!zero_damage_rect);
} else { // underlay
UnderlayDamage underlay_damage = UnderlayDamage::kZeroDamageRect;
if (zero_damage_rect) {
underlay_damage = UnderlayDamage::kZeroDamageRect;
} else {
if (has_occluding_surface_damage) {
if (occluding_damage_equal_to_damage_rect) {
underlay_damage = UnderlayDamage::kOccludingDamageOnly;
} else {
underlay_damage = UnderlayDamage::kOccludingAndNonOccludingDamages;
}
} else {
underlay_damage = UnderlayDamage::kNonOccludingDamageOnly;
}
}
UMA_HISTOGRAM_ENUMERATION("Viz.DisplayCompositor.RootDamageRect.Underlay",
underlay_damage);
}
}
std::unique_ptr<OverlayProcessorInterface>
OverlayProcessorInterface::CreateOverlayProcessor(
OutputSurface* output_surface,
gpu::SharedImageManager* shared_image_manager,
const RendererSettings& renderer_settings,
const DebugRendererSettings* debug_settings) {
#if defined(OS_APPLE)
bool could_overlay =
output_surface->GetSurfaceHandle() != gpu::kNullSurfaceHandle;
could_overlay &= output_surface->capabilities().supports_surfaceless;
bool enable_ca_overlay = could_overlay && renderer_settings.allow_overlays;
return std::make_unique<OverlayProcessorMac>(could_overlay,
enable_ca_overlay);
#elif defined(OS_WIN)
return std::make_unique<OverlayProcessorWin>(
output_surface, std::make_unique<DCLayerOverlayProcessor>(
debug_settings, /*allowed_yuv_overlay_count=*/1));
#elif defined(USE_OZONE)
if (!features::IsUsingOzonePlatform())
return std::make_unique<OverlayProcessorStub>();
bool overlay_enabled =
output_surface->GetSurfaceHandle() != gpu::kNullSurfaceHandle;
overlay_enabled &= !renderer_settings.overlay_strategies.empty();
std::unique_ptr<ui::OverlayCandidatesOzone> overlay_candidates;
if (overlay_enabled) {
auto* overlay_manager =
ui::OzonePlatform::GetInstance()->GetOverlayManager();
overlay_candidates = overlay_manager->CreateOverlayCandidates(
output_surface->GetSurfaceHandle());
}
gpu::SharedImageInterface* shared_image_interface = nullptr;
if (overlay_enabled && features::ShouldUseRealBuffersForPageFlipTest()) {
CHECK(output_surface->context_provider());
shared_image_interface =
output_surface->context_provider()->SharedImageInterface();
CHECK(shared_image_interface);
}
return std::make_unique<OverlayProcessorOzone>(
overlay_enabled, std::move(overlay_candidates),
std::move(renderer_settings.overlay_strategies), shared_image_interface);
#elif defined(OS_ANDROID)
bool overlay_enabled =
output_surface->GetSurfaceHandle() != gpu::kNullSurfaceHandle;
if (output_surface->capabilities().supports_surfaceless) {
// This is for Android SurfaceControl case.
return std::make_unique<OverlayProcessorSurfaceControl>(overlay_enabled);
} else {
// When SurfaceControl is enabled, any resource backed by
// an AHardwareBuffer can be marked as an overlay candidate but it requires
// that we use a SurfaceControl backed GLSurface. If we're creating a
// native window backed GLSurface, the overlay processing code will
// incorrectly assume these resources can be overlaid. So we disable all
// overlay processing for this OutputSurface.
overlay_enabled &=
!output_surface->capabilities().android_surface_control_feature_enabled;
return std::make_unique<OverlayProcessorAndroid>(
shared_image_manager, output_surface->GetMemoryTracker(),
output_surface->GetGpuTaskSchedulerHelper(), overlay_enabled);
}
#else // Default
return std::make_unique<OverlayProcessorStub>();
#endif
}
bool OverlayProcessorInterface::DisableSplittingQuads() const {
return false;
}
OverlayProcessorInterface::OutputSurfaceOverlayPlane
OverlayProcessorInterface::ProcessOutputSurfaceAsOverlay(
const gfx::Size& viewport_size,
const gfx::BufferFormat& buffer_format,
const gfx::ColorSpace& color_space,
bool has_alpha,
const gpu::Mailbox& mailbox) {
OutputSurfaceOverlayPlane overlay_plane;
overlay_plane.transform = gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE;
overlay_plane.resource_size = viewport_size;
overlay_plane.format = buffer_format;
overlay_plane.color_space = color_space;
overlay_plane.enable_blending = has_alpha;
overlay_plane.mailbox = mailbox;
// Adjust transformation and display_rect based on display rotation.
overlay_plane.display_rect =
gfx::RectF(viewport_size.width(), viewport_size.height());
#if defined(ALWAYS_ENABLE_BLENDING_FOR_PRIMARY)
// On Chromecast, always use RGBA as the scanout format for the primary plane.
overlay_plane.enable_blending = true;
#endif
return overlay_plane;
}
void OverlayProcessorInterface::ScheduleOverlays(
DisplayResourceProvider* display_resource_provider) {}
void OverlayProcessorInterface::OverlayPresentationComplete() {}
} // namespace viz