Delete pre-glop path

bug:19014311

Change-Id: I06376b6f625455892d8eafe2727b78025a64c4bf
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 6bef7c7..56380db 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -46,51 +46,11 @@
 // blur inputs smaller than this constant will bypass renderscript
 #define RS_MIN_INPUT_CUTOFF 10000
 
-#define USE_GLOPS true
-
 ///////////////////////////////////////////////////////////////////////////////
 // TextSetupFunctor
 ///////////////////////////////////////////////////////////////////////////////
-void TextSetupFunctor::setup(GLenum glyphFormat) {
-    renderer->setupDraw();
-    renderer->setupDrawTextGamma(paint);
-    renderer->setupDrawDirtyRegionsDisabled();
-    renderer->setupDrawWithTexture(glyphFormat == GL_ALPHA);
-    switch (glyphFormat) {
-        case GL_ALPHA: {
-            renderer->setupDrawAlpha8Color(paint->getColor(), alpha);
-            break;
-        }
-        case GL_RGBA: {
-            float floatAlpha = alpha / 255.0f;
-            renderer->setupDrawColor(floatAlpha, floatAlpha, floatAlpha, floatAlpha);
-            break;
-        }
-        default: {
-#if DEBUG_FONT_RENDERER
-            ALOGD("TextSetupFunctor: called with unknown glyph format %x", glyphFormat);
-#endif
-            break;
-        }
-    }
-    renderer->setupDrawColorFilter(paint->getColorFilter());
-    renderer->setupDrawShader(paint->getShader());
-    renderer->setupDrawBlending(paint);
-    renderer->setupDrawProgram();
-    renderer->setupDrawModelView(kModelViewMode_Translate, false,
-            0.0f, 0.0f, 0.0f, 0.0f, pureTranslate);
-    // Calling setupDrawTexture with the name 0 will enable the
-    // uv attributes and increase the texture unit count
-    // texture binding will be performed by the font renderer as
-    // needed
-    renderer->setupDrawTexture(0);
-    renderer->setupDrawPureColorUniforms();
-    renderer->setupDrawColorFilterUniforms(paint->getColorFilter());
-    renderer->setupDrawShaderUniforms(paint->getShader(), pureTranslate);
-    renderer->setupDrawTextGammaUniforms();
-}
 
-void TextSetupFunctor::draw(CacheTexture& texture, bool linearFiltering) {
+void TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) {
     int textureFillFlags = static_cast<int>(texture.getFormat() == GL_ALPHA
             ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
     if (linearFiltering) {
@@ -508,11 +468,6 @@
 void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) {
     if (!mFunctor) return;
 
-#if !USE_GLOPS
-    Caches& caches = mFunctor->renderer->getCaches();
-    RenderState& renderState = mFunctor->renderer->renderState();
-#endif
-
     bool first = true;
     bool forceRebind = false;
     for (uint32_t i = 0; i < cacheTextures.size(); i++) {
@@ -520,37 +475,12 @@
         if (texture->canDraw()) {
             if (first) {
                 checkTextureUpdate();
-#if !USE_GLOPS
-                mFunctor->setup(texture->getFormat());
-
-                renderState.meshState().bindQuadIndicesBuffer();
-
-                // If returns true, a VBO was bound and we must
-                // rebind our vertex attrib pointers even if
-                // they have the same values as the current pointers
-                forceRebind = renderState.meshState().unbindMeshBuffer();
-
-                caches.textureState().activateTexture(0);
-#endif
                 first = false;
                 mDrawn = true;
             }
-#if USE_GLOPS
+
             mFunctor->draw(*texture, mLinearFiltering);
-#endif
 
-#if !USE_GLOPS
-            caches.textureState().bindTexture(texture->getTextureId());
-            texture->setLinearFiltering(mLinearFiltering);
-
-            TextureVertex* mesh = texture->mesh();
-            MeshState& meshState = renderState.meshState();
-            meshState.bindPositionVertexPointer(forceRebind, &mesh[0].x);
-            meshState.bindTexCoordsVertexPointer(forceRebind, &mesh[0].u);
-
-            glDrawElements(GL_TRIANGLES, texture->meshElementCount(),
-                    GL_UNSIGNED_SHORT, texture->indices());
-#endif
             texture->resetMesh();
             forceRebind = false;
         }
@@ -689,7 +619,7 @@
     return image;
 }
 
-void FontRenderer::initRender(const Rect* clip, Rect* bounds, TextSetupFunctor* functor) {
+void FontRenderer::initRender(const Rect* clip, Rect* bounds, TextDrawFunctor* functor) {
     checkInit();
 
     mDrawn = false;
@@ -717,7 +647,7 @@
 
 bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const char *text,
         uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y,
-        const float* positions, Rect* bounds, TextSetupFunctor* functor, bool forceFinish) {
+        const float* positions, Rect* bounds, TextDrawFunctor* functor, bool forceFinish) {
     if (!mCurrentFont) {
         ALOGE("No font set");
         return false;
@@ -735,7 +665,7 @@
 
 bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text,
         uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path,
-        float hOffset, float vOffset, Rect* bounds, TextSetupFunctor* functor) {
+        float hOffset, float vOffset, Rect* bounds, TextDrawFunctor* functor) {
     if (!mCurrentFont) {
         ALOGE("No font set");
         return false;
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 0603389..dfb107c 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -46,9 +46,9 @@
 
 class OpenGLRenderer;
 
-class TextSetupFunctor {
+class TextDrawFunctor {
 public:
-    TextSetupFunctor(OpenGLRenderer* renderer, float x, float y, bool pureTranslate,
+    TextDrawFunctor(OpenGLRenderer* renderer, float x, float y, bool pureTranslate,
             int alpha, SkXfermode::Mode mode, const SkPaint* paint)
         : renderer(renderer)
         , x(x)
@@ -59,8 +59,6 @@
         , paint(paint) {
     }
 
-    void setup(GLenum glyphFormat);
-
     void draw(CacheTexture& texture, bool linearFiltering);
 
     OpenGLRenderer* renderer;
@@ -92,12 +90,12 @@
     // bounds is an out parameter
     bool renderPosText(const SkPaint* paint, const Rect* clip, const char *text,
             uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions,
-            Rect* bounds, TextSetupFunctor* functor, bool forceFinish = true);
+            Rect* bounds, TextDrawFunctor* functor, bool forceFinish = true);
 
     // bounds is an out parameter
     bool renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text,
             uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path,
-            float hOffset, float vOffset, Rect* bounds, TextSetupFunctor* functor);
+            float hOffset, float vOffset, Rect* bounds, TextDrawFunctor* functor);
 
     struct DropShadow {
         uint32_t width;
@@ -135,7 +133,7 @@
     void flushAllAndInvalidate();
 
     void checkInit();
-    void initRender(const Rect* clip, Rect* bounds, TextSetupFunctor* functor);
+    void initRender(const Rect* clip, Rect* bounds, TextDrawFunctor* functor);
     void finishRender();
 
     void issueDrawCommand(Vector<CacheTexture*>& cacheTextures);
@@ -176,7 +174,7 @@
 
     bool mUploadTexture;
 
-    TextSetupFunctor* mFunctor;
+    TextDrawFunctor* mFunctor;
     const Rect* mClip;
     Rect* mBounds;
     bool mDrawn;
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 0a46014..9ca6bc6 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -586,6 +586,12 @@
     mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kColor;
     mDescription.hasVertexAlpha = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kAlpha;
 
+    // Enable debug highlight when what we're about to draw is tested against
+    // the stencil buffer and if stencil highlight debugging is on
+    mDescription.hasDebugHighlight = !mCaches.debugOverdraw
+            && mCaches.debugStencilClip == Caches::kStencilShowHighlight
+            && mRenderState.stencil().isTestEnabled();
+
     // serialize shader info into ShaderData
     GLuint textureUnit = mOutGlop->fill.texture.texture ? 1 : 0;
     SkiaShader::store(mCaches, mShader, mOutGlop->transform.modelView,
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 02fbd89..aa722d0 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -57,8 +57,6 @@
     #define EVENT_LOGD(...)
 #endif
 
-#define USE_GLOPS true
-
 namespace android {
 namespace uirenderer {
 
@@ -82,8 +80,6 @@
     // *set* draw modifiers to be 0
     memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
     mDrawModifiers.mOverrideLayerAlpha = 1.0f;
-
-    memcpy(mMeshVertices, kUnitQuadVertices, sizeof(kUnitQuadVertices));
 }
 
 OpenGLRenderer::~OpenGLRenderer() {
@@ -846,124 +842,42 @@
 }
 
 void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
-    if (USE_GLOPS) {
-        bool snap = !layer->getForceFilter()
-                && layer->getWidth() == (uint32_t) rect.getWidth()
-                && layer->getHeight() == (uint32_t) rect.getHeight();
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
-                .setFillTextureLayer(*layer, getLayerAlpha(layer))
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewMapUnitToRectOptionalSnap(snap, rect)
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    float alpha = getLayerAlpha(layer);
-    setupDraw();
-    if (layer->getRenderTarget() == GL_TEXTURE_2D) {
-        setupDrawWithTexture();
-    } else {
-        setupDrawWithExternalTexture();
-    }
-    setupDrawTextureTransform();
-    setupDrawColor(alpha, alpha, alpha, alpha);
-    setupDrawColorFilter(layer->getColorFilter());
-    setupDrawBlending(layer);
-    setupDrawProgram();
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(layer->getColorFilter());
-    if (layer->getRenderTarget() == GL_TEXTURE_2D) {
-        setupDrawTexture(layer->getTextureId());
-    } else {
-        setupDrawExternalTexture(layer->getTextureId());
-    }
-    if (currentTransform()->isPureTranslate()
-            && !layer->getForceFilter()
+    bool snap = !layer->getForceFilter()
             && layer->getWidth() == (uint32_t) rect.getWidth()
-            && layer->getHeight() == (uint32_t) rect.getHeight()) {
-        const float x = floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
-        const float y = floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
-
-        layer->setFilter(GL_NEAREST);
-        setupDrawModelView(kModelViewMode_TranslateAndScale, false,
-                x, y, x + rect.getWidth(), y + rect.getHeight(), true);
-    } else {
-        layer->setFilter(GL_LINEAR);
-        setupDrawModelView(kModelViewMode_TranslateAndScale, false,
-                rect.left, rect.top, rect.right, rect.bottom);
-    }
-    setupDrawTextureTransformUniforms(layer->getTexTransform());
-    setupDrawMesh(&mMeshVertices[0].x, &mMeshVertices[0].u);
-
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
+            && layer->getHeight() == (uint32_t) rect.getHeight();
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
+            .setFillTextureLayer(*layer, getLayerAlpha(layer))
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewMapUnitToRectOptionalSnap(snap, rect)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
     if (layer->isTextureLayer()) {
         EVENT_LOGD("composeTextureLayerRect");
-        resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
         drawTextureLayer(layer, rect);
-        resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
     } else {
         EVENT_LOGD("composeHardwareLayerRect");
 
-        if (USE_GLOPS) {
-            Blend::ModeOrderSwap modeUsage = swap ?
-                    Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap;
-            const Matrix4& transform = swap ? Matrix4::identity() : *currentTransform();
-            bool snap = !swap
-                    && layer->getWidth() == static_cast<uint32_t>(rect.getWidth())
-                    && layer->getHeight() == static_cast<uint32_t>(rect.getHeight());
-            Glop glop;
-            GlopBuilder(mRenderState, mCaches, &glop)
-                    .setMeshTexturedUvQuad(nullptr, layer->texCoords)
-                    .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), modeUsage)
-                    .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
-                    .setModelViewMapUnitToRectOptionalSnap(snap, rect)
-                    .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                    .build();
-            renderGlop(glop);
-            return;
-        }
-
-        const Rect& texCoords = layer->texCoords;
-        resetDrawTextureTexCoords(texCoords.left, texCoords.top,
-                texCoords.right, texCoords.bottom);
-
-        float x = rect.left;
-        float y = rect.top;
-        bool simpleTransform = currentTransform()->isPureTranslate()
-                && layer->getWidth() == (uint32_t) rect.getWidth()
-                && layer->getHeight() == (uint32_t) rect.getHeight();
-
-        if (simpleTransform) {
-            // When we're swapping, the layer is already in screen coordinates
-            if (!swap) {
-                x = floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
-                y = floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
-            }
-
-            layer->setFilter(GL_NEAREST, true);
-        } else {
-            layer->setFilter(GL_LINEAR, true);
-        }
-
-        SkPaint layerPaint;
-        layerPaint.setAlpha(getLayerAlpha(layer) * 255);
-        layerPaint.setXfermodeMode(layer->getMode());
-        layerPaint.setColorFilter(layer->getColorFilter());
-
-        bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f;
-        drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
-                layer->getTextureId(), &layerPaint, blend,
-                &mMeshVertices[0].x, &mMeshVertices[0].u,
-                GL_TRIANGLE_STRIP, kUnitQuadCount, swap, swap || simpleTransform);
-
-        resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+        Blend::ModeOrderSwap modeUsage = swap ?
+                Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap;
+        const Matrix4& transform = swap ? Matrix4::identity() : *currentTransform();
+        bool snap = !swap
+                && layer->getWidth() == static_cast<uint32_t>(rect.getWidth())
+                && layer->getHeight() == static_cast<uint32_t>(rect.getHeight());
+        Glop glop;
+        GlopBuilder(mRenderState, mCaches, &glop)
+                .setMeshTexturedUvQuad(nullptr, layer->texCoords)
+                .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), modeUsage)
+                .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
+                .setModelViewMapUnitToRectOptionalSnap(snap, rect)
+                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+                .build();
+        renderGlop(glop);
     }
 }
 
@@ -1079,69 +993,8 @@
     const float texY = 1.0f / float(layer->getHeight());
     const float height = rect.getHeight();
 
-    if (USE_GLOPS) {
-        TextureVertex quadVertices[count * 4];
-        //std::unique_ptr<TextureVertex[]> quadVertices(new TextureVertex[count * 4]);
-        TextureVertex* mesh = &quadVertices[0];
-        for (size_t i = 0; i < count; i++) {
-            const android::Rect* r = &rects[i];
-
-            const float u1 = r->left * texX;
-            const float v1 = (height - r->top) * texY;
-            const float u2 = r->right * texX;
-            const float v2 = (height - r->bottom) * texY;
-
-            // TODO: Reject quads outside of the clip
-            TextureVertex::set(mesh++, r->left, r->top, u1, v1);
-            TextureVertex::set(mesh++, r->right, r->top, u2, v1);
-            TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
-            TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
-        }
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedIndexedQuads(&quadVertices[0], count * 6)
-                .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewOffsetRectSnap(0, 0, rect)
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
-        return;
-    }
-
-    const float alpha = getLayerAlpha(layer);
-
-    setupDraw();
-
-    // We must get (and therefore bind) the region mesh buffer
-    // after we setup drawing in case we need to mess with the
-    // stencil buffer in setupDraw()
-    TextureVertex* mesh = mCaches.getRegionMesh();
-    uint32_t numQuads = 0;
-
-    setupDrawWithTexture();
-    setupDrawColor(alpha, alpha, alpha, alpha);
-    setupDrawColorFilter(layer->getColorFilter());
-    setupDrawBlending(layer);
-    setupDrawProgram();
-    setupDrawDirtyRegionsDisabled();
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(layer->getColorFilter());
-    setupDrawTexture(layer->getTextureId());
-    if (currentTransform()->isPureTranslate()) {
-        const float x = floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
-        const float y = floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
-
-        layer->setFilter(GL_NEAREST);
-        setupDrawModelView(kModelViewMode_Translate, false,
-                x, y, x + rect.getWidth(), y + rect.getHeight(), true);
-    } else {
-        layer->setFilter(GL_LINEAR);
-        setupDrawModelView(kModelViewMode_Translate, false,
-                rect.left, rect.top, rect.right, rect.bottom);
-    }
-    setupDrawMeshIndices(&mesh[0].x, &mesh[0].u);
-
+    TextureVertex quadVertices[count * 4];
+    TextureVertex* mesh = &quadVertices[0];
     for (size_t i = 0; i < count; i++) {
         const android::Rect* r = &rects[i];
 
@@ -1155,21 +1008,16 @@
         TextureVertex::set(mesh++, r->right, r->top, u2, v1);
         TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
         TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
-
-        numQuads++;
-
-        if (numQuads >= kMaxNumberOfQuads) {
-            DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
-                    GL_UNSIGNED_SHORT, nullptr));
-            numQuads = 0;
-            mesh = mCaches.getRegionMesh();
-        }
     }
-
-    if (numQuads > 0) {
-        DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
-                GL_UNSIGNED_SHORT, nullptr));
-    }
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedIndexedQuads(&quadVertices[0], count * 6)
+            .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewOffsetRectSnap(0, 0, rect)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
 
 #if DEBUG_LAYERS_AS_REGIONS
     drawRegionRectsDebug(layer->region);
@@ -1248,21 +1096,6 @@
     }
 }
 
