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

#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkImage.h"
#include "src/core/SkBitmapCache.h"
#include "src/core/SkSpecialImage.h"
#include "src/core/SkSpecialSurface.h"
#include "src/core/SkSurfacePriv.h"
#include "src/image/SkImage_Base.h"
#include <atomic>

#if SK_SUPPORT_GPU
#include "include/gpu/GrContext.h"
#include "include/private/GrRecordingContext.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrSurfaceContext.h"
#include "src/gpu/GrTextureProxy.h"
#include "src/image/SkImage_Gpu.h"
#endif

// Currently the raster imagefilters can only handle certain imageinfos. Call this to know if
// a given info is supported.
static bool valid_for_imagefilters(const SkImageInfo& info) {
    // no support for other swizzles/depths yet
    return info.colorType() == kN32_SkColorType;
}

///////////////////////////////////////////////////////////////////////////////
class SkSpecialImage_Base : public SkSpecialImage {
public:
    SkSpecialImage_Base(const SkIRect& subset, uint32_t uniqueID, const SkSurfaceProps* props)
        : INHERITED(subset, uniqueID, props) {
    }
    ~SkSpecialImage_Base() override { }

    virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;

    virtual bool onGetROPixels(SkBitmap*) const = 0;

    virtual GrRecordingContext* onGetContext() const { return nullptr; }

    virtual SkColorSpace* onGetColorSpace() const = 0;

#if SK_SUPPORT_GPU
    virtual sk_sp<GrTextureProxy> onAsTextureProxyRef(GrRecordingContext* context) const = 0;
#endif

    // This subset is relative to the backing store's coordinate frame, it has already been mapped
    // from the content rect by the non-virtual makeSubset().
    virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;

    virtual sk_sp<SkSpecialSurface> onMakeSurface(
            const SkImageFilter_Base::OutputProperties& outProps, const SkISize& size,
            SkAlphaType at, const SkSurfaceProps* = nullptr) const = 0;

    // This subset (when not null) is relative to the backing store's coordinate frame, it has
    // already been mapped from the content rect by the non-virtual asImage().
    virtual sk_sp<SkImage> onAsImage(const SkIRect* subset) const = 0;

    virtual sk_sp<SkSurface> onMakeTightSurface(
            const SkImageFilter_Base::OutputProperties& outProps,
            const SkISize& size, SkAlphaType at) const = 0;

private:
    typedef SkSpecialImage INHERITED;
};

///////////////////////////////////////////////////////////////////////////////
static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) {
    return static_cast<const SkSpecialImage_Base*>(image);
}

SkSpecialImage::SkSpecialImage(const SkIRect& subset,
                               uint32_t uniqueID,
                               const SkSurfaceProps* props)
    : fProps(SkSurfacePropsCopyOrDefault(props))
    , fSubset(subset)
    , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID) {
}

sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrRecordingContext* context) {
#if SK_SUPPORT_GPU
    if (!context) {
        return nullptr;
    }
    if (GrRecordingContext* curContext = as_SIB(this)->onGetContext()) {
        return curContext->priv().matches(context) ? sk_sp<SkSpecialImage>(SkRef(this)) : nullptr;
    }

    auto proxyProvider = context->priv().proxyProvider();
    SkBitmap bmp;
    // At this point, we are definitely not texture-backed, so we must be raster or generator
    // backed. If we remove the special-wrapping-an-image subclass, we may be able to assert that
    // we are strictly raster-backed (i.e. generator images become raster when they are specialized)
    // in which case getROPixels could turn into peekPixels...
    if (!this->getROPixels(&bmp)) {
        return nullptr;
    }

    if (bmp.empty()) {
        return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props());
    }

    // TODO: this is a tight copy of 'bmp' but it doesn't have to be (given SkSpecialImage's
    // semantics). Since this is cached though we would have to bake the fit into the cache key.
    sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(proxyProvider, bmp);
    if (!proxy) {
        return nullptr;
    }

    const SkIRect rect = SkIRect::MakeWH(proxy->width(), proxy->height());

    // GrMakeCachedBitmapProxy has uploaded only the specified subset of 'bmp' so we need not
    // bother with SkBitmap::getSubset
    return SkSpecialImage::MakeDeferredFromGpu(context,
                                               rect,
                                               this->uniqueID(),
                                               std::move(proxy),
                                               sk_ref_sp(this->getColorSpace()),
                                               &this->props(),
                                               this->alphaType());
