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

Unified Diff: cc/surfaces/surface_aggregator.cc

Issue 1966073002: Reland: Correctly handle damage involving filters in SurfaceAggregator (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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/surfaces/surface_aggregator.h ('k') | cc/surfaces/surface_aggregator_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/surfaces/surface_aggregator.cc
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc
index fe2e7552b14ac825b9039a070d35a549a6fcbf8e..2beb8043e2b970c1eeb812622415e948c0732a97 100644
--- a/cc/surfaces/surface_aggregator.cc
+++ b/cc/surfaces/surface_aggregator.cc
@@ -9,6 +9,7 @@
#include <map>
#include "base/bind.h"
+#include "base/containers/adapters.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
@@ -224,7 +225,7 @@ void SurfaceAggregator::HandleSurfaceQuad(
RenderPassId remapped_pass_id = RemapPassId(source.id, surface_id);
- copy_pass->SetAll(remapped_pass_id, source.output_rect, gfx::Rect(),
+ copy_pass->SetAll(remapped_pass_id, source.output_rect, source.output_rect,
source.transform_to_root_target,
source.has_transparent_background);
@@ -243,6 +244,17 @@ void SurfaceAggregator::HandleSurfaceQuad(
child_to_parent_map, gfx::Transform(), ClipData(),
copy_pass.get(), surface_id);
+ if (!copy_request_passes_.count(remapped_pass_id) &&
+ !moved_pixel_passes_.count(remapped_pass_id)) {
+ gfx::Transform inverse_transform(gfx::Transform::kSkipInitialization);
+ if (copy_pass->transform_to_root_target.GetInverse(&inverse_transform)) {
+ gfx::Rect damage_rect_in_render_pass_space =
+ MathUtil::ProjectEnclosingClippedRect(inverse_transform,
+ root_damage_rect_);
+ copy_pass->damage_rect.Intersect(damage_rect_in_render_pass_space);
+ }
+ }
+
dest_pass_list_->push_back(std::move(copy_pass));
}
@@ -351,7 +363,9 @@ void SurfaceAggregator::CopyQuadsToPass(
const SharedQuadState* dest_shared_quad_state = nullptr;
// If the current frame has copy requests then aggregate the entire
// thing, as otherwise parts of the copy requests may be ignored.
- const bool ignore_undamaged = aggregate_only_damaged_ && !has_copy_requests_;
+ const bool ignore_undamaged = aggregate_only_damaged_ &&
+ !has_copy_requests_ &&
+ !moved_pixel_passes_.count(dest_pass->id);
// Damage rect in the quad space of the current shared quad state.
// TODO(jbauman): This rect may contain unnecessary area if
// transform isn't axis-aligned.
@@ -470,13 +484,23 @@ void SurfaceAggregator::CopyPasses(const DelegatedFrameData* frame_data,
RenderPassId remapped_pass_id =
RemapPassId(source.id, surface->surface_id());
- copy_pass->SetAll(remapped_pass_id, source.output_rect, gfx::Rect(),
+ copy_pass->SetAll(remapped_pass_id, source.output_rect, source.output_rect,
source.transform_to_root_target,
source.has_transparent_background);
CopyQuadsToPass(source.quad_list, source.shared_quad_state_list,
child_to_parent_map, gfx::Transform(), ClipData(),
copy_pass.get(), surface->surface_id());
+ if (!copy_request_passes_.count(remapped_pass_id) &&
+ !moved_pixel_passes_.count(remapped_pass_id)) {
+ gfx::Transform inverse_transform(gfx::Transform::kSkipInitialization);
+ if (copy_pass->transform_to_root_target.GetInverse(&inverse_transform)) {
+ gfx::Rect damage_rect_in_render_pass_space =
+ MathUtil::ProjectEnclosingClippedRect(inverse_transform,
+ root_damage_rect_);
+ copy_pass->damage_rect.Intersect(damage_rect_in_render_pass_space);
+ }
+ }
dest_pass_list_->push_back(std::move(copy_pass));
}
@@ -506,6 +530,8 @@ void SurfaceAggregator::ProcessAddedAndRemovedSurfaces() {
// surface and its descendants, check if there are any copy requests, and
// return the combined damage rect.
gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id,
+ bool in_moved_pixel_pass,
+ RenderPassId parent_pass,
PrewalkResult* result) {
// This is for debugging a possible use after free.
// TODO(jbauman): Remove this once we have enough information.
@@ -547,10 +573,26 @@ gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id,
provider_ ? provider_->GetChildToParentMap(child_id) : empty_map;
CHECK(debug_weak_this.get());
- // Each pair in the vector is a child surface and the transform from its
- // target to the root target of this surface.
- std::vector<std::pair<SurfaceId, gfx::Transform>> child_surfaces;
- for (const auto& render_pass : frame_data->render_pass_list) {
+ if (!frame_data->render_pass_list.empty()) {
+ RenderPassId remapped_pass_id =
+ RemapPassId(frame_data->render_pass_list.back()->id, surface_id);
+ if (in_moved_pixel_pass)
+ moved_pixel_passes_.insert(remapped_pass_id);
+ if (parent_pass.IsValid())
+ render_pass_dependencies_[parent_pass].insert(remapped_pass_id);
+ }
+
+ struct SurfaceInfo {
+ SurfaceId id;
+ bool has_moved_pixels;
+ RenderPassId parent_pass;
+ gfx::Transform target_to_surface_transform;
+ };
+ std::vector<SurfaceInfo> child_surfaces;
+
+ for (const auto& render_pass : base::Reversed(frame_data->render_pass_list)) {
+ RenderPassId remapped_pass_id = RemapPassId(render_pass->id, surface_id);
+ bool in_moved_pixel_pass = !!moved_pixel_passes_.count(remapped_pass_id);
for (const auto& quad : render_pass->quad_list) {
if (quad->material == DrawQuad::SURFACE_CONTENT) {
const SurfaceDrawQuad* surface_quad =
@@ -558,8 +600,22 @@ gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id,
gfx::Transform target_to_surface_transform(
render_pass->transform_to_root_target,
surface_quad->shared_quad_state->quad_to_target_transform);
- child_surfaces.push_back(std::make_pair(surface_quad->surface_id,
- target_to_surface_transform));
+ child_surfaces.push_back(
+ SurfaceInfo{surface_quad->surface_id, in_moved_pixel_pass,
+ remapped_pass_id, target_to_surface_transform});
+ } else if (quad->material == DrawQuad::RENDER_PASS) {
+ const RenderPassDrawQuad* render_pass_quad =
+ RenderPassDrawQuad::MaterialCast(quad);
+ if (in_moved_pixel_pass ||
+ render_pass_quad->filters.HasFilterThatMovesPixels()) {
+ moved_pixel_passes_.insert(
+ RemapPassId(render_pass_quad->render_pass_id, surface_id));
+ }
+ if (render_pass_quad->background_filters.HasFilterThatMovesPixels()) {
+ in_moved_pixel_pass = true;
+ }
+ render_pass_dependencies_[remapped_pass_id].insert(
+ RemapPassId(render_pass_quad->render_pass_id, surface_id));
}
if (!provider_)
@@ -584,8 +640,10 @@ gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id,
CHECK(debug_weak_this.get());
gfx::Rect damage_rect;
+ gfx::Rect full_damage;
if (!frame_data->render_pass_list.empty()) {
RenderPass* last_pass = frame_data->render_pass_list.back().get();
+ full_damage = last_pass->output_rect;
damage_rect =
DamageRectForSurface(surface, *last_pass, last_pass->output_rect);
}
@@ -595,16 +653,27 @@ gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id,
SurfaceSet::iterator it =
referenced_surfaces_.insert(surface->surface_id()).first;
for (const auto& surface_info : child_surfaces) {
- gfx::Rect surface_damage = PrewalkTree(surface_info.first, result);
- damage_rect.Union(
- MathUtil::MapEnclosingClippedRect(surface_info.second, surface_damage));
+ gfx::Rect surface_damage =
+ PrewalkTree(surface_info.id, surface_info.has_moved_pixels,
+ surface_info.parent_pass, result);
+ if (surface_damage.IsEmpty())
+ continue;
+ if (surface_info.has_moved_pixels) {
+ // Areas outside the rect hit by target_to_surface_transform may be
+ // modified if there is a filter that moves pixels.
+ damage_rect = full_damage;
Stephen White 2016/05/12 15:32:10 FYI, we could use FilterOperation::MapRect() here
+ continue;
+ }
+
+ damage_rect.Union(MathUtil::MapEnclosingClippedRect(
+ surface_info.target_to_surface_transform, surface_damage));
}
CHECK(debug_weak_this.get());
for (const auto& surface_id : surface_frame->metadata.referenced_surfaces) {
if (!contained_surfaces_.count(surface_id)) {
result->undrawn_surfaces.insert(surface_id);
- PrewalkTree(surface_id, result);
+ PrewalkTree(surface_id, false, RenderPassId(), result);
}
}
@@ -613,8 +682,12 @@ gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id,
surface->factory()->WillDrawSurface(surface->surface_id(), damage_rect);
CHECK(debug_weak_this.get());
- for (const auto& render_pass : frame_data->render_pass_list)
- result->has_copy_requests |= !render_pass->copy_requests.empty();
+ for (const auto& render_pass : frame_data->render_pass_list) {
+ if (!render_pass->copy_requests.empty()) {
+ RenderPassId remapped_pass_id = RemapPassId(render_pass->id, surface_id);
+ copy_request_passes_.insert(remapped_pass_id);
+ }
+ }
referenced_surfaces_.erase(it);
return damage_rect;
@@ -663,6 +736,23 @@ void SurfaceAggregator::CopyUndrawnSurfaces(PrewalkResult* prewalk_result) {
}
}
+void SurfaceAggregator::PropagateCopyRequestPasses() {
+ std::vector<RenderPassId> copy_requests_to_iterate(
+ copy_request_passes_.begin(), copy_request_passes_.end());
+ while (!copy_requests_to_iterate.empty()) {
+ RenderPassId first = copy_requests_to_iterate.back();
+ copy_requests_to_iterate.pop_back();
+ auto it = render_pass_dependencies_.find(first);
+ if (it == render_pass_dependencies_.end())
+ continue;
+ for (auto pass : it->second) {
+ if (copy_request_passes_.insert(pass).second) {
+ copy_requests_to_iterate.push_back(pass);
+ }
+ }
+ }
+}
+
std::unique_ptr<CompositorFrame> SurfaceAggregator::Aggregate(
SurfaceId surface_id) {
Surface* surface = manager_->GetSurfaceForId(surface_id);
@@ -683,19 +773,24 @@ std::unique_ptr<CompositorFrame> SurfaceAggregator::Aggregate(
valid_surfaces_.clear();
PrewalkResult prewalk_result;
- root_damage_rect_ = PrewalkTree(surface_id, &prewalk_result);
- has_copy_requests_ = prewalk_result.has_copy_requests;
+ root_damage_rect_ =
+ PrewalkTree(surface_id, false, RenderPassId(), &prewalk_result);
+ PropagateCopyRequestPasses();
+ has_copy_requests_ = !copy_request_passes_.empty();
CopyUndrawnSurfaces(&prewalk_result);
SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first;
CopyPasses(root_surface_frame->delegated_frame_data.get(), surface);
referenced_surfaces_.erase(it);
+ moved_pixel_passes_.clear();
+ copy_request_passes_.clear();
+ render_pass_dependencies_.clear();
+
DCHECK(referenced_surfaces_.empty());
if (dest_pass_list_->empty())
return nullptr;
- dest_pass_list_->back()->damage_rect = root_damage_rect_;
dest_pass_list_ = NULL;
ProcessAddedAndRemovedSurfaces();
« no previous file with comments | « cc/surfaces/surface_aggregator.h ('k') | cc/surfaces/surface_aggregator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698