-void OpenGLRenderer::issueIndexedQuadDraw(Vertex* mesh, GLsizei quadsCount) {
-    GLsizei elementsCount = quadsCount * 6;
-    while (elementsCount > 0) {
-        GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
-
-        setupDrawIndexedVertices(&mesh[0].x);
-        glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr);
-
-        elementsCount -= drawCount;
-        // Though there are 4 vertices in a quad, we use 6 indices per
-        // quad to draw with GL_TRIANGLES
-        mesh += (drawCount / 6) * 4;
-    }
-}
-
 void OpenGLRenderer::clearLayerRegions() {
     const size_t quadCount = mLayers.size();
     if (quadCount == 0) return;
@@ -1290,34 +1123,19 @@
             Vertex::set(vertex++, bounds.right, bounds.bottom);
         }
         // We must clear the list of dirty rects before we
-        // call setupDraw() to prevent stencil setup to do
-        // the same thing again
+        // call clearLayerRegions() in renderGlop to prevent
+        // stencil setup from doing the same thing again
         mLayers.clear();
 
-        if (USE_GLOPS) {
-            Glop glop;
-            GlopBuilder(mRenderState, mCaches, &glop)
-                    .setMeshIndexedQuads(&mesh[0], quadCount)
-                    .setFillClear()
-                    .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
-                    .setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getClipRect()))
-                    .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                    .build();
-            renderGlop(glop, false);
-        } else {
-            SkPaint clearPaint;
-            clearPaint.setXfermodeMode(SkXfermode::kClear_Mode);
-
-            setupDraw(false);
-            setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
-            setupDrawBlending(&clearPaint, true);
-            setupDrawProgram();
-            setupDrawPureColorUniforms();
-            setupDrawModelView(kModelViewMode_Translate, false,
-                    0.0f, 0.0f, 0.0f, 0.0f, true);
-
-            issueIndexedQuadDraw(&mesh[0], quadCount);
-        }
+        Glop glop;
+        GlopBuilder(mRenderState, mCaches, &glop)
+                .setMeshIndexedQuads(&mesh[0], quadCount)
+                .setFillClear()
+                .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+                .setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getClipRect()))
+                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+                .build();
+        renderGlop(glop, false);
 
         if (scissorChanged) mRenderState.scissor().setEnabled(true);
     } else {
@@ -1498,35 +1316,16 @@
     mRenderState.scissor().set(scissorBox.left, getViewportHeight() - scissorBox.bottom,
             scissorBox.getWidth(), scissorBox.getHeight());
 
-    if (USE_GLOPS) {
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshIndexedQuads(&rectangleVertices[0], rectangleVertices.size() / 4)
-                .setFillBlack()
-                .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
-                .setModelViewOffsetRect(0, 0, scissorBox)
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    const SkPaint* paint = nullptr;
-    setupDraw();
-    setupDrawNoTexture();
-    setupDrawColor(0, 0xff * currentSnapshot()->alpha);
-    setupDrawShader(getShader(paint));
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint);
-    setupDrawProgram();
-    setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(kModelViewMode_Translate, false,
-            0.0f, 0.0f, 0.0f, 0.0f, true);
-    setupDrawColorUniforms(getShader(paint));
-    setupDrawShaderUniforms(getShader(paint));
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-
-    issueIndexedQuadDraw(&rectangleVertices[0], rectangleVertices.size() / 4);
+    Glop glop;
+    Vertex* vertices = &rectangleVertices[0];
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshIndexedQuads(vertices, rectangleVertices.size() / 4)
+            .setFillBlack()
+            .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+            .setModelViewOffsetRect(0, 0, scissorBox)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::setStencilFromClip() {
@@ -1666,355 +1465,6 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// Drawing commands
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::setupDraw(bool clearLayer) {
-    // TODO: It would be best if we could do this before quickRejectSetupScissor()
-    //       changes the scissor test state
-    if (clearLayer) clearLayerRegions();
-    // Make sure setScissor & setStencil happen at the beginning of
-    // this method
-    if (mState.getDirtyClip()) {
-        if (mRenderState.scissor().isEnabled()) {
-            setScissorFromClip();
-        }
-
-        setStencilFromClip();
-    }
-
-    mDescription.reset();
-
-    mSetShaderColor = false;
-    mColorSet = false;
-    mColor.a = mColor.r = mColor.g = mColor.b = 0.0f;
-    mTextureUnit = 0;
-    mTrackDirtyRegions = true;
-
-    // Enable debug highlight when what we're about to draw is tested against
-    // the stencil buffer and if stencil highlight debugging is on
-    mDescription.hasDebugHighlight = !mCaches.debugOverdraw
-            && mCaches.debugStencilClip == Caches::kStencilShowHighlight
-            && mRenderState.stencil().isTestEnabled();
-}
-
-void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
-    mDescription.hasTexture = true;
-    mDescription.hasAlpha8Texture = isAlpha8;
-}
-
-void OpenGLRenderer::setupDrawWithTextureAndColor(bool isAlpha8) {
-    mDescription.hasTexture = true;
-    mDescription.hasColors = true;
-    mDescription.hasAlpha8Texture = isAlpha8;
-}
-
-void OpenGLRenderer::setupDrawWithExternalTexture() {
-    mDescription.hasExternalTexture = true;
-}
-
-void OpenGLRenderer::setupDrawNoTexture() {
-    mRenderState.meshState().disableTexCoordsVertexArray();
-}
-
-void OpenGLRenderer::setupDrawVertexAlpha(bool useShadowAlphaInterp) {
-    mDescription.hasVertexAlpha = true;
-    mDescription.useShadowAlphaInterp = useShadowAlphaInterp;
-}
-
-void OpenGLRenderer::setupDrawColor(int color, int alpha) {
-    mColor.a = alpha / 255.0f;
-    mColor.r = mColor.a * ((color >> 16) & 0xFF) / 255.0f;
-    mColor.g = mColor.a * ((color >>  8) & 0xFF) / 255.0f;
-    mColor.b = mColor.a * ((color      ) & 0xFF) / 255.0f;
-    mColorSet = true;
-    mSetShaderColor = mDescription.setColorModulate(mColor.a);
-}
-
-void OpenGLRenderer::setupDrawAlpha8Color(int color, int alpha) {
-    mColor.a = alpha / 255.0f;
-    mColor.r = mColor.a * ((color >> 16) & 0xFF) / 255.0f;
-    mColor.g = mColor.a * ((color >>  8) & 0xFF) / 255.0f;
-    mColor.b = mColor.a * ((color      ) & 0xFF) / 255.0f;
-    mColorSet = true;
-    mSetShaderColor = mDescription.setAlpha8ColorModulate(mColor.r, mColor.g, mColor.b, mColor.a);
-}
-
-void OpenGLRenderer::setupDrawTextGamma(const SkPaint* paint) {
-    mCaches.fontRenderer->describe(mDescription, paint);
-}
-
-void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) {
-    mColor.a = a;
-    mColor.r = r;
-    mColor.g = g;
-    mColor.b = b;
-    mColorSet = true;
-    mSetShaderColor = mDescription.setColorModulate(a);
-}
-
-void OpenGLRenderer::setupDrawShader(const SkShader* shader) {
-    if (shader != nullptr) {
-        SkiaShader::describe(&mCaches, mDescription, mCaches.extensions(), *shader);
-    }
-}
-
-void OpenGLRenderer::setupDrawColorFilter(const SkColorFilter* filter) {
-    if (filter == nullptr) {
-        return;
-    }
-
-    SkXfermode::Mode mode;
-    if (filter->asColorMode(nullptr, &mode)) {
-        mDescription.colorOp = ProgramDescription::kColorBlend;
-        mDescription.colorMode = mode;
-    } else if (filter->asColorMatrix(nullptr)) {
-        mDescription.colorOp = ProgramDescription::kColorMatrix;
-    }
-}
-
-void OpenGLRenderer::accountForClear(SkXfermode::Mode mode) {
-    if (mColorSet && mode == SkXfermode::kClear_Mode) {
-        mColor.a = 1.0f;
-        mColor.r = mColor.g = mColor.b = 0.0f;
-        mSetShaderColor = mDescription.modulate = true;
-    }
-}
-
-void OpenGLRenderer::setupDrawBlending(const Layer* layer, bool swapSrcDst) {
-    SkXfermode::Mode mode = layer->getMode();
-    // When the blending mode is kClear_Mode, we need to use a modulate color
-    // argb=1,0,0,0
-    accountForClear(mode);
-    // TODO: check shader blending, once we have shader drawing support for layers.
-    bool blend = layer->isBlend()
-            || getLayerAlpha(layer) < 1.0f
-            || (mColorSet && mColor.a < 1.0f)
-            || PaintUtils::isBlendedColorFilter(layer->getColorFilter());
-    chooseBlending(blend, mode, mDescription, swapSrcDst);
-}
-
-void OpenGLRenderer::setupDrawBlending(const SkPaint* paint, bool blend, bool swapSrcDst) {
-    SkXfermode::Mode mode = getXfermodeDirect(paint);
-    // When the blending mode is kClear_Mode, we need to use a modulate color
-    // argb=1,0,0,0
-    accountForClear(mode);
-    blend |= (mColorSet && mColor.a < 1.0f)
-            || (getShader(paint) && !getShader(paint)->isOpaque())
-            || PaintUtils::isBlendedColorFilter(getColorFilter(paint));
-    chooseBlending(blend, mode, mDescription, swapSrcDst);
-}
-
-void OpenGLRenderer::setupDrawProgram() {
-    mCaches.setProgram(mDescription);
-    if (mDescription.hasRoundRectClip) {
-        // TODO: avoid doing this repeatedly, stashing state pointer in program
-        const RoundRectClipState* state = writableSnapshot()->roundRectClipState;
-        const Rect& innerRect = state->innerRect;
-        glUniform4f(mCaches.program().getUniform("roundRectInnerRectLTRB"),
-                innerRect.left, innerRect.top,
-                innerRect.right, innerRect.bottom);
-        glUniformMatrix4fv(mCaches.program().getUniform("roundRectInvTransform"),
-                1, GL_FALSE, &state->matrix.data[0]);
-
-        // add half pixel to round out integer rect space to cover pixel centers
-        float roundedOutRadius = state->radius + 0.5f;
-        glUniform1f(mCaches.program().getUniform("roundRectRadius"),
-                roundedOutRadius);
-    }
-}
-
-void OpenGLRenderer::setupDrawDirtyRegionsDisabled() {
-    mTrackDirtyRegions = false;
-}
-
-void OpenGLRenderer::setupDrawModelView(ModelViewMode mode, bool offset,
-        float left, float top, float right, float bottom, bool ignoreTransform) {
-    mModelViewMatrix.loadTranslate(left, top, 0.0f);
-    if (mode == kModelViewMode_TranslateAndScale) {
-        mModelViewMatrix.scale(right - left, bottom - top, 1.0f);
-    }
-
-    bool dirty = right - left > 0.0f && bottom - top > 0.0f;
-    const Matrix4& transformMatrix = ignoreTransform ? Matrix4::identity() : *currentTransform();
-
-    mCaches.program().set(currentSnapshot()->getOrthoMatrix(),
-            mModelViewMatrix, transformMatrix, offset);
-    if (dirty && mTrackDirtyRegions) {
-        if (!ignoreTransform) {
-            dirtyLayer(left, top, right, bottom, *currentTransform());
-        } else {
-            dirtyLayer(left, top, right, bottom);
-        }
-    }
-}
-
-void OpenGLRenderer::setupDrawColorUniforms(bool hasShader) {
-    if ((mColorSet && !hasShader) || (hasShader && mSetShaderColor)) {
-        mCaches.program().setColor(mColor);
-    }
-}
-
-void OpenGLRenderer::setupDrawPureColorUniforms() {
-    if (mSetShaderColor) {
-        mCaches.program().setColor(mColor);
-    }
-}
-
-void OpenGLRenderer::setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform) {
-    if (shader == nullptr) {
-        return;
-    }
-
-    if (ignoreTransform) {
-        // if ignoreTransform=true was passed to setupDrawModelView, undo currentTransform()
-        // because it was built into modelView / the geometry, and the description needs to
-        // compensate.
-        mat4 modelViewWithoutTransform;
-        modelViewWithoutTransform.loadInverse(*currentTransform());
-        modelViewWithoutTransform.multiply(mModelViewMatrix);
-        mModelViewMatrix.load(modelViewWithoutTransform);
-    }
-
-    SkiaShader::setupProgram(&mCaches, mModelViewMatrix, &mTextureUnit,
-            mCaches.extensions(), *shader);
-}
-
-void OpenGLRenderer::setupDrawColorFilterUniforms(const SkColorFilter* filter) {
-    if (nullptr == filter) {
-        return;
-    }
-
-    SkColor color;
-    SkXfermode::Mode mode;
-    if (filter->asColorMode(&color, &mode)) {
-        const int alpha = SkColorGetA(color);
-        const GLfloat a = alpha / 255.0f;
-        const GLfloat r = a * SkColorGetR(color) / 255.0f;
-        const GLfloat g = a * SkColorGetG(color) / 255.0f;
-        const GLfloat b = a * SkColorGetB(color) / 255.0f;
-        glUniform4f(mCaches.program().getUniform("colorBlend"), r, g, b, a);
-        return;
-    }
-
-    SkScalar srcColorMatrix[20];
-    if (filter->asColorMatrix(srcColorMatrix)) {
-
-        float colorMatrix[16];
-        memcpy(colorMatrix, srcColorMatrix, 4 * sizeof(float));
-        memcpy(&colorMatrix[4], &srcColorMatrix[5], 4 * sizeof(float));
-        memcpy(&colorMatrix[8], &srcColorMatrix[10], 4 * sizeof(float));
-        memcpy(&colorMatrix[12], &srcColorMatrix[15], 4 * sizeof(float));
-
-        // Skia uses the range [0..255] for the addition vector, but we need
-        // the [0..1] range to apply the vector in GLSL
-        float colorVector[4];
-        colorVector[0] = srcColorMatrix[4] / 255.0f;
-        colorVector[1] = srcColorMatrix[9] / 255.0f;
-        colorVector[2] = srcColorMatrix[14] / 255.0f;
-        colorVector[3] = srcColorMatrix[19] / 255.0f;
-
-        glUniformMatrix4fv(mCaches.program().getUniform("colorMatrix"), 1,
-                GL_FALSE, colorMatrix);
-        glUniform4fv(mCaches.program().getUniform("colorMatrixVector"), 1, colorVector);
-        return;
-    }
-
-    // it is an error if we ever get here
-}
-
-void OpenGLRenderer::setupDrawTextGammaUniforms() {
-    mCaches.fontRenderer->setupProgram(mDescription, mCaches.program());
-}
-
-void OpenGLRenderer::setupDrawSimpleMesh() {
-    bool force = mRenderState.meshState().bindMeshBuffer();
-    mRenderState.meshState().bindPositionVertexPointer(force, nullptr);
-    mRenderState.meshState().unbindIndicesBuffer();
-}
-
-void OpenGLRenderer::setupDrawTexture(GLuint texture) {
-    if (texture) mCaches.textureState().bindTexture(texture);
-    mTextureUnit++;
-    mRenderState.meshState().enableTexCoordsVertexArray();
-}
-
-void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) {
-    mCaches.textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
-    mTextureUnit++;
-    mRenderState.meshState().enableTexCoordsVertexArray();
-}
-
-void OpenGLRenderer::setupDrawTextureTransform() {
-    mDescription.hasTextureTransform = true;
-}
-
-void OpenGLRenderer::setupDrawTextureTransformUniforms(mat4& transform) {
-    glUniformMatrix4fv(mCaches.program().getUniform("mainTextureTransform"), 1,
-            GL_FALSE, &transform.data[0]);
-}
-
-void OpenGLRenderer::setupDrawMesh(const GLvoid* vertices,
-        const GLvoid* texCoords, GLuint vbo) {
-    bool force = false;
-    if (!vertices || vbo) {
-        force = mRenderState.meshState().bindMeshBuffer(vbo);
-    } else {
-        force = mRenderState.meshState().unbindMeshBuffer();
-    }
-
-    mRenderState.meshState().bindPositionVertexPointer(force, vertices);
-    if (mCaches.program().texCoords >= 0) {
-        mRenderState.meshState().bindTexCoordsVertexPointer(force, texCoords);
-    }
-
-    mRenderState.meshState().unbindIndicesBuffer();
-}
-
-void OpenGLRenderer::setupDrawMesh(const GLvoid* vertices,
-        const GLvoid* texCoords, const GLvoid* colors) {
-    bool force = mRenderState.meshState().unbindMeshBuffer();
-    GLsizei stride = sizeof(ColorTextureVertex);
-
-    mRenderState.meshState().bindPositionVertexPointer(force, vertices, stride);
-    if (mCaches.program().texCoords >= 0) {
-        mRenderState.meshState().bindTexCoordsVertexPointer(force, texCoords, stride);
-    }
-    int slot = mCaches.program().getAttrib("colors");
-    if (slot >= 0) {
-        glEnableVertexAttribArray(slot);
-        glVertexAttribPointer(slot, 4, GL_FLOAT, GL_FALSE, stride, colors);
-    }
-
-    mRenderState.meshState().unbindIndicesBuffer();
-}
-
-void OpenGLRenderer::setupDrawMeshIndices(const GLvoid* vertices,
-        const GLvoid* texCoords, GLuint vbo) {
-    bool force = false;
-    // If vbo is != 0 we want to treat the vertices parameter as an offset inside
-    // a VBO. However, if vertices is set to NULL and vbo == 0 then we want to
-    // use the default VBO found in RenderState
-    if (!vertices || vbo) {
-        force = mRenderState.meshState().bindMeshBuffer(vbo);
-    } else {
-        force = mRenderState.meshState().unbindMeshBuffer();
-    }
-    mRenderState.meshState().bindQuadIndicesBuffer();
-
-    mRenderState.meshState().bindPositionVertexPointer(force, vertices);
-    if (mCaches.program().texCoords >= 0) {
-        mRenderState.meshState().bindTexCoordsVertexPointer(force, texCoords);
-    }
-}
-
-void OpenGLRenderer::setupDrawIndexedVertices(GLvoid* vertices) {
-    bool force = mRenderState.meshState().unbindMeshBuffer();
-    mRenderState.meshState().bindQuadIndicesBuffer();
-    mRenderState.meshState().bindPositionVertexPointer(force, vertices, kVertexStride);
-}
-
-///////////////////////////////////////////////////////////////////////////////
 // Drawing
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -2049,30 +1499,6 @@
     }
 }
 