#else
    return nullptr;
#endif
}

void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
    return as_SIB(this)->onDraw(canvas, x, y, paint);
}

bool SkSpecialImage::getROPixels(SkBitmap* bm) const {
    return as_SIB(this)->onGetROPixels(bm);
}

bool SkSpecialImage::isTextureBacked() const {
    return SkToBool(as_SIB(this)->onGetContext());
}

GrRecordingContext* SkSpecialImage::getContext() const {
    return as_SIB(this)->onGetContext();
}

SkColorSpace* SkSpecialImage::getColorSpace() const {
    return as_SIB(this)->onGetColorSpace();
}

#if SK_SUPPORT_GPU
sk_sp<GrTextureProxy> SkSpecialImage::asTextureProxyRef(GrRecordingContext* context) const {
    return as_SIB(this)->onAsTextureProxyRef(context);
}
#endif

sk_sp<SkSpecialSurface> SkSpecialImage::makeSurface(
        const SkImageFilter_Base::OutputProperties& outProps, const SkISize& size,
        SkAlphaType at, const SkSurfaceProps* props) const {
    return as_SIB(this)->onMakeSurface(outProps, size, at, props);
}

sk_sp<SkSurface> SkSpecialImage::makeTightSurface(
        const SkImageFilter_Base::OutputProperties& outProps, const SkISize& size,
        SkAlphaType at) const {
    return as_SIB(this)->onMakeTightSurface(outProps, size, at);
}

sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
    SkIRect absolute = subset.makeOffset(this->subset().x(), this->subset().y());
    return as_SIB(this)->onMakeSubset(absolute);
}

sk_sp<SkImage> SkSpecialImage::asImage(const SkIRect* subset) const {
    if (subset) {
        SkIRect absolute = subset->makeOffset(this->subset().x(), this->subset().y());
        return as_SIB(this)->onAsImage(&absolute);
    } else {
        return as_SIB(this)->onAsImage(nullptr);
    }
}

#if defined(SK_DEBUG) || SK_SUPPORT_GPU
static bool rect_fits(const SkIRect& rect, int width, int height) {
    if (0 == width && 0 == height) {
        SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom);
        return true;
    }

    return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight &&
           rect.fRight >= 0 && rect.fRight <= width &&
           rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom &&
           rect.fBottom >= 0 && rect.fBottom <= height;
}
#endif

sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(GrRecordingContext* context,
                                                    const SkIRect& subset,
                                                    sk_sp<SkImage> image,
                                                    const SkSurfaceProps* props) {
    SkASSERT(rect_fits(subset, image->width(), image->height()));

#if SK_SUPPORT_GPU
    if (sk_sp<GrTextureProxy> proxy = as_IB(image)->asTextureProxyRef(context)) {
        if (!as_IB(image)->context()->priv().matches(context)) {
            return nullptr;
        }

        return MakeDeferredFromGpu(context, subset, image->uniqueID(), std::move(proxy),
                                   image->refColorSpace(), props);
    } else
#endif
    {
        SkBitmap bm;
        if (as_IB(image)->getROPixels(&bm)) {
            return MakeFromRaster(subset, bm, props);
        }
    }
    return nullptr;
}

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

class SkSpecialImage_Raster : public SkSpecialImage_Base {
public:
    SkSpecialImage_Raster(const SkIRect& subset, const SkBitmap& bm, const SkSurfaceProps* props)
        : INHERITED(subset, bm.getGenerationID(), props)
        , fBitmap(bm)
    {
        SkASSERT(bm.pixelRef());
        SkASSERT(fBitmap.getPixels());
    }

    SkAlphaType alphaType() const override { return fBitmap.alphaType(); }

    size_t getSize() const override { return fBitmap.computeByteSize(); }

    void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
        SkRect dst = SkRect::MakeXYWH(x, y,
                                      this->subset().width(), this->subset().height());

