Index: cc/output/dc_layer_overlay.cc |
diff --git a/cc/output/dc_layer_overlay.cc b/cc/output/dc_layer_overlay.cc |
index e5a043dd218b7d2281386ca54adf6e8a6b54ecc8..28b68a39f0a3cf8184c35c0337ec38d1c4b95991 100644 |
--- a/cc/output/dc_layer_overlay.cc |
+++ b/cc/output/dc_layer_overlay.cc |
@@ -129,11 +129,10 @@ void DCLayerOverlayProcessor::Process(ResourceProvider* resource_provider, |
gfx::Rect* damage_rect, |
DCLayerOverlayList* ca_layer_overlays) { |
gfx::Rect this_frame_underlay_rect; |
- bool display_rect_changed = (display_rect != previous_display_rect_); |
for (auto it = quad_list->begin(); it != quad_list->end(); ++it) { |
- DCLayerOverlay ca_layer; |
+ DCLayerOverlay dc_layer; |
DCLayerResult result = FromDrawQuad(resource_provider, display_rect, |
- quad_list->begin(), it, &ca_layer); |
+ quad_list->begin(), it, &dc_layer); |
if (result != DC_LAYER_SUCCESS) { |
RecordDCLayerResult(result); |
continue; |
@@ -150,69 +149,100 @@ void DCLayerOverlayProcessor::Process(ResourceProvider* resource_provider, |
gfx::Rect quad_rectangle = gfx::ToEnclosingRect(ClippedQuadRectangle(*it)); |
gfx::RectF occlusion_bounding_box = |
GetOcclusionBounds(gfx::RectF(quad_rectangle), quad_list->begin(), it); |
- if (occlusion_bounding_box.IsEmpty()) { |
- // The quad is on top, so promote it to an overlay and remove all damage |
- // underneath it. |
- if (it->shared_quad_state->quad_to_target_transform |
- .Preserves2dAxisAlignment() && |
- !display_rect_changed && !it->ShouldDrawWithBlending()) { |
- damage_rect->Subtract(quad_rectangle); |
- } |
- quad_list->EraseAndInvalidateAllPointers(it); |
- } else if (!base::FeatureList::IsEnabled( |
- features::kDirectCompositionUnderlays)) { |
- RecordDCLayerResult(DC_LAYER_FAILED_OCCLUDED); |
- continue; |
- } else { |
- // The quad is occluded, so replace it with a black solid color quad and |
- // place the overlay itself under the quad. |
- if (it->shared_quad_state->quad_to_target_transform |
- .IsIdentityOrIntegerTranslation()) { |
- this_frame_underlay_rect = quad_rectangle; |
- } |
- ca_layer.shared_state->z_order = -1; |
- const SharedQuadState* shared_quad_state = it->shared_quad_state; |
- gfx::Rect rect = it->visible_rect; |
- SolidColorDrawQuad* replacement = |
- quad_list->ReplaceExistingElement<SolidColorDrawQuad>(it); |
- replacement->SetAll(shared_quad_state, rect, rect, rect, false, |
- SK_ColorTRANSPARENT, true); |
- |
- if (this_frame_underlay_rect == previous_frame_underlay_rect_) { |
- // If this underlay rect is the same as for last frame, subtract its |
- // area from the damage of the main surface, as the cleared area was |
- // already cleared last frame. Add back the damage from the occluded |
- // area for this and last frame, as that may have changed. |
- if (it->shared_quad_state->quad_to_target_transform |
- .Preserves2dAxisAlignment() && |
- !display_rect_changed) { |
- gfx::Rect occluding_damage_rect = *damage_rect; |
- occluding_damage_rect.Intersect(quad_rectangle); |
- damage_rect->Subtract(quad_rectangle); |
- gfx::Rect new_occlusion_bounding_box = |
- gfx::ToEnclosingRect(occlusion_bounding_box); |
- new_occlusion_bounding_box.Union(previous_occlusion_bounding_box_); |
- occluding_damage_rect.Intersect(new_occlusion_bounding_box); |
- |
- damage_rect->Union(occluding_damage_rect); |
- } |
- } else { |
- // Entire replacement quad must be redrawn. |
- damage_rect->Union(quad_rectangle); |
- } |
- previous_occlusion_bounding_box_ = |
- gfx::ToEnclosingRect(occlusion_bounding_box); |
- } |
- overlay_damage_rect->Union(quad_rectangle); |
- RecordDCLayerResult(DC_LAYER_SUCCESS); |
- ca_layer_overlays->push_back(ca_layer); |
- // Only allow one overlay for now. |
- break; |
+ // Underlays are less efficient, so attempt regular overlays first. |
+ if (ProcessForOverlay(display_rect, quad_list, quad_rectangle, |
+ occlusion_bounding_box, it, damage_rect) || |
+ ProcessForUnderlay(display_rect, quad_list, quad_rectangle, |
+ occlusion_bounding_box, it, damage_rect, |
+ &this_frame_underlay_rect, &dc_layer)) { |
+ overlay_damage_rect->Union(quad_rectangle); |
+ |
+ RecordDCLayerResult(DC_LAYER_SUCCESS); |
+ ca_layer_overlays->push_back(dc_layer); |
+ // Only allow one overlay for now. |
+ break; |
+ } |
} |
damage_rect->Intersect(gfx::ToEnclosingRect(display_rect)); |
previous_frame_underlay_rect_ = this_frame_underlay_rect; |
previous_display_rect_ = display_rect; |
} |
+bool DCLayerOverlayProcessor::ProcessForOverlay( |
+ const gfx::RectF& display_rect, |
+ QuadList* quad_list, |
+ const gfx::Rect& quad_rectangle, |
+ const gfx::RectF& occlusion_bounding_box, |
+ const QuadList::Iterator& it, |
+ gfx::Rect* damage_rect) { |
+ bool display_rect_changed = (display_rect != previous_display_rect_); |
+ if (!occlusion_bounding_box.IsEmpty()) |
+ return false; |
+ // The quad is on top, so promote it to an overlay and remove all damage |
+ // underneath it. |
+ if (it->shared_quad_state->quad_to_target_transform |
+ .Preserves2dAxisAlignment() && |
+ !display_rect_changed && !it->ShouldDrawWithBlending()) { |
+ damage_rect->Subtract(quad_rectangle); |
+ } |
+ quad_list->EraseAndInvalidateAllPointers(it); |
+ return true; |
+} |
+ |
+bool DCLayerOverlayProcessor::ProcessForUnderlay( |
+ const gfx::RectF& display_rect, |
+ QuadList* quad_list, |
+ const gfx::Rect& quad_rectangle, |
+ const gfx::RectF& occlusion_bounding_box, |
+ const QuadList::Iterator& it, |
+ gfx::Rect* damage_rect, |
+ gfx::Rect* this_frame_underlay_rect, |
+ DCLayerOverlay* dc_layer) { |
+ if (!base::FeatureList::IsEnabled(features::kDirectCompositionUnderlays)) { |
+ RecordDCLayerResult(DC_LAYER_FAILED_OCCLUDED); |
+ return false; |
+ } |
+ bool display_rect_changed = (display_rect != previous_display_rect_); |
+ // The quad is occluded, so replace it with a black solid color quad and |
+ // place the overlay itself under the quad. |
+ if (it->shared_quad_state->quad_to_target_transform |
+ .IsIdentityOrIntegerTranslation()) { |
+ *this_frame_underlay_rect = quad_rectangle; |
+ } |
+ dc_layer->shared_state->z_order = -1; |
+ const SharedQuadState* shared_quad_state = it->shared_quad_state; |
+ gfx::Rect rect = it->visible_rect; |
+ SolidColorDrawQuad* replacement = |
+ quad_list->ReplaceExistingElement<SolidColorDrawQuad>(it); |
+ replacement->SetAll(shared_quad_state, rect, rect, rect, false, |
+ SK_ColorTRANSPARENT, true); |
+ |
+ if (*this_frame_underlay_rect == previous_frame_underlay_rect_) { |
+ // If this underlay rect is the same as for last frame, subtract its |
+ // area from the damage of the main surface, as the cleared area was |
+ // already cleared last frame. Add back the damage from the occluded |
+ // area for this and last frame, as that may have changed. |
+ if (it->shared_quad_state->quad_to_target_transform |
+ .Preserves2dAxisAlignment() && |
+ !display_rect_changed) { |
+ gfx::Rect occluding_damage_rect = *damage_rect; |
+ occluding_damage_rect.Intersect(quad_rectangle); |
+ damage_rect->Subtract(quad_rectangle); |
+ gfx::Rect new_occlusion_bounding_box = |
+ gfx::ToEnclosingRect(occlusion_bounding_box); |
+ new_occlusion_bounding_box.Union(previous_occlusion_bounding_box_); |
+ occluding_damage_rect.Intersect(new_occlusion_bounding_box); |
+ |
+ damage_rect->Union(occluding_damage_rect); |
+ } |
+ } else { |
+ // Entire replacement quad must be redrawn. |
+ damage_rect->Union(quad_rectangle); |
+ } |
+ previous_occlusion_bounding_box_ = |
+ gfx::ToEnclosingRect(occlusion_bounding_box); |
+ return true; |
+} |
+ |
} // namespace cc |