/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <GpuMemoryTracker.h>
#include "OpenGLRenderer.h"

#include "DeferredDisplayList.h"
#include "GammaFontRenderer.h"
#include "Glop.h"
#include "GlopBuilder.h"
#include "Patch.h"
#include "PathTessellator.h"
#include "Properties.h"
#include "RenderNode.h"
#include "renderstate/MeshState.h"
#include "renderstate/RenderState.h"
#include "ShadowTessellator.h"
#include "SkiaShader.h"
#include "Vector.h"
#include "VertexBuffer.h"
#include "utils/GLUtils.h"
#include "utils/PaintUtils.h"
#include "utils/TraceUtils.h"

#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>

#include <SkCanvas.h>
#include <SkColor.h>
#include <SkPaintDefaults.h>
#include <SkPathOps.h>
#include <SkShader.h>
#include <SkTypeface.h>

#include <utils/Log.h>
#include <utils/StopWatch.h>

#include <private/hwui/DrawGlInfo.h>

#include <ui/Rect.h>

#if DEBUG_DETAILED_EVENTS
    #define EVENT_LOGD(...) eventMarkDEBUG(__VA_ARGS__)
#else
    #define EVENT_LOGD(...)
#endif

namespace android {
namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////

OpenGLRenderer::OpenGLRenderer(RenderState& renderState)
        : mState(*this)
        , mCaches(Caches::getInstance())
        , mRenderState(renderState)
        , mFrameStarted(false)
        , mScissorOptimizationDisabled(false)
        , mDirty(false)
        , mLightCenter((Vector3){FLT_MIN, FLT_MIN, FLT_MIN})
        , mLightRadius(FLT_MIN)
        , mAmbientShadowAlpha(0)
        , mSpotShadowAlpha(0) {
}

OpenGLRenderer::~OpenGLRenderer() {
    // The context has already been destroyed at this point, do not call
    // GL APIs. All GL state should be kept in Caches.h
}

void OpenGLRenderer::initProperties() {
    char property[PROPERTY_VALUE_MAX];
    if (property_get(PROPERTY_DISABLE_SCISSOR_OPTIMIZATION, property, "false")) {
        mScissorOptimizationDisabled = !strcasecmp(property, "true");
        INIT_LOGD("  Scissor optimization %s",
                mScissorOptimizationDisabled ? "disabled" : "enabled");
    } else {
        INIT_LOGD("  Scissor optimization enabled");
    }
}

void OpenGLRenderer::initLight(float lightRadius, uint8_t ambientShadowAlpha,
        uint8_t spotShadowAlpha) {
    mLightRadius = lightRadius;
    mAmbientShadowAlpha = ambientShadowAlpha;
    mSpotShadowAlpha = spotShadowAlpha;
}

void OpenGLRenderer::setLightCenter(const Vector3& lightCenter) {
    mLightCenter = lightCenter;
}

///////////////////////////////////////////////////////////////////////////////
// Setup
///////////////////////////////////////////////////////////////////////////////

void OpenGLRenderer::onViewportInitialized() {
    glDisable(GL_DITHER);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}

void OpenGLRenderer::setupFrameState(int viewportWidth, int viewportHeight,
        float left, float top, float right, float bottom, bool opaque) {
    mCaches.clearGarbage();
    mState.initializeSaveStack(viewportWidth, viewportHeight,
            left, top, right, bottom, mLightCenter);
    mOpaque = opaque;
    mTilingClip.set(left, top, right, bottom);
}

void OpenGLRenderer::startFrame() {
    if (mFrameStarted) return;
    mFrameStarted = true;

    mState.setDirtyClip(true);

    discardFramebuffer(mTilingClip.left, mTilingClip.top, mTilingClip.right, mTilingClip.bottom);

    mRenderState.setViewport(mState.getWidth(), mState.getHeight());

    debugOverdraw(true, true);

    clear(mTilingClip.left, mTilingClip.top,
            mTilingClip.right, mTilingClip.bottom, mOpaque);
}

void OpenGLRenderer::prepareDirty(int viewportWidth, int viewportHeight,
        float left, float top, float right, float bottom, bool opaque) {

    setupFrameState(viewportWidth, viewportHeight, left, top, right, bottom, opaque);

    // Layer renderers will start the frame immediately
    // The framebuffer renderer will first defer the display list
    // for each layer and wait until the first drawing command
    // to start the frame
    if (currentSnapshot()->fbo == 0) {
        mRenderState.blend().syncEnabled();
        updateLayers();
    } else {
        startFrame();
    }
}

void OpenGLRenderer::discardFramebuffer(float left, float top, float right, float bottom) {
    // If we know that we are going to redraw the entire framebuffer,
    // perform a discard to let the driver know we don't need to preserve
    // the back buffer for this frame.
    if (mCaches.extensions().hasDiscardFramebuffer() &&
            left <= 0.0f && top <= 0.0f && right >= mState.getWidth() && bottom >= mState.getHeight()) {
        const bool isFbo = getTargetFbo() == 0;
        const GLenum attachments[] = {
                isFbo ? (const GLenum) GL_COLOR_EXT : (const GLenum) GL_COLOR_ATTACHMENT0,
                isFbo ? (const GLenum) GL_STENCIL_EXT : (const GLenum) GL_STENCIL_ATTACHMENT };
        glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
    }
}

void OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
    if (!opaque) {
        mRenderState.scissor().setEnabled(true);
        mRenderState.scissor().set(left, getViewportHeight() - bottom, right - left, bottom - top);
        glClear(GL_COLOR_BUFFER_BIT);
        mDirty = true;
        return;
    }

    mRenderState.scissor().reset();
}

bool OpenGLRenderer::finish() {
    renderOverdraw();
    mTempPaths.clear();

    // When finish() is invoked on FBO 0 we've reached the end
    // of the current frame
    if (getTargetFbo() == 0) {
        mCaches.pathCache.trim();
        mCaches.tessellationCache.trim();
    }

    if (!suppressErrorChecks()) {
#if DEBUG_OPENGL
        GLUtils::dumpGLErrors();
#endif

#if DEBUG_MEMORY_USAGE
        mCaches.dumpMemoryUsage();
        GPUMemoryTracker::dump();
#else
        if (Properties::debugLevel & kDebugMemory) {
            mCaches.dumpMemoryUsage();
        }
#endif
    }

    mFrameStarted = false;

    return reportAndClearDirty();
}

void OpenGLRenderer::resumeAfterLayer() {
    mRenderState.setViewport(getViewportWidth(), getViewportHeight());
    mRenderState.bindFramebuffer(currentSnapshot()->fbo);
    debugOverdraw(true, false);

    mRenderState.scissor().reset();
    dirtyClip();
}

void OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
    if (mState.currentlyIgnored()) return;

    Rect clip(mState.currentRenderTargetClip());
    clip.snapToPixelBoundaries();

    // Since we don't know what the functor will draw, let's dirty
    // the entire clip region
    if (hasLayer()) {
        dirtyLayerUnchecked(clip, getRegion());
    }

    DrawGlInfo info;
    info.clipLeft = clip.left;
    info.clipTop = clip.top;
    info.clipRight = clip.right;
    info.clipBottom = clip.bottom;
    info.isLayer = hasLayer();
    info.width = getViewportWidth();
    info.height = getViewportHeight();
    currentTransform()->copyTo(&info.transform[0]);

    bool prevDirtyClip = mState.getDirtyClip();
    // setup GL state for functor
    if (mState.getDirtyClip()) {
        setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt()
    }
    if (mRenderState.scissor().setEnabled(true) || prevDirtyClip) {
        setScissorFromClip();
    }

    mRenderState.invokeFunctor(functor, DrawGlInfo::kModeDraw, &info);
    // Scissor may have been modified, reset dirty clip
    dirtyClip();

    mDirty = true;
}

///////////////////////////////////////////////////////////////////////////////
// Debug
///////////////////////////////////////////////////////////////////////////////

void OpenGLRenderer::eventMarkDEBUG(const char* fmt, ...) const {
#if DEBUG_DETAILED_EVENTS
    const int BUFFER_SIZE = 256;
    va_list ap;
    char buf[BUFFER_SIZE];

    va_start(ap, fmt);
    vsnprintf(buf, BUFFER_SIZE, fmt, ap);
    va_end(ap);

    eventMark(buf);
#endif
}


void OpenGLRenderer::eventMark(const char* name) const {
    mCaches.eventMark(0, name);
}

void OpenGLRenderer::startMark(const char* name) const {
    mCaches.startMark(0, name);
}

void OpenGLRenderer::endMark() const {
    mCaches.endMark();
}

void OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
    mRenderState.debugOverdraw(enable, clear);
}

void OpenGLRenderer::renderOverdraw() {
    if (Properties::debugOverdraw && getTargetFbo() == 0) {
        const Rect* clip = &mTilingClip;

        mRenderState.scissor().setEnabled(true);
        mRenderState.scissor().set(clip->left,
                mState.firstSnapshot()->getViewportHeight() - clip->bottom,
                clip->right - clip->left,
                clip->bottom - clip->top);

        // 1x overdraw
        mRenderState.stencil().enableDebugTest(2);
        drawColor(mCaches.getOverdrawColor(1), SkXfermode::kSrcOver_Mode);

        // 2x overdraw
        mRenderState.stencil().enableDebugTest(3);
        drawColor(mCaches.getOverdrawColor(2), SkXfermode::kSrcOver_Mode);

        // 3x overdraw
        mRenderState.stencil().enableDebugTest(4);
        drawColor(mCaches.getOverdrawColor(3), SkXfermode::kSrcOver_Mode);

        // 4x overdraw and higher
        mRenderState.stencil().enableDebugTest(4, true);
        drawColor(mCaches.getOverdrawColor(4), SkXfermode::kSrcOver_Mode);

        mRenderState.stencil().disable();
    }
}

///////////////////////////////////////////////////////////////////////////////
// Layers
///////////////////////////////////////////////////////////////////////////////

bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
    if (layer->deferredUpdateScheduled && layer->renderer
            && layer->renderNode.get() && layer->renderNode->isRenderable()) {

        if (inFrame) {
            debugOverdraw(false, false);
        }

        if (CC_UNLIKELY(inFrame || Properties::drawDeferDisabled)) {
            layer->render(*this);
        } else {
            layer->defer(*this);
        }

        if (inFrame) {
            resumeAfterLayer();
        }

        layer->debugDrawUpdate = Properties::debugLayersUpdates;
        layer->hasDrawnSinceUpdate = false;

        return true;
    }

    return false;
}

void OpenGLRenderer::updateLayers() {
    // If draw deferring is enabled this method will simply defer
    // the display list of each individual layer. The layers remain
    // in the layer updates list which will be cleared by flushLayers().
    int count = mLayerUpdates.size();
    if (count > 0) {
        if (CC_UNLIKELY(Properties::drawDeferDisabled)) {
            startMark("Layer Updates");
        } else {
            startMark("Defer Layer Updates");
        }

        // Note: it is very important to update the layers in order
        for (int i = 0; i < count; i++) {
            Layer* layer = mLayerUpdates[i].get();
            updateLayer(layer, false);
        }

        if (CC_UNLIKELY(Properties::drawDeferDisabled)) {
            mLayerUpdates.clear();
            mRenderState.bindFramebuffer(getTargetFbo());
        }
        endMark();
    }
}

void OpenGLRenderer::flushLayers() {
    int count = mLayerUpdates.size();
    if (count > 0) {
        startMark("Apply Layer Updates");

        // Note: it is very important to update the layers in order
        for (int i = 0; i < count; i++) {
            mLayerUpdates[i]->flush();
        }

        mLayerUpdates.clear();
        mRenderState.bindFramebuffer(getTargetFbo());

        endMark();
    }
}

void OpenGLRenderer::pushLayerUpdate(Layer* layer) {
    if (layer) {
        // Make sure we don't introduce duplicates.
        // SortedVector would do this automatically but we need to respect
        // the insertion order. The linear search is not an issue since
        // this list is usually very short (typically one item, at most a few)
        for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
            if (mLayerUpdates[i] == layer) {
                return;
            }
        }
        mLayerUpdates.push_back(layer);
    }
}

void OpenGLRenderer::cancelLayerUpdate(Layer* layer) {
    if (layer) {
        for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
            if (mLayerUpdates[i] == layer) {
                mLayerUpdates.erase(mLayerUpdates.begin() + i);
                break;
            }
        }
    }
}

void OpenGLRenderer::flushLayerUpdates() {
    ATRACE_NAME("Update HW Layers");
    mRenderState.blend().syncEnabled();
    updateLayers();
    flushLayers();
    // Wait for all the layer updates to be executed
    glFinish();
}

void OpenGLRenderer::markLayersAsBuildLayers() {
    for (size_t i = 0; i < mLayerUpdates.size(); i++) {
        mLayerUpdates[i]->wasBuildLayered = true;
    }
}

///////////////////////////////////////////////////////////////////////////////
// State management
///////////////////////////////////////////////////////////////////////////////

void OpenGLRenderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
    bool restoreViewport = removed.flags & Snapshot::kFlagIsFboLayer;
    bool restoreClip = removed.flags & Snapshot::kFlagClipSet;
    bool restoreLayer = removed.flags & Snapshot::kFlagIsLayer;

    if (restoreViewport) {
        mRenderState.setViewport(getViewportWidth(), getViewportHeight());
    }

    if (restoreClip) {
        dirtyClip();
    }

    if (restoreLayer) {
        endMark(); // Savelayer
        ATRACE_END(); // SaveLayer
        startMark("ComposeLayer");
        composeLayer(removed, restored);
        endMark();
    }
}

///////////////////////////////////////////////////////////////////////////////
// Layers
///////////////////////////////////////////////////////////////////////////////

int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
        const SkPaint* paint, int flags, const SkPath* convexMask) {
    // force matrix/clip isolation for layer
    flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag;

    const int count = mState.saveSnapshot(flags);

    if (!mState.currentlyIgnored()) {
        createLayer(left, top, right, bottom, paint, flags, convexMask);
    }

    return count;
}

void OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer) {
    const Rect untransformedBounds(bounds);

    currentTransform()->mapRect(bounds);

    // Layers only make sense if they are in the framebuffer's bounds
    bounds.doIntersect(mState.currentRenderTargetClip());
    if (!bounds.isEmpty()) {
        // We cannot work with sub-pixels in this case
        bounds.snapToPixelBoundaries();

        // When the layer is not an FBO, we may use glCopyTexImage so we
        // need to make sure the layer does not extend outside the bounds
        // of the framebuffer
        const Snapshot& previous = *(currentSnapshot()->previous);
        Rect previousViewport(0, 0, previous.getViewportWidth(), previous.getViewportHeight());

        bounds.doIntersect(previousViewport);
        if (!bounds.isEmpty() && fboLayer) {
            clip.set(bounds);
            mat4 inverse;
            inverse.loadInverse(*currentTransform());
            inverse.mapRect(clip);
            clip.snapToPixelBoundaries();
            clip.doIntersect(untransformedBounds);
            if (!clip.isEmpty()) {
                clip.translate(-untransformedBounds.left, -untransformedBounds.top);
                bounds.set(untransformedBounds);
            }
        }
    }
}

void OpenGLRenderer::updateSnapshotIgnoreForLayer(const Rect& bounds, const Rect& clip,
        bool fboLayer, int alpha) {
    if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
            bounds.getHeight() > mCaches.maxTextureSize ||
            (fboLayer && clip.isEmpty())) {
        writableSnapshot()->empty = fboLayer;
    } else {
        writableSnapshot()->invisible = writableSnapshot()->invisible || (alpha <= 0 && fboLayer);
    }
}

int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom,
        const SkPaint* paint, int flags) {
    const int count = mState.saveSnapshot(flags);

    if (!mState.currentlyIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) {
        // initialize the snapshot as though it almost represents an FBO layer so deferred draw
        // operations will be able to store and restore the current clip and transform info, and
        // quick rejection will be correct (for display lists)

        Rect bounds(left, top, right, bottom);
        Rect clip;
        calculateLayerBoundsAndClip(bounds, clip, true);
        updateSnapshotIgnoreForLayer(bounds, clip, true, PaintUtils::getAlphaDirect(paint));

        if (!mState.currentlyIgnored()) {
            writableSnapshot()->resetTransform(-bounds.left, -bounds.top, 0.0f);
            writableSnapshot()->resetClip(clip.left, clip.top, clip.right, clip.bottom);
            writableSnapshot()->initializeViewport(bounds.getWidth(), bounds.getHeight());
            writableSnapshot()->roundRectClipState = nullptr;
        }
    }

    return count;
}

/**
 * Layers are viewed by Skia are slightly different than layers in image editing
 * programs (for instance.) When a layer is created, previously created layers
 * and the frame buffer still receive every drawing command. For instance, if a
 * layer is created and a shape intersecting the bounds of the layers and the
 * framebuffer is draw, the shape will be drawn on both (unless the layer was
 * created with the SkCanvas::kClipToLayer_SaveFlag flag.)
 *
 * A way to implement layers is to create an FBO for each layer, backed by an RGBA
 * texture. Unfortunately, this is inefficient as it requires every primitive to
 * be drawn n + 1 times, where n is the number of active layers. In practice this
 * means, for every primitive:
 *   - Switch active frame buffer
 *   - Change viewport, clip and projection matrix
 *   - Issue the drawing
 *
 * Switching rendering target n + 1 times per drawn primitive is extremely costly.
 * To avoid this, layers are implemented in a different way here, at least in the
 * general case. FBOs are used, as an optimization, when the "clip to layer" flag
 * is set. When this flag is set we can redirect all drawing operations into a
 * single FBO.
 *
 * This implementation relies on the frame buffer being at least RGBA 8888. When
 * a layer is created, only a texture is created, not an FBO. The content of the
 * frame buffer contained within the layer's bounds is copied into this texture
 * using glCopyTexImage2D(). The layer's region is then cleared(1) in the frame
 * buffer and drawing continues as normal. This technique therefore treats the
 * frame buffer as a scratch buffer for the layers.
 *
 * To compose the layers back onto the frame buffer, each layer texture
 * (containing the original frame buffer data) is drawn as a simple quad over
 * the frame buffer. The trick is that the quad is set as the composition
 * destination in the blending equation, and the frame buffer becomes the source
 * of the composition.
 *
 * Drawing layers with an alpha value requires an extra step before composition.
 * An empty quad is drawn over the layer's region in the frame buffer. This quad
 * is drawn with the rgba color (0,0,0,alpha). The alpha value offered by the
 * quad is used to multiply the colors in the frame buffer. This is achieved by
 * changing the GL blend functions for the GL_FUNC_ADD blend equation to
 * GL_ZERO, GL_SRC_ALPHA.
 *
 * Because glCopyTexImage2D() can be slow, an alternative implementation might
 * be use to draw a single clipped layer. The implementation described above
 * is correct in every case.
 *
 * (1) The frame buffer is actually not cleared right away. To allow the GPU
 *     to potentially optimize series of calls to glCopyTexImage2D, the frame
 *     buffer is left untouched until the first drawing operation. Only when
 *     something actually gets drawn are the layers regions cleared.
 */