        canvas->drawBitmapRect(fBitmap, this->subset(),
                               dst, paint, SkCanvas::kStrict_SrcRectConstraint);
    }

    bool onGetROPixels(SkBitmap* bm) const override {
        return fBitmap.extractSubset(bm, this->subset());
    }

    SkColorSpace* onGetColorSpace() const override {
        return fBitmap.colorSpace();
    }

#if SK_SUPPORT_GPU
    sk_sp<GrTextureProxy> onAsTextureProxyRef(GrRecordingContext* context) const override {
        if (context) {
            return GrMakeCachedBitmapProxy(context->priv().proxyProvider(), fBitmap);
        }

        return nullptr;
    }
#endif

    sk_sp<SkSpecialSurface> onMakeSurface(const SkImageFilter_Base::OutputProperties& outProps,
                                          const SkISize& size, SkAlphaType at,
                                          const SkSurfaceProps* props) const override {
        SkColorSpace* colorSpace = outProps.colorSpace();
        SkColorType colorType = kN32_SkColorType;   // TODO: find ways to allow f16
        SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType, at,
                                             sk_ref_sp(colorSpace));
        return SkSpecialSurface::MakeRaster(info, props);
    }

    sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
        // No need to extract subset, onGetROPixels handles that when needed
        return SkSpecialImage::MakeFromRaster(subset, fBitmap, &this->props());
    }

    sk_sp<SkImage> onAsImage(const SkIRect* subset) const override {
        if (subset) {
            SkBitmap subsetBM;

            if (!fBitmap.extractSubset(&subsetBM, *subset)) {
                return nullptr;
            }

            return SkImage::MakeFromBitmap(subsetBM);
        }

        return SkImage::MakeFromBitmap(fBitmap);
    }

    sk_sp<SkSurface> onMakeTightSurface(const SkImageFilter_Base::OutputProperties& outProps,
                                        const SkISize& size, SkAlphaType at) const override {
        SkColorSpace* colorSpace = outProps.colorSpace();
        SkColorType colorType = kN32_SkColorType;   // TODO: find ways to allow f16
        SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType, at,
                                             sk_ref_sp(colorSpace));
        return SkSurface::MakeRaster(info);
    }

private:
    SkBitmap fBitmap;

    typedef SkSpecialImage_Base INHERITED;
};

sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
                                                     const SkBitmap& bm,
                                                     const SkSurfaceProps* props) {
    SkASSERT(rect_fits(subset, bm.width(), bm.height()));

    if (!bm.pixelRef()) {
        return nullptr;
    }

    const SkBitmap* srcBM = &bm;
    SkBitmap tmp;
    // ImageFilters only handle N32 at the moment, so force our src to be that
    if (!valid_for_imagefilters(bm.info())) {
        if (!tmp.tryAllocPixels(bm.info().makeColorType(kN32_SkColorType)) ||
            !bm.readPixels(tmp.info(), tmp.getPixels(), tmp.rowBytes(), 0, 0))
        {
            return nullptr;
        }
        srcBM = &tmp;
    }
    return sk_make_sp<SkSpecialImage_Raster>(subset, *srcBM, props);
}

sk_sp<SkSpecialImage> SkSpecialImage::CopyFromRaster(const SkIRect& subset,
                                                     const SkBitmap& bm,
                                                     const SkSurfaceProps* props) {
    SkASSERT(rect_fits(subset, bm.width(), bm.height()));

    if (!bm.pixelRef()) {
        return nullptr;
    }

    SkBitmap tmp;
    SkImageInfo info = bm.info().makeWH(subset.width(), subset.height());
    // As in MakeFromRaster, must force src to N32 for ImageFilters
    if (!valid_for_imagefilters(bm.info())) {
        info = info.makeColorType(kN32_SkColorType);
    }
    if (!tmp.tryAllocPixels(info)) {
        return nullptr;
    }
    if (!bm.readPixels(tmp.info(), tmp.getPixels(), tmp.rowBytes(), subset.x(), subset.y())) {
        return nullptr;
    }

    // Since we're making a copy of the raster, the resulting special image is the exact size
    // of the requested subset of the original and no longer needs to be offset by subset's left
    // and top, since those were relative to the original's buffer.
    return sk_make_sp<SkSpecialImage_Raster>(
            SkIRect::MakeWH(subset.width(), subset.height()), tmp, props);
}

