/*
 * 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 "GrLayerCache.h"
#include "GrLayerHoister.h"
#include "GrRecordReplaceDraw.h"

#include "SkBigPicture.h"
#include "SkCanvas.h"
#include "SkGpuDevice.h"
#include "SkLayerInfo.h"
#include "SkRecordDraw.h"
#include "SkSpecialImage.h"
#include "SkSurface.h"
#include "SkSurface_Gpu.h"

// Create the layer information for the hoisted layer and secure the
// required texture/render target resources.
static void prepare_for_hoisting(GrLayerCache* layerCache,
                                 const SkPicture* topLevelPicture,
                                 const SkMatrix& initialMat,
                                 const SkLayerInfo::BlockInfo& info,
                                 const SkIRect& srcIR,
                                 const SkIRect& dstIR,
                                 SkTDArray<GrHoistedLayer>* needRendering,
                                 SkTDArray<GrHoistedLayer>* recycled,
                                 bool attemptToAtlas,
                                 int numSamples) {
    const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture;

    GrCachedLayer* layer = layerCache->findLayerOrCreate(topLevelPicture->uniqueID(),
                                                         SkToInt(info.fSaveLayerOpID),
                                                         SkToInt(info.fRestoreOpID),
                                                         srcIR,
                                                         dstIR,
                                                         initialMat,
                                                         info.fKey,
                                                         info.fKeySize,
                                                         info.fPaint);
    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = srcIR.width();
    desc.fHeight = srcIR.height();
    desc.fConfig = kSkia8888_GrPixelConfig;
    desc.fSampleCnt = numSamples;

    bool locked, needsRendering;
    if (attemptToAtlas) {
        locked = layerCache->tryToAtlas(layer, desc, &needsRendering);
    } else {
        locked = layerCache->lock(layer, desc, &needsRendering);
    }
    if (!locked) {
        // GPU resources could not be secured for the hoisting of this layer
        return;
    }

    if (attemptToAtlas) {
        SkASSERT(layer->isAtlased());
    }

    GrHoistedLayer* hl;

    if (needsRendering) {
        if (!attemptToAtlas) {
            SkASSERT(!layer->isAtlased());
        }
        hl = needRendering->append();
    } else {
        hl = recycled->append();
    }

    layerCache->addUse(layer);
    hl->fLayer = layer;
    hl->fPicture = pict;
    hl->fLocalMat = info.fLocalMat;
    hl->fInitialMat = initialMat;
    hl->fPreMat = initialMat;
    hl->fPreMat.preConcat(info.fPreMat);
}

// Compute the source rect and return false if it is empty.
static bool compute_source_rect(const SkLayerInfo::BlockInfo& info, const SkMatrix& initialMat,
                                const SkIRect& dstIR, SkIRect* srcIR) {
    SkIRect clipBounds = dstIR;

    SkMatrix totMat = initialMat;
    totMat.preConcat(info.fPreMat);
    totMat.preConcat(info.fLocalMat);

    if (info.fPaint && info.fPaint->getImageFilter()) {
        clipBounds = info.fPaint->getImageFilter()->filterBounds(clipBounds, totMat);
    }

    if (!info.fSrcBounds.isEmpty()) {
        SkRect r;

        totMat.mapRect(&r, info.fSrcBounds);
        r.roundOut(srcIR);

        if (!srcIR->intersect(clipBounds)) {
            return false;
        }
    } else {
        *srcIR = clipBounds;
    }

    return true;
}

// Atlased layers must be small enough to fit in the atlas, not have a
// paint with an image filter and be neither nested nor nesting.
// TODO: allow leaf nested layers to appear in the atlas.
void GrLayerHoister::FindLayersToAtlas(GrContext* context,
                                       const SkPicture* topLevelPicture,
                                       const SkMatrix& initialMat,
                                       const SkRect& query,
                                       SkTDArray<GrHoistedLayer>* atlased,
                                       SkTDArray<GrHoistedLayer>* recycled,
                                       int numSamples) {
    if (0 != numSamples) {
        // MSAA layers are currently never atlased
        return;
    }

    GrLayerCache* layerCache = context->getLayerCache();
    layerCache->processDeletedPictures();

    const SkBigPicture::AccelData* topLevelData = nullptr;
    if (const SkBigPicture* bp = topLevelPicture->asSkBigPicture()) {
        topLevelData = bp->accelData();
    }
    if (!topLevelData) {
        return;
    }

    const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
    if (0 == topLevelGPUData->numBlocks()) {
        return;
    }

    atlased->setReserve(atlased->count() + topLevelGPUData->numBlocks());

    for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
        const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);

        // TODO: ignore perspective projected layers here?
        bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested ||
                                (info.fPaint && info.fPaint->getImageFilter());

        if (disallowAtlasing) {
            continue;
        }

        SkRect layerRect;
        initialMat.mapRect(&layerRect, info.fBounds);
        if (!layerRect.intersect(query)) {
            continue;
        }

        const SkIRect dstIR = layerRect.roundOut();

        SkIRect srcIR;

        if (!compute_source_rect(info, initialMat, dstIR, &srcIR) ||
            !GrLayerCache::PlausiblyAtlasable(srcIR.width(), srcIR.height())) {
            continue;
        }

        prepare_for_hoisting(layerCache, topLevelPicture, initialMat,
                             info, srcIR, dstIR, atlased, recycled, true, 0);
    }

}

void GrLayerHoister::FindLayersToHoist(GrContext* context,
                                       const SkPicture* topLevelPicture,
                                       const SkMatrix& initialMat,
                                       const SkRect& query,
                                       SkTDArray<GrHoistedLayer>* needRendering,
                                       SkTDArray<GrHoistedLayer>* recycled,
                                       int numSamples) {
    GrLayerCache* layerCache = context->getLayerCache();

    layerCache->processDeletedPictures();

    const SkBigPicture::AccelData* topLevelData = nullptr;
    if (const SkBigPicture* bp = topLevelPicture->asSkBigPicture()) {
        topLevelData = bp->accelData();
    }
    if (!topLevelData) {
        return;
    }

    const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
    if (0 == topLevelGPUData->numBlocks()) {
        return;
    }

    // Find and prepare for hoisting all the layers that intersect the query rect
    for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
        const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
        if (info.fIsNested) {
            // Parent layers are currently hoisted while nested layers are not.
            continue;
        }

        SkRect layerRect;
        initialMat.mapRect(&layerRect, info.fBounds);
        if (!layerRect.intersect(query)) {
            continue;
        }

        const SkIRect dstIR = layerRect.roundOut();

        SkIRect srcIR;
        if (!compute_source_rect(info, initialMat, dstIR, &srcIR)) {
            continue;
        }

        prepare_for_hoisting(layerCache, topLevelPicture, initialMat, info, srcIR, dstIR,
                             needRendering, recycled, false, numSamples);
    }
}

void GrLayerHoister::DrawLayersToAtlas(GrContext* context,
                                       const SkTDArray<GrHoistedLayer>& atlased) {
    if (atlased.count() > 0) {
        // All the atlased layers are rendered into the same GrTexture
        SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
        auto surface(SkSurface::MakeRenderTargetDirect(
                                        atlased[0].fLayer->texture()->asRenderTarget(), &props));

        SkCanvas* atlasCanvas = surface->getCanvas();

        for (int i = 0; i < atlased.count(); ++i) {
            const GrCachedLayer* layer = atlased[i].fLayer;
            const SkBigPicture* pict = atlased[i].fPicture->asSkBigPicture();
            if (!pict) {
                // TODO: can we assume / assert this?
                continue;
            }
            const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop);
            SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();)

            SkASSERT(!layerPaint || !layerPaint->getImageFilter());
            SkASSERT(!layer->filter());

            atlasCanvas->save();

            // Add a rect clip to make sure the rendering doesn't
            // extend beyond the boundaries of the atlased sub-rect
            const SkRect bound = SkRect::Make(layer->rect());
            atlasCanvas->clipRect(bound);
            atlasCanvas->clear(0);

            // '-offset' maps the layer's top/left to the origin.
            // Since this layer is atlased, the top/left corner needs
            // to be offset to the correct location in the backing texture.
            SkMatrix initialCTM;
            initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
            initialCTM.preTranslate(bound.fLeft, bound.fTop);
            initialCTM.preConcat(atlased[i].fPreMat);

            atlasCanvas->setMatrix(initialCTM);
            atlasCanvas->concat(atlased[i].fLocalMat);

            pict->partialPlayback(atlasCanvas, layer->start() + 1, layer->stop(), initialCTM);
            atlasCanvas->restore();
        }

        atlasCanvas->flush();
    }
}

void GrLayerHoister::FilterLayer(GrContext* context,
                                 SkGpuDevice* device,
                                 const GrHoistedLayer& info) {
    GrCachedLayer* layer = info.fLayer;

    SkASSERT(layer->filter());

    static const int kDefaultCacheSize = 32 * 1024 * 1024;

    const SkIPoint filterOffset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop);

    SkMatrix totMat(info.fPreMat);
    totMat.preConcat(info.fLocalMat);
    totMat.postTranslate(-SkIntToScalar(filterOffset.fX), -SkIntToScalar(filterOffset.fY));

    SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop);
    const SkIRect& clipBounds = layer->rect();

    // This cache is transient, and is freed (along with all its contained
    // textures) when it goes out of scope.
    SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(kDefaultCacheSize));
    SkImageFilter::Context filterContext(totMat, clipBounds, cache);

    SkImageFilter::DeviceProxy proxy(device);

    // TODO: should the layer hoister store stand alone layers as SkSpecialImages internally?
    const SkIRect subset = SkIRect::MakeWH(layer->texture()->width(), layer->texture()->height());
    sk_sp<SkSpecialImage> img(SkSpecialImage::MakeFromGpu(&proxy, subset,
                                                          kNeedNewImageUniqueID_SpecialImage,
                                                          layer->texture(),
                                                          &device->surfaceProps()));

    SkIPoint offset = SkIPoint::Make(0, 0);
    sk_sp<SkSpecialImage> result(layer->filter()->filterImage(img.get(),
                                                              filterContext,
                                                              &offset));
    if (!result) {
        // Filtering failed. Press on with the unfiltered version.
        return;
    }

    SkASSERT(result->isTextureBacked());
    SkAutoTUnref<GrTexture> texture(result->asTextureRef(context));
    layer->setTexture(texture, result->subset(), false);
    layer->setOffset(offset);
}

void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLayer>& layers) {
    for (int i = 0; i < layers.count(); ++i) {
        GrCachedLayer* layer = layers[i].fLayer;
        const SkBigPicture* pict = layers[i].fPicture->asSkBigPicture();
        if (!pict) {
            // TODO: can we assume / assert this?
            continue;
        }
        const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop);

        // Each non-atlased layer has its own GrTexture
        SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
        auto surface(SkSurface::MakeRenderTargetDirect(
                                        layer->texture()->asRenderTarget(), &props));

        SkCanvas* layerCanvas = surface->getCanvas();

        SkASSERT(0 == layer->rect().fLeft && 0 == layer->rect().fTop);

        // Add a rect clip to make sure the rendering doesn't
        // extend beyond the boundaries of the layer
        const SkRect bound = SkRect::Make(layer->rect());
        layerCanvas->clipRect(bound);
        layerCanvas->clear(SK_ColorTRANSPARENT);

        SkMatrix initialCTM;
        initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
        initialCTM.preConcat(layers[i].fPreMat);

        layerCanvas->setMatrix(initialCTM);
        layerCanvas->concat(layers[i].fLocalMat);

        pict->partialPlayback(layerCanvas, layer->start()+1, layer->stop(), initialCTM);
        layerCanvas->flush();

        if (layer->filter()) {
            SkSurface_Gpu* gpuSurf = static_cast<SkSurface_Gpu*>(surface.get());

            FilterLayer(context, gpuSurf->getDevice(), layers[i]);
        }
    }
}

void GrLayerHoister::UnlockLayers(GrContext* context,
                                  const SkTDArray<GrHoistedLayer>& layers) {
    GrLayerCache* layerCache = context->getLayerCache();

    for (int i = 0; i < layers.count(); ++i) {
        layerCache->removeUse(layers[i].fLayer);
    }

    SkDEBUGCODE(layerCache->validate();)
}

void GrLayerHoister::Begin(GrContext* context) {
    GrLayerCache* layerCache = context->getLayerCache();

    layerCache->begin();
}

void GrLayerHoister::End(GrContext* context) {
    GrLayerCache* layerCache = context->getLayerCache();

#if !GR_CACHE_HOISTED_LAYERS

    // This code completely clears out the atlas. It is required when
    // caching is disabled so the atlas doesn't fill up and force more
    // free floating layers
    layerCache->purgeAll();
#endif

    layerCache->end();
}