bool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
        const SkPaint* paint, int flags, const SkPath* convexMask) {
    LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
    LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());

    const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag;

    // Window coordinates of the layer
    Rect clip;
    Rect bounds(left, top, right, bottom);
    calculateLayerBoundsAndClip(bounds, clip, fboLayer);
    updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, PaintUtils::getAlphaDirect(paint));

    // Bail out if we won't draw in this snapshot
    if (mState.currentlyIgnored()) {
        return false;
    }

    mCaches.textureState().activateTexture(0);
    Layer* layer = mCaches.layerCache.get(mRenderState, bounds.getWidth(), bounds.getHeight());
    if (!layer) {
        return false;
    }

    layer->setPaint(paint);
    layer->layer.set(bounds);
    layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
            bounds.getWidth() / float(layer->getWidth()), 0.0f);

    layer->setBlend(true);
    layer->setDirty(false);
    layer->setConvexMask(convexMask); // note: the mask must be cleared before returning to the cache

    // Save the layer in the snapshot
    writableSnapshot()->flags |= Snapshot::kFlagIsLayer;
    writableSnapshot()->layer = layer;

    ATRACE_FORMAT_BEGIN("%ssaveLayer %ux%u",
            fboLayer ? "" : "unclipped ",
            layer->getWidth(), layer->getHeight());
    startMark("SaveLayer");
    if (fboLayer) {
        return createFboLayer(layer, bounds, clip);
    } else {
        // Copy the framebuffer into the layer
        layer->bindTexture();
        if (!bounds.isEmpty()) {
            if (layer->isEmpty()) {
                // Workaround for some GL drivers. When reading pixels lying outside
                // of the window we should get undefined values for those pixels.
                // Unfortunately some drivers will turn the entire target texture black
                // when reading outside of the window.
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->getWidth(), layer->getHeight(),
                        0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
                layer->setEmpty(false);
            }

            glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
                    bounds.left, getViewportHeight() - bounds.bottom,
                    bounds.getWidth(), bounds.getHeight());

            // Enqueue the buffer coordinates to clear the corresponding region later
            mLayers.push_back(Rect(bounds));
        }
    }

    return true;
}

bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) {
    layer->clipRect.set(clip);
    layer->setFbo(mRenderState.genFramebuffer());

    writableSnapshot()->region = &writableSnapshot()->layer->region;
    writableSnapshot()->flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer;
    writableSnapshot()->fbo = layer->getFbo();
    writableSnapshot()->resetTransform(-bounds.left, -bounds.top, 0.0f);
    writableSnapshot()->resetClip(clip.left, clip.top, clip.right, clip.bottom);
    writableSnapshot()->initializeViewport(bounds.getWidth(), bounds.getHeight());
    writableSnapshot()->roundRectClipState = nullptr;

    debugOverdraw(false, false);
    // Bind texture to FBO
    mRenderState.bindFramebuffer(layer->getFbo());
    layer->bindTexture();

    // Initialize the texture if needed
    if (layer->isEmpty()) {
        layer->allocateTexture();
        layer->setEmpty(false);
    }

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
            layer->getTextureId(), 0);

    // Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
    mRenderState.scissor().setEnabled(true);
    mRenderState.scissor().set(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
            clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    dirtyClip();

    // Change the ortho projection
    mRenderState.setViewport(bounds.getWidth(), bounds.getHeight());
    return true;
}

/**
 * Read the documentation of createLayer() before doing anything in this method.
 */
void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& restored) {
    if (!removed.layer) {
        ALOGE("Attempting to compose a layer that does not exist");
        return;
    }

    Layer* layer = removed.layer;
    const Rect& rect = layer->layer;
    const bool fboLayer = removed.flags & Snapshot::kFlagIsFboLayer;

    bool clipRequired = false;
    mState.calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom,
            &clipRequired, nullptr, false); // safely ignore return, should never be rejected
    mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);

    if (fboLayer) {
        // Detach the texture from the FBO
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);

        layer->removeFbo(false);

        // Unbind current FBO and restore previous one
        mRenderState.bindFramebuffer(restored.fbo);
        debugOverdraw(true, false);
    }

    if (!fboLayer && layer->getAlpha() < 255) {
        SkPaint layerPaint;
        layerPaint.setAlpha(layer->getAlpha());
        layerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
        layerPaint.setColorFilter(layer->getColorFilter());

        drawColorRect(rect.left, rect.top, rect.right, rect.bottom, &layerPaint, true);
        // Required below, composeLayerRect() will divide by 255
        layer->setAlpha(255);
    }

    mRenderState.meshState().unbindMeshBuffer();

    mCaches.textureState().activateTexture(0);

    // When the layer is stored in an FBO, we can save a bit of fillrate by
    // drawing only the dirty region
    if (fboLayer) {
        dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *restored.transform);
        composeLayerRegion(layer, rect);
    } else if (!rect.isEmpty()) {
        dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);

        save(0);
        // the layer contains screen buffer content that shouldn't be alpha modulated
        // (and any necessary alpha modulation was handled drawing into the layer)
        writableSnapshot()->alpha = 1.0f;
        composeLayerRectSwapped(layer, rect);
        restore();
    }

    dirtyClip();

    // Failing to add the layer to the cache should happen only if the layer is too large
    layer->setConvexMask(nullptr);
    if (!mCaches.layerCache.put(layer)) {
        LAYER_LOGD("Deleting layer");
        layer->decStrong(nullptr);
    }
}

void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
    const bool tryToSnap = !layer->getForceFilter()
            && layer->getWidth() == (uint32_t) rect.getWidth()
            && layer->getHeight() == (uint32_t) rect.getHeight();
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
            .setFillTextureLayer(*layer, getLayerAlpha(layer))
            .setTransform(*currentSnapshot(), TransformFlags::None)
            .setModelViewMapUnitToRectOptionalSnap(tryToSnap, rect)
            .build();
    renderGlop(glop);
}

void OpenGLRenderer::composeLayerRectSwapped(Layer* layer, const Rect& rect) {
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshTexturedUvQuad(nullptr, layer->texCoords)
            .setFillLayer(layer->getTexture(), layer->getColorFilter(),
                    getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::Swap)
            .setTransform(*currentSnapshot(), TransformFlags::MeshIgnoresCanvasTransform)
            .setModelViewMapUnitToRect(rect)
            .build();
    renderGlop(glop);
}

void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect) {
    if (layer->isTextureLayer()) {
        EVENT_LOGD("composeTextureLayerRect");
        drawTextureLayer(layer, rect);
    } else {
        EVENT_LOGD("composeHardwareLayerRect");

        const bool tryToSnap = layer->getWidth() == static_cast<uint32_t>(rect.getWidth())
                && layer->getHeight() == static_cast<uint32_t>(rect.getHeight());
        Glop glop;
        GlopBuilder(mRenderState, mCaches, &glop)
                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
                .setMeshTexturedUvQuad(nullptr, layer->texCoords)
                .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
                .setTransform(*currentSnapshot(), TransformFlags::None)
                .setModelViewMapUnitToRectOptionalSnap(tryToSnap, rect)
                .build();
        renderGlop(glop);
    }
}

/**
 * Issues the command X, and if we're composing a save layer to the fbo or drawing a newly updated
 * hardware layer with overdraw debug on, draws again to the stencil only, so that these draw
 * operations are correctly counted twice for overdraw. NOTE: assumes composeLayerRegion only used
 * by saveLayer's restore
 */
#define DRAW_DOUBLE_STENCIL_IF(COND, DRAW_COMMAND) { \
        DRAW_COMMAND; \
        if (CC_UNLIKELY(Properties::debugOverdraw && getTargetFbo() == 0 && COND)) { \
            glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); \
            DRAW_COMMAND; \
            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \
        } \
    }

#define DRAW_DOUBLE_STENCIL(DRAW_COMMAND) DRAW_DOUBLE_STENCIL_IF(true, DRAW_COMMAND)

// This class is purely for inspection. It inherits from SkShader, but Skia does not know how to
// use it. The OpenGLRenderer will look at it to find its Layer and whether it is opaque.
class LayerShader : public SkShader {
public:
    LayerShader(Layer* layer, const SkMatrix* localMatrix)
    : INHERITED(localMatrix)
    , mLayer(layer) {
    }

    virtual bool asACustomShader(void** data) const override {
        if (data) {
            *data = static_cast<void*>(mLayer);
        }
        return true;
    }

    virtual bool isOpaque() const override {
        return !mLayer->isBlend();
    }

protected:
    virtual void shadeSpan(int x, int y, SkPMColor[], int count) {
        LOG_ALWAYS_FATAL("LayerShader should never be drawn with raster backend.");
    }

    virtual void flatten(SkWriteBuffer&) const override {
        LOG_ALWAYS_FATAL("LayerShader should never be flattened.");
    }

    virtual Factory getFactory() const override {
        LOG_ALWAYS_FATAL("LayerShader should never be created from a stream.");
        return nullptr;
    }
private:
    // Unowned.
    Layer* mLayer;
    typedef SkShader INHERITED;
};

void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
    if (CC_UNLIKELY(layer->region.isEmpty())) return; // nothing to draw

    if (layer->getConvexMask()) {
        save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);

        // clip to the area of the layer the mask can be larger
        clipRect(rect.left, rect.top, rect.right, rect.bottom, SkRegion::kIntersect_Op);

        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setColor(SkColorSetARGB(int(getLayerAlpha(layer) * 255), 0, 0, 0));

        // create LayerShader to map SaveLayer content into subsequent draw
        SkMatrix shaderMatrix;
        shaderMatrix.setTranslate(rect.left, rect.bottom);
        shaderMatrix.preScale(1, -1);
        LayerShader layerShader(layer, &shaderMatrix);
        paint.setShader(&layerShader);

        // Since the drawing primitive is defined in local drawing space,
        // we don't need to modify the draw matrix
        const SkPath* maskPath = layer->getConvexMask();
        DRAW_DOUBLE_STENCIL(drawConvexPath(*maskPath, &paint));

        paint.setShader(nullptr);
        restore();

        return;
    }

    if (layer->region.isRect()) {
        layer->setRegionAsRect();

        DRAW_DOUBLE_STENCIL(composeLayerRect(layer, layer->regionRect));

        layer->region.clear();
        return;
    }

    EVENT_LOGD("composeLayerRegion");
    // standard Region based draw
    size_t count;
    const android::Rect* rects;
    Region safeRegion;
    if (CC_LIKELY(hasRectToRectTransform())) {
        rects = layer->region.getArray(&count);
    } else {
        safeRegion = Region::createTJunctionFreeRegion(layer->region);
        rects = safeRegion.getArray(&count);
    }

    const float texX = 1.0f / float(layer->getWidth());
    const float texY = 1.0f / float(layer->getHeight());
    const float height = rect.getHeight();

    TextureVertex quadVertices[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);
    }
    Rect modelRect = Rect(rect.getWidth(), rect.getHeight());
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshTexturedIndexedQuads(&quadVertices[0], count * 6)
            .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
            .setTransform(*currentSnapshot(),  TransformFlags::None)
            .setModelViewOffsetRectSnap(rect.left, rect.top, modelRect)
            .build();
    DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));

