OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/output/dc_layer_overlay.h" | 5 #include "cc/output/dc_layer_overlay.h" |
6 | 6 |
7 #include "base/metrics/histogram_macros.h" | 7 #include "base/metrics/histogram_macros.h" |
8 #include "cc/base/math_util.h" | 8 #include "cc/base/math_util.h" |
9 #include "cc/quads/solid_color_draw_quad.h" | 9 #include "cc/quads/solid_color_draw_quad.h" |
10 #include "cc/quads/yuv_video_draw_quad.h" | 10 #include "cc/quads/yuv_video_draw_quad.h" |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 return result; | 122 return result; |
123 } | 123 } |
124 | 124 |
125 void DCLayerOverlayProcessor::Process(ResourceProvider* resource_provider, | 125 void DCLayerOverlayProcessor::Process(ResourceProvider* resource_provider, |
126 const gfx::RectF& display_rect, | 126 const gfx::RectF& display_rect, |
127 QuadList* quad_list, | 127 QuadList* quad_list, |
128 gfx::Rect* overlay_damage_rect, | 128 gfx::Rect* overlay_damage_rect, |
129 gfx::Rect* damage_rect, | 129 gfx::Rect* damage_rect, |
130 DCLayerOverlayList* ca_layer_overlays) { | 130 DCLayerOverlayList* ca_layer_overlays) { |
131 gfx::Rect this_frame_underlay_rect; | 131 gfx::Rect this_frame_underlay_rect; |
132 bool display_rect_changed = (display_rect != previous_display_rect_); | |
133 for (auto it = quad_list->begin(); it != quad_list->end(); ++it) { | 132 for (auto it = quad_list->begin(); it != quad_list->end(); ++it) { |
134 DCLayerOverlay ca_layer; | 133 DCLayerOverlay dc_layer; |
135 DCLayerResult result = FromDrawQuad(resource_provider, display_rect, | 134 DCLayerResult result = FromDrawQuad(resource_provider, display_rect, |
136 quad_list->begin(), it, &ca_layer); | 135 quad_list->begin(), it, &dc_layer); |
137 if (result != DC_LAYER_SUCCESS) { | 136 if (result != DC_LAYER_SUCCESS) { |
138 RecordDCLayerResult(result); | 137 RecordDCLayerResult(result); |
139 continue; | 138 continue; |
140 } | 139 } |
141 | 140 |
142 if (!it->shared_quad_state->quad_to_target_transform | 141 if (!it->shared_quad_state->quad_to_target_transform |
143 .Preserves2dAxisAlignment() && | 142 .Preserves2dAxisAlignment() && |
144 !base::FeatureList::IsEnabled( | 143 !base::FeatureList::IsEnabled( |
145 features::kDirectCompositionComplexOverlays)) { | 144 features::kDirectCompositionComplexOverlays)) { |
146 RecordDCLayerResult(DC_LAYER_FAILED_COMPLEX_TRANSFORM); | 145 RecordDCLayerResult(DC_LAYER_FAILED_COMPLEX_TRANSFORM); |
147 continue; | 146 continue; |
148 } | 147 } |
149 | 148 |
150 gfx::Rect quad_rectangle = gfx::ToEnclosingRect(ClippedQuadRectangle(*it)); | 149 gfx::Rect quad_rectangle = gfx::ToEnclosingRect(ClippedQuadRectangle(*it)); |
151 gfx::RectF occlusion_bounding_box = | 150 gfx::RectF occlusion_bounding_box = |
152 GetOcclusionBounds(gfx::RectF(quad_rectangle), quad_list->begin(), it); | 151 GetOcclusionBounds(gfx::RectF(quad_rectangle), quad_list->begin(), it); |
153 if (occlusion_bounding_box.IsEmpty()) { | |
154 // The quad is on top, so promote it to an overlay and remove all damage | |
155 // underneath it. | |
156 if (it->shared_quad_state->quad_to_target_transform | |
157 .Preserves2dAxisAlignment() && | |
158 !display_rect_changed && !it->ShouldDrawWithBlending()) { | |
159 damage_rect->Subtract(quad_rectangle); | |
160 } | |
161 quad_list->EraseAndInvalidateAllPointers(it); | |
162 } else if (!base::FeatureList::IsEnabled( | |
163 features::kDirectCompositionUnderlays)) { | |
164 RecordDCLayerResult(DC_LAYER_FAILED_OCCLUDED); | |
165 continue; | |
166 } else { | |
167 // The quad is occluded, so replace it with a black solid color quad and | |
168 // place the overlay itself under the quad. | |
169 if (it->shared_quad_state->quad_to_target_transform | |
170 .IsIdentityOrIntegerTranslation()) { | |
171 this_frame_underlay_rect = quad_rectangle; | |
172 } | |
173 ca_layer.shared_state->z_order = -1; | |
174 const SharedQuadState* shared_quad_state = it->shared_quad_state; | |
175 gfx::Rect rect = it->visible_rect; | |
176 SolidColorDrawQuad* replacement = | |
177 quad_list->ReplaceExistingElement<SolidColorDrawQuad>(it); | |
178 replacement->SetAll(shared_quad_state, rect, rect, rect, false, | |
179 SK_ColorTRANSPARENT, true); | |
180 | 152 |
181 if (this_frame_underlay_rect == previous_frame_underlay_rect_) { | 153 // Underlays are less efficient, so attempt regular overlays first. |
182 // If this underlay rect is the same as for last frame, subtract its | 154 if (ProcessForOverlay(display_rect, quad_list, quad_rectangle, |
183 // area from the damage of the main surface, as the cleared area was | 155 occlusion_bounding_box, it, damage_rect) || |
184 // already cleared last frame. Add back the damage from the occluded | 156 ProcessForUnderlay(display_rect, quad_list, quad_rectangle, |
185 // area for this and last frame, as that may have changed. | 157 occlusion_bounding_box, it, damage_rect, |
186 if (it->shared_quad_state->quad_to_target_transform | 158 &this_frame_underlay_rect, &dc_layer)) { |
187 .Preserves2dAxisAlignment() && | 159 overlay_damage_rect->Union(quad_rectangle); |
188 !display_rect_changed) { | |
189 gfx::Rect occluding_damage_rect = *damage_rect; | |
190 occluding_damage_rect.Intersect(quad_rectangle); | |
191 damage_rect->Subtract(quad_rectangle); | |
192 gfx::Rect new_occlusion_bounding_box = | |
193 gfx::ToEnclosingRect(occlusion_bounding_box); | |
194 new_occlusion_bounding_box.Union(previous_occlusion_bounding_box_); | |
195 occluding_damage_rect.Intersect(new_occlusion_bounding_box); | |
196 | 160 |
197 damage_rect->Union(occluding_damage_rect); | 161 RecordDCLayerResult(DC_LAYER_SUCCESS); |
198 } | 162 ca_layer_overlays->push_back(dc_layer); |
199 } else { | 163 // Only allow one overlay for now. |
200 // Entire replacement quad must be redrawn. | 164 break; |
201 damage_rect->Union(quad_rectangle); | |
202 } | |
203 previous_occlusion_bounding_box_ = | |
204 gfx::ToEnclosingRect(occlusion_bounding_box); | |
205 } | 165 } |
206 overlay_damage_rect->Union(quad_rectangle); | |
207 | |
208 RecordDCLayerResult(DC_LAYER_SUCCESS); | |
209 ca_layer_overlays->push_back(ca_layer); | |
210 // Only allow one overlay for now. | |
211 break; | |
212 } | 166 } |
213 damage_rect->Intersect(gfx::ToEnclosingRect(display_rect)); | 167 damage_rect->Intersect(gfx::ToEnclosingRect(display_rect)); |
214 previous_frame_underlay_rect_ = this_frame_underlay_rect; | 168 previous_frame_underlay_rect_ = this_frame_underlay_rect; |
215 previous_display_rect_ = display_rect; | 169 previous_display_rect_ = display_rect; |
216 } | 170 } |
217 | 171 |
| 172 bool DCLayerOverlayProcessor::ProcessForOverlay( |
| 173 const gfx::RectF& display_rect, |
| 174 QuadList* quad_list, |
| 175 const gfx::Rect& quad_rectangle, |
| 176 const gfx::RectF& occlusion_bounding_box, |
| 177 const QuadList::Iterator& it, |
| 178 gfx::Rect* damage_rect) { |
| 179 bool display_rect_changed = (display_rect != previous_display_rect_); |
| 180 if (!occlusion_bounding_box.IsEmpty()) |
| 181 return false; |
| 182 // The quad is on top, so promote it to an overlay and remove all damage |
| 183 // underneath it. |
| 184 if (it->shared_quad_state->quad_to_target_transform |
| 185 .Preserves2dAxisAlignment() && |
| 186 !display_rect_changed && !it->ShouldDrawWithBlending()) { |
| 187 damage_rect->Subtract(quad_rectangle); |
| 188 } |
| 189 quad_list->EraseAndInvalidateAllPointers(it); |
| 190 return true; |
| 191 } |
| 192 |
| 193 bool DCLayerOverlayProcessor::ProcessForUnderlay( |
| 194 const gfx::RectF& display_rect, |
| 195 QuadList* quad_list, |
| 196 const gfx::Rect& quad_rectangle, |
| 197 const gfx::RectF& occlusion_bounding_box, |
| 198 const QuadList::Iterator& it, |
| 199 gfx::Rect* damage_rect, |
| 200 gfx::Rect* this_frame_underlay_rect, |
| 201 DCLayerOverlay* dc_layer) { |
| 202 if (!base::FeatureList::IsEnabled(features::kDirectCompositionUnderlays)) { |
| 203 RecordDCLayerResult(DC_LAYER_FAILED_OCCLUDED); |
| 204 return false; |
| 205 } |
| 206 bool display_rect_changed = (display_rect != previous_display_rect_); |
| 207 // The quad is occluded, so replace it with a black solid color quad and |
| 208 // place the overlay itself under the quad. |
| 209 if (it->shared_quad_state->quad_to_target_transform |
| 210 .IsIdentityOrIntegerTranslation()) { |
| 211 *this_frame_underlay_rect = quad_rectangle; |
| 212 } |
| 213 dc_layer->shared_state->z_order = -1; |
| 214 const SharedQuadState* shared_quad_state = it->shared_quad_state; |
| 215 gfx::Rect rect = it->visible_rect; |
| 216 SolidColorDrawQuad* replacement = |
| 217 quad_list->ReplaceExistingElement<SolidColorDrawQuad>(it); |
| 218 replacement->SetAll(shared_quad_state, rect, rect, rect, false, |
| 219 SK_ColorTRANSPARENT, true); |
| 220 |
| 221 if (*this_frame_underlay_rect == previous_frame_underlay_rect_) { |
| 222 // If this underlay rect is the same as for last frame, subtract its |
| 223 // area from the damage of the main surface, as the cleared area was |
| 224 // already cleared last frame. Add back the damage from the occluded |
| 225 // area for this and last frame, as that may have changed. |
| 226 if (it->shared_quad_state->quad_to_target_transform |
| 227 .Preserves2dAxisAlignment() && |
| 228 !display_rect_changed) { |
| 229 gfx::Rect occluding_damage_rect = *damage_rect; |
| 230 occluding_damage_rect.Intersect(quad_rectangle); |
| 231 damage_rect->Subtract(quad_rectangle); |
| 232 gfx::Rect new_occlusion_bounding_box = |
| 233 gfx::ToEnclosingRect(occlusion_bounding_box); |
| 234 new_occlusion_bounding_box.Union(previous_occlusion_bounding_box_); |
| 235 occluding_damage_rect.Intersect(new_occlusion_bounding_box); |
| 236 |
| 237 damage_rect->Union(occluding_damage_rect); |
| 238 } |
| 239 } else { |
| 240 // Entire replacement quad must be redrawn. |
| 241 damage_rect->Union(quad_rectangle); |
| 242 } |
| 243 previous_occlusion_bounding_box_ = |
| 244 gfx::ToEnclosingRect(occlusion_bounding_box); |
| 245 return true; |
| 246 } |
| 247 |
218 } // namespace cc | 248 } // namespace cc |
OLD | NEW |