diff options
-rw-r--r-- | core/java/android/view/ThreadedRenderer.java | 13 | ||||
-rw-r--r-- | core/jni/android_view_ThreadedRenderer.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/TreeInfo.h | 36 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 28 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 6 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.cpp | 18 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.h | 9 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.h | 2 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java | 9 |
11 files changed, 96 insertions, 39 deletions
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 89a2ea2..9c7fa25 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -53,6 +53,12 @@ public class ThreadedRenderer extends HardwareRenderer { private static final long NANOS_PER_MS = 1000000; + // Keep in sync with DrawFrameTask.h SYNC_* flags + // Nothing interesting to report + private static final int SYNC_OK = 0x0; + // Needs a ViewRoot invalidate + private static final int SYNC_INVALIDATE_REQUIRED = 0x1; + private int mWidth, mHeight; private long mNativeProxy; private boolean mInitialized = false; @@ -201,8 +207,11 @@ public class ThreadedRenderer extends HardwareRenderer { if (dirty == null) { dirty = NULL_RECT; } - nSyncAndDrawFrame(mNativeProxy, frameTimeNanos, + int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos, dirty.left, dirty.top, dirty.right, dirty.bottom); + if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) { + attachInfo.mViewRootImpl.invalidate(); + } } @Override @@ -304,7 +313,7 @@ public class ThreadedRenderer extends HardwareRenderer { private static native void nSetup(long nativeProxy, int width, int height); private static native void nSetDisplayListData(long nativeProxy, long displayList, long newData); - private static native void nSyncAndDrawFrame(long nativeProxy, long frameTimeNanos, + private static native int nSyncAndDrawFrame(long nativeProxy, long frameTimeNanos, int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom); private static native void nRunWithGlContext(long nativeProxy, Runnable runnable); private static native void nDestroyCanvasAndSurface(long nativeProxy); diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 6a04867..cd0ed8c 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -191,11 +191,11 @@ static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, proxy->setup(width, height); } -static void android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz, +static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz, jlong proxyPtr, jlong frameTimeNanos, jint dirtyLeft, jint dirtyTop, jint dirtyRight, jint dirtyBottom) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); - proxy->syncAndDrawFrame(frameTimeNanos, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom); + return proxy->syncAndDrawFrame(frameTimeNanos, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom); } static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz, @@ -272,7 +272,7 @@ static JNINativeMethod gMethods[] = { { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface }, { "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface }, { "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup }, - { "nSyncAndDrawFrame", "(JJIIII)V", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, + { "nSyncAndDrawFrame", "(JJIIII)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface }, { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext }, diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 2c29985..9902ff1 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -160,13 +160,13 @@ void RenderNode::evaluateAnimations(TreeInfo& info) { newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor); mAnimators.erase(newEnd, mAnimators.end()); mProperties.updateMatrix(); - info.hasAnimations |= mAnimators.size(); + info.out.hasAnimations |= mAnimators.size(); } void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) { if (subtree) { TextureCache& cache = Caches::getInstance().textureCache; - info.hasFunctors |= subtree->functorCount; + info.out.hasFunctors |= subtree->functorCount; // TODO: Fix ownedBitmapResources to not require disabling prepareTextures // and thus falling out of async drawing path. if (subtree->ownedBitmapResources.size()) { diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h index a383fbf..fc5994c 100644 --- a/libs/hwui/TreeInfo.h +++ b/libs/hwui/TreeInfo.h @@ -34,25 +34,33 @@ protected: struct TreeInfo { // The defaults here should be safe for everyone but DrawFrameTask to use as-is. TreeInfo() - : hasFunctors(false) - , prepareTextures(false) - , performStagingPush(true) - , frameTimeMs(0) - , evaluateAnimations(false) - , hasAnimations(false) - , animationHook(0) + : frameTimeMs(0) + , animationHook(NULL) + , prepareTextures(false) + , performStagingPush(true) + , evaluateAnimations(false) {} - bool hasFunctors; + nsecs_t frameTimeMs; + AnimationHook* animationHook; bool prepareTextures; bool performStagingPush; - - // Animations - nsecs_t frameTimeMs; bool evaluateAnimations; - // This is only updated if evaluateAnimations is true - bool hasAnimations; - AnimationHook* animationHook; + + struct Out { + Out() + : hasFunctors(false) + , hasAnimations(false) + , requiresUiRedraw(false) + {} + bool hasFunctors; + // This is only updated if evaluateAnimations is true + bool hasAnimations; + // This is set to true if there is an animation that RenderThread cannot + // animate itself, such as if hasFunctors is true + // This is only set if hasAnimations is true + bool requiresUiRedraw; + } out; // TODO: Damage calculations }; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index f199236..fc3548c 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -391,10 +391,20 @@ void CanvasContext::makeCurrent() { mHaveNewSurface |= mGlobalContext->makeCurrent(mEglSurface); } -void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, +void CanvasContext::prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info) { - LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!"); + 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); @@ -406,13 +416,19 @@ void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* lay } void CanvasContext::prepareTree(TreeInfo& info) { - info.frameTimeMs = mRenderThread.timeLord().frameTimeMs(); + mRenderThread.removeFrameCallback(this); + info.frameTimeMs = mRenderThread.timeLord().frameTimeMs(); mRootRenderNode->prepareTree(info); - if (info.hasAnimations && !info.hasFunctors) { - // TODO: Functors - mRenderThread.postFrameCallback(this); + if (info.out.hasAnimations) { + if (info.out.hasFunctors) { + info.out.requiresUiRedraw = true; + } else if (!info.out.requiresUiRedraw) { + // If animationsNeedsRedraw is set don't bother posting for an RT anim + // as we will just end up fighting the UI thread. + mRenderThread.postFrameCallback(this); + } } } diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 8022c9e..a95e27a 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -53,8 +53,7 @@ public: void pauseSurface(EGLNativeWindowType window); void setup(int width, int height); void makeCurrent(); - void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info); - void prepareTree(TreeInfo& info); + void prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info); void draw(Rect* dirty); void destroyCanvasAndSurface(); @@ -71,6 +70,9 @@ public: Layer* createTextureLayer(); private: + void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info); + void prepareTree(TreeInfo& info); + void setSurface(EGLNativeWindowType window); void swapBuffers(); void requireSurface(); diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index a7b781a..3b8786c 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -33,7 +33,8 @@ namespace renderthread { DrawFrameTask::DrawFrameTask() : mRenderThread(NULL) , mContext(NULL) - , mFrameTimeNanos(NULL) { + , mFrameTimeNanos(0) + , mSyncResult(kSync_OK) { } DrawFrameTask::~DrawFrameTask() { @@ -63,15 +64,18 @@ void DrawFrameTask::setDirty(int left, int top, int right, int bottom) { mDirty.set(left, top, right, bottom); } -void DrawFrameTask::drawFrame(nsecs_t frameTimeNanos) { +int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos) { LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!"); + mSyncResult = kSync_OK; mFrameTimeNanos = frameTimeNanos; postAndWait(); // Reset the single-frame data mFrameTimeNanos = 0; mDirty.setEmpty(); + + return mSyncResult; } void DrawFrameTask::postAndWait() { @@ -114,14 +118,16 @@ bool DrawFrameTask::syncFrameState() { Caches::getInstance().textureCache.resetMarkInUse(); TreeInfo info; initTreeInfo(info); - mContext->processLayerUpdates(&mLayers, info); - mContext->prepareTree(info); - if (info.hasAnimations) { + mContext->prepareDraw(&mLayers, info); + if (info.out.hasAnimations) { // TODO: dirty calculations, for now just do a full-screen inval mDirty.setEmpty(); + if (info.out.requiresUiRedraw) { + mSyncResult |= kSync_UIRedrawRequired; + } } // If prepareTextures is false, we ran out of texture cache space - return !info.hasFunctors && info.prepareTextures; + return !info.out.hasFunctors && info.prepareTextures; } void DrawFrameTask::unblockUiThread() { diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h index ea00900..b9307e1 100644 --- a/libs/hwui/renderthread/DrawFrameTask.h +++ b/libs/hwui/renderthread/DrawFrameTask.h @@ -37,6 +37,11 @@ namespace renderthread { class CanvasContext; class RenderThread; +enum SyncResult { + kSync_OK = 0, + kSync_UIRedrawRequired = 1 << 1, +}; + /* * This is a special Super Task. It is re-used multiple times by RenderProxy, * and contains state (such as layer updaters & new DisplayListDatas) that is @@ -54,7 +59,7 @@ public: void removeLayer(DeferredLayerUpdater* layer); void setDirty(int left, int top, int right, int bottom); - void drawFrame(nsecs_t frameTimeNanos); + int drawFrame(nsecs_t frameTimeNanos); virtual void run(); @@ -75,6 +80,8 @@ private: Rect mDirty; nsecs_t mFrameTimeNanos; + int mSyncResult; + /********************************************* * Multi frame data *********************************************/ diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 7b7c019..31bb61a 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -146,10 +146,10 @@ void RenderProxy::setup(int width, int height) { post(task); } -void RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, +int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) { mDrawFrameTask.setDirty(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom); - mDrawFrameTask.drawFrame(frameTimeNanos); + return mDrawFrameTask.drawFrame(frameTimeNanos); } CREATE_BRIDGE1(destroyCanvasAndSurface, CanvasContext* context) { diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index bfa2b8d..984cc65 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -66,7 +66,7 @@ public: ANDROID_API void updateSurface(const sp<ANativeWindow>& window); ANDROID_API void pauseSurface(const sp<ANativeWindow>& window); ANDROID_API void setup(int width, int height); - ANDROID_API void syncAndDrawFrame(nsecs_t frameTimeNanos, + ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos, int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom); ANDROID_API void destroyCanvasAndSurface(); diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java index f060bc8..5c273de 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java @@ -27,6 +27,9 @@ import android.os.Trace; import android.view.HardwareCanvas; import android.view.RenderNodeAnimator; import android.view.View; +import android.webkit.WebChromeClient; +import android.webkit.WebView; +import android.webkit.WebViewClient; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.ProgressBar; @@ -43,6 +46,12 @@ public class CirclePropActivity extends Activity { ProgressBar spinner = new ProgressBar(this, null, android.R.attr.progressBarStyleLarge); layout.addView(spinner, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + // For testing with a functor in the tree +// WebView wv = new WebView(this); +// wv.setWebViewClient(new WebViewClient()); +// wv.setWebChromeClient(new WebChromeClient()); +// wv.loadUrl("http://theverge.com"); +// layout.addView(wv, new LayoutParams(LayoutParams.MATCH_PARENT, 100)); layout.addView(new CircleView(this), new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); |