
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrAADistanceFieldPathRenderer.h"

#include "GrAtlas.h"
#include "GrContext.h"
#include "GrDrawState.h"
#include "GrSurfacePriv.h"
#include "GrSWMaskHelper.h"
#include "GrTexturePriv.h"
#include "effects/GrDistanceFieldTextureEffect.h"

#include "SkDistanceFieldGen.h"
#include "SkRTConf.h"

#define ATLAS_TEXTURE_WIDTH 1024
#define ATLAS_TEXTURE_HEIGHT 1024

#define PLOT_WIDTH  256
#define PLOT_HEIGHT 256

#define NUM_PLOTS_X   (ATLAS_TEXTURE_WIDTH / PLOT_WIDTH)
#define NUM_PLOTS_Y   (ATLAS_TEXTURE_HEIGHT / PLOT_HEIGHT)

SK_CONF_DECLARE(bool, c_DumpPathCache, "gpu.dumpPathCache", false,
                "Dump the contents of the path cache before every purge.");

////////////////////////////////////////////////////////////////////////////////
GrAADistanceFieldPathRenderer::~GrAADistanceFieldPathRenderer() {
    PathDataList::Iter iter;
    iter.init(fPathList, PathDataList::Iter::kHead_IterStart);
    PathData* pathData;
    while ((pathData = iter.get())) {
        iter.next();
        fPathList.remove(pathData);
        SkDELETE(pathData);
    }
    
    SkDELETE(fAtlas);
}

////////////////////////////////////////////////////////////////////////////////
bool GrAADistanceFieldPathRenderer::canDrawPath(const SkPath& path,
                                                const SkStrokeRec& stroke,
                                                const GrDrawTarget* target,
                                                bool antiAlias) const {
    // TODO: Support inverse fill
    // TODO: Support strokes
    if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInverseFillType()
        || SkStrokeRec::kFill_Style != stroke.getStyle()) {
        return false;
    }

    // currently don't support perspective or scaling more than 3x
    const GrDrawState& drawState = target->getDrawState();
    const SkMatrix& vm = drawState.getViewMatrix();
    if (vm.hasPerspective() || vm.getMaxScale() > 3.0f) {
        return false;
    }
    
    // only support paths smaller than 64 x 64
    const SkRect& bounds = path.getBounds();
    return bounds.width() < 64.f && bounds.height() < 64.f;
}


GrPathRenderer::StencilSupport GrAADistanceFieldPathRenderer::onGetStencilSupport(
                                                                       const SkPath&,
                                                                       const SkStrokeRec&,
                                                                       const GrDrawTarget*) const {
    return GrPathRenderer::kNoSupport_StencilSupport;
}

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

