OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/surfaces/surface_aggregator.h" | 5 #include "cc/surfaces/surface_aggregator.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 } // namespace | 41 } // namespace |
42 | 42 |
43 SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager, | 43 SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager, |
44 ResourceProvider* provider) | 44 ResourceProvider* provider) |
45 : manager_(manager), provider_(provider), next_render_pass_id_(1) { | 45 : manager_(manager), provider_(provider), next_render_pass_id_(1) { |
46 DCHECK(manager_); | 46 DCHECK(manager_); |
47 } | 47 } |
48 | 48 |
49 SurfaceAggregator::~SurfaceAggregator() {} | 49 SurfaceAggregator::~SurfaceAggregator() {} |
50 | 50 |
| 51 // Create a clip rect for an aggregated quad from the original clip rect and |
| 52 // the clip rect from the surface it's on. |
| 53 SurfaceAggregator::ClipData SurfaceAggregator::CalculateClipRect( |
| 54 const ClipData& surface_clip, |
| 55 const ClipData& quad_clip, |
| 56 const gfx::Transform& content_to_target_transform) { |
| 57 ClipData out_clip; |
| 58 if (surface_clip.is_clipped) |
| 59 out_clip = surface_clip; |
| 60 |
| 61 if (quad_clip.is_clipped) { |
| 62 // TODO(jamesr): This only works if content_to_target_transform maps integer |
| 63 // rects to integer rects. |
| 64 gfx::Rect final_clip = MathUtil::MapEnclosingClippedRect( |
| 65 content_to_target_transform, quad_clip.rect); |
| 66 if (out_clip.is_clipped) |
| 67 out_clip.rect.Intersect(final_clip); |
| 68 else |
| 69 out_clip.rect = final_clip; |
| 70 out_clip.is_clipped = true; |
| 71 } |
| 72 |
| 73 return out_clip; |
| 74 } |
| 75 |
51 class SurfaceAggregator::RenderPassIdAllocator { | 76 class SurfaceAggregator::RenderPassIdAllocator { |
52 public: | 77 public: |
53 explicit RenderPassIdAllocator(int* next_index) : next_index_(next_index) {} | 78 explicit RenderPassIdAllocator(int* next_index) : next_index_(next_index) {} |
54 ~RenderPassIdAllocator() {} | 79 ~RenderPassIdAllocator() {} |
55 | 80 |
56 void AddKnownPass(RenderPassId id) { | 81 void AddKnownPass(RenderPassId id) { |
57 if (id_to_index_map_.find(id) != id_to_index_map_.end()) | 82 if (id_to_index_map_.find(id) != id_to_index_map_.end()) |
58 return; | 83 return; |
59 id_to_index_map_[id] = (*next_index_)++; | 84 id_to_index_map_[id] = (*next_index_)++; |
60 } | 85 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 const RenderPass& source, | 181 const RenderPass& source, |
157 const gfx::Rect& full_rect) { | 182 const gfx::Rect& full_rect) { |
158 int previous_index = previous_contained_surfaces_[surface->surface_id()]; | 183 int previous_index = previous_contained_surfaces_[surface->surface_id()]; |
159 if (previous_index == surface->frame_index()) | 184 if (previous_index == surface->frame_index()) |
160 return gfx::Rect(); | 185 return gfx::Rect(); |
161 else if (previous_index == surface->frame_index() - 1) | 186 else if (previous_index == surface->frame_index() - 1) |
162 return source.damage_rect; | 187 return source.damage_rect; |
163 return full_rect; | 188 return full_rect; |
164 } | 189 } |
165 | 190 |
166 void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad, | 191 void SurfaceAggregator::HandleSurfaceQuad( |
167 float opacity, | 192 const SurfaceDrawQuad* surface_quad, |
168 RenderPass* dest_pass) { | 193 const gfx::Transform& content_to_target_transform, |
| 194 const ClipData& clip_rect, |
| 195 RenderPass* dest_pass) { |
169 SurfaceId surface_id = surface_quad->surface_id; | 196 SurfaceId surface_id = surface_quad->surface_id; |
170 // If this surface's id is already in our referenced set then it creates | 197 // If this surface's id is already in our referenced set then it creates |
171 // a cycle in the graph and should be dropped. | 198 // a cycle in the graph and should be dropped. |
172 if (referenced_surfaces_.count(surface_id)) | 199 if (referenced_surfaces_.count(surface_id)) |
173 return; | 200 return; |
174 Surface* surface = manager_->GetSurfaceForId(surface_id); | 201 Surface* surface = manager_->GetSurfaceForId(surface_id); |
175 if (!surface) { | 202 if (!surface) { |
176 contained_surfaces_[surface_id] = 0; | 203 contained_surfaces_[surface_id] = 0; |
177 return; | 204 return; |
178 } | 205 } |
(...skipping 13 matching lines...) Expand all Loading... |
192 if (invalid_frame) { | 219 if (invalid_frame) { |
193 for (auto& request : copy_requests) { | 220 for (auto& request : copy_requests) { |
194 request.second->SendEmptyResult(); | 221 request.second->SendEmptyResult(); |
195 delete request.second; | 222 delete request.second; |
196 } | 223 } |
197 return; | 224 return; |
198 } | 225 } |
199 | 226 |
200 SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; | 227 SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; |
201 | 228 |
202 bool merge_pass = copy_requests.empty(); | 229 bool merge_pass = surface_quad->opacity() == 1.f && copy_requests.empty(); |
203 | 230 |
204 const RenderPassList& referenced_passes = render_pass_list; | 231 const RenderPassList& referenced_passes = render_pass_list; |
205 size_t passes_to_copy = | 232 size_t passes_to_copy = |
206 merge_pass ? referenced_passes.size() - 1 : referenced_passes.size(); | 233 merge_pass ? referenced_passes.size() - 1 : referenced_passes.size(); |
207 for (size_t j = 0; j < passes_to_copy; ++j) { | 234 for (size_t j = 0; j < passes_to_copy; ++j) { |
208 const RenderPass& source = *referenced_passes[j]; | 235 const RenderPass& source = *referenced_passes[j]; |
209 | 236 |
210 size_t sqs_size = source.shared_quad_state_list.size(); | 237 size_t sqs_size = source.shared_quad_state_list.size(); |
211 size_t dq_size = source.quad_list.size(); | 238 size_t dq_size = source.quad_list.size(); |
212 scoped_ptr<RenderPass> copy_pass(RenderPass::Create(sqs_size, dq_size)); | 239 scoped_ptr<RenderPass> copy_pass(RenderPass::Create(sqs_size, dq_size)); |
213 | 240 |
214 RenderPassId remapped_pass_id = RemapPassId(source.id, surface_id); | 241 RenderPassId remapped_pass_id = RemapPassId(source.id, surface_id); |
215 | 242 |
216 copy_pass->SetAll(remapped_pass_id, | 243 copy_pass->SetAll(remapped_pass_id, |
217 source.output_rect, | 244 source.output_rect, |
218 source.damage_rect, | 245 source.damage_rect, |
219 source.transform_to_root_target, | 246 source.transform_to_root_target, |
220 source.has_transparent_background); | 247 source.has_transparent_background); |
221 | 248 |
222 MoveMatchingRequests(source.id, ©_requests, ©_pass->copy_requests); | 249 MoveMatchingRequests(source.id, ©_requests, ©_pass->copy_requests); |
223 | 250 |
224 // Contributing passes aggregated in to the pass list need to take the | 251 // Contributing passes aggregated in to the pass list need to take the |
225 // transform of the surface quad into account to update their transform to | 252 // transform of the surface quad into account to update their transform to |
226 // the root surface. | 253 // the root surface. |
227 // TODO(jamesr): Make sure this is sufficient for surfaces nested several | 254 // TODO(jamesr): Make sure this is sufficient for surfaces nested several |
228 // levels deep and add tests. | 255 // levels deep and add tests. |
229 copy_pass->transform_to_root_target.ConcatTransform( | 256 copy_pass->transform_to_root_target.ConcatTransform( |
230 surface_quad->quadTransform()); | 257 surface_quad->quadTransform()); |
| 258 copy_pass->transform_to_root_target.ConcatTransform( |
| 259 content_to_target_transform); |
231 | 260 |
232 CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, | 261 CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, |
233 gfx::Transform(), 1.f, copy_pass.get(), surface_id); | 262 gfx::Transform(), ClipData(), copy_pass.get(), surface_id); |
234 | 263 |
235 dest_pass_list_->push_back(copy_pass.Pass()); | 264 dest_pass_list_->push_back(copy_pass.Pass()); |
236 } | 265 } |
237 | 266 |
238 const RenderPass& last_pass = *render_pass_list.back(); | 267 const RenderPass& last_pass = *render_pass_list.back(); |
239 if (merge_pass) { | 268 if (merge_pass) { |
240 // TODO(jamesr): Clean up last pass special casing. | 269 // TODO(jamesr): Clean up last pass special casing. |
241 const QuadList& quads = last_pass.quad_list; | 270 const QuadList& quads = last_pass.quad_list; |
242 | 271 |
243 // TODO(jamesr): Make sure clipping is enforced. | 272 gfx::Transform surface_transform = surface_quad->quadTransform(); |
244 CopyQuadsToPass(quads, last_pass.shared_quad_state_list, | 273 surface_transform.ConcatTransform(content_to_target_transform); |
245 surface_quad->quadTransform(), | 274 |
246 surface_quad->opacity() * opacity, dest_pass, surface_id); | 275 // Intersect the transformed visible rect and the clip rect to create a |
| 276 // smaller cliprect for the quad. |
| 277 ClipData surface_quad_clip_rect( |
| 278 true, MathUtil::MapEnclosingClippedRect(surface_quad->quadTransform(), |
| 279 surface_quad->visible_rect)); |
| 280 if (surface_quad->isClipped()) |
| 281 surface_quad_clip_rect.rect.Intersect(surface_quad->clipRect()); |
| 282 |
| 283 ClipData quads_clip = CalculateClipRect(clip_rect, surface_quad_clip_rect, |
| 284 content_to_target_transform); |
| 285 |
| 286 CopyQuadsToPass(quads, last_pass.shared_quad_state_list, surface_transform, |
| 287 quads_clip, dest_pass, surface_id); |
247 } else { | 288 } else { |
248 RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id); | 289 RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id); |
249 | 290 |
| 291 CopySharedQuadState(surface_quad->shared_quad_state, |
| 292 content_to_target_transform, clip_rect, dest_pass); |
| 293 |
250 SharedQuadState* shared_quad_state = | 294 SharedQuadState* shared_quad_state = |
251 dest_pass->CreateAndAppendSharedQuadState(); | 295 dest_pass->shared_quad_state_list.back(); |
252 shared_quad_state->CopyFrom(surface_quad->shared_quad_state); | |
253 shared_quad_state->opacity *= opacity; | |
254 RenderPassDrawQuad* quad = | 296 RenderPassDrawQuad* quad = |
255 dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); | 297 dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); |
256 quad->SetNew(shared_quad_state, | 298 quad->SetNew(shared_quad_state, |
257 surface_quad->rect, | 299 surface_quad->rect, |
258 surface_quad->visible_rect, | 300 surface_quad->visible_rect, |
259 remapped_pass_id, | 301 remapped_pass_id, |
260 0, | 302 0, |
261 gfx::Vector2dF(), | 303 gfx::Vector2dF(), |
262 gfx::Size(), | 304 gfx::Size(), |
263 FilterOperations(), | 305 FilterOperations(), |
264 gfx::Vector2dF(), | 306 gfx::Vector2dF(), |
265 FilterOperations()); | 307 FilterOperations()); |
266 } | 308 } |
267 dest_pass->damage_rect = | 309 dest_pass->damage_rect = |
268 gfx::UnionRects(dest_pass->damage_rect, | 310 gfx::UnionRects(dest_pass->damage_rect, |
269 MathUtil::MapEnclosingClippedRect( | 311 MathUtil::MapEnclosingClippedRect( |
270 surface_quad->quadTransform(), | 312 surface_quad->quadTransform(), |
271 DamageRectForSurface(surface, last_pass, | 313 DamageRectForSurface(surface, last_pass, |
272 surface_quad->visible_rect))); | 314 surface_quad->visible_rect))); |
273 | 315 |
274 referenced_surfaces_.erase(it); | 316 referenced_surfaces_.erase(it); |
275 } | 317 } |
276 | 318 |
277 void SurfaceAggregator::CopySharedQuadState( | 319 void SurfaceAggregator::CopySharedQuadState( |
278 const SharedQuadState* source_sqs, | 320 const SharedQuadState* source_sqs, |
279 const gfx::Transform& content_to_target_transform, | 321 const gfx::Transform& content_to_target_transform, |
| 322 const ClipData& clip_rect, |
280 RenderPass* dest_render_pass) { | 323 RenderPass* dest_render_pass) { |
281 SharedQuadState* copy_shared_quad_state = | 324 SharedQuadState* copy_shared_quad_state = |
282 dest_render_pass->CreateAndAppendSharedQuadState(); | 325 dest_render_pass->CreateAndAppendSharedQuadState(); |
283 copy_shared_quad_state->CopyFrom(source_sqs); | 326 copy_shared_quad_state->CopyFrom(source_sqs); |
284 // content_to_target_transform contains any transformation that may exist | 327 // content_to_target_transform contains any transformation that may exist |
285 // between the context that these quads are being copied from (i.e. the | 328 // 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 | 329 // 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 | 330 // 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 | 331 // root draw pass from a surface into a pass when the surface draw quad's |
289 // transform is not identity. | 332 // transform is not identity. |
290 copy_shared_quad_state->content_to_target_transform.ConcatTransform( | 333 copy_shared_quad_state->content_to_target_transform.ConcatTransform( |
291 content_to_target_transform); | 334 content_to_target_transform); |
292 if (copy_shared_quad_state->is_clipped) { | 335 |
293 copy_shared_quad_state->clip_rect = MathUtil::MapEnclosingClippedRect( | 336 ClipData new_clip_rect = CalculateClipRect( |
294 content_to_target_transform, copy_shared_quad_state->clip_rect); | 337 clip_rect, ClipData(source_sqs->is_clipped, source_sqs->clip_rect), |
295 } | 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; |
296 } | 341 } |
297 | 342 |
298 void SurfaceAggregator::CopyQuadsToPass( | 343 void SurfaceAggregator::CopyQuadsToPass( |
299 const QuadList& source_quad_list, | 344 const QuadList& source_quad_list, |
300 const SharedQuadStateList& source_shared_quad_state_list, | 345 const SharedQuadStateList& source_shared_quad_state_list, |
301 const gfx::Transform& content_to_target_transform, | 346 const gfx::Transform& content_to_target_transform, |
302 float opacity, | 347 const ClipData& clip_rect, |
303 RenderPass* dest_pass, | 348 RenderPass* dest_pass, |
304 SurfaceId surface_id) { | 349 SurfaceId surface_id) { |
305 const SharedQuadState* last_copied_source_shared_quad_state = NULL; | 350 const SharedQuadState* last_copied_source_shared_quad_state = NULL; |
306 | 351 |
307 SharedQuadStateList::ConstIterator sqs_iter = | 352 SharedQuadStateList::ConstIterator sqs_iter = |
308 source_shared_quad_state_list.begin(); | 353 source_shared_quad_state_list.begin(); |
309 for (const auto& quad : source_quad_list) { | 354 for (const auto& quad : source_quad_list) { |
310 while (quad->shared_quad_state != *sqs_iter) { | 355 while (quad->shared_quad_state != *sqs_iter) { |
311 ++sqs_iter; | 356 ++sqs_iter; |
312 DCHECK(sqs_iter != source_shared_quad_state_list.end()); | 357 DCHECK(sqs_iter != source_shared_quad_state_list.end()); |
313 } | 358 } |
314 DCHECK_EQ(quad->shared_quad_state, *sqs_iter); | 359 DCHECK_EQ(quad->shared_quad_state, *sqs_iter); |
315 | 360 |
316 if (quad->material == DrawQuad::SURFACE_CONTENT) { | 361 if (quad->material == DrawQuad::SURFACE_CONTENT) { |
317 const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad); | 362 const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad); |
318 HandleSurfaceQuad(surface_quad, opacity, dest_pass); | 363 HandleSurfaceQuad(surface_quad, content_to_target_transform, clip_rect, |
| 364 dest_pass); |
319 } else { | 365 } else { |
320 if (quad->shared_quad_state != last_copied_source_shared_quad_state) { | 366 if (quad->shared_quad_state != last_copied_source_shared_quad_state) { |
321 CopySharedQuadState( | 367 CopySharedQuadState(quad->shared_quad_state, |
322 quad->shared_quad_state, content_to_target_transform, dest_pass); | 368 content_to_target_transform, clip_rect, dest_pass); |
323 dest_pass->shared_quad_state_list.back()->opacity *= opacity; | |
324 last_copied_source_shared_quad_state = quad->shared_quad_state; | 369 last_copied_source_shared_quad_state = quad->shared_quad_state; |
325 } | 370 } |
326 if (quad->material == DrawQuad::RENDER_PASS) { | 371 if (quad->material == DrawQuad::RENDER_PASS) { |
327 const RenderPassDrawQuad* pass_quad = | 372 const RenderPassDrawQuad* pass_quad = |
328 RenderPassDrawQuad::MaterialCast(quad); | 373 RenderPassDrawQuad::MaterialCast(quad); |
329 RenderPassId original_pass_id = pass_quad->render_pass_id; | 374 RenderPassId original_pass_id = pass_quad->render_pass_id; |
330 RenderPassId remapped_pass_id = | 375 RenderPassId remapped_pass_id = |
331 RemapPassId(original_pass_id, surface_id); | 376 RemapPassId(original_pass_id, surface_id); |
332 | 377 |
333 dest_pass->CopyFromAndAppendRenderPassDrawQuad( | 378 dest_pass->CopyFromAndAppendRenderPassDrawQuad( |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 | 410 |
366 RenderPassId remapped_pass_id = | 411 RenderPassId remapped_pass_id = |
367 RemapPassId(source.id, surface->surface_id()); | 412 RemapPassId(source.id, surface->surface_id()); |
368 | 413 |
369 copy_pass->SetAll(remapped_pass_id, source.output_rect, | 414 copy_pass->SetAll(remapped_pass_id, source.output_rect, |
370 DamageRectForSurface(surface, source, source.output_rect), | 415 DamageRectForSurface(surface, source, source.output_rect), |
371 source.transform_to_root_target, | 416 source.transform_to_root_target, |
372 source.has_transparent_background); | 417 source.has_transparent_background); |
373 | 418 |
374 CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, | 419 CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, |
375 gfx::Transform(), 1.f, copy_pass.get(), | 420 gfx::Transform(), ClipData(), copy_pass.get(), |
376 surface->surface_id()); | 421 surface->surface_id()); |
377 | 422 |
378 dest_pass_list_->push_back(copy_pass.Pass()); | 423 dest_pass_list_->push_back(copy_pass.Pass()); |
379 } | 424 } |
380 } | 425 } |
381 | 426 |
382 void SurfaceAggregator::RemoveUnreferencedChildren() { | 427 void SurfaceAggregator::RemoveUnreferencedChildren() { |
383 for (const auto& surface : previous_contained_surfaces_) { | 428 for (const auto& surface : previous_contained_surfaces_) { |
384 if (!contained_surfaces_.count(surface.first)) { | 429 if (!contained_surfaces_.count(surface.first)) { |
385 SurfaceToResourceChildIdMap::iterator it = | 430 SurfaceToResourceChildIdMap::iterator it = |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 void SurfaceAggregator::ReleaseResources(SurfaceId surface_id) { | 486 void SurfaceAggregator::ReleaseResources(SurfaceId surface_id) { |
442 SurfaceToResourceChildIdMap::iterator it = | 487 SurfaceToResourceChildIdMap::iterator it = |
443 surface_id_to_resource_child_id_.find(surface_id); | 488 surface_id_to_resource_child_id_.find(surface_id); |
444 if (it != surface_id_to_resource_child_id_.end()) { | 489 if (it != surface_id_to_resource_child_id_.end()) { |
445 provider_->DestroyChild(it->second); | 490 provider_->DestroyChild(it->second); |
446 surface_id_to_resource_child_id_.erase(it); | 491 surface_id_to_resource_child_id_.erase(it); |
447 } | 492 } |
448 } | 493 } |
449 | 494 |
450 } // namespace cc | 495 } // namespace cc |
OLD | NEW |