/*
    Copyright 2011 Google Inc.

    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 "GrContext.h"
#include "GrTextContext.h"

#include "SkGpuDevice.h"
#include "SkGpuDeviceFactory.h"
#include "SkGrTexturePixelRef.h"

#include "SkColorFilter.h"
#include "SkDrawProcs.h"
#include "SkGlyphCache.h"
#include "SkUtils.h"

#define CACHE_LAYER_TEXTURES 1

#if 0
    extern bool (*gShouldDrawProc)();
    #define CHECK_SHOULD_DRAW(draw)                             \
        do {                                                    \
            if (gShouldDrawProc && !gShouldDrawProc()) return;  \
            this->prepareRenderTarget(draw);                    \
        } while (0)
#else
    #define CHECK_SHOULD_DRAW(draw) this->prepareRenderTarget(draw)
#endif

///////////////////////////////////////////////////////////////////////////////

SkGpuDevice::SkAutoCachedTexture::
             SkAutoCachedTexture(SkGpuDevice* device,
                                 const SkBitmap& bitmap,
                                 const GrSamplerState& sampler,
                                 GrTexture** texture) {
    GrAssert(texture);
    fTex = NULL;
    *texture = this->set(device, bitmap, sampler);
}

SkGpuDevice::SkAutoCachedTexture::SkAutoCachedTexture() {
    fTex = NULL;
}

GrTexture* SkGpuDevice::SkAutoCachedTexture::set(SkGpuDevice* device,
                                                 const SkBitmap& bitmap,
                                                 const GrSamplerState& sampler) {
    if (fTex) {
        fDevice->unlockCachedTexture(fTex);
    }
    fDevice = device;
    GrTexture* texture = (GrTexture*)bitmap.getTexture();
    if (texture) {
        // return the native texture
        fTex = NULL;
    } else {
        // look it up in our cache
        fTex = device->lockCachedTexture(bitmap, sampler, &texture, false);
    }
    return texture;
}

SkGpuDevice::SkAutoCachedTexture::~SkAutoCachedTexture() {
    if (fTex) {
        fDevice->unlockCachedTexture(fTex);
    }
}

///////////////////////////////////////////////////////////////////////////////

bool gDoTraceDraw;

struct GrSkDrawProcs : public SkDrawProcs {
public:
    GrContext* fContext;
    GrTextContext* fTextContext;
    GrFontScaler* fFontScaler;  // cached in the skia glyphcache
};

///////////////////////////////////////////////////////////////////////////////

GrRenderTarget* SkGpuDevice::Current3DApiRenderTarget() {
    return (GrRenderTarget*) -1;
}

SkGpuDevice::SkGpuDevice(GrContext* context,
                         const SkBitmap& bitmap,
                         GrRenderTarget* renderTargetOrNull)
        : SkDevice(NULL, bitmap, (NULL == renderTargetOrNull)) {

    fNeedPrepareRenderTarget = false;
    fDrawProcs = NULL;

    fContext = context;
    fContext->ref();

    fCache = NULL;
    fTexture = NULL;
    fRenderTarget = NULL;
    fNeedClear = false;

    if (NULL == renderTargetOrNull) {
        SkBitmap::Config c = bitmap.config();
        if (c != SkBitmap::kRGB_565_Config) {
            c = SkBitmap::kARGB_8888_Config;
        }
        SkBitmap bm;
        bm.setConfig(c, this->width(), this->height());

#if CACHE_LAYER_TEXTURES

        fCache = this->lockCachedTexture(bm, GrSamplerState::ClampNoFilter(),
                       &fTexture, true);
        if (fCache) {
            SkASSERT(NULL != fTexture);
            SkASSERT(NULL != fTexture->asRenderTarget());
        }
#else
        const GrGpu::TextureDesc desc = {
            GrGpu::kRenderTarget_TextureFlag,
            GrGpu::kNone_AALevel,
            this->width(),
            this->height(),
            SkGr::Bitmap2PixelConfig(bm)
        };

        fTexture = fContext->createUncachedTexture(desc, NULL, 0);
#endif
        if (NULL != fTexture) {
            fRenderTarget = fTexture->asRenderTarget();

            GrAssert(NULL != fRenderTarget);

            // we defer the actual clear until our gainFocus()
            fNeedClear = true;

            // wrap the bitmap with a pixelref to expose our texture
            SkGrTexturePixelRef* pr = new SkGrTexturePixelRef(fTexture);
            this->setPixelRef(pr, 0)->unref();
        } else {
            GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
                     this->width(), this->height());
            GrAssert(false);
        }
    } else {
        if (Current3DApiRenderTarget() == renderTargetOrNull) {
            fRenderTarget = fContext->createRenderTargetFrom3DApiState();
        } else {
            fRenderTarget = renderTargetOrNull;
            fRenderTarget->ref();
        }
        SkGrRenderTargetPixelRef* pr = new SkGrRenderTargetPixelRef(fRenderTarget);
        this->setPixelRef(pr, 0)->unref();
    }
}

SkGpuDevice::~SkGpuDevice() {
    if (fDrawProcs) {
        delete fDrawProcs;
    }

    if (fCache) {
        GrAssert(NULL != fTexture);
        GrAssert(fRenderTarget == fTexture->asRenderTarget());
        fContext->unlockTexture((GrTextureEntry*)fCache);
    } else if (NULL != fTexture) {
        GrAssert(!CACHE_LAYER_TEXTURES);
        GrAssert(fRenderTarget == fTexture->asRenderTarget());
        fTexture->unref();
    } else if (NULL != fRenderTarget) {
        fRenderTarget->unref();
    }
    fContext->unref();
}

intptr_t SkGpuDevice::getLayerTextureHandle() const {
    if (fTexture) {
        return fTexture->getTextureHandle();
    } else {
        return 0;
    }
}

SkDeviceFactory* SkGpuDevice::onNewDeviceFactory() {
    return SkNEW_ARGS(SkGpuDeviceFactory, (fContext, fRenderTarget));
}

///////////////////////////////////////////////////////////////////////////////

void SkGpuDevice::makeRenderTargetCurrent() {
    fContext->setRenderTarget(fRenderTarget);
    fContext->flush(true);
    fNeedPrepareRenderTarget = true;
}

///////////////////////////////////////////////////////////////////////////////

bool SkGpuDevice::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
    SkIRect bounds;
    bounds.set(0, 0, this->width(), this->height());
    if (!bounds.intersect(srcRect)) {
        return false;
    }

    const int w = bounds.width();
    const int h = bounds.height();
    SkBitmap tmp;
    // note we explicitly specify our rowBytes to be snug (no gap between rows)
    tmp.setConfig(SkBitmap::kARGB_8888_Config, w, h, w * 4);
    if (!tmp.allocPixels()) {
        return false;
    }

    tmp.lockPixels();

    bool read = fContext->readRenderTargetPixels(fRenderTarget,
                                                 bounds.fLeft, bounds.fTop,
                                                 bounds.width(), bounds.height(),
                                                 kRGBA_8888_GrPixelConfig,
                                                 tmp.getPixels());
    tmp.unlockPixels();
    if (!read) {
        return false;
    }

    tmp.swap(*bitmap);
    return true;
}

void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y) {
    SkAutoLockPixels alp(bitmap);
    if (!bitmap.readyToDraw()) {
        return;
    }
    GrPixelConfig config = SkGr::BitmapConfig2PixelConfig(bitmap.config(),
                                                          bitmap.isOpaque());
    fContext->setRenderTarget(fRenderTarget);
    // we aren't setting the clip or matrix, so mark as dirty
    // we don't need to set them for this call and don't have them anyway
    fNeedPrepareRenderTarget = true;

    fContext->writePixels(x, y, bitmap.width(), bitmap.height(),
                          config, bitmap.getPixels(), bitmap.rowBytes());
}

///////////////////////////////////////////////////////////////////////////////

static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
                               const SkClipStack& clipStack,
                               const SkRegion& clipRegion,
                               const SkIPoint& origin) {
    context->setMatrix(matrix);

    SkGrClipIterator iter;
    iter.reset(clipStack);
    const SkIRect& skBounds = clipRegion.getBounds();
    GrRect bounds;
    bounds.setLTRB(GrIntToScalar(skBounds.fLeft),
                   GrIntToScalar(skBounds.fTop),
                   GrIntToScalar(skBounds.fRight),
                   GrIntToScalar(skBounds.fBottom));
    GrClip grc(&iter, GrIntToScalar(-origin.x()), GrIntToScalar(-origin.y()),
               &bounds);
    context->setClip(grc);
}

// call this ever each draw call, to ensure that the context reflects our state,
// and not the state from some other canvas/device
void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) {
    if (fNeedPrepareRenderTarget ||
        fContext->getRenderTarget() != fRenderTarget) {

        fContext->setRenderTarget(fRenderTarget);
        SkASSERT(draw.fClipStack);
        convert_matrixclip(fContext, *draw.fMatrix,
                           *draw.fClipStack, *draw.fClip, this->getOrigin());
        fNeedPrepareRenderTarget = false;
    }
}

void SkGpuDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& clip,
                                const SkClipStack& clipStack) {
    this->INHERITED::setMatrixClip(matrix, clip, clipStack);
    // We don't need to set them now because the context may not reflect this device.
    fNeedPrepareRenderTarget = true;
}

void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix,
                            const SkRegion& clip, const SkClipStack& clipStack) {

    fContext->setRenderTarget(fRenderTarget);

    this->INHERITED::gainFocus(canvas, matrix, clip, clipStack);

    convert_matrixclip(fContext, matrix, clipStack, clip, this->getOrigin());

    if (fNeedClear) {
        fContext->clear(NULL, 0x0);
        fNeedClear = false;
    }
}

bool SkGpuDevice::bindDeviceAsTexture(GrPaint* paint) {
    if (NULL != fTexture) {
        paint->setTexture(fTexture);
        return true;
    }
    return false;
}

///////////////////////////////////////////////////////////////////////////////

SK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch);
SK_COMPILE_ASSERT(SkShader::kDefault_BitmapType == 1, shader_type_mismatch);
SK_COMPILE_ASSERT(SkShader::kRadial_BitmapType == 2, shader_type_mismatch);
SK_COMPILE_ASSERT(SkShader::kSweep_BitmapType == 3, shader_type_mismatch);
SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4,
                  shader_type_mismatch);
SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 4, shader_type_mismatch);

static const GrSamplerState::SampleMode sk_bmp_type_to_sample_mode[] = {
    (GrSamplerState::SampleMode) -1,                    // kNone_BitmapType
    GrSamplerState::kNormal_SampleMode,                 // kDefault_BitmapType
    GrSamplerState::kRadial_SampleMode,                 // kRadial_BitmapType
    GrSamplerState::kSweep_SampleMode,                  // kSweep_BitmapType
    GrSamplerState::kRadial2_SampleMode,                // kTwoPointRadial_BitmapType
};

bool SkGpuDevice::skPaint2GrPaintNoShader(const SkPaint& skPaint,
                                          bool justAlpha,
                                          GrPaint* grPaint) {

    grPaint->fDither    = skPaint.isDither();
    grPaint->fAntiAlias = skPaint.isAntiAlias();

    SkXfermode::Coeff sm = SkXfermode::kOne_Coeff;
    SkXfermode::Coeff dm = SkXfermode::kISA_Coeff;

    SkXfermode* mode = skPaint.getXfermode();
    if (mode) {
        if (!mode->asCoeff(&sm, &dm)) {
            SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
#if 0
            return false;
#endif
        }
    }
    grPaint->fSrcBlendCoeff = sk_blend_to_grblend(sm);
    grPaint->fDstBlendCoeff = sk_blend_to_grblend(dm);

    if (justAlpha) {
        uint8_t alpha = skPaint.getAlpha();
        grPaint->fColor = GrColorPackRGBA(alpha, alpha, alpha, alpha);
    } else {
        grPaint->fColor = SkGr::SkColor2GrColor(skPaint.getColor());
        grPaint->setTexture(NULL);
    }
    SkColorFilter* colorFilter = skPaint.getColorFilter();
    SkColor color;
    SkXfermode::Mode filterMode;
    if (colorFilter != NULL && colorFilter->asColorMode(&color, &filterMode)) {
        grPaint->fColorFilterColor = SkGr::SkColor2GrColor(color);
        grPaint->fColorFilterXfermode = filterMode;
    } else {
        grPaint->resetColorFilter();
    }
    return true;
}

bool SkGpuDevice::skPaint2GrPaintShader(const SkPaint& skPaint,
                                        SkAutoCachedTexture* act,
                                        const SkMatrix& ctm,
                                        GrPaint* grPaint) {

    SkASSERT(NULL != act);

    SkShader* shader = skPaint.getShader();
    if (NULL == shader) {
        return this->skPaint2GrPaintNoShader(skPaint, false, grPaint);
    } else if (!this->skPaint2GrPaintNoShader(skPaint, true, grPaint)) {
        return false;
    }

    SkPaint noAlphaPaint(skPaint);
    noAlphaPaint.setAlpha(255);
    shader->setContext(this->accessBitmap(false), noAlphaPaint, ctm);

    SkBitmap bitmap;
    SkMatrix matrix;
    SkShader::TileMode tileModes[2];
    SkScalar twoPointParams[3];
    SkShader::BitmapType bmptype = shader->asABitmap(&bitmap, &matrix,
                                                     tileModes, twoPointParams);

    GrSamplerState::SampleMode sampleMode = sk_bmp_type_to_sample_mode[bmptype];
    if (-1 == sampleMode) {
        SkDebugf("shader->asABitmap() == kNone_BitmapType\n");
        return false;
    }
    grPaint->fSampler.setSampleMode(sampleMode);
    if (skPaint.isFilterBitmap()) {
        grPaint->fSampler.setFilter(GrSamplerState::kBilinear_Filter);
    } else {
        grPaint->fSampler.setFilter(GrSamplerState::kNearest_Filter);
    }
    grPaint->fSampler.setWrapX(sk_tile_mode_to_grwrap(tileModes[0]));
    grPaint->fSampler.setWrapY(sk_tile_mode_to_grwrap(tileModes[1]));
    if (GrSamplerState::kRadial2_SampleMode == sampleMode) {
        grPaint->fSampler.setRadial2Params(twoPointParams[0],
                                           twoPointParams[1],
                                           twoPointParams[2] < 0);
    }

    GrTexture* texture = act->set(this, bitmap, grPaint->fSampler);
    if (NULL == texture) {
        SkDebugf("Couldn't convert bitmap to texture.\n");
        return false;
    }
    grPaint->setTexture(texture);

    // since our texture coords will be in local space, we wack the texture
    // matrix to map them back into 0...1 before we load it
    SkMatrix localM;
    if (shader->getLocalMatrix(&localM)) {
        SkMatrix inverse;
        if (localM.invert(&inverse)) {
            matrix.preConcat(inverse);
        }
    }
    if (SkShader::kDefault_BitmapType == bmptype) {
        GrScalar sx = GrFixedToScalar(GR_Fixed1 / bitmap.width());
        GrScalar sy = GrFixedToScalar(GR_Fixed1 / bitmap.height());
        matrix.postScale(sx, sy);
    } else if (SkShader::kRadial_BitmapType == bmptype) {
        GrScalar s = GrFixedToScalar(GR_Fixed1 / bitmap.width());
        matrix.postScale(s, s);
    }
    grPaint->fSampler.setMatrix(matrix);

    return true;
}

///////////////////////////////////////////////////////////////////////////////

class SkPositionSource {
public:
    SkPositionSource(const SkPoint* points, int count)
        : fPoints(points), fCount(count) {}

    int count() const { return fCount; }

    void writeValue(int i, GrPoint* dstPosition) const {
        SkASSERT(i < fCount);
        dstPosition->fX = SkScalarToGrScalar(fPoints[i].fX);
        dstPosition->fY = SkScalarToGrScalar(fPoints[i].fY);
    }
private:
    const SkPoint*  fPoints;
    int             fCount;
};

class SkTexCoordSource {
public:
    SkTexCoordSource(const SkPoint* coords)
        : fCoords(coords) {}

    void writeValue(int i, GrPoint* dstCoord) const {
        dstCoord->fX = SkScalarToGrScalar(fCoords[i].fX);
        dstCoord->fY = SkScalarToGrScalar(fCoords[i].fY);
    }
private:
    const SkPoint*  fCoords;
};

class SkColorSource {
public:
    SkColorSource(const SkColor* colors) : fColors(colors) {}

    void writeValue(int i, GrColor* dstColor) const {
        *dstColor = SkGr::SkColor2GrColor(fColors[i]);
    }
private:
    const SkColor* fColors;
};

class SkIndexSource {
public:
    SkIndexSource(const uint16_t* indices, int count)
        : fIndices(indices), fCount(count) {
    }

    int count() const { return fCount; }

    void writeValue(int i, uint16_t* dstIndex) const {
        *dstIndex = fIndices[i];
    }

private:
    const uint16_t* fIndices;
    int             fCount;
};

///////////////////////////////////////////////////////////////////////////////

#if 0 // not currently being used so don't compile,

// can be used for positions or texture coordinates

class SkRectFanSource {
public:
    SkRectFanSource(const SkRect& rect) : fRect(rect) {}

    int count() const { return 4; }

    void writeValue(int i, GrPoint* dstPoint) const {
        SkASSERT(i < 4);
        dstPoint->fX = SkScalarToGrScalar((i % 3) ? fRect.fRight :
                                                    fRect.fLeft);
        dstPoint->fY = SkScalarToGrScalar((i < 2) ? fRect.fTop  :
                                                    fRect.fBottom);
    }
private:
    const SkRect&   fRect;
};

class SkIRectFanSource {
public:
    SkIRectFanSource(const SkIRect& rect) : fRect(rect) {}

    int count() const { return 4; }

    void writeValue(int i, GrPoint* dstPoint) const {
        SkASSERT(i < 4);
        dstPoint->fX = (i % 3) ? GrIntToScalar(fRect.fRight) :
                                 GrIntToScalar(fRect.fLeft);
        dstPoint->fY = (i < 2) ? GrIntToScalar(fRect.fTop)  :
                                 GrIntToScalar(fRect.fBottom);
    }
private:
    const SkIRect&   fRect;
};

class SkMatRectFanSource {
public:
    SkMatRectFanSource(const SkRect& rect, const SkMatrix& matrix)
        : fRect(rect), fMatrix(matrix) {}

    int count() const { return 4; }

    void writeValue(int i, GrPoint* dstPoint) const {
        SkASSERT(i < 4);

#if SK_SCALAR_IS_GR_SCALAR
        fMatrix.mapXY((i % 3) ? fRect.fRight : fRect.fLeft,
                      (i < 2) ? fRect.fTop   : fRect.fBottom,
                      (SkPoint*)dstPoint);
#else
        SkPoint dst;
        fMatrix.mapXY((i % 3) ? fRect.fRight : fRect.fLeft,
                      (i < 2) ? fRect.fTop   : fRect.fBottom,
                      &dst);
        dstPoint->fX = SkScalarToGrScalar(dst.fX);
        dstPoint->fY = SkScalarToGrScalar(dst.fY);
#endif
    }
private:
    const SkRect&   fRect;
    const SkMatrix& fMatrix;
};

#endif

///////////////////////////////////////////////////////////////////////////////

void SkGpuDevice::clear(SkColor color) {
    fContext->clear(NULL, color);
}

void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
    CHECK_SHOULD_DRAW(draw);

    GrPaint grPaint;
    SkAutoCachedTexture act;
    if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
        return;
    }

    fContext->drawPaint(grPaint);
}

// must be in SkCanvas::PointMode order
static const GrPrimitiveType gPointMode2PrimtiveType[] = {
    kPoints_PrimitiveType,
    kLines_PrimitiveType,
    kLineStrip_PrimitiveType
};

void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
                             size_t count, const SkPoint pts[], const SkPaint& paint) {
    CHECK_SHOULD_DRAW(draw);

    SkScalar width = paint.getStrokeWidth();
    if (width < 0) {
        return;
    }

    // we only handle hairlines here, else we let the SkDraw call our drawPath()
    if (width > 0) {
        draw.drawPoints(mode, count, pts, paint, true);
        return;
    }

    GrPaint grPaint;
    SkAutoCachedTexture act;
    if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
        return;
    }

#if SK_SCALAR_IS_GR_SCALAR
    fContext->drawVertices(grPaint,
                           gPointMode2PrimtiveType[mode],
                           count,
                           (GrPoint*)pts,
                           NULL,
                           NULL,
                           NULL,
                           0);
#else
    fContext->drawCustomVertices(grPaint,
                                 gPointMode2PrimtiveType[mode],
                                 SkPositionSource(pts, count));
#endif
}

///////////////////////////////////////////////////////////////////////////////

void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
                          const SkPaint& paint) {
    CHECK_SHOULD_DRAW(draw);

    bool doStroke = paint.getStyle() == SkPaint::kStroke_Style;
    SkScalar width = paint.getStrokeWidth();

    /*
        We have special code for hairline strokes, miter-strokes, and fills.
        Anything else we just call our path code.
     */
    bool usePath = doStroke && width > 0 &&
                    paint.getStrokeJoin() != SkPaint::kMiter_Join;
    // another reason we might need to call drawPath...
    if (paint.getMaskFilter()) {
        usePath = true;
    }

    if (usePath) {
        SkPath path;
        path.addRect(rect);
        this->drawPath(draw, path, paint, NULL, true);
        return;
    }

    GrPaint grPaint;
    SkAutoCachedTexture act;
    if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix,  &grPaint)) {
        return;
    }
    fContext->drawRect(grPaint, rect, doStroke ? width : -1);
}

