diff options
| -rw-r--r-- | core/java/android/view/HardwareRenderer.java | 82 |
1 files changed, 64 insertions, 18 deletions
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 71d55f7a476d..d46dacc2e55d 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -42,10 +42,23 @@ public abstract class HardwareRenderer { /** * Turn on to only refresh the parts of the screen that need updating. + * When turned on the property defined by {@link #RENDER_DIRTY_REGIONS_PROPERTY} + * must also have the value "true". */ public static final boolean RENDER_DIRTY_REGIONS = true; /** + * System property used to enable or disable dirty regions invalidation. + * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true. + * The default value of this property is assumed to be true. + * + * Possible values: + * "true", to enable partial invalidates + * "false", to disable partial invalidates + */ + static final String RENDER_DIRTY_REGIONS_PROPERTY = "hwui.render_dirty_regions"; + + /** * Turn on to draw dirty regions every other frame. */ private static final boolean DEBUG_DIRTY_REGION = false; @@ -113,8 +126,23 @@ public abstract class HardwareRenderer { */ abstract void setup(int width, int height); + /** + * Interface used to receive callbacks whenever a view is drawn by + * a hardware renderer instance. + */ interface HardwareDrawCallbacks { + /** + * Invoked before a view is drawn by a hardware renderer. + * + * @param canvas The Canvas used to render the view. + */ void onHardwarePreDraw(Canvas canvas); + + /** + * Invoked after a view is drawn by a hardware renderer. + * + * @param canvas The Canvas used to render the view. + */ void onHardwarePostDraw(Canvas canvas); } @@ -250,6 +278,7 @@ public abstract class HardwareRenderer { int mFrameCount; Paint mDebugPaint; + boolean mDirtyRegions; final int mGlVersion; final boolean mTranslucent; @@ -259,6 +288,9 @@ public abstract class HardwareRenderer { GlRenderer(int glVersion, boolean translucent) { mGlVersion = glVersion; mTranslucent = translucent; + final String dirtyProperty = System.getProperty(RENDER_DIRTY_REGIONS_PROPERTY, "true"); + //noinspection PointlessBooleanExpression,ConstantConditions + mDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty); } /** @@ -388,10 +420,24 @@ public abstract class HardwareRenderer { // We can now initialize EGL for that display int[] version = new int[2]; if (!sEgl.eglInitialize(sEglDisplay, version)) { - throw new RuntimeException("eglInitialize failed " - + getEGLErrorString(sEgl.eglGetError())); + throw new RuntimeException("eglInitialize failed " + + getEGLErrorString(sEgl.eglGetError())); } + sEglConfig = getConfigChooser(mGlVersion).chooseConfig(sEgl, sEglDisplay); + if (sEglConfig == null) { + // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without + if (mDirtyRegions) { + mDirtyRegions = false; + + sEglConfig = getConfigChooser(mGlVersion).chooseConfig(sEgl, sEglDisplay); + if (sEglConfig == null) { + throw new RuntimeException("eglConfig not initialized"); + } + } else { + throw new RuntimeException("eglConfig not initialized"); + } + } /* * Create an EGL context. We want to do this as rarely as we can, because an @@ -409,7 +455,7 @@ public abstract class HardwareRenderer { throw new RuntimeException("eglDisplay not initialized"); } if (sEglConfig == null) { - throw new RuntimeException("mEglConfig not initialized"); + throw new RuntimeException("eglConfig not initialized"); } if (Thread.currentThread() != sEglThread) { throw new IllegalStateException("HardwareRenderer cannot be used " @@ -452,7 +498,7 @@ public abstract class HardwareRenderer { + getEGLErrorString(sEgl.eglGetError())); } - if (RENDER_DIRTY_REGIONS) { + if (mDirtyRegions) { if (!GLES20Canvas.preserveBackBuffer()) { Log.w(LOG_TAG, "Backbuffer cannot be preserved"); } @@ -518,15 +564,14 @@ public abstract class HardwareRenderer { * @return An {@link android.view.HardwareRenderer.GlRenderer.EglConfigChooser}. */ EglConfigChooser getConfigChooser(int glVersion) { - return new ComponentSizeChooser(glVersion, 8, 8, 8, 8, 0, 0); + return new ComponentSizeChooser(glVersion, 8, 8, 8, 8, 0, 0, mDirtyRegions); } @Override void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) { if (canDraw()) { - //noinspection PointlessBooleanExpression,ConstantConditions - if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { + if (!mDirtyRegions) { dirty = null; } @@ -676,16 +721,16 @@ public abstract class HardwareRenderer { static class ComponentSizeChooser extends EglConfigChooser { private int[] mValue; - private int mRedSize; - private int mGreenSize; - private int mBlueSize; - private int mAlphaSize; - private int mDepthSize; - private int mStencilSize; + private final int mRedSize; + private final int mGreenSize; + private final int mBlueSize; + private final int mAlphaSize; + private final int mDepthSize; + private final int mStencilSize; + private final boolean mDirtyRegions; ComponentSizeChooser(int glVersion, int redSize, int greenSize, int blueSize, - int alphaSize, int depthSize, int stencilSize) { - //noinspection PointlessBitwiseExpression + int alphaSize, int depthSize, int stencilSize, boolean dirtyRegions) { super(glVersion, new int[] { EGL10.EGL_RED_SIZE, redSize, EGL10.EGL_GREEN_SIZE, greenSize, @@ -694,7 +739,7 @@ public abstract class HardwareRenderer { EGL10.EGL_DEPTH_SIZE, depthSize, EGL10.EGL_STENCIL_SIZE, stencilSize, EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT | - (RENDER_DIRTY_REGIONS ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0), + (dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0), EGL10.EGL_NONE }); mValue = new int[1]; mRedSize = redSize; @@ -703,7 +748,8 @@ public abstract class HardwareRenderer { mAlphaSize = alphaSize; mDepthSize = depthSize; mStencilSize = stencilSize; - } + mDirtyRegions = dirtyRegions; + } @Override EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) { @@ -716,7 +762,7 @@ public abstract class HardwareRenderer { int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0); int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0); boolean backBuffer; - if (RENDER_DIRTY_REGIONS) { + if (mDirtyRegions) { int surfaceType = findConfigAttrib(egl, display, config, EGL_SURFACE_TYPE, 0); backBuffer = (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) != 0; |