Landing Recent QUIC changes until 8/19/2015 17:00 UTC.
[chromium-blink-merge.git] / cc / output / overlay_strategy_sandwich.cc
blob1c02b8e73cbfb38e75a25f3e5ed2a9d427b889c5
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"
14 namespace {
16 gfx::Rect AlignPixelRectToDIP(float scale_factor, const gfx::Rect& pixel_rect) {
17 gfx::Rect dip_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));
28 } // namespace
30 namespace cc {
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))
50 return false;
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)
59 return false;
60 if (!IsPixelRectAlignedToDIP(device_scale_factor, candidate_pixel_rect))
61 return false;
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))
69 continue;
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
79 // covered region.
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)
116 return false;
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);
123 } else {
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);
142 return true;
145 } // namespace cc