Add functor support to new reorderer/renderer

bug:22480459

Change-Id: I95df7e0504f62d254e8ffbd8d65ed5d763080b9c
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 6ba23e9..9e39797 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -518,6 +518,10 @@
     renderer.renderGlop(state, glop);
 }
 
+void BakedOpDispatcher::onFunctorOp(BakedOpRenderer& renderer, const FunctorOp& op, const BakedOpState& state) {
+    renderer.renderFunctor(op, state);
+}
+
 void BakedOpDispatcher::onLinesOp(BakedOpRenderer& renderer, const LinesOp& op, const BakedOpState& state) {
     VertexBuffer buffer;
     PathTessellator::tessellateLines(op.points, op.floatCount, op.paint,
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 93a9406..f8282dc 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -128,7 +128,7 @@
     return texture;
 }
 
-void BakedOpRenderer::renderGlop(const Rect* dirtyBounds, const Rect* clip, const Glop& glop) {
+void BakedOpRenderer::prepareRender(const Rect* dirtyBounds, const Rect* clip) {
     mRenderState.scissor().setEnabled(clip != nullptr);
     if (clip) {
         mRenderState.scissor().set(clip->left, mRenderTarget.viewportHeight - clip->bottom,
@@ -140,10 +140,31 @@
                 dirtyBounds->right, dirtyBounds->bottom);
         mRenderTarget.offscreenBuffer->region.orSelf(dirty);
     }
+}
+
+void BakedOpRenderer::renderGlop(const Rect* dirtyBounds, const Rect* clip, const Glop& glop) {
+    prepareRender(dirtyBounds, clip);
     mRenderState.render(glop, mRenderTarget.orthoMatrix);
     if (!mRenderTarget.frameBufferId) mHasDrawn = true;
 }
 
+void BakedOpRenderer::renderFunctor(const FunctorOp& op, const BakedOpState& state) {
+    prepareRender(&state.computedState.clippedBounds, &state.computedState.clipRect);
+
+    DrawGlInfo info;
+    auto&& clip = state.computedState.clipRect;
+    info.clipLeft = clip.left;
+    info.clipTop = clip.top;
+    info.clipRight = clip.right;
+    info.clipBottom = clip.bottom;
+    info.isLayer = offscreenRenderTarget();
+    info.width = mRenderTarget.viewportWidth;
+    info.height = mRenderTarget.viewportHeight;
+    state.computedState.transform.copyTo(&info.transform[0]);
+
+    mRenderState.invokeFunctor(op.functor, DrawGlInfo::kModeDraw, &info);
+}
+
 void BakedOpRenderer::dirtyRenderTarget(const Rect& uiDirty) {
     if (mRenderTarget.offscreenBuffer) {
         android::Rect dirty(uiDirty.left, uiDirty.top, uiDirty.right, uiDirty.bottom);
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index d7600db..f158e8b 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -65,7 +65,7 @@
     void endLayer();
 
     Texture* getTexture(const SkBitmap* bitmap);
-    const LightInfo& getLightInfo() { return mLightInfo; }
+    const LightInfo& getLightInfo() const { return mLightInfo; }
 
     void renderGlop(const BakedOpState& state, const Glop& glop) {
         bool useScissor = state.computedState.clipSideFlags != OpClipSideFlags::None;
@@ -73,14 +73,16 @@
                 useScissor ? &state.computedState.clipRect : nullptr,
                 glop);
     }
+    void renderFunctor(const FunctorOp& op, const BakedOpState& state);
 
     void renderGlop(const Rect* dirtyBounds, const Rect* clip, const Glop& glop);
     bool offscreenRenderTarget() { return mRenderTarget.offscreenBuffer != nullptr; }
     void dirtyRenderTarget(const Rect& dirtyRect);
-    bool didDraw() { return mHasDrawn; }
+    bool didDraw() const { return mHasDrawn; }
 private:
     void setViewport(uint32_t width, uint32_t height);
     void clearColorBuffer(const Rect& clearRect);
+    void prepareRender(const Rect* dirtyBounds, const Rect* clip);
 
     RenderState& mRenderState;
     Caches& mCaches;
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/OpReorderer.cpp
index ec03e83..6d90a42 100644
--- a/libs/hwui/OpReorderer.cpp
+++ b/libs/hwui/OpReorderer.cpp
@@ -784,6 +784,12 @@
     deferOvalOp(*resolvedOp);
 }
 
+void OpReorderer::deferFunctorOp(const FunctorOp& op) {
+    BakedOpState* bakedState = tryBakeOpState(op);
+    if (!bakedState) return; // quick rejected
+    currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::None);
+}
+
 void OpReorderer::deferLinesOp(const LinesOp& op) {
     batchid_t batch = op.paint->isAntiAlias() ? OpBatchType::AlphaVertices : OpBatchType::Vertices;
     deferStrokeableOp(op, batch, BakedOpState::StrokeBehavior::Forced);
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index cd7a4bb..b58b774 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -49,6 +49,7 @@
         U_OP_FN(BitmapMeshOp) \
         U_OP_FN(BitmapRectOp) \
         U_OP_FN(CirclePropsOp) \
+        U_OP_FN(FunctorOp) \
         U_OP_FN(LinesOp) \
         U_OP_FN(OvalOp) \
         M_OP_FN(PatchOp) \
@@ -195,6 +196,13 @@
     const float* radius;
 };
 
+struct FunctorOp : RecordedOp {
+    FunctorOp(BASE_PARAMS_PAINTLESS, Functor* functor)
+            : SUPER_PAINTLESS(FunctorOp)
+            , functor(functor) {}
+    Functor* functor;
+};
+
 struct LinesOp : RecordedOp {
     LinesOp(BASE_PARAMS, const float* points, const int floatCount)
             : SUPER(LinesOp)
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index c7b16a1..7f035e5 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -197,8 +197,7 @@
 
 // Clip
 bool RecordingCanvas::getClipBounds(SkRect* outRect) const {
-    Rect bounds = mState.getLocalClipBounds();
-    *outRect = SkRect::MakeLTRB(bounds.left, bounds.top, bounds.right, bounds.bottom);
+    *outRect = mState.getLocalClipBounds().toSkRect();
     return !(outRect->isEmpty());
 }
 bool RecordingCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
@@ -516,6 +515,7 @@
             mState.getRenderTargetClipBounds(),
             refPaint(paint), refBitmap(*bitmap)));
 }
+
 void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
     auto&& stagingProps = renderNode->stagingProperties();
     RenderNodeOp* op = new (alloc()) RenderNodeOp(
@@ -536,6 +536,15 @@
     }
 }
 
+void RecordingCanvas::callDrawGLFunction(Functor* functor) {
+    mDisplayList->functors.push_back(functor);
+    addOp(new (alloc()) FunctorOp(
+            mState.getRenderTargetClipBounds(), // TODO: explicitly define bounds
+            *(mState.currentSnapshot()->transform),
+            mState.getRenderTargetClipBounds(),
+            functor));
+}
+
 size_t RecordingCanvas::addOp(RecordedOp* op) {
     // TODO: validate if "addDrawOp" quickrejection logic is useful before adding
     int insertIndex = mDisplayList->ops.size();
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 6fbaa8a..49bdba8 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -61,6 +61,9 @@
     }
     void drawRenderNode(RenderNode* renderNode);
 
+    // TODO: rename for consistency
+    void callDrawGLFunction(Functor* functor);
+
 // ----------------------------------------------------------------------------
 // CanvasStateClient interface
 // ----------------------------------------------------------------------------