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

#include "gm/gm.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageGenerator.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
#include "src/image/SkImageGeneratorPriv.h"
#include "src/image/SkImage_Base.h"

#if defined(SK_GANESH)
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrExternalTextureGenerator.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/private/gpu/ganesh/GrTextureGenerator.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrSamplerState.h"
#include "src/gpu/ganesh/GrTextureProxy.h"
#include "src/gpu/ganesh/SurfaceContext.h"
#include "src/gpu/ganesh/image/GrImageUtils.h"
#include "src/gpu/ganesh/image/SkImage_Ganesh.h"
#endif

#if defined(SK_GRAPHITE)
#include "include/gpu/graphite/Surface.h"
#endif

#include <memory>
#include <utility>

class GrRecordingContext;

static void draw_something(SkCanvas* canvas, const SkRect& bounds) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setColor(SK_ColorRED);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(10);
    canvas->drawRect(bounds, paint);
    paint.setStyle(SkPaint::kFill_Style);
    paint.setColor(SK_ColorBLUE);
    canvas->drawOval(bounds, paint);
}

/*
 *  Exercise drawing pictures inside an image, showing that the image version is pixelated
 *  (correctly) when it is inside an image.
 */
class ImagePictGM : public skiagm::GM {
    sk_sp<SkPicture> fPicture;
    sk_sp<SkImage>   fImage0;
    sk_sp<SkImage>   fImage1;
public:
    ImagePictGM() {}

protected:
    SkString getName() const override { return SkString("image-picture"); }

    SkISize getISize() override { return SkISize::Make(850, 450); }

    void onOnceBeforeDraw() override {
        const SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
        SkPictureRecorder recorder;
        draw_something(recorder.beginRecording(bounds), bounds);
        fPicture = recorder.finishRecordingAsPicture();

        // extract enough just for the oval.
        const SkISize size = SkISize::Make(100, 100);
        auto srgbColorSpace = SkColorSpace::MakeSRGB();

        SkMatrix matrix;
        matrix.setTranslate(-100, -100);
        fImage0 = SkImages::DeferredFromPicture(
                fPicture, size, &matrix, nullptr, SkImages::BitDepth::kU8, srgbColorSpace);
        matrix.postTranslate(-50, -50);
        matrix.postRotate(45);
        matrix.postTranslate(50, 50);
        fImage1 = SkImages::DeferredFromPicture(
                fPicture, size, &matrix, nullptr, SkImages::BitDepth::kU8, srgbColorSpace);
    }

    void drawSet(SkCanvas* canvas) const {
        SkMatrix matrix = SkMatrix::Translate(-100, -100);
        canvas->drawPicture(fPicture, &matrix, nullptr);
        canvas->drawImage(fImage0.get(), 150, 0);
        canvas->drawImage(fImage1.get(), 300, 0);
    }

    void onDraw(SkCanvas* canvas) override {
        canvas->translate(20, 20);

        this->drawSet(canvas);

        canvas->save();
        canvas->translate(0, 130);
        canvas->scale(0.25f, 0.25f);
        this->drawSet(canvas);
        canvas->restore();

        canvas->save();
        canvas->translate(0, 200);
        canvas->scale(2, 2);
        this->drawSet(canvas);
        canvas->restore();
    }

private:
    using INHERITED = skiagm::GM;
};
DEF_GM( return new ImagePictGM; )

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

static std::unique_ptr<SkImageGenerator> make_pic_generator(SkCanvas*,
                                                            sk_sp<SkPicture> pic) {
    SkMatrix matrix;
    matrix.setTranslate(-100, -100);
    return SkImageGenerators::MakeFromPicture({100, 100},
                                              std::move(pic),
                                              &matrix,
                                              nullptr,
                                              SkImages::BitDepth::kU8,
                                              SkColorSpace::MakeSRGB());
}

class RasterGenerator : public SkImageGenerator {
public:
    RasterGenerator(const SkBitmap& bm) : SkImageGenerator(bm.info()), fBM(bm)
    {}

protected:
    bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
                     const Options&) override {
        SkASSERT(fBM.width() == info.width());
        SkASSERT(fBM.height() == info.height());
        return fBM.readPixels(info, pixels, rowBytes, 0, 0);
    }
private:
    SkBitmap fBM;
};
static std::unique_ptr<SkImageGenerator> make_ras_generator(SkCanvas*,
                                                            sk_sp<SkPicture> pic) {
    SkBitmap bm;
    bm.allocN32Pixels(100, 100);
    SkCanvas canvas(bm);
    canvas.clear(0);
    canvas.translate(-100, -100);
    canvas.drawPicture(pic);
    return std::make_unique<RasterGenerator>(bm);
}