#include "SkMaskFilter.h"
#include "SkBounder.h"

static bool drawWithMaskFilter(GrContext* context, const SkPath& path,
                               SkMaskFilter* filter, const SkMatrix& matrix,
                               const SkRegion& clip, SkBounder* bounder,
                               GrPaint* grp) {
    SkMask  srcM, dstM;

    if (!SkDraw::DrawToMask(path, &clip.getBounds(), filter, &matrix, &srcM,
                            SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
        return false;
    }

    SkAutoMaskImage autoSrc(&srcM, false);

    if (!filter->filterMask(&dstM, srcM, matrix, NULL)) {
        return false;
    }
    // this will free-up dstM when we're done (allocated in filterMask())
    SkAutoMaskImage autoDst(&dstM, false);

    if (clip.quickReject(dstM.fBounds)) {
        return false;
    }
    if (bounder && !bounder->doIRect(dstM.fBounds)) {
        return false;
    }

    // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
    // the current clip (and identity matrix) and grpaint settings

    GrAutoMatrix avm(context, GrMatrix::I());

    const GrTextureDesc desc = {
        kNone_GrTextureFlags,
        kNone_GrAALevel,
        dstM.fBounds.width(),
        dstM.fBounds.height(),
        kAlpha_8_GrPixelConfig
    };

    GrTexture* texture = context->createUncachedTexture(desc, dstM.fImage,
                                                        dstM.fRowBytes);
    if (NULL == texture) {
        return false;
    }

    grp->setTexture(texture);
    texture->unref();
    grp->fSampler.setClampNoFilter();

    GrRect d;
    d.setLTRB(GrIntToScalar(dstM.fBounds.fLeft),
              GrIntToScalar(dstM.fBounds.fTop),
              GrIntToScalar(dstM.fBounds.fRight),
              GrIntToScalar(dstM.fBounds.fBottom));
    GrRect s;
    s.setLTRB(0, 0, GR_Scalar1, GR_Scalar1);
    context->drawRectToRect(*grp, d, s);
    return true;
}

void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
                           const SkPaint& paint, const SkMatrix* prePathMatrix,
                           bool pathIsMutable) {
    CHECK_SHOULD_DRAW(draw);

    GrPaint grPaint;
    SkAutoCachedTexture act;
    if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
        return;
    }

    // BEGIN lift from SkDraw::drawPath()

    SkPath*         pathPtr = const_cast<SkPath*>(&origSrcPath);
    bool            doFill = true;
    SkPath          tmpPath;

    if (prePathMatrix) {
        SkPath* result = pathPtr;

        if (!pathIsMutable) {
            result = &tmpPath;
            pathIsMutable = true;
        }
        // should I push prePathMatrix on our MV stack temporarily, instead
        // of applying it here? See SkDraw.cpp
        pathPtr->transform(*prePathMatrix, result);
        pathPtr = result;
    }
    // at this point we're done with prePathMatrix
    SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)

    // This "if" is not part of the SkDraw::drawPath() lift.
    // When we get a 1.0 wide stroke we hairline stroke it instead of creating
    // a new stroked-path. This is motivated by canvas2D sites that draw
    // lines as 1.0 wide stroked paths. We can consider doing an alpha-modulated-
    // hairline for width < 1.0 when AA is enabled.
    static const int gMatrixMask = ~(SkMatrix::kIdentity_Mask | 
                                     SkMatrix::kTranslate_Mask);
    if (!paint.getPathEffect() && 
        SkPaint::kStroke_Style == paint.getStyle() &&
        !(draw.fMatrix->getType() & gMatrixMask) &&
        SK_Scalar1 == paint.getStrokeWidth()) {
        doFill = false;
    }

    if (doFill && (paint.getPathEffect() || 
                   paint.getStyle() != SkPaint::kFill_Style)) {
        doFill = paint.getFillPath(*pathPtr, &tmpPath);
        pathPtr = &tmpPath;
    }

    // END lift from SkDraw::drawPath()

    if (paint.getMaskFilter()) {
        // avoid possibly allocating a new path in transform if we can
        SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;

        // transform the path into device space
        pathPtr->transform(*draw.fMatrix, devPathPtr);

        drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
                           *draw.fMatrix, *draw.fClip, draw.fBounder, &grPaint);
        return;
    }

    GrPathFill fill = kHairLine_PathFill;

    if (doFill) {
        switch (pathPtr->getFillType()) {
            case SkPath::kWinding_FillType:
                fill = kWinding_PathFill;
                break;
            case SkPath::kEvenOdd_FillType:
                fill = kEvenOdd_PathFill;
                break;
            case SkPath::kInverseWinding_FillType:
                fill = kInverseWinding_PathFill;
                break;
            case SkPath::kInverseEvenOdd_FillType:
                fill = kInverseEvenOdd_PathFill;
                break;
            default:
                SkDebugf("Unsupported path fill type\n");
                return;
        }
    }

    SkGrPathIter iter(*pathPtr);
    fContext->drawPath(grPaint, &iter, fill);
}

