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

#include "GrSWMaskHelper.h"

#include "GrCaps.h"
#include "GrDrawTarget.h"
#include "GrGpu.h"
#include "GrPipelineBuilder.h"
#include "GrStyle.h"

#include "SkData.h"
#include "SkDistanceFieldGen.h"
#include "SkStrokeRec.h"

#include "batches/GrRectBatchFactory.h"

namespace {

/*
 * Convert a boolean operation into a transfer mode code
 */
SkXfermode::Mode op_to_mode(SkRegion::Op op) {

    static const SkXfermode::Mode modeMap[] = {
        SkXfermode::kDstOut_Mode,   // kDifference_Op
        SkXfermode::kModulate_Mode, // kIntersect_Op
        SkXfermode::kSrcOver_Mode,  // kUnion_Op
        SkXfermode::kXor_Mode,      // kXOR_Op
        SkXfermode::kClear_Mode,    // kReverseDifference_Op
        SkXfermode::kSrc_Mode,      // kReplace_Op
    };

    return modeMap[op];
}

static inline GrPixelConfig fmt_to_config(SkTextureCompressor::Format fmt) {

    GrPixelConfig config;
    switch (fmt) {
        case SkTextureCompressor::kLATC_Format:
            config = kLATC_GrPixelConfig;
            break;

        case SkTextureCompressor::kR11_EAC_Format:
            config = kR11_EAC_GrPixelConfig;
            break;

        case SkTextureCompressor::kASTC_12x12_Format:
            config = kASTC_12x12_GrPixelConfig;
            break;

        case SkTextureCompressor::kETC1_Format:
            config = kETC1_GrPixelConfig;
            break;

        default:
            SkDEBUGFAIL("No GrPixelConfig for compression format!");
            // Best guess
            config = kAlpha_8_GrPixelConfig;
            break;
    }

    return config;
}

static bool choose_compressed_fmt(const GrCaps* caps,
                                  SkTextureCompressor::Format *fmt) {
    if (nullptr == fmt) {
        return false;
    }

    // We can't use scratch textures without the ability to update
    // compressed textures...
    if (!(caps->compressedTexSubImageSupport())) {
        return false;
    }

    // Figure out what our preferred texture type is. If ASTC is available, that always
    // gives the biggest win. Otherwise, in terms of compression speed and accuracy,
    // LATC has a slight edge over R11 EAC.
    if (caps->isConfigTexturable(kASTC_12x12_GrPixelConfig)) {
        *fmt = SkTextureCompressor::kASTC_12x12_Format;
        return true;
    } else if (caps->isConfigTexturable(kLATC_GrPixelConfig)) {
        *fmt = SkTextureCompressor::kLATC_Format;
        return true;
    } else if (caps->isConfigTexturable(kR11_EAC_GrPixelConfig)) {
        *fmt = SkTextureCompressor::kR11_EAC_Format;
        return true;
    }

    return false;
}

}

/**
 * Draw a single rect element of the clip stack into the accumulation bitmap
 */
void GrSWMaskHelper::draw(const SkRect& rect, SkRegion::Op op,
                          bool antiAlias, uint8_t alpha) {
    SkPaint paint;

    SkASSERT(kNone_CompressionMode == fCompressionMode);

    paint.setXfermode(SkXfermode::Make(op_to_mode(op)));
    paint.setAntiAlias(antiAlias);
    paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));

    fDraw.drawRect(rect, paint);
}

/**
 * Draw a single path element of the clip stack into the accumulation bitmap
 */
void GrSWMaskHelper::draw(const SkPath& path, const GrStyle& style, SkRegion::Op op,
                          bool antiAlias, uint8_t alpha) {
    SkPaint paint;
    paint.setPathEffect(sk_ref_sp(style.pathEffect()));
    style.strokeRec().applyToPaint(&paint);
    paint.setAntiAlias(antiAlias);

    SkTBlitterAllocator allocator;
    SkBlitter* blitter = nullptr;
    if (kBlitter_CompressionMode == fCompressionMode) {
        SkASSERT(fCompressedBuffer.get());
        blitter = SkTextureCompressor::CreateBlitterForFormat(
            fPixels.width(), fPixels.height(), fCompressedBuffer.get(), &allocator,
                                                              fCompressedFormat);
    }

    if (SkRegion::kReplace_Op == op && 0xFF == alpha) {
        SkASSERT(0xFF == paint.getAlpha());
        fDraw.drawPathCoverage(path, paint, blitter);
    } else {
        paint.setXfermodeMode(op_to_mode(op));
        paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
        fDraw.drawPath(path, paint, blitter);
    }
}