-void OpenGLRenderer::drawAlphaBitmap(Texture* texture, const SkPaint* paint) {
-    float x = 0;
-    float y = 0;
-
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-
-    bool ignoreTransform = false;
-    if (currentTransform()->isPureTranslate()) {
-        x = floorf(currentTransform()->getTranslateX() + 0.5f);
-        y = floorf(currentTransform()->getTranslateY() + 0.5f);
-        ignoreTransform = true;
-
-        texture->setFilter(GL_NEAREST, true);
-    } else {
-        texture->setFilter(PaintUtils::getFilter(paint), true);
-    }
-
-    // No need to check for a UV mapper on the texture object, only ARGB_8888
-    // bitmaps get packed in the atlas
-    drawAlpha8TextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
-            paint, (GLvoid*) nullptr, (GLvoid*) kMeshTextureOffset,
-            GL_TRIANGLE_STRIP, kUnitQuadCount, ignoreTransform);
-}
-
 /**
  * Important note: this method is intended to draw batches of bitmaps and
  * will not set the scissor enable or dirty the current layer, if any.
@@ -2086,45 +1512,22 @@
 
     const AutoTexture autoCleanup(texture);
 
-    if (USE_GLOPS) {
-        // TODO: remove layer dirty in multi-draw callers
-        // TODO: snap doesn't need to touch transform, only texture filter.
-        bool snap = pureTranslate;
-        const float x = floorf(bounds.left + 0.5f);
-        const float y = floorf(bounds.top + 0.5f);
-        int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
-                ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedMesh(vertices, bitmapCount * 6)
-                .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
-                .setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(0, 0, bounds.getWidth(), bounds.getHeight()))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    mCaches.textureState().activateTexture(0);
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-    texture->setFilter(pureTranslate ? GL_NEAREST : PaintUtils::getFilter(paint), true);
-
+    // TODO: remove layer dirty in multi-draw callers
+    // TODO: snap doesn't need to touch transform, only texture filter.
+    bool snap = pureTranslate;
     const float x = floorf(bounds.left + 0.5f);
     const float y = floorf(bounds.top + 0.5f);
-    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
-        drawAlpha8TextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
-                texture->id, paint, &vertices[0].x, &vertices[0].u,
-                GL_TRIANGLES, bitmapCount * 6, true,
-                kModelViewMode_Translate, false);
-    } else {
-        drawTextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
-                texture->id, paint, texture->blend, &vertices[0].x, &vertices[0].u,
-                GL_TRIANGLES, bitmapCount * 6, false, true, 0,
-                kModelViewMode_Translate, false);
-    }
-
-    mDirty = true;
+    int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
+            ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedMesh(vertices, bitmapCount * 6)
+            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+            .setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(0, 0, bounds.getWidth(), bounds.getHeight()))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
@@ -2137,28 +1540,17 @@
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
 
-    if (USE_GLOPS) {
-        int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
-                ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedUnitQuad(texture->uvMapper)
-                .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
-        drawAlphaBitmap(texture, paint);
-    } else {
-        drawTextureRect(texture, paint);
-    }
-
-    mDirty = true;
+    int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
+            ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedUnitQuad(texture->uvMapper)
+            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
@@ -2235,56 +1627,19 @@
     }
     const AutoTexture autoCleanup(texture);
 
-    if (USE_GLOPS) {
-        /*
-         * TODO: handle alpha_8 textures correctly by applying paint color, but *not*
-         * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh.
-         */
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshColoredTexturedMesh(mesh.get(), elementCount)
-                .setFillTexturePaint(*texture, static_cast<int>(TextureFillFlags::kNone), paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    mCaches.textureState().activateTexture(0);
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-    texture->setFilter(PaintUtils::getFilter(paint), true);
-
-    int alpha;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &alpha, &mode);
-
-
-    dirtyLayer(left, top, right, bottom, *currentTransform());
-
-    float a = alpha / 255.0f;
-    setupDraw();
-    setupDrawWithTextureAndColor();
-    setupDrawColor(a, a, a, a);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint, true);
-    setupDrawProgram();
-    setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(kModelViewMode_Translate, false, 0, 0, 0, 0);
-    setupDrawTexture(texture->id);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawMesh(&mesh[0].x, &mesh[0].u, &mesh[0].r);
-
-    glDrawArrays(GL_TRIANGLES, 0, elementCount);
-
-    int slot = mCaches.program().getAttrib("colors");
-    if (slot >= 0) {
-        glDisableVertexAttribArray(slot);
-    }
-
-    mDirty = true;
+    /*
+     * TODO: handle alpha_8 textures correctly by applying paint color, but *not*
+     * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh.
+     */
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshColoredTexturedMesh(mesh.get(), elementCount)
+            .setFillTexturePaint(*texture, static_cast<int>(TextureFillFlags::kNone), paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, Rect src, Rect dst, const SkPaint* paint) {
@@ -2296,80 +1651,22 @@
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
 
-    if (USE_GLOPS) {
-        Rect uv(fmax(0.0f, src.left / texture->width),
-                fmax(0.0f, src.top / texture->height),
-                fmin(1.0f, src.right / texture->width),
-                fmin(1.0f, src.bottom / texture->height));
+    Rect uv(fmax(0.0f, src.left / texture->width),
+            fmax(0.0f, src.top / texture->height),
+            fmin(1.0f, src.right / texture->width),
+            fmin(1.0f, src.bottom / texture->height));
 
-        int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
-                ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedUvQuad(texture->uvMapper, uv)
-                .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewMapUnitToRectSnap(dst)
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    mCaches.textureState().activateTexture(0);
-
-    const float width = texture->width;
-    const float height = texture->height;
-
-    float u1 = fmax(0.0f, src.left / width);
-    float v1 = fmax(0.0f, src.top / height);
-    float u2 = fmin(1.0f, src.right / width);
-    float v2 = fmin(1.0f, src.bottom / height);
-
-    getMapper(texture).map(u1, v1, u2, v2);
-
-    mRenderState.meshState().unbindMeshBuffer();
-    resetDrawTextureTexCoords(u1, v1, u2, v2);
-
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-
-    float scaleX = (dst.right - dst.left) / (src.right - src.left);
-    float scaleY = (dst.bottom - dst.top) / (src.bottom - src.top);
-
-    bool scaled = scaleX != 1.0f || scaleY != 1.0f;
-    bool ignoreTransform = false;
-
-    if (CC_LIKELY(currentTransform()->isPureTranslate())) {
-        float x = floorf(dst.left + currentTransform()->getTranslateX() + 0.5f);
-        float y = floorf(dst.top + currentTransform()->getTranslateY() + 0.5f);
-
-        dst.right = x + (dst.right - dst.left);
-        dst.bottom = y + (dst.bottom - dst.top);
-
-        dst.left = x;
-        dst.top = y;
-
-        texture->setFilter(scaled ? PaintUtils::getFilter(paint) : GL_NEAREST, true);
-        ignoreTransform = true;
-    } else {
-        texture->setFilter(PaintUtils::getFilter(paint), true);
-    }
-
-    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
-        drawAlpha8TextureMesh(dst.left, dst.top, dst.right, dst.bottom,
-                texture->id, paint,
-                &mMeshVertices[0].x, &mMeshVertices[0].u,
-                GL_TRIANGLE_STRIP, kUnitQuadCount, ignoreTransform);
-    } else {
-        drawTextureMesh(dst.left, dst.top, dst.right, dst.bottom,
-                texture->id, paint, texture->blend,
-                &mMeshVertices[0].x, &mMeshVertices[0].u,
-                GL_TRIANGLE_STRIP, kUnitQuadCount, false, ignoreTransform);
-    }
-
-    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
-
-    mDirty = true;
+    int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
+            ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedUvQuad(texture->uvMapper, uv)
+            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewMapUnitToRectSnap(dst)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh,
@@ -2382,66 +1679,20 @@
     Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
     if (!texture) return;
 
-    if (USE_GLOPS) {
-        // 9 patches are built for stretching - always filter
-        int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter);
-        if (bitmap->colorType() == kAlpha_8_SkColorType) {
-            textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture;
-        }
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshPatchQuads(*mesh)
-                .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewOffsetRectSnap(left, top, Rect(0, 0, right - left, bottom - top)) // TODO: get minimal bounds from patch
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
+    // 9 patches are built for stretching - always filter
+    int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter);
+    if (bitmap->colorType() == kAlpha_8_SkColorType) {
+        textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture;
     }
