| 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 |