void SkGpuDevice::drawBitmap(const SkDraw& draw,
                             const SkBitmap& bitmap,
                             const SkIRect* srcRectPtr,
                             const SkMatrix& m,
                             const SkPaint& paint) {
    CHECK_SHOULD_DRAW(draw);

    SkIRect srcRect;
    if (NULL == srcRectPtr) {
        srcRect.set(0, 0, bitmap.width(), bitmap.height());
    } else {
        srcRect = *srcRectPtr;
    }

    GrPaint grPaint;
    if (!this->skPaint2GrPaintNoShader(paint, true, &grPaint)) {
        return;
    }
    if (paint.isFilterBitmap()) {
        grPaint.fSampler.setFilter(GrSamplerState::kBilinear_Filter);
    } else {
        grPaint.fSampler.setFilter(GrSamplerState::kNearest_Filter);
    }
    

    const int maxTextureDim = fContext->getMaxTextureDimension();
    if (bitmap.getTexture() || (bitmap.width() <= maxTextureDim &&
                                bitmap.height() <= maxTextureDim)) {
        // take the fast case
        this->internalDrawBitmap(draw, bitmap, srcRect, m, &grPaint);
        return;
    }

    // undo the translate done by SkCanvas
    int DX = SkMax32(0, srcRect.fLeft);
    int DY = SkMax32(0, srcRect.fTop);
    // compute clip bounds in local coordinates
    SkIRect clipRect;
    {
        SkRect r;
        r.set(draw.fClip->getBounds());
        SkMatrix matrix, inverse;
        matrix.setConcat(*draw.fMatrix, m);
        if (!matrix.invert(&inverse)) {
            return;
        }
        inverse.mapRect(&r);
        r.roundOut(&clipRect);
        // apply the canvas' translate to our local clip
        clipRect.offset(DX, DY);
    }

    int nx = bitmap.width() / maxTextureDim;
    int ny = bitmap.height() / maxTextureDim;
    for (int x = 0; x <= nx; x++) {
        for (int y = 0; y <= ny; y++) {
            SkIRect tileR;
            tileR.set(x * maxTextureDim, y * maxTextureDim,
                      (x + 1) * maxTextureDim, (y + 1) * maxTextureDim);
            if (!SkIRect::Intersects(tileR, clipRect)) {
                continue;
            }

            SkIRect srcR = tileR;
            if (!srcR.intersect(srcRect)) {
                continue;
            }

            SkBitmap tmpB;
            if (bitmap.extractSubset(&tmpB, tileR)) {
                // now offset it to make it "local" to our tmp bitmap
                srcR.offset(-tileR.fLeft, -tileR.fTop);

                SkMatrix tmpM(m);
                {
                    int dx = tileR.fLeft - DX + SkMax32(0, srcR.fLeft);
                    int dy = tileR.fTop -  DY + SkMax32(0, srcR.fTop);
                    tmpM.preTranslate(SkIntToScalar(dx), SkIntToScalar(dy));
                }
                this->internalDrawBitmap(draw, tmpB, srcR, tmpM, &grPaint);
            }
        }
    }
}

