Allow fine-grained control over functors execution

Adds non-drawing execution mode

Change-Id: I82f92cf1b9a3b9ff2ca6d7427c4e02b73e04e6bf
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::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 @@
     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 @@
     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();