1 // Copyright 2015 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.
5 #include "cc/output/overlay_strategy_sandwich.h"
7 #include "cc/base/region.h"
8 #include "cc/output/overlay_candidate_validator.h"
9 #include "cc/quads/draw_quad.h"
10 #include "cc/quads/solid_color_draw_quad.h"
11 #include "ui/gfx/geometry/dip_util.h"
12 #include "ui/gfx/geometry/rect_conversions.h"
16 gfx::Rect
AlignPixelRectToDIP(float scale_factor
, const gfx::Rect
& pixel_rect
) {
18 gfx::ToEnclosingRect(gfx::ScaleRect(pixel_rect
, 1.0f
/ scale_factor
));
19 gfx::Rect new_pixel_rect
=
20 gfx::ToEnclosingRect(gfx::ScaleRect(dip_rect
, scale_factor
));
21 return new_pixel_rect
;
24 bool IsPixelRectAlignedToDIP(float scale_factor
, const gfx::Rect
& pixel_rect
) {
25 return (pixel_rect
== AlignPixelRectToDIP(scale_factor
, pixel_rect
));
32 OverlayStrategySandwich::~OverlayStrategySandwich() {}
34 bool OverlayStrategySandwich::TryOverlay(
35 OverlayCandidateValidator
* capability_checker
,
36 RenderPassList
* render_passes_in_draw_order
,
37 OverlayCandidateList
* output_candidate_list
,
38 const OverlayCandidate
& candidate
,
39 QuadList::Iterator candidate_iter_in_quad_list
,
40 float device_scale_factor
) {
41 RenderPass
* root_render_pass
= render_passes_in_draw_order
->back();
42 QuadList
& quad_list
= root_render_pass
->quad_list
;
43 gfx::Rect pixel_bounds
= root_render_pass
->output_rect
;
45 const DrawQuad
* candidate_quad
= *candidate_iter_in_quad_list
;
46 const gfx::Transform
& candidate_transform
=
47 candidate_quad
->shared_quad_state
->quad_to_target_transform
;
48 gfx::Transform candidate_inverse_transform
;
49 if (!candidate_transform
.GetInverse(&candidate_inverse_transform
))
52 // Compute the candidate's rect in display space (pixels on the screen). The
53 // rect needs to be DIP-aligned, or we cannot use it.
54 gfx::RectF candidate_pixel_rect_float
= candidate_quad
->rect
;
55 candidate_transform
.TransformRect(&candidate_pixel_rect_float
);
56 gfx::Rect candidate_pixel_rect
;
57 candidate_pixel_rect
= gfx::ToEnclosingRect(candidate_pixel_rect_float
);
58 if (candidate_pixel_rect
!= candidate_pixel_rect_float
)
60 if (!IsPixelRectAlignedToDIP(device_scale_factor
, candidate_pixel_rect
))
63 // Iterate through the quads in front of |potential_candidate|, and compute
64 // the region of |potential_candidate| that is covered.
65 Region pixel_covered_region
;
66 for (auto overlap_iter
= quad_list
.cbegin();
67 overlap_iter
!= candidate_iter_in_quad_list
; ++overlap_iter
) {
68 if (OverlayStrategyCommon::IsInvisibleQuad(*overlap_iter
))
70 // Compute the quad's bounds in display space, and ensure that it is rounded
71 // up to be DIP-aligned.
72 gfx::RectF pixel_covered_rect_float
= overlap_iter
->rect
;
73 overlap_iter
->shared_quad_state
->quad_to_target_transform
.TransformRect(
74 &pixel_covered_rect_float
);
75 gfx::Rect pixel_covered_rect
= AlignPixelRectToDIP(
76 device_scale_factor
, gfx::ToEnclosingRect(pixel_covered_rect_float
));
78 // Include the intersection of that quad with the candidate's quad in the
80 pixel_covered_rect
.Intersect(candidate_pixel_rect
);
81 pixel_covered_region
.Union(pixel_covered_rect
);
84 // Add our primary surface.
85 OverlayCandidateList new_candidate_list
;
86 OverlayCandidate main_image
;
87 main_image
.display_rect
= pixel_bounds
;
88 new_candidate_list
.push_back(main_image
);
90 // Add the candidate's overlay.
91 DCHECK(candidate
.resource_id
);
92 new_candidate_list
.push_back(candidate
);
93 new_candidate_list
.back().plane_z_order
= 1;
95 // Add an overlay of the primary surface for any part of the candidate's
96 // quad that was covered.
97 // TODO(ccameron): Create an OverlayCandidate for each rect in the region.
98 gfx::Rect pixel_covered_rect
= pixel_covered_region
.bounds();
99 DCHECK(IsPixelRectAlignedToDIP(device_scale_factor
, pixel_covered_rect
));
100 if (!pixel_covered_rect
.IsEmpty()) {
101 OverlayCandidate main_image_on_top
;
102 main_image_on_top
.display_rect
= pixel_covered_rect
;
103 main_image_on_top
.uv_rect
= pixel_covered_rect
;
104 main_image_on_top
.uv_rect
.Scale(1.f
/ pixel_bounds
.width(),
105 1.f
/ pixel_bounds
.height());
106 main_image_on_top
.plane_z_order
= 2;
107 main_image_on_top
.transform
= gfx::OVERLAY_TRANSFORM_NONE
;
108 main_image_on_top
.use_output_surface_for_resource
= true;
109 new_candidate_list
.push_back(main_image_on_top
);
112 // Check for support.
113 capability_checker
->CheckOverlaySupport(&new_candidate_list
);
114 for (const OverlayCandidate
& candidate
: new_candidate_list
) {
115 if (candidate
.plane_z_order
> 0 && !candidate
.overlay_handled
)
119 // Remove the quad for the overlay quad. Replace it with a transparent quad
120 // if we're putting a new overlay on top.
121 if (pixel_covered_rect
.IsEmpty()) {
122 quad_list
.EraseAndInvalidateAllPointers(candidate_iter_in_quad_list
);
124 gfx::RectF quad_space_covered_rect_float
= pixel_covered_rect
;
125 candidate_inverse_transform
.TransformRect(&quad_space_covered_rect_float
);
126 gfx::Rect quad_space_covered_rect
=
127 gfx::ToEnclosingRect(quad_space_covered_rect_float
);
128 quad_space_covered_rect
.Intersect(candidate_quad
->rect
);
130 const SharedQuadState
* shared_quad_state
=
131 candidate_quad
->shared_quad_state
;
133 SolidColorDrawQuad
* replacement
=
134 quad_list
.ReplaceExistingElement
<SolidColorDrawQuad
>(
135 candidate_iter_in_quad_list
);
136 replacement
->SetAll(shared_quad_state
, quad_space_covered_rect
,
137 quad_space_covered_rect
, quad_space_covered_rect
, false,
138 SK_ColorTRANSPARENT
, true);
141 output_candidate_list
->swap(new_candidate_list
);