/*
 *  This is called by drawBitmap(), which has to handle images that may be too
 *  large to be represented by a single texture.
 *
 *  internalDrawBitmap assumes that the specified bitmap will fit in a texture
 *  and that non-texture portion of the GrPaint has already been setup.
 */
void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
                                     const SkBitmap& bitmap,
                                     const SkIRect& srcRect,
                                     const SkMatrix& m,
                                     GrPaint* grPaint) {
    SkASSERT(bitmap.width() <= fContext->getMaxTextureDimension() &&
             bitmap.height() <= fContext->getMaxTextureDimension());

    SkAutoLockPixels alp(bitmap);
    if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
        return;
    }

    grPaint->fSampler.setWrapX(GrSamplerState::kClamp_WrapMode);
    grPaint->fSampler.setWrapY(GrSamplerState::kClamp_WrapMode);
    grPaint->fSampler.setSampleMode(GrSamplerState::kNormal_SampleMode);
    grPaint->fSampler.setMatrix(GrMatrix::I());

    GrTexture* texture;
    SkAutoCachedTexture act(this, bitmap, grPaint->fSampler, &texture);
    if (NULL == texture) {
        return;
    }

    grPaint->setTexture(texture);

    GrRect dstRect = SkRect::MakeWH(GrIntToScalar(srcRect.width()),
                                    GrIntToScalar(srcRect.height()));
    GrRect paintRect;
    paintRect.setLTRB(GrFixedToScalar((srcRect.fLeft << 16)   / bitmap.width()),
                      GrFixedToScalar((srcRect.fTop << 16)    / bitmap.height()),
                      GrFixedToScalar((srcRect.fRight << 16)  / bitmap.width()),
                      GrFixedToScalar((srcRect.fBottom << 16) / bitmap.height()));

    fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m);
}

