| 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
|
|
|