summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/view/GLES20Canvas.java34
-rw-r--r--core/java/android/view/GLES20Layer.java100
-rw-r--r--core/java/android/view/GLES20RenderLayer.java130
-rw-r--r--core/java/android/view/GLES20TextureLayer.java108
-rw-r--r--core/java/android/view/GLRenderer.java51
-rw-r--r--core/java/android/view/HardwareLayer.java328
-rw-r--r--core/java/android/view/HardwareRenderer.java34
-rw-r--r--core/java/android/view/TextureView.java9
-rw-r--r--core/java/android/view/ThreadedRenderer.java14
-rw-r--r--core/java/android/view/View.java56
-rw-r--r--core/java/android/view/ViewRootImpl.java6
11 files changed, 281 insertions, 589 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()) {