void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
                            int left, int top, const SkPaint& paint) {
    CHECK_SHOULD_DRAW(draw);

    SkAutoLockPixels alp(bitmap);
    if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
        return;
    }

    GrPaint grPaint;
    if(!this->skPaint2GrPaintNoShader(paint, true, &grPaint)) {
        return;
    }

    GrAutoMatrix avm(fContext, GrMatrix::I());

    GrTexture* texture;
    grPaint.fSampler.setClampNoFilter();
    SkAutoCachedTexture act(this, bitmap, grPaint.fSampler, &texture);

    grPaint.setTexture(texture);

    fContext->drawRectToRect(grPaint,
                             GrRect::MakeXYWH(GrIntToScalar(left),
                                              GrIntToScalar(top),
                                              GrIntToScalar(bitmap.width()),
                                              GrIntToScalar(bitmap.height())),
                             GrRect::MakeWH(GR_Scalar1, GR_Scalar1));
}

void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* dev,
                            int x, int y, const SkPaint& paint) {
    CHECK_SHOULD_DRAW(draw);

    GrPaint grPaint;
    if (!((SkGpuDevice*)dev)->bindDeviceAsTexture(&grPaint) ||
        !this->skPaint2GrPaintNoShader(paint, true, &grPaint)) {
        return;
    }

    SkASSERT(NULL != grPaint.getTexture());

    const SkBitmap& bm = dev->accessBitmap(false);
    int w = bm.width();
    int h = bm.height();

    GrAutoMatrix avm(fContext, GrMatrix::I());

    grPaint.fSampler.setClampNoFilter();

    fContext->drawRectToRect(grPaint,
                             GrRect::MakeXYWH(GrIntToScalar(x),
                                              GrIntToScalar(y),
                                              GrIntToScalar(w),
                                              GrIntToScalar(h)),
                             GrRect::MakeWH(GR_Scalar1, GR_Scalar1));
}