#if SK_SUPPORT_GPU
///////////////////////////////////////////////////////////////////////////////
static sk_sp<SkImage> wrap_proxy_in_image(GrRecordingContext* context, sk_sp<GrTextureProxy> proxy,
                                          SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
    // CONTEXT TODO: remove this use of 'backdoor' to create an SkImage
    return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context->priv().backdoor()),
                                   kNeedNewImageUniqueID, alphaType,
                                   std::move(proxy), std::move(colorSpace));
}

class SkSpecialImage_Gpu : public SkSpecialImage_Base {
public:
    SkSpecialImage_Gpu(GrRecordingContext* context, const SkIRect& subset,
                       uint32_t uniqueID, sk_sp<GrTextureProxy> proxy, SkAlphaType at,
                       sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* props)
        : INHERITED(subset, uniqueID, props)
        , fContext(context)
        , fTextureProxy(std::move(proxy))
        , fAlphaType(at)
        , fColorSpace(std::move(colorSpace))
        , fAddedRasterVersionToCache(false) {
    }

    ~SkSpecialImage_Gpu() override {
        if (fAddedRasterVersionToCache.load()) {
            SkNotifyBitmapGenIDIsStale(this->uniqueID());
        }
    }

    SkAlphaType alphaType() const override { return fAlphaType; }

    size_t getSize() const override { return fTextureProxy->gpuMemorySize(); }

    void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
        SkRect dst = SkRect::MakeXYWH(x, y,
                                      this->subset().width(), this->subset().height());

        // TODO: In this instance we know we're going to draw a sub-portion of the backing
        // texture into the canvas so it is okay to wrap it in an SkImage. This poses
        // some problems for full deferral however in that when the deferred SkImage_Gpu
        // instantiates itself it is going to have to either be okay with having a larger
        // than expected backing texture (unlikely) or the 'fit' of the SurfaceProxy needs
        // to be tightened (if it is deferred).
        sk_sp<SkImage> img =
                sk_sp<SkImage>(new SkImage_Gpu(sk_ref_sp(canvas->getGrContext()), this->uniqueID(),
                                               fAlphaType, fTextureProxy, fColorSpace));

