Add TextureView support to new renderer/reorderer

bug:22480459

Change-Id: I2e4c0bc6b904706132f3f5087ededc9cac9b40fb
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 0d1ee46..a1ea9ce 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
-HWUI_NEW_OPS := false
+HWUI_NEW_OPS := true
 
 hwui_src_files := \
     font/CacheTexture.cpp \
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index a892b1b..0f0768f 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -735,6 +735,20 @@
     }
 }
 
+void BakedOpDispatcher::onTextureLayerOp(BakedOpRenderer& renderer, const TextureLayerOp& op, const BakedOpState& state) {
+    const bool tryToSnap = !op.layer->getForceFilter();
+    float alpha = (op.layer->getAlpha() / 255.0f) * state.alpha;
+    Glop glop;
+    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
+            .setRoundRectClipState(state.roundRectClipState)
+            .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
+            .setFillTextureLayer(*(op.layer), alpha)
+            .setTransform(state.computedState.transform, TransformFlags::None)
+            .setModelViewMapUnitToRectOptionalSnap(tryToSnap, Rect(op.layer->getWidth(), op.layer->getHeight()))
+            .build();
+    renderer.renderGlop(state, glop);
+}
+
 void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) {
     OffscreenBuffer* buffer = *op.layerHandle;
 
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 7038334..f833a54 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -53,8 +53,7 @@
     SkRefCnt_SafeAssign(mColorFilter, colorFilter);
 }
 
-bool DeferredLayerUpdater::apply() {
-    bool success = true;
+void DeferredLayerUpdater::apply() {
     // These properties are applied the same to both layer types
     mLayer->setColorFilter(mColorFilter);
     mLayer->setAlpha(mAlpha, mMode);
@@ -73,7 +72,6 @@
             setTransform(nullptr);
         }
     }
-    return success;
 }
 
 void DeferredLayerUpdater::doUpdateTexImage() {
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index df7c594..6a3c890 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -77,13 +77,13 @@
 
     ANDROID_API void setPaint(const SkPaint* paint);
 
-    ANDROID_API bool apply();
+    void apply();
 
     Layer* backingLayer() {
         return mLayer;
     }
 
-    ANDROID_API void detachSurfaceTexture();
+    void detachSurfaceTexture();
 
 private:
     // Generic properties
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index e9e5d81..0cf643f 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -287,7 +287,7 @@
 }
 
 void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
-        bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform) {
+        bool isOpaque, bool forceFilter, GLenum renderTarget, const float* textureTransform) {
     if (layer) {
         layer->setBlend(!isOpaque);
         layer->setForceFilter(forceFilter);
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index e4a54b0..38c3705 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -59,7 +59,7 @@
     static Layer* createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height);
     static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
     static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
-            bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform);
+            bool isOpaque, bool forceFilter, GLenum renderTarget, const float* textureTransform);
     static void destroyLayer(Layer* layer);
     static bool copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap);
 
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index c017638..1c25f26 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -139,9 +139,11 @@
     }
 
     void multiply(const Matrix4& v) {
-        Matrix4 u;
-        u.loadMultiply(*this, v);
-        *this = u;
+        if (!v.isIdentity()) {
+            Matrix4 u;
+            u.loadMultiply(*this, v);
+            *this = u;
+        }
     }
 
     void multiply(float v);
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/OpReorderer.cpp
index e147211..bdc8f68 100644
--- a/libs/hwui/OpReorderer.cpp
+++ b/libs/hwui/OpReorderer.cpp
@@ -783,7 +783,7 @@
 void OpReorderer::deferFunctorOp(const FunctorOp& op) {
     BakedOpState* bakedState = tryBakeOpState(op);
     if (!bakedState) return; // quick rejected
-    currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::None);
+    currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Functor);
 }
 
 void OpReorderer::deferLinesOp(const LinesOp& op) {
@@ -871,6 +871,12 @@
     currentLayer().deferUnmergeableOp(mAllocator, bakedState, textBatchId(*(op.paint)));
 }
 
+void OpReorderer::deferTextureLayerOp(const TextureLayerOp& op) {
+    BakedOpState* bakedState = tryBakeOpState(op);
+    if (!bakedState) return; // quick rejected
+    currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::TextureLayer);
+}
+
 void OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
         float contentTranslateX, float contentTranslateY,
         const Rect& repaintRect,
