| // 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 <vector> |
| |
| #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/display_compositor_memory_and_task_controller.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, // deprecated |
| 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) { |
| 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) { |
| 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::SurfaceHandle surface_handle, |
| const OutputSurface::Capabilities& capabilities, |
| DisplayCompositorMemoryAndTaskController* display_controller, |
| gpu::SharedImageInterface* shared_image_interface, |
| const RendererSettings& renderer_settings, |
| const DebugRendererSettings* debug_settings) { |
| // If we are offscreen, we don't have overlay support. |
| // TODO(vasilyt): WebView would have a kNullSurfaceHandle. Make sure when |
| // overlay for WebView is enabled, this check still works. |
| if (surface_handle == gpu::kNullSurfaceHandle) |
| return std::make_unique<OverlayProcessorStub>(); |
| |
| #if defined(OS_APPLE) |
| DCHECK(capabilities.supports_surfaceless); |
| |
| return std::make_unique<OverlayProcessorMac>( |
| renderer_settings.allow_overlays); |
| #elif defined(OS_WIN) |
| if (!capabilities.supports_dc_layers) |
| return std::make_unique<OverlayProcessorStub>(); |
| |
| 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>(); |
| |
| // In tests and Ozone/X11, we do not expect surfaceless surface support. |
| if (!capabilities.supports_surfaceless) |
| return std::make_unique<OverlayProcessorStub>(); |
| |
| std::unique_ptr<ui::OverlayCandidatesOzone> overlay_candidates; |
| if (!renderer_settings.overlay_strategies.empty()) { |
| auto* overlay_manager = |
| ui::OzonePlatform::GetInstance()->GetOverlayManager(); |
| overlay_candidates = |
| overlay_manager->CreateOverlayCandidates(surface_handle); |
| } |
| |
| gpu::SharedImageInterface* sii = nullptr; |
| if (features::ShouldUseRealBuffersForPageFlipTest()) { |
| sii = shared_image_interface; |
| CHECK(shared_image_interface); |
| } |
| |
| return std::make_unique<OverlayProcessorOzone>( |
| std::move(overlay_candidates), |
| std::move(renderer_settings.overlay_strategies), sii); |
| #elif defined(OS_ANDROID) |
| DCHECK(display_controller); |
| |
| if (capabilities.supports_surfaceless) { |
| // This is for Android SurfaceControl case. |
| return std::make_unique<OverlayProcessorSurfaceControl>(); |
| } 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. |
| if (capabilities.android_surface_control_feature_enabled) |
| return std::make_unique<OverlayProcessorStub>(); |
| |
| return std::make_unique<OverlayProcessorAndroid>(display_controller); |
| } |
| #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 |