Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 363 }; | 364 }; |
| 364 | 365 |
| 365 gpu::gles2::GLES2Interface* gl_; | 366 gpu::gles2::GLES2Interface* gl_; |
| 366 unsigned query_id_; | 367 unsigned query_id_; |
| 367 bool is_pending_; | 368 bool is_pending_; |
| 368 base::WeakPtrFactory<SyncQuery> weak_ptr_factory_; | 369 base::WeakPtrFactory<SyncQuery> weak_ptr_factory_; |
| 369 | 370 |
| 370 DISALLOW_COPY_AND_ASSIGN(SyncQuery); | 371 DISALLOW_COPY_AND_ASSIGN(SyncQuery); |
| 371 }; | 372 }; |
| 372 | 373 |
| 374 struct GLRenderer::PendingOverdrawQuery { | |
| 375 explicit PendingOverdrawQuery(unsigned query) : query(query) {} | |
| 376 | |
| 377 base::CancelableClosure overdraw_callback; | |
|
danakj
2017/01/12 00:42:58
this makes a weakptrfactory for each query, is tha
reveman
2017/01/13 01:27:43
This code has been removed from latest patch.
| |
| 378 const unsigned query; | |
|
danakj
2017/01/12 00:42:57
query is a GLuint, can you use that instead of "un
reveman
2017/01/13 01:27:42
This code has been removed from latest patch but u
| |
| 379 | |
| 380 private: | |
| 381 DISALLOW_COPY_AND_ASSIGN(PendingOverdrawQuery); | |
| 382 }; | |
| 383 | |
| 373 GLRenderer::GLRenderer(const RendererSettings* settings, | 384 GLRenderer::GLRenderer(const RendererSettings* settings, |
| 374 OutputSurface* output_surface, | 385 OutputSurface* output_surface, |
| 375 ResourceProvider* resource_provider, | 386 ResourceProvider* resource_provider, |
| 376 TextureMailboxDeleter* texture_mailbox_deleter, | 387 TextureMailboxDeleter* texture_mailbox_deleter, |
| 377 int highp_threshold_min) | 388 int highp_threshold_min) |
| 378 : DirectRenderer(settings, output_surface, resource_provider), | 389 : DirectRenderer(settings, output_surface, resource_provider), |
| 379 offscreen_framebuffer_id_(0), | 390 offscreen_framebuffer_id_(0), |
| 380 shared_geometry_quad_(QuadVertexRect()), | 391 shared_geometry_quad_(QuadVertexRect()), |
| 381 gl_(output_surface->context_provider()->ContextGL()), | 392 gl_(output_surface->context_provider()->ContextGL()), |
| 382 context_support_(output_surface->context_provider()->ContextSupport()), | 393 context_support_(output_surface->context_provider()->ContextSupport()), |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 408 } | 419 } |
| 409 | 420 |
| 410 GLRenderer::~GLRenderer() { | 421 GLRenderer::~GLRenderer() { |
| 411 while (!pending_async_read_pixels_.empty()) { | 422 while (!pending_async_read_pixels_.empty()) { |
| 412 PendingAsyncReadPixels* pending_read = | 423 PendingAsyncReadPixels* pending_read = |
| 413 pending_async_read_pixels_.back().get(); | 424 pending_async_read_pixels_.back().get(); |
| 414 pending_read->finished_read_pixels_callback.Cancel(); | 425 pending_read->finished_read_pixels_callback.Cancel(); |
| 415 pending_async_read_pixels_.pop_back(); | 426 pending_async_read_pixels_.pop_back(); |
| 416 } | 427 } |
| 417 | 428 |
| 429 while (!pending_overdraw_queries_.empty()) { | |
| 430 PendingOverdrawQuery* pending_query = | |
| 431 pending_overdraw_queries_.back().get(); | |
| 432 pending_query->overdraw_callback.Cancel(); | |
|
danakj
2017/01/12 00:42:58
destroying a WeakPtrFactory (inside the Cancelable
reveman
2017/01/13 01:27:42
This code has been removed from latest patch.
| |
| 433 pending_overdraw_queries_.pop_back(); | |
| 434 } | |
| 435 | |
| 418 CleanupSharedObjects(); | 436 CleanupSharedObjects(); |
| 419 | 437 |
| 420 if (context_visibility_) { | 438 if (context_visibility_) { |
| 421 auto* context_provider = output_surface_->context_provider(); | 439 auto* context_provider = output_surface_->context_provider(); |
| 422 auto* cache_controller = context_provider->CacheController(); | 440 auto* cache_controller = context_provider->CacheController(); |
| 423 cache_controller->ClientBecameNotVisible(std::move(context_visibility_)); | 441 cache_controller->ClientBecameNotVisible(std::move(context_visibility_)); |
| 424 } | 442 } |
| 425 } | 443 } |
| 426 | 444 |
| 427 bool GLRenderer::CanPartialSwap() { | 445 bool GLRenderer::CanPartialSwap() { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 488 } | 506 } |
| 489 | 507 |
| 490 void GLRenderer::ClearFramebuffer(DrawingFrame* frame) { | 508 void GLRenderer::ClearFramebuffer(DrawingFrame* frame) { |
| 491 // On DEBUG builds, opaque render passes are cleared to blue to easily see | 509 // On DEBUG builds, opaque render passes are cleared to blue to easily see |
| 492 // regions that were not drawn on the screen. | 510 // regions that were not drawn on the screen. |
| 493 if (frame->current_render_pass->has_transparent_background) | 511 if (frame->current_render_pass->has_transparent_background) |
| 494 gl_->ClearColor(0, 0, 0, 0); | 512 gl_->ClearColor(0, 0, 0, 0); |
| 495 else | 513 else |
| 496 gl_->ClearColor(0, 0, 1, 1); | 514 gl_->ClearColor(0, 0, 1, 1); |
| 497 | 515 |
| 498 bool always_clear = false; | 516 gl_->ClearStencil(0); |
|
danakj
2017/01/12 00:42:58
Does this add cost when not using overdraw feedbac
reveman
2017/01/13 01:27:42
Pretty sure it doesn't and doing this unconditiona
| |
| 517 | |
| 518 bool always_clear = overdraw_feedback_; | |
| 499 #ifndef NDEBUG | 519 #ifndef NDEBUG |
| 500 always_clear = true; | 520 always_clear = true; |
| 501 #endif | 521 #endif |
| 502 if (always_clear || frame->current_render_pass->has_transparent_background) { | 522 if (always_clear || frame->current_render_pass->has_transparent_background) { |
| 503 GLbitfield clear_bits = GL_COLOR_BUFFER_BIT; | 523 GLbitfield clear_bits = GL_COLOR_BUFFER_BIT; |
| 504 if (always_clear) | 524 if (always_clear) |
| 505 clear_bits |= GL_STENCIL_BUFFER_BIT; | 525 clear_bits |= GL_STENCIL_BUFFER_BIT; |
| 506 gl_->Clear(clear_bits); | 526 gl_->Clear(clear_bits); |
| 507 } | 527 } |
| 508 } | 528 } |
| (...skipping 2248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2757 } | 2777 } |
| 2758 } | 2778 } |
| 2759 | 2779 |
| 2760 void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) { | 2780 void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) { |
| 2761 if (use_sync_query_) { | 2781 if (use_sync_query_) { |
| 2762 DCHECK(current_sync_query_); | 2782 DCHECK(current_sync_query_); |
| 2763 current_sync_query_->End(); | 2783 current_sync_query_->End(); |
| 2764 pending_sync_queries_.push_back(std::move(current_sync_query_)); | 2784 pending_sync_queries_.push_back(std::move(current_sync_query_)); |
| 2765 } | 2785 } |
| 2766 | 2786 |
| 2787 swap_buffer_rect_.Union(frame->root_damage_rect); | |
| 2788 if (overdraw_feedback_) | |
| 2789 FlushOverdrawFeedback(frame, swap_buffer_rect_); | |
| 2790 | |
| 2767 current_framebuffer_lock_ = nullptr; | 2791 current_framebuffer_lock_ = nullptr; |
| 2768 swap_buffer_rect_.Union(frame->root_damage_rect); | |
| 2769 | 2792 |
| 2770 gl_->Disable(GL_BLEND); | 2793 gl_->Disable(GL_BLEND); |
| 2771 blend_shadow_ = false; | 2794 blend_shadow_ = false; |
| 2772 | 2795 |
| 2773 ScheduleCALayers(frame); | 2796 ScheduleCALayers(frame); |
| 2774 ScheduleOverlays(frame); | 2797 ScheduleOverlays(frame); |
| 2775 } | 2798 } |
| 2776 | 2799 |
| 2777 void GLRenderer::FinishDrawingQuadList() { | 2800 void GLRenderer::FinishDrawingQuadList() { |
| 2778 FlushTextureQuadCache(SHARED_BINDING); | 2801 FlushTextureQuadCache(SHARED_BINDING); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2996 void GLRenderer::GetFramebufferPixelsAsync( | 3019 void GLRenderer::GetFramebufferPixelsAsync( |
| 2997 const DrawingFrame* frame, | 3020 const DrawingFrame* frame, |
| 2998 const gfx::Rect& rect, | 3021 const gfx::Rect& rect, |
| 2999 std::unique_ptr<CopyOutputRequest> request) { | 3022 std::unique_ptr<CopyOutputRequest> request) { |
| 3000 DCHECK(!request->IsEmpty()); | 3023 DCHECK(!request->IsEmpty()); |
| 3001 if (request->IsEmpty()) | 3024 if (request->IsEmpty()) |
| 3002 return; | 3025 return; |
| 3003 if (rect.IsEmpty()) | 3026 if (rect.IsEmpty()) |
| 3004 return; | 3027 return; |
| 3005 | 3028 |
| 3029 if (overdraw_feedback_) | |
|
danakj
2017/01/12 00:42:58
how come you do this into readbacks?
reveman
2017/01/13 01:27:42
For screenshots. That's very important for debuggi
danakj
2017/01/16 16:02:57
Do you need it in screenshots of non-root render s
reveman
2017/01/16 18:02:26
This is needed for all types of screenshots on Chr
| |
| 3030 FlushOverdrawFeedback(frame, rect); | |
| 3031 | |
| 3006 gfx::Rect window_rect = MoveFromDrawToWindowSpace(frame, rect); | 3032 gfx::Rect window_rect = MoveFromDrawToWindowSpace(frame, rect); |
| 3007 DCHECK_GE(window_rect.x(), 0); | 3033 DCHECK_GE(window_rect.x(), 0); |
| 3008 DCHECK_GE(window_rect.y(), 0); | 3034 DCHECK_GE(window_rect.y(), 0); |
| 3009 DCHECK_LE(window_rect.right(), current_surface_size_.width()); | 3035 DCHECK_LE(window_rect.right(), current_surface_size_.width()); |
| 3010 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); | 3036 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); |
| 3011 | 3037 |
| 3012 if (!request->force_bitmap_result()) { | 3038 if (!request->force_bitmap_result()) { |
| 3013 bool own_mailbox = !request->has_texture_mailbox(); | 3039 bool own_mailbox = !request->has_texture_mailbox(); |
| 3014 | 3040 |
| 3015 GLuint texture_id = 0; | 3041 GLuint texture_id = 0; |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3196 gl_->CopyTexImage2D(GL_TEXTURE_2D, 0, format, window_rect.x(), | 3222 gl_->CopyTexImage2D(GL_TEXTURE_2D, 0, format, window_rect.x(), |
| 3197 window_rect.y(), window_rect.width(), | 3223 window_rect.y(), window_rect.width(), |
| 3198 window_rect.height(), 0); | 3224 window_rect.height(), 0); |
| 3199 gl_->BindTexture(GL_TEXTURE_2D, 0); | 3225 gl_->BindTexture(GL_TEXTURE_2D, 0); |
| 3200 } | 3226 } |
| 3201 | 3227 |
| 3202 void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) { | 3228 void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) { |
| 3203 current_framebuffer_lock_ = nullptr; | 3229 current_framebuffer_lock_ = nullptr; |
| 3204 output_surface_->BindFramebuffer(); | 3230 output_surface_->BindFramebuffer(); |
| 3205 | 3231 |
| 3206 if (output_surface_->HasExternalStencilTest()) { | 3232 if (overdraw_feedback_) { |
| 3233 SetupOverdrawFeedback(); | |
| 3234 SetStencilEnabled(true); | |
| 3235 } else if (output_surface_->HasExternalStencilTest()) { | |
|
danakj
2017/01/12 00:42:58
using else here means turning on overdraw feedback
reveman
2017/01/13 01:27:42
I'm expecting an output surface that might have an
| |
| 3207 output_surface_->ApplyExternalStencil(); | 3236 output_surface_->ApplyExternalStencil(); |
| 3208 SetStencilEnabled(true); | 3237 SetStencilEnabled(true); |
| 3209 } else { | 3238 } else { |
| 3210 SetStencilEnabled(false); | 3239 SetStencilEnabled(false); |
| 3211 } | 3240 } |
| 3212 } | 3241 } |
| 3213 | 3242 |
| 3214 bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame, | 3243 bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame, |
| 3215 const ScopedResource* texture) { | 3244 const ScopedResource* texture) { |
| 3216 DCHECK(texture->id()); | 3245 DCHECK(texture->id()); |
| 3217 | 3246 |
| 3218 // Explicitly release lock, otherwise we can crash when try to lock | 3247 // Explicitly release lock, otherwise we can crash when try to lock |
| 3219 // same texture again. | 3248 // same texture again. |
| 3220 current_framebuffer_lock_ = nullptr; | 3249 current_framebuffer_lock_ = nullptr; |
| 3221 | 3250 |
| 3222 SetStencilEnabled(false); | |
| 3223 gl_->BindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_); | 3251 gl_->BindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_); |
| 3224 current_framebuffer_lock_ = | 3252 current_framebuffer_lock_ = |
| 3225 base::MakeUnique<ResourceProvider::ScopedWriteLockGL>( | 3253 base::MakeUnique<ResourceProvider::ScopedWriteLockGL>( |
| 3226 resource_provider_, texture->id(), false); | 3254 resource_provider_, texture->id(), false); |
| 3227 current_framebuffer_format_ = texture->format(); | 3255 current_framebuffer_format_ = texture->format(); |
| 3228 unsigned texture_id = current_framebuffer_lock_->texture_id(); | 3256 unsigned texture_id = current_framebuffer_lock_->texture_id(); |
| 3229 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | 3257 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, |
| 3230 texture_id, 0); | 3258 texture_id, 0); |
| 3259 if (overdraw_feedback_) { | |
| 3260 if (!offscreen_stencil_renderbuffer_id_) | |
| 3261 gl_->GenRenderbuffers(1, &offscreen_stencil_renderbuffer_id_); | |
| 3262 if (texture->size() != offscreen_stencil_renderbuffer_size_) { | |
| 3263 gl_->BindRenderbuffer(GL_RENDERBUFFER, | |
| 3264 offscreen_stencil_renderbuffer_id_); | |
| 3265 gl_->RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, | |
| 3266 texture->size().width(), | |
| 3267 texture->size().height()); | |
| 3268 gl_->BindRenderbuffer(GL_RENDERBUFFER, 0); | |
| 3269 offscreen_stencil_renderbuffer_size_ = texture->size(); | |
| 3270 } | |
| 3271 gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, | |
| 3272 GL_RENDERBUFFER, | |
| 3273 offscreen_stencil_renderbuffer_id_); | |
| 3274 } | |
| 3231 | 3275 |
| 3232 DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) == | 3276 DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) == |
| 3233 GL_FRAMEBUFFER_COMPLETE || | 3277 GL_FRAMEBUFFER_COMPLETE || |
| 3234 IsContextLost()); | 3278 IsContextLost()); |
| 3279 | |
| 3280 if (overdraw_feedback_) { | |
|
danakj
2017/01/12 00:42:58
Hm why do you do stencil and overdraw stuff for ch
reveman
2017/01/13 01:27:42
Yes, this is for copy requests.
| |
| 3281 SetupOverdrawFeedback(); | |
| 3282 SetStencilEnabled(true); | |
| 3283 } else { | |
| 3284 SetStencilEnabled(false); | |
| 3285 } | |
| 3235 return true; | 3286 return true; |
| 3236 } | 3287 } |
| 3237 | 3288 |
| 3238 void GLRenderer::SetScissorTestRect(const gfx::Rect& scissor_rect) { | 3289 void GLRenderer::SetScissorTestRect(const gfx::Rect& scissor_rect) { |
| 3239 EnsureScissorTestEnabled(); | 3290 EnsureScissorTestEnabled(); |
| 3240 | 3291 |
| 3241 // Don't unnecessarily ask the context to change the scissor, because it | 3292 // Don't unnecessarily ask the context to change the scissor, because it |
| 3242 // may cause undesired GPU pipeline flushes. | 3293 // may cause undesired GPU pipeline flushes. |
| 3243 if (scissor_rect == scissor_rect_) | 3294 if (scissor_rect == scissor_rect_) |
| 3244 return; | 3295 return; |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3726 video_stream_texture_program_[i].Cleanup(gl_); | 3777 video_stream_texture_program_[i].Cleanup(gl_); |
| 3727 } | 3778 } |
| 3728 | 3779 |
| 3729 debug_border_program_.Cleanup(gl_); | 3780 debug_border_program_.Cleanup(gl_); |
| 3730 solid_color_program_.Cleanup(gl_); | 3781 solid_color_program_.Cleanup(gl_); |
| 3731 solid_color_program_aa_.Cleanup(gl_); | 3782 solid_color_program_aa_.Cleanup(gl_); |
| 3732 | 3783 |
| 3733 if (offscreen_framebuffer_id_) | 3784 if (offscreen_framebuffer_id_) |
| 3734 gl_->DeleteFramebuffers(1, &offscreen_framebuffer_id_); | 3785 gl_->DeleteFramebuffers(1, &offscreen_framebuffer_id_); |
| 3735 | 3786 |
| 3787 if (offscreen_stencil_renderbuffer_id_) | |
| 3788 gl_->DeleteRenderbuffers(1, &offscreen_stencil_renderbuffer_id_); | |
| 3789 | |
| 3736 ReleaseRenderPassTextures(); | 3790 ReleaseRenderPassTextures(); |
| 3737 } | 3791 } |
| 3738 | 3792 |
| 3739 void GLRenderer::ReinitializeGLState() { | 3793 void GLRenderer::ReinitializeGLState() { |
| 3740 is_scissor_enabled_ = false; | 3794 is_scissor_enabled_ = false; |
| 3741 scissor_rect_ = gfx::Rect(); | 3795 scissor_rect_ = gfx::Rect(); |
| 3742 stencil_shadow_ = false; | 3796 stencil_shadow_ = false; |
| 3743 blend_shadow_ = true; | 3797 blend_shadow_ = true; |
| 3744 program_shadow_ = 0; | 3798 program_shadow_ = 0; |
| 3745 | 3799 |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4058 | 4112 |
| 4059 // The alpha has already been applied when copying the RPDQ to an IOSurface. | 4113 // The alpha has already been applied when copying the RPDQ to an IOSurface. |
| 4060 GLfloat alpha = 1; | 4114 GLfloat alpha = 1; |
| 4061 gl_->ScheduleCALayerSharedStateCHROMIUM(alpha, is_clipped, clip_rect, | 4115 gl_->ScheduleCALayerSharedStateCHROMIUM(alpha, is_clipped, clip_rect, |
| 4062 sorting_context_id, gl_transform); | 4116 sorting_context_id, gl_transform); |
| 4063 gl_->ScheduleCALayerCHROMIUM( | 4117 gl_->ScheduleCALayerCHROMIUM( |
| 4064 texture_id, contents_rect, ca_layer_overlay->background_color, | 4118 texture_id, contents_rect, ca_layer_overlay->background_color, |
| 4065 ca_layer_overlay->edge_aa_mask, bounds_rect, filter); | 4119 ca_layer_overlay->edge_aa_mask, bounds_rect, filter); |
| 4066 } | 4120 } |
| 4067 | 4121 |
| 4122 void GLRenderer::SetupOverdrawFeedback() { | |
| 4123 gl_->StencilFunc(GL_ALWAYS, 1, 0xffffffff); | |
| 4124 // First two values are ignored as test always passes. | |
| 4125 gl_->StencilOp(GL_KEEP, GL_KEEP, GL_INCR); | |
| 4126 gl_->StencilMask(0xff); | |
| 4127 } | |
| 4128 | |
| 4129 void GLRenderer::FlushOverdrawFeedback(const DrawingFrame* frame, | |
| 4130 const gfx::Rect& output_rect) { | |
| 4131 // Return early if already flushed. | |
|
danakj
2017/01/12 00:42:58
I don't understand how we can flush twice for a si
reveman
2017/01/13 01:27:42
Good point. Now a DCHECK.
| |
| 4132 if (!stencil_shadow_) | |
| 4133 return; | |
| 4134 | |
| 4135 // Test only, keep everything. | |
| 4136 gl_->StencilOp(GL_KEEP, GL_KEEP, GL_KEEP); | |
| 4137 gl_->StencilMask(0); | |
| 4138 | |
| 4139 EnsureScissorTestDisabled(); | |
| 4140 SetBlendEnabled(true); | |
| 4141 | |
| 4142 PrepareGeometry(SHARED_BINDING); | |
| 4143 | |
| 4144 const DebugBorderProgram* program = GetDebugBorderProgram(); | |
| 4145 DCHECK(program && (program->initialized() || IsContextLost())); | |
| 4146 SetUseProgram(program->program()); | |
| 4147 | |
| 4148 gfx::Transform render_matrix; | |
| 4149 render_matrix.Translate(0.5 * output_rect.width() + output_rect.x(), | |
| 4150 0.5 * output_rect.height() + output_rect.y()); | |
| 4151 render_matrix.Scale(output_rect.width(), output_rect.height()); | |
| 4152 static float gl_matrix[16]; | |
| 4153 GLRenderer::ToGLMatrix(&gl_matrix[0], | |
| 4154 frame->projection_matrix * render_matrix); | |
| 4155 gl_->UniformMatrix4fv(program->vertex_shader().matrix_location(), 1, false, | |
| 4156 &gl_matrix[0]); | |
| 4157 | |
| 4158 // Produce hinting for the amount of overdraw on screen for each pixel by | |
| 4159 // drawing hint colors to the framebuffer based on the current stencil value. | |
| 4160 struct { | |
| 4161 int category; | |
| 4162 GLenum func; | |
| 4163 GLint ref; | |
| 4164 SkColor color; | |
| 4165 } stencil_tests[] = { | |
| 4166 {1, GL_EQUAL, 2, 0x2f0000ff}, // Blue: Overdrawn once. | |
| 4167 {2, GL_EQUAL, 3, 0x2f00ff00}, // Green: Overdrawn twice. | |
| 4168 {3, GL_EQUAL, 4, 0x3fff0000}, // Pink: Overdrawn three times. | |
| 4169 {4, GL_LESS, 4, 0x7fff0000}, // Red: Overdrawn four or more times. | |
| 4170 }; | |
| 4171 | |
| 4172 // Occlusion queries can be expensive, so only collect trace data if we select | |
| 4173 // cc.debug.overdraw. | |
| 4174 bool tracing_enabled; | |
| 4175 TRACE_EVENT_CATEGORY_GROUP_ENABLED( | |
| 4176 TRACE_DISABLED_BY_DEFAULT("cc.debug.overdraw"), &tracing_enabled); | |
| 4177 | |
| 4178 // Trace only the root render pass. | |
| 4179 if (frame->current_render_pass != frame->root_render_pass) | |
| 4180 tracing_enabled = false; | |
| 4181 | |
| 4182 base::Closure barrier = base::BarrierClosure( | |
| 4183 arraysize(stencil_tests), | |
| 4184 base::Bind(&GLRenderer::UpdateOverdrawCounter, base::Unretained(this))); | |
| 4185 | |
| 4186 for (const auto& test : stencil_tests) { | |
| 4187 if (tracing_enabled) { | |
| 4188 GLuint query = 0; | |
| 4189 gl_->GenQueriesEXT(1, &query); | |
| 4190 // TODO(reveman): Use SAMPLES_PASSED_ARB when available for exact amount | |
| 4191 // of overdraw. | |
| 4192 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query); | |
|
danakj
2017/01/12 00:42:57
would it not work to do one query around the whole
reveman
2017/01/13 01:27:43
We want samples for each overdraw category and wit
| |
| 4193 | |
| 4194 std::unique_ptr<PendingOverdrawQuery> pending_overdraw_query( | |
| 4195 new PendingOverdrawQuery(query)); | |
| 4196 pending_overdraw_queries_.push_back(std::move(pending_overdraw_query)); | |
| 4197 } | |
| 4198 | |
| 4199 gl_->StencilFunc(test.func, test.ref, 0xffffffff); | |
| 4200 // Transparent color unless color-coding of overdraw is enabled. | |
| 4201 Float4 color = | |
| 4202 PremultipliedColor(settings_->show_overdraw_feedback ? test.color : 0); | |
| 4203 gl_->Uniform4fv(program->fragment_shader().color_location(), 1, color.data); | |
| 4204 gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); | |
| 4205 | |
| 4206 if (tracing_enabled) { | |
| 4207 base::Closure overdraw_feedback_callback = base::Bind( | |
| 4208 &GLRenderer::OverdrawFeedback, base::Unretained(this), | |
| 4209 pending_overdraw_queries_.back()->query, test.category, barrier); | |
| 4210 | |
| 4211 // Save the overdraw_feedback_callback so it can be cancelled. | |
|
danakj
2017/01/12 00:42:57
If you just put a WeakPtrFactory on GLRenderer and
reveman
2017/01/13 01:27:42
Done but updated to be less complicated as a resul
| |
| 4212 pending_overdraw_queries_.back()->overdraw_callback.Reset( | |
| 4213 overdraw_feedback_callback); | |
| 4214 base::Closure cancelable_callback = | |
| 4215 pending_overdraw_queries_.back()->overdraw_callback.callback(); | |
| 4216 | |
| 4217 gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); | |
| 4218 context_support_->SignalQuery(pending_overdraw_queries_.back()->query, | |
| 4219 cancelable_callback); | |
| 4220 } | |
| 4221 } | |
| 4222 | |
| 4223 gl_->StencilFunc(GL_ALWAYS, 0, 0xffffffff); | |
| 4224 gl_->Disable(GL_STENCIL_TEST); | |
| 4225 stencil_shadow_ = false; | |
|
danakj
2017/01/12 00:42:58
It feels weird that this method is changing this,
reveman
2017/01/13 01:27:42
Good point. Removed it.
| |
| 4226 } | |
| 4227 | |
| 4228 void GLRenderer::OverdrawFeedback(unsigned query, | |
| 4229 int category, | |
| 4230 base::Closure barrier) { | |
|
danakj
2017/01/12 00:42:58
const&
reveman
2017/01/13 01:27:42
Done.
| |
| 4231 DCHECK(!pending_overdraw_queries_.empty()); | |
| 4232 DCHECK_EQ(pending_overdraw_queries_.front()->query, query); | |
| 4233 pending_overdraw_queries_.pop_front(); | |
| 4234 | |
| 4235 unsigned result = 0; | |
| 4236 if (query) { | |
| 4237 gl_->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result); | |
| 4238 gl_->DeleteQueriesEXT(1, &query); | |
| 4239 } | |
| 4240 | |
| 4241 if (result) | |
| 4242 current_overdraw_.insert(category); | |
| 4243 else | |
| 4244 current_overdraw_.erase(category); | |
| 4245 | |
| 4246 barrier.Run(); | |
| 4247 } | |
| 4248 | |
| 4249 void GLRenderer::UpdateOverdrawCounter() const { | |
| 4250 // Report overdraw as multiple of the screen size. ie. 1x for the whole | |
| 4251 // screen is 1.0. Note: this will always report the worst overdraw on screen | |
| 4252 // as the overdraw for the whole screen until SAMPLES_PASSED_ARB is supported. | |
| 4253 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.overdraw"), "GPU Overdraw", | |
| 4254 current_overdraw_.empty() ? 0 : *current_overdraw_.rbegin()); | |
| 4255 } | |
| 4256 | |
| 4068 } // namespace cc | 4257 } // namespace cc |
| OLD | NEW |