diff --git a/libs/hwui/OpReorderer.h b/libs/hwui/OpReorderer.h
index 35343c8b..dbbce8b 100644
--- a/libs/hwui/OpReorderer.h
+++ b/libs/hwui/OpReorderer.h
@@ -43,7 +43,6 @@
 
 namespace OpBatchType {
     enum {
-        None = 0, // Don't batch
         Bitmap,
         MergedPatch,
         AlphaVertices,
@@ -52,6 +51,8 @@
         Text,
         ColorText,
         Shadow,
+        TextureLayer,
+        Functor,
 
         Count // must be last
     };
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index bb23005..cfdd0d2 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -63,6 +63,7 @@
         U_OP_FN(SimpleRectsOp) \
         M_OP_FN(TextOp) \
         U_OP_FN(TextOnPathOp) \
+        U_OP_FN(TextureLayerOp) \
         U_OP_FN(BeginLayerOp) \
         U_OP_FN(EndLayerOp) \
         U_OP_FN(LayerOp)
@@ -345,11 +346,17 @@
     const float vOffset;
 };
 
+struct TextureLayerOp : RecordedOp {
+    TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer)
+            : SUPER_PAINTLESS(TextureLayerOp)
+            , layer(layer) {}
+    Layer* layer;
+};
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Layers
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 
-
 /**
  * Stateful operation! denotes the creation of an off-screen layer,
  * and that commands following will render into it.
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 46ae790..f75d8d4 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -16,6 +16,7 @@
 
 #include "RecordingCanvas.h"
 
+#include "DeferredLayerUpdater.h"
 #include "RecordedOp.h"
 #include "RenderNode.h"
 
@@ -542,6 +543,21 @@
     }
 }
 
+void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
+    // We ref the DeferredLayerUpdater due to its thread-safe ref-counting semantics.
+    mDisplayList->ref(layerHandle);
+
+    Layer* layer = layerHandle->backingLayer();
+    Matrix4 totalTransform(*(mState.currentSnapshot()->transform));
+    totalTransform.multiply(layer->getTransform());
+
+    addOp(new (alloc()) TextureLayerOp(
+            Rect(layer->getWidth(), layer->getHeight()),
+            totalTransform,
+            mState.getRenderTargetClipBounds(),
+            layer));
+}
+
 void RecordingCanvas::callDrawGLFunction(Functor* functor) {
     mDisplayList->functors.push_back(functor);
     addOp(new (alloc()) FunctorOp(
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index ce7d1350..48cc91a 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -36,7 +36,7 @@
 namespace android {
 namespace uirenderer {
 
-class OpReceiver;
+class DeferredLayerUpdater;
 struct RecordedOp;
 
 class RecordingCanvas: public Canvas, public CanvasStateClient {
@@ -59,6 +59,8 @@
         mDeferredBarrierType = enableReorder
                 ? DeferredBarrierType::OutOfOrder : DeferredBarrierType::InOrder;
     }
+
+    void drawLayer(DeferredLayerUpdater* layerHandle);
     void drawRenderNode(RenderNode* renderNode);
 
     // TODO: rename for consistency
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index ca85dfb..4c58676 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -182,16 +182,6 @@
     }
 }
 
-void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater) {
-#if !HWUI_NEW_OPS
-    bool success = layerUpdater->apply();
-    LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!");
-    if (layerUpdater->backingLayer()->deferredUpdateScheduled) {
-        mCanvas->pushLayerUpdate(layerUpdater->backingLayer());
-    }
-#endif
-}
-
 static bool wasSkipped(FrameInfo* info) {
     return info && ((*info)[FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame);
 }
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index d36ce99..ca5aa5c 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -83,7 +83,6 @@
     void setLightCenter(const Vector3& lightCenter);
     void setOpaque(bool opaque);
     void makeCurrent();
-    void processLayerUpdate(DeferredLayerUpdater* layerUpdater);
     void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
             int64_t syncQueued, RenderNode* target);
     void draw();
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index ab860c7..e8b9725 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -117,7 +117,7 @@
     Caches::getInstance().textureCache.resetMarkInUse(mContext);
 
     for (size_t i = 0; i < mLayers.size(); i++) {
-        mContext->processLayerUpdate(mLayers[i].get());
+        mLayers[i]->apply();
     }
     mLayers.clear();
     mContext->prepareTree(info, mFrameInfo, mSyncQueued, mTargetNode);
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 4c8d23d..624f3bd 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -16,6 +16,9 @@
 
 #include "TestUtils.h"
 
+#include "DeferredLayerUpdater.h"
+#include "LayerRenderer.h"
+
 namespace android {
 namespace uirenderer {
 
@@ -36,6 +39,22 @@
             | (int)((startB + (int)(fraction * (endB - startB))));
 }
 
+sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater(
+        renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
+        std::function<void(Matrix4*)> transformSetupCallback) {
+    bool isOpaque = true;
+    bool forceFilter = true;
+    GLenum renderTarget = GL_TEXTURE_EXTERNAL_OES;
+
+    Layer* layer = LayerRenderer::createTextureLayer(renderThread.renderState());
+    LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, forceFilter,
+            renderTarget, Matrix4::identity().data);
+    transformSetupCallback(&(layer->getTransform()));
+
+    sp<DeferredLayerUpdater> layerUpdater = new DeferredLayerUpdater(layer);
+    return layerUpdater;
+}
+
 void TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text,
         const SkPaint& paint, float x, float y) {
     // drawing text requires GlyphID TextEncoding (which JNI layer would have done)
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 4f84474..d37fad4 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -113,6 +113,10 @@
         return bitmap;
     }
 
+    static sp<DeferredLayerUpdater> createTextureLayerUpdater(
+            renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
+            std::function<void(Matrix4*)> transformSetupCallback);
+
     template<class CanvasType>
     static std::unique_ptr<DisplayList> createDisplayList(int width, int height,
             std::function<void(CanvasType& canvas)> canvasCallback) {
diff --git a/libs/hwui/tests/unit/OpReordererTests.cpp b/libs/hwui/tests/unit/OpReordererTests.cpp
index ab0cc87..288f8af 100644
--- a/libs/hwui/tests/unit/OpReordererTests.cpp
+++ b/libs/hwui/tests/unit/OpReordererTests.cpp
@@ -17,6 +17,7 @@
 #include <gtest/gtest.h>
 
 #include <BakedOpState.h>
+#include <DeferredLayerUpdater.h>
 #include <LayerUpdateQueue.h>
 #include <OpReorderer.h>
 #include <RecordedOp.h>
@@ -281,6 +282,39 @@
             << "Expect number of ops = 2 * loop count";
 }
 
+RENDERTHREAD_TEST(OpReorderer, textureLayer) {
+    class TextureLayerTestRenderer : public TestRendererBase {
+    public:
+        void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(0, mIndex++);
+            EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect);
+            EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds);
+
+            Matrix4 expected;
+            expected.loadTranslate(5, 5, 0);
+            EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform);
+        }
+    };
+
+    auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
+            [](Matrix4* transform) {
+        transform->loadTranslate(5, 5, 0);
+    });
+
+    auto node = TestUtils::createNode(0, 0, 200, 200,
+            [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
+        canvas.save(SkCanvas::kMatrixClip_SaveFlag);
+        canvas.clipRect(50, 50, 150, 150, SkRegion::kIntersect_Op);
+        canvas.drawLayer(layerUpdater.get());
+        canvas.restore();
+    });
+    OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+            createSyncedNodeList(node), sLightCenter);
+    TextureLayerTestRenderer renderer;
+    reorderer.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(1, renderer.getIndex());
+}
+
 TEST(OpReorderer, renderNode) {
     class RenderNodeTestRenderer : public TestRendererBase {
     public:
@@ -307,16 +341,15 @@
         canvas.drawRect(0, 0, 100, 100, paint);
     });
 
-    RenderNode* childPtr = child.get();
     auto parent = TestUtils::createNode(0, 0, 200, 200,
-            [childPtr](RenderProperties& props, RecordingCanvas& canvas) {
+            [&child](RenderProperties& props, RecordingCanvas& canvas) {
         SkPaint paint;
         paint.setColor(SK_ColorDKGRAY);
         canvas.drawRect(0, 0, 200, 200, paint);
 
         canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
         canvas.translate(40, 40);
-        canvas.drawRenderNode(childPtr);
+        canvas.drawRenderNode(child.get());
         canvas.restore();
     });