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

Side by Side Diff: cc/surfaces/surface_aggregator.cc

Issue 1535833002: Delete CC. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-5
Patch Set: rebase Created 4 years, 10 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 unified diff | Download patch
« no previous file with comments | « cc/surfaces/surface_aggregator.h ('k') | cc/surfaces/surface_aggregator_test_helpers.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "cc/surfaces/surface_aggregator.h"
6
7 #include <map>
8
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
24 namespace cc {
25 namespace {
26
27 void MoveMatchingRequests(
28 RenderPassId id,
29 std::multimap<RenderPassId, CopyOutputRequest*>* copy_requests,
30 ScopedPtrVector<CopyOutputRequest>* output_requests) {
31 auto request_range = copy_requests->equal_range(id);
32 for (auto it = request_range.first; it != request_range.second; ++it) {
33 DCHECK(it->second);
34 output_requests->push_back(scoped_ptr<CopyOutputRequest>(it->second));
35 it->second = nullptr;
36 }
37 copy_requests->erase(request_range.first, request_range.second);
38 }
39
40 } // namespace
41
42 SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager,
43 ResourceProvider* provider)
44 : manager_(manager), provider_(provider), next_render_pass_id_(1) {
45 DCHECK(manager_);
46 }
47
48 SurfaceAggregator::~SurfaceAggregator() {}
49
50 // Create a clip rect for an aggregated quad from the original clip rect and
51 // the clip rect from the surface it's on.
52 SurfaceAggregator::ClipData SurfaceAggregator::CalculateClipRect(
53 const ClipData& surface_clip,
54 const ClipData& quad_clip,
55 const gfx::Transform& content_to_target_transform) {
56 ClipData out_clip;
57 if (surface_clip.is_clipped)
58 out_clip = surface_clip;
59
60 if (quad_clip.is_clipped) {
61 // TODO(jamesr): This only works if content_to_target_transform maps integer
62 // rects to integer rects.
63 gfx::Rect final_clip = MathUtil::MapEnclosingClippedRect(
64 content_to_target_transform, quad_clip.rect);
65 if (out_clip.is_clipped)
66 out_clip.rect.Intersect(final_clip);
67 else
68 out_clip.rect = final_clip;
69 out_clip.is_clipped = true;
70 }
71
72 return out_clip;
73 }
74
75 class SurfaceAggregator::RenderPassIdAllocator {
76 public:
77 explicit RenderPassIdAllocator(int* next_index) : next_index_(next_index) {}
78 ~RenderPassIdAllocator() {}
79
80 void AddKnownPass(RenderPassId id) {
81 if (id_to_index_map_.find(id) != id_to_index_map_.end())
82 return;
83 id_to_index_map_[id] = (*next_index_)++;
84 }
85
86 RenderPassId Remap(RenderPassId id) {
87 DCHECK(id_to_index_map_.find(id) != id_to_index_map_.end());
88 return RenderPassId(1, id_to_index_map_[id]);
89 }
90
91 private:
92 base::hash_map<RenderPassId, int> id_to_index_map_;
93 int* next_index_;
94
95 DISALLOW_COPY_AND_ASSIGN(RenderPassIdAllocator);
96 };
97
98 static void UnrefHelper(base::WeakPtr<SurfaceFactory> surface_factory,
99 const ReturnedResourceArray& resources,
100 BlockingTaskRunner* main_thread_task_runner) {
101 if (surface_factory)
102 surface_factory->UnrefResources(resources);
103 }
104
105 RenderPassId SurfaceAggregator::RemapPassId(RenderPassId surface_local_pass_id,
106 SurfaceId surface_id) {
107 RenderPassIdAllocator* allocator = render_pass_allocator_map_.get(surface_id);
108 if (!allocator) {
109 allocator = new RenderPassIdAllocator(&next_render_pass_id_);
110 render_pass_allocator_map_.set(surface_id, make_scoped_ptr(allocator));
111 }
112 allocator->AddKnownPass(surface_local_pass_id);
113 return allocator->Remap(surface_local_pass_id);
114 }
115
116 int SurfaceAggregator::ChildIdForSurface(Surface* surface) {
117 SurfaceToResourceChildIdMap::iterator it =
118 surface_id_to_resource_child_id_.find(surface->surface_id());
119 if (it == surface_id_to_resource_child_id_.end()) {
120 int child_id =
121 provider_->CreateChild(base::Bind(&UnrefHelper, surface->factory()));
122 surface_id_to_resource_child_id_[surface->surface_id()] = child_id;
123 return child_id;
124 } else {
125 return it->second;
126 }
127 }
128
129 static ResourceProvider::ResourceId ResourceRemapHelper(
130 bool* invalid_frame,
131 const ResourceProvider::ResourceIdMap& child_to_parent_map,
132 ResourceProvider::ResourceIdArray* resources_in_frame,
133 ResourceProvider::ResourceId id) {
134 ResourceProvider::ResourceIdMap::const_iterator it =
135 child_to_parent_map.find(id);
136 if (it == child_to_parent_map.end()) {
137 *invalid_frame = true;
138 return 0;
139 }
140
141 DCHECK_EQ(it->first, id);
142 ResourceProvider::ResourceId remapped_id = it->second;
143 resources_in_frame->push_back(id);
144 return remapped_id;
145 }
146
147 bool SurfaceAggregator::TakeResources(Surface* surface,
148 const DelegatedFrameData* frame_data,
149 RenderPassList* render_pass_list) {
150 RenderPass::CopyAll(frame_data->render_pass_list, render_pass_list);
151 if (!provider_) // TODO(jamesr): hack for unit tests that don't set up rp
152 return false;
153
154 int child_id = ChildIdForSurface(surface);
155 if (surface->factory())
156 surface->factory()->RefResources(frame_data->resource_list);
157 provider_->ReceiveFromChild(child_id, frame_data->resource_list);
158
159 typedef ResourceProvider::ResourceIdArray IdArray;
160 IdArray referenced_resources;
161
162 bool invalid_frame = false;
163 DrawQuad::ResourceIteratorCallback remap =
164 base::Bind(&ResourceRemapHelper,
165 &invalid_frame,
166 provider_->GetChildToParentMap(child_id),
167 &referenced_resources);
168 for (const auto& render_pass : *render_pass_list) {
169 for (const auto& quad : render_pass->quad_list)
170 quad->IterateResources(remap);
171 }
172
173 if (!invalid_frame)
174 provider_->DeclareUsedResourcesFromChild(child_id, referenced_resources);
175
176 return invalid_frame;
177 }
178
179 gfx::Rect SurfaceAggregator::DamageRectForSurface(const Surface* surface,
180 const RenderPass& source,
181 const gfx::Rect& full_rect) {
182 int previous_index = previous_contained_surfaces_[surface->surface_id()];
183 if (previous_index == surface->frame_index())
184 return gfx::Rect();
185 else if (previous_index == surface->frame_index() - 1)
186 return source.damage_rect;
187 return full_rect;
188 }
189
190 void SurfaceAggregator::HandleSurfaceQuad(
191 const SurfaceDrawQuad* surface_quad,
192 const gfx::Transform& content_to_target_transform,
193 const ClipData& clip_rect,
194 RenderPass* dest_pass) {
195 SurfaceId surface_id = surface_quad->surface_id;
196 // If this surface's id is already in our referenced set then it creates
197 // a cycle in the graph and should be dropped.
198 if (referenced_surfaces_.count(surface_id))
199 return;
200 Surface* surface = manager_->GetSurfaceForId(surface_id);
201 if (!surface) {
202 contained_surfaces_[surface_id] = 0;
203 return;
204 }
205 contained_surfaces_[surface_id] = surface->frame_index();
206 const CompositorFrame* frame = surface->GetEligibleFrame();
207 if (!frame)
208 return;
209 const DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
210 if (!frame_data)
211 return;
212
213 std::multimap<RenderPassId, CopyOutputRequest*> copy_requests;
214 surface->TakeCopyOutputRequests(&copy_requests);
215
216 RenderPassList render_pass_list;
217 bool invalid_frame = TakeResources(surface, frame_data, &render_pass_list);
218 if (invalid_frame) {
219 for (auto& request : copy_requests) {
220 request.second->SendEmptyResult();
221 delete request.second;
222 }
223 return;
224 }
225
226 SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first;
227
228 bool merge_pass = surface_quad->opacity() == 1.f && copy_requests.empty();
229
230 gfx::Rect surface_damage = DamageRectForSurface(
231 surface, *render_pass_list.back(), surface_quad->visible_rect);
232 const RenderPassList& referenced_passes = render_pass_list;
233 size_t passes_to_copy =
234 merge_pass ? referenced_passes.size() - 1 : referenced_passes.size();
235 for (size_t j = 0; j < passes_to_copy; ++j) {
236 const RenderPass& source = *referenced_passes[j];
237
238 size_t sqs_size = source.shared_quad_state_list.size();
239 size_t dq_size = source.quad_list.size();
240 scoped_ptr<RenderPass> copy_pass(RenderPass::Create(sqs_size, dq_size));
241
242 RenderPassId remapped_pass_id = RemapPassId(source.id, surface_id);
243
244 copy_pass->SetAll(remapped_pass_id, source.output_rect, gfx::Rect(),
245 source.transform_to_root_target,
246 source.has_transparent_background);
247
248 MoveMatchingRequests(source.id, &copy_requests, &copy_pass->copy_requests);
249
250 // Contributing passes aggregated in to the pass list need to take the
251 // transform of the surface quad into account to update their transform to
252 // the root surface.
253 copy_pass->transform_to_root_target.ConcatTransform(
254 surface_quad->quadTransform());
255 copy_pass->transform_to_root_target.ConcatTransform(
256 content_to_target_transform);
257 copy_pass->transform_to_root_target.ConcatTransform(
258 dest_pass->transform_to_root_target);
259
260 CopyQuadsToPass(source.quad_list, source.shared_quad_state_list,
261 gfx::Transform(), ClipData(), copy_pass.get(), surface_id);
262
263 if (j == referenced_passes.size() - 1)
264 surface_damage = gfx::UnionRects(surface_damage, copy_pass->damage_rect);
265
266 dest_pass_list_->push_back(copy_pass.Pass());
267 }
268
269 const RenderPass& last_pass = *render_pass_list.back();
270 if (merge_pass) {
271 // TODO(jamesr): Clean up last pass special casing.
272 const QuadList& quads = last_pass.quad_list;
273
274 gfx::Transform surface_transform = surface_quad->quadTransform();
275 surface_transform.ConcatTransform(content_to_target_transform);
276
277 // Intersect the transformed visible rect and the clip rect to create a
278 // smaller cliprect for the quad.
279 ClipData surface_quad_clip_rect(
280 true, MathUtil::MapEnclosingClippedRect(surface_quad->quadTransform(),
281 surface_quad->visible_rect));
282 if (surface_quad->isClipped())
283 surface_quad_clip_rect.rect.Intersect(surface_quad->clipRect());
284
285 ClipData quads_clip = CalculateClipRect(clip_rect, surface_quad_clip_rect,
286 content_to_target_transform);
287
288 CopyQuadsToPass(quads, last_pass.shared_quad_state_list, surface_transform,
289 quads_clip, dest_pass, surface_id);
290 } else {
291 RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id);
292
293 CopySharedQuadState(surface_quad->shared_quad_state,
294 content_to_target_transform, clip_rect, dest_pass);
295
296 SharedQuadState* shared_quad_state =
297 dest_pass->shared_quad_state_list.back();
298 RenderPassDrawQuad* quad =
299 dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
300 quad->SetNew(shared_quad_state,
301 surface_quad->rect,
302 surface_quad->visible_rect,
303 remapped_pass_id,
304 0,
305 gfx::Vector2dF(),
306 gfx::Size(),
307 FilterOperations(),
308 gfx::Vector2dF(),
309 FilterOperations());
310 }
311 dest_pass->damage_rect =
312 gfx::UnionRects(dest_pass->damage_rect,
313 MathUtil::MapEnclosingClippedRect(
314 surface_quad->quadTransform(), surface_damage));
315
316 referenced_surfaces_.erase(it);
317 }
318
319 void SurfaceAggregator::CopySharedQuadState(
320 const SharedQuadState* source_sqs,
321 const gfx::Transform& content_to_target_transform,
322 const ClipData& clip_rect,
323 RenderPass* dest_render_pass) {
324 SharedQuadState* copy_shared_quad_state =
325 dest_render_pass->CreateAndAppendSharedQuadState();
326 copy_shared_quad_state->CopyFrom(source_sqs);
327 // content_to_target_transform contains any transformation that may exist
328 // between the context that these quads are being copied from (i.e. the
329 // surface's draw transform when aggregated from within a surface) to the
330 // target space of the pass. This will be identity except when copying the
331 // root draw pass from a surface into a pass when the surface draw quad's
332 // transform is not identity.
333 copy_shared_quad_state->content_to_target_transform.ConcatTransform(
334 content_to_target_transform);
335
336 ClipData new_clip_rect = CalculateClipRect(
337 clip_rect, ClipData(source_sqs->is_clipped, source_sqs->clip_rect),
338 content_to_target_transform);
339 copy_shared_quad_state->is_clipped = new_clip_rect.is_clipped;
340 copy_shared_quad_state->clip_rect = new_clip_rect.rect;
341 }
342
343 void SurfaceAggregator::CopyQuadsToPass(
344 const QuadList& source_quad_list,
345 const SharedQuadStateList& source_shared_quad_state_list,
346 const gfx::Transform& content_to_target_transform,
347 const ClipData& clip_rect,
348 RenderPass* dest_pass,
349 SurfaceId surface_id) {
350 const SharedQuadState* last_copied_source_shared_quad_state = NULL;
351
352 SharedQuadStateList::ConstIterator sqs_iter =
353 source_shared_quad_state_list.begin();
354 for (const auto& quad : source_quad_list) {
355 while (quad->shared_quad_state != *sqs_iter) {
356 ++sqs_iter;
357 DCHECK(sqs_iter != source_shared_quad_state_list.end());
358 }
359 DCHECK_EQ(quad->shared_quad_state, *sqs_iter);
360
361 if (quad->material == DrawQuad::SURFACE_CONTENT) {
362 const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
363 HandleSurfaceQuad(surface_quad, content_to_target_transform, clip_rect,
364 dest_pass);
365 } else {
366 if (quad->shared_quad_state != last_copied_source_shared_quad_state) {
367 CopySharedQuadState(quad->shared_quad_state,
368 content_to_target_transform, clip_rect, dest_pass);
369 last_copied_source_shared_quad_state = quad->shared_quad_state;
370 }
371 if (quad->material == DrawQuad::RENDER_PASS) {
372 const RenderPassDrawQuad* pass_quad =
373 RenderPassDrawQuad::MaterialCast(quad);
374 RenderPassId original_pass_id = pass_quad->render_pass_id;
375 RenderPassId remapped_pass_id =
376 RemapPassId(original_pass_id, surface_id);
377
378 gfx::Rect pass_damage;
379 for (const auto* pass : *dest_pass_list_) {
380 if (pass->id == remapped_pass_id) {
381 pass_damage = pass->damage_rect;
382 break;
383 }
384 }
385
386 DrawQuad* rpdq = dest_pass->CopyFromAndAppendRenderPassDrawQuad(
387 pass_quad, dest_pass->shared_quad_state_list.back(),
388 remapped_pass_id);
389 dest_pass->damage_rect = gfx::UnionRects(
390 dest_pass->damage_rect, MathUtil::MapEnclosingClippedRect(
391 rpdq->quadTransform(), pass_damage));
392 } else {
393 dest_pass->CopyFromAndAppendDrawQuad(
394 quad, dest_pass->shared_quad_state_list.back());
395 }
396 }
397 }
398 }
399
400 void SurfaceAggregator::CopyPasses(const DelegatedFrameData* frame_data,
401 Surface* surface) {
402 RenderPassList source_pass_list;
403
404 // The root surface is allowed to have copy output requests, so grab them
405 // off its render passes.
406 std::multimap<RenderPassId, CopyOutputRequest*> copy_requests;
407 surface->TakeCopyOutputRequests(&copy_requests);
408
409 bool invalid_frame = TakeResources(surface, frame_data, &source_pass_list);
410 DCHECK(!invalid_frame);
411
412 for (size_t i = 0; i < source_pass_list.size(); ++i) {
413 const RenderPass& source = *source_pass_list[i];
414
415 size_t sqs_size = source.shared_quad_state_list.size();
416 size_t dq_size = source.quad_list.size();
417 scoped_ptr<RenderPass> copy_pass(RenderPass::Create(sqs_size, dq_size));
418
419 MoveMatchingRequests(source.id, &copy_requests, &copy_pass->copy_requests);
420
421 RenderPassId remapped_pass_id =
422 RemapPassId(source.id, surface->surface_id());
423
424 gfx::Rect damage_rect =
425 (i < source_pass_list.size() - 1)
426 ? gfx::Rect()
427 : DamageRectForSurface(surface, source, source.output_rect);
428 copy_pass->SetAll(remapped_pass_id, source.output_rect, damage_rect,
429 source.transform_to_root_target,
430 source.has_transparent_background);
431
432 CopyQuadsToPass(source.quad_list, source.shared_quad_state_list,
433 gfx::Transform(), ClipData(), copy_pass.get(),
434 surface->surface_id());
435
436 dest_pass_list_->push_back(copy_pass.Pass());
437 }
438 }
439
440 void SurfaceAggregator::RemoveUnreferencedChildren() {
441 for (const auto& surface : previous_contained_surfaces_) {
442 if (!contained_surfaces_.count(surface.first)) {
443 SurfaceToResourceChildIdMap::iterator it =
444 surface_id_to_resource_child_id_.find(surface.first);
445 if (it != surface_id_to_resource_child_id_.end()) {
446 provider_->DestroyChild(it->second);
447 surface_id_to_resource_child_id_.erase(it);
448 }
449
450 Surface* surface_ptr = manager_->GetSurfaceForId(surface.first);
451 if (surface_ptr)
452 surface_ptr->RunDrawCallbacks(SurfaceDrawStatus::DRAW_SKIPPED);
453 }
454 }
455 }
456
457 scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) {
458 Surface* surface = manager_->GetSurfaceForId(surface_id);
459 DCHECK(surface);
460 contained_surfaces_[surface_id] = surface->frame_index();
461 const CompositorFrame* root_surface_frame = surface->GetEligibleFrame();
462 if (!root_surface_frame)
463 return nullptr;
464 TRACE_EVENT0("cc", "SurfaceAggregator::Aggregate");
465
466 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
467 frame->delegated_frame_data = make_scoped_ptr(new DelegatedFrameData);
468
469 DCHECK(root_surface_frame->delegated_frame_data);
470
471 SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first;
472
473 dest_resource_list_ = &frame->delegated_frame_data->resource_list;
474 dest_pass_list_ = &frame->delegated_frame_data->render_pass_list;
475
476 CopyPasses(root_surface_frame->delegated_frame_data.get(), surface);
477
478 referenced_surfaces_.erase(it);
479 DCHECK(referenced_surfaces_.empty());
480
481 if (dest_pass_list_->empty())
482 return nullptr;
483
484 dest_pass_list_ = NULL;
485 RemoveUnreferencedChildren();
486 contained_surfaces_.swap(previous_contained_surfaces_);
487 contained_surfaces_.clear();
488
489 for (SurfaceIndexMap::iterator it = previous_contained_surfaces_.begin();
490 it != previous_contained_surfaces_.end();
491 ++it) {
492 Surface* surface = manager_->GetSurfaceForId(it->first);
493 if (surface)
494 surface->TakeLatencyInfo(&frame->metadata.latency_info);
495 }
496
497 // TODO(jamesr): Aggregate all resource references into the returned frame's
498 // resource list.
499
500 return frame.Pass();
501 }
502
503 void SurfaceAggregator::ReleaseResources(SurfaceId surface_id) {
504 SurfaceToResourceChildIdMap::iterator it =
505 surface_id_to_resource_child_id_.find(surface_id);
506 if (it != surface_id_to_resource_child_id_.end()) {
507 provider_->DestroyChild(it->second);
508 surface_id_to_resource_child_id_.erase(it);
509 }
510 }
511
512 } // namespace cc
OLDNEW
« no previous file with comments | « cc/surfaces/surface_aggregator.h ('k') | cc/surfaces/surface_aggregator_test_helpers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698