bool GrSWMaskHelper::init(const SkIRect& resultBounds,
                          const SkMatrix* matrix,
                          bool allowCompression) {
    if (matrix) {
        fMatrix = *matrix;
    } else {
        fMatrix.setIdentity();
    }

    // Now translate so the bound's UL corner is at the origin
    fMatrix.postTranslate(-resultBounds.fLeft * SK_Scalar1,
                          -resultBounds.fTop * SK_Scalar1);
    SkIRect bounds = SkIRect::MakeWH(resultBounds.width(),
                                     resultBounds.height());

    if (allowCompression &&
        fContext->caps()->drawPathMasksToCompressedTexturesSupport() &&
        choose_compressed_fmt(fContext->caps(), &fCompressedFormat)) {
        fCompressionMode = kCompress_CompressionMode;
    }

    // Make sure that the width is a multiple of the desired block dimensions
    // to allow for specialized SIMD instructions that compress multiple blocks at a time.
    int cmpWidth = bounds.fRight;
    int cmpHeight = bounds.fBottom;
    if (kCompress_CompressionMode == fCompressionMode) {
        int dimX, dimY;
        SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY);
        cmpWidth = dimX * ((cmpWidth + (dimX - 1)) / dimX);
        cmpHeight = dimY * ((cmpHeight + (dimY - 1)) / dimY);

        // Can we create a blitter?
        if (SkTextureCompressor::ExistsBlitterForFormat(fCompressedFormat)) {
            int cmpSz = SkTextureCompressor::GetCompressedDataSize(
                fCompressedFormat, cmpWidth, cmpHeight);

            SkASSERT(cmpSz > 0);
            SkASSERT(nullptr == fCompressedBuffer.get());
            fCompressedBuffer.reset(cmpSz);
            fCompressionMode = kBlitter_CompressionMode;
        }
    }

    sk_bzero(&fDraw, sizeof(fDraw));

    // If we don't have a custom blitter, then we either need a bitmap to compress
    // from or a bitmap that we're going to use as a texture. In any case, we should
    // allocate the pixels for a bitmap
    const SkImageInfo bmImageInfo = SkImageInfo::MakeA8(cmpWidth, cmpHeight);
    if (kBlitter_CompressionMode != fCompressionMode) {
        if (!fPixels.tryAlloc(bmImageInfo)) {
            return false;
        }
        fPixels.erase(0);
    } else {
        // Otherwise, we just need to remember how big the buffer is...
        fPixels.reset(bmImageInfo);
    }
    fDraw.fDst      = fPixels;
    fRasterClip.setRect(bounds);
    fDraw.fRC       = &fRasterClip;
    fDraw.fMatrix   = &fMatrix;
    return true;
}

/**
 * Get a texture (from the texture cache) of the correct size & format.
 */
GrTexture* GrSWMaskHelper::createTexture() {
    GrSurfaceDesc desc;
    desc.fWidth = fPixels.width();
    desc.fHeight = fPixels.height();
    desc.fConfig = kAlpha_8_GrPixelConfig;

    if (kNone_CompressionMode != fCompressionMode) {

#ifdef SK_DEBUG
        int dimX, dimY;
        SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY);
        SkASSERT((desc.fWidth % dimX) == 0);
        SkASSERT((desc.fHeight % dimY) == 0);
#endif

        desc.fConfig = fmt_to_config(fCompressedFormat);
        SkASSERT(fContext->caps()->isConfigTexturable(desc.fConfig));
    }

    return fContext->textureProvider()->createApproxTexture(desc);
}

void GrSWMaskHelper::sendTextureData(GrTexture *texture, const GrSurfaceDesc& desc,
                                     const void *data, size_t rowbytes) {
    // Since we're uploading to it, and it's compressed, 'texture' shouldn't
    // have a render target.
    SkASSERT(nullptr == texture->asRenderTarget());

    texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, data, rowbytes);
}