#if DEBUG_LAYERS_AS_REGIONS
    drawRegionRectsDebug(layer->region);
#endif

    layer->region.clear();
}

#if DEBUG_LAYERS_AS_REGIONS
void OpenGLRenderer::drawRegionRectsDebug(const Region& region) {
    size_t count;
    const android::Rect* rects = region.getArray(&count);

    uint32_t colors[] = {
            0x7fff0000, 0x7f00ff00,
            0x7f0000ff, 0x7fff00ff,
    };

    int offset = 0;
    int32_t top = rects[0].top;

    for (size_t i = 0; i < count; i++) {
        if (top != rects[i].top) {
            offset ^= 0x2;
            top = rects[i].top;
        }

        SkPaint paint;
        paint.setColor(colors[offset + (i & 0x1)]);
        Rect r(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
        drawColorRect(r.left, r.top, r.right, r.bottom, paint);
    }
}
#endif

void OpenGLRenderer::drawRegionRects(const SkRegion& region, const SkPaint& paint, bool dirty) {
    Vector<float> rects;

    SkRegion::Iterator it(region);
    while (!it.done()) {
        const SkIRect& r = it.rect();
        rects.push(r.fLeft);
        rects.push(r.fTop);
        rects.push(r.fRight);
        rects.push(r.fBottom);
        it.next();
    }

    drawColorRects(rects.array(), rects.size(), &paint, true, dirty, false);
}

void OpenGLRenderer::dirtyLayer(const float left, const float top,
        const float right, const float bottom, const Matrix4& transform) {
    if (hasLayer()) {
        Rect bounds(left, top, right, bottom);
        transform.mapRect(bounds);
        dirtyLayerUnchecked(bounds, getRegion());
    }
}

void OpenGLRenderer::dirtyLayer(const float left, const float top,
        const float right, const float bottom) {
    if (hasLayer()) {
        Rect bounds(left, top, right, bottom);
        dirtyLayerUnchecked(bounds, getRegion());
    }
}

void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) {
    bounds.doIntersect(mState.currentRenderTargetClip());
    if (!bounds.isEmpty()) {
        bounds.snapToPixelBoundaries();
        android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
        if (!dirty.isEmpty()) {
            region->orSelf(dirty);
        }
    }
}

void OpenGLRenderer::clearLayerRegions() {
    const size_t quadCount = mLayers.size();
    if (quadCount == 0) return;

    if (!mState.currentlyIgnored()) {
        EVENT_LOGD("clearLayerRegions");
        // Doing several glScissor/glClear here can negatively impact
        // GPUs with a tiler architecture, instead we draw quads with
        // the Clear blending mode

        // The list contains bounds that have already been clipped
        // against their initial clip rect, and the current clip
        // is likely different so we need to disable clipping here
        bool scissorChanged = mRenderState.scissor().setEnabled(false);

        Vertex mesh[quadCount * 4];
        Vertex* vertex = mesh;

        for (uint32_t i = 0; i < quadCount; i++) {
            const Rect& bounds = mLayers[i];

            Vertex::set(vertex++, bounds.left, bounds.top);
            Vertex::set(vertex++, bounds.right, bounds.top);
            Vertex::set(vertex++, bounds.left, bounds.bottom);
            Vertex::set(vertex++, bounds.right, bounds.bottom);
        }
        // We must clear the list of dirty rects before we
        // call clearLayerRegions() in renderGlop to prevent
        // stencil setup from doing the same thing again
        mLayers.clear();

        const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
        Glop glop;
        GlopBuilder(mRenderState, mCaches, &glop)
                .setRoundRectClipState(nullptr) // clear ignores clip state
                .setMeshIndexedQuads(&mesh[0], quadCount)
                .setFillClear()
                .setTransform(*currentSnapshot(), transformFlags)
                .setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getRenderTargetClip()))
                .build();
        renderGlop(glop, GlopRenderType::LayerClear);

        if (scissorChanged) mRenderState.scissor().setEnabled(true);
    } else {
        mLayers.clear();
    }
}

///////////////////////////////////////////////////////////////////////////////
// State Deferral
///////////////////////////////////////////////////////////////////////////////

bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDeferFlags) {
    const Rect& currentClip = mState.currentRenderTargetClip();
    const mat4* currentMatrix = currentTransform();

    if (stateDeferFlags & kStateDeferFlag_Draw) {
        // state has bounds initialized in local coordinates
        if (!state.mBounds.isEmpty()) {
            currentMatrix->mapRect(state.mBounds);
            Rect clippedBounds(state.mBounds);
            // NOTE: if we ever want to use this clipping info to drive whether the scissor
            // is used, it should more closely duplicate the quickReject logic (in how it uses
            // snapToPixelBoundaries)

            clippedBounds.doIntersect(currentClip);
            if (clippedBounds.isEmpty()) {
                // quick rejected
                return true;
            }

            state.mClipSideFlags = kClipSide_None;
            if (!currentClip.contains(state.mBounds)) {
                int& flags = state.mClipSideFlags;
                // op partially clipped, so record which sides are clipped for clip-aware merging
                if (currentClip.left > state.mBounds.left) flags |= kClipSide_Left;
                if (currentClip.top > state.mBounds.top) flags |= kClipSide_Top;
                if (currentClip.right < state.mBounds.right) flags |= kClipSide_Right;
                if (currentClip.bottom < state.mBounds.bottom) flags |= kClipSide_Bottom;
            }
            state.mBounds.set(clippedBounds);
        } else {
            // Empty bounds implies size unknown. Label op as conservatively clipped to disable
            // overdraw avoidance (since we don't know what it overlaps)
            state.mClipSideFlags = kClipSide_ConservativeFull;
            state.mBounds.set(currentClip);
        }
    }

    state.mClipValid = (stateDeferFlags & kStateDeferFlag_Clip);
    if (state.mClipValid) {
        state.mClip.set(currentClip);
    }

    // Transform and alpha always deferred, since they are used by state operations
    // (Note: saveLayer/restore use colorFilter and alpha, so we just save restore everything)
    state.mMatrix = *currentMatrix;
    state.mAlpha = currentSnapshot()->alpha;

    // always store/restore, since these are just pointers
    state.mRoundRectClipState = currentSnapshot()->roundRectClipState;
    state.mProjectionPathMask = currentSnapshot()->projectionPathMask;
    return false;
}

void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore) {
    setGlobalMatrix(state.mMatrix);
    writableSnapshot()->alpha = state.mAlpha;
    writableSnapshot()->roundRectClipState = state.mRoundRectClipState;
    writableSnapshot()->projectionPathMask = state.mProjectionPathMask;

    if (state.mClipValid && !skipClipRestore) {
        writableSnapshot()->setClip(state.mClip.left, state.mClip.top,
                state.mClip.right, state.mClip.bottom);
        dirtyClip();
    }
}

/**
 * Merged multidraw (such as in drawText and drawBitmaps rely on the fact that no clipping is done
 * in the draw path. Instead, clipping is done ahead of time - either as a single clip rect (when at
 * least one op is clipped), or disabled entirely (because no merged op is clipped)
 *
 * This method should be called when restoreDisplayState() won't be restoring the clip
 */