-
-    mCaches.textureState().activateTexture(0);
-    const AutoTexture autoCleanup(texture);
-
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-    texture->setFilter(GL_LINEAR, true);
-
-    const bool pureTranslate = currentTransform()->isPureTranslate();
-    // Mark the current layer dirty where we are going to draw the patch
-    if (hasLayer() && mesh->hasEmptyQuads) {
-        const float offsetX = left + currentTransform()->getTranslateX();
-        const float offsetY = top + currentTransform()->getTranslateY();
-        const size_t count = mesh->quads.size();
-        for (size_t i = 0; i < count; i++) {
-            const Rect& bounds = mesh->quads.itemAt(i);
-            if (CC_LIKELY(pureTranslate)) {
-                const float x = floorf(bounds.left + offsetX + 0.5f);
-                const float y = floorf(bounds.top + offsetY + 0.5f);
-                dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight());
-            } else {
-                dirtyLayer(left + bounds.left, top + bounds.top,
-                        left + bounds.right, top + bounds.bottom, *currentTransform());
-            }
-        }
-    }
-
-    bool ignoreTransform = false;
-    if (CC_LIKELY(pureTranslate)) {
-        const float x = floorf(left + currentTransform()->getTranslateX() + 0.5f);
-        const float y = floorf(top + currentTransform()->getTranslateY() + 0.5f);
-
-        right = x + right - left;
-        bottom = y + bottom - top;
-        left = x;
-        top = y;
-        ignoreTransform = true;
-    }
-    drawIndexedTextureMesh(left, top, right, bottom, texture->id, paint,
-            texture->blend, (GLvoid*) mesh->positionOffset, (GLvoid*) mesh->textureOffset,
-            GL_TRIANGLES, mesh->indexCount, false, ignoreTransform,
-            mCaches.patchCache.getMeshBuffer(), kModelViewMode_Translate, !mesh->hasEmptyQuads);
-
-    mDirty = true;
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshPatchQuads(*mesh)
+            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewOffsetRectSnap(left, top, Rect(0, 0, right - left, bottom - top)) // TODO: get minimal bounds from patch
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 /**
@@ -2456,33 +1707,21 @@
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
 
-    if (USE_GLOPS) {
-        // TODO: get correct bounds from caller
-        // 9 patches are built for stretching - always filter
-        int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter);
-        if (bitmap->colorType() == kAlpha_8_SkColorType) {
-            textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture;
-        }
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedIndexedQuads(vertices, elementCount)
-                .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
-                .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
+    // TODO: get correct bounds from caller
+    // 9 patches are built for stretching - always filter
+    int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter);
+    if (bitmap->colorType() == kAlpha_8_SkColorType) {
+        textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture;
     }
-
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-    texture->setFilter(GL_LINEAR, true);
-
-    drawIndexedTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, paint,
-            texture->blend, &vertices[0].x, &vertices[0].u,
-            GL_TRIANGLES, elementCount, false, true, 0, kModelViewMode_Translate, false);
-
-    mDirty = true;
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedIndexedQuads(vertices, elementCount)
+            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+            .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY,
@@ -2493,72 +1732,17 @@
         return;
     }
 
-    if (USE_GLOPS) {
-        bool fudgeOffset = displayFlags & kVertexBuffer_Offset;
-        bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp;
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshVertexBuffer(vertexBuffer, shadowInterp)
-                .setFillPaint(*paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset)
-                .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    const VertexBuffer::MeshFeatureFlags meshFeatureFlags = vertexBuffer.getMeshFeatureFlags();
-    Rect bounds(vertexBuffer.getBounds());
-    bounds.translate(translateX, translateY);
-    dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, *currentTransform());
-
-    int color = paint->getColor();
-    bool isAA = meshFeatureFlags & VertexBuffer::kAlpha;
-
-    setupDraw();
-    setupDrawNoTexture();
-    if (isAA) setupDrawVertexAlpha((displayFlags & kVertexBuffer_ShadowInterp));
-    setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawShader(getShader(paint));
-    setupDrawBlending(paint, isAA);
-    setupDrawProgram();
-    setupDrawModelView(kModelViewMode_Translate, (displayFlags & kVertexBuffer_Offset),
-            translateX, translateY, 0, 0);
-    setupDrawColorUniforms(getShader(paint));
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawShaderUniforms(getShader(paint));
-
-    const void* vertices = vertexBuffer.getBuffer();
-    mRenderState.meshState().unbindMeshBuffer();
-    mRenderState.meshState().bindPositionVertexPointer(true, vertices,
-            isAA ? kAlphaVertexStride : kVertexStride);
-    mRenderState.meshState().resetTexCoordsVertexPointer();
-
-    int alphaSlot = -1;
-    if (isAA) {
-        void* alphaCoords = ((GLbyte*) vertices) + kVertexAlphaOffset;
-        alphaSlot = mCaches.program().getAttrib("vtxAlpha");
-        // TODO: avoid enable/disable in back to back uses of the alpha attribute
-        glEnableVertexAttribArray(alphaSlot);
-        glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, kAlphaVertexStride, alphaCoords);
-    }
-
-    if (meshFeatureFlags & VertexBuffer::kIndices) {
-        mRenderState.meshState().unbindIndicesBuffer();
-        glDrawElements(GL_TRIANGLE_STRIP, vertexBuffer.getIndexCount(),
-                GL_UNSIGNED_SHORT, vertexBuffer.getIndices());
-    } else {
-        mRenderState.meshState().unbindIndicesBuffer();
-        glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount());
-    }
-
-    if (isAA) {
-        glDisableVertexAttribArray(alphaSlot);
-    }
-
-    mDirty = true;
+    bool fudgeOffset = displayFlags & kVertexBuffer_Offset;
+    bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp;
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshVertexBuffer(vertexBuffer, shadowInterp)
+            .setFillPaint(*paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset)
+            .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 /**
@@ -2813,40 +1997,15 @@
     const float sx = x - texture->left + textShadow.dx;
     const float sy = y - texture->top + textShadow.dy;
 
-    if (USE_GLOPS) {
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedUnitQuad(nullptr)
-                .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * currentSnapshot()->alpha;
-    if (getShader(paint)) {
-        textShadow.color = SK_ColorWHITE;
-    }
-
-    setupDraw();
-    setupDrawWithTexture(true);
-    setupDrawAlpha8Color(textShadow.color, shadowAlpha < 255 ? shadowAlpha : alpha);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawShader(getShader(paint));
-    setupDrawBlending(paint, true);
-    setupDrawProgram();
-    setupDrawModelView(kModelViewMode_TranslateAndScale, false,
-            sx, sy, sx + texture->width, sy + texture->height);
-    setupDrawTexture(texture->id);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawShaderUniforms(getShader(paint));
-    setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset);
-
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedUnitQuad(nullptr)
+            .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
@@ -2898,7 +2057,7 @@
     const Rect& clip(pureTranslate ? writableSnapshot()->getClipRect() : writableSnapshot()->getLocalClip());
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
-    TextSetupFunctor functor(this, x, y, pureTranslate, alpha, mode, paint);
+    TextDrawFunctor functor(this, x, y, pureTranslate, alpha, mode, paint);
     if (fontRenderer.renderPosText(paint, &clip, text, 0, bytesCount, count, x, y,
             positions, hasLayer() ? &bounds : nullptr, &functor)) {
         dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, *currentTransform());
@@ -3050,7 +2209,7 @@
     Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
     bool status;
-    TextSetupFunctor functor(this, x, y, pureTranslate, alpha, mode, paint);
+    TextDrawFunctor functor(this, x, y, pureTranslate, alpha, mode, paint);
 
     // don't call issuedrawcommand, do it at end of batch
     bool forceFinish = (drawOpMode != DrawOpMode::kDefer);
@@ -3092,7 +2251,7 @@
     int alpha;
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
-    TextSetupFunctor functor(this, 0.0f, 0.0f, false, alpha, mode, paint);
+    TextDrawFunctor functor(this, 0.0f, 0.0f, false, alpha, mode, paint);
 
     const Rect* clip = &writableSnapshot()->getLocalClip();
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
@@ -3159,56 +2318,15 @@
             DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
                     composeLayerRect(layer, layer->regionRect));
         } else if (layer->mesh) {
-            if (USE_GLOPS) {
-                Glop glop;
-                GlopBuilder(mRenderState, mCaches, &glop)
-                        .setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
-                        .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
-                        .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                        .setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
-                        .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                        .build();
-                DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
-            } else {
-                const float a = getLayerAlpha(layer);
-                setupDraw();
-                setupDrawWithTexture();
-                setupDrawColor(a, a, a, a);
-                setupDrawColorFilter(layer->getColorFilter());
-                setupDrawBlending(layer);
-                setupDrawProgram();
-                setupDrawPureColorUniforms();
-                setupDrawColorFilterUniforms(layer->getColorFilter());
-                setupDrawTexture(layer->getTextureId());
-                if (CC_LIKELY(currentTransform()->isPureTranslate())) {
-                    int tx = (int) floorf(x + currentTransform()->getTranslateX() + 0.5f);
-                    int ty = (int) floorf(y + currentTransform()->getTranslateY() + 0.5f);
-
-                    layer->setFilter(GL_NEAREST);
-                    setupDrawModelView(kModelViewMode_Translate, false, tx, ty,
-                            tx + layer->layer.getWidth(), ty + layer->layer.getHeight(), true);
-                } else {
-                    layer->setFilter(GL_LINEAR);
-                    setupDrawModelView(kModelViewMode_Translate, false, x, y,
-                            x + layer->layer.getWidth(), y + layer->layer.getHeight());
-                }
-
-                TextureVertex* mesh = &layer->mesh[0];
-                GLsizei elementsCount = layer->meshElementCount;
-
-                while (elementsCount > 0) {
-                    GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
-
-                    setupDrawMeshIndices(&mesh[0].x, &mesh[0].u);
-                    DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
-                            glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr));
-
-                    elementsCount -= drawCount;
-                    // Though there are 4 vertices in a quad, we use 6 indices per
-                    // quad to draw with GL_TRIANGLES
-                    mesh += (drawCount / 6) * 4;
-                }
-            }
+            Glop glop;
+            GlopBuilder(mRenderState, mCaches, &glop)
+                    .setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
+                    .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
+                    .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+                    .setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
+                    .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+                    .build();
+            DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
 #if DEBUG_LAYERS_AS_REGIONS
             drawRegionRectsDebug(layer->region);
 #endif
@@ -3258,40 +2376,15 @@
         return;
     }
 
-    if (USE_GLOPS) {
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedUnitQuad(nullptr)
-                .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha)
-                .setTransform(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);
-
-    setupDraw();
-    setupDrawWithTexture(true);
-    setupDrawAlpha8Color(paint->getColor(), alpha);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawShader(getShader(paint));
-    setupDrawBlending(paint, true);
-    setupDrawProgram();
-    setupDrawModelView(kModelViewMode_TranslateAndScale, false,
-            x, y, x + texture->width, y + texture->height);
-    setupDrawTexture(texture->id);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawShaderUniforms(getShader(paint));
-    setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset);
-
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedUnitQuad(nullptr)
+            .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 // Same values used by Skia
@@ -3419,249 +2512,30 @@
         return;
     }
 
-    if (USE_GLOPS) {
-        const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshIndexedQuads(&mesh[0], count / 4)
-                .setFillPaint(*paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
-                .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    int color = paint->getColor();
-    // If a shader is set, preserve only the alpha
-    if (getShader(paint)) {
-        color |= 0x00ffffff;
-    }
-
-    setupDraw();
-    setupDrawNoTexture();
-    setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
-    setupDrawShader(getShader(paint));
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint);
-    setupDrawProgram();
-    setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(kModelViewMode_Translate, false,
-            0.0f, 0.0f, 0.0f, 0.0f, ignoreTransform);
-    setupDrawColorUniforms(getShader(paint));
-    setupDrawShaderUniforms(getShader(paint));
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-
-    if (dirty && hasLayer()) {
-        dirtyLayer(left, top, right, bottom, *currentTransform());
-    }
-
-    issueIndexedQuadDraw(&mesh[0], count / 4);
-
-    mDirty = true;
+    const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshIndexedQuads(&mesh[0], count / 4)
+            .setFillPaint(*paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
+            .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
         const SkPaint* paint, bool ignoreTransform) {
-
-    if (USE_GLOPS) {
-        const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshUnitQuad()
-                .setFillPaint(*paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
-                .setModelViewMapUnitToRect(Rect(left, top, right, bottom))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    int color = paint->getColor();
-    // If a shader is set, preserve only the alpha
-    if (getShader(paint)) {
-        color |= 0x00ffffff;
-    }
-
-    setupDraw();
-    setupDrawNoTexture();
-    setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
-    setupDrawShader(getShader(paint));
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint);
-    setupDrawProgram();
-    setupDrawModelView(kModelViewMode_TranslateAndScale, false,
-            left, top, right, bottom, ignoreTransform);
-    setupDrawColorUniforms(getShader(paint));
-    setupDrawShaderUniforms(getShader(paint), ignoreTransform);
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawSimpleMesh();
-
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
-}
-
-void OpenGLRenderer::drawTextureRect(Texture* texture, const SkPaint* paint) {
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-
-    GLvoid* vertices = (GLvoid*) nullptr;
-    GLvoid* texCoords = (GLvoid*) kMeshTextureOffset;
-
-    if (texture->uvMapper) {
-        vertices = &mMeshVertices[0].x;
-        texCoords = &mMeshVertices[0].u;
-
-        Rect uvs(0.0f, 0.0f, 1.0f, 1.0f);
-        texture->uvMapper->map(uvs);
-
-        resetDrawTextureTexCoords(uvs.left, uvs.top, uvs.right, uvs.bottom);
-    }
-
-    if (CC_LIKELY(currentTransform()->isPureTranslate())) {
-        const float x = floorf(currentTransform()->getTranslateX() + 0.5f);
-        const float y = floorf(currentTransform()->getTranslateY() + 0.5f);
-
-        texture->setFilter(GL_NEAREST, true);
-        drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
-                paint, texture->blend, vertices, texCoords,
-                GL_TRIANGLE_STRIP, kUnitQuadCount, false, true);
-    } else {
-        texture->setFilter(PaintUtils::getFilter(paint), true);
-        drawTextureMesh(0, 0, texture->width, texture->height, texture->id, paint,
-                texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, kUnitQuadCount);
-    }
-
-    if (texture->uvMapper) {
-        resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
-    }
-}
-
-void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
-        GLuint texture, const SkPaint* paint, bool blend,
-        GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-        bool swapSrcDst, bool ignoreTransform, GLuint vbo,
-        ModelViewMode modelViewMode, bool dirty) {
-
-    int a;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &a, &mode);
-    const float alpha = a / 255.0f;
-
-    setupDraw();
-    setupDrawWithTexture();
-    setupDrawColor(alpha, alpha, alpha, alpha);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint, blend, swapSrcDst);
-    setupDrawProgram();
-    if (!dirty) setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform);
-    setupDrawTexture(texture);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawMesh(vertices, texCoords, vbo);
-
-    glDrawArrays(drawMode, 0, elementsCount);
-}
-
-void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right, float bottom,
-        GLuint texture, const SkPaint* paint, bool blend,
-        GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-        bool swapSrcDst, bool ignoreTransform, GLuint vbo,
-        ModelViewMode modelViewMode, bool dirty) {
-
-    int a;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &a, &mode);
-    const float alpha = a / 255.0f;
-
-    setupDraw();
-    setupDrawWithTexture();
-    setupDrawColor(alpha, alpha, alpha, alpha);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint, blend, swapSrcDst);
-    setupDrawProgram();
-    if (!dirty) setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform);
-    setupDrawTexture(texture);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawMeshIndices(vertices, texCoords, vbo);
-
-    glDrawElements(drawMode, elementsCount, GL_UNSIGNED_SHORT, nullptr);
-}
-
-void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom,
-        GLuint texture, const SkPaint* paint,
-        GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-        bool ignoreTransform, ModelViewMode modelViewMode, bool dirty) {
-
-    int color = paint != nullptr ? paint->getColor() : 0;
-    int alpha;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &alpha, &mode);
-
-    setupDraw();
-    setupDrawWithTexture(true);
-    if (paint != nullptr) {
-        setupDrawAlpha8Color(color, alpha);
-    }
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawShader(getShader(paint));
-    setupDrawBlending(paint, true);
-    setupDrawProgram();
-    if (!dirty) setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform);
-    setupDrawTexture(texture);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawShaderUniforms(getShader(paint), ignoreTransform);
-    setupDrawMesh(vertices, texCoords);
-
-    glDrawArrays(drawMode, 0, elementsCount);
-}
-
-void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
-        ProgramDescription& description, bool swapSrcDst) {
-
-    if (currentSnapshot()->roundRectClipState != nullptr /*&& !mSkipOutlineClip*/) {
-        blend = true;
-        mDescription.hasRoundRectClip = true;
-    }
-    mSkipOutlineClip = true;
-
-    blend = blend || mode != SkXfermode::kSrcOver_Mode;
-
-    if (blend) {
-        // These blend modes are not supported by OpenGL directly and have
-        // to be implemented using shaders. Since the shader will perform
-        // the blending, turn blending off here
-        // If the blend mode cannot be implemented using shaders, fall
-        // back to the default SrcOver blend mode instead
-        if (CC_UNLIKELY(mode > SkXfermode::kScreen_Mode)) {
-            if (CC_UNLIKELY(mCaches.extensions().hasFramebufferFetch())) {
-                description.framebufferMode = mode;
-                description.swapSrcDst = swapSrcDst;
-
-                mRenderState.blend().disable();
-                return;
-            } else {
-                mode = SkXfermode::kSrcOver_Mode;
-            }
-        }
-        mRenderState.blend().enable(mode,
-                swapSrcDst ? Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap);
-    } else {
-        mRenderState.blend().disable();
-    }
-}
-
-void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
-    TextureVertex* v = &mMeshVertices[0];
-    TextureVertex::setUV(v++, u1, v1);
-    TextureVertex::setUV(v++, u2, v1);
-    TextureVertex::setUV(v++, u1, v2);
-    TextureVertex::setUV(v++, u2, v2);
+    const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshUnitQuad()
+            .setFillPaint(*paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
+            .setModelViewMapUnitToRect(Rect(left, top, right, bottom))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha,
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index f4acad0..5f8960a 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -65,7 +65,7 @@
 struct Glop;
 class RenderState;
 class RenderNode;
-class TextSetupFunctor;
+class TextDrawFunctor;
 class VertexBuffer;
 
 struct DrawModifiers {
@@ -727,15 +727,6 @@
     void drawShape(float left, float top, PathTexture* texture, const SkPaint* paint);
 
     /**
-     * Draws the specified texture as an alpha bitmap. Alpha bitmaps obey
-     * different compositing rules.
-     *
-     * @param texture The texture to draw with
-     * @param paint The paint to render with
-     */
-    void drawAlphaBitmap(Texture* texture, const SkPaint* paint);
-
-    /**
      * Renders a strip of polygons with the specified paint, used for tessellated geometry.
      *
      * @param vertexBuffer The VertexBuffer to be drawn
@@ -762,60 +753,6 @@
     void drawConvexPath(const SkPath& path, const SkPaint* paint);
 
     /**
-     * Draws a textured rectangle with the specified texture.
-     *
-     * @param texture The texture to use
-     * @param paint The paint containing the alpha, blending mode, etc.
-     */
-    void drawTextureRect(Texture* texture, const SkPaint* paint);
-
-    /**
-     * Draws a textured mesh with the specified texture. If the indices are omitted,
-     * the mesh is drawn as a simple quad. The mesh pointers become offsets when a
-     * VBO is bound.
-     *
-     * @param left The left coordinate of the rectangle
-     * @param top The top coordinate of the rectangle
-     * @param right The right coordinate of the rectangle
-     * @param bottom The bottom coordinate of the rectangle
-     * @param texture The texture name to map onto the rectangle
-     * @param paint The paint containing the alpha, blending mode, colorFilter, etc.
-     * @param blend True if the texture contains an alpha channel
-     * @param vertices The vertices that define the mesh
-     * @param texCoords The texture coordinates of each vertex
-     * @param elementsCount The number of elements in the mesh, required by indices
-     * @param swapSrcDst Whether or not the src and dst blending operations should be swapped
-     * @param ignoreTransform True if the current transform should be ignored
-     * @param vbo The VBO used to draw the mesh
-     * @param modelViewMode Defines whether the model view matrix should be scaled
-     * @param dirty True if calling this method should dirty the current layer
-     */
-    void drawTextureMesh(float left, float top, float right, float bottom, GLuint texture,
-            const SkPaint* paint, bool blend,
-            GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-            bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0,
-            ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale, bool dirty = true);
-
-    void drawIndexedTextureMesh(float left, float top, float right, float bottom, GLuint texture,
-            const SkPaint* paint, bool blend,
-            GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-            bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0,
-            ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale, bool dirty = true);
-
-    void drawAlpha8TextureMesh(float left, float top, float right, float bottom,
-            GLuint texture, const SkPaint* paint,
-            GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-            bool ignoreTransform, ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale,
-            bool dirty = true);
-
-    /**
-     * Draws the specified list of vertices as quads using indexed GL_TRIANGLES.
-     * If the number of vertices to draw exceeds the number of indices we have
-     * pre-allocated, this method will generate several glDrawElements() calls.
-     */
-    void issueIndexedQuadDraw(Vertex* mesh, GLsizei quadsCount);
-
-    /**
      * Draws text underline and strike-through if needed.
      *
      * @param text The text to decor
@@ -873,78 +810,6 @@
      */
     bool canSkipText(const SkPaint* paint) const;
 
-    /**
-     * Enable or disable blending as necessary. This function sets the appropriate
-     * blend function based on the specified xfermode.
-     */
-    inline void chooseBlending(bool blend, SkXfermode::Mode mode, ProgramDescription& description,
-            bool swapSrcDst = false);
-
-    /**
-     * Invoked before any drawing operation. This sets required state.
-     */
-    void setupDraw(bool clear = true);
-
-    /**
-     * Various methods to setup OpenGL rendering.
-     */
-    void setupDrawWithTexture(bool isAlpha8 = false);
-    void setupDrawWithTextureAndColor(bool isAlpha8 = false);
-    void setupDrawWithExternalTexture();
-    void setupDrawNoTexture();
-    void setupDrawVertexAlpha(bool useShadowAlphaInterp);
-    void setupDrawColor(int color, int alpha);
-    void setupDrawColor(float r, float g, float b, float a);
-    void setupDrawAlpha8Color(int color, int alpha);
-    void setupDrawTextGamma(const SkPaint* paint);
-    void setupDrawShader(const SkShader* shader);
-    void setupDrawColorFilter(const SkColorFilter* filter);
-    void setupDrawBlending(const Layer* layer, bool swapSrcDst = false);
-    void setupDrawBlending(const SkPaint* paint, bool blend = true, bool swapSrcDst = false);
-    void setupDrawProgram();
-    void setupDrawDirtyRegionsDisabled();
-
-    /**
-     * Setup the current program matrices based upon the nature of the geometry.
-     *
-     * @param mode If kModelViewMode_Translate, the geometry must be translated by the left and top
-     * parameters. If kModelViewMode_TranslateAndScale, the geometry that exists in the (0,0, 1,1)
-     * space must be scaled up and translated to fill the quad provided in (l,t,r,b). These
-     * transformations are stored in the modelView matrix and uploaded to the shader.
-     *
-     * @param offset Set to true if the the matrix should be fudged (translated) slightly to
-     * disambiguate geometry pixel positioning. See Vertex::GeometryFudgeFactor().
-     *
-     * @param ignoreTransform Set to true if l,t,r,b coordinates already in layer space,
-     * currentTransform() will be ignored. (e.g. when drawing clip in layer coordinates to stencil,
-     * or when simple translation has been extracted)
-     */
-    void setupDrawModelView(ModelViewMode mode, bool offset,
-            float left, float top, float right, float bottom, bool ignoreTransform = false);
-    void setupDrawColorUniforms(bool hasShader);
-    void setupDrawPureColorUniforms();
-
-    /**
-     * Setup uniforms for the current shader.
-     *
-     * @param shader SkShader on the current paint.
-     *
-     * @param ignoreTransform Set to true to ignore the transform in shader.
-     */
-    void setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform = false);
-    void setupDrawColorFilterUniforms(const SkColorFilter* paint);
-    void setupDrawSimpleMesh();
-    void setupDrawTexture(GLuint texture);
-    void setupDrawExternalTexture(GLuint texture);
-    void setupDrawTextureTransform();
-    void setupDrawTextureTransformUniforms(mat4& transform);
-    void setupDrawTextGammaUniforms();
-    void setupDrawMesh(const GLvoid* vertices, const GLvoid* texCoords = nullptr, GLuint vbo = 0);
-    void setupDrawMesh(const GLvoid* vertices, const GLvoid* texCoords, const GLvoid* colors);
-    void setupDrawMeshIndices(const GLvoid* vertices, const GLvoid* texCoords, GLuint vbo = 0);
-    void setupDrawIndexedVertices(GLvoid* vertices);
-    void accountForClear(SkXfermode::Mode mode);
-
     bool updateLayer(Layer* layer, bool inFrame);
     void updateLayers();
     void flushLayers();
@@ -993,22 +858,6 @@
     inline Snapshot* writableSnapshot() { return mState.writableSnapshot(); }
     inline const Snapshot* currentSnapshot() const { return mState.currentSnapshot(); }
 
-    /**
-     * Model-view matrix used to position/size objects
-     *
-     * Stores operation-local modifications to the draw matrix that aren't incorporated into the
-     * currentTransform().
-     *
-     * If generated with kModelViewMode_Translate, mModelViewMatrix will reflect an x/y offset,
-     * e.g. the offset in drawLayer(). If generated with kModelViewMode_TranslateAndScale,
-     * mModelViewMatrix will reflect a translation and scale, e.g. the translation and scale
-     * required to make VBO 0 (a rect of (0,0,1,1)) scaled to match the x,y offset, and width/height
-     * of a bitmap.
-     *
-     * Used as input to SkiaShader transformation.
-     */
-    mat4 mModelViewMatrix;
-
     // State used to define the clipping region
     Rect mTilingClip;
     // Is the target render surface opaque
@@ -1016,9 +865,6 @@
     // Is a frame currently being rendered
     bool mFrameStarted;
 
-    // Used to draw textured quads
-    TextureVertex mMeshVertices[4];
-
     // Default UV mapper
     const UvMapper mUvMapper;
 
@@ -1031,21 +877,6 @@
     // List of layers to update at the beginning of a frame
     Vector< sp<Layer> > mLayerUpdates;
 
-    // The following fields are used to setup drawing
-    // Used to describe the shaders to generate
-    ProgramDescription mDescription;
-    // Color description
-    bool mColorSet;
-    FloatColor mColor;
-    // Indicates that the shader should get a color
-    bool mSetShaderColor;
-    // Current texture unit
-    GLuint mTextureUnit;
-    // Track dirty regions, true by default
-    bool mTrackDirtyRegions;
-    // Indicate whether we are drawing an opaque frame
-    bool mOpaqueFrame;
-
     // See PROPERTY_DISABLE_SCISSOR_OPTIMIZATION in
     // Properties.h
     bool mScissorOptimizationDisabled;
@@ -1070,7 +901,7 @@
     std::vector<std::unique_ptr<SkPath>> mTempPaths;
 
     friend class Layer;
-    friend class TextSetupFunctor;
+    friend class TextDrawFunctor;
     friend class DrawBitmapOp;
     friend class DrawPatchOp;
 
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 2fcf7f3..ecf8b6b 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -47,15 +47,6 @@
     return !(n & (n - 1));
 }
 
