Fix some edge cases
Bug: 27709981 This desperately needs a refactor, but to keep the current (really needed & nice) behavior of dispatching after sync finishes would be difficult to handle cleanly without lots of ripping so... #yolo Change-Id: I831a06c6ae7412a062720d68ecbe3085190f0258
This commit is contained in:
@@ -794,8 +794,7 @@ public final class ThreadedRenderer {
|
||||
}
|
||||
|
||||
final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
|
||||
int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length,
|
||||
mRootNode.mNativeRenderNode);
|
||||
int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
|
||||
if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
|
||||
setEnabled(false);
|
||||
attachInfo.mViewRootImpl.mSurface.release();
|
||||
@@ -994,8 +993,7 @@ public final class ThreadedRenderer {
|
||||
private static native void nSetLightCenter(long nativeProxy,
|
||||
float lightX, float lightY, float lightZ);
|
||||
private static native void nSetOpaque(long nativeProxy, boolean opaque);
|
||||
private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size,
|
||||
long rootRenderNode);
|
||||
private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
|
||||
private static native void nDestroy(long nativeProxy, long rootRenderNode);
|
||||
private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
|
||||
|
||||
|
||||
@@ -128,9 +128,22 @@ static void android_view_RenderNode_destroyRenderNode(JNIEnv* env,
|
||||
|
||||
static void android_view_RenderNode_setDisplayList(JNIEnv* env,
|
||||
jobject clazz, jlong renderNodePtr, jlong displayListPtr) {
|
||||
class RemovedObserver : public TreeObserver {
|
||||
public:
|
||||
virtual void onMaybeRemovedFromTree(RenderNode* node) override {
|
||||
maybeRemovedNodes.insert(sp<RenderNode>(node));
|
||||
}
|
||||
std::set< sp<RenderNode> > maybeRemovedNodes;
|
||||
};
|
||||
|
||||
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
|
||||
DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr);
|
||||
renderNode->setStagingDisplayList(newData);
|
||||
RemovedObserver observer;
|
||||
renderNode->setStagingDisplayList(newData, &observer);
|
||||
for (auto& node : observer.maybeRemovedNodes) {
|
||||
if (node->hasParents()) continue;
|
||||
onRenderNodeRemoved(env, node.get());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -525,7 +525,7 @@ static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
|
||||
UiFrameInfoBuilder(proxy->frameInfo())
|
||||
.setVsync(vsync, vsync)
|
||||
.addFlag(FrameInfoFlags::SurfaceCanvas);
|
||||
proxy->syncAndDrawFrame();
|
||||
proxy->syncAndDrawFrame(nullptr);
|
||||
}
|
||||
|
||||
static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
|
||||
|
||||
@@ -72,6 +72,31 @@ static JNIEnv* getenv(JavaVM* vm) {
|
||||
return env;
|
||||
}
|
||||
|
||||
// TODO: Clean this up, it's a bit odd to need to call over to
|
||||
// rendernode's jni layer. Probably means RootRenderNode should be pulled
|
||||
// into HWUI with appropriate callbacks for the various JNI hooks so
|
||||
// that RenderNode's JNI layer can handle its own thing
|
||||
void onRenderNodeRemoved(JNIEnv* env, RenderNode* node);
|
||||
|
||||
class ScopedRemovedRenderNodeObserver : public TreeObserver {
|
||||
public:
|
||||
ScopedRemovedRenderNodeObserver(JNIEnv* env) : mEnv(env) {}
|
||||
~ScopedRemovedRenderNodeObserver() {
|
||||
for (auto& node : mMaybeRemovedNodes) {
|
||||
if (node->hasParents()) continue;
|
||||
onRenderNodeRemoved(mEnv, node.get());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void onMaybeRemovedFromTree(RenderNode* node) override {
|
||||
mMaybeRemovedNodes.insert(sp<RenderNode>(node));
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* mEnv;
|
||||
std::set< sp<RenderNode> > mMaybeRemovedNodes;
|
||||
};
|
||||
|
||||
class OnFinishedEvent {
|
||||
public:
|
||||
OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
|
||||
@@ -120,13 +145,7 @@ private:
|
||||
std::string mMessage;
|
||||
};
|
||||
|
||||
// TODO: Clean this up, it's a bit odd to need to call over to
|
||||
// rendernode's jni layer. Probably means RootRenderNode should be pulled
|
||||
// into HWUI with appropriate callbacks for the various JNI hooks so
|
||||
// that RenderNode's JNI layer can handle its own thing
|
||||
void onRenderNodeRemoved(JNIEnv* env, RenderNode* node);
|
||||
|
||||
class RootRenderNode : public RenderNode, ErrorHandler, TreeObserver {
|
||||
class RootRenderNode : public RenderNode, ErrorHandler {
|
||||
public:
|
||||
RootRenderNode(JNIEnv* env) : RenderNode() {
|
||||
mLooper = Looper::getForThread();
|
||||
@@ -143,9 +162,6 @@ public:
|
||||
|
||||
virtual void prepareTree(TreeInfo& info) override {
|
||||
info.errorHandler = this;
|
||||
if (info.mode == TreeInfo::MODE_FULL) {
|
||||
info.observer = this;
|
||||
}
|
||||
// TODO: This is hacky
|
||||
info.windowInsetLeft = -stagingProperties().getLeft();
|
||||
info.windowInsetTop = -stagingProperties().getTop();
|
||||
@@ -155,7 +171,6 @@ public:
|
||||
info.windowInsetLeft = 0;
|
||||
info.windowInsetTop = 0;
|
||||
info.errorHandler = nullptr;
|
||||
info.observer = nullptr;
|
||||
}
|
||||
|
||||
void sendMessage(const sp<MessageHandler>& handler) {
|
||||
@@ -181,27 +196,10 @@ public:
|
||||
mPendingAnimatingRenderNodes.clear();
|
||||
}
|
||||
|
||||
virtual void onMaybeRemovedFromTree(RenderNode* node) override {
|
||||
mMaybeRemovedNodes.insert(sp<RenderNode>(node));
|
||||
}
|
||||
|
||||
void processMaybeRemovedNodes(JNIEnv* env) {
|
||||
// We can safely access mMaybeRemovedNodes here because
|
||||
// we will only modify it in prepareTree calls that are
|
||||
// MODE_FULL
|
||||
|
||||
for (auto& node : mMaybeRemovedNodes) {
|
||||
if (node->hasParents()) continue;
|
||||
onRenderNodeRemoved(env, node.get());
|
||||
}
|
||||
mMaybeRemovedNodes.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
sp<Looper> mLooper;
|
||||
JavaVM* mVm;
|
||||
std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
|
||||
std::set< sp<RenderNode> > mMaybeRemovedNodes;
|
||||
};
|
||||
|
||||
class AnimationContextBridge : public AnimationContext {
|
||||
@@ -500,24 +498,23 @@ static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
|
||||
}
|
||||
|
||||
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize, jlong rootNodePtr) {
|
||||
jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
|
||||
LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
|
||||
"Mismatched size expectations, given %d expected %d",
|
||||
frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
|
||||
ScopedRemovedRenderNodeObserver observer(env);
|
||||
env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
|
||||
int ret = proxy->syncAndDrawFrame();
|
||||
rootRenderNode->processMaybeRemovedNodes(env);
|
||||
return ret;
|
||||
return proxy->syncAndDrawFrame(&observer);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jlong rootNodePtr) {
|
||||
ScopedRemovedRenderNodeObserver observer(env);
|
||||
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
|
||||
rootRenderNode->destroy();
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
proxy->destroy();
|
||||
proxy->destroy(&observer);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
|
||||
@@ -542,9 +539,10 @@ static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobje
|
||||
|
||||
static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jlong nodePtr) {
|
||||
ScopedRemovedRenderNodeObserver observer(env);
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
|
||||
proxy->buildLayer(node);
|
||||
proxy->buildLayer(node, &observer);
|
||||
}
|
||||
|
||||
static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
|
||||
@@ -579,8 +577,9 @@ static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobj
|
||||
|
||||
static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr) {
|
||||
ScopedRemovedRenderNodeObserver observer(env);
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
proxy->destroyHardwareResources();
|
||||
proxy->destroyHardwareResources(&observer);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
|
||||
@@ -736,7 +735,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
{ "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup },
|
||||
{ "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
|
||||
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
|
||||
{ "nSyncAndDrawFrame", "(J[JIJ)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
|
||||
{ "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
|
||||
{ "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy },
|
||||
{ "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
|
||||
{ "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
|
||||
|
||||
@@ -81,14 +81,14 @@ RenderNode::~RenderNode() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void RenderNode::setStagingDisplayList(DisplayList* displayList) {
|
||||
void RenderNode::setStagingDisplayList(DisplayList* displayList, TreeObserver* observer) {
|
||||
mNeedsDisplayListSync = true;
|
||||
delete mStagingDisplayList;
|
||||
mStagingDisplayList = displayList;
|
||||
// If mParentCount == 0 we are the sole reference to this RenderNode,
|
||||
// so immediately free the old display list
|
||||
if (!mParentCount && !mStagingDisplayList) {
|
||||
deleteDisplayList(nullptr);
|
||||
deleteDisplayList(observer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
|
||||
void debugDumpLayers(const char* prefix);
|
||||
|
||||
ANDROID_API void setStagingDisplayList(DisplayList* newData);
|
||||
ANDROID_API void setStagingDisplayList(DisplayList* newData, TreeObserver* observer);
|
||||
|
||||
void computeOrdering();
|
||||
|
||||
|
||||
@@ -76,15 +76,15 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
|
||||
}
|
||||
|
||||
CanvasContext::~CanvasContext() {
|
||||
destroy();
|
||||
destroy(nullptr);
|
||||
mRenderThread.renderState().unregisterCanvasContext(this);
|
||||
}
|
||||
|
||||
void CanvasContext::destroy() {
|
||||
void CanvasContext::destroy(TreeObserver* observer) {
|
||||
stopDrawing();
|
||||
setSurface(nullptr);
|
||||
freePrefetechedLayers();
|
||||
destroyHardwareResources();
|
||||
freePrefetchedLayers(observer);
|
||||
destroyHardwareResources(observer);
|
||||
mAnimationContext->destroy();
|
||||
#if !HWUI_NEW_OPS
|
||||
if (mCanvas) {
|
||||
@@ -222,7 +222,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
|
||||
mAnimationContext->runRemainingAnimations(info);
|
||||
GL_CHECKPOINT(MODERATE);
|
||||
|
||||
freePrefetechedLayers();
|
||||
freePrefetchedLayers(info.observer);
|
||||
GL_CHECKPOINT(MODERATE);
|
||||
|
||||
if (CC_UNLIKELY(!mNativeSurface.get())) {
|
||||
@@ -569,25 +569,24 @@ void CanvasContext::invokeFunctor(RenderThread& thread, Functor* functor) {
|
||||
}
|
||||
|
||||
void CanvasContext::markLayerInUse(RenderNode* node) {
|
||||
if (mPrefetechedLayers.erase(node)) {
|
||||
if (mPrefetchedLayers.erase(node)) {
|
||||
node->decStrong(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void destroyPrefetechedNode(RenderNode* node) {
|
||||
ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...", node->getName());
|
||||
node->destroyHardwareResources(nullptr);
|
||||
node->decStrong(nullptr);
|
||||
}
|
||||
|
||||
void CanvasContext::freePrefetechedLayers() {
|
||||
if (mPrefetechedLayers.size()) {
|
||||
std::for_each(mPrefetechedLayers.begin(), mPrefetechedLayers.end(), destroyPrefetechedNode);
|
||||
mPrefetechedLayers.clear();
|
||||
void CanvasContext::freePrefetchedLayers(TreeObserver* observer) {
|
||||
if (mPrefetchedLayers.size()) {
|
||||
for (auto& node : mPrefetchedLayers) {
|
||||
ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...",
|
||||
node->getName());
|
||||
node->destroyHardwareResources(observer);
|
||||
node->decStrong(observer);
|
||||
}
|
||||
mPrefetchedLayers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasContext::buildLayer(RenderNode* node) {
|
||||
void CanvasContext::buildLayer(RenderNode* node, TreeObserver* observer) {
|
||||
ATRACE_CALL();
|
||||
if (!mEglManager.hasEglContext()) return;
|
||||
#if !HWUI_NEW_OPS
|
||||
@@ -599,6 +598,7 @@ void CanvasContext::buildLayer(RenderNode* node) {
|
||||
|
||||
TreeInfo info(TreeInfo::MODE_FULL, *this);
|
||||
info.damageAccumulator = &mDamageAccumulator;
|
||||
info.observer = observer;
|
||||
#if HWUI_NEW_OPS
|
||||
info.layerUpdateQueue = &mLayerUpdateQueue;
|
||||
#else
|
||||
@@ -628,7 +628,7 @@ void CanvasContext::buildLayer(RenderNode* node) {
|
||||
#endif
|
||||
|
||||
node->incStrong(nullptr);
|
||||
mPrefetechedLayers.insert(node);
|
||||
mPrefetchedLayers.insert(node);
|
||||
}
|
||||
|
||||
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
|
||||
@@ -636,12 +636,12 @@ bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap)
|
||||
return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
|
||||
}
|
||||
|
||||
void CanvasContext::destroyHardwareResources() {
|
||||
void CanvasContext::destroyHardwareResources(TreeObserver* observer) {
|
||||
stopDrawing();
|
||||
if (mEglManager.hasEglContext()) {
|
||||
freePrefetechedLayers();
|
||||
freePrefetchedLayers(observer);
|
||||
for (const sp<RenderNode>& node : mRenderNodes) {
|
||||
node->destroyHardwareResources(nullptr);
|
||||
node->destroyHardwareResources(observer);
|
||||
}
|
||||
Caches& caches = Caches::getInstance();
|
||||
// Make sure to release all the textures we were owning as there won't
|
||||
|
||||
@@ -92,17 +92,17 @@ public:
|
||||
void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
|
||||
int64_t syncQueued, RenderNode* target);
|
||||
void draw();
|
||||
void destroy();
|
||||
void destroy(TreeObserver* observer);
|
||||
|
||||
// IFrameCallback, Choreographer-driven frame callback entry point
|
||||
virtual void doFrame() override;
|
||||
void prepareAndDraw(RenderNode* node);
|
||||
|
||||
void buildLayer(RenderNode* node);
|
||||
void buildLayer(RenderNode* node, TreeObserver* observer);
|
||||
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
|
||||
void markLayerInUse(RenderNode* node);
|
||||
|
||||
void destroyHardwareResources();
|
||||
void destroyHardwareResources(TreeObserver* observer);
|
||||
static void trimMemory(RenderThread& thread, int level);
|
||||
|
||||
static void invokeFunctor(RenderThread& thread, Functor* functor);
|
||||
@@ -174,7 +174,7 @@ private:
|
||||
void setSurface(Surface* window);
|
||||
void requireSurface();
|
||||
|
||||
void freePrefetechedLayers();
|
||||
void freePrefetchedLayers(TreeObserver* observer);
|
||||
|
||||
void waitOnFences();
|
||||
|
||||
@@ -218,7 +218,7 @@ private:
|
||||
FrameInfoVisualizer mProfiler;
|
||||
std::unique_ptr<FrameMetricsReporter> mFrameMetricsReporter;
|
||||
|
||||
std::set<RenderNode*> mPrefetechedLayers;
|
||||
std::set<RenderNode*> mPrefetchedLayers;
|
||||
|
||||
// Stores the bounds of the main content.
|
||||
Rect mContentDrawBounds;
|
||||
|
||||
@@ -65,11 +65,12 @@ void DrawFrameTask::removeLayerUpdate(DeferredLayerUpdater* layer) {
|
||||
}
|
||||
}
|
||||
|
||||
int DrawFrameTask::drawFrame() {
|
||||
int DrawFrameTask::drawFrame(TreeObserver* observer) {
|
||||
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
|
||||
|
||||
mSyncResult = kSync_OK;
|
||||
mSyncQueued = systemTime(CLOCK_MONOTONIC);
|
||||
mObserver = observer;
|
||||
postAndWait();
|
||||
|
||||
return mSyncResult;
|
||||
@@ -88,6 +89,7 @@ void DrawFrameTask::run() {
|
||||
bool canDrawThisFrame;
|
||||
{
|
||||
TreeInfo info(TreeInfo::MODE_FULL, *mContext);
|
||||
info.observer = mObserver;
|
||||
canUnblockUiThread = syncFrameState(info);
|
||||
canDrawThisFrame = info.out.canDrawThisFrame;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
void pushLayerUpdate(DeferredLayerUpdater* layer);
|
||||
void removeLayerUpdate(DeferredLayerUpdater* layer);
|
||||
|
||||
int drawFrame();
|
||||
int drawFrame(TreeObserver* observer);
|
||||
|
||||
int64_t* frameInfo() { return mFrameInfo; }
|
||||
|
||||
@@ -87,6 +87,7 @@ private:
|
||||
|
||||
int mSyncResult;
|
||||
int64_t mSyncQueued;
|
||||
TreeObserver* mObserver;
|
||||
|
||||
int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
|
||||
};
|
||||
|
||||
@@ -222,18 +222,19 @@ int64_t* RenderProxy::frameInfo() {
|
||||
return mDrawFrameTask.frameInfo();
|
||||
}
|
||||
|
||||
int RenderProxy::syncAndDrawFrame() {
|
||||
return mDrawFrameTask.drawFrame();
|
||||
int RenderProxy::syncAndDrawFrame(TreeObserver* observer) {
|
||||
return mDrawFrameTask.drawFrame(observer);
|
||||
}
|
||||
|
||||
CREATE_BRIDGE1(destroy, CanvasContext* context) {
|
||||
args->context->destroy();
|
||||
CREATE_BRIDGE2(destroy, CanvasContext* context, TreeObserver* observer) {
|
||||
args->context->destroy(args->observer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RenderProxy::destroy() {
|
||||
void RenderProxy::destroy(TreeObserver* observer) {
|
||||
SETUP_TASK(destroy);
|
||||
args->context = mContext;
|
||||
args->observer = observer;
|
||||
// destroyCanvasAndSurface() needs a fence as when it returns the
|
||||
// underlying BufferQueue is going to be released from under
|
||||
// the render thread.
|
||||
@@ -287,15 +288,16 @@ DeferredLayerUpdater* RenderProxy::createTextureLayer() {
|
||||
return layer;
|
||||
}
|
||||
|
||||
CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
|
||||
args->context->buildLayer(args->node);
|
||||
CREATE_BRIDGE3(buildLayer, CanvasContext* context, RenderNode* node, TreeObserver* observer) {
|
||||
args->context->buildLayer(args->node, args->observer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RenderProxy::buildLayer(RenderNode* node) {
|
||||
void RenderProxy::buildLayer(RenderNode* node, TreeObserver* observer) {
|
||||
SETUP_TASK(buildLayer);
|
||||
args->context = mContext;
|
||||
args->node = node;
|
||||
args->observer = observer;
|
||||
postAndWait(task);
|
||||
}
|
||||
|
||||
@@ -332,15 +334,16 @@ void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
|
||||
postAndWait(task);
|
||||
}
|
||||
|
||||
CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
|
||||
args->context->destroyHardwareResources();
|
||||
CREATE_BRIDGE2(destroyHardwareResources, CanvasContext* context, TreeObserver* observer) {
|
||||
args->context->destroyHardwareResources(args->observer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RenderProxy::destroyHardwareResources() {
|
||||
void RenderProxy::destroyHardwareResources(TreeObserver* observer) {
|
||||
SETUP_TASK(destroyHardwareResources);
|
||||
args->context = mContext;
|
||||
post(task);
|
||||
args->observer = observer;
|
||||
postAndWait(task);
|
||||
}
|
||||
|
||||
CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {
|
||||
|
||||
@@ -42,6 +42,7 @@ class RenderNode;
|
||||
class DisplayList;
|
||||
class Layer;
|
||||
class Rect;
|
||||
class TreeObserver;
|
||||
|
||||
namespace renderthread {
|
||||
|
||||
@@ -75,21 +76,21 @@ public:
|
||||
ANDROID_API void setLightCenter(const Vector3& lightCenter);
|
||||
ANDROID_API void setOpaque(bool opaque);
|
||||
ANDROID_API int64_t* frameInfo();
|
||||
ANDROID_API int syncAndDrawFrame();
|
||||
ANDROID_API void destroy();
|
||||
ANDROID_API int syncAndDrawFrame(TreeObserver* observer);
|
||||
ANDROID_API void destroy(TreeObserver* observer);
|
||||
|
||||
ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
|
||||
|
||||
ANDROID_API void runWithGlContext(RenderTask* task);
|
||||
|
||||
ANDROID_API DeferredLayerUpdater* createTextureLayer();
|
||||
ANDROID_API void buildLayer(RenderNode* node);
|
||||
ANDROID_API void buildLayer(RenderNode* node, TreeObserver* observer);
|
||||
ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap);
|
||||
ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer);
|
||||
ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
|
||||
ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer);
|
||||
|
||||
ANDROID_API void destroyHardwareResources();
|
||||
ANDROID_API void destroyHardwareResources(TreeObserver* observer);
|
||||
ANDROID_API static void trimMemory(int level);
|
||||
ANDROID_API static void overrideProperty(const char* name, const char* value);
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ public:
|
||||
if (setup) {
|
||||
TestCanvas canvas(props.getWidth(), props.getHeight());
|
||||
setup(props, canvas);
|
||||
node->setStagingDisplayList(canvas.finishRecording());
|
||||
node->setStagingDisplayList(canvas.finishRecording(), nullptr);
|
||||
}
|
||||
node->setPropertyFieldsDirty(0xFFFFFFFF);
|
||||
return node;
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
TestCanvas canvas(node.stagingProperties().getWidth(),
|
||||
node.stagingProperties().getHeight());
|
||||
contentCallback(canvas);
|
||||
node.setStagingDisplayList(canvas.finishRecording());
|
||||
node.setStagingDisplayList(canvas.finishRecording(), nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,6 +59,6 @@ public:
|
||||
0, 100 * (i + 2), kBidi_Force_LTR, paint, nullptr);
|
||||
}
|
||||
|
||||
container->setStagingDisplayList(canvas.finishRecording());
|
||||
container->setStagingDisplayList(canvas.finishRecording(), nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
// draw it to parent DisplayList
|
||||
canvas.drawRenderNode(cards[ci].get());
|
||||
}
|
||||
listView->setStagingDisplayList(canvas.finishRecording());
|
||||
listView->setStagingDisplayList(canvas.finishRecording(), nullptr);
|
||||
}
|
||||
private:
|
||||
SkBitmap createRandomCharIcon() {
|
||||
|
||||
@@ -95,7 +95,7 @@ void run(const TestScene::Info& info, const TestScene::Options& opts) {
|
||||
testContext.waitForVsync();
|
||||
nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
|
||||
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
|
||||
proxy->syncAndDrawFrame();
|
||||
proxy->syncAndDrawFrame(nullptr);
|
||||
}
|
||||
|
||||
proxy->resetProfileInfo();
|
||||
@@ -110,7 +110,7 @@ void run(const TestScene::Info& info, const TestScene::Options& opts) {
|
||||
ATRACE_NAME("UI-Draw Frame");
|
||||
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
|
||||
scene->doFrame(i);
|
||||
proxy->syncAndDrawFrame();
|
||||
proxy->syncAndDrawFrame(nullptr);
|
||||
}
|
||||
if (opts.reportFrametimeWeight) {
|
||||
proxy->fence();
|
||||
|
||||
@@ -104,8 +104,8 @@ public:
|
||||
}
|
||||
|
||||
void finishDrawing() {
|
||||
mRootNode->setStagingDisplayList(mCanvas->finishRecording());
|
||||
mProxy->syncAndDrawFrame();
|
||||
mRootNode->setStagingDisplayList(mCanvas->finishRecording(), nullptr);
|
||||
mProxy->syncAndDrawFrame(nullptr);
|
||||
// Surprisingly, calling mProxy->fence() here appears to make no difference to
|
||||
// the timings we record.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user