| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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/output/direct_renderer.h" | 5 #include "cc/output/direct_renderer.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 return render_pass_scissor; | 271 return render_pass_scissor; |
| 272 } | 272 } |
| 273 | 273 |
| 274 bool DirectRenderer::NeedDeviceClip(const DrawingFrame* frame) const { | 274 bool DirectRenderer::NeedDeviceClip(const DrawingFrame* frame) const { |
| 275 if (frame->current_render_pass != frame->root_render_pass) | 275 if (frame->current_render_pass != frame->root_render_pass) |
| 276 return false; | 276 return false; |
| 277 | 277 |
| 278 return !frame->device_clip_rect.Contains(frame->device_viewport_rect); | 278 return !frame->device_clip_rect.Contains(frame->device_viewport_rect); |
| 279 } | 279 } |
| 280 | 280 |
| 281 gfx::Rect DirectRenderer::DeviceClipRectInWindowSpace(const DrawingFrame* frame) | 281 gfx::Rect DirectRenderer::DeviceClipRectInDrawSpace( |
| 282 const { | 282 const DrawingFrame* frame) const { |
| 283 gfx::Rect device_clip_rect = frame->device_clip_rect; | 283 gfx::Rect device_clip_rect = frame->device_clip_rect; |
| 284 if (FlippedFramebuffer(frame)) | 284 device_clip_rect -= current_viewport_rect_.OffsetFromOrigin(); |
| 285 device_clip_rect.set_y(current_surface_size_.height() - | 285 device_clip_rect += current_draw_rect_.OffsetFromOrigin(); |
| 286 device_clip_rect.bottom()); | |
| 287 return device_clip_rect; | 286 return device_clip_rect; |
| 288 } | 287 } |
| 289 | 288 |
| 290 void DirectRenderer::SetScissorStateForQuad(const DrawingFrame* frame, | 289 gfx::Rect DirectRenderer::DeviceViewportRectInDrawSpace( |
| 291 const DrawQuad& quad) { | 290 const DrawingFrame* frame) const { |
| 292 if (quad.isClipped()) { | 291 gfx::Rect device_viewport_rect = frame->device_viewport_rect; |
| 293 SetScissorTestRectInDrawSpace(frame, quad.clipRect()); | 292 device_viewport_rect -= current_viewport_rect_.OffsetFromOrigin(); |
| 294 return; | 293 device_viewport_rect += current_draw_rect_.OffsetFromOrigin(); |
| 294 return device_viewport_rect; |
| 295 } |
| 296 |
| 297 gfx::Rect DirectRenderer::OutputSurfaceRectInDrawSpace( |
| 298 const DrawingFrame* frame) const { |
| 299 if (frame->current_render_pass == frame->root_render_pass) { |
| 300 gfx::Rect output_surface_rect(output_surface_->SurfaceSize()); |
| 301 output_surface_rect -= current_viewport_rect_.OffsetFromOrigin(); |
| 302 output_surface_rect += current_draw_rect_.OffsetFromOrigin(); |
| 303 return output_surface_rect; |
| 304 } else { |
| 305 return frame->current_render_pass->output_rect; |
| 295 } | 306 } |
| 296 if (NeedDeviceClip(frame)) { | |
| 297 SetScissorTestRect(DeviceClipRectInWindowSpace(frame)); | |
| 298 return; | |
| 299 } | |
| 300 | |
| 301 EnsureScissorTestDisabled(); | |
| 302 } | 307 } |
| 303 | 308 |
| 304 bool DirectRenderer::ShouldSkipQuad(const DrawQuad& quad, | 309 bool DirectRenderer::ShouldSkipQuad(const DrawQuad& quad, |
| 305 const gfx::Rect& render_pass_scissor) { | 310 const gfx::Rect& render_pass_scissor) { |
| 306 if (render_pass_scissor.IsEmpty()) | 311 if (render_pass_scissor.IsEmpty()) |
| 307 return true; | 312 return true; |
| 308 | 313 |
| 309 if (quad.isClipped()) { | 314 if (quad.isClipped()) { |
| 310 gfx::Rect r = quad.clipRect(); | 315 gfx::Rect r = quad.clipRect(); |
| 311 r.Intersect(render_pass_scissor); | 316 r.Intersect(render_pass_scissor); |
| 312 return r.IsEmpty(); | 317 return r.IsEmpty(); |
| 313 } | 318 } |
| 314 | 319 |
| 315 return false; | 320 return false; |
| 316 } | 321 } |
| 317 | 322 |
| 318 void DirectRenderer::SetScissorStateForQuadWithRenderPassScissor( | 323 void DirectRenderer::SetScissorStateForQuad( |
| 319 const DrawingFrame* frame, | 324 const DrawingFrame* frame, |
| 320 const DrawQuad& quad, | 325 const DrawQuad& quad, |
| 321 const gfx::Rect& render_pass_scissor) { | 326 const gfx::Rect& render_pass_scissor, |
| 322 gfx::Rect quad_scissor_rect = render_pass_scissor; | 327 bool use_render_pass_scissor) { |
| 323 if (quad.isClipped()) | 328 if (use_render_pass_scissor) { |
| 324 quad_scissor_rect.Intersect(quad.clipRect()); | 329 gfx::Rect quad_scissor_rect = render_pass_scissor; |
| 325 SetScissorTestRectInDrawSpace(frame, quad_scissor_rect); | 330 if (quad.isClipped()) |
| 331 quad_scissor_rect.Intersect(quad.clipRect()); |
| 332 SetScissorTestRectInDrawSpace(frame, quad_scissor_rect); |
| 333 return; |
| 334 } else if (quad.isClipped()) { |
| 335 SetScissorTestRectInDrawSpace(frame, quad.clipRect()); |
| 336 return; |
| 337 } |
| 338 |
| 339 EnsureScissorTestDisabled(); |
| 326 } | 340 } |
| 327 | 341 |
| 328 void DirectRenderer::SetScissorTestRectInDrawSpace( | 342 void DirectRenderer::SetScissorTestRectInDrawSpace( |
| 329 const DrawingFrame* frame, | 343 const DrawingFrame* frame, |
| 330 const gfx::Rect& draw_space_rect) { | 344 const gfx::Rect& draw_space_rect) { |
| 331 gfx::Rect window_space_rect = | 345 gfx::Rect window_space_rect = |
| 332 MoveFromDrawToWindowSpace(frame, draw_space_rect); | 346 MoveFromDrawToWindowSpace(frame, draw_space_rect); |
| 333 if (NeedDeviceClip(frame)) | |
| 334 window_space_rect.Intersect(DeviceClipRectInWindowSpace(frame)); | |
| 335 SetScissorTestRect(window_space_rect); | 347 SetScissorTestRect(window_space_rect); |
| 336 } | 348 } |
| 337 | 349 |
| 338 void DirectRenderer::FinishDrawingQuadList() {} | 350 void DirectRenderer::FinishDrawingQuadList() {} |
| 339 | 351 |
| 340 void DirectRenderer::DoDrawPolygon(const DrawPolygon& poly, | 352 void DirectRenderer::DoDrawPolygon(const DrawPolygon& poly, |
| 341 DrawingFrame* frame, | 353 DrawingFrame* frame, |
| 342 const gfx::Rect& render_pass_scissor, | 354 const gfx::Rect& render_pass_scissor, |
| 343 bool using_scissor_as_optimization) { | 355 bool use_render_pass_scissor) { |
| 344 if (using_scissor_as_optimization) { | 356 SetScissorStateForQuad(frame, *poly.original_ref(), render_pass_scissor, |
| 345 SetScissorStateForQuadWithRenderPassScissor(frame, *poly.original_ref(), | 357 use_render_pass_scissor); |
| 346 render_pass_scissor); | |
| 347 } else { | |
| 348 SetScissorStateForQuad(frame, *poly.original_ref()); | |
| 349 } | |
| 350 | 358 |
| 351 // If the poly has not been split, then it is just a normal DrawQuad, | 359 // If the poly has not been split, then it is just a normal DrawQuad, |
| 352 // and we should save any extra processing that would have to be done. | 360 // and we should save any extra processing that would have to be done. |
| 353 if (!poly.is_split()) { | 361 if (!poly.is_split()) { |
| 354 DoDrawQuad(frame, poly.original_ref(), NULL); | 362 DoDrawQuad(frame, poly.original_ref(), NULL); |
| 355 return; | 363 return; |
| 356 } | 364 } |
| 357 | 365 |
| 358 std::vector<gfx::QuadF> quads; | 366 std::vector<gfx::QuadF> quads; |
| 359 poly.ToQuads2D(&quads); | 367 poly.ToQuads2D(&quads); |
| 360 for (size_t i = 0; i < quads.size(); ++i) { | 368 for (size_t i = 0; i < quads.size(); ++i) { |
| 361 DoDrawQuad(frame, poly.original_ref(), &quads[i]); | 369 DoDrawQuad(frame, poly.original_ref(), &quads[i]); |
| 362 } | 370 } |
| 363 } | 371 } |
| 364 | 372 |
| 365 void DirectRenderer::FlushPolygons(ScopedPtrDeque<DrawPolygon>* poly_list, | 373 void DirectRenderer::FlushPolygons(ScopedPtrDeque<DrawPolygon>* poly_list, |
| 366 DrawingFrame* frame, | 374 DrawingFrame* frame, |
| 367 const gfx::Rect& render_pass_scissor, | 375 const gfx::Rect& render_pass_scissor, |
| 368 bool using_scissor_as_optimization) { | 376 bool use_render_pass_scissor) { |
| 369 if (poly_list->empty()) { | 377 if (poly_list->empty()) { |
| 370 return; | 378 return; |
| 371 } | 379 } |
| 372 | 380 |
| 373 BspTree bsp_tree(poly_list); | 381 BspTree bsp_tree(poly_list); |
| 374 BspWalkActionDrawPolygon action_handler(this, frame, render_pass_scissor, | 382 BspWalkActionDrawPolygon action_handler(this, frame, render_pass_scissor, |
| 375 using_scissor_as_optimization); | 383 use_render_pass_scissor); |
| 376 bsp_tree.TraverseWithActionHandler(&action_handler); | 384 bsp_tree.TraverseWithActionHandler(&action_handler); |
| 377 DCHECK(poly_list->empty()); | 385 DCHECK(poly_list->empty()); |
| 378 } | 386 } |
| 379 | 387 |
| 380 void DirectRenderer::DrawRenderPass(DrawingFrame* frame, | 388 void DirectRenderer::DrawRenderPass(DrawingFrame* frame, |
| 381 const RenderPass* render_pass) { | 389 const RenderPass* render_pass) { |
| 382 TRACE_EVENT0("cc", "DirectRenderer::DrawRenderPass"); | 390 TRACE_EVENT0("cc", "DirectRenderer::DrawRenderPass"); |
| 383 if (!UseRenderPass(frame, render_pass)) | 391 if (!UseRenderPass(frame, render_pass)) |
| 384 return; | 392 return; |
| 385 | 393 |
| 386 bool using_scissor_as_optimization = Capabilities().using_partial_swap; | 394 const gfx::Rect surface_rect_in_draw_space = |
| 387 gfx::Rect render_pass_scissor; | 395 OutputSurfaceRectInDrawSpace(frame); |
| 388 bool draw_rect_covers_full_surface = true; | 396 gfx::Rect render_pass_scissor_in_draw_space = surface_rect_in_draw_space; |
| 389 if (frame->current_render_pass == frame->root_render_pass && | |
| 390 !frame->device_viewport_rect.Contains( | |
| 391 gfx::Rect(output_surface_->SurfaceSize()))) | |
| 392 draw_rect_covers_full_surface = false; | |
| 393 | 397 |
| 394 if (using_scissor_as_optimization) { | 398 if (frame->current_render_pass == frame->root_render_pass) { |
| 395 render_pass_scissor = ComputeScissorRectForRenderPass(frame); | 399 render_pass_scissor_in_draw_space.Intersect( |
| 396 SetScissorTestRectInDrawSpace(frame, render_pass_scissor); | 400 DeviceViewportRectInDrawSpace(frame)); |
| 397 if (!render_pass_scissor.Contains(frame->current_render_pass->output_rect)) | |
| 398 draw_rect_covers_full_surface = false; | |
| 399 } | 401 } |
| 400 | 402 |
| 401 if (frame->current_render_pass != frame->root_render_pass || | 403 if (Capabilities().using_partial_swap) { |
| 402 settings_->should_clear_root_render_pass) { | 404 render_pass_scissor_in_draw_space.Intersect( |
| 403 if (NeedDeviceClip(frame)) { | 405 ComputeScissorRectForRenderPass(frame)); |
| 404 SetScissorTestRect(DeviceClipRectInWindowSpace(frame)); | 406 } |
| 405 draw_rect_covers_full_surface = false; | |
| 406 } else if (!using_scissor_as_optimization) { | |
| 407 EnsureScissorTestDisabled(); | |
| 408 } | |
| 409 | 407 |
| 410 bool has_external_stencil_test = | 408 if (NeedDeviceClip(frame)) { |
| 411 output_surface_->HasExternalStencilTest() && | 409 render_pass_scissor_in_draw_space.Intersect( |
| 412 frame->current_render_pass == frame->root_render_pass; | 410 DeviceClipRectInDrawSpace(frame)); |
| 411 } |
| 413 | 412 |
| 414 DiscardPixels(has_external_stencil_test, draw_rect_covers_full_surface); | 413 bool render_pass_is_clipped = |
| 415 ClearFramebuffer(frame, has_external_stencil_test); | 414 !render_pass_scissor_in_draw_space.Contains(surface_rect_in_draw_space); |
| 415 bool is_root_render_pass = |
| 416 frame->current_render_pass == frame->root_render_pass; |
| 417 bool has_external_stencil_test = |
| 418 is_root_render_pass && output_surface_->HasExternalStencilTest(); |
| 419 bool should_clear_surface = |
| 420 !has_external_stencil_test && |
| 421 (!is_root_render_pass || settings_->should_clear_root_render_pass); |
| 422 |
| 423 // If |has_external_stencil_test| we can't discard or clear. Make sure we |
| 424 // don't need to. |
| 425 DCHECK_IMPLIES(has_external_stencil_test, |
| 426 !frame->current_render_pass->has_transparent_background); |
| 427 |
| 428 SurfaceInitializationMode mode; |
| 429 if (should_clear_surface && render_pass_is_clipped) { |
| 430 mode = SURFACE_INITIALIZATION_MODE_SCISSORED_CLEAR; |
| 431 } else if (should_clear_surface) { |
| 432 mode = SURFACE_INITIALIZATION_MODE_FULL_SURFACE_CLEAR; |
| 433 } else { |
| 434 mode = SURFACE_INITIALIZATION_MODE_PRESERVE; |
| 416 } | 435 } |
| 417 | 436 |
| 437 PrepareSurfaceForPass( |
| 438 frame, mode, |
| 439 MoveFromDrawToWindowSpace(frame, render_pass_scissor_in_draw_space)); |
| 440 |
| 418 const QuadList& quad_list = render_pass->quad_list; | 441 const QuadList& quad_list = render_pass->quad_list; |
| 419 ScopedPtrDeque<DrawPolygon> poly_list; | 442 ScopedPtrDeque<DrawPolygon> poly_list; |
| 420 | 443 |
| 421 int next_polygon_id = 0; | 444 int next_polygon_id = 0; |
| 422 int last_sorting_context_id = 0; | 445 int last_sorting_context_id = 0; |
| 423 for (auto it = quad_list.BackToFrontBegin(); it != quad_list.BackToFrontEnd(); | 446 for (auto it = quad_list.BackToFrontBegin(); it != quad_list.BackToFrontEnd(); |
| 424 ++it) { | 447 ++it) { |
| 425 const DrawQuad& quad = **it; | 448 const DrawQuad& quad = **it; |
| 426 gfx::QuadF send_quad(quad.visible_rect); | 449 gfx::QuadF send_quad(quad.visible_rect); |
| 427 | 450 |
| 428 if (using_scissor_as_optimization && | 451 if (render_pass_is_clipped && |
| 429 ShouldSkipQuad(quad, render_pass_scissor)) { | 452 ShouldSkipQuad(quad, render_pass_scissor_in_draw_space)) { |
| 430 continue; | 453 continue; |
| 431 } | 454 } |
| 432 | 455 |
| 433 if (last_sorting_context_id != quad.shared_quad_state->sorting_context_id) { | 456 if (last_sorting_context_id != quad.shared_quad_state->sorting_context_id) { |
| 434 last_sorting_context_id = quad.shared_quad_state->sorting_context_id; | 457 last_sorting_context_id = quad.shared_quad_state->sorting_context_id; |
| 435 FlushPolygons(&poly_list, frame, render_pass_scissor, | 458 FlushPolygons(&poly_list, frame, render_pass_scissor_in_draw_space, |
| 436 using_scissor_as_optimization); | 459 render_pass_is_clipped); |
| 437 } | 460 } |
| 438 | 461 |
| 439 // This layer is in a 3D sorting context so we add it to the list of | 462 // This layer is in a 3D sorting context so we add it to the list of |
| 440 // polygons to go into the BSP tree. | 463 // polygons to go into the BSP tree. |
| 441 if (quad.shared_quad_state->sorting_context_id != 0) { | 464 if (quad.shared_quad_state->sorting_context_id != 0) { |
| 442 scoped_ptr<DrawPolygon> new_polygon(new DrawPolygon( | 465 scoped_ptr<DrawPolygon> new_polygon(new DrawPolygon( |
| 443 *it, quad.visible_rect, quad.quadTransform(), next_polygon_id++)); | 466 *it, quad.visible_rect, quad.quadTransform(), next_polygon_id++)); |
| 444 if (new_polygon->points().size() > 2u) { | 467 if (new_polygon->points().size() > 2u) { |
| 445 poly_list.push_back(new_polygon.Pass()); | 468 poly_list.push_back(new_polygon.Pass()); |
| 446 } | 469 } |
| 447 continue; | 470 continue; |
| 448 } | 471 } |
| 449 | 472 |
| 450 // We are not in a 3d sorting context, so we should draw the quad normally. | 473 // We are not in a 3d sorting context, so we should draw the quad normally. |
| 451 if (using_scissor_as_optimization) { | 474 SetScissorStateForQuad(frame, quad, render_pass_scissor_in_draw_space, |
| 452 SetScissorStateForQuadWithRenderPassScissor(frame, quad, | 475 render_pass_is_clipped); |
| 453 render_pass_scissor); | |
| 454 } else { | |
| 455 SetScissorStateForQuad(frame, quad); | |
| 456 } | |
| 457 | 476 |
| 458 DoDrawQuad(frame, &quad, nullptr); | 477 DoDrawQuad(frame, &quad, nullptr); |
| 459 } | 478 } |
| 460 FlushPolygons(&poly_list, frame, render_pass_scissor, | 479 FlushPolygons(&poly_list, frame, render_pass_scissor_in_draw_space, |
| 461 using_scissor_as_optimization); | 480 render_pass_is_clipped); |
| 462 FinishDrawingQuadList(); | 481 FinishDrawingQuadList(); |
| 463 } | 482 } |
| 464 | 483 |
| 465 bool DirectRenderer::UseRenderPass(DrawingFrame* frame, | 484 bool DirectRenderer::UseRenderPass(DrawingFrame* frame, |
| 466 const RenderPass* render_pass) { | 485 const RenderPass* render_pass) { |
| 467 frame->current_render_pass = render_pass; | 486 frame->current_render_pass = render_pass; |
| 468 frame->current_texture = NULL; | 487 frame->current_texture = NULL; |
| 469 | 488 |
| 470 if (render_pass == frame->root_render_pass) { | 489 if (render_pass == frame->root_render_pass) { |
| 471 BindFramebufferToOutputSurface(frame); | 490 BindFramebufferToOutputSurface(frame); |
| 472 InitializeViewport(frame, | 491 InitializeViewport(frame, |
| 473 render_pass->output_rect, | 492 render_pass->output_rect, |
| 474 frame->device_viewport_rect, | 493 frame->device_viewport_rect, |
| 475 output_surface_->SurfaceSize()); | 494 output_surface_->SurfaceSize()); |
| 476 return true; | 495 return true; |
| 477 } | 496 } |
| 478 | 497 |
| 479 ScopedResource* texture = render_pass_textures_.get(render_pass->id); | 498 ScopedResource* texture = render_pass_textures_.get(render_pass->id); |
| 480 DCHECK(texture); | 499 DCHECK(texture); |
| 481 | 500 |
| 482 gfx::Size size = RenderPassTextureSize(render_pass); | 501 gfx::Size size = RenderPassTextureSize(render_pass); |
| 483 size.Enlarge(enlarge_pass_texture_amount_.x(), | 502 size.Enlarge(enlarge_pass_texture_amount_.x(), |
| 484 enlarge_pass_texture_amount_.y()); | 503 enlarge_pass_texture_amount_.y()); |
| 485 if (!texture->id()) | 504 if (!texture->id()) |
| 486 texture->Allocate( | 505 texture->Allocate( |
| 487 size, ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER, RGBA_8888); | 506 size, ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER, RGBA_8888); |
| 488 DCHECK(texture->id()); | 507 DCHECK(texture->id()); |
| 489 | 508 |
| 490 return BindFramebufferToTexture(frame, texture, render_pass->output_rect); | 509 if (BindFramebufferToTexture(frame, texture, render_pass->output_rect)) { |
| 510 InitializeViewport(frame, render_pass->output_rect, |
| 511 gfx::Rect(render_pass->output_rect.size()), |
| 512 render_pass->output_rect.size()); |
| 513 return true; |
| 514 } |
| 515 |
| 516 return false; |
| 491 } | 517 } |
| 492 | 518 |
| 493 bool DirectRenderer::HasAllocatedResourcesForTesting(RenderPassId id) const { | 519 bool DirectRenderer::HasAllocatedResourcesForTesting(RenderPassId id) const { |
| 494 ScopedResource* texture = render_pass_textures_.get(id); | 520 ScopedResource* texture = render_pass_textures_.get(id); |
| 495 return texture && texture->id(); | 521 return texture && texture->id(); |
| 496 } | 522 } |
| 497 | 523 |
| 498 // static | 524 // static |
| 499 gfx::Size DirectRenderer::RenderPassTextureSize(const RenderPass* render_pass) { | 525 gfx::Size DirectRenderer::RenderPassTextureSize(const RenderPass* render_pass) { |
| 500 return render_pass->output_rect.size(); | 526 return render_pass->output_rect.size(); |
| 501 } | 527 } |
| 502 | 528 |
| 503 } // namespace cc | 529 } // namespace cc |
| OLD | NEW |