void OpenGLRenderer::setupMergedMultiDraw(const Rect* clipRect) {
    if (clipRect != nullptr) {
        writableSnapshot()->setClip(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
    } else {
        writableSnapshot()->setClip(0, 0, mState.getWidth(), mState.getHeight());
    }
    dirtyClip();
    bool enableScissor = (clipRect != nullptr) || mScissorOptimizationDisabled;
    mRenderState.scissor().setEnabled(enableScissor);
}

///////////////////////////////////////////////////////////////////////////////
// Clipping
///////////////////////////////////////////////////////////////////////////////

void OpenGLRenderer::setScissorFromClip() {
    Rect clip(mState.currentRenderTargetClip());
    clip.snapToPixelBoundaries();

    if (mRenderState.scissor().set(clip.left, getViewportHeight() - clip.bottom,
            clip.getWidth(), clip.getHeight())) {
        mState.setDirtyClip(false);
    }
}

void OpenGLRenderer::ensureStencilBuffer() {
    // Thanks to the mismatch between EGL and OpenGL ES FBO we
    // cannot attach a stencil buffer to fbo0 dynamically. Let's
    // just hope we have one when hasLayer() returns false.
    if (hasLayer()) {
        attachStencilBufferToLayer(currentSnapshot()->layer);
    }
}

void OpenGLRenderer::attachStencilBufferToLayer(Layer* layer) {
    // The layer's FBO is already bound when we reach this stage
    if (!layer->getStencilRenderBuffer()) {
        RenderBuffer* buffer = mCaches.renderBufferCache.get(
                Stencil::getLayerStencilFormat(),
                layer->getWidth(), layer->getHeight());
        layer->setStencilRenderBuffer(buffer);
    }
}

static void handlePoint(std::vector<Vertex>& rectangleVertices, const Matrix4& transform,
        float x, float y) {
    Vertex v;
    v.x = x;
    v.y = y;
    transform.mapPoint(v.x, v.y);
    rectangleVertices.push_back(v);
}

static void handlePointNoTransform(std::vector<Vertex>& rectangleVertices, float x, float y) {
    Vertex v;
    v.x = x;
    v.y = y;
    rectangleVertices.push_back(v);
}

void OpenGLRenderer::drawRectangleList(const RectangleList& rectangleList) {
    int quadCount = rectangleList.getTransformedRectanglesCount();
    std::vector<Vertex> rectangleVertices(quadCount * 4);
    Rect scissorBox = rectangleList.calculateBounds();
    scissorBox.snapToPixelBoundaries();
    for (int i = 0; i < quadCount; ++i) {
        const TransformedRectangle& tr(rectangleList.getTransformedRectangle(i));
        const Matrix4& transform = tr.getTransform();
        Rect bounds = tr.getBounds();
        if (transform.rectToRect()) {
            transform.mapRect(bounds);
            bounds.doIntersect(scissorBox);
            if (!bounds.isEmpty()) {
                handlePointNoTransform(rectangleVertices, bounds.left, bounds.top);
                handlePointNoTransform(rectangleVertices, bounds.right, bounds.top);
                handlePointNoTransform(rectangleVertices, bounds.left, bounds.bottom);
                handlePointNoTransform(rectangleVertices, bounds.right, bounds.bottom);
            }
        } else {
            handlePoint(rectangleVertices, transform, bounds.left, bounds.top);
            handlePoint(rectangleVertices, transform, bounds.right, bounds.top);
            handlePoint(rectangleVertices, transform, bounds.left, bounds.bottom);
            handlePoint(rectangleVertices, transform, bounds.right, bounds.bottom);
        }
    }

    mRenderState.scissor().set(scissorBox.left, getViewportHeight() - scissorBox.bottom,
            scissorBox.getWidth(), scissorBox.getHeight());
    const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
    Glop glop;
    Vertex* vertices = &rectangleVertices[0];
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshIndexedQuads(vertices, rectangleVertices.size() / 4)
            .setFillBlack()
            .setTransform(*currentSnapshot(), transformFlags)
            .setModelViewOffsetRect(0, 0, scissorBox)
            .build();
    renderGlop(glop);
}

void OpenGLRenderer::setStencilFromClip() {
    if (!Properties::debugOverdraw) {
        if (!currentSnapshot()->clipIsSimple()) {
            int incrementThreshold;
            EVENT_LOGD("setStencilFromClip - enabling");

            // NOTE: The order here is important, we must set dirtyClip to false
            //       before any draw call to avoid calling back into this method
            mState.setDirtyClip(false);

            ensureStencilBuffer();

            const ClipArea& clipArea = currentSnapshot()->getClipArea();

            bool isRectangleList = clipArea.isRectangleList();
            if (isRectangleList) {
                incrementThreshold = clipArea.getRectangleList().getTransformedRectanglesCount();
            } else {
                incrementThreshold = 0;
            }

            mRenderState.stencil().enableWrite(incrementThreshold);

            // Clean and update the stencil, but first make sure we restrict drawing
            // to the region's bounds
            bool resetScissor = mRenderState.scissor().setEnabled(true);
            if (resetScissor) {
                // The scissor was not set so we now need to update it
                setScissorFromClip();
            }

            mRenderState.stencil().clear();

            // stash and disable the outline clip state, since stencil doesn't account for outline
            bool storedSkipOutlineClip = mSkipOutlineClip;
            mSkipOutlineClip = true;

            SkPaint paint;
            paint.setColor(SK_ColorBLACK);
            paint.setXfermodeMode(SkXfermode::kSrc_Mode);

            if (isRectangleList) {
                drawRectangleList(clipArea.getRectangleList());
            } else {
                // NOTE: We could use the region contour path to generate a smaller mesh
                //       Since we are using the stencil we could use the red book path
                //       drawing technique. It might increase bandwidth usage though.

                // The last parameter is important: we are not drawing in the color buffer
                // so we don't want to dirty the current layer, if any
                drawRegionRects(clipArea.getClipRegion(), paint, false);
            }
            if (resetScissor) mRenderState.scissor().setEnabled(false);
            mSkipOutlineClip = storedSkipOutlineClip;

            mRenderState.stencil().enableTest(incrementThreshold);

            // Draw the region used to generate the stencil if the appropriate debug
            // mode is enabled
            // TODO: Implement for rectangle list clip areas
            if (Properties::debugStencilClip == StencilClipDebug::ShowRegion
                    && !clipArea.isRectangleList()) {
                paint.setColor(0x7f0000ff);
                paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
                drawRegionRects(currentSnapshot()->getClipRegion(), paint);
            }
        } else {
            EVENT_LOGD("setStencilFromClip - disabling");
            mRenderState.stencil().disable();
        }
    }
}

/**
 * Returns false and sets scissor enable based upon bounds if drawing won't be clipped out.
 *
 * @param paint if not null, the bounds will be expanded to account for stroke depending on paint
 *         style, and tessellated AA ramp
 */
bool OpenGLRenderer::quickRejectSetupScissor(float left, float top, float right, float bottom,
        const SkPaint* paint) {
    bool snapOut = paint && paint->isAntiAlias();

    if (paint && paint->getStyle() != SkPaint::kFill_Style) {
        float outset = paint->getStrokeWidth() * 0.5f;
        left -= outset;
        top -= outset;
        right += outset;
        bottom += outset;
    }

    bool clipRequired = false;
    bool roundRectClipRequired = false;
    if (mState.calculateQuickRejectForScissor(left, top, right, bottom,
            &clipRequired, &roundRectClipRequired, snapOut)) {
        return true;
    }

    // not quick rejected, so enable the scissor if clipRequired
    mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
    mSkipOutlineClip = !roundRectClipRequired;
    return false;
}

void OpenGLRenderer::debugClip() {
#if DEBUG_CLIP_REGIONS
    if (!currentSnapshot()->clipRegion->isEmpty()) {
        SkPaint paint;
        paint.setColor(0x7f00ff00);
        drawRegionRects(*(currentSnapshot()->clipRegion, paint);

    }
#endif
}

void OpenGLRenderer::renderGlop(const Glop& glop, GlopRenderType type) {
    // TODO: It would be best if we could do this before quickRejectSetupScissor()
    //       changes the scissor test state
    if (type != GlopRenderType::LayerClear) {
        // Regular draws need to clear the dirty area on the layer before they start drawing on top
        // of it. If this draw *is* a layer clear, it skips the clear step (since it would
        // infinitely recurse)
        clearLayerRegions();
    }

    if (mState.getDirtyClip()) {
        if (mRenderState.scissor().isEnabled()) {
            setScissorFromClip();
        }

        setStencilFromClip();
    }
    mRenderState.render(glop, currentSnapshot()->getOrthoMatrix());
    if (type == GlopRenderType::Standard && !mRenderState.stencil().isWriteEnabled()) {
        // TODO: specify more clearly when a draw should dirty the layer.
        // is writing to the stencil the only time we should ignore this?
        dirtyLayer(glop.bounds.left, glop.bounds.top, glop.bounds.right, glop.bounds.bottom);
        mDirty = true;
    }
}

///////////////////////////////////////////////////////////////////////////////
// Drawing
///////////////////////////////////////////////////////////////////////////////

void OpenGLRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t replayFlags) {
    // All the usual checks and setup operations (quickReject, setupDraw, etc.)
    // will be performed by the display list itself
    if (renderNode && renderNode->isRenderable()) {
        // compute 3d ordering
        renderNode->computeOrdering();
        if (CC_UNLIKELY(Properties::drawDeferDisabled)) {
            startFrame();
            ReplayStateStruct replayStruct(*this, dirty, replayFlags);
            renderNode->replay(replayStruct, 0);
            return;
        }

        DeferredDisplayList deferredList(mState.currentRenderTargetClip());
        DeferStateStruct deferStruct(deferredList, *this, replayFlags);
        renderNode->defer(deferStruct, 0);

        flushLayers();
        startFrame();

        deferredList.flush(*this, dirty);
    } else {
        // Even if there is no drawing command(Ex: invisible),
        // it still needs startFrame to clear buffer and start tiling.
        startFrame();
    }
}

/**
 * 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.
 * The caller is responsible for properly dirtying the current layer.
 */
void OpenGLRenderer::drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entry,
        int bitmapCount, TextureVertex* vertices, bool pureTranslate,
        const Rect& bounds, const SkPaint* paint) {
    Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
    if (!texture) return;

    const AutoTexture autoCleanup(texture);

    // 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);

    const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
            ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
    const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshTexturedMesh(vertices, bitmapCount * 6)
            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
            .setTransform(*currentSnapshot(), transformFlags)
            .setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(bounds.getWidth(), bounds.getHeight()))
            .build();
    renderGlop(glop, GlopRenderType::Multi);
}

void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
    if (quickRejectSetupScissor(0, 0, bitmap->width(), bitmap->height())) {
        return;
    }

    mCaches.textureState().activateTexture(0);
    Texture* texture = getTexture(bitmap);
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
            ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshTexturedUnitQuad(texture->uvMapper)
            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
            .setTransform(*currentSnapshot(),  TransformFlags::None)
            .setModelViewMapUnitToRectSnap(Rect(texture->width(), texture->height()))
            .build();
    renderGlop(glop);
}

