Linux: Depend on liberation-fonts package for RPMs.
[chromium-blink-merge.git] / cc / surfaces / surface_aggregator.cc
blob69618ba8b4ca4507f77705db7fa2834e2a07e452
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/surfaces/surface_aggregator.h"
7 #include <map>
9 #include "base/bind.h"
10 #include "base/containers/hash_tables.h"
11 #include "base/logging.h"
12 #include "base/trace_event/trace_event.h"
13 #include "cc/base/math_util.h"
14 #include "cc/output/compositor_frame.h"
15 #include "cc/output/delegated_frame_data.h"
16 #include "cc/quads/draw_quad.h"
17 #include "cc/quads/render_pass_draw_quad.h"
18 #include "cc/quads/shared_quad_state.h"
19 #include "cc/quads/surface_draw_quad.h"
20 #include "cc/surfaces/surface.h"
21 #include "cc/surfaces/surface_factory.h"
22 #include "cc/surfaces/surface_manager.h"
23 #include "cc/trees/blocking_task_runner.h"
25 namespace cc {
26 namespace {
28 void MoveMatchingRequests(
29 RenderPassId id,
30 std::multimap<RenderPassId, CopyOutputRequest*>* copy_requests,
31 ScopedPtrVector<CopyOutputRequest>* output_requests) {
32 auto request_range = copy_requests->equal_range(id);
33 for (auto it = request_range.first; it != request_range.second; ++it) {
34 DCHECK(it->second);
35 output_requests->push_back(scoped_ptr<CopyOutputRequest>(it->second));
36 it->second = nullptr;
38 copy_requests->erase(request_range.first, request_range.second);
41 } // namespace
43 SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager,
44 ResourceProvider* provider,
45 bool aggregate_only_damaged)
46 : manager_(manager),
47 provider_(provider),
48 next_render_pass_id_(1),
49 aggregate_only_damaged_(aggregate_only_damaged) {
50 DCHECK(manager_);
53 SurfaceAggregator::~SurfaceAggregator() {}
55 // Create a clip rect for an aggregated quad from the original clip rect and
56 // the clip rect from the surface it's on.
57 SurfaceAggregator::ClipData SurfaceAggregator::CalculateClipRect(
58 const ClipData& surface_clip,
59 const ClipData& quad_clip,
60 const gfx::Transform& target_transform) {
61 ClipData out_clip;
62 if (surface_clip.is_clipped)
63 out_clip = surface_clip;
65 if (quad_clip.is_clipped) {
66 // TODO(jamesr): This only works if target_transform maps integer
67 // rects to integer rects.
68 gfx::Rect final_clip =
69 MathUtil::MapEnclosingClippedRect(target_transform, quad_clip.rect);
70 if (out_clip.is_clipped)
71 out_clip.rect.Intersect(final_clip);
72 else
73 out_clip.rect = final_clip;
74 out_clip.is_clipped = true;
77 return out_clip;
80 class SurfaceAggregator::RenderPassIdAllocator {
81 public:
82 explicit RenderPassIdAllocator(int* next_index) : next_index_(next_index) {}
83 ~RenderPassIdAllocator() {}
85 void AddKnownPass(RenderPassId id) {
86 if (id_to_index_map_.find(id) != id_to_index_map_.end())
87 return;
88 id_to_index_map_[id] = (*next_index_)++;
91 RenderPassId Remap(RenderPassId id) {
92 DCHECK(id_to_index_map_.find(id) != id_to_index_map_.end());
93 return RenderPassId(1, id_to_index_map_[id]);
96 private:
97 base::hash_map<RenderPassId, int> id_to_index_map_;
98 int* next_index_;
100 DISALLOW_COPY_AND_ASSIGN(RenderPassIdAllocator);
103 static void UnrefHelper(base::WeakPtr<SurfaceFactory> surface_factory,
104 const ReturnedResourceArray& resources,
105 BlockingTaskRunner* main_thread_task_runner) {
106 if (surface_factory)
107 surface_factory->UnrefResources(resources);
110 RenderPassId SurfaceAggregator::RemapPassId(RenderPassId surface_local_pass_id,
111 SurfaceId surface_id) {
112 RenderPassIdAllocator* allocator = render_pass_allocator_map_.get(surface_id);
113 if (!allocator) {
114 allocator = new RenderPassIdAllocator(&next_render_pass_id_);
115 render_pass_allocator_map_.set(surface_id, make_scoped_ptr(allocator));
117 allocator->AddKnownPass(surface_local_pass_id);
118 return allocator->Remap(surface_local_pass_id);
121 int SurfaceAggregator::ChildIdForSurface(Surface* surface) {
122 SurfaceToResourceChildIdMap::iterator it =
123 surface_id_to_resource_child_id_.find(surface->surface_id());
124 if (it == surface_id_to_resource_child_id_.end()) {
125 int child_id =
126 provider_->CreateChild(base::Bind(&UnrefHelper, surface->factory()));
127 if (surface->factory()) {
128 provider_->SetChildNeedsSyncPoints(
129 child_id, surface->factory()->needs_sync_points());
131 surface_id_to_resource_child_id_[surface->surface_id()] = child_id;
132 return child_id;
133 } else {
134 return it->second;
139 gfx::Rect SurfaceAggregator::DamageRectForSurface(const Surface* surface,
140 const RenderPass& source,
141 const gfx::Rect& full_rect) {
142 int previous_index = previous_contained_surfaces_[surface->surface_id()];
143 if (previous_index == surface->frame_index())
144 return gfx::Rect();
145 else if (previous_index == surface->frame_index() - 1)
146 return source.damage_rect;
147 return full_rect;
150 void SurfaceAggregator::HandleSurfaceQuad(
151 const SurfaceDrawQuad* surface_quad,
152 const gfx::Transform& target_transform,
153 const ClipData& clip_rect,
154 RenderPass* dest_pass) {
155 SurfaceId surface_id = surface_quad->surface_id;
156 // If this surface's id is already in our referenced set then it creates
157 // a cycle in the graph and should be dropped.
158 if (referenced_surfaces_.count(surface_id))
159 return;
160 Surface* surface = manager_->GetSurfaceForId(surface_id);
161 if (!surface)
162 return;
163 const CompositorFrame* frame = surface->GetEligibleFrame();
164 if (!frame)
165 return;
166 const DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
167 if (!frame_data)
168 return;
170 std::multimap<RenderPassId, CopyOutputRequest*> copy_requests;
171 surface->TakeCopyOutputRequests(&copy_requests);
173 const RenderPassList& render_pass_list = frame_data->render_pass_list;
174 if (!valid_surfaces_.count(surface->surface_id())) {
175 for (auto& request : copy_requests) {
176 request.second->SendEmptyResult();
177 delete request.second;
179 return;
182 SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first;
183 // TODO(vmpstr): provider check is a hack for unittests that don't set up a
184 // resource provider.
185 ResourceProvider::ResourceIdMap empty_map;
186 const ResourceProvider::ResourceIdMap& child_to_parent_map =
187 provider_ ? provider_->GetChildToParentMap(ChildIdForSurface(surface))
188 : empty_map;
189 bool merge_pass =
190 surface_quad->shared_quad_state->opacity == 1.f && copy_requests.empty();
192 const RenderPassList& referenced_passes = render_pass_list;
193 size_t passes_to_copy =
194 merge_pass ? referenced_passes.size() - 1 : referenced_passes.size();
195 for (size_t j = 0; j < passes_to_copy; ++j) {
196 const RenderPass& source = *referenced_passes[j];
198 size_t sqs_size = source.shared_quad_state_list.size();
199 size_t dq_size = source.quad_list.size();
200 scoped_ptr<RenderPass> copy_pass(RenderPass::Create(sqs_size, dq_size));
202 RenderPassId remapped_pass_id = RemapPassId(source.id, surface_id);
204 copy_pass->SetAll(remapped_pass_id, source.output_rect, gfx::Rect(),
205 source.transform_to_root_target,
206 source.has_transparent_background);
208 MoveMatchingRequests(source.id, &copy_requests, &copy_pass->copy_requests);
210 // Contributing passes aggregated in to the pass list need to take the
211 // transform of the surface quad into account to update their transform to
212 // the root surface.
213 copy_pass->transform_to_root_target.ConcatTransform(
214 surface_quad->shared_quad_state->quad_to_target_transform);
215 copy_pass->transform_to_root_target.ConcatTransform(target_transform);
216 copy_pass->transform_to_root_target.ConcatTransform(
217 dest_pass->transform_to_root_target);
219 CopyQuadsToPass(source.quad_list, source.shared_quad_state_list,
220 child_to_parent_map, gfx::Transform(), ClipData(),
221 copy_pass.get(), surface_id);
223 dest_pass_list_->push_back(copy_pass.Pass());
226 gfx::Transform surface_transform =
227 surface_quad->shared_quad_state->quad_to_target_transform;
228 surface_transform.ConcatTransform(target_transform);
230 const RenderPass& last_pass = *render_pass_list.back();
231 if (merge_pass) {
232 // TODO(jamesr): Clean up last pass special casing.
233 const QuadList& quads = last_pass.quad_list;
235 // Intersect the transformed visible rect and the clip rect to create a
236 // smaller cliprect for the quad.
237 ClipData surface_quad_clip_rect(
238 true, MathUtil::MapEnclosingClippedRect(
239 surface_quad->shared_quad_state->quad_to_target_transform,
240 surface_quad->visible_rect));
241 if (surface_quad->shared_quad_state->is_clipped) {
242 surface_quad_clip_rect.rect.Intersect(
243 surface_quad->shared_quad_state->clip_rect);
246 ClipData quads_clip =
247 CalculateClipRect(clip_rect, surface_quad_clip_rect, target_transform);
249 CopyQuadsToPass(quads, last_pass.shared_quad_state_list,
250 child_to_parent_map, surface_transform, quads_clip,
251 dest_pass, surface_id);
252 } else {
253 RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id);
255 SharedQuadState* shared_quad_state =
256 CopySharedQuadState(surface_quad->shared_quad_state, target_transform,
257 clip_rect, dest_pass);
259 RenderPassDrawQuad* quad =
260 dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
261 quad->SetNew(shared_quad_state,
262 surface_quad->rect,
263 surface_quad->visible_rect,
264 remapped_pass_id,
266 gfx::Vector2dF(),
267 gfx::Size(),
268 FilterOperations(),
269 gfx::Vector2dF(),
270 FilterOperations());
273 referenced_surfaces_.erase(it);
276 SharedQuadState* SurfaceAggregator::CopySharedQuadState(
277 const SharedQuadState* source_sqs,
278 const gfx::Transform& target_transform,
279 const ClipData& clip_rect,
280 RenderPass* dest_render_pass) {
281 SharedQuadState* copy_shared_quad_state =
282 dest_render_pass->CreateAndAppendSharedQuadState();
283 copy_shared_quad_state->CopyFrom(source_sqs);
284 // target_transform contains any transformation that may exist
285 // between the context that these quads are being copied from (i.e. the
286 // surface's draw transform when aggregated from within a surface) to the
287 // target space of the pass. This will be identity except when copying the
288 // root draw pass from a surface into a pass when the surface draw quad's
289 // transform is not identity.
290 copy_shared_quad_state->quad_to_target_transform.ConcatTransform(
291 target_transform);
293 ClipData new_clip_rect = CalculateClipRect(
294 clip_rect, ClipData(source_sqs->is_clipped, source_sqs->clip_rect),
295 target_transform);
296 copy_shared_quad_state->is_clipped = new_clip_rect.is_clipped;
297 copy_shared_quad_state->clip_rect = new_clip_rect.rect;
298 return copy_shared_quad_state;
301 static gfx::Rect CalculateQuadSpaceDamageRect(
302 const gfx::Transform& quad_to_target_transform,
303 const gfx::Transform& target_to_root_transform,
304 const gfx::Rect& root_damage_rect) {
305 gfx::Transform quad_to_root_transform(target_to_root_transform,
306 quad_to_target_transform);
307 gfx::Transform inverse_transform(gfx::Transform::kSkipInitialization);
308 bool inverse_valid = quad_to_root_transform.GetInverse(&inverse_transform);
309 DCHECK(inverse_valid);
311 return MathUtil::ProjectEnclosingClippedRect(inverse_transform,
312 root_damage_rect);
315 void SurfaceAggregator::CopyQuadsToPass(
316 const QuadList& source_quad_list,
317 const SharedQuadStateList& source_shared_quad_state_list,
318 const ResourceProvider::ResourceIdMap& child_to_parent_map,
319 const gfx::Transform& target_transform,
320 const ClipData& clip_rect,
321 RenderPass* dest_pass,
322 SurfaceId surface_id) {
323 const SharedQuadState* last_copied_source_shared_quad_state = nullptr;
324 const SharedQuadState* dest_shared_quad_state = nullptr;
325 // If the current frame has copy requests then aggregate the entire
326 // thing, as otherwise parts of the copy requests may be ignored.
327 const bool ignore_undamaged = aggregate_only_damaged_ && !has_copy_requests_;
328 // Damage rect in the quad space of the current shared quad state.
329 // TODO(jbauman): This rect may contain unnecessary area if
330 // transform isn't axis-aligned.
331 gfx::Rect damage_rect_in_quad_space;
333 #if DCHECK_IS_ON()
334 // If quads have come in with SharedQuadState out of order, or when quads have
335 // invalid SharedQuadState pointer, it should DCHECK.
336 SharedQuadStateList::ConstIterator sqs_iter =
337 source_shared_quad_state_list.begin();
338 for (const auto& quad : source_quad_list) {
339 while (sqs_iter != source_shared_quad_state_list.end() &&
340 quad->shared_quad_state != *sqs_iter) {
341 ++sqs_iter;
343 DCHECK(sqs_iter != source_shared_quad_state_list.end());
345 #endif
347 for (const auto& quad : source_quad_list) {
348 if (quad->material == DrawQuad::SURFACE_CONTENT) {
349 const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
350 // HandleSurfaceQuad may add other shared quad state, so reset the
351 // current data.
352 last_copied_source_shared_quad_state = nullptr;
354 if (ignore_undamaged) {
355 gfx::Transform quad_to_target_transform(
356 target_transform,
357 quad->shared_quad_state->quad_to_target_transform);
358 damage_rect_in_quad_space = CalculateQuadSpaceDamageRect(
359 quad_to_target_transform, dest_pass->transform_to_root_target,
360 root_damage_rect_);
361 if (!damage_rect_in_quad_space.Intersects(quad->visible_rect))
362 continue;
364 HandleSurfaceQuad(surface_quad, target_transform, clip_rect, dest_pass);
365 } else {
366 if (quad->shared_quad_state != last_copied_source_shared_quad_state) {
367 dest_shared_quad_state = CopySharedQuadState(
368 quad->shared_quad_state, target_transform, clip_rect, dest_pass);
369 last_copied_source_shared_quad_state = quad->shared_quad_state;
370 if (aggregate_only_damaged_ && !has_copy_requests_) {
371 damage_rect_in_quad_space = CalculateQuadSpaceDamageRect(
372 dest_shared_quad_state->quad_to_target_transform,
373 dest_pass->transform_to_root_target, root_damage_rect_);
377 if (ignore_undamaged) {
378 if (!damage_rect_in_quad_space.Intersects(quad->visible_rect))
379 continue;
382 DrawQuad* dest_quad;
383 if (quad->material == DrawQuad::RENDER_PASS) {
384 const RenderPassDrawQuad* pass_quad =
385 RenderPassDrawQuad::MaterialCast(quad);
386 RenderPassId original_pass_id = pass_quad->render_pass_id;
387 RenderPassId remapped_pass_id =
388 RemapPassId(original_pass_id, surface_id);
390 dest_quad = dest_pass->CopyFromAndAppendRenderPassDrawQuad(
391 pass_quad, dest_shared_quad_state, remapped_pass_id);
392 } else {
393 dest_quad =
394 dest_pass->CopyFromAndAppendDrawQuad(quad, dest_shared_quad_state);
396 if (!child_to_parent_map.empty()) {
397 for (ResourceId& resource_id : dest_quad->resources) {
398 ResourceProvider::ResourceIdMap::const_iterator it =
399 child_to_parent_map.find(resource_id);
400 DCHECK(it != child_to_parent_map.end());
402 DCHECK_EQ(it->first, resource_id);
403 ResourceId remapped_id = it->second;
404 resource_id = remapped_id;
411 void SurfaceAggregator::CopyPasses(const DelegatedFrameData* frame_data,
412 Surface* surface) {
413 // The root surface is allowed to have copy output requests, so grab them
414 // off its render passes.
415 std::multimap<RenderPassId, CopyOutputRequest*> copy_requests;
416 surface->TakeCopyOutputRequests(&copy_requests);
418 const RenderPassList& source_pass_list = frame_data->render_pass_list;
419 DCHECK(valid_surfaces_.count(surface->surface_id()));
420 if (!valid_surfaces_.count(surface->surface_id()))
421 return;
423 // TODO(vmpstr): provider check is a hack for unittests that don't set up a
424 // resource provider.
425 ResourceProvider::ResourceIdMap empty_map;
426 const ResourceProvider::ResourceIdMap& child_to_parent_map =
427 provider_ ? provider_->GetChildToParentMap(ChildIdForSurface(surface))
428 : empty_map;
429 for (size_t i = 0; i < source_pass_list.size(); ++i) {
430 const RenderPass& source = *source_pass_list[i];
432 size_t sqs_size = source.shared_quad_state_list.size();
433 size_t dq_size = source.quad_list.size();
434 scoped_ptr<RenderPass> copy_pass(RenderPass::Create(sqs_size, dq_size));
436 MoveMatchingRequests(source.id, &copy_requests, &copy_pass->copy_requests);
438 RenderPassId remapped_pass_id =
439 RemapPassId(source.id, surface->surface_id());
441 copy_pass->SetAll(remapped_pass_id, source.output_rect, gfx::Rect(),
442 source.transform_to_root_target,
443 source.has_transparent_background);
445 CopyQuadsToPass(source.quad_list, source.shared_quad_state_list,
446 child_to_parent_map, gfx::Transform(), ClipData(),
447 copy_pass.get(), surface->surface_id());
449 dest_pass_list_->push_back(copy_pass.Pass());
453 void SurfaceAggregator::RemoveUnreferencedChildren() {
454 for (const auto& surface : previous_contained_surfaces_) {
455 if (!contained_surfaces_.count(surface.first)) {
456 SurfaceToResourceChildIdMap::iterator it =
457 surface_id_to_resource_child_id_.find(surface.first);
458 if (it != surface_id_to_resource_child_id_.end()) {
459 provider_->DestroyChild(it->second);
460 surface_id_to_resource_child_id_.erase(it);
463 Surface* surface_ptr = manager_->GetSurfaceForId(surface.first);
464 if (surface_ptr)
465 surface_ptr->RunDrawCallbacks(SurfaceDrawStatus::DRAW_SKIPPED);
470 // Walk the Surface tree from surface_id. Validate the resources of the current
471 // surface and its descendants, check if there are any copy requests, and
472 // return the combined damage rect.
473 gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id) {
474 if (referenced_surfaces_.count(surface_id))
475 return gfx::Rect();
476 Surface* surface = manager_->GetSurfaceForId(surface_id);
477 if (!surface) {
478 contained_surfaces_[surface_id] = 0;
479 return gfx::Rect();
481 contained_surfaces_[surface_id] = surface->frame_index();
482 const CompositorFrame* surface_frame = surface->GetEligibleFrame();
483 if (!surface_frame)
484 return gfx::Rect();
485 const DelegatedFrameData* frame_data =
486 surface_frame->delegated_frame_data.get();
487 if (!frame_data)
488 return gfx::Rect();
489 int child_id = 0;
490 // TODO(jbauman): hack for unit tests that don't set up rp
491 if (provider_) {
492 child_id = ChildIdForSurface(surface);
493 if (surface->factory())
494 surface->factory()->RefResources(frame_data->resource_list);
495 provider_->ReceiveFromChild(child_id, frame_data->resource_list);
498 ResourceProvider::ResourceIdSet referenced_resources;
499 size_t reserve_size = frame_data->resource_list.size();
500 #if defined(COMPILER_MSVC)
501 referenced_resources.reserve(reserve_size);
502 #elif defined(COMPILER_GCC)
503 // Pre-standard hash-tables only implement resize, which behaves similarly
504 // to reserve for these keys. Resizing to 0 may also be broken (particularly
505 // on stlport).
506 // TODO(jbauman): Replace with reserve when C++11 is supported everywhere.
507 if (reserve_size)
508 referenced_resources.resize(reserve_size);
509 #endif
511 bool invalid_frame = false;
512 ResourceProvider::ResourceIdMap empty_map;
513 const ResourceProvider::ResourceIdMap& child_to_parent_map =
514 provider_ ? provider_->GetChildToParentMap(child_id) : empty_map;
516 // Each pair in the vector is a child surface and the transform from its
517 // target to the root target of this surface.
518 std::vector<std::pair<SurfaceId, gfx::Transform>> child_surfaces;
519 for (const auto& render_pass : frame_data->render_pass_list) {
520 for (const auto& quad : render_pass->quad_list) {
521 if (quad->material == DrawQuad::SURFACE_CONTENT) {
522 const SurfaceDrawQuad* surface_quad =
523 SurfaceDrawQuad::MaterialCast(quad);
524 gfx::Transform target_to_surface_transform(
525 render_pass->transform_to_root_target,
526 surface_quad->shared_quad_state->quad_to_target_transform);
527 child_surfaces.push_back(std::make_pair(surface_quad->surface_id,
528 target_to_surface_transform));
531 if (!provider_)
532 continue;
533 for (ResourceId resource_id : quad->resources) {
534 if (!child_to_parent_map.count(resource_id)) {
535 invalid_frame = true;
536 break;
538 referenced_resources.insert(resource_id);
543 if (invalid_frame)
544 return gfx::Rect();
545 valid_surfaces_.insert(surface->surface_id());
547 if (provider_)
548 provider_->DeclareUsedResourcesFromChild(child_id, referenced_resources);
550 for (const auto& render_pass : frame_data->render_pass_list)
551 has_copy_requests_ |= !render_pass->copy_requests.empty();
553 gfx::Rect damage_rect;
554 if (!frame_data->render_pass_list.empty()) {
555 RenderPass* last_pass = frame_data->render_pass_list.back();
556 damage_rect =
557 DamageRectForSurface(surface, *last_pass, last_pass->output_rect);
560 // Avoid infinite recursion by adding current surface to
561 // referenced_surfaces_.
562 SurfaceSet::iterator it =
563 referenced_surfaces_.insert(surface->surface_id()).first;
564 for (const auto& surface_info : child_surfaces) {
565 gfx::Rect surface_damage = PrewalkTree(surface_info.first);
566 damage_rect.Union(
567 MathUtil::MapEnclosingClippedRect(surface_info.second, surface_damage));
569 referenced_surfaces_.erase(it);
570 return damage_rect;
573 scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) {
574 Surface* surface = manager_->GetSurfaceForId(surface_id);
575 DCHECK(surface);
576 contained_surfaces_[surface_id] = surface->frame_index();
577 const CompositorFrame* root_surface_frame = surface->GetEligibleFrame();
578 if (!root_surface_frame)
579 return nullptr;
580 TRACE_EVENT0("cc", "SurfaceAggregator::Aggregate");
582 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
583 frame->delegated_frame_data = make_scoped_ptr(new DelegatedFrameData);
585 DCHECK(root_surface_frame->delegated_frame_data);
587 dest_resource_list_ = &frame->delegated_frame_data->resource_list;
588 dest_pass_list_ = &frame->delegated_frame_data->render_pass_list;
590 valid_surfaces_.clear();
591 has_copy_requests_ = false;
592 root_damage_rect_ = PrewalkTree(surface_id);
594 SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first;
595 CopyPasses(root_surface_frame->delegated_frame_data.get(), surface);
596 referenced_surfaces_.erase(it);
598 DCHECK(referenced_surfaces_.empty());
600 if (dest_pass_list_->empty())
601 return nullptr;
602 dest_pass_list_->back()->damage_rect = root_damage_rect_;
604 dest_pass_list_ = NULL;
605 RemoveUnreferencedChildren();
606 contained_surfaces_.swap(previous_contained_surfaces_);
607 contained_surfaces_.clear();
609 for (SurfaceIndexMap::iterator it = previous_contained_surfaces_.begin();
610 it != previous_contained_surfaces_.end();
611 ++it) {
612 Surface* surface = manager_->GetSurfaceForId(it->first);
613 if (surface)
614 surface->TakeLatencyInfo(&frame->metadata.latency_info);
617 // TODO(jamesr): Aggregate all resource references into the returned frame's
618 // resource list.
620 return frame.Pass();
623 void SurfaceAggregator::ReleaseResources(SurfaceId surface_id) {
624 SurfaceToResourceChildIdMap::iterator it =
625 surface_id_to_resource_child_id_.find(surface_id);
626 if (it != surface_id_to_resource_child_id_.end()) {
627 provider_->DestroyChild(it->second);
628 surface_id_to_resource_child_id_.erase(it);
632 void SurfaceAggregator::SetFullDamageForSurface(SurfaceId surface_id) {
633 auto it = previous_contained_surfaces_.find(surface_id);
634 if (it == previous_contained_surfaces_.end())
635 return;
636 // Set the last drawn index as 0 to ensure full damage next time it's drawn.
637 it->second = 0;
640 } // namespace cc