diff options
| author | Romain Guy <romainguy@google.com> | 2013-05-03 14:24:16 -0700 |
|---|---|---|
| committer | Romain Guy <romainguy@google.com> | 2013-05-03 17:08:20 -0700 |
| commit | 78dd96d5af20f489f0e8b288617d57774ec284f7 (patch) | |
| tree | 742b702647ae37e196021707fa45cbb8568353e1 /core/java | |
| parent | 927bc7d72048ac90e3b95845699efb479b5589b4 (diff) | |
| download | frameworks_base-78dd96d5af20f489f0e8b288617d57774ec284f7.zip frameworks_base-78dd96d5af20f489f0e8b288617d57774ec284f7.tar.gz frameworks_base-78dd96d5af20f489f0e8b288617d57774ec284f7.tar.bz2 | |
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
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/view/GLES20Canvas.java | 12 | ||||
| -rw-r--r-- | core/java/android/view/GLES20RenderLayer.java | 7 | ||||
| -rw-r--r-- | core/java/android/view/GLES20TextureLayer.java | 5 | ||||
| -rw-r--r-- | core/java/android/view/HardwareLayer.java | 12 | ||||
| -rw-r--r-- | core/java/android/view/HardwareRenderer.java | 137 |
5 files changed, 155 insertions, 18 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 21a03d8..cc7d948 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -274,6 +274,18 @@ class GLES20Canvas extends HardwareCanvas { private static native int nGetStencilSize(); + void setCountOverdrawEnabled(boolean enabled) { + nSetCountOverdrawEnabled(mRenderer, enabled); + } + + static native void nSetCountOverdrawEnabled(int renderer, boolean enabled); + + float getOverdraw() { + return nGetOverdraw(mRenderer); + } + + static native float nGetOverdraw(int renderer); + /////////////////////////////////////////////////////////////////////////// // Functor /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java index 685dc70..68ba77c 100644 --- a/core/java/android/view/GLES20RenderLayer.java +++ b/core/java/android/view/GLES20RenderLayer.java @@ -100,12 +100,17 @@ class GLES20RenderLayer extends GLES20Layer { @Override HardwareCanvas start(Canvas currentCanvas) { + return start(currentCanvas, null); + } + + @Override + HardwareCanvas start(Canvas currentCanvas, Rect dirty) { if (currentCanvas instanceof GLES20Canvas) { ((GLES20Canvas) currentCanvas).interrupt(); } HardwareCanvas canvas = getCanvas(); canvas.setViewport(mWidth, mHeight); - canvas.onPreDraw(null); + canvas.onPreDraw(dirty); return canvas; } diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java index e863e49..a4cc630 100644 --- a/core/java/android/view/GLES20TextureLayer.java +++ b/core/java/android/view/GLES20TextureLayer.java @@ -63,6 +63,11 @@ class GLES20TextureLayer extends GLES20Layer { } @Override + HardwareCanvas start(Canvas currentCanvas, Rect dirty) { + return null; + } + + @Override void end(Canvas currentCanvas) { } diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java index 18b838b..23383d9 100644 --- a/core/java/android/view/HardwareLayer.java +++ b/core/java/android/view/HardwareLayer.java @@ -158,14 +158,22 @@ abstract class HardwareLayer { /** * This must be invoked before drawing onto this layer. * - * @param currentCanvas + * @param currentCanvas The canvas whose rendering needs to be interrupted */ abstract HardwareCanvas start(Canvas currentCanvas); /** + * This must be invoked before drawing onto this layer. + * + * @param dirty The dirty area to repaint + * @param currentCanvas The canvas whose rendering needs to be interrupted + */ + abstract HardwareCanvas start(Canvas currentCanvas, Rect dirty); + + /** * This must be invoked after drawing onto this layer. * - * @param currentCanvas + * @param currentCanvas The canvas whose rendering needs to be resumed */ abstract void end(Canvas currentCanvas); diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index c7b1253..e8c1653 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -17,6 +17,7 @@ package android.view; import android.content.ComponentCallbacks2; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.SurfaceTexture; @@ -45,7 +46,6 @@ import javax.microedition.khronos.opengles.GL; import java.io.File; import java.io.PrintWriter; -import java.util.Arrays; import java.util.concurrent.locks.ReentrantLock; import static javax.microedition.khronos.egl.EGL10.*; @@ -165,15 +165,32 @@ public abstract class HardwareRenderer { "debug.hwui.show_layers_updates"; /** - * Turn on to show overdraw level. + * Controls overdraw debugging. * * Possible values: - * "true", to enable overdraw debugging * "false", to disable overdraw debugging + * "show", to show overdraw areas on screen + * "count", to display an overdraw counter * * @hide */ - public static final String DEBUG_SHOW_OVERDRAW_PROPERTY = "debug.hwui.show_overdraw"; + public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw"; + + /** + * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this + * value, overdraw will be shown on screen by coloring pixels. + * + * @hide + */ + public static final String OVERDRAW_PROPERTY_SHOW = "show"; + + /** + * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this + * value, an overdraw counter will be shown on screen. + * + * @hide + */ + public static final String OVERDRAW_PROPERTY_COUNT = "count"; /** * Turn on to debug non-rectangular clip operations. @@ -765,6 +782,17 @@ public abstract class HardwareRenderer { private static final int PROFILE_DRAW_THRESHOLD_STROKE_WIDTH = 2; private static final int PROFILE_DRAW_DP_PER_MS = 7; + private static final String[] VISUALIZERS = { + PROFILE_PROPERTY_VISUALIZE_BARS, + PROFILE_PROPERTY_VISUALIZE_LINES + }; + + private static final String[] OVERDRAW = { + OVERDRAW_PROPERTY_SHOW, + OVERDRAW_PROPERTY_COUNT + }; + private static final int OVERDRAW_TYPE_COUNT = 1; + static EGL10 sEgl; static EGLDisplay sEglDisplay; static EGLConfig sEglConfig; @@ -810,7 +838,9 @@ public abstract class HardwareRenderer { Paint mProfilePaint; boolean mDebugDirtyRegions; - boolean mShowOverdraw; + int mDebugOverdraw = -1; + HardwareLayer mDebugOverdrawLayer; + Paint mDebugOverdrawPaint; final int mGlVersion; final boolean mTranslucent; @@ -829,18 +859,13 @@ public abstract class HardwareRenderer { loadSystemProperties(null); } - private static final String[] VISUALIZERS = { - PROFILE_PROPERTY_VISUALIZE_BARS, - PROFILE_PROPERTY_VISUALIZE_LINES - }; - @Override boolean loadSystemProperties(Surface surface) { boolean value; boolean changed = false; String profiling = SystemProperties.get(PROFILE_PROPERTY); - int graphType = Arrays.binarySearch(VISUALIZERS, profiling); + int graphType = search(VISUALIZERS, profiling); value = graphType >= 0; if (graphType != mProfileVisualizerType) { @@ -897,11 +922,19 @@ public abstract class HardwareRenderer { } } - value = SystemProperties.getBoolean( - HardwareRenderer.DEBUG_SHOW_OVERDRAW_PROPERTY, false); - if (value != mShowOverdraw) { + String overdraw = SystemProperties.get(HardwareRenderer.DEBUG_OVERDRAW_PROPERTY); + int debugOverdraw = search(OVERDRAW, overdraw); + if (debugOverdraw != mDebugOverdraw) { changed = true; - mShowOverdraw = value; + mDebugOverdraw = debugOverdraw; + + if (mDebugOverdraw != OVERDRAW_TYPE_COUNT) { + if (mDebugOverdrawLayer != null) { + mDebugOverdrawLayer.destroy(); + mDebugOverdrawLayer = null; + mDebugOverdrawPaint = null; + } + } } if (nLoadProperties()) { @@ -911,6 +944,13 @@ public abstract class HardwareRenderer { return changed; } + private static int search(String[] values, String value) { + for (int i = 0; i < values.length; i++) { + if (values[i].equals(value)) return i; + } + return -1; + } + @Override void dumpGfxInfo(PrintWriter pw) { if (mProfileEnabled) { @@ -1392,6 +1432,8 @@ public abstract class HardwareRenderer { canvas.restoreToCount(saveCount); view.mRecreateDisplayList = false; + debugOverdraw(attachInfo, dirty, canvas, displayList); + mFrameCount++; debugDirtyRegions(dirty, canvas); @@ -1411,6 +1453,61 @@ public abstract class HardwareRenderer { } } + abstract void countOverdraw(HardwareCanvas canvas); + abstract float getOverdraw(HardwareCanvas canvas); + + private void debugOverdraw(View.AttachInfo attachInfo, Rect dirty, + HardwareCanvas canvas, DisplayList displayList) { + + if (mDebugOverdraw == OVERDRAW_TYPE_COUNT) { + // TODO: Use an alpha layer allocated from a GraphicBuffer + // The alpha format will help with rendering performance and + // the GraphicBuffer will let us skip the read pixels step + if (mDebugOverdrawLayer == null) { + mDebugOverdrawLayer = createHardwareLayer(mWidth, mHeight, true); + } else if (mDebugOverdrawLayer.getWidth() != mWidth || + mDebugOverdrawLayer.getHeight() != mHeight) { + mDebugOverdrawLayer.resize(mWidth, mHeight); + } + + if (!mDebugOverdrawLayer.isValid()) { + mDebugOverdraw = -1; + return; + } + + HardwareCanvas layerCanvas = mDebugOverdrawLayer.start(canvas, dirty); + countOverdraw(layerCanvas); + final int restoreCount = layerCanvas.save(); + layerCanvas.drawDisplayList(displayList, null, DisplayList.FLAG_CLIP_CHILDREN); + layerCanvas.restoreToCount(restoreCount); + mDebugOverdrawLayer.end(canvas); + + float overdraw = getOverdraw(layerCanvas); + DisplayMetrics metrics = attachInfo.mRootView.getResources().getDisplayMetrics(); + + drawOverdrawCounter(canvas, overdraw, metrics.density); + } + } + + private void drawOverdrawCounter(HardwareCanvas canvas, float overdraw, float density) { + final String text = String.format("%.2fx", overdraw); + final Paint paint = setupPaint(density); + // HSBtoColor will clamp the values in the 0..1 range + paint.setColor(Color.HSBtoColor(0.28f - 0.28f * overdraw / 3.5f, 0.8f, 1.0f)); + + canvas.drawText(text, density * 4.0f, mHeight - paint.getFontMetrics().bottom, paint); + } + + private Paint setupPaint(float density) { + if (mDebugOverdrawPaint == null) { + mDebugOverdrawPaint = new Paint(); + mDebugOverdrawPaint.setAntiAlias(true); + mDebugOverdrawPaint.setShadowLayer(density * 3.0f, 0.0f, 0.0f, 0xff000000); + mDebugOverdrawPaint.setTextSize(density * 20.0f); + } + return mDebugOverdrawPaint; + } + private DisplayList buildDisplayList(View view, HardwareCanvas canvas) { view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED) == View.PFLAG_INVALIDATED; @@ -2019,6 +2116,16 @@ public abstract class HardwareRenderer { } @Override + void countOverdraw(HardwareCanvas canvas) { + ((GLES20Canvas) canvas).setCountOverdrawEnabled(true); + } + + @Override + float getOverdraw(HardwareCanvas canvas) { + return ((GLES20Canvas) canvas).getOverdraw(); + } + + @Override public SurfaceTexture createSurfaceTexture(HardwareLayer layer) { return ((GLES20TextureLayer) layer).getSurfaceTexture(); } |
