1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/viz/service/display/overlay_processor_surface_control.h"
6
7 #include "components/viz/service/display/overlay_strategy_underlay.h"
8 #include "ui/gfx/geometry/rect_conversions.h"
9 #include "ui/gfx/overlay_transform_utils.h"
10 #include "ui/gl/android/android_surface_control_compat.h"
11
12 namespace viz {
13 namespace {
14
ClipFromOrigin(gfx::RectF input)15 gfx::RectF ClipFromOrigin(gfx::RectF input) {
16 if (input.x() < 0.f) {
17 input.set_width(input.width() + input.x());
18 input.set_x(0.f);
19 }
20
21 if (input.y() < 0) {
22 input.set_height(input.height() + input.y());
23 input.set_y(0.f);
24 }
25
26 return input;
27 }
28
29 } // namespace
30
OverlayProcessorSurfaceControl(bool enable_overlay)31 OverlayProcessorSurfaceControl::OverlayProcessorSurfaceControl(
32 bool enable_overlay)
33 : OverlayProcessorUsingStrategy(), overlay_enabled_(enable_overlay) {
34 if (overlay_enabled_) {
35 strategies_.push_back(std::make_unique<OverlayStrategyUnderlay>(
36 this, OverlayStrategyUnderlay::OpaqueMode::AllowTransparentCandidates));
37 }
38 }
39
~OverlayProcessorSurfaceControl()40 OverlayProcessorSurfaceControl::~OverlayProcessorSurfaceControl() {}
41
IsOverlaySupported() const42 bool OverlayProcessorSurfaceControl::IsOverlaySupported() const {
43 return overlay_enabled_;
44 }
45
NeedsSurfaceOccludingDamageRect() const46 bool OverlayProcessorSurfaceControl::NeedsSurfaceOccludingDamageRect() const {
47 return true;
48 }
49
CheckOverlaySupport(const OverlayProcessorInterface::OutputSurfaceOverlayPlane * primary_plane,OverlayCandidateList * candidates)50 void OverlayProcessorSurfaceControl::CheckOverlaySupport(
51 const OverlayProcessorInterface::OutputSurfaceOverlayPlane* primary_plane,
52 OverlayCandidateList* candidates) {
53 DCHECK(!candidates->empty());
54
55 for (auto& candidate : *candidates) {
56 if (!gl::SurfaceControl::SupportsColorSpace(candidate.color_space)) {
57 candidate.overlay_handled = false;
58 return;
59 }
60
61 // Check if screen rotation matches.
62 if (candidate.transform != display_transform_) {
63 candidate.overlay_handled = false;
64 return;
65 }
66 candidate.transform = gfx::OVERLAY_TRANSFORM_NONE;
67
68 gfx::RectF orig_display_rect = candidate.display_rect;
69 gfx::RectF display_rect = orig_display_rect;
70 if (candidate.is_clipped)
71 display_rect.Intersect(gfx::RectF(candidate.clip_rect));
72 // The framework doesn't support display rects positioned at a negative
73 // offset.
74 display_rect = ClipFromOrigin(display_rect);
75 if (display_rect.IsEmpty()) {
76 candidate.overlay_handled = false;
77 return;
78 }
79
80 // The display rect above includes the |display_transform_| while the rects
81 // sent to the platform API need to be in the logical screen space.
82 const gfx::Transform display_inverse = gfx::OverlayTransformToTransform(
83 gfx::InvertOverlayTransform(display_transform_),
84 gfx::SizeF(viewport_size_));
85 display_inverse.TransformRect(&orig_display_rect);
86 display_inverse.TransformRect(&display_rect);
87
88 candidate.display_rect = gfx::RectF(gfx::ToEnclosingRect(display_rect));
89 candidate.uv_rect = cc::MathUtil::ScaleRectProportional(
90 candidate.uv_rect, orig_display_rect, candidate.display_rect);
91 candidate.overlay_handled = true;
92 }
93 }
94
AdjustOutputSurfaceOverlay(base::Optional<OutputSurfaceOverlayPlane> * output_surface_plane)95 void OverlayProcessorSurfaceControl::AdjustOutputSurfaceOverlay(
96 base::Optional<OutputSurfaceOverlayPlane>* output_surface_plane) {
97 // For surface control, we should always have a valid |output_surface_plane|
98 // here.
99 DCHECK(output_surface_plane && output_surface_plane->has_value());
100
101 OutputSurfaceOverlayPlane& plane = output_surface_plane->value();
102 DCHECK(gl::SurfaceControl::SupportsColorSpace(plane.color_space))
103 << "The main overlay must only use color space supported by the "
104 "device";
105
106 DCHECK_EQ(plane.transform, gfx::OVERLAY_TRANSFORM_NONE);
107 DCHECK(plane.display_rect == ClipFromOrigin(plane.display_rect));
108
109 plane.transform = display_transform_;
110 const gfx::Transform display_inverse = gfx::OverlayTransformToTransform(
111 gfx::InvertOverlayTransform(display_transform_),
112 gfx::SizeF(viewport_size_));
113 display_inverse.TransformRect(&plane.display_rect);
114 plane.display_rect = gfx::RectF(gfx::ToEnclosingRect(plane.display_rect));
115
116 // Call the base class implementation.
117 OverlayProcessorUsingStrategy::AdjustOutputSurfaceOverlay(
118 output_surface_plane);
119 }
120
GetOverlayDamageRectForOutputSurface(const OverlayCandidate & candidate) const121 gfx::Rect OverlayProcessorSurfaceControl::GetOverlayDamageRectForOutputSurface(
122 const OverlayCandidate& candidate) const {
123 // Should only be called after ProcessForOverlays on handled candidates.
124 DCHECK(candidate.overlay_handled);
125 // We transform the candidate's display rect to the logical screen space (used
126 // by the ui when preparing the frame) that the SurfaceControl expects it to
127 // be in. So in order to provide a damage rect which maps to the
128 // OutputSurface's main plane, we need to undo that transformation. But only
129 // if the overlay is in handled state, since the modification above is only
130 // applied when we mark the overlay as handled.
131 gfx::Size viewport_size_pre_display_transform(viewport_size_.height(),
132 viewport_size_.width());
133 auto transform = gfx::OverlayTransformToTransform(
134 display_transform_, gfx::SizeF(viewport_size_pre_display_transform));
135 gfx::RectF transformed_rect(candidate.display_rect);
136 transform.TransformRect(&transformed_rect);
137 return gfx::ToEnclosedRect(transformed_rect);
138 }
139
SetDisplayTransformHint(gfx::OverlayTransform transform)140 void OverlayProcessorSurfaceControl::SetDisplayTransformHint(
141 gfx::OverlayTransform transform) {
142 display_transform_ = transform;
143 }
144
SetViewportSize(const gfx::Size & viewport_size)145 void OverlayProcessorSurfaceControl::SetViewportSize(
146 const gfx::Size& viewport_size) {
147 viewport_size_ = viewport_size;
148 }
149
150 } // namespace viz
151