#if defined(SK_GANESH)
class TextureGenerator : public GrTextureGenerator {
public:
    TextureGenerator(SkCanvas* canvas, const SkImageInfo& info, sk_sp<SkPicture> pic)
            : GrTextureGenerator(info) {

        fRContext = sk_ref_sp(canvas->recordingContext());

        sk_sp<SkSurface> surface;

        if (fRContext) {
            surface = SkSurfaces::RenderTarget(fRContext.get(),
                                               skgpu::Budgeted::kYes,
                                               info,
                                               0,
                                               kTopLeft_GrSurfaceOrigin,
                                               nullptr);
        }
#if defined(SK_GRAPHITE)
        if (skgpu::graphite::Recorder* recorder = canvas->recorder()) {
            surface = SkSurfaces::RenderTarget(recorder, info);
        }
#endif

        if (surface) {
            surface->getCanvas()->clear(0);
            surface->getCanvas()->translate(-100, -100);
            surface->getCanvas()->drawPicture(pic);
            fImage = surface->makeImageSnapshot();
        }
    }
protected:
    GrSurfaceProxyView onGenerateTexture(GrRecordingContext* rContext,
                                         const SkImageInfo& info,
                                         skgpu::Mipmapped mipmapped,
                                         GrImageTexGenPolicy policy) override {
        SkASSERT(rContext);
        SkASSERT(rContext->priv().matches(fRContext.get()));

        // We are immediately copying the view so no need to pass in targetSurface
        auto [view, _] = skgpu::ganesh::AsView(rContext, fImage, skgpu::Mipmapped::kNo,
                                               /*targetSurface=*/nullptr);
        if (!view) {
            return {};
        }

        SkASSERT_RELEASE(info.dimensions() == view.proxy()->dimensions());

        if (policy == GrImageTexGenPolicy::kDraw) {
            return view;
        }
        auto budgeted = policy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
                                ? skgpu::Budgeted::kNo
                                : skgpu::Budgeted::kYes;
        return GrSurfaceProxyView::Copy(
                fRContext.get(),
                view,
                mipmapped,
                SkIRect::MakeWH(info.width(), info.height()),
                SkBackingFit::kExact,
                budgeted,
                /*label=*/"SurfaceProxyView_GenerateTexture");
    }

private:
    sk_sp<GrRecordingContext> fRContext;
    sk_sp<SkImage>            fImage;
};

static std::unique_ptr<SkImageGenerator> make_tex_generator(SkCanvas* canvas,
                                                            sk_sp<SkPicture> pic) {
    auto dContext = GrAsDirectContext(canvas->recordingContext());
    if (!dContext && !canvas->recorder()) {
        return nullptr;
    }

    const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);

    return std::make_unique<TextureGenerator>(canvas, info, pic);
}
#endif  // SK_GANESH

class ImageCacheratorGM : public skiagm::GM {
    typedef std::unique_ptr<SkImageGenerator> (*FactoryFunc)(SkCanvas*, sk_sp<SkPicture>);

    SkString         fName;
    FactoryFunc      fFactory;
    sk_sp<SkPicture> fPicture;
    sk_sp<SkImage>   fImage;
    sk_sp<SkImage>   fImageSubset;
    bool             fUseTexture;

public:
    ImageCacheratorGM(const char suffix[], FactoryFunc factory, bool useTexture) :
                    fFactory(factory), fUseTexture(useTexture) {
        fName.printf("image-cacherator-from-%s", suffix);
    }

protected:
    SkString getName() const override { return fName; }

    SkISize getISize() override { return SkISize::Make(960, 450); }

    void onOnceBeforeDraw() override {
        const SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
        SkPictureRecorder recorder;
        draw_something(recorder.beginRecording(bounds), bounds);
        fPicture = recorder.finishRecordingAsPicture();
    }

    bool makeCaches(SkCanvas* canvas) {
        {
            auto gen = fFactory(canvas, fPicture);
            if (!gen) {
                return false;
            }
#if defined(SK_GANESH)
            if (fUseTexture) {
                auto textureGen = std::unique_ptr<GrTextureGenerator>(
                        static_cast<GrTextureGenerator*>(gen.release()));
                fImage = SkImages::DeferredFromTextureGenerator(std::move(textureGen));
            } else
#endif
            {
                SkASSERT(!fUseTexture);
                fImage = SkImages::DeferredFromGenerator(std::move(gen));
            }
            if (!fImage) {
                return false;
            }
            SkASSERT(fImage->dimensions() == SkISize::Make(100, 100));
        }

        {
            const SkIRect subset = SkIRect::MakeLTRB(50, 50, 100, 100);

            // We re-create the generator here on the off chance that making a subset from
            // 'fImage' might perturb its state.
            auto gen = fFactory(canvas, fPicture);
            if (!gen) {
                return false;
            }

            auto recorder = canvas->baseRecorder();
#if defined(SK_GANESH)
            if (fUseTexture) {
                auto textureGen = std::unique_ptr<GrTextureGenerator>(
                        static_cast<GrTextureGenerator*>(gen.release()));
                fImageSubset = SkImages::DeferredFromTextureGenerator(std::move(textureGen))
                                       ->makeSubset(recorder, subset, {});
            } else
#endif
            {
                SkASSERT(!fUseTexture);
                fImageSubset = SkImages::DeferredFromGenerator(std::move(gen))
                                       ->makeSubset(recorder, subset, {});
            }
            if (!fImageSubset) {
                return false;
            }
            SkASSERT(fImageSubset->dimensions() == SkISize::Make(50, 50));
        }

        return true;
    }

