Loading core/java/android/view/HardwareRenderer.java +64 −18 Original line number Original line Diff line number Diff line Loading @@ -42,9 +42,22 @@ public abstract class HardwareRenderer { /** /** * Turn on to only refresh the parts of the screen that need updating. * 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; 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. * Turn on to draw dirty regions every other frame. */ */ Loading Loading @@ -113,8 +126,23 @@ public abstract class HardwareRenderer { */ */ abstract void setup(int width, int height); abstract void setup(int width, int height); /** * Interface used to receive callbacks whenever a view is drawn by * a hardware renderer instance. */ interface HardwareDrawCallbacks { 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); 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); void onHardwarePostDraw(Canvas canvas); } } Loading Loading @@ -250,6 +278,7 @@ public abstract class HardwareRenderer { int mFrameCount; int mFrameCount; Paint mDebugPaint; Paint mDebugPaint; boolean mDirtyRegions; final int mGlVersion; final int mGlVersion; final boolean mTranslucent; final boolean mTranslucent; Loading @@ -259,6 +288,9 @@ public abstract class HardwareRenderer { GlRenderer(int glVersion, boolean translucent) { GlRenderer(int glVersion, boolean translucent) { mGlVersion = glVersion; mGlVersion = glVersion; mTranslucent = translucent; mTranslucent = translucent; final String dirtyProperty = System.getProperty(RENDER_DIRTY_REGIONS_PROPERTY, "true"); //noinspection PointlessBooleanExpression,ConstantConditions mDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty); } } /** /** Loading Loading @@ -388,10 +420,24 @@ public abstract class HardwareRenderer { // We can now initialize EGL for that display // We can now initialize EGL for that display int[] version = new int[2]; int[] version = new int[2]; if (!sEgl.eglInitialize(sEglDisplay, version)) { if (!sEgl.eglInitialize(sEglDisplay, version)) { throw new RuntimeException("eglInitialize failed " throw new RuntimeException("eglInitialize failed " + + getEGLErrorString(sEgl.eglGetError())); getEGLErrorString(sEgl.eglGetError())); } } sEglConfig = getConfigChooser(mGlVersion).chooseConfig(sEgl, sEglDisplay); 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 * Create an EGL context. We want to do this as rarely as we can, because an Loading @@ -409,7 +455,7 @@ public abstract class HardwareRenderer { throw new RuntimeException("eglDisplay not initialized"); throw new RuntimeException("eglDisplay not initialized"); } } if (sEglConfig == null) { if (sEglConfig == null) { throw new RuntimeException("mEglConfig not initialized"); throw new RuntimeException("eglConfig not initialized"); } } if (Thread.currentThread() != sEglThread) { if (Thread.currentThread() != sEglThread) { throw new IllegalStateException("HardwareRenderer cannot be used " throw new IllegalStateException("HardwareRenderer cannot be used " Loading Loading @@ -452,7 +498,7 @@ public abstract class HardwareRenderer { + getEGLErrorString(sEgl.eglGetError())); + getEGLErrorString(sEgl.eglGetError())); } } if (RENDER_DIRTY_REGIONS) { if (mDirtyRegions) { if (!GLES20Canvas.preserveBackBuffer()) { if (!GLES20Canvas.preserveBackBuffer()) { Log.w(LOG_TAG, "Backbuffer cannot be preserved"); Log.w(LOG_TAG, "Backbuffer cannot be preserved"); } } Loading Loading @@ -518,15 +564,14 @@ public abstract class HardwareRenderer { * @return An {@link android.view.HardwareRenderer.GlRenderer.EglConfigChooser}. * @return An {@link android.view.HardwareRenderer.GlRenderer.EglConfigChooser}. */ */ EglConfigChooser getConfigChooser(int glVersion) { 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 @Override void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) { Rect dirty) { if (canDraw()) { if (canDraw()) { //noinspection PointlessBooleanExpression,ConstantConditions if (!mDirtyRegions) { if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { dirty = null; dirty = null; } } Loading Loading @@ -676,16 +721,16 @@ public abstract class HardwareRenderer { static class ComponentSizeChooser extends EglConfigChooser { static class ComponentSizeChooser extends EglConfigChooser { private int[] mValue; private int[] mValue; private int mRedSize; private final int mRedSize; private int mGreenSize; private final int mGreenSize; private int mBlueSize; private final int mBlueSize; private int mAlphaSize; private final int mAlphaSize; private int mDepthSize; private final int mDepthSize; private int mStencilSize; private final int mStencilSize; private final boolean mDirtyRegions; ComponentSizeChooser(int glVersion, int redSize, int greenSize, int blueSize, ComponentSizeChooser(int glVersion, int redSize, int greenSize, int blueSize, int alphaSize, int depthSize, int stencilSize) { int alphaSize, int depthSize, int stencilSize, boolean dirtyRegions) { //noinspection PointlessBitwiseExpression super(glVersion, new int[] { super(glVersion, new int[] { EGL10.EGL_RED_SIZE, redSize, EGL10.EGL_RED_SIZE, redSize, EGL10.EGL_GREEN_SIZE, greenSize, EGL10.EGL_GREEN_SIZE, greenSize, Loading @@ -694,7 +739,7 @@ public abstract class HardwareRenderer { EGL10.EGL_DEPTH_SIZE, depthSize, EGL10.EGL_DEPTH_SIZE, depthSize, EGL10.EGL_STENCIL_SIZE, stencilSize, EGL10.EGL_STENCIL_SIZE, stencilSize, EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT | 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 }); EGL10.EGL_NONE }); mValue = new int[1]; mValue = new int[1]; mRedSize = redSize; mRedSize = redSize; Loading @@ -703,6 +748,7 @@ public abstract class HardwareRenderer { mAlphaSize = alphaSize; mAlphaSize = alphaSize; mDepthSize = depthSize; mDepthSize = depthSize; mStencilSize = stencilSize; mStencilSize = stencilSize; mDirtyRegions = dirtyRegions; } } @Override @Override Loading @@ -716,7 +762,7 @@ public abstract class HardwareRenderer { int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0); int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0); int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0); int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0); boolean backBuffer; boolean backBuffer; if (RENDER_DIRTY_REGIONS) { if (mDirtyRegions) { int surfaceType = findConfigAttrib(egl, display, config, int surfaceType = findConfigAttrib(egl, display, config, EGL_SURFACE_TYPE, 0); EGL_SURFACE_TYPE, 0); backBuffer = (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) != 0; backBuffer = (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) != 0; Loading Loading
core/java/android/view/HardwareRenderer.java +64 −18 Original line number Original line Diff line number Diff line Loading @@ -42,9 +42,22 @@ public abstract class HardwareRenderer { /** /** * Turn on to only refresh the parts of the screen that need updating. * 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; 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. * Turn on to draw dirty regions every other frame. */ */ Loading Loading @@ -113,8 +126,23 @@ public abstract class HardwareRenderer { */ */ abstract void setup(int width, int height); abstract void setup(int width, int height); /** * Interface used to receive callbacks whenever a view is drawn by * a hardware renderer instance. */ interface HardwareDrawCallbacks { 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); 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); void onHardwarePostDraw(Canvas canvas); } } Loading Loading @@ -250,6 +278,7 @@ public abstract class HardwareRenderer { int mFrameCount; int mFrameCount; Paint mDebugPaint; Paint mDebugPaint; boolean mDirtyRegions; final int mGlVersion; final int mGlVersion; final boolean mTranslucent; final boolean mTranslucent; Loading @@ -259,6 +288,9 @@ public abstract class HardwareRenderer { GlRenderer(int glVersion, boolean translucent) { GlRenderer(int glVersion, boolean translucent) { mGlVersion = glVersion; mGlVersion = glVersion; mTranslucent = translucent; mTranslucent = translucent; final String dirtyProperty = System.getProperty(RENDER_DIRTY_REGIONS_PROPERTY, "true"); //noinspection PointlessBooleanExpression,ConstantConditions mDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty); } } /** /** Loading Loading @@ -388,10 +420,24 @@ public abstract class HardwareRenderer { // We can now initialize EGL for that display // We can now initialize EGL for that display int[] version = new int[2]; int[] version = new int[2]; if (!sEgl.eglInitialize(sEglDisplay, version)) { if (!sEgl.eglInitialize(sEglDisplay, version)) { throw new RuntimeException("eglInitialize failed " throw new RuntimeException("eglInitialize failed " + + getEGLErrorString(sEgl.eglGetError())); getEGLErrorString(sEgl.eglGetError())); } } sEglConfig = getConfigChooser(mGlVersion).chooseConfig(sEgl, sEglDisplay); 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 * Create an EGL context. We want to do this as rarely as we can, because an Loading @@ -409,7 +455,7 @@ public abstract class HardwareRenderer { throw new RuntimeException("eglDisplay not initialized"); throw new RuntimeException("eglDisplay not initialized"); } } if (sEglConfig == null) { if (sEglConfig == null) { throw new RuntimeException("mEglConfig not initialized"); throw new RuntimeException("eglConfig not initialized"); } } if (Thread.currentThread() != sEglThread) { if (Thread.currentThread() != sEglThread) { throw new IllegalStateException("HardwareRenderer cannot be used " throw new IllegalStateException("HardwareRenderer cannot be used " Loading Loading @@ -452,7 +498,7 @@ public abstract class HardwareRenderer { + getEGLErrorString(sEgl.eglGetError())); + getEGLErrorString(sEgl.eglGetError())); } } if (RENDER_DIRTY_REGIONS) { if (mDirtyRegions) { if (!GLES20Canvas.preserveBackBuffer()) { if (!GLES20Canvas.preserveBackBuffer()) { Log.w(LOG_TAG, "Backbuffer cannot be preserved"); Log.w(LOG_TAG, "Backbuffer cannot be preserved"); } } Loading Loading @@ -518,15 +564,14 @@ public abstract class HardwareRenderer { * @return An {@link android.view.HardwareRenderer.GlRenderer.EglConfigChooser}. * @return An {@link android.view.HardwareRenderer.GlRenderer.EglConfigChooser}. */ */ EglConfigChooser getConfigChooser(int glVersion) { 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 @Override void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) { Rect dirty) { if (canDraw()) { if (canDraw()) { //noinspection PointlessBooleanExpression,ConstantConditions if (!mDirtyRegions) { if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { dirty = null; dirty = null; } } Loading Loading @@ -676,16 +721,16 @@ public abstract class HardwareRenderer { static class ComponentSizeChooser extends EglConfigChooser { static class ComponentSizeChooser extends EglConfigChooser { private int[] mValue; private int[] mValue; private int mRedSize; private final int mRedSize; private int mGreenSize; private final int mGreenSize; private int mBlueSize; private final int mBlueSize; private int mAlphaSize; private final int mAlphaSize; private int mDepthSize; private final int mDepthSize; private int mStencilSize; private final int mStencilSize; private final boolean mDirtyRegions; ComponentSizeChooser(int glVersion, int redSize, int greenSize, int blueSize, ComponentSizeChooser(int glVersion, int redSize, int greenSize, int blueSize, int alphaSize, int depthSize, int stencilSize) { int alphaSize, int depthSize, int stencilSize, boolean dirtyRegions) { //noinspection PointlessBitwiseExpression super(glVersion, new int[] { super(glVersion, new int[] { EGL10.EGL_RED_SIZE, redSize, EGL10.EGL_RED_SIZE, redSize, EGL10.EGL_GREEN_SIZE, greenSize, EGL10.EGL_GREEN_SIZE, greenSize, Loading @@ -694,7 +739,7 @@ public abstract class HardwareRenderer { EGL10.EGL_DEPTH_SIZE, depthSize, EGL10.EGL_DEPTH_SIZE, depthSize, EGL10.EGL_STENCIL_SIZE, stencilSize, EGL10.EGL_STENCIL_SIZE, stencilSize, EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT | 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 }); EGL10.EGL_NONE }); mValue = new int[1]; mValue = new int[1]; mRedSize = redSize; mRedSize = redSize; Loading @@ -703,6 +748,7 @@ public abstract class HardwareRenderer { mAlphaSize = alphaSize; mAlphaSize = alphaSize; mDepthSize = depthSize; mDepthSize = depthSize; mStencilSize = stencilSize; mStencilSize = stencilSize; mDirtyRegions = dirtyRegions; } } @Override @Override Loading @@ -716,7 +762,7 @@ public abstract class HardwareRenderer { int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0); int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0); int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0); int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0); boolean backBuffer; boolean backBuffer; if (RENDER_DIRTY_REGIONS) { if (mDirtyRegions) { int surfaceType = findConfigAttrib(egl, display, config, int surfaceType = findConfigAttrib(egl, display, config, EGL_SURFACE_TYPE, 0); EGL_SURFACE_TYPE, 0); backBuffer = (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) != 0; backBuffer = (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) != 0; Loading