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

Unified Diff: cc/output/gl_renderer.cc

Issue 2612023002: cc: Implement overdraw feedback debugging feature. (Closed)
Patch Set: make sure overdraw_feedback_ is initialized and reset properly 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/output/gl_renderer.cc
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 35ecffb78519161433797545a8f1f05db763bc51..2ef2d36ba4252b5e864e25c652a5af8a11448f79 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -488,7 +488,9 @@ void GLRenderer::ClearFramebuffer(DrawingFrame* frame) {
else
gl_->ClearColor(0, 0, 1, 1);
- bool always_clear = false;
+ gl_->ClearStencil(0);
+
+ bool always_clear = overdraw_feedback_;
#ifndef NDEBUG
always_clear = true;
#endif
@@ -605,7 +607,8 @@ void GLRenderer::DrawDebugBorderQuad(const DrawingFrame* frame,
static float gl_matrix[16];
const Program* program = GetProgram(ProgramKey::DebugBorder());
- DCHECK(program && (program->initialized() || IsContextLost()));
+ DCHECK(program);
+ DCHECK(program->initialized() || IsContextLost());
SetUseProgram(program->program());
// Use the full quad_rect for debug quads to not move the edges based on
@@ -2146,7 +2149,8 @@ void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame,
use_nv12 ? UV_TEXTURE_MODE_UV : UV_TEXTURE_MODE_U_V,
use_color_lut ? COLOR_CONVERSION_MODE_2D_LUT_AS_3D_FROM_YUV
: COLOR_CONVERSION_MODE_NONE));
- DCHECK(program && (program->initialized() || IsContextLost()));
+ DCHECK(program);
+ DCHECK(program->initialized() || IsContextLost());
SetUseProgram(program->program());
matrix_location = program->matrix_location();
ya_tex_scale_location = program->ya_tex_scale_location();
@@ -2448,7 +2452,8 @@ void GLRenderer::FlushTextureQuadCache(BoundGeometry flush_binding) {
DCHECK_EQ(1u, draw_cache_.matrix_data.size());
SetBlendEnabled(false);
const Program* program = GetProgram(ProgramKey::DebugBorder());
- DCHECK(program && (program->initialized() || IsContextLost()));
+ DCHECK(program);
+ DCHECK(program->initialized() || IsContextLost());
SetUseProgram(program->program());
gl_->UniformMatrix4fv(
@@ -2588,8 +2593,11 @@ void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) {
pending_sync_queries_.push_back(std::move(current_sync_query_));
}
- current_framebuffer_lock_ = nullptr;
swap_buffer_rect_.Union(frame->root_damage_rect);
+ if (overdraw_feedback_)
+ FlushOverdrawFeedback(frame, swap_buffer_rect_);
+
+ current_framebuffer_lock_ = nullptr;
gl_->Disable(GL_BLEND);
blend_shadow_ = false;
@@ -2827,6 +2835,9 @@ void GLRenderer::GetFramebufferPixelsAsync(
if (rect.IsEmpty())
return;
+ if (overdraw_feedback_)
+ FlushOverdrawFeedback(frame, rect);
+
gfx::Rect window_rect = MoveFromDrawToWindowSpace(frame, rect);
DCHECK_GE(window_rect.x(), 0);
DCHECK_GE(window_rect.y(), 0);
@@ -3018,7 +3029,13 @@ void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) {
current_framebuffer_lock_ = nullptr;
output_surface_->BindFramebuffer();
- if (output_surface_->HasExternalStencilTest()) {
+ if (overdraw_feedback_) {
+ // Output surfaces that require an external stencil test should not allow
+ // overdraw feedback by setting |supports_stencil| to false.
+ DCHECK(!output_surface_->HasExternalStencilTest());
+ SetupOverdrawFeedback();
+ SetStencilEnabled(true);
+ } else if (output_surface_->HasExternalStencilTest()) {
output_surface_->ApplyExternalStencil();
SetStencilEnabled(true);
} else {
@@ -3034,7 +3051,6 @@ bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame,
// same texture again.
current_framebuffer_lock_ = nullptr;
- SetStencilEnabled(false);
gl_->BindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_);
current_framebuffer_lock_ =
base::MakeUnique<ResourceProvider::ScopedWriteLockGL>(
@@ -3043,10 +3059,33 @@ bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame,
unsigned texture_id = current_framebuffer_lock_->texture_id();
gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
texture_id, 0);
+ if (overdraw_feedback_) {
+ if (!offscreen_stencil_renderbuffer_id_)
+ gl_->GenRenderbuffers(1, &offscreen_stencil_renderbuffer_id_);
+ if (texture->size() != offscreen_stencil_renderbuffer_size_) {
+ gl_->BindRenderbuffer(GL_RENDERBUFFER,
+ offscreen_stencil_renderbuffer_id_);
+ gl_->RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8,
+ texture->size().width(),
+ texture->size().height());
+ gl_->BindRenderbuffer(GL_RENDERBUFFER, 0);
+ offscreen_stencil_renderbuffer_size_ = texture->size();
+ }
+ gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER,
+ offscreen_stencil_renderbuffer_id_);
+ }
DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) ==
GL_FRAMEBUFFER_COMPLETE ||
IsContextLost());
+
+ if (overdraw_feedback_) {
+ SetupOverdrawFeedback();
+ SetStencilEnabled(true);
+ } else {
+ SetStencilEnabled(false);
+ }
return true;
}
@@ -3127,6 +3166,9 @@ void GLRenderer::CleanupSharedObjects() {
if (offscreen_framebuffer_id_)
gl_->DeleteFramebuffers(1, &offscreen_framebuffer_id_);
+ if (offscreen_stencil_renderbuffer_id_)
+ gl_->DeleteRenderbuffers(1, &offscreen_stencil_renderbuffer_id_);
+
ReleaseRenderPassTextures();
}
@@ -3459,4 +3501,112 @@ void GLRenderer::ScheduleRenderPassDrawQuad(
ca_layer_overlay->edge_aa_mask, bounds_rect, filter);
}
+void GLRenderer::SetupOverdrawFeedback() {
+ gl_->StencilFunc(GL_ALWAYS, 1, 0xffffffff);
+ // First two values are ignored as test always passes.
+ gl_->StencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+ gl_->StencilMask(0xffffffff);
+}
+
+void GLRenderer::FlushOverdrawFeedback(const DrawingFrame* frame,
+ const gfx::Rect& output_rect) {
+ DCHECK(stencil_shadow_);
+
+ // Test only, keep everything.
+ gl_->StencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ EnsureScissorTestDisabled();
+ SetBlendEnabled(true);
+
+ PrepareGeometry(SHARED_BINDING);
+
+ const Program* program = GetProgram(ProgramKey::DebugBorder());
+ DCHECK(program);
+ DCHECK(program->initialized() || IsContextLost());
+ SetUseProgram(program->program());
+
+ gfx::Transform render_matrix;
+ render_matrix.Translate(0.5 * output_rect.width() + output_rect.x(),
+ 0.5 * output_rect.height() + output_rect.y());
+ render_matrix.Scale(output_rect.width(), output_rect.height());
+ static float gl_matrix[16];
+ GLRenderer::ToGLMatrix(&gl_matrix[0],
+ frame->projection_matrix * render_matrix);
+ gl_->UniformMatrix4fv(program->matrix_location(), 1, false, &gl_matrix[0]);
+
+ // Produce hinting for the amount of overdraw on screen for each pixel by
+ // drawing hint colors to the framebuffer based on the current stencil value.
+ struct {
+ int multiplier;
+ GLenum func;
+ GLint ref;
+ SkColor color;
+ } stencil_tests[] = {
+ {1, GL_EQUAL, 2, 0x2f0000ff}, // Blue: Overdrawn once.
+ {2, GL_EQUAL, 3, 0x2f00ff00}, // Green: Overdrawn twice.
+ {3, GL_EQUAL, 4, 0x3fff0000}, // Pink: Overdrawn three times.
+ {4, GL_LESS, 4, 0x7fff0000}, // Red: Overdrawn four or more times.
+ };
+
+ // Occlusion queries can be expensive, so only collect trace data if we select
+ // cc.debug.overdraw.
+ bool tracing_enabled;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(
+ TRACE_DISABLED_BY_DEFAULT("cc.debug.overdraw"), &tracing_enabled);
+
+ // Trace only the root render pass.
+ if (frame->current_render_pass != frame->root_render_pass)
+ tracing_enabled = false;
+
+ OverdrawFeedbackCallback overdraw_feedback_callback = base::Bind(
+ &GLRenderer::ProcessOverdrawFeedback, weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(new std::vector<int>), arraysize(stencil_tests));
+
+ for (const auto& test : stencil_tests) {
+ GLuint query = 0;
+ if (tracing_enabled) {
+ gl_->GenQueriesEXT(1, &query);
+ // TODO(reveman): Use SAMPLES_PASSED_ARB for exact amount of overdraw.
+ gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
+ }
+
+ gl_->StencilFunc(test.func, test.ref, 0xffffffff);
+ // Transparent color unless color-coding of overdraw is enabled.
+ Float4 color =
+ PremultipliedColor(settings_->show_overdraw_feedback ? test.color : 0);
+ gl_->Uniform4fv(program->color_location(), 1, color.data);
+ gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
+
+ if (query) {
+ gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
+ context_support_->SignalQuery(
+ query,
+ base::Bind(overdraw_feedback_callback, query, test.multiplier));
+ }
+ }
+}
+
+void GLRenderer::ProcessOverdrawFeedback(std::vector<int>* overdraw,
+ size_t num_expected_results,
+ unsigned query,
+ int multiplier) {
+ unsigned result = 0;
+ if (query) {
+ gl_->GetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
+ DCHECK_LE(result, 1u);
+ gl_->DeleteQueriesEXT(1, &query);
+ }
+
+ // Apply multiplier to get the amount of overdraw.
+ overdraw->push_back(result * multiplier);
+
+ // Return early if we are expecting more results.
+ if (overdraw->size() < num_expected_results)
+ return;
+
+ // Report the maximum amount of overdraw.
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.overdraw"), "GPU Overdraw",
+ *std::max_element(overdraw->begin(), overdraw->end()));
+}
+
} // namespace cc
« 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