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:
John Reck
2014-05-29 18:56:11 -07:00
parent aee470c023
commit d72e0a339b
15 changed files with 135 additions and 195 deletions

View File

@@ -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

View File

@@ -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;
}
}
}
}

View File

@@ -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.

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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) {

View File

@@ -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();
};

View File

@@ -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());
}
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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 */

View File

@@ -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) {

View File

@@ -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);