Glop path texture support

Change-Id: I505eb05991ca4c9b2e01e49988b8f962fad51462
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index 12c6e45..10dbd5c 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -39,7 +39,6 @@
  * are enabled/disabled dynamically based on mesh content.
  */
 enum VertexAttribFlags {
-    // NOTE: position attribute always enabled
     kNone_Attrib = 0,
     kTextureCoord_Attrib = 1 << 0,
     kColor_Attrib = 1 << 1,
@@ -61,9 +60,6 @@
  */
 // TODO: PREVENT_COPY_AND_ASSIGN(...) or similar
 struct Glop {
-    Rect bounds;
-    const RoundRectClipState* roundRectClipState;
-
     /*
      * Stores mesh - vertex and index data.
      *
@@ -85,8 +81,10 @@
 
     struct Fill {
         Program* program;
+
         Texture* texture;
         GLenum textureFilter;
+        GLenum textureClamp;
 
         bool colorEnabled;
         FloatColor color;
@@ -113,12 +111,25 @@
         bool fudgingOffset;
     } transform;
 
+    const RoundRectClipState* roundRectClipState;
+
+    /**
+     * Blending to be used by this draw - both GL_NONE if blending is disabled.
+     *
+     * Defined by fill step, but can be force-enabled by presence of kAlpha_Attrib
+     */
     struct Blend {
         GLenum src;
         GLenum dst;
     } blend;
 
     /**
+     * Bounds of the drawing command in layer space. Only mapped into layer
+     * space once GlopBuilder::build() is called.
+     */
+    Rect bounds;
+
+    /**
      * Additional render state to enumerate:
      * - scissor + (bits for whether each of LTRB needed?)
      * - stencil mode (draw into, mask, count, etc)
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index e56988c..91e0f89 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -246,6 +246,7 @@
 
     mOutGlop->fill.texture = &texture;
     mOutGlop->fill.textureFilter = PaintUtils::getFilter(paint);
+    mOutGlop->fill.textureClamp = GL_CLAMP_TO_EDGE;
 
     if (paint) {
         int color = paint->getColor();
@@ -289,7 +290,8 @@
     REQUIRE_STAGES(kMeshStage);
 
     mOutGlop->fill.texture = nullptr;
-    mOutGlop->fill.textureFilter = GL_NEAREST;
+    mOutGlop->fill.textureFilter = GL_INVALID_ENUM;
+    mOutGlop->fill.textureClamp = GL_INVALID_ENUM;
 
     setFill(paint.getColor(), alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
             paint.getShader(), paint.getColorFilter());
@@ -297,6 +299,27 @@
     return *this;
 }
 
+GlopBuilder& GlopBuilder::setFillPathTexturePaint(Texture& texture,
+        const SkPaint& paint, float alphaScale) {
+    TRIGGER_STAGE(kFillStage);
+    REQUIRE_STAGES(kMeshStage);
+
+    mOutGlop->fill.texture = &texture;
+
+    //specify invalid, since these are always static for path textures
+    mOutGlop->fill.textureFilter = GL_INVALID_ENUM;
+    mOutGlop->fill.textureClamp = GL_INVALID_ENUM;
+
+    setFill(paint.getColor(), alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
+            paint.getShader(), paint.getColorFilter());
+
+    mDescription.modulate = mOutGlop->fill.color.a < 1.0f
+            || mOutGlop->fill.color.r > 0.0f
+            || mOutGlop->fill.color.g > 0.0f
+            || mOutGlop->fill.color.b > 0.0f;
+    return *this;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Transform
 ////////////////////////////////////////////////////////////////////////////////
@@ -311,7 +334,6 @@
     return *this;
 }
 
-
 ////////////////////////////////////////////////////////////////////////////////
 // ModelView
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 04d421c..d724041 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -45,6 +45,8 @@
     GlopBuilder& setFillPaint(const SkPaint& paint, float alphaScale);
     GlopBuilder& setFillTexturePaint(Texture& texture, bool isAlphaMaskTexture,
             const SkPaint* paint, float alphaScale);
+    GlopBuilder& setFillPathTexturePaint(Texture& texture,
+            const SkPaint& paint, float alphaScale);
 
     GlopBuilder& setTransformClip(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset);
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 0841124..a00a2bc 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2505,7 +2505,7 @@
     mDirty = true;
 }
 
-void OpenGLRenderer::drawShape(float left, float top, const PathTexture* texture,
+void OpenGLRenderer::drawShape(float left, float top, PathTexture* texture,
         const SkPaint* paint) {
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
@@ -2528,7 +2528,7 @@
 
     if (p->getPathEffect() != nullptr) {
         mCaches.textureState().activateTexture(0);
-        const PathTexture* texture = mCaches.pathCache.getRoundRect(
+        PathTexture* texture = mCaches.pathCache.getRoundRect(
                 right - left, bottom - top, rx, ry, p);
         drawShape(left, top, texture, p);
     } else {
@@ -2546,7 +2546,7 @@
     }
     if (p->getPathEffect() != nullptr) {
         mCaches.textureState().activateTexture(0);
-        const PathTexture* texture = mCaches.pathCache.getCircle(radius, p);
+        PathTexture* texture = mCaches.pathCache.getCircle(radius, p);
         drawShape(x - radius, y - radius, texture, p);
     } else {
         SkPath path;
@@ -2569,7 +2569,7 @@
 
     if (p->getPathEffect() != nullptr) {
         mCaches.textureState().activateTexture(0);
-        const PathTexture* texture = mCaches.pathCache.getOval(right - left, bottom - top, p);
+        PathTexture* texture = mCaches.pathCache.getOval(right - left, bottom - top, p);
         drawShape(left, top, texture, p);
     } else {
         SkPath path;
@@ -2593,7 +2593,7 @@
     // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
     if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != nullptr || useCenter) {
         mCaches.textureState().activateTexture(0);
-        const PathTexture* texture = mCaches.pathCache.getArc(right - left, bottom - top,
+        PathTexture* texture = mCaches.pathCache.getArc(right - left, bottom - top,
                 startAngle, sweepAngle, useCenter, p);
         drawShape(left, top, texture, p);
         return;
@@ -2630,7 +2630,7 @@
         if (p->getPathEffect() != nullptr || p->getStrokeJoin() != SkPaint::kMiter_Join ||
                 p->getStrokeMiter() != SkPaintDefaults_MiterLimit) {
             mCaches.textureState().activateTexture(0);
-            const PathTexture* texture =
+            PathTexture* texture =
                     mCaches.pathCache.getRect(right - left, bottom - top, p);
             drawShape(left, top, texture, p);
         } else {
@@ -2974,7 +2974,7 @@
 
     mCaches.textureState().activateTexture(0);
 
-    const PathTexture* texture = mCaches.pathCache.get(path, paint);
+    PathTexture* texture = mCaches.pathCache.get(path, paint);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
 
@@ -3107,12 +3107,26 @@
     return texture;
 }
 
-void OpenGLRenderer::drawPathTexture(const PathTexture* texture,
+void OpenGLRenderer::drawPathTexture(PathTexture* texture,
         float x, float y, const SkPaint* paint) {
     if (quickRejectSetupScissor(x, y, x + texture->width, y + texture->height)) {
         return;
     }
 
+    if (USE_GLOPS && !paint->getShader()) {
+        Glop glop;
+        GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+        aBuilder.setMeshTexturedUnitQuad(nullptr, true)
+                .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha)
+                .setTransformClip(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+                .setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height))
+                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+                .build();
+        renderGlop(glop);
+        return;
+    }
+
+
     int alpha;
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 4f8a2ea..851effa5 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -690,7 +690,7 @@
      * @param texture The texture reprsenting the shape
      * @param paint The paint to draw the shape with
      */
-    void drawShape(float left, float top, const PathTexture* texture, const SkPaint* paint);
+    void drawShape(float left, float top, PathTexture* texture, const SkPaint* paint);
 
     /**
      * Draws the specified texture as an alpha bitmap. Alpha bitmaps obey
@@ -819,7 +819,7 @@
      * @param y The y coordinate where the texture will be drawn
      * @param paint The paint to draw the texture with
      */
-     void drawPathTexture(const PathTexture* texture, float x, float y, const SkPaint* paint);
+     void drawPathTexture(PathTexture* texture, float x, float y, const SkPaint* paint);
 
     /**
      * Resets the texture coordinates stored in mMeshVertices. Setting the values
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 3953ecd..e35327b 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -269,8 +269,12 @@
         // TODO: to support shaders, increment texture unit
         mCaches->textureState().activateTexture(0);
 
-        glop.fill.texture->setWrap(GL_CLAMP_TO_EDGE, true);
-        glop.fill.texture->setFilter(glop.fill.textureFilter, true);
+        if (glop.fill.textureClamp != GL_INVALID_ENUM) {
+            glop.fill.texture->setWrap(glop.fill.textureClamp, true);
+        }
+        if (glop.fill.textureFilter != GL_INVALID_ENUM) {
+            glop.fill.texture->setFilter(glop.fill.textureFilter, true);
+        }
 
         mCaches->textureState().bindTexture(fill.texture->id);
         meshState().enableTexCoordsVertexArray();