// position + texture coord
extern const GrVertexAttrib gSDFPathVertexAttribs[] = {
    { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
    { kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding }
};
static const size_t kSDFPathVASize = 2 * sizeof(SkPoint);

bool GrAADistanceFieldPathRenderer::onDrawPath(const SkPath& path,
                                               const SkStrokeRec& stroke,
                                               GrDrawTarget* target,
                                               bool antiAlias) {
    // we've already bailed on inverse filled paths, so this is safe
    if (path.isEmpty()) {
        return true;
    }

    SkASSERT(fContext);

    // check to see if path is cached
    // TODO: handle stroked vs. filled version of same path
    PathData* pathData = fPathCache.find(path.getGenerationID());
    if (NULL == pathData) {
        pathData = this->addPathToAtlas(path, stroke, antiAlias);
        if (NULL == pathData) {
            return false;
        }
    }

    // use signed distance field to render
    return this->internalDrawPath(path, pathData, target);
}

// factor used to scale the path prior to building distance field
const SkScalar kScaleFactor = 2.0f;
// padding around path bounds to allow for antialiased pixels
const SkScalar kAntiAliasPad = 1.0f;

GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathToAtlas(
                                                                        const SkPath& path,
                                                                        const SkStrokeRec& stroke,
                                                                        bool antiAlias) {

    // generate distance field and add to atlas
    if (NULL == fAtlas) {
        SkISize textureSize = SkISize::Make(ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT);
        fAtlas = SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kAlpha_8_GrPixelConfig,
                                      kNone_GrTextureFlags, textureSize,
                                      NUM_PLOTS_X, NUM_PLOTS_Y, false));
        if (NULL == fAtlas) {
            return NULL;
        }
    }
    
    const SkRect& bounds = path.getBounds();
    
    // generate bounding rect for bitmap draw
    SkRect scaledBounds = bounds;
    // scale up to improve maxification range
    scaledBounds.fLeft *= kScaleFactor;
    scaledBounds.fTop *= kScaleFactor;
    scaledBounds.fRight *= kScaleFactor;
    scaledBounds.fBottom *= kScaleFactor;
    // move the origin to an integer boundary (gives better results)
    SkScalar dx = SkScalarFraction(scaledBounds.fLeft);
    SkScalar dy = SkScalarFraction(scaledBounds.fTop);
    scaledBounds.offset(-dx, -dy);
    // get integer boundary
    SkIRect devPathBounds;
    scaledBounds.roundOut(&devPathBounds);
    // pad to allow room for antialiasing
    devPathBounds.outset(SkScalarCeilToInt(kAntiAliasPad), SkScalarCeilToInt(kAntiAliasPad));
    // move origin to upper left corner
    devPathBounds.offsetTo(0,0);
    
    // draw path to bitmap
    SkMatrix drawMatrix;
    drawMatrix.setTranslate(-bounds.left(), -bounds.top());
    drawMatrix.postScale(kScaleFactor, kScaleFactor);
    drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad);
    GrSWMaskHelper helper(fContext);
    
    if (!helper.init(devPathBounds, &drawMatrix)) {
        return NULL;
    }
    helper.draw(path, stroke, SkRegion::kReplace_Op, antiAlias, 0xFF);
    
    // generate signed distance field
    devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
    int width = devPathBounds.width();
    int height = devPathBounds.height();
    SkAutoSMalloc<1024> dfStorage(width*height*sizeof(unsigned char));
    helper.toSDF((unsigned char*) dfStorage.get());
    
    // add to atlas
    SkIPoint16  atlasLocation;
    GrPlot* plot = fAtlas->addToAtlas(&fPlotUsage, width, height, dfStorage.get(),
                                      &atlasLocation);
    
    // if atlas full
    if (NULL == plot) {
        if (this->freeUnusedPlot()) {
            plot = fAtlas->addToAtlas(&fPlotUsage, width, height, dfStorage.get(),
                                      &atlasLocation);
            if (plot) {
                goto HAS_ATLAS;
            }
        }
    
        if (c_DumpPathCache) {
#ifdef SK_DEVELOPER
            GrTexture* texture = fAtlas->getTexture();
            texture->surfacePriv().savePixels("pathcache.png");
#endif
        }
        
        // before we purge the cache, we must flush any accumulated draws
        fContext->flush();
        
        if (this->freeUnusedPlot()) {
            plot = fAtlas->addToAtlas(&fPlotUsage, width, height, dfStorage.get(),
                                      &atlasLocation);
            if (plot) {
                goto HAS_ATLAS;
            }
        }
            
        return NULL;
    }
    
HAS_ATLAS:
    // add to cache
    PathData* pathData = SkNEW(PathData);
    pathData->fGenID = path.getGenerationID();
    pathData->fPlot = plot;
    // change the scaled rect to match the size of the inset distance field
    scaledBounds.fRight = scaledBounds.fLeft +
        SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset);
    scaledBounds.fBottom = scaledBounds.fTop +
        SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset);
    // shift the origin to the correct place relative to the distance field
    // need to also restore the fractional translation
    scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dx,
                        -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dy);
    pathData->fBounds = scaledBounds;
    // origin we render from is inset from distance field edge
    atlasLocation.fX += SK_DistanceFieldInset;
    atlasLocation.fY += SK_DistanceFieldInset;
    pathData->fAtlasLocation = atlasLocation;
    
    fPathCache.add(pathData);
    fPathList.addToTail(pathData);
    
    return pathData;
}