-static inline void bindUniformColor(int slot, uint32_t color) {
-    const float a = ((color >> 24) & 0xff) / 255.0f;
-    glUniform4f(slot,
-            a * ((color >> 16) & 0xff) / 255.0f,
-            a * ((color >>  8) & 0xff) / 255.0f,
-            a * ((color      ) & 0xff) / 255.0f,
-            a);
-}
-
 static inline void bindUniformColor(int slot, FloatColor color) {
     glUniform4fv(slot, 1, reinterpret_cast<const float*>(&color));
 }
@@ -83,229 +74,11 @@
     screenSpace.multiply(modelViewMatrix);
 }
 
-// Returns true if one is a bitmap and the other is a gradient
-static bool bitmapAndGradient(SkiaShaderType type1, SkiaShaderType type2) {
-    return (type1 == kBitmap_SkiaShaderType && type2 == kGradient_SkiaShaderType)
-            || (type2 == kBitmap_SkiaShaderType && type1 == kGradient_SkiaShaderType);
-}
-
-SkiaShaderType SkiaShader::getType(const SkShader& shader) {
-    // First check for a gradient shader.
-    switch (shader.asAGradient(nullptr)) {
-        case SkShader::kNone_GradientType:
-            // Not a gradient shader. Fall through to check for other types.
-            break;
-        case SkShader::kLinear_GradientType:
-        case SkShader::kRadial_GradientType:
-        case SkShader::kSweep_GradientType:
-            return kGradient_SkiaShaderType;
-        default:
-            // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip.
-            return kNone_SkiaShaderType;
-    }
-
-    // The shader is not a gradient. Check for a bitmap shader.
-    if (shader.asABitmap(nullptr, nullptr, nullptr) == SkShader::kDefault_BitmapType) {
-        return kBitmap_SkiaShaderType;
-    }
-
-    // Check for a ComposeShader.
-    SkShader::ComposeRec rec;
-    if (shader.asACompose(&rec)) {
-        const SkiaShaderType shaderAType = getType(*rec.fShaderA);
-        const SkiaShaderType shaderBType = getType(*rec.fShaderB);
-
-        // Compose is only supported if one is a bitmap and the other is a
-        // gradient. Otherwise, return None to skip.
-        if (!bitmapAndGradient(shaderAType, shaderBType)) {
-            return kNone_SkiaShaderType;
-        }
-        return kCompose_SkiaShaderType;
-    }
-
-    if (shader.asACustomShader(nullptr)) {
-        return kLayer_SkiaShaderType;
-    }
-
-    return kNone_SkiaShaderType;
-}
-
-typedef void (*describeProc)(Caches* caches, ProgramDescription& description,
-        const Extensions& extensions, const SkShader& shader);
-
-describeProc gDescribeProc[] = {
-    InvalidSkiaShader::describe,
-    SkiaBitmapShader::describe,
-    SkiaGradientShader::describe,
-    SkiaComposeShader::describe,
-    SkiaLayerShader::describe,
-};
-
-typedef void (*setupProgramProc)(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-
-setupProgramProc gSetupProgramProc[] = {
-    InvalidSkiaShader::setupProgram,
-    SkiaBitmapShader::setupProgram,
-    SkiaGradientShader::setupProgram,
-    SkiaComposeShader::setupProgram,
-    SkiaLayerShader::setupProgram,
-};
-
-void SkiaShader::describe(Caches* caches, ProgramDescription& description,
-        const Extensions& extensions, const SkShader& shader) {
-    gDescribeProc[getType(shader)](caches, description, extensions, shader);
-}
-
-void SkiaShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
-
-    gSetupProgramProc[getType(shader)](caches, modelViewMatrix, textureUnit, extensions, shader);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
-// Layer shader
+// gradient shader matrix helpers
 ///////////////////////////////////////////////////////////////////////////////
 
-void SkiaLayerShader::describe(Caches*, ProgramDescription& description,
-        const Extensions&, const SkShader& shader) {
-    description.hasBitmap = true;
-}
-
-void SkiaLayerShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions&, const SkShader& shader) {
-    Layer* layer;
-    if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
-        LOG_ALWAYS_FATAL("SkiaLayerShader::setupProgram called on the wrong type of shader!");
-    }
-
-    GLuint textureSlot = (*textureUnit)++;
-    caches->textureState().activateTexture(textureSlot);
-
-    const float width = layer->getWidth();
-    const float height = layer->getHeight();
-
-    mat4 textureTransform;
-    computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
-            modelViewMatrix);
-
-
-    // Uniforms
-    layer->bindTexture();
-    layer->setWrap(GL_CLAMP_TO_EDGE);
-    layer->setFilter(GL_LINEAR);
-
-    Program& program = caches->program();
-    glUniform1i(program.getUniform("bitmapSampler"), textureSlot);
-    glUniformMatrix4fv(program.getUniform("textureTransform"), 1,
-            GL_FALSE, &textureTransform.data[0]);
-    glUniform2f(program.getUniform("textureDimension"), 1.0f / width, 1.0f / height);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Bitmap shader
-///////////////////////////////////////////////////////////////////////////////
-
-struct BitmapShaderInfo {
-    float width;
-    float height;
-    GLenum wrapS;
-    GLenum wrapT;
-    Texture* texture;
-};
-
-static bool bitmapShaderHelper(Caches* caches, ProgramDescription* description,
-        BitmapShaderInfo* shaderInfo,
-        const Extensions& extensions,
-        const SkBitmap& bitmap, SkShader::TileMode tileModes[2]) {
-    Texture* texture = caches->textureCache.get(&bitmap);
-    if (!texture) return false;
-
-    const float width = texture->width;
-    const float height = texture->height;
-    GLenum wrapS, wrapT;
-
-    if (description) {
-        description->hasBitmap = true;
-    }
-    // The driver does not support non-power of two mirrored/repeated
-    // textures, so do it ourselves
-    if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
-            (tileModes[0] != SkShader::kClamp_TileMode ||
-             tileModes[1] != SkShader::kClamp_TileMode)) {
-        if (description) {
-            description->isBitmapNpot = true;
-            description->bitmapWrapS = gTileModes[tileModes[0]];
-            description->bitmapWrapT = gTileModes[tileModes[1]];
-        }
-        wrapS = GL_CLAMP_TO_EDGE;
-        wrapT = GL_CLAMP_TO_EDGE;
-    } else {
-        wrapS = gTileModes[tileModes[0]];
-        wrapT = gTileModes[tileModes[1]];
-    }
-
-    if (shaderInfo) {
-        shaderInfo->width = width;
-        shaderInfo->height = height;
-        shaderInfo->wrapS = wrapS;
-        shaderInfo->wrapT = wrapT;
-        shaderInfo->texture = texture;
-    }
-    return true;
-}
-
-void SkiaBitmapShader::describe(Caches* caches, ProgramDescription& description,
-        const Extensions& extensions, const SkShader& shader) {
-    SkBitmap bitmap;
-    SkShader::TileMode xy[2];
-    if (shader.asABitmap(&bitmap, nullptr, xy) != SkShader::kDefault_BitmapType) {
-        LOG_ALWAYS_FATAL("SkiaBitmapShader::describe called with a different kind of shader!");
-    }
-    bitmapShaderHelper(caches, &description, nullptr, extensions, bitmap, xy);
-}
-
-void SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
-    SkBitmap bitmap;
-    SkShader::TileMode xy[2];
-    if (shader.asABitmap(&bitmap, nullptr, xy) != SkShader::kDefault_BitmapType) {
-        LOG_ALWAYS_FATAL("SkiaBitmapShader::setupProgram called with a different kind of shader!");
-    }
-
-    GLuint textureSlot = (*textureUnit)++;
-    caches->textureState().activateTexture(textureSlot);
-
-    BitmapShaderInfo shaderInfo;
-    if (!bitmapShaderHelper(caches, nullptr, &shaderInfo, extensions, bitmap, xy)) {
-        return;
-    }
-
-    Program& program = caches->program();
-    Texture* texture = shaderInfo.texture;
-
-    const AutoTexture autoCleanup(texture);
-
-    mat4 textureTransform;
-    computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
-            modelViewMatrix);
-
-    // Uniforms
-    bindTexture(caches, texture, shaderInfo.wrapS, shaderInfo.wrapT);
-    texture->setFilter(GL_LINEAR);
-
-    glUniform1i(program.getUniform("bitmapSampler"), textureSlot);
-    glUniformMatrix4fv(program.getUniform("textureTransform"), 1,
-            GL_FALSE, &textureTransform.data[0]);
-    glUniform2f(program.getUniform("textureDimension"), 1.0f / shaderInfo.width,
-            1.0f / shaderInfo.height);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Linear gradient shader
-///////////////////////////////////////////////////////////////////////////////
-
-static void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
+static void toLinearUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
     SkVector vec = pts[1] - pts[0];
     const float mag = vec.length();
     const float inv = mag ? 1.0f / mag : 0;