///////////////////////////////////////////////////////////////////////////////

// must be in SkCanvas::VertexMode order
static const GrPrimitiveType gVertexMode2PrimitiveType[] = {
    kTriangles_PrimitiveType,
    kTriangleStrip_PrimitiveType,
    kTriangleFan_PrimitiveType,
};

void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
                              int vertexCount, const SkPoint vertices[],
                              const SkPoint texs[], const SkColor colors[],
                              SkXfermode* xmode,
                              const uint16_t indices[], int indexCount,
                              const SkPaint& paint) {
    CHECK_SHOULD_DRAW(draw);

    GrPaint grPaint;
    SkAutoCachedTexture act;
    // we ignore the shader if texs is null.
    if (NULL == texs) {
        if (!this->skPaint2GrPaintNoShader(paint, false, &grPaint)) {
            return;
        }
    } else {
        if (!this->skPaint2GrPaintShader(paint, &act,
                                         *draw.fMatrix,
                                         &grPaint)) {
            return;
        }
    }

    if (NULL != xmode && NULL != texs && NULL != colors) {
        SkXfermode::Mode mode;
        if (!SkXfermode::IsMode(xmode, &mode) ||
            SkXfermode::kMultiply_Mode != mode) {
            SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
#if 0
            return
#endif
        }
    }

#if SK_SCALAR_IS_GR_SCALAR
    // even if GrColor and SkColor byte offsets match we need
    // to perform pre-multiply.
    if (NULL == colors) {
        fContext->drawVertices(grPaint,
                               gVertexMode2PrimitiveType[vmode],
                               vertexCount,
                               (GrPoint*) vertices,
                               (GrPoint*) texs,
                               NULL,
                               indices,
                               indexCount);
    } else
#endif
    {
        SkTexCoordSource texSrc(texs);
        SkColorSource colSrc(colors);
        SkIndexSource idxSrc(indices, indexCount);

        fContext->drawCustomVertices(grPaint,
                                     gVertexMode2PrimitiveType[vmode],
                                     SkPositionSource(vertices, vertexCount),
                                     (NULL == texs) ? NULL : &texSrc,
                                     (NULL == colors) ? NULL : &colSrc,
                                     (NULL == indices) ? NULL : &idxSrc);
    }
}