        canvas->drawImageRect(img, this->subset(),
                              dst, paint, SkCanvas::kStrict_SrcRectConstraint);
    }

    GrRecordingContext* onGetContext() const override { return fContext; }

    sk_sp<GrTextureProxy> onAsTextureProxyRef(GrRecordingContext*) const override {
        return fTextureProxy;
    }

    bool onGetROPixels(SkBitmap* dst) const override {
        const auto desc = SkBitmapCacheDesc::Make(this->uniqueID(), this->subset());
        if (SkBitmapCache::Find(desc, dst)) {
            SkASSERT(dst->getGenerationID() == this->uniqueID());
            SkASSERT(dst->isImmutable());
            SkASSERT(dst->getPixels());
            return true;
        }

        SkPixmap pmap;
        SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
                                                this->alphaType(), fColorSpace);
        auto rec = SkBitmapCache::Alloc(desc, info, &pmap);
        if (!rec) {
            return false;
        }
        sk_sp<GrSurfaceContext> sContext = fContext->priv().makeWrappedSurfaceContext(
                fTextureProxy, GrPixelConfigToColorType(fTextureProxy->config()), this->alphaType(),
                fColorSpace);
        if (!sContext) {
            return false;
        }

        if (!sContext->readPixels(info, pmap.writable_addr(), pmap.rowBytes(),
                                  {this->subset().left(), this->subset().top()})) {
            return false;
        }

        SkBitmapCache::Add(std::move(rec), dst);
        fAddedRasterVersionToCache.store(true);
        return true;
    }

    SkColorSpace* onGetColorSpace() const override {
        return fColorSpace.get();
    }

    sk_sp<SkSpecialSurface> onMakeSurface(const SkImageFilter_Base::OutputProperties& outProps,
                                          const SkISize& size, SkAlphaType at,
                                          const SkSurfaceProps* props) const override {
        if (!fContext) {
            return nullptr;
        }

        return SkSpecialSurface::MakeRenderTarget(fContext, size.width(), size.height(),
                                                  SkColorTypeToGrColorType(outProps.colorType()),
                                                  sk_ref_sp(outProps.colorSpace()), props);
    }

    sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const override {
        return SkSpecialImage::MakeDeferredFromGpu(fContext,
                                                   subset,
                                                   this->uniqueID(),
                                                   fTextureProxy,
                                                   fColorSpace,
                                                   &this->props(),
                                                   fAlphaType);
    }

    // TODO: move all the logic here into the subset-flavor GrSurfaceProxy::copy?
    sk_sp<SkImage> onAsImage(const SkIRect* subset) const override {
        if (subset) {
            // TODO: if this becomes a bottle neck we could base this logic on what the size
            // will be when it is finally instantiated - but that is more fraught.
            if (GrProxyProvider::IsFunctionallyExact(fTextureProxy.get()) &&
                0 == subset->fLeft && 0 == subset->fTop &&
                fTextureProxy->width() == subset->width() &&
                fTextureProxy->height() == subset->height()) {
                fTextureProxy->priv().exactify(false);
                // The existing GrTexture is already tight so reuse it in the SkImage
                return wrap_proxy_in_image(fContext, fTextureProxy, fAlphaType, fColorSpace);
            }

            sk_sp<GrTextureProxy> subsetProxy(
                    GrSurfaceProxy::Copy(fContext, fTextureProxy.get(), GrMipMapped::kNo, *subset,
                                         SkBackingFit::kExact, SkBudgeted::kYes));
            if (!subsetProxy) {
                return nullptr;
            }

            SkASSERT(subsetProxy->priv().isExact());
            // MDB: this is acceptable (wrapping subsetProxy in an SkImage) bc Copy will
            // return a kExact-backed proxy
            return wrap_proxy_in_image(fContext, std::move(subsetProxy), fAlphaType, fColorSpace);
        }

        fTextureProxy->priv().exactify(true);

        return wrap_proxy_in_image(fContext, fTextureProxy, fAlphaType, fColorSpace);
    }

    sk_sp<SkSurface> onMakeTightSurface(const SkImageFilter_Base::OutputProperties& outProps,
                                        const SkISize& size, SkAlphaType at) const override {
        SkColorSpace* colorSpace = outProps.colorSpace();
        SkColorType colorType = colorSpace && colorSpace->gammaIsLinear()
            ? kRGBA_F16_SkColorType : kRGBA_8888_SkColorType;
        SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType, at,
                                             sk_ref_sp(colorSpace));
        // CONTEXT TODO: remove this use of 'backdoor' to create an SkSurface
        return SkSurface::MakeRenderTarget(fContext->priv().backdoor(), SkBudgeted::kYes, info);
    }

private:
    GrRecordingContext*       fContext;
    sk_sp<GrTextureProxy>     fTextureProxy;
    const SkAlphaType         fAlphaType;
    sk_sp<SkColorSpace>       fColorSpace;
    mutable std::atomic<bool> fAddedRasterVersionToCache;

    typedef SkSpecialImage_Base INHERITED;
};

sk_sp<SkSpecialImage> SkSpecialImage::MakeDeferredFromGpu(GrRecordingContext* context,
                                                          const SkIRect& subset,
                                                          uint32_t uniqueID,
                                                          sk_sp<GrTextureProxy> proxy,
                                                          sk_sp<SkColorSpace> colorSpace,
                                                          const SkSurfaceProps* props,
                                                          SkAlphaType at) {
    if (!context || context->priv().abandoned() || !proxy) {
        return nullptr;
    }
    SkASSERT_RELEASE(rect_fits(subset, proxy->width(), proxy->height()));
    return sk_make_sp<SkSpecialImage_Gpu>(context, subset, uniqueID, std::move(proxy), at,
                                          std::move(colorSpace), props);
}
#endif
