diff options
author | John Reck <jreck@google.com> | 2014-02-11 17:30:53 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-02-11 17:30:53 +0000 |
commit | f6eebb21d5c58345eca8be25676e34346f5809b2 (patch) | |
tree | 1a86b74f2bb3fd44f4dff4422affe9ce79938946 | |
parent | faa91f852e9526b2f112122da9ae0956526cf662 (diff) | |
parent | 04fc583c3dd3144bc6b718fcac4b3e1afdfdb067 (diff) | |
download | frameworks_base-f6eebb21d5c58345eca8be25676e34346f5809b2.zip frameworks_base-f6eebb21d5c58345eca8be25676e34346f5809b2.tar.gz frameworks_base-f6eebb21d5c58345eca8be25676e34346f5809b2.tar.bz2 |
Merge "Refactor HardwareLayer"
22 files changed, 757 insertions, 758 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index b763888..2ed0cba 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -31,7 +31,6 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.graphics.Shader; -import android.graphics.SurfaceTexture; import android.graphics.TemporaryBuffer; import android.text.GraphicsOperations; import android.text.SpannableString; @@ -87,15 +86,6 @@ class GLES20Canvas extends HardwareCanvas { GLES20Canvas(boolean translucent) { this(false, translucent); } - - /** - * Creates a canvas to render into an FBO. - */ - GLES20Canvas(long layer, boolean translucent) { - mOpaque = !translucent; - mRenderer = nCreateLayerRenderer(layer); - setupFinalizer(); - } protected GLES20Canvas(boolean record, boolean translucent) { mOpaque = !translucent; @@ -122,7 +112,6 @@ class GLES20Canvas extends HardwareCanvas { } private static native long nCreateRenderer(); - private static native long nCreateLayerRenderer(long layer); private static native long nCreateDisplayListRenderer(); private static native void nResetDisplayListRenderer(long renderer); private static native void nDestroyRenderer(long renderer); @@ -156,12 +145,12 @@ class GLES20Canvas extends HardwareCanvas { @Override void pushLayerUpdate(HardwareLayer layer) { - nPushLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer); + nPushLayerUpdate(mRenderer, layer.getLayer()); } @Override void cancelLayerUpdate(HardwareLayer layer) { - nCancelLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer); + nCancelLayerUpdate(mRenderer, layer.getLayer()); } @Override @@ -174,22 +163,7 @@ class GLES20Canvas extends HardwareCanvas { nClearLayerUpdates(mRenderer); } - static native long nCreateTextureLayer(boolean opaque, int[] layerInfo); - static native long nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo); - static native boolean nResizeLayer(long layerId, int width, int height, int[] layerInfo); - static native void nSetOpaqueLayer(long layerId, boolean isOpaque); - static native void nSetLayerPaint(long layerId, long nativePaint); - static native void nSetLayerColorFilter(long layerId, long nativeColorFilter); - static native void nUpdateTextureLayer(long layerId, int width, int height, boolean opaque, - SurfaceTexture surface); - static native void nClearLayerTexture(long layerId); - static native void nSetTextureLayerTransform(long layerId, long matrix); - static native void nDestroyLayer(long layerId); - static native void nDestroyLayerDeferred(long layerId); - static native void nUpdateRenderLayer(long layerId, long renderer, long displayList, - int left, int top, int right, int bottom); static native boolean nCopyLayer(long layerId, long bitmap); - private static native void nClearLayerUpdates(long renderer); private static native void nFlushLayerUpdates(long renderer); private static native void nPushLayerUpdate(long renderer, long layer); @@ -408,9 +382,7 @@ class GLES20Canvas extends HardwareCanvas { void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) { layer.setLayerPaint(paint); - - final GLES20Layer glLayer = (GLES20Layer) layer; - nDrawLayer(mRenderer, glLayer.getLayer(), x, y); + nDrawLayer(mRenderer, layer.getLayer(), x, y); } private static native void nDrawLayer(long renderer, long layer, float x, float y); diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java deleted file mode 100644 index 1d30824..0000000 --- a/core/java/android/view/GLES20Layer.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package android.view; - -import android.graphics.Bitmap; -import android.graphics.Paint; - -/** - * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. - */ -abstract class GLES20Layer extends HardwareLayer { - long mLayer; - Finalizer mFinalizer; - - GLES20Layer() { - } - - GLES20Layer(int width, int height, boolean opaque) { - super(width, height, opaque); - } - - /** - * Returns the native layer object used to render this layer. - * - * @return A pointer to the native layer object, or 0 if the object is NULL - */ - public long getLayer() { - return mLayer; - } - - @Override - void setLayerPaint(Paint paint) { - if (paint != null) { - GLES20Canvas.nSetLayerPaint(mLayer, paint.mNativePaint); - GLES20Canvas.nSetLayerColorFilter(mLayer, paint.getColorFilter() != null ? - paint.getColorFilter().native_instance : 0); - } - } - - @Override - public boolean copyInto(Bitmap bitmap) { - return GLES20Canvas.nCopyLayer(mLayer, bitmap.mNativeBitmap); - } - - @Override - public void destroy() { - if (mDisplayList != null) { - mDisplayList.reset(); - } - if (mFinalizer != null) { - mFinalizer.destroy(); - mFinalizer = null; - } - mLayer = 0; - } - - @Override - void clearStorage() { - if (mLayer != 0) GLES20Canvas.nClearLayerTexture(mLayer); - } - - static class Finalizer { - private long mLayerId; - - public Finalizer(long layerId) { - mLayerId = layerId; - } - - @Override - protected void finalize() throws Throwable { - try { - if (mLayerId != 0) { - GLES20Canvas.nDestroyLayerDeferred(mLayerId); - } - } finally { - super.finalize(); - } - } - - void destroy() { - GLES20Canvas.nDestroyLayer(mLayerId); - mLayerId = 0; - } - } -} diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java deleted file mode 100644 index 8c97867..0000000 --- a/core/java/android/view/GLES20RenderLayer.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.view; - -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Rect; - -/** - * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This - * implementation can be used a rendering target. It generates a - * {@link Canvas} that can be used to render into an FBO using OpenGL. - */ -class GLES20RenderLayer extends GLES20Layer { - private int mLayerWidth; - private int mLayerHeight; - - private final GLES20Canvas mCanvas; - - GLES20RenderLayer(int width, int height, boolean isOpaque) { - super(width, height, isOpaque); - - int[] layerInfo = new int[2]; - mLayer = GLES20Canvas.nCreateLayer(width, height, isOpaque, layerInfo); - if (mLayer != 0) { - mLayerWidth = layerInfo[0]; - mLayerHeight = layerInfo[1]; - - mCanvas = new GLES20Canvas(mLayer, !isOpaque); - mFinalizer = new Finalizer(mLayer); - } else { - mCanvas = null; - mFinalizer = null; - } - } - - @Override - boolean isValid() { - return mLayer != 0 && mLayerWidth > 0 && mLayerHeight > 0; - } - - @Override - boolean resize(int width, int height) { - if (!isValid() || width <= 0 || height <= 0) return false; - - mWidth = width; - mHeight = height; - - if (width != mLayerWidth || height != mLayerHeight) { - int[] layerInfo = new int[2]; - - if (GLES20Canvas.nResizeLayer(mLayer, width, height, layerInfo)) { - mLayerWidth = layerInfo[0]; - mLayerHeight = layerInfo[1]; - } else { - // Failure: not enough GPU resources for requested size - mLayer = 0; - mLayerWidth = 0; - mLayerHeight = 0; - } - } - return isValid(); - } - - @Override - void setOpaque(boolean isOpaque) { - mOpaque = isOpaque; - GLES20Canvas.nSetOpaqueLayer(mLayer, isOpaque); - } - - @Override - HardwareCanvas getCanvas() { - return mCanvas; - } - - @Override - void end(Canvas currentCanvas) { - HardwareCanvas canvas = getCanvas(); - if (canvas != null) { - canvas.onPostDraw(); - } - if (currentCanvas instanceof GLES20Canvas) { - ((GLES20Canvas) currentCanvas).resume(); - } - } - - @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(dirty); - return canvas; - } - - /** - * Ignored - */ - @Override - void setTransform(Matrix matrix) { - } - - @Override - void redrawLater(DisplayList displayList, Rect dirtyRect) { - GLES20Canvas.nUpdateRenderLayer(mLayer, mCanvas.getRenderer(), - displayList.getNativeDisplayList(), - dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom); - } -} diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java deleted file mode 100644 index bb5a6eb..0000000 --- a/core/java/android/view/GLES20TextureLayer.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.view; - -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.graphics.SurfaceTexture; - -/** - * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This - * implementation can be used as a texture. Rendering into this - * layer is not controlled by a {@link HardwareCanvas}. - */ -class GLES20TextureLayer extends GLES20Layer { - private int mTexture; - private SurfaceTexture mSurface; - - GLES20TextureLayer(boolean isOpaque) { - int[] layerInfo = new int[2]; - mLayer = GLES20Canvas.nCreateTextureLayer(isOpaque, layerInfo); - - if (mLayer != 0) { - mTexture = layerInfo[0]; - mFinalizer = new Finalizer(mLayer); - } else { - mFinalizer = null; - } - } - - @Override - boolean isValid() { - return mLayer != 0 && mTexture != 0; - } - - @Override - boolean resize(int width, int height) { - return isValid(); - } - - @Override - HardwareCanvas getCanvas() { - return null; - } - - @Override - HardwareCanvas start(Canvas currentCanvas) { - return null; - } - - @Override - HardwareCanvas start(Canvas currentCanvas, Rect dirty) { - return null; - } - - @Override - void end(Canvas currentCanvas) { - } - - SurfaceTexture getSurfaceTexture() { - if (mSurface == null) { - mSurface = new SurfaceTexture(mTexture); - } - return mSurface; - } - - void setSurfaceTexture(SurfaceTexture surfaceTexture) { - if (mSurface != null) { - mSurface.release(); - } - mSurface = surfaceTexture; - mSurface.attachToGLContext(mTexture); - } - - @Override - void update(int width, int height, boolean isOpaque) { - super.update(width, height, isOpaque); - GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, isOpaque, mSurface); - } - - @Override - void setOpaque(boolean isOpaque) { - throw new UnsupportedOperationException("Use update(int, int, boolean) instead"); - } - - @Override - void setTransform(Matrix matrix) { - GLES20Canvas.nSetTextureLayerTransform(mLayer, matrix.native_instance); - } - - @Override - void redrawLater(DisplayList displayList, Rect dirtyRect) { - } -} diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java index 5002fe5..40ad72c 100644 --- a/core/java/android/view/GLRenderer.java +++ b/core/java/android/view/GLRenderer.java @@ -40,7 +40,7 @@ import static javax.microedition.khronos.egl.EGL10.EGL_WIDTH; import static javax.microedition.khronos.egl.EGL10.EGL_WINDOW_BIT; import android.content.ComponentCallbacks2; -import android.graphics.Color; +import android.graphics.Bitmap; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.SurfaceTexture; @@ -62,6 +62,8 @@ import android.view.Surface.OutOfResourcesException; import com.google.android.gles_jni.EGLImpl; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.locks.ReentrantLock; import javax.microedition.khronos.egl.EGL10; @@ -177,6 +179,8 @@ public class GLRenderer extends HardwareRenderer { private static EGLSurface sPbuffer; private static final Object[] sPbufferLock = new Object[0]; + private List<HardwareLayer> mAttachedLayers = new ArrayList<HardwareLayer>(); + private static class GLRendererEglContext extends ManagedEGLContext { final Handler mHandler = new Handler(); @@ -472,33 +476,40 @@ public class GLRenderer extends HardwareRenderer { } @Override - void cancelLayerUpdate(HardwareLayer layer) { - mGlCanvas.cancelLayerUpdate(layer); + void flushLayerUpdates() { + mGlCanvas.flushLayerUpdates(); } @Override - void flushLayerUpdates() { - mGlCanvas.flushLayerUpdates(); + HardwareLayer createTextureLayer() { + return HardwareLayer.createTextureLayer(this); } @Override - HardwareLayer createHardwareLayer(boolean isOpaque) { - return new GLES20TextureLayer(isOpaque); + public HardwareLayer createDisplayListLayer(int width, int height) { + return HardwareLayer.createRenderLayer(this, width, height); } @Override - public HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) { - return new GLES20RenderLayer(width, height, isOpaque); + void onLayerCreated(HardwareLayer hardwareLayer) { + mAttachedLayers.add(hardwareLayer); + } + + @Override + void onLayerDestroyed(HardwareLayer layer) { + mGlCanvas.cancelLayerUpdate(layer); + mAttachedLayers.remove(layer); } @Override public SurfaceTexture createSurfaceTexture(HardwareLayer layer) { - return ((GLES20TextureLayer) layer).getSurfaceTexture(); + return layer.createSurfaceTexture(); } @Override - void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture) { - ((GLES20TextureLayer) layer).setSurfaceTexture(surfaceTexture); + boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap) { + layer.flushChanges(); + return GLES20Canvas.nCopyLayer(layer.getLayer(), bitmap.mNativeBitmap); } @Override @@ -1127,6 +1138,8 @@ public class GLRenderer extends HardwareRenderer { DisplayList displayList = buildDisplayList(view, canvas); + flushLayerChanges(); + // buildDisplayList() calls into user code which can cause // an eglMakeCurrent to happen with a different surface/context. // We must therefore check again here. @@ -1180,6 +1193,20 @@ public class GLRenderer extends HardwareRenderer { } } + private void flushLayerChanges() { + // Loop through and apply any pending layer changes + for (int i = 0; i < mAttachedLayers.size(); i++) { + HardwareLayer layer = mAttachedLayers.get(i); + layer.flushChanges(); + if (!layer.isValid()) { + // The layer was removed from mAttachedLayers, rewind i by 1 + // Note that this shouldn't actually happen as View.getHardwareLayer() + // is already flushing for error checking reasons + i--; + } + } + } + private DisplayList buildDisplayList(View view, HardwareCanvas canvas) { if (mDrawDelta <= 0) { return view.mDisplayList; diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java index 23383d9..9bbcf7c 100644 --- a/core/java/android/view/HardwareLayer.java +++ b/core/java/android/view/HardwareLayer.java @@ -17,10 +17,10 @@ package android.view; import android.graphics.Bitmap; -import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.SurfaceTexture; /** * A hardware layer can be used to render graphics operations into a hardware @@ -28,38 +28,35 @@ import android.graphics.Rect; * would use a Frame Buffer Object (FBO.) The hardware layer can be used as * a drawing cache when a complex set of graphics operations needs to be * drawn several times. + * + * @hide */ -abstract class HardwareLayer { - /** - * Indicates an unknown dimension (width or height.) - */ - static final int DIMENSION_UNDEFINED = -1; - - int mWidth; - int mHeight; - DisplayList mDisplayList; +final class HardwareLayer { + private static final int LAYER_TYPE_TEXTURE = 1; + private static final int LAYER_TYPE_RENDER = 2; - boolean mOpaque; + private HardwareRenderer mRenderer; + private Finalizer mFinalizer; + private DisplayList mDisplayList; + private final int mLayerType; - /** - * Creates a new hardware layer with undefined dimensions. - */ - HardwareLayer() { - this(DIMENSION_UNDEFINED, DIMENSION_UNDEFINED, false); + private HardwareLayer(HardwareRenderer renderer, long deferredUpdater, int type) { + if (renderer == null || deferredUpdater == 0) { + throw new IllegalArgumentException("Either hardware renderer: " + renderer + + " or deferredUpdater: " + deferredUpdater + " is invalid"); + } + mRenderer = renderer; + mLayerType = type; + mFinalizer = new Finalizer(deferredUpdater); + + // Layer is considered initialized at this point, notify the HardwareRenderer + mRenderer.onLayerCreated(this); } - /** - * Creates a new hardware layer at least as large as the supplied - * dimensions. - * - * @param width The minimum width of the layer - * @param height The minimum height of the layer - * @param isOpaque Whether the layer should be opaque or not - */ - HardwareLayer(int width, int height, boolean isOpaque) { - mWidth = width; - mHeight = height; - mOpaque = isOpaque; + private void assertType(int type) { + if (mLayerType != type) { + throw new IllegalAccessError("Method not appropriate for this layer type! " + mLayerType); + } } /** @@ -68,158 +65,225 @@ abstract class HardwareLayer { * @param paint The paint used when the layer is drawn into the destination canvas. * @see View#setLayerPaint(android.graphics.Paint) */ - void setLayerPaint(Paint paint) { } + public void setLayerPaint(Paint paint) { + nSetLayerPaint(mFinalizer.mDeferredUpdater, paint.mNativePaint, + paint.getColorFilter() != null ? paint.getColorFilter().native_instance : 0); + } /** - * Returns the minimum width of the layer. - * - * @return The minimum desired width of the hardware layer + * Indicates whether this layer can be rendered. + * + * @return True if the layer can be rendered into, false otherwise */ - int getWidth() { - return mWidth; + public boolean isValid() { + return mFinalizer != null && mFinalizer.mDeferredUpdater != 0; } /** - * Returns the minimum height of the layer. - * - * @return The minimum desired height of the hardware layer + * Destroys resources without waiting for a GC. */ - int getHeight() { - return mHeight; + public void destroy() { + if (!isValid()) { + // Already destroyed + return; + } + + if (mDisplayList != null) { + mDisplayList.reset(); + mDisplayList = null; + } + if (mRenderer != null) { + mRenderer.onLayerDestroyed(this); + mRenderer = null; + } + doDestroyLayerUpdater(); } /** - * Returns the DisplayList for the layer. + * Destroys the deferred layer updater but not the backing layer. The + * backing layer is instead returned and is the caller's responsibility + * to destroy/recycle as appropriate. * - * @return The DisplayList of the hardware layer + * It is safe to call this in onLayerDestroyed only */ - DisplayList getDisplayList() { + public long detachBackingLayer() { + long backingLayer = nDetachBackingLayer(mFinalizer.mDeferredUpdater); + doDestroyLayerUpdater(); + return backingLayer; + } + + private void doDestroyLayerUpdater() { + if (mFinalizer != null) { + mFinalizer.destroy(); + mFinalizer = null; + } + } + + public DisplayList startRecording() { + assertType(LAYER_TYPE_RENDER); + + if (mDisplayList == null) { + mDisplayList = DisplayList.create("HardwareLayer"); + } return mDisplayList; } + public void endRecording(Rect dirtyRect) { + nUpdateRenderLayer(mFinalizer.mDeferredUpdater, mDisplayList.getNativeDisplayList(), + dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom); + mRenderer.pushLayerUpdate(this); + } + /** - * Sets the DisplayList for the layer. + * Copies this layer into the specified bitmap. * - * @param displayList The new DisplayList for this layer + * @param bitmap The bitmap to copy they layer into + * + * @return True if the copy was successful, false otherwise */ - void setDisplayList(DisplayList displayList) { - mDisplayList = displayList; + public boolean copyInto(Bitmap bitmap) { + return mRenderer.copyLayerInto(this, bitmap); } /** - * Returns whether or not this layer is opaque. - * - * @return True if the layer is opaque, false otherwise + * Update the layer's properties. Note that after calling this isValid() may + * return false if the requested width/height cannot be satisfied + * + * @param width The new width of this layer + * @param height The new height of this layer + * @param isOpaque Whether this layer is opaque + * + * @return true if the layer's properties will change, false if they already + * match the desired values. */ - boolean isOpaque() { - return mOpaque; + public boolean prepare(int width, int height, boolean isOpaque) { + return nPrepare(mFinalizer.mDeferredUpdater, width, height, isOpaque); } /** - * Sets whether or not this layer should be considered opaque. - * - * @param isOpaque True if the layer is opaque, false otherwise + * Sets an optional transform on this layer. + * + * @param matrix The transform to apply to the layer. */ - abstract void setOpaque(boolean isOpaque); + public void setTransform(Matrix matrix) { + nSetTransform(mFinalizer.mDeferredUpdater, matrix.native_instance); + } /** - * Indicates whether this layer can be rendered. - * - * @return True if the layer can be rendered into, false otherwise + * Indicates that this layer has lost its texture. */ - abstract boolean isValid(); + public void onTextureDestroyed() { + assertType(LAYER_TYPE_TEXTURE); + nOnTextureDestroyed(mFinalizer.mDeferredUpdater); + } /** - * Resize the layer, if necessary, to be at least as large - * as the supplied dimensions. - * - * @param width The new desired minimum width for this layer - * @param height The new desired minimum height for this layer - * @return True if the resulting layer is valid, false otherwise + * This exists to minimize impact into the current HardwareLayer paths as + * some of the specifics of how to handle error cases in the fully + * deferred model will work */ - abstract boolean resize(int width, int height); + @Deprecated + public void flushChanges() { + if (HardwareRenderer.sUseRenderThread) { + // Not supported, don't try. + return; + } - /** - * Returns a hardware canvas that can be used to render onto - * this layer. - * - * @return A hardware canvas, or null if a canvas cannot be created - * - * @see #start(android.graphics.Canvas) - * @see #end(android.graphics.Canvas) - */ - abstract HardwareCanvas getCanvas(); + boolean success = nFlushChanges(mFinalizer.mDeferredUpdater); + if (!success) { + destroy(); + } + } - /** - * Destroys resources without waiting for a GC. - */ - abstract void destroy(); + public long getLayer() { + return nGetLayer(mFinalizer.mDeferredUpdater); + } - /** - * This must be invoked before drawing onto this layer. - * - * @param currentCanvas The canvas whose rendering needs to be interrupted - */ - abstract HardwareCanvas start(Canvas currentCanvas); + public void setSurfaceTexture(SurfaceTexture surface) { + assertType(LAYER_TYPE_TEXTURE); + nSetSurfaceTexture(mFinalizer.mDeferredUpdater, surface, false); + } - /** - * 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); + public void updateSurfaceTexture() { + assertType(LAYER_TYPE_TEXTURE); + nUpdateSurfaceTexture(mFinalizer.mDeferredUpdater); + } /** - * This must be invoked after drawing onto this layer. - * - * @param currentCanvas The canvas whose rendering needs to be resumed + * This should only be used by HardwareRenderer! Do not call directly */ - abstract void end(Canvas currentCanvas); + SurfaceTexture createSurfaceTexture() { + assertType(LAYER_TYPE_TEXTURE); + SurfaceTexture st = new SurfaceTexture(nGetTexName(mFinalizer.mDeferredUpdater)); + nSetSurfaceTexture(mFinalizer.mDeferredUpdater, st, true); + return st; + } /** - * Copies this layer into the specified bitmap. - * - * @param bitmap The bitmap to copy they layer into - * - * @return True if the copy was successful, false otherwise + * This should only be used by HardwareRenderer! Do not call directly */ - abstract boolean copyInto(Bitmap bitmap); + static HardwareLayer createTextureLayer(HardwareRenderer renderer) { + return new HardwareLayer(renderer, nCreateTextureLayer(), LAYER_TYPE_TEXTURE); + } /** - * Update the layer's properties. This method should be used - * when the underlying storage is modified by an external entity. - * To change the underlying storage, use the {@link #resize(int, int)} - * method instead. - * - * @param width The new width of this layer - * @param height The new height of this layer - * @param isOpaque Whether this layer is opaque + * This should only be used by HardwareRenderer! Do not call directly */ - void update(int width, int height, boolean isOpaque) { - mWidth = width; - mHeight = height; - mOpaque = isOpaque; + static HardwareLayer createRenderLayer(HardwareRenderer renderer, + int width, int height) { + return new HardwareLayer(renderer, nCreateRenderLayer(width, height), LAYER_TYPE_RENDER); } - /** - * Sets an optional transform on this layer. - * - * @param matrix The transform to apply to the layer. - */ - abstract void setTransform(Matrix matrix); + /** This also creates the underlying layer */ + private static native long nCreateTextureLayer(); + private static native long nCreateRenderLayer(int width, int height); - /** - * Specifies the display list to use to refresh the layer. - * - * @param displayList The display list containing the drawing commands to - * execute in this layer - * @param dirtyRect The dirty region of the layer that needs to be redrawn - */ - abstract void redrawLater(DisplayList displayList, Rect dirtyRect); + private static native void nOnTextureDestroyed(long layerUpdater); + private static native long nDetachBackingLayer(long layerUpdater); - /** - * Indicates that this layer has lost its underlying storage. + /** This also destroys the underlying layer if it is still attached. + * Note it does not recycle the underlying layer, but instead queues it + * for deferred deletion. + * The HardwareRenderer should use detachBackingLayer() in the + * onLayerDestroyed() callback to do recycling if desired. */ - abstract void clearStorage(); + private static native void nDestroyLayerUpdater(long layerUpdater); + + private static native boolean nPrepare(long layerUpdater, int width, int height, boolean isOpaque); + private static native void nSetLayerPaint(long layerUpdater, long paint, long colorFilter); + private static native void nSetTransform(long layerUpdater, long matrix); + private static native void nSetSurfaceTexture(long layerUpdater, + SurfaceTexture surface, boolean isAlreadyAttached); + private static native void nUpdateSurfaceTexture(long layerUpdater); + private static native void nUpdateRenderLayer(long layerUpdater, long displayList, + int left, int top, int right, int bottom); + + private static native boolean nFlushChanges(long layerUpdater); + + private static native long nGetLayer(long layerUpdater); + private static native int nGetTexName(long layerUpdater); + + private static class Finalizer { + private long mDeferredUpdater; + + public Finalizer(long deferredUpdater) { + mDeferredUpdater = deferredUpdater; + } + + @Override + protected void finalize() throws Throwable { + try { + destroy(); + } finally { + super.finalize(); + } + } + + void destroy() { + if (mDeferredUpdater != 0) { + nDestroyLayerUpdater(mDeferredUpdater); + mDeferredUpdater = 0; + } + } + } } diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 352ab83..93cc9d1 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -16,6 +16,7 @@ package android.view; +import android.graphics.Bitmap; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.SurfaceTexture; @@ -344,19 +345,20 @@ public abstract class HardwareRenderer { * @param layer The hardware layer that needs an update * * @see #flushLayerUpdates() - * @see #cancelLayerUpdate(HardwareLayer) */ abstract void pushLayerUpdate(HardwareLayer layer); /** - * Cancels a queued layer update. If the specified layer was not - * queued for update, this method has no effect. - * - * @param layer The layer whose update to cancel - * - * @see #pushLayerUpdate(HardwareLayer) + * Tells the HardwareRenderer that a layer was created. The renderer should + * make sure to apply any pending layer changes at the start of a new frame + */ + abstract void onLayerCreated(HardwareLayer hardwareLayer); + + /** + * Tells the HardwareRenderer that the layer is destroyed. The renderer + * should remove the layer from any update queues. */ - abstract void cancelLayerUpdate(HardwareLayer layer); + abstract void onLayerDestroyed(HardwareLayer layer); /** * Forces all enqueued layer updates to be executed immediately. @@ -403,22 +405,19 @@ public abstract class HardwareRenderer { * Creates a new hardware layer. A hardware layer built by calling this * method will be treated as a texture layer, instead of as a render target. * - * @param isOpaque Whether the layer should be opaque or not - * * @return A hardware layer */ - abstract HardwareLayer createHardwareLayer(boolean isOpaque); + abstract HardwareLayer createTextureLayer(); /** * Creates a new hardware layer. * * @param width The minimum width of the layer * @param height The minimum height of the layer - * @param isOpaque Whether the layer should be opaque or not * * @return A hardware layer */ - abstract HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque); + abstract HardwareLayer createDisplayListLayer(int width, int height); /** * Creates a new {@link SurfaceTexture} that can be used to render into the @@ -430,14 +429,7 @@ public abstract class HardwareRenderer { */ abstract SurfaceTexture createSurfaceTexture(HardwareLayer layer); - /** - * Sets the {@link android.graphics.SurfaceTexture} that will be used to - * render into the specified hardware layer. - * - * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture} - * @param surfaceTexture The {@link android.graphics.SurfaceTexture} to use for the layer - */ - abstract void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture); + abstract boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap); /** * Detaches the specified functor from the current functor execution queue. diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 161fe33..e789407 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -250,7 +250,7 @@ public class TextureView extends View { mSurface.detachFromGLContext(); // SurfaceTexture owns the texture name and detachFromGLContext // should have deleted it - mLayer.clearStorage(); + mLayer.onTextureDestroyed(); boolean shouldRelease = true; if (mListener != null) { @@ -375,7 +375,7 @@ public class TextureView extends View { return null; } - mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque); + mLayer = mAttachInfo.mHardwareRenderer.createTextureLayer(); if (!mUpdateSurface) { // Create a new SurfaceTexture for the layer. mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer); @@ -416,7 +416,7 @@ public class TextureView extends View { updateLayer(); mMatrixChanged = true; - mAttachInfo.mHardwareRenderer.setSurfaceTexture(mLayer, mSurface); + mLayer.setSurfaceTexture(mSurface); mSurface.setDefaultBufferSize(getWidth(), getHeight()); } @@ -469,7 +469,8 @@ public class TextureView extends View { } } - mLayer.update(getWidth(), getHeight(), mOpaque); + mLayer.prepare(getWidth(), getHeight(), mOpaque); + mLayer.updateSurfaceTexture(); if (mListener != null) { mListener.onSurfaceTextureUpdated(mSurface); diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 2c9f1d9..1c20923 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -16,6 +16,7 @@ package android.view; +import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.os.SystemClock; @@ -155,7 +156,12 @@ public class ThreadedRenderer extends HardwareRenderer { } @Override - void cancelLayerUpdate(HardwareLayer layer) { + void onLayerCreated(HardwareLayer layer) { + throw new NoSuchMethodError(); + } + + @Override + void onLayerDestroyed(HardwareLayer layer) { throw new NoSuchMethodError(); } @@ -197,12 +203,12 @@ public class ThreadedRenderer extends HardwareRenderer { } @Override - HardwareLayer createHardwareLayer(boolean isOpaque) { + HardwareLayer createTextureLayer() { throw new NoSuchMethodError(); } @Override - HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) { + HardwareLayer createDisplayListLayer(int width, int height) { throw new NoSuchMethodError(); } @@ -212,7 +218,7 @@ public class ThreadedRenderer extends HardwareRenderer { } @Override - void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture) { + boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap) { throw new NoSuchMethodError(); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index fbeddc8..393b166 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -87,7 +87,6 @@ import static java.lang.Math.max; import com.android.internal.R; import com.android.internal.util.Predicate; import com.android.internal.view.menu.MenuBuilder; - import com.google.android.collect.Lists; import com.google.android.collect.Maps; @@ -13629,16 +13628,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) { if (mHardwareLayer == null) { - mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer( - width, height, isOpaque()); + mHardwareLayer = mAttachInfo.mHardwareRenderer.createDisplayListLayer( + width, height); mLocalDirtyRect.set(0, 0, width, height); - } else { - if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) { - if (mHardwareLayer.resize(width, height)) { - mLocalDirtyRect.set(0, 0, width, height); - } - } - + } else if (mHardwareLayer.isValid()) { // This should not be necessary but applications that change // the parameters of their background drawable without calling // this.setBackground(Drawable) can leave the view in a bad state @@ -13646,23 +13639,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // not opaque.) computeOpaqueFlags(); - final boolean opaque = isOpaque(); - if (mHardwareLayer.isValid() && mHardwareLayer.isOpaque() != opaque) { - mHardwareLayer.setOpaque(opaque); + if (mHardwareLayer.prepare(width, height, isOpaque())) { mLocalDirtyRect.set(0, 0, width, height); } } // The layer is not valid if the underlying GPU resources cannot be allocated + mHardwareLayer.flushChanges(); if (!mHardwareLayer.isValid()) { return null; } mHardwareLayer.setLayerPaint(mLayerPaint); - mHardwareLayer.redrawLater(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect); - ViewRootImpl viewRoot = getViewRootImpl(); - if (viewRoot != null) viewRoot.pushHardwareLayerUpdate(mHardwareLayer); - + DisplayList displayList = mHardwareLayer.startRecording(); + if (getDisplayList(displayList, true) != displayList) { + throw new IllegalStateException("getDisplayList() didn't return" + + " the input displaylist for a hardware layer!"); + } + mHardwareLayer.endRecording(mLocalDirtyRect); mLocalDirtyRect.setEmpty(); } @@ -13679,18 +13673,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ boolean destroyLayer(boolean valid) { if (mHardwareLayer != null) { - AttachInfo info = mAttachInfo; - if (info != null && info.mHardwareRenderer != null && - info.mHardwareRenderer.isEnabled() && - (valid || info.mHardwareRenderer.validate())) { - - info.mHardwareRenderer.cancelLayerUpdate(mHardwareLayer); - mHardwareLayer.destroy(); - mHardwareLayer = null; + mHardwareLayer.destroy(); + mHardwareLayer = null; - invalidate(true); - invalidateParentCaches(); - } + invalidate(true); + invalidateParentCaches(); return true; } return false; @@ -13911,19 +13898,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Get the DisplayList for the HardwareLayer - * - * @param layer The HardwareLayer whose DisplayList we want - * @return A DisplayList fopr the specified HardwareLayer - */ - private DisplayList getHardwareLayerDisplayList(HardwareLayer layer) { - DisplayList displayList = getDisplayList(layer.getDisplayList(), true); - layer.setDisplayList(displayList); - return displayList; - } - - - /** * <p>Returns a display list that can be used to draw this view again * without executing its draw method.</p> * diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index ccb85a6..ef69948 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -642,12 +642,6 @@ public final class ViewRootImpl implements ViewParent, } } - void pushHardwareLayerUpdate(HardwareLayer layer) { - if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) { - mAttachInfo.mHardwareRenderer.pushLayerUpdate(layer); - } - } - void flushHardwareLayerUpdates() { if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled() && mAttachInfo.mHardwareRenderer.validate()) { diff --git a/core/jni/Android.mk b/core/jni/Android.mk index f8d96e3..f1047f3 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -57,6 +57,7 @@ LOCAL_SRC_FILES:= \ android_view_GraphicBuffer.cpp \ android_view_GLRenderer.cpp \ android_view_GLES20Canvas.cpp \ + android_view_HardwareLayer.cpp \ android_view_ThreadedRenderer.cpp \ android_view_MotionEvent.cpp \ android_view_PointerIcon.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 7ed6641..77c5c18 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -123,6 +123,7 @@ extern int register_android_view_DisplayList(JNIEnv* env); extern int register_android_view_GraphicBuffer(JNIEnv* env); extern int register_android_view_GLES20Canvas(JNIEnv* env); extern int register_android_view_GLRenderer(JNIEnv* env); +extern int register_android_view_HardwareLayer(JNIEnv* env); extern int register_android_view_ThreadedRenderer(JNIEnv* env); extern int register_android_view_Surface(JNIEnv* env); extern int register_android_view_SurfaceControl(JNIEnv* env); @@ -1127,6 +1128,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_view_GraphicBuffer), REG_JNI(register_android_view_GLES20Canvas), REG_JNI(register_android_view_GLRenderer), + REG_JNI(register_android_view_HardwareLayer), REG_JNI(register_android_view_ThreadedRenderer), REG_JNI(register_android_view_Surface), REG_JNI(register_android_view_SurfaceControl), diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index b854fb9..dd089f2 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -914,147 +914,6 @@ static void android_view_GLES20Canvas_resume(JNIEnv* env, jobject clazz, renderer->resume(); } -static jint android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env, - jobject clazz, jlong layerPtr) { - Layer* layer = reinterpret_cast<Layer*>(layerPtr); - if (layer) { - OpenGLRenderer* renderer = new LayerRenderer(layer); - renderer->initProperties(); - return reinterpret_cast<jint>(renderer); - } - return NULL; -} - -static jlong android_view_GLES20Canvas_createTextureLayer(JNIEnv* env, jobject clazz, - jboolean isOpaque, jintArray layerInfo) { - Layer* layer = LayerRenderer::createTextureLayer(isOpaque); - - if (layer) { - jint* storage = env->GetIntArrayElements(layerInfo, NULL); - storage[0] = layer->getTexture(); - env->ReleaseIntArrayElements(layerInfo, storage, 0); - } - - return reinterpret_cast<jlong>(layer); -} - -static jlong android_view_GLES20Canvas_createLayer(JNIEnv* env, jobject clazz, - jint width, jint height, jboolean isOpaque, jintArray layerInfo) { - Layer* layer = LayerRenderer::createLayer(width, height, isOpaque); - - if (layer) { - jint* storage = env->GetIntArrayElements(layerInfo, NULL); - storage[0] = layer->getWidth(); - storage[1] = layer->getHeight(); - env->ReleaseIntArrayElements(layerInfo, storage, 0); - } - - return reinterpret_cast<jlong>(layer); -} - -static jboolean android_view_GLES20Canvas_resizeLayer(JNIEnv* env, jobject clazz, - jlong layerPtr, jint width, jint height, jintArray layerInfo) { - Layer* layer = reinterpret_cast<Layer*>(layerPtr); - if (LayerRenderer::resizeLayer(layer, width, height)) { - jint* storage = env->GetIntArrayElements(layerInfo, NULL); - storage[0] = layer->getWidth(); - storage[1] = layer->getHeight(); - env->ReleaseIntArrayElements(layerInfo, storage, 0); - return JNI_TRUE; - } - return JNI_FALSE; -} - -static void android_view_GLES20Canvas_setLayerPaint(JNIEnv* env, jobject clazz, - jlong layerPtr, jlong paintPtr) { - Layer* layer = reinterpret_cast<Layer*>(layerPtr); - if (layer) { - SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); - layer->setPaint(paint); - } -} - -static void android_view_GLES20Canvas_setLayerColorFilter(JNIEnv* env, jobject clazz, - jlong layerPtr, jlong colorFilterPtr) { - Layer* layer = reinterpret_cast<Layer*>(layerPtr); - if (layer) { - SkColorFilter* colorFilter = reinterpret_cast<SkColorFilter*>(colorFilterPtr); - layer->setColorFilter(colorFilter); - } -} - -static void android_view_GLES20Canvas_setOpaqueLayer(JNIEnv* env, jobject clazz, - jlong layerPtr, jboolean isOpaque) { - Layer* layer = reinterpret_cast<Layer*>(layerPtr); - if (layer) { - layer->setBlend(!isOpaque); - } -} - -static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject clazz, - jlong layerPtr, jint width, jint height, jboolean isOpaque, jobject surface) { - float transform[16]; - sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface)); - - if (surfaceTexture->updateTexImage() == NO_ERROR) { - int64_t frameNumber = surfaceTexture->getFrameNumber(); - // If the GLConsumer queue is in synchronous mode, need to discard all - // but latest frame, using the frame number to tell when we no longer - // have newer frames to target. Since we can't tell which mode it is in, - // do this unconditionally. - int dropCounter = 0; - while (surfaceTexture->updateTexImage() == NO_ERROR) { - int64_t newFrameNumber = surfaceTexture->getFrameNumber(); - if (newFrameNumber == frameNumber) break; - frameNumber = newFrameNumber; - dropCounter++; - } - #if DEBUG_RENDERER - if (dropCounter > 0) { - RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter); - } - #endif - surfaceTexture->getTransformMatrix(transform); - GLenum renderTarget = surfaceTexture->getCurrentTextureTarget(); - - Layer* layer = reinterpret_cast<Layer*>(layerPtr); - LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, renderTarget, transform); - } -} - -static void android_view_GLES20Canvas_updateRenderLayer(JNIEnv* env, jobject clazz, - jlong layerPtr, jlong rendererPtr, jlong displayListPtr, - jint left, jint top, jint right, jint bottom) { - Layer* layer = reinterpret_cast<Layer*>(layerPtr); - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); - DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr); - layer->updateDeferred(renderer, displayList, left, top, right, bottom); -} - -static void android_view_GLES20Canvas_clearLayerTexture(JNIEnv* env, jobject clazz, - jlong layerPtr) { - Layer* layer = reinterpret_cast<Layer*>(layerPtr); - layer->clearTexture(); -} - -static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz, - jlong layerPtr, jlong matrixPtr) { - Layer* layer = reinterpret_cast<Layer*>(layerPtr); - SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr); - layer->getTransform().load(*matrix); -} - -static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, jlong layerPtr) { - Layer* layer = reinterpret_cast<Layer*>(layerPtr); - LayerRenderer::destroyLayer(layer); -} - -static void android_view_GLES20Canvas_destroyLayerDeferred(JNIEnv* env, - jobject clazz, jlong layerPtr) { - Layer* layer = reinterpret_cast<Layer*>(layerPtr); - LayerRenderer::destroyLayerDeferred(layer); -} - static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) { OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); @@ -1247,19 +1106,6 @@ static JNINativeMethod gMethods[] = { { "nInterrupt", "(J)V", (void*) android_view_GLES20Canvas_interrupt }, { "nResume", "(J)V", (void*) android_view_GLES20Canvas_resume }, - { "nCreateLayerRenderer", "(J)J", (void*) android_view_GLES20Canvas_createLayerRenderer }, - { "nCreateLayer", "(IIZ[I)J", (void*) android_view_GLES20Canvas_createLayer }, - { "nResizeLayer", "(JII[I)Z" , (void*) android_view_GLES20Canvas_resizeLayer }, - { "nSetLayerPaint", "(JJ)V", (void*) android_view_GLES20Canvas_setLayerPaint }, - { "nSetLayerColorFilter", "(JJ)V", (void*) android_view_GLES20Canvas_setLayerColorFilter }, - { "nSetOpaqueLayer", "(JZ)V", (void*) android_view_GLES20Canvas_setOpaqueLayer }, - { "nCreateTextureLayer", "(Z[I)J", (void*) android_view_GLES20Canvas_createTextureLayer }, - { "nUpdateTextureLayer", "(JIIZLandroid/graphics/SurfaceTexture;)V", - (void*) android_view_GLES20Canvas_updateTextureLayer }, - { "nUpdateRenderLayer", "(JJJIIII)V", (void*) android_view_GLES20Canvas_updateRenderLayer }, - { "nClearLayerTexture", "(J)V", (void*) android_view_GLES20Canvas_clearLayerTexture }, - { "nDestroyLayer", "(J)V", (void*) android_view_GLES20Canvas_destroyLayer }, - { "nDestroyLayerDeferred", "(J)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred }, { "nDrawLayer", "(JJFF)V", (void*) android_view_GLES20Canvas_drawLayer }, { "nCopyLayer", "(JJ)Z", (void*) android_view_GLES20Canvas_copyLayer }, { "nClearLayerUpdates", "(J)V", (void*) android_view_GLES20Canvas_clearLayerUpdates }, @@ -1267,8 +1113,6 @@ static JNINativeMethod gMethods[] = { { "nPushLayerUpdate", "(JJ)V", (void*) android_view_GLES20Canvas_pushLayerUpdate }, { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_GLES20Canvas_cancelLayerUpdate }, - { "nSetTextureLayerTransform", "(JJ)V", (void*) android_view_GLES20Canvas_setTextureLayerTransform }, - { "nGetMaximumTextureWidth", "()I", (void*) android_view_GLES20Canvas_getMaxTextureWidth }, { "nGetMaximumTextureHeight", "()I", (void*) android_view_GLES20Canvas_getMaxTextureHeight }, diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp new file mode 100644 index 0000000..8a0a011 --- /dev/null +++ b/core/jni/android_view_HardwareLayer.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "OpenGLRenderer" + +#include "jni.h" +#include "GraphicsJNI.h" +#include <nativehelper/JNIHelp.h> + +#include <android_runtime/AndroidRuntime.h> +#include <android_runtime/android_graphics_SurfaceTexture.h> + +#include <gui/GLConsumer.h> + +#include <SkBitmap.h> +#include <SkCanvas.h> +#include <SkMatrix.h> +#include <SkPaint.h> +#include <SkXfermode.h> + +#include <DeferredLayerUpdater.h> +#include <DisplayList.h> +#include <LayerRenderer.h> +#include <SkiaShader.h> +#include <Rect.h> + +namespace android { + +using namespace uirenderer; + +#ifdef USE_OPENGL_RENDERER + +static jlong android_view_HardwareLayer_createTextureLayer(JNIEnv* env, jobject clazz) { + Layer* layer = LayerRenderer::createTextureLayer(); + if (!layer) return 0; + + return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer) ); +} + +static jlong android_view_HardwareLayer_createRenderLayer(JNIEnv* env, jobject clazz, + jint width, jint height) { + Layer* layer = LayerRenderer::createRenderLayer(width, height); + if (!layer) return 0; + + OpenGLRenderer* renderer = new LayerRenderer(layer); + renderer->initProperties(); + return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer, renderer) ); +} + +static void android_view_HardwareLayer_onTextureDestroyed(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + layer->backingLayer()->clearTexture(); +} + +static jlong android_view_HardwareLayer_detachBackingLayer(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + return reinterpret_cast<jlong>( layer->detachBackingLayer() ); +} + +static void android_view_HardwareLayer_destroyLayerUpdater(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + delete layer; +} + +static jboolean android_view_HardwareLayer_prepare(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr, jint width, jint height, jboolean isOpaque) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + bool changed = false; + changed |= layer->setSize(width, height); + changed |= layer->setBlend(!isOpaque); + return changed; +} + +static void android_view_HardwareLayer_setLayerPaint(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr, jlong paintPtr, jlong colorFilterPtr) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + if (layer) { + SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); + SkColorFilter* colorFilter = reinterpret_cast<SkColorFilter*>(colorFilterPtr); + layer->setPaint(paint); + layer->setColorFilter(colorFilter); + } +} + +static void android_view_HardwareLayer_setTransform(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr, jlong matrixPtr) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr); + layer->setTransform(matrix); +} + +static void android_view_HardwareLayer_setSurfaceTexture(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr, jobject surface, jboolean isAlreadyAttached) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface)); + layer->setSurfaceTexture(surfaceTexture, !isAlreadyAttached); +} + +static void android_view_HardwareLayer_updateSurfaceTexture(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + layer->updateTexImage(); +} + +static void android_view_HardwareLayer_updateRenderLayer(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr, jlong displayListPtr, + jint left, jint top, jint right, jint bottom) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr); + layer->setDisplayList(displayList, left, top, right, bottom); +} + +static jboolean android_view_HardwareLayer_flushChanges(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + return layer->apply(); +} + +static jlong android_view_HardwareLayer_getLayer(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + return reinterpret_cast<jlong>( layer->backingLayer() ); +} + +static jint android_view_HardwareLayer_getTexName(JNIEnv* env, jobject clazz, + jlong layerUpdaterPtr) { + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr); + return layer->backingLayer()->getTexture(); +} + +#endif // USE_OPENGL_RENDERER + +// ---------------------------------------------------------------------------- +// JNI Glue +// ---------------------------------------------------------------------------- + +const char* const kClassPathName = "android/view/HardwareLayer"; + +static JNINativeMethod gMethods[] = { +#ifdef USE_OPENGL_RENDERER + + { "nCreateTextureLayer", "()J", (void*) android_view_HardwareLayer_createTextureLayer }, + { "nCreateRenderLayer", "(II)J", (void*) android_view_HardwareLayer_createRenderLayer }, + { "nOnTextureDestroyed", "(J)V", (void*) android_view_HardwareLayer_onTextureDestroyed }, + { "nDetachBackingLayer", "(J)J", (void*) android_view_HardwareLayer_detachBackingLayer }, + { "nDestroyLayerUpdater", "(J)V", (void*) android_view_HardwareLayer_destroyLayerUpdater }, + + { "nPrepare", "(JIIZ)Z", (void*) android_view_HardwareLayer_prepare }, + { "nSetLayerPaint", "(JJJ)V", (void*) android_view_HardwareLayer_setLayerPaint }, + { "nSetTransform", "(JJ)V", (void*) android_view_HardwareLayer_setTransform }, + { "nSetSurfaceTexture", "(JLandroid/graphics/SurfaceTexture;Z)V", + (void*) android_view_HardwareLayer_setSurfaceTexture }, + { "nUpdateSurfaceTexture", "(J)V", (void*) android_view_HardwareLayer_updateSurfaceTexture }, + { "nUpdateRenderLayer", "(JJIIII)V", (void*) android_view_HardwareLayer_updateRenderLayer }, + + { "nFlushChanges", "(J)Z", (void*) android_view_HardwareLayer_flushChanges }, + + { "nGetLayer", "(J)J", (void*) android_view_HardwareLayer_getLayer }, + { "nGetTexName", "(J)I", (void*) android_view_HardwareLayer_getTexName }, +#endif +}; + +int register_android_view_HardwareLayer(JNIEnv* env) { + return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); +} + +}; diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 8c388d9..495ad19 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -17,6 +17,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) Caches.cpp \ DisplayList.cpp \ DeferredDisplayList.cpp \ + DeferredLayerUpdater.cpp \ DisplayListLogBuffer.cpp \ DisplayListRenderer.cpp \ Dither.cpp \ @@ -70,7 +71,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES LOCAL_CFLAGS += -Wno-unused-parameter LOCAL_MODULE_CLASS := SHARED_LIBRARIES - LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libEGL libGLESv2 libskia libui + LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libEGL libGLESv2 libskia libui libgui LOCAL_MODULE := libhwui LOCAL_MODULE_TAGS := optional diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp new file mode 100644 index 0000000..ed05d04 --- /dev/null +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "DeferredLayerUpdater.h" + +#include "OpenGLRenderer.h" + +#include "LayerRenderer.h" + +namespace android { +namespace uirenderer { + +DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, OpenGLRenderer* renderer) + : mDisplayList(0) + , mSurfaceTexture(0) + , mTransform(0) + , mNeedsGLContextAttach(false) + , mUpdateTexImage(false) + , mLayer(layer) + , mRenderer(renderer) + , mCaches(Caches::getInstance()) { + mCaches.resourceCache.incrementRefcount(mLayer); + mWidth = mLayer->layer.getWidth(); + mHeight = mLayer->layer.getHeight(); + mBlend = mLayer->isBlend(); + mColorFilter = mLayer->getColorFilter(); + mAlpha = mLayer->getAlpha(); + mMode = mLayer->getMode(); + mDirtyRect.setEmpty(); +} + +DeferredLayerUpdater::~DeferredLayerUpdater() { + setColorFilter(NULL); + if (mLayer) { + mCaches.resourceCache.decrementRefcount(mLayer); + } + delete mRenderer; +} + +void DeferredLayerUpdater::setColorFilter(SkColorFilter* colorFilter) { + SkRefCnt_SafeAssign(mColorFilter, colorFilter); +} + +void DeferredLayerUpdater::setDisplayList(DisplayList* displayList, + int left, int top, int right, int bottom) { + mDisplayList = displayList; + if (mDirtyRect.isEmpty()) { + mDirtyRect.set(left, top, right, bottom); + } else { + mDirtyRect.unionWith(Rect(left, top, right, bottom)); + } +} + +bool DeferredLayerUpdater::apply() { + bool success = true; + // These properties are applied the same to both layer types + mLayer->setColorFilter(mColorFilter); + mLayer->setAlpha(mAlpha, mMode); + + if (mDisplayList) { + if (mWidth != mLayer->layer.getWidth() || mHeight != mLayer->layer.getHeight()) { + success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight); + } + mLayer->setBlend(mBlend); + mLayer->updateDeferred(mRenderer, mDisplayList, + mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom); + mDirtyRect.setEmpty(); + mDisplayList = 0; + } else if (mSurfaceTexture.get()) { + if (mNeedsGLContextAttach) { + mNeedsGLContextAttach = false; + mSurfaceTexture->attachToContext(mLayer->getTexture()); + } + if (mUpdateTexImage) { + mUpdateTexImage = false; + doUpdateTexImage(); + } + if (mTransform) { + mLayer->getTransform().load(*mTransform); + setTransform(0); + } + } + return success; +} + +void DeferredLayerUpdater::doUpdateTexImage() { + if (mSurfaceTexture->updateTexImage() == NO_ERROR) { + float transform[16]; + + int64_t frameNumber = mSurfaceTexture->getFrameNumber(); + // If the GLConsumer queue is in synchronous mode, need to discard all + // but latest frame, using the frame number to tell when we no longer + // have newer frames to target. Since we can't tell which mode it is in, + // do this unconditionally. + int dropCounter = 0; + while (mSurfaceTexture->updateTexImage() == NO_ERROR) { + int64_t newFrameNumber = mSurfaceTexture->getFrameNumber(); + if (newFrameNumber == frameNumber) break; + frameNumber = newFrameNumber; + dropCounter++; + } + #if DEBUG_RENDERER + if (dropCounter > 0) { + RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter); + } + #endif + mSurfaceTexture->getTransformMatrix(transform); + GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget(); + + LayerRenderer::updateTextureLayer(mLayer, mWidth, mHeight, !mBlend, + renderTarget, transform); + } +} + +void DeferredLayerUpdater::applyDeferred(DeferredLayerUpdater* deferredApply) { + // Default assignment operator doesn't quite work, and fails due to mCaches anyway + deferredApply->mWidth = mWidth; + deferredApply->mHeight = mHeight; + deferredApply->mBlend = mBlend; + deferredApply->mAlpha = mAlpha; + deferredApply->mMode = mMode; + deferredApply->mDirtyRect.set(mDirtyRect); + deferredApply->mDisplayList = mDisplayList; + deferredApply->mSurfaceTexture = mSurfaceTexture; + deferredApply->mNeedsGLContextAttach = mNeedsGLContextAttach; + deferredApply->mUpdateTexImage = mUpdateTexImage; + deferredApply->setColorFilter(mColorFilter); + deferredApply->setTransform(mTransform); + + mDisplayList = 0; + mDirtyRect.setEmpty(); + mTransform = 0; + mNeedsGLContextAttach = false; + mUpdateTexImage = false; +} + +} /* namespace uirenderer */ +} /* namespace android */ diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h new file mode 100644 index 0000000..0350eef --- /dev/null +++ b/libs/hwui/DeferredLayerUpdater.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef DEFERREDLAYERUPDATE_H_ +#define DEFERREDLAYERUPDATE_H_ + +#include <cutils/compiler.h> +#include <gui/GLConsumer.h> +#include <SkColorFilter.h> +#include <SkMatrix.h> +#include <utils/StrongPointer.h> + +#include "DisplayList.h" +#include "Layer.h" +#include "OpenGLRenderer.h" +#include "Rect.h" + +namespace android { +namespace uirenderer { + +// Container to hold the properties a layer should be set to at the start +// of a render pass +class DeferredLayerUpdater { +public: + ANDROID_API DeferredLayerUpdater(Layer* layer, OpenGLRenderer* renderer = 0); + ANDROID_API ~DeferredLayerUpdater(); + + ANDROID_API bool setSize(uint32_t width, uint32_t height) { + if (mWidth != width || mHeight != height) { + mWidth = width; + mHeight = height; + return true; + } + return false; + } + + ANDROID_API bool setBlend(bool blend) { + if (blend != mBlend) { + mBlend = blend; + return true; + } + return false; + } + + ANDROID_API void setSurfaceTexture(const sp<GLConsumer>& texture, bool needsAttach) { + if (texture.get() != mSurfaceTexture.get()) { + mNeedsGLContextAttach = needsAttach; + mSurfaceTexture = texture; + } + } + + ANDROID_API void updateTexImage() { + mUpdateTexImage = true; + } + + ANDROID_API void setTransform(const SkMatrix* matrix) { + delete mTransform; + mTransform = matrix ? new SkMatrix(*matrix) : 0; + } + + ANDROID_API void setDisplayList(DisplayList* displayList, + int left, int top, int right, int bottom); + + ANDROID_API void setPaint(const SkPaint* paint) { + OpenGLRenderer::getAlphaAndModeDirect(paint, &mAlpha, &mMode); + } + + ANDROID_API void setColorFilter(SkColorFilter* colorFilter); + + ANDROID_API bool apply(); + ANDROID_API void applyDeferred(DeferredLayerUpdater* deferredApply); + + ANDROID_API Layer* backingLayer() { + return mLayer; + } + + ANDROID_API Layer* detachBackingLayer() { + Layer* layer = mLayer; + mLayer = 0; + return layer; + } + +private: + // Generic properties + uint32_t mWidth; + uint32_t mHeight; + bool mBlend; + SkColorFilter* mColorFilter; + int mAlpha; + SkXfermode::Mode mMode; + + // Layer type specific properties + // displayList and surfaceTexture are mutually exclusive, only 1 may be set + // dirtyRect is only valid if displayList is set + DisplayList* mDisplayList; + Rect mDirtyRect; + sp<GLConsumer> mSurfaceTexture; + SkMatrix* mTransform; + bool mNeedsGLContextAttach; + bool mUpdateTexImage; + + Layer* mLayer; + OpenGLRenderer* mRenderer; + Caches& mCaches; + + void doUpdateTexImage(); +}; + +} /* namespace uirenderer */ +} /* namespace android */ + +#endif /* DEFERREDLAYERUPDATE_H_ */ diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 0b38c4d..ea8eb31 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -184,7 +184,7 @@ void LayerRenderer::generateMesh() { // Layers management /////////////////////////////////////////////////////////////////////////////// -Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) { +Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) { LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height); Caches& caches = Caches::getInstance(); @@ -221,7 +221,6 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque layer->texCoords.set(0.0f, height / float(layer->getHeight()), width / float(layer->getWidth()), 0.0f); layer->setAlpha(255, SkXfermode::kSrcOver_Mode); - layer->setBlend(!isOpaque); layer->setColorFilter(NULL); layer->setDirty(true); layer->region.clear(); @@ -270,13 +269,12 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) { return true; } -Layer* LayerRenderer::createTextureLayer(bool isOpaque) { +Layer* LayerRenderer::createTextureLayer() { LAYER_RENDERER_LOGD("Creating new texture layer"); Layer* layer = new Layer(0, 0); layer->setCacheable(false); layer->setTextureLayer(true); - layer->setBlend(!isOpaque); layer->setEmpty(true); layer->setFbo(0); layer->setAlpha(255, SkXfermode::kSrcOver_Mode); diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index f24c8d4..84acd44 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -52,8 +52,8 @@ public: virtual status_t clear(float left, float top, float right, float bottom, bool opaque); virtual void finish(); - ANDROID_API static Layer* createTextureLayer(bool isOpaque); - ANDROID_API static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false); + ANDROID_API static Layer* createTextureLayer(); + ANDROID_API static Layer* createRenderLayer(uint32_t width, uint32_t height); ANDROID_API static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height); ANDROID_API static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, bool isOpaque, GLenum renderTarget, float* transform); diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java index 0b85189..8d8d9de 100644 --- a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java +++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java @@ -97,7 +97,7 @@ abstract public class CompareActivity extends Activity { Log.d(LOG_TAG, "failure to access hardware layer"); return; } - Method copyInto = hardwareLayer.getClass().getSuperclass() + Method copyInto = hardwareLayer.getClass() .getDeclaredMethod("copyInto", Bitmap.class); if (!copyInto.isAccessible()) copyInto.setAccessible(true); diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java index a08b558..c90b626 100644 --- a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java +++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java @@ -35,23 +35,24 @@ public class ErrorCalculator { private static final boolean LOG_TIMING = false; private static final boolean LOG_CALC = false; - private final RenderScript mRS; + private RenderScript mRS; private Allocation mIdealPixelsAllocation; private Allocation mGivenPixelsAllocation; private Allocation mOutputPixelsAllocation; - private final Allocation mInputRowsAllocation; - private final Allocation mOutputRegionsAllocation; + private Allocation mInputRowsAllocation; + private Allocation mOutputRegionsAllocation; - private final ScriptC_errorCalculator mScript; + private ScriptC_errorCalculator mScript; - private final int[] mOutputRowRegions; + private int[] mOutputRowRegions; public ErrorCalculator(Context c, Resources resources) { int width = resources.getDimensionPixelSize(R.dimen.layer_width); int height = resources.getDimensionPixelSize(R.dimen.layer_height); mOutputRowRegions = new int[height / REGION_SIZE]; +/* mRS = RenderScript.create(c); int[] rowIndices = new int[height / REGION_SIZE]; for (int i = 0; i < rowIndices.length; i++) @@ -67,12 +68,15 @@ public class ErrorCalculator { mInputRowsAllocation.copyFrom(rowIndices); mOutputRegionsAllocation = Allocation.createSized(mRS, Element.I32(mRS), mOutputRowRegions.length, Allocation.USAGE_SCRIPT); +*/ } private static long startMillis, middleMillis; public float calcErrorRS(Bitmap ideal, Bitmap given) { + if (true) + return calcError(ideal, given); if (LOG_TIMING) { startMillis = System.currentTimeMillis(); } |