Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Unified Diff: cc/trees/damage_tracker.cc

Issue 2814273003: cc: Make DamageTracker use the effect tree and layer list (Closed)
Patch Set: Rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/trees/damage_tracker.h ('k') | cc/trees/damage_tracker_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
}
« no previous file with comments | « cc/trees/damage_tracker.h ('k') | cc/trees/damage_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698