Add an on-screen overdraw counter
The counter can be enabled by setting the system property called
debug.hwui.overdraw to the string "count". If the string is set
to "show", overdraw will be highlighted on screen instead of
printing out a simple counter.
Change-Id: I9a9c970d54bffab43138bbb7682f6c04bc2c40bd
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index c60848c..f08b5ca 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -152,7 +152,7 @@
if (property_get(PROPERTY_DEBUG_OVERDRAW, property, NULL) > 0) {
INIT_LOGD(" Overdraw debug enabled: %s", property);
- debugOverdraw = !strcmp(property, "true");
+ debugOverdraw = !strcmp(property, "show");
} else {
debugOverdraw = false;
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 025e9f8..1447eb7 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <SkCanvas.h>
-#include <SkPathMeasure.h>
#include <SkTypeface.h>
#include <utils/Log.h>
@@ -120,6 +119,7 @@
mFirstSnapshot = new Snapshot;
mFrameStarted = false;
+ mCountOverdraw = false;
mScissorOptimizationDisabled = false;
}
@@ -222,6 +222,7 @@
status_t OpenGLRenderer::prepareDirty(float left, float top,
float right, float bottom, bool opaque) {
+
setupFrameState(left, top, right, bottom, opaque);
// Layer renderers will start the frame immediately
@@ -253,7 +254,7 @@
}
status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
- if (!opaque) {
+ if (!opaque || mCountOverdraw) {
mCaches.enableScissor();
mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
glClear(GL_COLOR_BUFFER_BIT);
@@ -335,6 +336,10 @@
#endif
}
+ if (mCountOverdraw) {
+ countOverdraw();
+ }
+
mFrameStarted = false;
}
@@ -524,6 +529,21 @@
}
}
+void OpenGLRenderer::countOverdraw() {
+ size_t count = mWidth * mHeight;
+ uint32_t* buffer = new uint32_t[count];
+ glReadPixels(0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, &buffer[0]);
+
+ size_t total = 0;
+ for (size_t i = 0; i < count; i++) {
+ total += buffer[i] & 0xff;
+ }
+
+ mOverdraw = total / float(count);
+
+ delete[] buffer;
+}
+
///////////////////////////////////////////////////////////////////////////////
// Layers
///////////////////////////////////////////////////////////////////////////////
@@ -1656,6 +1676,8 @@
mDescription.hasDebugHighlight = !mCaches.debugOverdraw &&
mCaches.debugStencilClip == Caches::kStencilShowHighlight &&
mCaches.stencil.isTestEnabled();
+
+ mDescription.emulateStencil = mCountOverdraw;
}
void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
@@ -3546,6 +3568,19 @@
void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
ProgramDescription& description, bool swapSrcDst) {
+ if (mCountOverdraw) {
+ if (!mCaches.blend) glEnable(GL_BLEND);
+ if (mCaches.lastSrcMode != GL_ONE || mCaches.lastDstMode != GL_ONE) {
+ glBlendFunc(GL_ONE, GL_ONE);
+ }
+
+ mCaches.blend = true;
+ mCaches.lastSrcMode = GL_ONE;
+ mCaches.lastDstMode = GL_ONE;
+
+ return;
+ }
+
blend = blend || mode != SkXfermode::kSrcOver_Mode;
if (blend) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 640c7db..df275d7 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -192,6 +192,14 @@
*/
virtual void resume();
+ ANDROID_API void setCountOverdrawEnabled(bool enabled) {
+ mCountOverdraw = enabled;
+ }
+
+ ANDROID_API float getOverdraw() {
+ return mCountOverdraw ? mOverdraw : 0.0f;
+ }
+
ANDROID_API status_t invokeFunctors(Rect& dirty);
ANDROID_API void detachFunctor(Functor* functor);
ANDROID_API void attachFunctor(Functor* functor);
@@ -981,6 +989,7 @@
void debugOverdraw(bool enable, bool clear);
void renderOverdraw();
+ void countOverdraw();
/**
* Should be invoked every time the glScissor is modified.
@@ -1072,6 +1081,12 @@
// No-ops start/endTiling when set
bool mSuppressTiling;
+
+ // If true, this renderer will setup drawing to emulate
+ // an increment stencil buffer in the color buffer
+ bool mCountOverdraw;
+ float mOverdraw;
+
// Optional name of the renderer
String8 mName;
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index a252209..dd1aaa2 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -85,6 +85,7 @@
#define PROGRAM_HAS_COLORS 42
#define PROGRAM_HAS_DEBUG_HIGHLIGHT 43
+#define PROGRAM_EMULATE_STENCIL 44
///////////////////////////////////////////////////////////////////////////////
// Types
@@ -163,6 +164,7 @@
float gamma;
bool hasDebugHighlight;
+ bool emulateStencil;
/**
* Resets this description. All fields are reset back to the default
@@ -275,6 +277,7 @@
if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT;
if (hasColors) key |= programid(0x1) << PROGRAM_HAS_COLORS;
if (hasDebugHighlight) key |= programid(0x1) << PROGRAM_HAS_DEBUG_HIGHLIGHT;
+ if (emulateStencil) key |= programid(0x1) << PROGRAM_EMULATE_STENCIL;
return key;
}
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 8eb85e5..367294c 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -342,6 +342,12 @@
};
const char* gFS_Main_DebugHighlight =
" gl_FragColor.rgb = vec3(0.0, gl_FragColor.a, 0.0);\n";
+const char* gFS_Main_EmulateStencil =
+ " gl_FragColor.rgba = vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 1.0);\n"
+ " return;\n"
+ " /*\n";
+const char* gFS_Footer_EmulateStencil =
+ " */\n";
const char* gFS_Footer =
"}\n\n";
@@ -603,7 +609,8 @@
// Optimization for common cases
if (!description.isAA && !blendFramebuffer && !description.hasColors &&
description.colorOp == ProgramDescription::kColorNone &&
- !description.isPoint && !description.hasDebugHighlight) {
+ !description.isPoint && !description.hasDebugHighlight &&
+ !description.emulateStencil) {
bool fast = false;
const bool noShader = !description.hasGradient && !description.hasBitmap;
@@ -683,6 +690,9 @@
// Begin the shader
shader.append(gFS_Main); {
+ if (description.emulateStencil) {
+ shader.append(gFS_Main_EmulateStencil);
+ }
// Stores the result in fragColor directly
if (description.hasTexture || description.hasExternalTexture) {
if (description.hasAlpha8Texture) {
@@ -757,6 +767,9 @@
shader.append(gFS_Main_DebugHighlight);
}
}
+ if (description.emulateStencil) {
+ shader.append(gFS_Footer_EmulateStencil);
+ }
// End the shader
shader.append(gFS_Footer);
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 87ac845..7c68b5b 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -71,9 +71,9 @@
/**
* Used to enable/disable overdraw debugging. The accepted values are
- * "true" and "false". The default value is "false".
+ * "show", "count" and "false". The default value is "false".
*/
-#define PROPERTY_DEBUG_OVERDRAW "debug.hwui.show_overdraw"
+#define PROPERTY_DEBUG_OVERDRAW "debug.hwui.overdraw"
/**
* Used to enable/disable non-rectangular clipping debugging.
diff --git a/libs/hwui/thread/TaskManager.h b/libs/hwui/thread/TaskManager.h
index 477314b..f2a216f 100644
--- a/libs/hwui/thread/TaskManager.h
+++ b/libs/hwui/thread/TaskManager.h
@@ -43,7 +43,7 @@
/**
* Returns true if this task manager can run tasks,
* false otherwise. This method will typically return
- * true on a single CPU core device.
+ * false on a single CPU core device.
*/
bool canRunTasks() const;