Loading core/java/android/view/GLES20Canvas.java +12 −0 Original line number Diff line number Diff line Loading @@ -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 /////////////////////////////////////////////////////////////////////////// Loading core/java/android/view/GLES20RenderLayer.java +6 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading core/java/android/view/GLES20TextureLayer.java +5 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,11 @@ class GLES20TextureLayer extends GLES20Layer { return null; } @Override HardwareCanvas start(Canvas currentCanvas, Rect dirty) { return null; } @Override void end(Canvas currentCanvas) { } Loading core/java/android/view/HardwareLayer.java +10 −2 Original line number Diff line number Diff line Loading @@ -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); Loading core/java/android/view/HardwareRenderer.java +122 −15 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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.*; Loading Loading @@ -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. Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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()) { Loading @@ -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) { Loading Loading @@ -1392,6 +1432,8 @@ public abstract class HardwareRenderer { canvas.restoreToCount(saveCount); view.mRecreateDisplayList = false; debugOverdraw(attachInfo, dirty, canvas, displayList); mFrameCount++; debugDirtyRegions(dirty, canvas); Loading @@ -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; Loading Loading @@ -2018,6 +2115,16 @@ public abstract class HardwareRenderer { return new GLES20RenderLayer(width, height, isOpaque); } @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(); Loading Loading
core/java/android/view/GLES20Canvas.java +12 −0 Original line number Diff line number Diff line Loading @@ -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 /////////////////////////////////////////////////////////////////////////// Loading
core/java/android/view/GLES20RenderLayer.java +6 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading
core/java/android/view/GLES20TextureLayer.java +5 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,11 @@ class GLES20TextureLayer extends GLES20Layer { return null; } @Override HardwareCanvas start(Canvas currentCanvas, Rect dirty) { return null; } @Override void end(Canvas currentCanvas) { } Loading
core/java/android/view/HardwareLayer.java +10 −2 Original line number Diff line number Diff line Loading @@ -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); Loading
core/java/android/view/HardwareRenderer.java +122 −15 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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.*; Loading Loading @@ -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. Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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()) { Loading @@ -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) { Loading Loading @@ -1392,6 +1432,8 @@ public abstract class HardwareRenderer { canvas.restoreToCount(saveCount); view.mRecreateDisplayList = false; debugOverdraw(attachInfo, dirty, canvas, displayList); mFrameCount++; debugDirtyRegions(dirty, canvas); Loading @@ -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; Loading Loading @@ -2018,6 +2115,16 @@ public abstract class HardwareRenderer { return new GLES20RenderLayer(width, height, isOpaque); } @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(); Loading