diff options
-rw-r--r-- | core/java/android/os/Message.java | 17 | ||||
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 7 | ||||
-rw-r--r-- | core/java/android/view/HardwareCanvas.java | 12 | ||||
-rw-r--r-- | core/java/android/view/HardwareRenderer.java | 54 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 21 | ||||
-rw-r--r-- | include/private/hwui/DrawGlInfo.h | 17 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 43 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 7 |
8 files changed, 148 insertions, 30 deletions
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java index b816b11..4aa7fe2 100644 --- a/core/java/android/os/Message.java +++ b/core/java/android/os/Message.java @@ -16,9 +16,6 @@ package android.os; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; import android.util.TimeUtils; /** @@ -368,13 +365,13 @@ public final class Message implements Parcelable { * * Asynchronous messages represent interrupts or events that do not require global ordering * with represent to synchronous messages. Asynchronous messages are not subject to - * the synchronization barriers introduced by {@link MessageQueue#acquireSyncBarrier()}. + * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @return True if the message is asynchronous. * * @see #setAsynchronous(boolean) - * @see MessageQueue#acquireSyncBarrier() - * @see MessageQueue#releaseSyncBarrier() + * @see MessageQueue#enqueueSyncBarrier(long) + * @see MessageQueue#removeSyncBarrier(int) * * @hide */ @@ -387,13 +384,13 @@ public final class Message implements Parcelable { * * Asynchronous messages represent interrupts or events that do not require global ordering * with represent to synchronous messages. Asynchronous messages are not subject to - * the synchronization barriers introduced by {@link MessageQueue#acquireSyncBarrier()}. + * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param async True if the message is asynchronous. * * @see #isAsynchronous() - * @see MessageQueue#acquireSyncBarrier() - * @see MessageQueue#releaseSyncBarrier() + * @see MessageQueue#enqueueSyncBarrier(long) + * @see MessageQueue#removeSyncBarrier(int) * * @hide */ @@ -506,7 +503,7 @@ public final class Message implements Parcelable { Messenger.writeMessengerOrNullToParcel(replyTo, dest); } - private final void readFromParcel(Parcel source) { + private void readFromParcel(Parcel source) { what = source.readInt(); arg1 = source.readInt(); arg2 = source.readInt(); diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 5b0433e..bedafc7 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -259,6 +259,13 @@ class GLES20Canvas extends HardwareCanvas { private static native int nCallDrawGLFunction(int renderer, int drawGLFunction); + @Override + public int invokeFunctors(Rect dirty) { + return nInvokeFunctors(mRenderer, dirty); + } + + private static native int nInvokeFunctors(int renderer, Rect dirty); + /////////////////////////////////////////////////////////////////////////// // Memory /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java index 2636ea2..de8c62d 100644 --- a/core/java/android/view/HardwareCanvas.java +++ b/core/java/android/view/HardwareCanvas.java @@ -98,4 +98,16 @@ public abstract class HardwareCanvas extends Canvas { // Noop - this is done in the display list recorder subclass return DisplayList.STATUS_DONE; } + + /** + * Invoke all the functors who requested to be invoked during the previous frame. + * + * @param dirty The region to redraw when the functors return {@link DisplayList#STATUS_DRAW} + * + * @return One of {@link DisplayList#STATUS_DONE}, {@link DisplayList#STATUS_DRAW} or + * {@link DisplayList#STATUS_INVOKE} + */ + public int invokeFunctors(Rect dirty) { + return DisplayList.STATUS_DONE; + } } diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 133f601..b100a0c 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -502,7 +502,9 @@ public abstract class HardwareRenderer { static final int SURFACE_STATE_ERROR = 0; static final int SURFACE_STATE_SUCCESS = 1; static final int SURFACE_STATE_UPDATED = 2; - + + static final int FUNCTOR_PROCESS_DELAY = 2; + static EGL10 sEgl; static EGLDisplay sEglDisplay; static EGLConfig sEglConfig; @@ -549,7 +551,9 @@ public abstract class HardwareRenderer { private boolean mDestroyed; private final Rect mRedrawClip = new Rect(); + private final int[] mSurfaceSize = new int[2]; + private final FunctorsRunnable mFunctorsRunnable = new FunctorsRunnable(); GlRenderer(int glVersion, boolean translucent) { mGlVersion = glVersion; @@ -957,6 +961,24 @@ public abstract class HardwareRenderer { void onPostDraw() { } + class FunctorsRunnable implements Runnable { + View.AttachInfo attachInfo; + + @Override + public void run() { + final HardwareRenderer renderer = attachInfo.mHardwareRenderer; + if (renderer == null || !renderer.isEnabled() || renderer != GlRenderer.this) { + return; + } + + final int surfaceState = checkCurrent(); + if (surfaceState != SURFACE_STATE_ERROR) { + int status = mCanvas.invokeFunctors(mRedrawClip); + handleFunctorStatus(attachInfo, status); + } + } + } + @Override boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) { @@ -1051,15 +1073,7 @@ public abstract class HardwareRenderer { } } - if (status != DisplayList.STATUS_DONE) { - if (mRedrawClip.isEmpty()) { - attachInfo.mViewRootImpl.invalidate(); - } else { - attachInfo.mViewRootImpl.invalidateChildInParent( - null, mRedrawClip); - mRedrawClip.setEmpty(); - } - } + handleFunctorStatus(attachInfo, status); } else { // Shouldn't reach here view.draw(canvas); @@ -1111,6 +1125,26 @@ public abstract class HardwareRenderer { return false; } + private void handleFunctorStatus(View.AttachInfo attachInfo, int status) { + // If the draw flag is set, functors will be invoked while executing + // the tree of display lists + if ((status & DisplayList.STATUS_DRAW) != 0) { + if (mRedrawClip.isEmpty()) { + attachInfo.mViewRootImpl.invalidate(); + } else { + attachInfo.mViewRootImpl.invalidateChildInParent(null, mRedrawClip); + mRedrawClip.setEmpty(); + } + } + + if ((status & DisplayList.STATUS_INVOKE) != 0) { + attachInfo.mHandler.removeCallbacks(mFunctorsRunnable); + mFunctorsRunnable.attachInfo = attachInfo; + // delay the functor callback by a few ms so it isn't polled constantly + attachInfo.mHandler.postDelayed(mFunctorsRunnable, FUNCTOR_PROCESS_DELAY); + } + } + /** * Ensures the current EGL context is the one we expect. * diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index b472eef..6028814 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -163,6 +163,21 @@ static jint android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject cl return renderer->callDrawGLFunction(functor, dirty); } +static jint android_view_GLES20Canvas_invokeFunctors(JNIEnv* env, + jobject clazz, OpenGLRenderer* renderer, jobject dirty) { + android::uirenderer::Rect bounds; + status_t status = renderer->invokeFunctors(bounds); + if (status != DrawGlInfo::kStatusDone && dirty != NULL) { + env->CallVoidMethod(dirty, gRectClassInfo.set, + int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom)); + } + return status; +} + +// ---------------------------------------------------------------------------- +// Misc +// ---------------------------------------------------------------------------- + static jint android_view_GLES20Canvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) { return Caches::getInstance().maxTextureSize; } @@ -824,6 +839,8 @@ static JNINativeMethod gMethods[] = { { "nGetStencilSize", "()I", (void*) android_view_GLES20Canvas_getStencilSize }, { "nCallDrawGLFunction", "(II)I", (void*) android_view_GLES20Canvas_callDrawGLFunction }, + { "nInvokeFunctors", "(ILandroid/graphics/Rect;)I", + (void*) android_view_GLES20Canvas_invokeFunctors }, { "nSave", "(II)I", (void*) android_view_GLES20Canvas_save }, { "nRestore", "(I)V", (void*) android_view_GLES20Canvas_restore }, @@ -899,9 +916,9 @@ static JNINativeMethod gMethods[] = { { "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList }, { "nGetDisplayListSize", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListSize }, { "nSetDisplayListName", "(ILjava/lang/String;)V", - (void*) android_view_GLES20Canvas_setDisplayListName }, + (void*) android_view_GLES20Canvas_setDisplayListName }, { "nDrawDisplayList", "(IIIILandroid/graphics/Rect;I)I", - (void*) android_view_GLES20Canvas_drawDisplayList }, + (void*) android_view_GLES20Canvas_drawDisplayList }, { "nCreateDisplayListRenderer", "()I", (void*) android_view_GLES20Canvas_createDisplayListRenderer }, { "nResetDisplayListRenderer", "(I)V", (void*) android_view_GLES20Canvas_resetDisplayListRenderer }, diff --git a/include/private/hwui/DrawGlInfo.h b/include/private/hwui/DrawGlInfo.h index abcf41d..8028bf3 100644 --- a/include/private/hwui/DrawGlInfo.h +++ b/include/private/hwui/DrawGlInfo.h @@ -44,20 +44,31 @@ struct DrawGlInfo { float dirtyBottom; /** + * Values used as the "what" parameter of the functor. + */ + enum Mode { + // Indicates that the functor is called to perform a draw + kModeDraw, + // Indicates the the functor is called only to perform + // processing and that no draw should be attempted + kModeProcess + }; + + /** * Values used by OpenGL functors to tell the framework * what to do next. */ enum Status { // The functor is done - kStatusDone, + kStatusDone = 0x0, // The functor is requesting a redraw (the clip rect // used by the redraw is specified by DrawGlInfo.) // The rest of the UI might redraw too. - kStatusDraw, + kStatusDraw = 0x1, // The functor needs to be invoked again but will // not redraw. Only the functor is invoked again // (unless another functor requests a redraw.) - kStatusInvoke + kStatusInvoke = 0x2 }; }; // struct DrawGlInfo diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index eb4b83b..39be5ed 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -166,6 +166,7 @@ void OpenGLRenderer::prepare(bool opaque) { void OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) { mCaches.clearGarbage(); + mFunctors.clear(); mSnapshot = new Snapshot(mFirstSnapshot, SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); @@ -236,7 +237,39 @@ void OpenGLRenderer::resume() { glBlendEquation(GL_FUNC_ADD); } -status_t OpenGLRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) { +status_t OpenGLRenderer::invokeFunctors(Rect& dirty) { + status_t result = DrawGlInfo::kStatusDone; + + Vector<Functor*> functors(mFunctors); + mFunctors.clear(); + + DrawGlInfo info; + info.clipLeft = 0; + info.clipTop = 0; + info.clipRight = 0; + info.clipBottom = 0; + info.isLayer = false; + memset(info.transform, 0, sizeof(float) * 16); + + size_t count = functors.size(); + for (size_t i = 0; i < count; i++) { + Functor* f = functors.itemAt(i); + result |= (*f)(DrawGlInfo::kModeProcess, &info); + + if (result != DrawGlInfo::kStatusDone) { + Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom); + dirty.unionWith(localDirty); + + if (result == DrawGlInfo::kStatusInvoke) { + mFunctors.push(f); + } + } + } + + return result; +} + +status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) { interrupt(); if (mDirtyClip) { setScissorFromClip(); @@ -261,11 +294,15 @@ status_t OpenGLRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) { info.isLayer = hasLayer(); getSnapshot()->transform->copyTo(&info.transform[0]); - status_t result = (*functor)(0, &info); + status_t result = (*functor)(DrawGlInfo::kModeDraw, &info); - if (result != 0) { + if (result != DrawGlInfo::kStatusDone) { Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom); dirty.unionWith(localDirty); + + if (result == DrawGlInfo::kStatusInvoke) { + mFunctors.push(functor); + } } resume(); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 3ba6202..b651904 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -72,7 +72,8 @@ public: virtual void interrupt(); virtual void resume(); - virtual status_t callDrawGLFunction(Functor *functor, Rect& dirty); + ANDROID_API status_t invokeFunctors(Rect& dirty); + virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty); ANDROID_API int getSaveCount() const; virtual int save(int flags); @@ -602,8 +603,10 @@ private: // Various caches Caches& mCaches; - // List of rectagnles to clear after saveLayer() is invoked + // List of rectangles to clear after saveLayer() is invoked Vector<Rect*> mLayers; + // List of functors to invoke after a frame is drawn + Vector<Functor*> mFunctors; // Indentity matrix const mat4 mIdentity; |