@@ -316,10 +89,6 @@
     matrix->postScale(inv, inv);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Circular gradient shader
-///////////////////////////////////////////////////////////////////////////////
-
 static void toCircularUnitMatrix(const float x, const float y, const float radius,
         SkMatrix* matrix) {
     const float inv = 1.0f / radius;
@@ -327,10 +96,6 @@
     matrix->postScale(inv, inv);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Sweep gradient shader
-///////////////////////////////////////////////////////////////////////////////
-
 static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) {
     matrix->setTranslate(-x, -y);
 }
@@ -343,137 +108,6 @@
     return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
 }
 
-void SkiaGradientShader::describe(Caches*, ProgramDescription& description,
-        const Extensions& extensions, const SkShader& shader) {
-    SkShader::GradientInfo gradInfo;
-    gradInfo.fColorCount = 0;
-    gradInfo.fColors = nullptr;
-    gradInfo.fColorOffsets = nullptr;
-
-    switch (shader.asAGradient(&gradInfo)) {
-        case SkShader::kLinear_GradientType:
-            description.gradientType = ProgramDescription::kGradientLinear;
-            break;
-        case SkShader::kRadial_GradientType:
-            description.gradientType = ProgramDescription::kGradientCircular;
-            break;
-        case SkShader::kSweep_GradientType:
-            description.gradientType = ProgramDescription::kGradientSweep;
-            break;
-        default:
-            // Do nothing. This shader is unsupported.
-            return;
-    }
-    description.hasGradient = true;
-    description.isSimpleGradient = isSimpleGradient(gradInfo);
-}
-
-void SkiaGradientShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions&, const SkShader& shader) {
-    // SkShader::GradientInfo.fColorCount is an in/out parameter. As input, it tells asAGradient
-    // how much space has been allocated for fColors and fColorOffsets.  10 was chosen
-    // arbitrarily, but should be >= 2.
-    // As output, it tells the number of actual colors/offsets in the gradient.
-    const int COLOR_COUNT = 10;
-    SkAutoSTMalloc<COLOR_COUNT, SkColor> colorStorage(COLOR_COUNT);
-    SkAutoSTMalloc<COLOR_COUNT, SkScalar> positionStorage(COLOR_COUNT);
-
-    SkShader::GradientInfo gradInfo;
-    gradInfo.fColorCount = COLOR_COUNT;
-    gradInfo.fColors = colorStorage.get();
-    gradInfo.fColorOffsets = positionStorage.get();
-
-    SkShader::GradientType gradType = shader.asAGradient(&gradInfo);
-
-    Program& program = caches->program();
-    if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
-        if (gradInfo.fColorCount > COLOR_COUNT) {
-            // There was not enough room in our arrays for all the colors and offsets. Try again,
-            // now that we know the true number of colors.
-            gradInfo.fColors = colorStorage.reset(gradInfo.fColorCount);
-            gradInfo.fColorOffsets = positionStorage.reset(gradInfo.fColorCount);
-
-            shader.asAGradient(&gradInfo);
-        }
-        GLuint textureSlot = (*textureUnit)++;
-        caches->textureState().activateTexture(textureSlot);
-
-#ifndef SK_SCALAR_IS_FLOAT
-    #error Need to convert gradInfo.fColorOffsets to float!
-#endif
-        Texture* texture = caches->gradientCache.get(gradInfo.fColors, gradInfo.fColorOffsets,
-                gradInfo.fColorCount);
-
-        // Uniforms
-        bindTexture(caches, texture, gTileModes[gradInfo.fTileMode], gTileModes[gradInfo.fTileMode]);
-        glUniform1i(program.getUniform("gradientSampler"), textureSlot);
-    } else {
-        bindUniformColor(program.getUniform("startColor"), gradInfo.fColors[0]);
-        bindUniformColor(program.getUniform("endColor"), gradInfo.fColors[1]);
-    }
-
-    caches->dither.setupProgram(program, textureUnit);
-
-    SkMatrix unitMatrix;
-    switch (gradType) {
-        case SkShader::kLinear_GradientType:
-            toUnitMatrix(gradInfo.fPoint, &unitMatrix);
-            break;
-        case SkShader::kRadial_GradientType:
-            toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY,
-                    gradInfo.fRadius[0], &unitMatrix);
-            break;
-        case SkShader::kSweep_GradientType:
-            toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix);
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Invalid SkShader gradient type %d", gradType);
-    }
-
-    mat4 screenSpace;
-    computeScreenSpaceMatrix(screenSpace, unitMatrix, shader.getLocalMatrix(), modelViewMatrix);
-    glUniformMatrix4fv(program.getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Compose shader
-///////////////////////////////////////////////////////////////////////////////
-
-void SkiaComposeShader::describe(Caches* caches, ProgramDescription& description,
-        const Extensions& extensions, const SkShader& shader) {
-    SkShader::ComposeRec rec;
-    if (!shader.asACompose(&rec)) {
-        LOG_ALWAYS_FATAL("SkiaComposeShader::describe called on the wrong shader type!");
-    }
-    SkiaShader::describe(caches, description, extensions, *rec.fShaderA);
-    SkiaShader::describe(caches, description, extensions, *rec.fShaderB);
-    if (SkiaShader::getType(*rec.fShaderA) == kBitmap_SkiaShaderType) {
-        description.isBitmapFirst = true;
-    }
-    if (!SkXfermode::AsMode(rec.fMode, &description.shadersMode)) {
-        // TODO: Support other modes.
-        description.shadersMode = SkXfermode::kSrcOver_Mode;
-    }
-}
-
-void SkiaComposeShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
-    SkShader::ComposeRec rec;
-    if (!shader.asACompose(&rec)) {
-        LOG_ALWAYS_FATAL("SkiaComposeShader::setupProgram called on the wrong shader type!");
-    }
-
-    // Apply this compose shader's local transform and pass it down to
-    // the child shaders. They will in turn apply their local transform
-    // to this matrix.
-    mat4 transform;
-    computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(),
-            modelViewMatrix);
-
-    SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderA);
-    SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Store / apply
 ///////////////////////////////////////////////////////////////////////////////
