| Index: cc/trees/damage_tracker.cc
|
| diff --git a/cc/trees/damage_tracker.cc b/cc/trees/damage_tracker.cc
|
| index aa4a6236801612cd8b4effb572ed9eaa822a27b7..4ce0dca25b2dde880574a335c95cebd8ec376090 100644
|
| --- a/cc/trees/damage_tracker.cc
|
| +++ b/cc/trees/damage_tracker.cc
|
| @@ -14,6 +14,7 @@
|
| #include "cc/layers/heads_up_display_layer_impl.h"
|
| #include "cc/layers/layer_impl.h"
|
| #include "cc/layers/render_surface_impl.h"
|
| +#include "cc/trees/effect_node.h"
|
| #include "cc/trees/layer_tree_host_common.h"
|
| #include "cc/trees/layer_tree_impl.h"
|
| #include "ui/gfx/geometry/rect_conversions.h"
|
| @@ -29,18 +30,14 @@ DamageTracker::DamageTracker()
|
|
|
| DamageTracker::~DamageTracker() {}
|
|
|
| -void DamageTracker::UpdateDamageTrackingState(
|
| - const LayerImplList& layer_list,
|
| - const RenderSurfaceImpl* target_surface,
|
| - bool target_surface_property_changed_only_from_descendant,
|
| - const gfx::Rect& target_surface_content_rect,
|
| - LayerImpl* target_surface_mask_layer,
|
| - const FilterOperations& filters) {
|
| +void DamageTracker::UpdateDamageTracking(
|
| + LayerTreeImpl* layer_tree_impl,
|
| + const LayerImplList& render_surface_list) {
|
| //
|
| - // This function computes the "damage rect" of a target surface, and updates
|
| - // the state that is used to correctly track damage across frames. The damage
|
| - // rect is the region of the surface that may have changed and needs to be
|
| - // redrawn. This can be used to scissor what is actually drawn, to save GPU
|
| + // This function computes the "damage rect" of each target surface, and
|
| + // updates the state that is used to correctly track damage across frames. The
|
| + // damage rect is the region of the surface that may have changed and needs to
|
| + // be redrawn. This can be used to scissor what is actually drawn, to save GPU
|
| // computation and bandwidth.
|
| //
|
| // The surface's damage rect is computed as the union of all possible changes
|
| @@ -52,25 +49,30 @@ void DamageTracker::UpdateDamageTrackingState(
|
| //
|
| // The basic algorithm for computing the damage region is as follows:
|
| //
|
| - // 1. compute damage caused by changes in active/new layers
|
| - // for each layer in the layer_list:
|
| - // if the layer is actually a render_surface:
|
| - // add the surface's damage to our target surface.
|
| - // else
|
| - // add the layer's damage to the target surface.
|
| + // 1. compute damage caused by changes in contributing layers or surfaces
|
| + // for each contributing layer or render surface:
|
| + // add the layer's or surface's damage to the target surface.
|
| //
|
| // 2. compute damage caused by the target surface's mask, if it exists.
|
| //
|
| // 3. compute damage caused by old layers/surfaces that no longer exist
|
| - // for each leftover layer:
|
| + // for each leftover layer or render surface:
|
| // add the old layer/surface bounds to the target surface damage.
|
| //
|
| // 4. combine all partial damage rects to get the full damage rect.
|
| //
|
| // Additional important points:
|
| //
|
| - // - This algorithm is implicitly recursive; it assumes that descendant
|
| - // surfaces have already computed their damage.
|
| + // - This algorithm requires that descendant surfaces compute their damage
|
| + // before ancestor surfaces. Further, since contributing surfaces with
|
| + // background filters can expand the damage caused by contributors
|
| + // underneath them (that is, before them in draw order), the exact damage
|
| + // caused by these contributors must be computed before computing the damage
|
| + // caused by the contributing surface. This is implemented by visiting
|
| + // layers in draw order, computing the damage caused by each one to their
|
| + // target; during this walk, as soon as all of a surface's contributors have
|
| + // been visited, the surface's own damage is computed and then added to its
|
| + // target's accumulated damage.
|
| //
|
| // - Changes to layers/surfaces indicate "damage" to the target surface; If a
|
| // layer is not changed, it does NOT mean that the layer can skip drawing.
|
| @@ -104,40 +106,98 @@ void DamageTracker::UpdateDamageTrackingState(
|
| // erased from map.
|
| //
|
|
|
| - PrepareRectHistoryForUpdate();
|
| + for (LayerImpl* layer : render_surface_list) {
|
| + layer->GetRenderSurface()->damage_tracker()->PrepareForUpdate();
|
| + }
|
| +
|
| + EffectTree& effect_tree = layer_tree_impl->property_trees()->effect_tree;
|
| + int current_target_effect_id = EffectTree::kContentsRootNodeId;
|
| + DCHECK(effect_tree.GetRenderSurface(current_target_effect_id));
|
| + for (LayerImpl* layer : *layer_tree_impl) {
|
| + if (!layer->is_drawn_render_surface_layer_list_member())
|
| + continue;
|
| +
|
| + int next_target_effect_id = layer->render_target_effect_tree_index();
|
| + if (next_target_effect_id != current_target_effect_id) {
|
| + int lowest_common_ancestor_id =
|
| + effect_tree.LowestCommonAncestorWithRenderSurface(
|
| + current_target_effect_id, next_target_effect_id);
|
| + while (current_target_effect_id != lowest_common_ancestor_id) {
|
| + // Moving to a non-descendant target surface. This implies that the
|
| + // current target doesn't have any more contributors, since only
|
| + // descendants can contribute to a target, and the each's target's
|
| + // content (including content contributed by descendants) is contiguous
|
| + // in draw order.
|
| + RenderSurfaceImpl* current_target =
|
| + effect_tree.GetRenderSurface(current_target_effect_id);
|
| + current_target->damage_tracker()->ComputeSurfaceDamage(current_target);
|
| + RenderSurfaceImpl* parent_target = current_target->render_target();
|
| + parent_target->damage_tracker()->AccumulateDamageFromRenderSurface(
|
| + current_target);
|
| + current_target_effect_id =
|
| + effect_tree.Node(current_target_effect_id)->target_id;
|
| + }
|
| + current_target_effect_id = next_target_effect_id;
|
| + }
|
| +
|
| + RenderSurfaceImpl* target_surface = layer->render_target();
|
| +
|
| + // We skip damage from the HUD layer because (a) the HUD layer damages the
|
| + // whole frame and (b) we don't want HUD layer damage to be shown by the
|
| + // HUD damage rect visualization.
|
| + if (layer != layer_tree_impl->hud_layer()) {
|
| + target_surface->damage_tracker()->AccumulateDamageFromLayer(layer);
|
| + }
|
| + }
|
| +
|
| + DCHECK_GE(current_target_effect_id, EffectTree::kContentsRootNodeId);
|
| + RenderSurfaceImpl* current_target =
|
| + effect_tree.GetRenderSurface(current_target_effect_id);
|
| + while (true) {
|
| + current_target->damage_tracker()->ComputeSurfaceDamage(current_target);
|
| + if (current_target->EffectTreeIndex() == EffectTree::kContentsRootNodeId)
|
| + break;
|
| + RenderSurfaceImpl* next_target = current_target->render_target();
|
| + next_target->damage_tracker()->AccumulateDamageFromRenderSurface(
|
| + current_target);
|
| + current_target = next_target;
|
| + }
|
| +}
|
| +
|
| +void DamageTracker::ComputeSurfaceDamage(RenderSurfaceImpl* render_surface) {
|
| + // All damage from contributing layers and surfaces must already have been
|
| + // added to damage_for_this_update_ through calls to AccumulateDamageFromLayer
|
| + // and AccumulateDamageFromRenderSurface.
|
| +
|
| // These functions cannot be bypassed with early-exits, even if we know what
|
| // the damage will be for this frame, because we need to update the damage
|
| // tracker state to correctly track the next frame.
|
| - DamageAccumulator damage_from_active_layers =
|
| - TrackDamageFromActiveLayers(layer_list, target_surface);
|
| DamageAccumulator damage_from_surface_mask =
|
| - TrackDamageFromSurfaceMask(target_surface_mask_layer);
|
| + TrackDamageFromSurfaceMask(render_surface->MaskLayer());
|
| DamageAccumulator damage_from_leftover_rects = TrackDamageFromLeftoverRects();
|
|
|
| - DamageAccumulator damage_for_this_update;
|
| -
|
| - if (target_surface_property_changed_only_from_descendant) {
|
| - damage_for_this_update.Union(target_surface_content_rect);
|
| + if (render_surface->SurfacePropertyChangedOnlyFromDescendant()) {
|
| + damage_for_this_update_ = DamageAccumulator();
|
| + damage_for_this_update_.Union(render_surface->content_rect());
|
| } else {
|
| // TODO(shawnsingh): can we clamp this damage to the surface's content rect?
|
| // (affects performance, but not correctness)
|
| - damage_for_this_update.Union(damage_from_active_layers);
|
| - damage_for_this_update.Union(damage_from_surface_mask);
|
| - damage_for_this_update.Union(damage_from_leftover_rects);
|
| + damage_for_this_update_.Union(damage_from_surface_mask);
|
| + damage_for_this_update_.Union(damage_from_leftover_rects);
|
|
|
| gfx::Rect damage_rect;
|
| - bool is_rect_valid = damage_for_this_update.GetAsRect(&damage_rect);
|
| + bool is_rect_valid = damage_for_this_update_.GetAsRect(&damage_rect);
|
| if (is_rect_valid) {
|
| - damage_rect =
|
| - filters.MapRect(damage_rect, target_surface->SurfaceScale().matrix());
|
| - damage_for_this_update = DamageAccumulator();
|
| - damage_for_this_update.Union(damage_rect);
|
| + damage_rect = render_surface->Filters().MapRect(
|
| + damage_rect, render_surface->SurfaceScale().matrix());
|
| + damage_for_this_update_ = DamageAccumulator();
|
| + damage_for_this_update_.Union(damage_rect);
|
| }
|
| }
|
|
|
| // Damage accumulates until we are notified that we actually did draw on that
|
| // frame.
|
| - current_damage_.Union(damage_for_this_update);
|
| + current_damage_.Union(damage_for_this_update_);
|
| }
|
|
|
| bool DamageTracker::GetDamageRectIfValid(gfx::Rect* rect) {
|
| @@ -177,31 +237,6 @@ DamageTracker::SurfaceRectMapData& DamageTracker::RectDataForSurface(
|
| return *it;
|
| }
|
|
|
| -DamageTracker::DamageAccumulator DamageTracker::TrackDamageFromActiveLayers(
|
| - const LayerImplList& layer_list,
|
| - const RenderSurfaceImpl* target_surface) {
|
| - DamageAccumulator damage;
|
| -
|
| - for (size_t layer_index = 0; layer_index < layer_list.size(); ++layer_index) {
|
| - // Visit layers in back-to-front order.
|
| - LayerImpl* layer = layer_list[layer_index];
|
| -
|
| - // We skip damage from the HUD layer because (a) the HUD layer damages the
|
| - // whole frame and (b) we don't want HUD layer damage to be shown by the
|
| - // HUD damage rect visualization.
|
| - if (layer == layer->layer_tree_impl()->hud_layer())
|
| - continue;
|
| -
|
| - RenderSurfaceImpl* render_surface = layer->GetRenderSurface();
|
| - if (render_surface && render_surface != target_surface)
|
| - ExtendDamageForRenderSurface(render_surface, &damage);
|
| - else
|
| - ExtendDamageForLayer(layer, &damage);
|
| - }
|
| -
|
| - return damage;
|
| -}
|
| -
|
| DamageTracker::DamageAccumulator DamageTracker::TrackDamageFromSurfaceMask(
|
| LayerImpl* target_surface_mask_layer) {
|
| DamageAccumulator damage;
|
| @@ -220,8 +255,9 @@ DamageTracker::DamageAccumulator DamageTracker::TrackDamageFromSurfaceMask(
|
| return damage;
|
| }
|
|
|
| -void DamageTracker::PrepareRectHistoryForUpdate() {
|
| +void DamageTracker::PrepareForUpdate() {
|
| mailboxId_++;
|
| + damage_for_this_update_ = DamageAccumulator();
|
| }
|
|
|
| DamageTracker::DamageAccumulator DamageTracker::TrackDamageFromLeftoverRects() {
|
| @@ -292,12 +328,11 @@ DamageTracker::DamageAccumulator DamageTracker::TrackDamageFromLeftoverRects() {
|
|
|
| void DamageTracker::ExpandDamageInsideRectWithFilters(
|
| const gfx::Rect& pre_filter_rect,
|
| - const FilterOperations& filters,
|
| - DamageAccumulator* damage) {
|
| + const FilterOperations& filters) {
|
| gfx::Rect damage_rect;
|
| - bool is_valid_rect = damage->GetAsRect(&damage_rect);
|
| - // If the input isn't a valid rect, then there is no point in trying to make
|
| - // it bigger.
|
| + bool is_valid_rect = damage_for_this_update_.GetAsRect(&damage_rect);
|
| + // If the damage accumulated so far isn't a valid rect, then there is no point
|
| + // in trying to make it bigger.
|
| if (!is_valid_rect)
|
| return;
|
|
|
| @@ -308,11 +343,10 @@ void DamageTracker::ExpandDamageInsideRectWithFilters(
|
| // Restrict it to the rectangle in which the background filter is shown.
|
| expanded_damage_rect.Intersect(pre_filter_rect);
|
|
|
| - damage->Union(expanded_damage_rect);
|
| + damage_for_this_update_.Union(expanded_damage_rect);
|
| }
|
|
|
| -void DamageTracker::ExtendDamageForLayer(LayerImpl* layer,
|
| - DamageAccumulator* target_damage) {
|
| +void DamageTracker::AccumulateDamageFromLayer(LayerImpl* layer) {
|
| // There are two ways that a layer can damage a region of the target surface:
|
| // 1. Property change (e.g. opacity, position, transforms):
|
| // - the entire region of the layer itself damages the surface.
|
| @@ -341,11 +375,11 @@ void DamageTracker::ExtendDamageForLayer(LayerImpl* layer,
|
| if (layer_is_new || layer->LayerPropertyChanged()) {
|
| // If a layer is new or has changed, then its entire layer rect affects the
|
| // target surface.
|
| - target_damage->Union(rect_in_target_space);
|
| + damage_for_this_update_.Union(rect_in_target_space);
|
|
|
| // The layer's old region is now exposed on the target surface, too.
|
| // Note old_rect_in_target_space is already in target space.
|
| - target_damage->Union(old_rect_in_target_space);
|
| + damage_for_this_update_.Union(old_rect_in_target_space);
|
| return;
|
| }
|
|
|
| @@ -357,13 +391,12 @@ void DamageTracker::ExtendDamageForLayer(LayerImpl* layer,
|
| if (!damage_rect.IsEmpty()) {
|
| gfx::Rect damage_rect_in_target_space =
|
| MathUtil::MapEnclosingClippedRect(layer->DrawTransform(), damage_rect);
|
| - target_damage->Union(damage_rect_in_target_space);
|
| + damage_for_this_update_.Union(damage_rect_in_target_space);
|
| }
|
| }
|
|
|
| -void DamageTracker::ExtendDamageForRenderSurface(
|
| - RenderSurfaceImpl* render_surface,
|
| - DamageAccumulator* target_damage) {
|
| +void DamageTracker::AccumulateDamageFromRenderSurface(
|
| + RenderSurfaceImpl* render_surface) {
|
| // There are two ways a "descendant surface" can damage regions of the "target
|
| // surface":
|
| // 1. Property change:
|
| @@ -390,10 +423,10 @@ void DamageTracker::ExtendDamageForRenderSurface(
|
|
|
| if (surface_is_new || render_surface->SurfacePropertyChanged()) {
|
| // The entire surface contributes damage.
|
| - target_damage->Union(surface_rect_in_target_space);
|
| + damage_for_this_update_.Union(surface_rect_in_target_space);
|
|
|
| // The surface's old region is now exposed on the target surface, too.
|
| - target_damage->Union(old_surface_rect);
|
| + damage_for_this_update_.Union(old_surface_rect);
|
| } else {
|
| // Only the surface's damage_rect will damage the target surface.
|
| gfx::Rect damage_rect_in_local_space;
|
| @@ -405,9 +438,9 @@ void DamageTracker::ExtendDamageForRenderSurface(
|
| const gfx::Transform& draw_transform = render_surface->draw_transform();
|
| gfx::Rect damage_rect_in_target_space = MathUtil::MapEnclosingClippedRect(
|
| draw_transform, damage_rect_in_local_space);
|
| - target_damage->Union(damage_rect_in_target_space);
|
| + damage_for_this_update_.Union(damage_rect_in_target_space);
|
| } else if (!is_valid_rect) {
|
| - target_damage->Union(surface_rect_in_target_space);
|
| + damage_for_this_update_.Union(surface_rect_in_target_space);
|
| }
|
| }
|
|
|
| @@ -421,7 +454,7 @@ void DamageTracker::ExtendDamageForRenderSurface(
|
| render_surface->BackgroundFilters();
|
| if (background_filters.HasFilterThatMovesPixels()) {
|
| ExpandDamageInsideRectWithFilters(surface_rect_in_target_space,
|
| - background_filters, target_damage);
|
| + background_filters);
|
| }
|
| }
|
|
|
|
|