bool GrAADistanceFieldPathRenderer::freeUnusedPlot() {
    // find an unused plot
    GrPlot* plot = fAtlas->getUnusedPlot();
    if (NULL == plot) {
        return false;
    }
    plot->resetRects();

    // remove any paths that use this plot
    PathDataList::Iter iter;
    iter.init(fPathList, PathDataList::Iter::kHead_IterStart);
    PathData* pathData;
    while ((pathData = iter.get())) {
        iter.next();
        if (plot == pathData->fPlot) {
            fPathCache.remove(pathData->fGenID);
            fPathList.remove(pathData);
            SkDELETE(pathData);
        }
    }
        
    // tell the atlas to free the plot
    GrAtlas::RemovePlot(&fPlotUsage, plot);
    
    return true;
}

bool GrAADistanceFieldPathRenderer::internalDrawPath(const SkPath& path,
                                                     const PathData* pathData,
                                                     GrDrawTarget* target) {
    
    GrTexture* texture = fAtlas->getTexture();
    GrDrawState* drawState = target->drawState();
    GrDrawState::AutoRestoreEffects are(drawState);
    
    SkASSERT(pathData->fPlot);
    GrDrawTarget::DrawToken drawToken = target->getCurrentDrawToken();
    pathData->fPlot->setDrawToken(drawToken);
    
    // make me some vertices
    drawState->setVertexAttribs<gSDFPathVertexAttribs>(SK_ARRAY_COUNT(gSDFPathVertexAttribs),
                                                       kSDFPathVASize);
    void* vertices = NULL;
    void* indices = NULL;
    bool success = target->reserveVertexAndIndexSpace(4, 6, &vertices, &indices);
    GrAlwaysAssert(success);
    
    SkScalar dx = pathData->fBounds.fLeft;
    SkScalar dy = pathData->fBounds.fTop;
    SkScalar width = pathData->fBounds.width();
    SkScalar height = pathData->fBounds.height();
    
    SkScalar invScale = 1.0f/kScaleFactor;
    dx *= invScale;
    dy *= invScale;
    width *= invScale;
    height *= invScale;
    
    SkFixed tx = SkIntToFixed(pathData->fAtlasLocation.fX);
    SkFixed ty = SkIntToFixed(pathData->fAtlasLocation.fY);
    SkFixed tw = SkScalarToFixed(pathData->fBounds.width());
    SkFixed th = SkScalarToFixed(pathData->fBounds.height());
    
    // vertex positions
    SkRect r = SkRect::MakeXYWH(dx, dy, width, height);    
    size_t vertSize = 2 * sizeof(SkPoint);
    SkPoint* positions = reinterpret_cast<SkPoint*>(vertices);
    positions->setRectFan(r.left(), r.top(), r.right(), r.bottom(), vertSize);
    
    // vertex texture coords
    intptr_t intPtr = reinterpret_cast<intptr_t>(positions);
    SkPoint* textureCoords = reinterpret_cast<SkPoint*>(intPtr + vertSize - sizeof(SkPoint));
    textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx)),
                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty)),
                              SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx + tw)),
                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + th)),
                              vertSize);
    
    uint16_t* indexPtr = reinterpret_cast<uint16_t*>(indices);
    *indexPtr++ = 0;
    *indexPtr++ = 1;
    *indexPtr++ = 2;
    *indexPtr++ = 0;
    *indexPtr++ = 2;
    *indexPtr++ = 3;
    
    // set up any flags
    uint32_t flags = 0;
    const SkMatrix& vm = drawState->getViewMatrix();
    flags |= vm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
    
    GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
    drawState->setGeometryProcessor(GrDistanceFieldNoGammaTextureEffect::Create(texture,
                                                                                params,
                                                                                flags))->unref();
    

    vm.mapRect(&r);
    target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &r);
    target->resetVertexSource();
    target->resetIndexSource();
    
    return true;
}