@@ -491,7 +125,7 @@
         case SkShader::kLinear_GradientType:
             description->gradientType = ProgramDescription::kGradientLinear;
 
-            toUnitMatrix(gradInfo.fPoint, &unitMatrix);
+            toLinearUnitMatrix(gradInfo.fPoint, &unitMatrix);
             break;
         case SkShader::kRadial_GradientType:
             description->gradientType = ProgramDescription::kGradientCircular;
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 2962441c..5b8aa86 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -87,77 +87,12 @@
 
 class SkiaShader {
 public:
-    static SkiaShaderType getType(const SkShader& shader);
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader);
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-
-    // new SkiaShader interaction model - store into ShaderData, and apply to Caches/Program/GL
     static void store(Caches& caches, const SkShader* shader, const Matrix4& modelViewMatrix,
             GLuint* textureUnit, ProgramDescription* description,
             SkiaShaderData* outData);
     static void apply(Caches& caches, const SkiaShaderData& data);
 };
 
-class InvalidSkiaShader {
-public:
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader) {
-        // This shader is unsupported. Skip it.
-    }
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
-        // This shader is unsupported. Skip it.
-    }
-
-};
-/**
- * A shader that draws a layer.
- */
-class SkiaLayerShader {
-public:
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader);
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-}; // class SkiaLayerShader
-
-/**
- * A shader that draws a bitmap.
- */
-class SkiaBitmapShader {
-public:
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader);
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-
-
-}; // class SkiaBitmapShader
-
-/**
- * A shader that draws one of three types of gradient, depending on shader param.
- */
-class SkiaGradientShader {
-public:
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader);
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-};
-
-/**
- * A shader that draws two shaders, composited with an xfermode.
- */
-class SkiaComposeShader {
-public:
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader);
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-}; // class SkiaComposeShader
-
 }; // namespace uirenderer
 }; // namespace android