void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
        const float* vertices, const int* colors, const SkPaint* paint) {
    if (!vertices || mState.currentlyIgnored()) {
        return;
    }

    float left = FLT_MAX;
    float top = FLT_MAX;
    float right = FLT_MIN;
    float bottom = FLT_MIN;

    const uint32_t elementCount = meshWidth * meshHeight * 6;

    std::unique_ptr<ColorTextureVertex[]> mesh(new ColorTextureVertex[elementCount]);
    ColorTextureVertex* vertex = &mesh[0];

    std::unique_ptr<int[]> tempColors;
    if (!colors) {
        uint32_t colorsCount = (meshWidth + 1) * (meshHeight + 1);
        tempColors.reset(new int[colorsCount]);
        memset(tempColors.get(), 0xff, colorsCount * sizeof(int));
        colors = tempColors.get();
    }

    Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap->pixelRef());
    const UvMapper& mapper(getMapper(texture));

    for (int32_t y = 0; y < meshHeight; y++) {
        for (int32_t x = 0; x < meshWidth; x++) {
            uint32_t i = (y * (meshWidth + 1) + x) * 2;

            float u1 = float(x) / meshWidth;
            float u2 = float(x + 1) / meshWidth;
            float v1 = float(y) / meshHeight;
            float v2 = float(y + 1) / meshHeight;

            mapper.map(u1, v1, u2, v2);

            int ax = i + (meshWidth + 1) * 2;
            int ay = ax + 1;
            int bx = i;
            int by = bx + 1;
            int cx = i + 2;
            int cy = cx + 1;
            int dx = i + (meshWidth + 1) * 2 + 2;
            int dy = dx + 1;

            ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
            ColorTextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2, colors[ax / 2]);
            ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);

            ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
            ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);
            ColorTextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1, colors[cx / 2]);

            left = std::min(left, std::min(vertices[ax], std::min(vertices[bx], vertices[cx])));
            top = std::min(top, std::min(vertices[ay], std::min(vertices[by], vertices[cy])));
            right = std::max(right, std::max(vertices[ax], std::max(vertices[bx], vertices[cx])));
            bottom = std::max(bottom, std::max(vertices[ay], std::max(vertices[by], vertices[cy])));
        }
    }

    if (quickRejectSetupScissor(left, top, right, bottom)) {
        return;
    }

    if (!texture) {
        texture = mCaches.textureCache.get(bitmap);
        if (!texture) {
            return;
        }
    }
    const AutoTexture autoCleanup(texture);

    /*
     * TODO: handle alpha_8 textures correctly by applying paint color, but *not*
     * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh.
     */
    const int textureFillFlags = TextureFillFlags::None;
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshColoredTexturedMesh(mesh.get(), elementCount)
            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
            .setTransform(*currentSnapshot(),  TransformFlags::None)
            .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
            .build();
    renderGlop(glop);
}

void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, Rect src, Rect dst, const SkPaint* paint) {
    if (quickRejectSetupScissor(dst)) {
        return;
    }

    Texture* texture = getTexture(bitmap);
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    Rect uv(std::max(0.0f, src.left / texture->width()),
            std::max(0.0f, src.top / texture->height()),
            std::min(1.0f, src.right / texture->width()),
            std::min(1.0f, src.bottom / texture->height()));

    const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
            ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
    const bool tryToSnap = MathUtils::areEqual(src.getWidth(), dst.getWidth())
            && MathUtils::areEqual(src.getHeight(), dst.getHeight());
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshTexturedUvQuad(texture->uvMapper, uv)
            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
            .setTransform(*currentSnapshot(),  TransformFlags::None)
            .setModelViewMapUnitToRectOptionalSnap(tryToSnap, dst)
            .build();
    renderGlop(glop);
}

void OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh,
        AssetAtlas::Entry* entry, float left, float top, float right, float bottom,
        const SkPaint* paint) {
    if (!mesh || !mesh->verticesCount || quickRejectSetupScissor(left, top, right, bottom)) {
        return;
    }

    Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
    if (!texture) return;

    // 9 patches are built for stretching - always filter
    int textureFillFlags = TextureFillFlags::ForceFilter;
    if (bitmap->colorType() == kAlpha_8_SkColorType) {
        textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
    }
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshPatchQuads(*mesh)
            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
            .setTransform(*currentSnapshot(),  TransformFlags::None)
            .setModelViewOffsetRectSnap(left, top, Rect(right - left, bottom - top)) // TODO: get minimal bounds from patch
            .build();
    renderGlop(glop);
}

/**
 * Important note: this method is intended to draw batches of 9-patch objects and
 * will not set the scissor enable or dirty the current layer, if any.
 * The caller is responsible for properly dirtying the current layer.
 */
void OpenGLRenderer::drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* entry,
        TextureVertex* vertices, uint32_t elementCount, const SkPaint* paint) {
    mCaches.textureState().activateTexture(0);
    Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    // TODO: get correct bounds from caller
    const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
    // 9 patches are built for stretching - always filter
    int textureFillFlags = TextureFillFlags::ForceFilter;
    if (bitmap->colorType() == kAlpha_8_SkColorType) {
        textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
    }
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshTexturedIndexedQuads(vertices, elementCount)
            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
            .setTransform(*currentSnapshot(), transformFlags)
            .setModelViewOffsetRect(0, 0, Rect())
            .build();
    renderGlop(glop, GlopRenderType::Multi);
}

void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY,
        const VertexBuffer& vertexBuffer, const SkPaint* paint, int displayFlags) {
    // not missing call to quickReject/dirtyLayer, always done at a higher level
    if (!vertexBuffer.getVertexCount()) {
        // no vertices to draw
        return;
    }

    bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp;
    const int transformFlags = TransformFlags::OffsetByFudgeFactor;
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshVertexBuffer(vertexBuffer, shadowInterp)
            .setFillPaint(*paint, currentSnapshot()->alpha)
            .setTransform(*currentSnapshot(), transformFlags)
            .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
            .build();
    renderGlop(glop);
}

/**
 * Renders a convex path via tessellation. For AA paths, this function uses a similar approach to
 * that of AA lines in the drawLines() function.  We expand the convex path by a half pixel in
 * screen space in all directions. However, instead of using a fragment shader to compute the
 * translucency of the color from its position, we simply use a varying parameter to define how far
 * a given pixel is from the edge. For non-AA paths, the expansion and alpha varying are not used.
 *
 * Doesn't yet support joins, caps, or path effects.
 */
void OpenGLRenderer::drawConvexPath(const SkPath& path, const SkPaint* paint) {
    VertexBuffer vertexBuffer;
    // TODO: try clipping large paths to viewport

    PathTessellator::tessellatePath(path, paint, *currentTransform(), vertexBuffer);
    drawVertexBuffer(vertexBuffer, paint);
}

/**
 * We create tristrips for the lines much like shape stroke tessellation, using a per-vertex alpha
 * and additional geometry for defining an alpha slope perimeter.
 *
 * Using GL_LINES can be difficult because the rasterization rules for those lines produces some
 * unexpected results, and may vary between hardware devices. Previously we used a varying-base
 * in-shader alpha region, but found it to be taxing on some GPUs.
 *
 * TODO: try using a fixed input buffer for non-capped lines as in text rendering. this may reduce
 * memory transfer by removing need for degenerate vertices.
 */
void OpenGLRenderer::drawLines(const float* points, int count, const SkPaint* paint) {
    if (mState.currentlyIgnored() || count < 4) return;

    count &= ~0x3; // round down to nearest four

    VertexBuffer buffer;
    PathTessellator::tessellateLines(points, count, paint, *currentTransform(), buffer);
    const Rect& bounds = buffer.getBounds();

    if (quickRejectSetupScissor(bounds.left, bounds.top, bounds.right, bounds.bottom)) {
        return;
    }

    int displayFlags = paint->isAntiAlias() ? 0 : kVertexBuffer_Offset;
    drawVertexBuffer(buffer, paint, displayFlags);
}

void OpenGLRenderer::drawPoints(const float* points, int count, const SkPaint* paint) {
    if (mState.currentlyIgnored() || count < 2) return;

    count &= ~0x1; // round down to nearest two

    VertexBuffer buffer;
    PathTessellator::tessellatePoints(points, count, paint, *currentTransform(), buffer);

    const Rect& bounds = buffer.getBounds();
    if (quickRejectSetupScissor(bounds.left, bounds.top, bounds.right, bounds.bottom)) {
        return;
    }

    int displayFlags = paint->isAntiAlias() ? 0 : kVertexBuffer_Offset;
    drawVertexBuffer(buffer, paint, displayFlags);

    mDirty = true;
}

void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
    // No need to check against the clip, we fill the clip region
    if (mState.currentlyIgnored()) return;

    Rect clip(mState.currentRenderTargetClip());
    clip.snapToPixelBoundaries();

    SkPaint paint;
    paint.setColor(color);
    paint.setXfermodeMode(mode);

    drawColorRect(clip.left, clip.top, clip.right, clip.bottom, &paint, true);

    mDirty = true;
}

void OpenGLRenderer::drawShape(float left, float top, PathTexture* texture,
        const SkPaint* paint) {
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    const float x = left + texture->left - texture->offset;
    const float y = top + texture->top - texture->offset;

    drawPathTexture(texture, x, y, paint);

    mDirty = true;
}

void OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom,
        float rx, float ry, const SkPaint* p) {
    if (mState.currentlyIgnored()
            || quickRejectSetupScissor(left, top, right, bottom, p)
            || PaintUtils::paintWillNotDraw(*p)) {
        return;
    }

    if (p->getPathEffect() != nullptr) {
        mCaches.textureState().activateTexture(0);
        PathTexture* texture = mCaches.pathCache.getRoundRect(
                right - left, bottom - top, rx, ry, p);
        drawShape(left, top, texture, p);
    } else {
        const VertexBuffer* vertexBuffer = mCaches.tessellationCache.getRoundRect(
                *currentTransform(), *p, right - left, bottom - top, rx, ry);
        drawVertexBuffer(left, top, *vertexBuffer, p);
    }
}

void OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p) {
    if (mState.currentlyIgnored()
            || quickRejectSetupScissor(x - radius, y - radius, x + radius, y + radius, p)
            || PaintUtils::paintWillNotDraw(*p)) {
        return;
    }

    if (p->getPathEffect() != nullptr) {
        mCaches.textureState().activateTexture(0);
        PathTexture* texture = mCaches.pathCache.getCircle(radius, p);
        drawShape(x - radius, y - radius, texture, p);
        return;
    }

    SkPath path;
    if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
        path.addCircle(x, y, radius + p->getStrokeWidth() / 2);
    } else {
        path.addCircle(x, y, radius);
    }

    if (CC_UNLIKELY(currentSnapshot()->projectionPathMask != nullptr)) {
        // mask ripples with projection mask
        SkPath maskPath = *(currentSnapshot()->projectionPathMask->projectionMask);

        Matrix4 screenSpaceTransform;
        currentSnapshot()->buildScreenSpaceTransform(&screenSpaceTransform);

        Matrix4 totalTransform;
        totalTransform.loadInverse(screenSpaceTransform);
        totalTransform.multiply(currentSnapshot()->projectionPathMask->projectionMaskTransform);

        SkMatrix skTotalTransform;
        totalTransform.copyTo(skTotalTransform);
        maskPath.transform(skTotalTransform);

        // Mask the ripple path by the projection mask, now that it's
        // in local space. Note that this can create CCW paths.
        Op(path, maskPath, kIntersect_SkPathOp, &path);
    }
    drawConvexPath(path, p);
}

void OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
        const SkPaint* p) {
    if (mState.currentlyIgnored()
            || quickRejectSetupScissor(left, top, right, bottom, p)
            || PaintUtils::paintWillNotDraw(*p)) {
        return;
    }

    if (p->getPathEffect() != nullptr) {
        mCaches.textureState().activateTexture(0);
        PathTexture* texture = mCaches.pathCache.getOval(right - left, bottom - top, p);
        drawShape(left, top, texture, p);
    } else {
        SkPath path;
        SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
        if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
            rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2);
        }
        path.addOval(rect);
        drawConvexPath(path, p);
    }
}

void OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
        float startAngle, float sweepAngle, bool useCenter, const SkPaint* p) {
    if (mState.currentlyIgnored()
            || quickRejectSetupScissor(left, top, right, bottom, p)
            || PaintUtils::paintWillNotDraw(*p)) {
        return;
    }

    // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
    if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != nullptr || useCenter) {
        mCaches.textureState().activateTexture(0);
        PathTexture* texture = mCaches.pathCache.getArc(right - left, bottom - top,
                startAngle, sweepAngle, useCenter, p);
        drawShape(left, top, texture, p);
        return;
    }
    SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
    if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
        rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2);
    }

    SkPath path;
    if (useCenter) {
        path.moveTo(rect.centerX(), rect.centerY());
    }
    path.arcTo(rect, startAngle, sweepAngle, !useCenter);
    if (useCenter) {
        path.close();
    }
    drawConvexPath(path, p);
}

void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
        const SkPaint* p) {
    if (mState.currentlyIgnored()
            || quickRejectSetupScissor(left, top, right, bottom, p)
            || PaintUtils::paintWillNotDraw(*p)) {
        return;
    }

    if (p->getStyle() != SkPaint::kFill_Style) {
        // only fill style is supported by drawConvexPath, since others have to handle joins
        static_assert(SkPaintDefaults_MiterLimit == 4.0f, "Miter limit has changed");
        if (p->getPathEffect() != nullptr || p->getStrokeJoin() != SkPaint::kMiter_Join ||
                p->getStrokeMiter() != SkPaintDefaults_MiterLimit) {
            mCaches.textureState().activateTexture(0);
            PathTexture* texture =
                    mCaches.pathCache.getRect(right - left, bottom - top, p);
            drawShape(left, top, texture, p);
        } else {
            SkPath path;
            SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
            if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
                rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2);
            }
            path.addRect(rect);
            drawConvexPath(path, p);
        }
    } else {
        if (p->isAntiAlias() && !currentTransform()->isSimple()) {
            SkPath path;
            path.addRect(left, top, right, bottom);
            drawConvexPath(path, p);
        } else {
            drawColorRect(left, top, right, bottom, p);

            mDirty = true;
        }
    }
}

void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
        int count, const float* positions,
        FontRenderer& fontRenderer, int alpha, float x, float y) {
    mCaches.textureState().activateTexture(0);

    PaintUtils::TextShadow textShadow;
    if (!PaintUtils::getTextShadow(paint, &textShadow)) {
        LOG_ALWAYS_FATAL("failed to query shadow attributes");
    }

    // NOTE: The drop shadow will not perform gamma correction
    //       if shader-based correction is enabled
    mCaches.dropShadowCache.setFontRenderer(fontRenderer);
    ShadowTexture* texture = mCaches.dropShadowCache.get(
            paint, text, count, textShadow.radius, positions);
    // If the drop shadow exceeds the max texture size or couldn't be
    // allocated, skip drawing
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    const float sx = x - texture->left + textShadow.dx;
    const float sy = y - texture->top + textShadow.dy;

    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshTexturedUnitQuad(nullptr)
            .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha)
            .setTransform(*currentSnapshot(),  TransformFlags::None)
            .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width(), sy + texture->height()))
            .build();
    renderGlop(glop);
}

// TODO: remove this, once mState.currentlyIgnored captures snapshot alpha
bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
    float alpha = (PaintUtils::hasTextShadow(paint)
            ? 1.0f : paint->getAlpha()) * currentSnapshot()->alpha;
    return MathUtils::isZero(alpha)
            && PaintUtils::getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
}

bool OpenGLRenderer::findBestFontTransform(const mat4& transform, SkMatrix* outMatrix) const {
    if (CC_LIKELY(transform.isPureTranslate())) {
        outMatrix->setIdentity();
        return false;
    } else if (CC_UNLIKELY(transform.isPerspective())) {
        outMatrix->setIdentity();
        return true;
    }

    /**
     * Input is a non-perspective, scaling transform. Generate a scale-only transform,
     * with values rounded to the nearest int.
     */
    float sx, sy;
    transform.decomposeScale(sx, sy);
    outMatrix->setScale(
            roundf(std::max(1.0f, sx)),
            roundf(std::max(1.0f, sy)));
    return true;
}

int OpenGLRenderer::getSaveCount() const {
    return mState.getSaveCount();
}

int OpenGLRenderer::save(int flags) {
    return mState.save(flags);
}

void OpenGLRenderer::restore() {
    mState.restore();
}

void OpenGLRenderer::restoreToCount(int saveCount) {
    mState.restoreToCount(saveCount);
}


void OpenGLRenderer::translate(float dx, float dy, float dz) {
    mState.translate(dx, dy, dz);
}

void OpenGLRenderer::rotate(float degrees) {
    mState.rotate(degrees);
}

void OpenGLRenderer::scale(float sx, float sy) {
    mState.scale(sx, sy);
}

void OpenGLRenderer::skew(float sx, float sy) {
    mState.skew(sx, sy);
}

void OpenGLRenderer::setLocalMatrix(const Matrix4& matrix) {
    mState.setMatrix(mBaseTransform);
    mState.concatMatrix(matrix);
}

void OpenGLRenderer::setLocalMatrix(const SkMatrix& matrix) {
    mState.setMatrix(mBaseTransform);
    mState.concatMatrix(matrix);
}

void OpenGLRenderer::concatMatrix(const Matrix4& matrix) {
    mState.concatMatrix(matrix);
}

bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
    return mState.clipRect(left, top, right, bottom, op);
}

bool OpenGLRenderer::clipPath(const SkPath* path, SkRegion::Op op) {
    return mState.clipPath(path, op);
}

bool OpenGLRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
    return mState.clipRegion(region, op);
}

void OpenGLRenderer::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
    mState.setClippingOutline(allocator, outline);
}

void OpenGLRenderer::setClippingRoundRect(LinearAllocator& allocator,
        const Rect& rect, float radius, bool highPriority) {
    mState.setClippingRoundRect(allocator, rect, radius, highPriority);
}

void OpenGLRenderer::setProjectionPathMask(LinearAllocator& allocator, const SkPath* path) {
    mState.setProjectionPathMask(allocator, path);
}

void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y,
        const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
        DrawOpMode drawOpMode) {

    if (drawOpMode == DrawOpMode::kImmediate) {
        // The checks for corner-case ignorable text and quick rejection is only done for immediate
        // drawing as ops from DeferredDisplayList are already filtered for these
        if (text == nullptr || count == 0 || mState.currentlyIgnored() || canSkipText(paint) ||
                quickRejectSetupScissor(bounds)) {
            return;
        }
    }

    const float oldX = x;
    const float oldY = y;

    const mat4& transform = *currentTransform();
    const bool pureTranslate = transform.isPureTranslate();

    if (CC_LIKELY(pureTranslate)) {
        x = floorf(x + transform.getTranslateX() + 0.5f);
        y = floorf(y + transform.getTranslateY() + 0.5f);
    }

    int alpha = PaintUtils::getAlphaDirect(paint) * currentSnapshot()->alpha;
    SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(paint);

    FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();

    if (CC_UNLIKELY(PaintUtils::hasTextShadow(paint))) {
        fontRenderer.setFont(paint, SkMatrix::I());
        drawTextShadow(paint, text, count, positions, fontRenderer,
                alpha, oldX, oldY);
    }

    const bool hasActiveLayer = hasLayer();

    // We only pass a partial transform to the font renderer. That partial
    // matrix defines how glyphs are rasterized. Typically we want glyphs
    // to be rasterized at their final size on screen, which means the partial
    // matrix needs to take the scale factor into account.
    // When a partial matrix is used to transform glyphs during rasterization,
    // the mesh is generated with the inverse transform (in the case of scale,
    // the mesh is generated at 1.0 / scale for instance.) This allows us to
    // apply the full transform matrix at draw time in the vertex shader.
    // Applying the full matrix in the shader is the easiest way to handle
    // rotation and perspective and allows us to always generated quads in the
    // font renderer which greatly simplifies the code, clipping in particular.
    SkMatrix fontTransform;
    bool linearFilter = findBestFontTransform(transform, &fontTransform)
            || fabs(y - (int) y) > 0.0f
            || fabs(x - (int) x) > 0.0f;
    fontRenderer.setFont(paint, fontTransform);
    fontRenderer.setTextureFiltering(linearFilter);

    // TODO: Implement better clipping for scaled/rotated text
    const Rect* clip = !pureTranslate ? nullptr : &mState.currentRenderTargetClip();
    Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);

    bool status;
