Re-jigger layers
Bug: 15185239 Bug: 15238382 Make DeferredLayerUpdater ref counted so that HardwareLayer:finalizer() works non-crashily on leaked layers Give DeferredLayerUpdater the ability to have a layer destroyer set so that leaked layers can still be recycled on the RenderThread Order layer updates based off of pushLayerUpdate() calls to fix issue with nested layers Change-Id: I4449cee607f7e5126e02fed7464cf48038e3dfdf
This commit is contained in:
@@ -178,7 +178,7 @@ 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 List<HardwareLayer> mLayerUpdates = new ArrayList<HardwareLayer>();
|
||||
|
||||
private static class GLRendererEglContext extends ManagedEGLContext {
|
||||
final Handler mHandler = new Handler();
|
||||
@@ -471,7 +471,7 @@ public class GLRenderer extends HardwareRenderer {
|
||||
|
||||
@Override
|
||||
void pushLayerUpdate(HardwareLayer layer) {
|
||||
mGlCanvas.pushLayerUpdate(layer);
|
||||
mLayerUpdates.add(layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -494,11 +494,6 @@ public class GLRenderer extends HardwareRenderer {
|
||||
return HardwareLayer.createDisplayListLayer(this, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onLayerCreated(HardwareLayer hardwareLayer) {
|
||||
mAttachedLayers.add(hardwareLayer);
|
||||
}
|
||||
|
||||
boolean hasContext() {
|
||||
return sEgl != null && mEglContext != null
|
||||
&& mEglContext.equals(sEgl.eglGetCurrentContext());
|
||||
@@ -509,11 +504,7 @@ public class GLRenderer extends HardwareRenderer {
|
||||
if (mGlCanvas != null) {
|
||||
mGlCanvas.cancelLayerUpdate(layer);
|
||||
}
|
||||
if (hasContext()) {
|
||||
long backingLayer = layer.detachBackingLayer();
|
||||
nDestroyLayer(backingLayer);
|
||||
}
|
||||
mAttachedLayers.remove(layer);
|
||||
mLayerUpdates.remove(layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1198,16 +1189,19 @@ 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);
|
||||
for (int i = 0; i < mLayerUpdates.size(); i++) {
|
||||
HardwareLayer layer = mLayerUpdates.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--;
|
||||
} else if (layer.hasDisplayList()) {
|
||||
mCanvas.pushLayerUpdate(layer);
|
||||
}
|
||||
}
|
||||
mLayerUpdates.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,6 +22,8 @@ import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.SurfaceTexture;
|
||||
|
||||
import com.android.internal.util.VirtualRefBasePtr;
|
||||
|
||||
/**
|
||||
* A hardware layer can be used to render graphics operations into a hardware
|
||||
* friendly buffer. For instance, with an OpenGL backend a hardware layer
|
||||
@@ -36,7 +38,7 @@ final class HardwareLayer {
|
||||
private static final int LAYER_TYPE_DISPLAY_LIST = 2;
|
||||
|
||||
private HardwareRenderer mRenderer;
|
||||
private Finalizer mFinalizer;
|
||||
private VirtualRefBasePtr mFinalizer;
|
||||
private RenderNode mDisplayList;
|
||||
private final int mLayerType;
|
||||
|
||||
@@ -47,10 +49,7 @@ final class HardwareLayer {
|
||||
}
|
||||
mRenderer = renderer;
|
||||
mLayerType = type;
|
||||
mFinalizer = new Finalizer(deferredUpdater);
|
||||
|
||||
// Layer is considered initialized at this point, notify the HardwareRenderer
|
||||
mRenderer.onLayerCreated(this);
|
||||
mFinalizer = new VirtualRefBasePtr(deferredUpdater);
|
||||
}
|
||||
|
||||
private void assertType(int type) {
|
||||
@@ -59,6 +58,10 @@ final class HardwareLayer {
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasDisplayList() {
|
||||
return mDisplayList != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the paint used when drawing this layer.
|
||||
*
|
||||
@@ -66,7 +69,8 @@ final class HardwareLayer {
|
||||
* @see View#setLayerPaint(android.graphics.Paint)
|
||||
*/
|
||||
public void setLayerPaint(Paint paint) {
|
||||
nSetLayerPaint(mFinalizer.mDeferredUpdater, paint.mNativePaint);
|
||||
nSetLayerPaint(mFinalizer.get(), paint.mNativePaint);
|
||||
mRenderer.pushLayerUpdate(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +79,7 @@ final class HardwareLayer {
|
||||
* @return True if the layer can be rendered into, false otherwise
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return mFinalizer != null && mFinalizer.mDeferredUpdater != 0;
|
||||
return mFinalizer != null && mFinalizer.get() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,35 +95,14 @@ final class HardwareLayer {
|
||||
mDisplayList.destroyDisplayListData();
|
||||
mDisplayList = null;
|
||||
}
|
||||
if (mRenderer != null) {
|
||||
mRenderer.onLayerDestroyed(this);
|
||||
mRenderer = null;
|
||||
}
|
||||
doDestroyLayerUpdater();
|
||||
mRenderer.onLayerDestroyed(this);
|
||||
mRenderer = null;
|
||||
mFinalizer.release();
|
||||
mFinalizer = null;
|
||||
}
|
||||
|
||||
public long getDeferredLayerUpdater() {
|
||||
return mFinalizer.mDeferredUpdater;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* It is safe to call this in onLayerDestroyed only
|
||||
*/
|
||||
public long detachBackingLayer() {
|
||||
long backingLayer = nDetachBackingLayer(mFinalizer.mDeferredUpdater);
|
||||
doDestroyLayerUpdater();
|
||||
return backingLayer;
|
||||
}
|
||||
|
||||
private void doDestroyLayerUpdater() {
|
||||
if (mFinalizer != null) {
|
||||
mFinalizer.destroy();
|
||||
mFinalizer = null;
|
||||
}
|
||||
return mFinalizer.get();
|
||||
}
|
||||
|
||||
public RenderNode startRecording() {
|
||||
@@ -132,7 +115,7 @@ final class HardwareLayer {
|
||||
}
|
||||
|
||||
public void endRecording(Rect dirtyRect) {
|
||||
nUpdateRenderLayer(mFinalizer.mDeferredUpdater, mDisplayList.getNativeDisplayList(),
|
||||
nUpdateRenderLayer(mFinalizer.get(), mDisplayList.getNativeDisplayList(),
|
||||
dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom);
|
||||
mRenderer.pushLayerUpdate(this);
|
||||
}
|
||||
@@ -160,7 +143,7 @@ final class HardwareLayer {
|
||||
* match the desired values.
|
||||
*/
|
||||
public boolean prepare(int width, int height, boolean isOpaque) {
|
||||
return nPrepare(mFinalizer.mDeferredUpdater, width, height, isOpaque);
|
||||
return nPrepare(mFinalizer.get(), width, height, isOpaque);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,7 +152,8 @@ final class HardwareLayer {
|
||||
* @param matrix The transform to apply to the layer.
|
||||
*/
|
||||
public void setTransform(Matrix matrix) {
|
||||
nSetTransform(mFinalizer.mDeferredUpdater, matrix.native_instance);
|
||||
nSetTransform(mFinalizer.get(), matrix.native_instance);
|
||||
mRenderer.pushLayerUpdate(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,7 +167,7 @@ final class HardwareLayer {
|
||||
surface.detachFromGLContext();
|
||||
// SurfaceTexture owns the texture name and detachFromGLContext
|
||||
// should have deleted it
|
||||
nOnTextureDestroyed(mFinalizer.mDeferredUpdater);
|
||||
nOnTextureDestroyed(mFinalizer.get());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -200,24 +184,26 @@ final class HardwareLayer {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean success = nFlushChanges(mFinalizer.mDeferredUpdater);
|
||||
boolean success = nFlushChanges(mFinalizer.get());
|
||||
if (!success) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public long getLayer() {
|
||||
return nGetLayer(mFinalizer.mDeferredUpdater);
|
||||
return nGetLayer(mFinalizer.get());
|
||||
}
|
||||
|
||||
public void setSurfaceTexture(SurfaceTexture surface) {
|
||||
assertType(LAYER_TYPE_TEXTURE);
|
||||
nSetSurfaceTexture(mFinalizer.mDeferredUpdater, surface, false);
|
||||
nSetSurfaceTexture(mFinalizer.get(), surface, false);
|
||||
mRenderer.pushLayerUpdate(this);
|
||||
}
|
||||
|
||||
public void updateSurfaceTexture() {
|
||||
assertType(LAYER_TYPE_TEXTURE);
|
||||
nUpdateSurfaceTexture(mFinalizer.mDeferredUpdater);
|
||||
nUpdateSurfaceTexture(mFinalizer.get());
|
||||
mRenderer.pushLayerUpdate(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,8 +211,8 @@ final class HardwareLayer {
|
||||
*/
|
||||
SurfaceTexture createSurfaceTexture() {
|
||||
assertType(LAYER_TYPE_TEXTURE);
|
||||
SurfaceTexture st = new SurfaceTexture(nGetTexName(mFinalizer.mDeferredUpdater));
|
||||
nSetSurfaceTexture(mFinalizer.mDeferredUpdater, st, true);
|
||||
SurfaceTexture st = new SurfaceTexture(nGetTexName(mFinalizer.get()));
|
||||
nSetSurfaceTexture(mFinalizer.get(), st, true);
|
||||
return st;
|
||||
}
|
||||
|
||||
@@ -258,15 +244,6 @@ final class HardwareLayer {
|
||||
private static native long nCreateRenderLayer(int width, int height);
|
||||
|
||||
private static native void nOnTextureDestroyed(long layerUpdater);
|
||||
private static native long nDetachBackingLayer(long layerUpdater);
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
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);
|
||||
@@ -281,28 +258,4 @@ final class HardwareLayer {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,12 +322,6 @@ public abstract class HardwareRenderer {
|
||||
*/
|
||||
abstract void pushLayerUpdate(HardwareLayer layer);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
||||
@@ -294,12 +294,7 @@ public class ThreadedRenderer extends HardwareRenderer {
|
||||
|
||||
@Override
|
||||
void pushLayerUpdate(HardwareLayer layer) {
|
||||
// TODO: Remove this, it's not needed outside of GLRenderer
|
||||
}
|
||||
|
||||
@Override
|
||||
void onLayerCreated(HardwareLayer layer) {
|
||||
// TODO: Is this actually useful?
|
||||
nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -309,7 +304,7 @@ public class ThreadedRenderer extends HardwareRenderer {
|
||||
|
||||
@Override
|
||||
void onLayerDestroyed(HardwareLayer layer) {
|
||||
nDestroyLayer(mNativeProxy, layer.getDeferredLayerUpdater());
|
||||
nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -398,7 +393,8 @@ public class ThreadedRenderer extends HardwareRenderer {
|
||||
private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
|
||||
private static native long nCreateTextureLayer(long nativeProxy);
|
||||
private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
|
||||
private static native void nDestroyLayer(long nativeProxy, long layer);
|
||||
private static native void nPushLayerUpdate(long nativeProxy, long layer);
|
||||
private static native void nCancelLayerUpdate(long nativeProxy, long layer);
|
||||
|
||||
private static native void nFlushCaches(long nativeProxy, int flushMode);
|
||||
|
||||
|
||||
@@ -32,11 +32,17 @@ public final class VirtualRefBasePtr {
|
||||
return mNativePtr;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
if (mNativePtr != 0) {
|
||||
nDecStrong(mNativePtr);
|
||||
mNativePtr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
nDecStrong(mNativePtr);
|
||||
mNativePtr = 0;
|
||||
release();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
@@ -55,9 +55,7 @@ static jlong android_view_HardwareLayer_createRenderLayer(JNIEnv* env, jobject c
|
||||
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) );
|
||||
return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer) );
|
||||
}
|
||||
|
||||
static void android_view_HardwareLayer_onTextureDestroyed(JNIEnv* env, jobject clazz,
|
||||
@@ -66,18 +64,6 @@ static void android_view_HardwareLayer_onTextureDestroyed(JNIEnv* env, jobject c
|
||||
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);
|
||||
@@ -157,8 +143,6 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "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", "(JJ)V", (void*) android_view_HardwareLayer_setLayerPaint },
|
||||
|
||||
@@ -287,11 +287,18 @@ static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject
|
||||
return proxy->copyLayerInto(layer, bitmap);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_destroyLayer(JNIEnv* env, jobject clazz,
|
||||
static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jlong layerPtr) {
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
|
||||
proxy->destroyLayer(layer);
|
||||
proxy->pushLayerUpdate(layer);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jlong layerPtr) {
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
|
||||
proxy->cancelLayerUpdate(layer);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_flushCaches(JNIEnv* env, jobject clazz,
|
||||
@@ -347,7 +354,8 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
|
||||
{ "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
|
||||
{ "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
|
||||
{ "nDestroyLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_destroyLayer },
|
||||
{ "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
|
||||
{ "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
|
||||
{ "nFlushCaches", "(JI)V", (void*) android_view_ThreadedRenderer_flushCaches },
|
||||
{ "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
|
||||
{ "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
|
||||
|
||||
@@ -22,14 +22,19 @@
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, OpenGLRenderer* renderer)
|
||||
static void defaultLayerDestroyer(Layer* layer) {
|
||||
Caches::getInstance().resourceCache.decrementRefcount(layer);
|
||||
}
|
||||
|
||||
DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, LayerDestroyer destroyer)
|
||||
: mDisplayList(0)
|
||||
, mSurfaceTexture(0)
|
||||
, mTransform(0)
|
||||
, mNeedsGLContextAttach(false)
|
||||
, mUpdateTexImage(false)
|
||||
, mLayer(layer)
|
||||
, mCaches(Caches::getInstance()) {
|
||||
, mCaches(Caches::getInstance())
|
||||
, mDestroyer(destroyer) {
|
||||
mWidth = mLayer->layer.getWidth();
|
||||
mHeight = mLayer->layer.getHeight();
|
||||
mBlend = mLayer->isBlend();
|
||||
@@ -37,14 +42,16 @@ DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, OpenGLRenderer* rendere
|
||||
mAlpha = mLayer->getAlpha();
|
||||
mMode = mLayer->getMode();
|
||||
mDirtyRect.setEmpty();
|
||||
|
||||
if (!mDestroyer) {
|
||||
mDestroyer = defaultLayerDestroyer;
|
||||
}
|
||||
}
|
||||
|
||||
DeferredLayerUpdater::~DeferredLayerUpdater() {
|
||||
SkSafeUnref(mColorFilter);
|
||||
setTransform(0);
|
||||
if (mLayer) {
|
||||
mCaches.resourceCache.decrementRefcount(mLayer);
|
||||
}
|
||||
mDestroyer(mLayer);
|
||||
}
|
||||
|
||||
void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
|
||||
|
||||
@@ -30,13 +30,15 @@
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
typedef void (*LayerDestroyer)(Layer* layer);
|
||||
|
||||
// Container to hold the properties a layer should be set to at the start
|
||||
// of a render pass
|
||||
class DeferredLayerUpdater {
|
||||
class DeferredLayerUpdater : public VirtualLightRefBase {
|
||||
public:
|
||||
// Note that DeferredLayerUpdater assumes it is taking ownership of the layer
|
||||
// and will not call incrementRef on it as a result.
|
||||
ANDROID_API DeferredLayerUpdater(Layer* layer, OpenGLRenderer* renderer = 0);
|
||||
ANDROID_API DeferredLayerUpdater(Layer* layer, LayerDestroyer = 0);
|
||||
ANDROID_API ~DeferredLayerUpdater();
|
||||
|
||||
ANDROID_API bool setSize(uint32_t width, uint32_t height) {
|
||||
@@ -83,12 +85,6 @@ public:
|
||||
return mLayer;
|
||||
}
|
||||
|
||||
ANDROID_API Layer* detachBackingLayer() {
|
||||
Layer* layer = mLayer;
|
||||
mLayer = 0;
|
||||
return layer;
|
||||
}
|
||||
|
||||
private:
|
||||
// Generic properties
|
||||
uint32_t mWidth;
|
||||
@@ -111,6 +107,8 @@ private:
|
||||
Layer* mLayer;
|
||||
Caches& mCaches;
|
||||
|
||||
LayerDestroyer mDestroyer;
|
||||
|
||||
void doUpdateTexImage();
|
||||
};
|
||||
|
||||
|
||||
@@ -427,27 +427,11 @@ void CanvasContext::makeCurrent() {
|
||||
mHaveNewSurface |= mGlobalContext->makeCurrent(mEglSurface);
|
||||
}
|
||||
|
||||
void CanvasContext::prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters,
|
||||
TreeInfo& info) {
|
||||
LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot prepareDraw without a canvas!");
|
||||
makeCurrent();
|
||||
|
||||
processLayerUpdates(layerUpdaters, info);
|
||||
if (info.out.hasAnimations) {
|
||||
// TODO: Uh... crap?
|
||||
}
|
||||
prepareTree(info);
|
||||
}
|
||||
|
||||
void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
|
||||
TreeInfo& info) {
|
||||
for (size_t i = 0; i < layerUpdaters->size(); i++) {
|
||||
DeferredLayerUpdater* update = layerUpdaters->itemAt(i);
|
||||
bool success = update->apply(info);
|
||||
LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!");
|
||||
if (update->backingLayer()->deferredUpdateScheduled) {
|
||||
mCanvas->pushLayerUpdate(update->backingLayer());
|
||||
}
|
||||
void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater, TreeInfo& info) {
|
||||
bool success = layerUpdater->apply(info);
|
||||
LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!");
|
||||
if (layerUpdater->backingLayer()->deferredUpdateScheduled) {
|
||||
mCanvas->pushLayerUpdate(layerUpdater->backingLayer());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ public:
|
||||
void setup(int width, int height, const Vector3& lightCenter, float lightRadius);
|
||||
void setOpaque(bool opaque);
|
||||
void makeCurrent();
|
||||
void prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
|
||||
void processLayerUpdate(DeferredLayerUpdater* layerUpdater, TreeInfo& info);
|
||||
void prepareTree(TreeInfo& info);
|
||||
void draw(Rect* dirty);
|
||||
void destroyCanvasAndSurface();
|
||||
|
||||
@@ -83,9 +84,6 @@ public:
|
||||
private:
|
||||
friend class RegisterFrameCallbackTask;
|
||||
|
||||
void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
|
||||
void prepareTree(TreeInfo& info);
|
||||
|
||||
void setSurface(ANativeWindow* window);
|
||||
void swapBuffers();
|
||||
void requireSurface();
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Trace.h>
|
||||
|
||||
#include "../DeferredLayerUpdater.h"
|
||||
#include "../DisplayList.h"
|
||||
#include "../RenderNode.h"
|
||||
#include "CanvasContext.h"
|
||||
@@ -47,17 +48,22 @@ void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) {
|
||||
LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to addLayer with!");
|
||||
void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
|
||||
LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to pushLayerUpdate with!");
|
||||
|
||||
mLayers.push(layer);
|
||||
for (size_t i = 0; i < mLayers.size(); i++) {
|
||||
if (mLayers[i].get() == layer) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mLayers.push_back(layer);
|
||||
}
|
||||
|
||||
void DrawFrameTask::removeLayer(DeferredLayerUpdater* layer) {
|
||||
void DrawFrameTask::removeLayerUpdate(DeferredLayerUpdater* layer) {
|
||||
for (size_t i = 0; i < mLayers.size(); i++) {
|
||||
if (mLayers[i] == layer) {
|
||||
mLayers.removeAt(i);
|
||||
break;
|
||||
if (mLayers[i].get() == layer) {
|
||||
mLayers.erase(mLayers.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,7 +138,16 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
|
||||
mContext->makeCurrent();
|
||||
Caches::getInstance().textureCache.resetMarkInUse();
|
||||
initTreeInfo(info);
|
||||
mContext->prepareDraw(&mLayers, info);
|
||||
|
||||
for (size_t i = 0; i < mLayers.size(); i++) {
|
||||
mContext->processLayerUpdate(mLayers[i].get(), info);
|
||||
}
|
||||
mLayers.clear();
|
||||
if (info.out.hasAnimations) {
|
||||
// TODO: Uh... crap?
|
||||
}
|
||||
mContext->prepareTree(info);
|
||||
|
||||
if (info.out.hasAnimations) {
|
||||
// TODO: dirty calculations, for now just do a full-screen inval
|
||||
mDirty.setEmpty();
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
#ifndef DRAWFRAMETASK_H
|
||||
#define DRAWFRAMETASK_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <utils/Condition.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
#include <utils/Vector.h>
|
||||
|
||||
#include "RenderTask.h"
|
||||
|
||||
@@ -56,8 +57,8 @@ public:
|
||||
|
||||
void setContext(RenderThread* thread, CanvasContext* context);
|
||||
|
||||
void addLayer(DeferredLayerUpdater* layer);
|
||||
void removeLayer(DeferredLayerUpdater* layer);
|
||||
void pushLayerUpdate(DeferredLayerUpdater* layer);
|
||||
void removeLayerUpdate(DeferredLayerUpdater* layer);
|
||||
|
||||
void setDirty(int left, int top, int right, int bottom);
|
||||
void setDensity(float density) { mDensity = density; }
|
||||
@@ -83,13 +84,9 @@ private:
|
||||
nsecs_t mFrameTimeNanos;
|
||||
nsecs_t mRecordDurationNanos;
|
||||
float mDensity;
|
||||
std::vector< sp<DeferredLayerUpdater> > mLayers;
|
||||
|
||||
int mSyncResult;
|
||||
|
||||
/*********************************************
|
||||
* Multi frame data
|
||||
*********************************************/
|
||||
Vector<DeferredLayerUpdater*> mLayers;
|
||||
};
|
||||
|
||||
} /* namespace renderthread */
|
||||
|
||||
@@ -229,10 +229,21 @@ void RenderProxy::runWithGlContext(RenderTask* gltask) {
|
||||
postAndWait(task);
|
||||
}
|
||||
|
||||
CREATE_BRIDGE1(destroyLayer, Layer* layer) {
|
||||
LayerRenderer::destroyLayer(args->layer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void enqueueDestroyLayer(Layer* layer) {
|
||||
SETUP_TASK(destroyLayer);
|
||||
args->layer = layer;
|
||||
RenderThread::getInstance().queue(task);
|
||||
}
|
||||
|
||||
CREATE_BRIDGE3(createDisplayListLayer, CanvasContext* context, int width, int height) {
|
||||
Layer* layer = args->context->createRenderLayer(args->width, args->height);
|
||||
if (!layer) return 0;
|
||||
return new DeferredLayerUpdater(layer);
|
||||
return new DeferredLayerUpdater(layer, enqueueDestroyLayer);
|
||||
}
|
||||
|
||||
DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) {
|
||||
@@ -242,14 +253,13 @@ DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height)
|
||||
args->context = mContext;
|
||||
void* retval = postAndWait(task);
|
||||
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
|
||||
mDrawFrameTask.addLayer(layer);
|
||||
return layer;
|
||||
}
|
||||
|
||||
CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
|
||||
Layer* layer = args->context->createTextureLayer();
|
||||
if (!layer) return 0;
|
||||
return new DeferredLayerUpdater(layer);
|
||||
return new DeferredLayerUpdater(layer, enqueueDestroyLayer);
|
||||
}
|
||||
|
||||
DeferredLayerUpdater* RenderProxy::createTextureLayer() {
|
||||
@@ -257,15 +267,9 @@ DeferredLayerUpdater* RenderProxy::createTextureLayer() {
|
||||
args->context = mContext;
|
||||
void* retval = postAndWait(task);
|
||||
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
|
||||
mDrawFrameTask.addLayer(layer);
|
||||
return layer;
|
||||
}
|
||||
|
||||
CREATE_BRIDGE1(destroyLayer, Layer* layer) {
|
||||
LayerRenderer::destroyLayer(args->layer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
|
||||
SkBitmap* bitmap) {
|
||||
bool success = args->context->copyLayerInto(args->layer, args->bitmap);
|
||||
@@ -280,11 +284,12 @@ bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
|
||||
return (bool) postAndWait(task);
|
||||
}
|
||||
|
||||
void RenderProxy::destroyLayer(DeferredLayerUpdater* layer) {
|
||||
mDrawFrameTask.removeLayer(layer);
|
||||
SETUP_TASK(destroyLayer);
|
||||
args->layer = layer->detachBackingLayer();
|
||||
post(task);
|
||||
void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
|
||||
mDrawFrameTask.pushLayerUpdate(layer);
|
||||
}
|
||||
|
||||
void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) {
|
||||
mDrawFrameTask.removeLayerUpdate(layer);
|
||||
}
|
||||
|
||||
CREATE_BRIDGE2(flushCaches, CanvasContext* context, Caches::FlushMode flushMode) {
|
||||
|
||||
@@ -80,7 +80,8 @@ public:
|
||||
ANDROID_API DeferredLayerUpdater* createDisplayListLayer(int width, int height);
|
||||
ANDROID_API DeferredLayerUpdater* createTextureLayer();
|
||||
ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
|
||||
ANDROID_API void destroyLayer(DeferredLayerUpdater* layer);
|
||||
ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer);
|
||||
ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
|
||||
|
||||
ANDROID_API void flushCaches(Caches::FlushMode flushMode);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user