///////////////////////////////////////////////////////////////////////////////

static void GlyphCacheAuxProc(void* data) {
    delete (GrFontScaler*)data;
}

static GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
    void* auxData;
    GrFontScaler* scaler = NULL;
    if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
        scaler = (GrFontScaler*)auxData;
    }
    if (NULL == scaler) {
        scaler = new SkGrFontScaler(cache);
        cache->setAuxProc(GlyphCacheAuxProc, scaler);
    }
    return scaler;
}

static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
                             SkFixed fx, SkFixed fy,
                             const SkGlyph& glyph) {
    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);

    GrSkDrawProcs* procs = (GrSkDrawProcs*)state.fDraw->fProcs;

    if (NULL == procs->fFontScaler) {
        procs->fFontScaler = get_gr_font_scaler(state.fCache);
    }

    /*
     *  Skia calls us with fx,fy already biased by 1/2. It does this to speed
     *  up rounding these, so that all of its procs (like us) can just call
     *  SkFixedFloor and get the "rounded" value.
     *
     *  We take advantage of that for fx, where we pass a rounded value, but
     *  we want the fractional fy, so we have to unbias it first.
     */
    procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), fx, 0),
                                         SkIntToFixed(SkFixedFloor(fx)),
                                         fy - SK_FixedHalf,
                                         procs->fFontScaler);
}

SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {

    // deferred allocation
    if (NULL == fDrawProcs) {
        fDrawProcs = new GrSkDrawProcs;
        fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
        fDrawProcs->fContext = fContext;
    }

    // init our (and GL's) state
    fDrawProcs->fTextContext = context;
    fDrawProcs->fFontScaler = NULL;
    return fDrawProcs;
}