    static void draw_placeholder(SkCanvas* canvas, SkScalar x, SkScalar y, int w, int h) {
        SkPaint paint;
        paint.setStyle(SkPaint::kStroke_Style);
        SkRect r = SkRect::MakeXYWH(x, y, SkIntToScalar(w), SkIntToScalar(h));
        canvas->drawRect(r, paint);
        canvas->drawLine(r.left(), r.top(), r.right(), r.bottom(), paint);
        canvas->drawLine(r.left(), r.bottom(), r.right(), r.top(), paint);
    }

    static void draw_as_bitmap(GrDirectContext* dContext, SkCanvas* canvas, SkImage* image,
                               SkScalar x, SkScalar y) {
        SkBitmap bitmap;
        if (as_IB(image)->getROPixels(dContext, &bitmap)) {
            canvas->drawImage(bitmap.asImage(), x, y);
        } else {
            draw_placeholder(canvas, x, y, image->width(), image->height());
        }
    }

    static void draw_as_tex(SkCanvas* canvas, SkImage* image, SkScalar x, SkScalar y) {
#if defined(SK_GANESH)
        if (as_IB(image)->isGaneshBacked()) {
            // The gpu-backed images are drawn in this manner bc the generator backed images
            // aren't considered texture-backed
            // We know for this test the targetSurface proxy is different from the image so we can
            // just pass in nullptr.
            auto [view, ct] =
                    skgpu::ganesh::AsView(canvas->recordingContext(), image, skgpu::Mipmapped::kNo,
                                          /*targetSurface=*/nullptr);
            if (!view) {
                // show placeholder if we have no texture
                draw_placeholder(canvas, x, y, image->width(), image->height());
                return;
            }
            SkColorInfo colorInfo(GrColorTypeToSkColorType(ct),
                                  image->alphaType(),
                                  image->refColorSpace());
            // No API to draw a GrTexture directly, so we cheat and create a private image subclass
            sk_sp<SkImage> texImage(new SkImage_Ganesh(sk_ref_sp(canvas->recordingContext()),
                                                       image->uniqueID(),
                                                       std::move(view),
                                                       std::move(colorInfo)));
            canvas->drawImage(texImage.get(), x, y);
        } else
#endif
        {
            canvas->drawImage(image, x, y);
        }
    }

    void drawRow(GrDirectContext* dContext, SkCanvas* canvas, float scale) const {
        canvas->scale(scale, scale);

        SkMatrix matrix = SkMatrix::Translate(-100, -100);
        canvas->drawPicture(fPicture, &matrix, nullptr);

        // Draw the tex first, so it doesn't hit a lucky cache from the raster version. This
        // way we also can force the generateTexture call.

        draw_as_tex(canvas, fImage.get(), 150, 0);
        draw_as_tex(canvas, fImageSubset.get(), 150+101, 0);

        draw_as_bitmap(dContext, canvas, fImage.get(), 310, 0);
        draw_as_bitmap(dContext, canvas, fImageSubset.get(), 310+101, 0);
    }

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
#if defined(SK_GANESH)
        auto dContext = GrAsDirectContext(canvas->recordingContext());
#else
        constexpr GrDirectContext* dContext = nullptr;
#endif
        if (!this->makeCaches(canvas)) {
            errorMsg->printf("Could not create cached images");
            return DrawResult::kSkip;
        }

        canvas->save();
            canvas->translate(20, 20);
            this->drawRow(dContext, canvas, 1.0);
        canvas->restore();

        canvas->save();
            canvas->translate(20, 150);
            this->drawRow(dContext, canvas, 0.25f);
        canvas->restore();

        canvas->save();
            canvas->translate(20, 220);
            this->drawRow(dContext, canvas, 2.0f);
        canvas->restore();

        return DrawResult::kOk;
    }

private:
    using INHERITED = skiagm::GM;
};

DEF_GM( return new ImageCacheratorGM("picture", make_pic_generator, false); )
DEF_GM( return new ImageCacheratorGM("raster", make_ras_generator, false); )
#if defined(SK_GANESH)
DEF_GM( return new ImageCacheratorGM("texture", make_tex_generator, true); )
#endif
