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

Side by Side Diff: cc/output/gl_renderer.cc

Issue 2612023002: cc: Implement overdraw feedback debugging feature. (Closed)
Patch Set: rebase Created 3 years, 11 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/output/gl_renderer.h ('k') | cc/output/gl_renderer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 The Chromium Authors. All rights reserved. 1 // Copyright 2010 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/gl_renderer.h" 5 #include "cc/output/gl_renderer.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 #include <limits> 11 #include <limits>
12 #include <memory> 12 #include <memory>
13 #include <set> 13 #include <set>
14 #include <string> 14 #include <string>
15 #include <vector> 15 #include <vector>
16 16
17 #include "base/barrier_closure.h"
17 #include "base/feature_list.h" 18 #include "base/feature_list.h"
18 #include "base/logging.h" 19 #include "base/logging.h"
19 #include "base/macros.h" 20 #include "base/macros.h"
20 #include "base/memory/ptr_util.h" 21 #include "base/memory/ptr_util.h"
21 #include "base/strings/string_split.h" 22 #include "base/strings/string_split.h"
22 #include "base/strings/string_util.h" 23 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h" 24 #include "base/strings/stringprintf.h"
24 #include "base/threading/thread_task_runner_handle.h" 25 #include "base/threading/thread_task_runner_handle.h"
25 #include "base/trace_event/trace_event.h" 26 #include "base/trace_event/trace_event.h"
26 #include "build/build_config.h" 27 #include "build/build_config.h"
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 } 482 }
482 483
483 void GLRenderer::ClearFramebuffer(DrawingFrame* frame) { 484 void GLRenderer::ClearFramebuffer(DrawingFrame* frame) {
484 // On DEBUG builds, opaque render passes are cleared to blue to easily see 485 // On DEBUG builds, opaque render passes are cleared to blue to easily see
485 // regions that were not drawn on the screen. 486 // regions that were not drawn on the screen.
486 if (frame->current_render_pass->has_transparent_background) 487 if (frame->current_render_pass->has_transparent_background)
487 gl_->ClearColor(0, 0, 0, 0); 488 gl_->ClearColor(0, 0, 0, 0);
488 else 489 else
489 gl_->ClearColor(0, 0, 1, 1); 490 gl_->ClearColor(0, 0, 1, 1);
490 491
491 bool always_clear = false; 492 gl_->ClearStencil(0);
493
494 bool always_clear = overdraw_feedback_;
492 #ifndef NDEBUG 495 #ifndef NDEBUG
493 always_clear = true; 496 always_clear = true;
494 #endif 497 #endif
495 if (always_clear || frame->current_render_pass->has_transparent_background) { 498 if (always_clear || frame->current_render_pass->has_transparent_background) {
496 GLbitfield clear_bits = GL_COLOR_BUFFER_BIT; 499 GLbitfield clear_bits = GL_COLOR_BUFFER_BIT;
497 if (always_clear) 500 if (always_clear)
498 clear_bits |= GL_STENCIL_BUFFER_BIT; 501 clear_bits |= GL_STENCIL_BUFFER_BIT;
499 gl_->Clear(clear_bits); 502 gl_->Clear(clear_bits);
500 } 503 }
501 } 504 }
(...skipping 2077 matching lines...) Expand 10 before | Expand all | Expand 10 after
2579 } 2582 }
2580 } 2583 }
2581 2584
2582 void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) { 2585 void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) {
2583 if (use_sync_query_) { 2586 if (use_sync_query_) {
2584 DCHECK(current_sync_query_); 2587 DCHECK(current_sync_query_);
2585 current_sync_query_->End(); 2588 current_sync_query_->End();
2586 pending_sync_queries_.push_back(std::move(current_sync_query_)); 2589 pending_sync_queries_.push_back(std::move(current_sync_query_));
2587 } 2590 }
2588 2591
2592 swap_buffer_rect_.Union(frame->root_damage_rect);
2593 if (overdraw_feedback_)
2594 FlushOverdrawFeedback(frame, swap_buffer_rect_);
2595
2589 current_framebuffer_lock_ = nullptr; 2596 current_framebuffer_lock_ = nullptr;
2590 swap_buffer_rect_.Union(frame->root_damage_rect);
2591 2597
2592 gl_->Disable(GL_BLEND); 2598 gl_->Disable(GL_BLEND);
2593 blend_shadow_ = false; 2599 blend_shadow_ = false;
2594 2600
2595 ScheduleCALayers(frame); 2601 ScheduleCALayers(frame);
2596 ScheduleOverlays(frame); 2602 ScheduleOverlays(frame);
2597 } 2603 }
2598 2604
2599 void GLRenderer::FinishDrawingQuadList() { 2605 void GLRenderer::FinishDrawingQuadList() {
2600 FlushTextureQuadCache(SHARED_BINDING); 2606 FlushTextureQuadCache(SHARED_BINDING);
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
2818 void GLRenderer::GetFramebufferPixelsAsync( 2824 void GLRenderer::GetFramebufferPixelsAsync(
2819 const DrawingFrame* frame, 2825 const DrawingFrame* frame,
2820 const gfx::Rect& rect, 2826 const gfx::Rect& rect,
2821 std::unique_ptr<CopyOutputRequest> request) { 2827 std::unique_ptr<CopyOutputRequest> request) {
2822 DCHECK(!request->IsEmpty()); 2828 DCHECK(!request->IsEmpty());
2823 if (request->IsEmpty()) 2829 if (request->IsEmpty())
2824 return; 2830 return;
2825 if (rect.IsEmpty()) 2831 if (rect.IsEmpty())
2826 return; 2832 return;
2827 2833
2834 if (overdraw_feedback_)
2835 FlushOverdrawFeedback(frame, rect);
2836
2828 gfx::Rect window_rect = MoveFromDrawToWindowSpace(frame, rect); 2837 gfx::Rect window_rect = MoveFromDrawToWindowSpace(frame, rect);
2829 DCHECK_GE(window_rect.x(), 0); 2838 DCHECK_GE(window_rect.x(), 0);
2830 DCHECK_GE(window_rect.y(), 0); 2839 DCHECK_GE(window_rect.y(), 0);
2831 DCHECK_LE(window_rect.right(), current_surface_size_.width()); 2840 DCHECK_LE(window_rect.right(), current_surface_size_.width());
2832 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); 2841 DCHECK_LE(window_rect.bottom(), current_surface_size_.height());
2833 2842
2834 if (!request->force_bitmap_result()) { 2843 if (!request->force_bitmap_result()) {
2835 bool own_mailbox = !request->has_texture_mailbox(); 2844 bool own_mailbox = !request->has_texture_mailbox();
2836 2845
2837 GLuint texture_id = 0; 2846 GLuint texture_id = 0;
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
3009 gl_->CopyTexImage2D(GL_TEXTURE_2D, 0, format, window_rect.x(), 3018 gl_->CopyTexImage2D(GL_TEXTURE_2D, 0, format, window_rect.x(),
3010 window_rect.y(), window_rect.width(), 3019 window_rect.y(), window_rect.width(),
3011 window_rect.height(), 0); 3020 window_rect.height(), 0);
3012 gl_->BindTexture(GL_TEXTURE_2D, 0); 3021 gl_->BindTexture(GL_TEXTURE_2D, 0);
3013 } 3022 }
3014 3023
3015 void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) { 3024 void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) {
3016 current_framebuffer_lock_ = nullptr; 3025 current_framebuffer_lock_ = nullptr;
3017 output_surface_->BindFramebuffer(); 3026 output_surface_->BindFramebuffer();
3018 3027
3019 if (output_surface_->HasExternalStencilTest()) { 3028 if (overdraw_feedback_) {
3029 DCHECK(!output_surface_->HasExternalStencilTest());
danakj 2017/01/16 16:02:57 Can you put in a comment that the output surface s
reveman 2017/01/16 18:02:27 Done.
3030 SetupOverdrawFeedback();
3031 SetStencilEnabled(true);
3032 } else if (output_surface_->HasExternalStencilTest()) {
3020 output_surface_->ApplyExternalStencil(); 3033 output_surface_->ApplyExternalStencil();
3021 SetStencilEnabled(true); 3034 SetStencilEnabled(true);
3022 } else { 3035 } else {
3023 SetStencilEnabled(false); 3036 SetStencilEnabled(false);
3024 } 3037 }
3025 } 3038 }
3026 3039
3027 bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame, 3040 bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame,
3028 const ScopedResource* texture) { 3041 const ScopedResource* texture) {
3029 DCHECK(texture->id()); 3042 DCHECK(texture->id());
3030 3043
3031 // Explicitly release lock, otherwise we can crash when try to lock 3044 // Explicitly release lock, otherwise we can crash when try to lock
3032 // same texture again. 3045 // same texture again.
3033 current_framebuffer_lock_ = nullptr; 3046 current_framebuffer_lock_ = nullptr;
3034 3047
3035 SetStencilEnabled(false);
3036 gl_->BindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_); 3048 gl_->BindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_);
3037 current_framebuffer_lock_ = 3049 current_framebuffer_lock_ =
3038 base::MakeUnique<ResourceProvider::ScopedWriteLockGL>( 3050 base::MakeUnique<ResourceProvider::ScopedWriteLockGL>(
3039 resource_provider_, texture->id(), false); 3051 resource_provider_, texture->id(), false);
3040 current_framebuffer_format_ = texture->format(); 3052 current_framebuffer_format_ = texture->format();
3041 unsigned texture_id = current_framebuffer_lock_->texture_id(); 3053 unsigned texture_id = current_framebuffer_lock_->texture_id();
3042 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 3054 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3043 texture_id, 0); 3055 texture_id, 0);
3056 if (overdraw_feedback_) {
3057 if (!offscreen_stencil_renderbuffer_id_)
3058 gl_->GenRenderbuffers(1, &offscreen_stencil_renderbuffer_id_);
3059 if (texture->size() != offscreen_stencil_renderbuffer_size_) {
3060 gl_->BindRenderbuffer(GL_RENDERBUFFER,
3061 offscreen_stencil_renderbuffer_id_);
3062 gl_->RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8,
3063 texture->size().width(),
3064 texture->size().height());
3065 gl_->BindRenderbuffer(GL_RENDERBUFFER, 0);
3066 offscreen_stencil_renderbuffer_size_ = texture->size();
3067 }
3068 gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
3069 GL_RENDERBUFFER,
3070 offscreen_stencil_renderbuffer_id_);
3071 }
3044 3072
3045 DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) == 3073 DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) ==
3046 GL_FRAMEBUFFER_COMPLETE || 3074 GL_FRAMEBUFFER_COMPLETE ||
3047 IsContextLost()); 3075 IsContextLost());
3076
3077 if (overdraw_feedback_) {
3078 SetupOverdrawFeedback();
3079 SetStencilEnabled(true);
3080 } else {
3081 SetStencilEnabled(false);
3082 }
3048 return true; 3083 return true;
3049 } 3084 }
3050 3085
3051 void GLRenderer::SetScissorTestRect(const gfx::Rect& scissor_rect) { 3086 void GLRenderer::SetScissorTestRect(const gfx::Rect& scissor_rect) {
3052 EnsureScissorTestEnabled(); 3087 EnsureScissorTestEnabled();
3053 3088
3054 // Don't unnecessarily ask the context to change the scissor, because it 3089 // Don't unnecessarily ask the context to change the scissor, because it
3055 // may cause undesired GPU pipeline flushes. 3090 // may cause undesired GPU pipeline flushes.
3056 if (scissor_rect == scissor_rect_) 3091 if (scissor_rect == scissor_rect_)
3057 return; 3092 return;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
3151 } 3186 }
3152 } 3187 }
3153 } 3188 }
3154 for (auto& iter : program_cache_) 3189 for (auto& iter : program_cache_)
3155 iter.second->Cleanup(gl_); 3190 iter.second->Cleanup(gl_);
3156 program_cache_.clear(); 3191 program_cache_.clear();
3157 3192
3158 if (offscreen_framebuffer_id_) 3193 if (offscreen_framebuffer_id_)
3159 gl_->DeleteFramebuffers(1, &offscreen_framebuffer_id_); 3194 gl_->DeleteFramebuffers(1, &offscreen_framebuffer_id_);
3160 3195
3196 if (offscreen_stencil_renderbuffer_id_)
3197 gl_->DeleteRenderbuffers(1, &offscreen_stencil_renderbuffer_id_);
3198
3161 ReleaseRenderPassTextures(); 3199 ReleaseRenderPassTextures();
3162 } 3200 }
3163 3201
3164 void GLRenderer::ReinitializeGLState() { 3202 void GLRenderer::ReinitializeGLState() {
3165 is_scissor_enabled_ = false; 3203 is_scissor_enabled_ = false;
3166 scissor_rect_ = gfx::Rect(); 3204 scissor_rect_ = gfx::Rect();
3167 stencil_shadow_ = false; 3205 stencil_shadow_ = false;
3168 blend_shadow_ = true; 3206 blend_shadow_ = true;
3169 program_shadow_ = 0; 3207 program_shadow_ = 0;
3170 3208
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
3483 3521
3484 // The alpha has already been applied when copying the RPDQ to an IOSurface. 3522 // The alpha has already been applied when copying the RPDQ to an IOSurface.
3485 GLfloat alpha = 1; 3523 GLfloat alpha = 1;
3486 gl_->ScheduleCALayerSharedStateCHROMIUM(alpha, is_clipped, clip_rect, 3524 gl_->ScheduleCALayerSharedStateCHROMIUM(alpha, is_clipped, clip_rect,
3487 sorting_context_id, gl_transform); 3525 sorting_context_id, gl_transform);
3488 gl_->ScheduleCALayerCHROMIUM( 3526 gl_->ScheduleCALayerCHROMIUM(
3489 texture_id, contents_rect, ca_layer_overlay->background_color, 3527 texture_id, contents_rect, ca_layer_overlay->background_color,
3490 ca_layer_overlay->edge_aa_mask, bounds_rect, filter); 3528 ca_layer_overlay->edge_aa_mask, bounds_rect, filter);
3491 } 3529 }
3492 3530
3531 void GLRenderer::SetupOverdrawFeedback() {
3532 gl_->StencilFunc(GL_ALWAYS, 1, 0xffffffff);
3533 // First two values are ignored as test always passes.
3534 gl_->StencilOp(GL_KEEP, GL_KEEP, GL_INCR);
3535 gl_->StencilMask(0xff);
3536 }
3537
3538 void GLRenderer::FlushOverdrawFeedback(const DrawingFrame* frame,
3539 const gfx::Rect& output_rect) {
3540 DCHECK(stencil_shadow_);
3541
3542 // Test only, keep everything.
3543 gl_->StencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3544 gl_->StencilMask(0);
3545
3546 EnsureScissorTestDisabled();
3547 SetBlendEnabled(true);
3548
3549 PrepareGeometry(SHARED_BINDING);
3550
3551 const Program* program = GetProgram(ProgramKey::DebugBorder());
3552 DCHECK(program && (program->initialized() || IsContextLost()));
3553 SetUseProgram(program->program());
3554
3555 gfx::Transform render_matrix;
3556 render_matrix.Translate(0.5 * output_rect.width() + output_rect.x(),
3557 0.5 * output_rect.height() + output_rect.y());
3558 render_matrix.Scale(output_rect.width(), output_rect.height());
3559 static float gl_matrix[16];
3560 GLRenderer::ToGLMatrix(&gl_matrix[0],
3561 frame->projection_matrix * render_matrix);
3562 gl_->UniformMatrix4fv(program->matrix_location(), 1, false, &gl_matrix[0]);
3563
3564 // Produce hinting for the amount of overdraw on screen for each pixel by
3565 // drawing hint colors to the framebuffer based on the current stencil value.
3566 struct {
3567 int category;
3568 GLenum func;
3569 GLint ref;
3570 SkColor color;
3571 } stencil_tests[] = {
3572 {1, GL_EQUAL, 2, 0x2f0000ff}, // Blue: Overdrawn once.
3573 {2, GL_EQUAL, 3, 0x2f00ff00}, // Green: Overdrawn twice.
3574 {3, GL_EQUAL, 4, 0x3fff0000}, // Pink: Overdrawn three times.
3575 {4, GL_LESS, 4, 0x7fff0000}, // Red: Overdrawn four or more times.
3576 };
3577
3578 // Occlusion queries can be expensive, so only collect trace data if we select
3579 // cc.debug.overdraw.
3580 bool tracing_enabled;
3581 TRACE_EVENT_CATEGORY_GROUP_ENABLED(
3582 TRACE_DISABLED_BY_DEFAULT("cc.debug.overdraw"), &tracing_enabled);
3583
3584 // Trace only the root render pass.
3585 if (frame->current_render_pass != frame->root_render_pass)
3586 tracing_enabled = false;
3587
3588 auto overdraw = new OverdrawResult;
3589 base::Closure barrier = base::BarrierClosure(
3590 arraysize(stencil_tests),
3591 base::Bind(&GLRenderer::UpdateOverdrawCounter, base::Owned(overdraw)));
3592
3593 for (const auto& test : stencil_tests) {
3594 GLuint query = 0;
3595 if (tracing_enabled) {
3596 gl_->GenQueriesEXT(1, &query);
3597 // TODO(reveman): Use SAMPLES_PASSED_ARB when available for exact amount
3598 // of overdraw.
3599 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
3600 }
3601
3602 gl_->StencilFunc(test.func, test.ref, 0xffffffff);
3603 // Transparent color unless color-coding of overdraw is enabled.
3604 Float4 color =
3605 PremultipliedColor(settings_->show_overdraw_feedback ? test.color : 0);
3606 gl_->Uniform4fv(program->color_location(), 1, color.data);
3607 gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
3608
3609 if (query) {
3610 gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
3611 context_support_->SignalQuery(
3612 query, base::Bind(&GLRenderer::ProcessOverdrawFeedback,
3613 weak_ptr_factory_.GetWeakPtr(), query,
3614 test.category, overdraw, barrier));
3615 }
3616 }
3617 }
3618
3619 void GLRenderer::ProcessOverdrawFeedback(unsigned query,
3620 int category,
3621 OverdrawResult* overdraw,
3622 const base::Closure& callback) {
3623 if (query) {
3624 unsigned result = 0;
3625 gl_->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
3626 gl_->DeleteQueriesEXT(1, &query);
3627 if (result)
3628 overdraw->insert(category);
3629 }
3630
3631 callback.Run();
3632 }
3633
3634 // static
3635 void GLRenderer::UpdateOverdrawCounter(const OverdrawResult* overdraw) {
3636 // Report overdraw as multiple of the screen size. ie. 1x for the whole
3637 // screen is 1.0. Note: this will always report the worst overdraw on screen
3638 // as the overdraw for the whole screen until SAMPLES_PASSED_ARB is supported.
3639 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.overdraw"), "GPU Overdraw",
3640 overdraw->empty() ? 0 : *overdraw->rbegin());
3641 }
3642
3493 } // namespace cc 3643 } // namespace cc
OLDNEW
« no previous file with comments | « cc/output/gl_renderer.h ('k') | cc/output/gl_renderer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698