void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
                          size_t byteLength, SkScalar x, SkScalar y,
                          const SkPaint& paint) {
    CHECK_SHOULD_DRAW(draw);

    if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
        // this guy will just call our drawPath()
        draw.drawText((const char*)text, byteLength, x, y, paint);
    } else {
        SkDraw myDraw(draw);

        GrPaint grPaint;
        SkAutoCachedTexture act;

        if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
            return;
        }
        GrTextContext context(fContext, grPaint, draw.fExtMatrix);
        myDraw.fProcs = this->initDrawForText(&context);
        this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
    }
}

void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
                             size_t byteLength, const SkScalar pos[],
                             SkScalar constY, int scalarsPerPos,
                             const SkPaint& paint) {
    CHECK_SHOULD_DRAW(draw);

    if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
        // this guy will just call our drawPath()
        draw.drawPosText((const char*)text, byteLength, pos, constY,
                         scalarsPerPos, paint);
    } else {
        SkDraw myDraw(draw);

        GrPaint grPaint;
        SkAutoCachedTexture act;
        if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
            return;
        }

        GrTextContext context(fContext, grPaint, draw.fExtMatrix);
        myDraw.fProcs = this->initDrawForText(&context);
        this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
                                     scalarsPerPos, paint);
    }
}

void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text,
                                size_t len, const SkPath& path,
                                const SkMatrix* m, const SkPaint& paint) {
    CHECK_SHOULD_DRAW(draw);

    SkASSERT(draw.fDevice == this);
    draw.drawTextOnPath((const char*)text, len, path, m, paint);
}

///////////////////////////////////////////////////////////////////////////////

bool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
    if (!paint.isLCDRenderText()) {
        // we're cool with the paint as is
        return false;
    }

    if (paint.getShader() ||
        paint.getXfermode() || // unless its srcover
        paint.getMaskFilter() ||
        paint.getRasterizer() ||
        paint.getColorFilter() ||
        paint.getPathEffect() ||
        paint.isFakeBoldText() ||
        paint.getStyle() != SkPaint::kFill_Style) {
        // turn off lcd
        flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
        flags->fHinting = paint.getHinting();
        return true;
    }
    // we're cool with the paint as is
    return false;
}

///////////////////////////////////////////////////////////////////////////////

SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
                                                      const GrSamplerState& sampler,
                                                      GrTexture** texture,
                                                      bool forDeviceRenderTarget) {
    GrTexture* newTexture = NULL;
    GrTextureEntry* entry = NULL;
    GrContext* ctx = this->context();

    if (forDeviceRenderTarget) {
        const GrTextureDesc desc = {
            kRenderTarget_GrTextureFlagBit,
            kNone_GrAALevel,
            bitmap.width(),
            bitmap.height(),
            SkGr::Bitmap2PixelConfig(bitmap)
        };
        entry = ctx->lockKeylessTexture(desc);
    } else {
        uint32_t p0, p1;
        p0 = bitmap.getGenerationID();
        p1 = bitmap.pixelRefOffset();

        GrTextureKey key(p0, p1, bitmap.width(), bitmap.height());
        entry = ctx->findAndLockTexture(&key, sampler);

        if (NULL == entry) {
            entry = sk_gr_create_bitmap_texture(ctx, &key, sampler, bitmap);
            if (NULL == entry) {
                GrPrintf("---- failed to create texture for cache [%d %d]\n",
                         bitmap.width(), bitmap.height());
            }
        }
    }

    if (NULL != entry) {
        newTexture = entry->texture();
        if (texture) {
            *texture = newTexture;
        }
    }
    return (TexCache*)entry;
}

void SkGpuDevice::unlockCachedTexture(TexCache* cache) {
    this->context()->unlockTexture((GrTextureEntry*)cache);
}

///////////////////////////////////////////////////////////////////////////////

SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context,
                                       GrRenderTarget* rootRenderTarget) {
    GrAssert(NULL != context);
    GrAssert(NULL != rootRenderTarget);

    // check this now rather than passing this value to SkGpuDevice cons.
    // we want the rt that is bound *now* in the 3D API, not the one
    // at the time of newDevice.
    if (SkGpuDevice::Current3DApiRenderTarget() == rootRenderTarget) {
        fRootRenderTarget = context->createRenderTargetFrom3DApiState();
    } else {
        fRootRenderTarget = rootRenderTarget;
        rootRenderTarget->ref();
    }

    fContext = context;
    context->ref();

    fRootTexture = NULL;
}

SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, GrTexture* rootRenderTargetTexture) {
    GrAssert(NULL != context);
    GrAssert(NULL != rootRenderTargetTexture);
    GrAssert(NULL != rootRenderTargetTexture->asRenderTarget());

    fRootTexture = rootRenderTargetTexture;
    rootRenderTargetTexture->ref();

    fRootRenderTarget = rootRenderTargetTexture->asRenderTarget();
    fRootRenderTarget->ref();

    fContext = context;
    context->ref();
}

SkGpuDeviceFactory::~SkGpuDeviceFactory() {
    fContext->unref();
    fRootRenderTarget->unref();
    GrSafeUnref(fRootTexture);
}

SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
                                        int width, int height,
                                        bool isOpaque, bool isLayer) {
    SkBitmap bm;
    bm.setConfig(config, width, height);
    bm.setIsOpaque(isOpaque);
    return new SkGpuDevice(fContext, bm, isLayer ?  NULL : fRootRenderTarget);
}
