summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2014-02-11 17:30:53 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-02-11 17:30:53 +0000
commitf6eebb21d5c58345eca8be25676e34346f5809b2 (patch)
tree1a86b74f2bb3fd44f4dff4422affe9ce79938946
parentfaa91f852e9526b2f112122da9ae0956526cf662 (diff)
parent04fc583c3dd3144bc6b718fcac4b3e1afdfdb067 (diff)
downloadframeworks_base-f6eebb21d5c58345eca8be25676e34346f5809b2.zip
frameworks_base-f6eebb21d5c58345eca8be25676e34346f5809b2.tar.gz
frameworks_base-f6eebb21d5c58345eca8be25676e34346f5809b2.tar.bz2
Merge "Refactor HardwareLayer"
-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
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp156
-rw-r--r--core/jni/android_view_HardwareLayer.cpp183
-rw-r--r--libs/hwui/Android.mk3
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp150
-rw-r--r--libs/hwui/DeferredLayerUpdater.h124
-rw-r--r--libs/hwui/LayerRenderer.cpp6
-rw-r--r--libs/hwui/LayerRenderer.h4
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java2
-rw-r--r--tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java14
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();
}