void GrSWMaskHelper::compressTextureData(GrTexture *texture, const GrSurfaceDesc& desc) {

    SkASSERT(GrPixelConfigIsCompressed(desc.fConfig));
    SkASSERT(fmt_to_config(fCompressedFormat) == desc.fConfig);

    SkAutoDataUnref cmpData(SkTextureCompressor::CompressBitmapToFormat(fPixels,
                                                                        fCompressedFormat));
    SkASSERT(cmpData);

    this->sendTextureData(texture, desc, cmpData->data(), 0);
}

/**
 * Move the result of the software mask generation back to the gpu
 */
void GrSWMaskHelper::toTexture(GrTexture *texture) {
    GrSurfaceDesc desc;
    desc.fWidth = fPixels.width();
    desc.fHeight = fPixels.height();
    desc.fConfig = texture->config();

    // First see if we should compress this texture before uploading.
    switch (fCompressionMode) {
        case kNone_CompressionMode:
            this->sendTextureData(texture, desc, fPixels.addr(), fPixels.rowBytes());
            break;

        case kCompress_CompressionMode:
            this->compressTextureData(texture, desc);
            break;

        case kBlitter_CompressionMode:
            SkASSERT(fCompressedBuffer.get());
            this->sendTextureData(texture, desc, fCompressedBuffer.get(), 0);
            break;
    }
}

/**
 * Convert mask generation results to a signed distance field
 */
void GrSWMaskHelper::toSDF(unsigned char* sdf) {
    SkGenerateDistanceFieldFromA8Image(sdf, (const unsigned char*)fPixels.addr(),
                                       fPixels.width(), fPixels.height(), fPixels.rowBytes());
}

////////////////////////////////////////////////////////////////////////////////
/**
 * Software rasterizes path to A8 mask (possibly using the context's matrix)
 * and uploads the result to a scratch texture. Returns the resulting
 * texture on success; nullptr on failure.
 */
GrTexture* GrSWMaskHelper::DrawPathMaskToTexture(GrContext* context,
                                                 const SkPath& path,
                                                 const GrStyle& style,
                                                 const SkIRect& resultBounds,
                                                 bool antiAlias,
                                                 const SkMatrix* matrix) {
    GrSWMaskHelper helper(context);

    if (!helper.init(resultBounds, matrix)) {
        return nullptr;
    }

    helper.draw(path, style, SkRegion::kReplace_Op, antiAlias, 0xFF);

    GrTexture* texture(helper.createTexture());
    if (!texture) {
        return nullptr;
    }

    helper.toTexture(texture);

    return texture;
}

void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture,
                                              GrDrawTarget* target,
                                              GrPipelineBuilder* pipelineBuilder,
                                              const GrClip& clip,
                                              GrColor color,
                                              const SkMatrix& viewMatrix,
                                              const SkIRect& rect) {
    SkMatrix invert;
    if (!viewMatrix.invert(&invert)) {
        return;
    }
    GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps(*pipelineBuilder);

    SkRect dstRect = SkRect::MakeLTRB(SK_Scalar1 * rect.fLeft,
                                      SK_Scalar1 * rect.fTop,
                                      SK_Scalar1 * rect.fRight,
                                      SK_Scalar1 * rect.fBottom);

    // We use device coords to compute the texture coordinates. We take the device coords and apply
    // a translation so that the top-left of the device bounds maps to 0,0, and then a scaling
    // matrix to normalized coords.
    SkMatrix maskMatrix;
    maskMatrix.setIDiv(texture->width(), texture->height());
    maskMatrix.preTranslate(SkIntToScalar(-rect.fLeft), SkIntToScalar(-rect.fTop));

    pipelineBuilder->addCoverageFragmentProcessor(
                         GrSimpleTextureEffect::Create(texture,
                                                       maskMatrix,
                                                       GrTextureParams::kNone_FilterMode,
                                                       kDevice_GrCoordSet))->unref();

    SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, SkMatrix::I(),
                                                                        dstRect, nullptr, &invert));
    target->drawBatch(*pipelineBuilder, clip, batch);
}