#if HWUI_NEW_OPS
    LOG_ALWAYS_FATAL("unsupported");
    TextDrawFunctor functor(nullptr, nullptr, nullptr, x, y, pureTranslate, alpha, mode, paint);
#else
    TextDrawFunctor functor(this, x, y, pureTranslate, alpha, mode, paint);
#endif

    // don't call issuedrawcommand, do it at end of batch
    bool forceFinish = (drawOpMode != DrawOpMode::kDefer);
    if (CC_UNLIKELY(paint->getTextAlign() != SkPaint::kLeft_Align)) {
        SkPaint paintCopy(*paint);
        paintCopy.setTextAlign(SkPaint::kLeft_Align);
        status = fontRenderer.renderPosText(&paintCopy, clip, text, count, x, y,
                positions, hasActiveLayer ? &layerBounds : nullptr, &functor, forceFinish);
    } else {
        status = fontRenderer.renderPosText(paint, clip, text, count, x, y,
                positions, hasActiveLayer ? &layerBounds : nullptr, &functor, forceFinish);
    }

    if ((status || drawOpMode != DrawOpMode::kImmediate) && hasActiveLayer) {
        if (!pureTranslate) {
            transform.mapRect(layerBounds);
        }
        dirtyLayerUnchecked(layerBounds, getRegion());
    }

    mDirty = true;
}

void OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
        const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) {
    if (text == nullptr || count == 0 || mState.currentlyIgnored() || canSkipText(paint)) {
        return;
    }

    // TODO: avoid scissor by calculating maximum bounds using path bounds + font metrics
    mRenderState.scissor().setEnabled(true);

    FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
    fontRenderer.setFont(paint, SkMatrix::I());
    fontRenderer.setTextureFiltering(true);

    int alpha = PaintUtils::getAlphaDirect(paint) * currentSnapshot()->alpha;
    SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(paint);
#if HWUI_NEW_OPS
    LOG_ALWAYS_FATAL("unsupported");
    TextDrawFunctor functor(nullptr, nullptr, nullptr, 0.0f, 0.0f, false, alpha, mode, paint);
#else
    TextDrawFunctor functor(this, 0.0f, 0.0f, false, alpha, mode, paint);
#endif

    const Rect* clip = &writableSnapshot()->getLocalClip();
    Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);

    if (fontRenderer.renderTextOnPath(paint, clip, text, count, path,
            hOffset, vOffset, hasLayer() ? &bounds : nullptr, &functor)) {
        dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, *currentTransform());
        mDirty = true;
    }
}

void OpenGLRenderer::drawPath(const SkPath* path, const SkPaint* paint) {
    if (mState.currentlyIgnored()) return;

    mCaches.textureState().activateTexture(0);

    PathTexture* texture = mCaches.pathCache.get(path, paint);
    if (!texture) return;

    const float x = texture->left - texture->offset;
    const float y = texture->top - texture->offset;

    drawPathTexture(texture, x, y, paint);

    if (texture->cleanup) {
        mCaches.pathCache.remove(path, paint);
    }
    mDirty = true;
}

void OpenGLRenderer::drawLayer(Layer* layer) {
    if (!layer) {
        return;
    }

    mat4* transform = nullptr;
    if (layer->isTextureLayer()) {
        transform = &layer->getTransform();
        if (!transform->isIdentity()) {
            save(SkCanvas::kMatrix_SaveFlag);
            concatMatrix(*transform);
        }
    }

    bool clipRequired = false;
    const bool rejected = mState.calculateQuickRejectForScissor(
            0, 0, layer->layer.getWidth(), layer->layer.getHeight(),
            &clipRequired, nullptr, false);

    if (rejected) {
        if (transform && !transform->isIdentity()) {
            restore();
        }
        return;
    }

    EVENT_LOGD("drawLayer," RECT_STRING ", clipRequired %d", x, y,
            x + layer->layer.getWidth(), y + layer->layer.getHeight(), clipRequired);

    updateLayer(layer, true);

    mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
    mCaches.textureState().activateTexture(0);

    if (CC_LIKELY(!layer->region.isEmpty())) {
        if (layer->region.isRect()) {
            DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
                    composeLayerRect(layer, layer->regionRect));
        } else if (layer->mesh) {
            Glop glop;
            GlopBuilder(mRenderState, mCaches, &glop)
                    .setRoundRectClipState(currentSnapshot()->roundRectClipState)
                    .setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
                    .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
                    .setTransform(*currentSnapshot(),  TransformFlags::None)
                    .setModelViewOffsetRectSnap(0, 0, Rect(layer->layer.getWidth(), layer->layer.getHeight()))
                    .build();
            DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
#if DEBUG_LAYERS_AS_REGIONS
            drawRegionRectsDebug(layer->region);
#endif
        }

        if (layer->debugDrawUpdate) {
            layer->debugDrawUpdate = false;

            SkPaint paint;
            paint.setColor(0x7f00ff00);
            drawColorRect(0, 0, layer->layer.getWidth(), layer->layer.getHeight(), &paint);
        }
    }
    layer->hasDrawnSinceUpdate = true;

    if (transform && !transform->isIdentity()) {
        restore();
    }

    mDirty = true;
}

///////////////////////////////////////////////////////////////////////////////
// Draw filters
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::setDrawFilter(SkDrawFilter* filter) {
    // We should never get here since we apply the draw filter when stashing
    // the paints in the DisplayList.
    LOG_ALWAYS_FATAL("OpenGLRenderer does not directly support DrawFilters");
}

///////////////////////////////////////////////////////////////////////////////
// Drawing implementation
///////////////////////////////////////////////////////////////////////////////

Texture* OpenGLRenderer::getTexture(const SkBitmap* bitmap) {
    Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap->pixelRef());
    if (!texture) {
        return mCaches.textureCache.get(bitmap);
    }
    return texture;
}

void OpenGLRenderer::drawPathTexture(PathTexture* texture, float x, float y,
        const SkPaint* paint) {
    if (quickRejectSetupScissor(x, y, x + texture->width(), y + texture->height())) {
        return;
    }

    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshTexturedUnitQuad(nullptr)
            .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha)
            .setTransform(*currentSnapshot(),  TransformFlags::None)
            .setModelViewMapUnitToRect(Rect(x, y, x + texture->width(), y + texture->height()))
            .build();
    renderGlop(glop);
}

void OpenGLRenderer::drawRects(const float* rects, int count, const SkPaint* paint) {
    if (mState.currentlyIgnored()) {
        return;
    }

    drawColorRects(rects, count, paint, false, true, true);
}

void OpenGLRenderer::drawShadow(float casterAlpha,
        const VertexBuffer* ambientShadowVertexBuffer, const VertexBuffer* spotShadowVertexBuffer) {
    if (mState.currentlyIgnored()) return;

    // TODO: use quickRejectWithScissor. For now, always force enable scissor.
    mRenderState.scissor().setEnabled(true);

    SkPaint paint;
    paint.setAntiAlias(true); // want to use AlphaVertex

    // The caller has made sure casterAlpha > 0.
    float ambientShadowAlpha = mAmbientShadowAlpha;
    if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) {
        ambientShadowAlpha = Properties::overrideAmbientShadowStrength;
    }
    if (ambientShadowVertexBuffer && ambientShadowAlpha > 0) {
        paint.setARGB(casterAlpha * ambientShadowAlpha, 0, 0, 0);
        drawVertexBuffer(*ambientShadowVertexBuffer, &paint, kVertexBuffer_ShadowInterp);
    }

    float spotShadowAlpha = mSpotShadowAlpha;
    if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) {
        spotShadowAlpha = Properties::overrideSpotShadowStrength;
    }
    if (spotShadowVertexBuffer && spotShadowAlpha > 0) {
        paint.setARGB(casterAlpha * spotShadowAlpha, 0, 0, 0);
        drawVertexBuffer(*spotShadowVertexBuffer, &paint, kVertexBuffer_ShadowInterp);
    }

    mDirty=true;
}

void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint* paint,
        bool ignoreTransform, bool dirty, bool clip) {
    if (count == 0) {
        return;
    }

    float left = FLT_MAX;
    float top = FLT_MAX;
    float right = FLT_MIN;
    float bottom = FLT_MIN;

    Vertex mesh[count];
    Vertex* vertex = mesh;

    for (int index = 0; index < count; index += 4) {
        float l = rects[index + 0];
        float t = rects[index + 1];
        float r = rects[index + 2];
        float b = rects[index + 3];

        Vertex::set(vertex++, l, t);
        Vertex::set(vertex++, r, t);
        Vertex::set(vertex++, l, b);
        Vertex::set(vertex++, r, b);

        left = std::min(left, l);
        top = std::min(top, t);
        right = std::max(right, r);
        bottom = std::max(bottom, b);
    }

    if (clip && quickRejectSetupScissor(left, top, right, bottom)) {
        return;
    }

    const int transformFlags = ignoreTransform
            ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshIndexedQuads(&mesh[0], count / 4)
            .setFillPaint(*paint, currentSnapshot()->alpha)
            .setTransform(*currentSnapshot(), transformFlags)
            .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
            .build();
    renderGlop(glop);
}

void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
        const SkPaint* paint, bool ignoreTransform) {
    const int transformFlags = ignoreTransform
            ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
    Glop glop;
    GlopBuilder(mRenderState, mCaches, &glop)
            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
            .setMeshUnitQuad()
            .setFillPaint(*paint, currentSnapshot()->alpha)
            .setTransform(*currentSnapshot(), transformFlags)
            .setModelViewMapUnitToRect(Rect(left, top, right, bottom))
            .build();
    renderGlop(glop);
}

float OpenGLRenderer::getLayerAlpha(const Layer* layer) const {
    return (layer->getAlpha() / 255.0f) * currentSnapshot()->alpha;
}

}; // namespace uirenderer
}; // namespace android
