summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2012-03-27 16:33:45 -0700
committerChris Craik <ccraik@google.com>2012-04-02 15:15:07 -0700
commit8f3b8e32993d190a26c70c839a63d8ce4c3b16d9 (patch)
tree8e49ffa8f5405f22b8bb12be9e5607ec6a0fc00a
parente6c966caa3aff3099e6fb00caefa10387f57b9c3 (diff)
downloadframeworks_base-8f3b8e32993d190a26c70c839a63d8ce4c3b16d9.zip
frameworks_base-8f3b8e32993d190a26c70c839a63d8ce4c3b16d9.tar.gz
frameworks_base-8f3b8e32993d190a26c70c839a63d8ce4c3b16d9.tar.bz2
Allow fine-grained control over functors execution
Adds non-drawing execution mode Change-Id: I82f92cf1b9a3b9ff2ca6d7427c4e02b73e04e6bf
-rw-r--r--core/java/android/os/Message.java17
-rw-r--r--core/java/android/view/GLES20Canvas.java7
-rw-r--r--core/java/android/view/HardwareCanvas.java12
-rw-r--r--core/java/android/view/HardwareRenderer.java54
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp21
-rw-r--r--include/private/hwui/DrawGlInfo.h17
-rw-r--r--libs/hwui/OpenGLRenderer.cpp43
-rw-r--r--libs/hwui/OpenGLRenderer.h7
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;