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" |
11 #include "base/containers/scoped_ptr_hash_map.h" | 11 #include "base/containers/scoped_ptr_hash_map.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/trace_event/trace_event.h" | 13 #include "base/trace_event/trace_event.h" |
14 #include "cc/base/math_util.h" | 14 #include "cc/base/math_util.h" |
15 #include "cc/output/bsp_tree.h" | |
16 #include "cc/output/bsp_walk_action.h" | |
17 #include "cc/output/copy_output_request.h" | 15 #include "cc/output/copy_output_request.h" |
18 #include "cc/quads/draw_quad.h" | 16 #include "cc/quads/draw_quad.h" |
19 #include "ui/gfx/geometry/rect_conversions.h" | 17 #include "ui/gfx/geometry/rect_conversions.h" |
20 #include "ui/gfx/transform.h" | 18 #include "ui/gfx/transform.h" |
21 | 19 |
22 static gfx::Transform OrthoProjectionMatrix(float left, | 20 static gfx::Transform OrthoProjectionMatrix(float left, |
23 float right, | 21 float right, |
24 float bottom, | 22 float bottom, |
25 float top) { | 23 float top) { |
26 // Use the standard formula to map the clipping frustum to the cube from | 24 // Use the standard formula to map the clipping frustum to the cube from |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 return; | 292 return; |
295 } | 293 } |
296 if (NeedDeviceClip(frame)) { | 294 if (NeedDeviceClip(frame)) { |
297 SetScissorTestRect(DeviceClipRectInWindowSpace(frame)); | 295 SetScissorTestRect(DeviceClipRectInWindowSpace(frame)); |
298 return; | 296 return; |
299 } | 297 } |
300 | 298 |
301 EnsureScissorTestDisabled(); | 299 EnsureScissorTestDisabled(); |
302 } | 300 } |
303 | 301 |
304 bool DirectRenderer::ShouldSkipQuad(const DrawQuad& quad, | |
305 const gfx::Rect& render_pass_scissor) { | |
306 if (render_pass_scissor.IsEmpty()) | |
307 return true; | |
308 | |
309 if (quad.isClipped()) { | |
310 gfx::Rect r = quad.clipRect(); | |
311 r.Intersect(render_pass_scissor); | |
312 return r.IsEmpty(); | |
313 } | |
314 | |
315 return false; | |
316 } | |
317 | |
318 void DirectRenderer::SetScissorStateForQuadWithRenderPassScissor( | 302 void DirectRenderer::SetScissorStateForQuadWithRenderPassScissor( |
319 const DrawingFrame* frame, | 303 const DrawingFrame* frame, |
320 const DrawQuad& quad, | 304 const DrawQuad& quad, |
321 const gfx::Rect& render_pass_scissor) { | 305 const gfx::Rect& render_pass_scissor, |
| 306 bool* should_skip_quad) { |
322 gfx::Rect quad_scissor_rect = render_pass_scissor; | 307 gfx::Rect quad_scissor_rect = render_pass_scissor; |
| 308 |
323 if (quad.isClipped()) | 309 if (quad.isClipped()) |
324 quad_scissor_rect.Intersect(quad.clipRect()); | 310 quad_scissor_rect.Intersect(quad.clipRect()); |
| 311 |
| 312 if (quad_scissor_rect.IsEmpty()) { |
| 313 *should_skip_quad = true; |
| 314 return; |
| 315 } |
| 316 |
| 317 *should_skip_quad = false; |
325 SetScissorTestRectInDrawSpace(frame, quad_scissor_rect); | 318 SetScissorTestRectInDrawSpace(frame, quad_scissor_rect); |
326 } | 319 } |
327 | 320 |
328 void DirectRenderer::SetScissorTestRectInDrawSpace( | 321 void DirectRenderer::SetScissorTestRectInDrawSpace( |
329 const DrawingFrame* frame, | 322 const DrawingFrame* frame, |
330 const gfx::Rect& draw_space_rect) { | 323 const gfx::Rect& draw_space_rect) { |
331 gfx::Rect window_space_rect = | 324 gfx::Rect window_space_rect = |
332 MoveFromDrawToWindowSpace(frame, draw_space_rect); | 325 MoveFromDrawToWindowSpace(frame, draw_space_rect); |
333 if (NeedDeviceClip(frame)) | 326 if (NeedDeviceClip(frame)) |
334 window_space_rect.Intersect(DeviceClipRectInWindowSpace(frame)); | 327 window_space_rect.Intersect(DeviceClipRectInWindowSpace(frame)); |
335 SetScissorTestRect(window_space_rect); | 328 SetScissorTestRect(window_space_rect); |
336 } | 329 } |
337 | 330 |
338 void DirectRenderer::FinishDrawingQuadList() {} | 331 void DirectRenderer::FinishDrawingQuadList() {} |
339 | 332 |
340 void DirectRenderer::DoDrawPolygon(const DrawPolygon& poly, | |
341 DrawingFrame* frame, | |
342 const gfx::Rect& render_pass_scissor, | |
343 bool using_scissor_as_optimization) { | |
344 if (using_scissor_as_optimization) { | |
345 SetScissorStateForQuadWithRenderPassScissor(frame, *poly.original_ref(), | |
346 render_pass_scissor); | |
347 } else { | |
348 SetScissorStateForQuad(frame, *poly.original_ref()); | |
349 } | |
350 | |
351 // 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. | |
353 if (!poly.is_split()) { | |
354 DoDrawQuad(frame, poly.original_ref(), NULL); | |
355 return; | |
356 } | |
357 | |
358 std::vector<gfx::QuadF> quads; | |
359 poly.ToQuads2D(&quads); | |
360 for (size_t i = 0; i < quads.size(); ++i) { | |
361 DoDrawQuad(frame, poly.original_ref(), &quads[i]); | |
362 } | |
363 } | |
364 | |
365 void DirectRenderer::FlushPolygons(ScopedPtrDeque<DrawPolygon>* poly_list, | |
366 DrawingFrame* frame, | |
367 const gfx::Rect& render_pass_scissor, | |
368 bool using_scissor_as_optimization) { | |
369 if (poly_list->empty()) { | |
370 return; | |
371 } | |
372 | |
373 BspTree bsp_tree(poly_list); | |
374 BspWalkActionDrawPolygon action_handler(this, frame, render_pass_scissor, | |
375 using_scissor_as_optimization); | |
376 bsp_tree.TraverseWithActionHandler(&action_handler); | |
377 DCHECK(poly_list->empty()); | |
378 } | |
379 | |
380 void DirectRenderer::DrawRenderPass(DrawingFrame* frame, | 333 void DirectRenderer::DrawRenderPass(DrawingFrame* frame, |
381 const RenderPass* render_pass) { | 334 const RenderPass* render_pass) { |
382 TRACE_EVENT0("cc", "DirectRenderer::DrawRenderPass"); | 335 TRACE_EVENT0("cc", "DirectRenderer::DrawRenderPass"); |
383 if (!UseRenderPass(frame, render_pass)) | 336 if (!UseRenderPass(frame, render_pass)) |
384 return; | 337 return; |
385 | 338 |
386 bool using_scissor_as_optimization = Capabilities().using_partial_swap; | 339 bool using_scissor_as_optimization = Capabilities().using_partial_swap; |
387 gfx::Rect render_pass_scissor; | 340 gfx::Rect render_pass_scissor; |
388 bool draw_rect_covers_full_surface = true; | 341 bool draw_rect_covers_full_surface = true; |
389 if (frame->current_render_pass == frame->root_render_pass && | 342 if (frame->current_render_pass == frame->root_render_pass && |
(...skipping 19 matching lines...) Expand all Loading... |
409 | 362 |
410 bool has_external_stencil_test = | 363 bool has_external_stencil_test = |
411 output_surface_->HasExternalStencilTest() && | 364 output_surface_->HasExternalStencilTest() && |
412 frame->current_render_pass == frame->root_render_pass; | 365 frame->current_render_pass == frame->root_render_pass; |
413 | 366 |
414 DiscardPixels(has_external_stencil_test, draw_rect_covers_full_surface); | 367 DiscardPixels(has_external_stencil_test, draw_rect_covers_full_surface); |
415 ClearFramebuffer(frame, has_external_stencil_test); | 368 ClearFramebuffer(frame, has_external_stencil_test); |
416 } | 369 } |
417 | 370 |
418 const QuadList& quad_list = render_pass->quad_list; | 371 const QuadList& quad_list = render_pass->quad_list; |
419 ScopedPtrDeque<DrawPolygon> poly_list; | |
420 | |
421 int next_polygon_id = 0; | |
422 int last_sorting_context_id = 0; | |
423 for (auto it = quad_list.BackToFrontBegin(); it != quad_list.BackToFrontEnd(); | 372 for (auto it = quad_list.BackToFrontBegin(); it != quad_list.BackToFrontEnd(); |
424 ++it) { | 373 ++it) { |
425 const DrawQuad& quad = **it; | 374 const DrawQuad& quad = **it; |
426 gfx::QuadF send_quad(quad.visible_rect); | 375 bool should_skip_quad = false; |
427 | 376 |
428 if (using_scissor_as_optimization && | |
429 ShouldSkipQuad(quad, render_pass_scissor)) { | |
430 continue; | |
431 } | |
432 | |
433 if (last_sorting_context_id != quad.shared_quad_state->sorting_context_id) { | |
434 last_sorting_context_id = quad.shared_quad_state->sorting_context_id; | |
435 FlushPolygons(&poly_list, frame, render_pass_scissor, | |
436 using_scissor_as_optimization); | |
437 } | |
438 | |
439 // This layer is in a 3D sorting context so we add it to the list of | |
440 // polygons to go into the BSP tree. | |
441 if (quad.shared_quad_state->sorting_context_id != 0) { | |
442 scoped_ptr<DrawPolygon> new_polygon(new DrawPolygon( | |
443 *it, quad.visible_rect, quad.quadTransform(), next_polygon_id++)); | |
444 if (new_polygon->points().size() > 2u) { | |
445 poly_list.push_back(new_polygon.Pass()); | |
446 } | |
447 continue; | |
448 } | |
449 | |
450 // We are not in a 3d sorting context, so we should draw the quad normally. | |
451 if (using_scissor_as_optimization) { | 377 if (using_scissor_as_optimization) { |
452 SetScissorStateForQuadWithRenderPassScissor(frame, quad, | 378 SetScissorStateForQuadWithRenderPassScissor( |
453 render_pass_scissor); | 379 frame, quad, render_pass_scissor, &should_skip_quad); |
454 } else { | 380 } else { |
455 SetScissorStateForQuad(frame, quad); | 381 SetScissorStateForQuad(frame, quad); |
456 } | 382 } |
457 | 383 |
458 DoDrawQuad(frame, &quad, nullptr); | 384 if (!should_skip_quad) |
| 385 DoDrawQuad(frame, &quad); |
459 } | 386 } |
460 FlushPolygons(&poly_list, frame, render_pass_scissor, | |
461 using_scissor_as_optimization); | |
462 FinishDrawingQuadList(); | 387 FinishDrawingQuadList(); |
463 } | 388 } |
464 | 389 |
465 bool DirectRenderer::UseRenderPass(DrawingFrame* frame, | 390 bool DirectRenderer::UseRenderPass(DrawingFrame* frame, |
466 const RenderPass* render_pass) { | 391 const RenderPass* render_pass) { |
467 frame->current_render_pass = render_pass; | 392 frame->current_render_pass = render_pass; |
468 frame->current_texture = NULL; | 393 frame->current_texture = NULL; |
469 | 394 |
470 if (render_pass == frame->root_render_pass) { | 395 if (render_pass == frame->root_render_pass) { |
471 BindFramebufferToOutputSurface(frame); | 396 BindFramebufferToOutputSurface(frame); |
(...skipping 22 matching lines...) Expand all Loading... |
494 ScopedResource* texture = render_pass_textures_.get(id); | 419 ScopedResource* texture = render_pass_textures_.get(id); |
495 return texture && texture->id(); | 420 return texture && texture->id(); |
496 } | 421 } |
497 | 422 |
498 // static | 423 // static |
499 gfx::Size DirectRenderer::RenderPassTextureSize(const RenderPass* render_pass) { | 424 gfx::Size DirectRenderer::RenderPassTextureSize(const RenderPass* render_pass) { |
500 return render_pass->output_rect.size(); | 425 return render_pass->output_rect.size(); |
501 } | 426 } |
502 | 427 |
503 } // namespace cc | 428 } // namespace cc |
OLD | NEW |