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

#ifndef GrSurfaceFillContext_DEFINED
#define GrSurfaceFillContext_DEFINED

#include "include/core/SkSize.h"
#include "include/private/GrTypesPriv.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrOpsTask.h"
#include "src/gpu/GrSurfaceContext.h"
#include "src/gpu/GrSwizzle.h"
#include "src/gpu/effects/GrMatrixEffect.h"

#include <array>
#include <tuple>

class GrFragmentProcessor;
class GrImageContext;
class GrOp;
class GrBackendFormat;
class GrRecordingContext;
class GrSurfaceProxyView;
class SkColorSpace;

class GrSurfaceFillContext : public GrSurfaceContext {
public:
    GrSurfaceFillContext(GrRecordingContext*,
                         GrSurfaceProxyView readView,
                         GrSurfaceProxyView writeView,
                         const GrColorInfo&,
                         bool flushTimeOpsTask = false);

    /**
     * Uses GrImageInfo's color type to pick the default texture format. Will return a
     * GrSurfaceDrawContext if possible.
     */
    static std::unique_ptr<GrSurfaceFillContext> Make(GrRecordingContext*,
                                                      GrImageInfo,
                                                      SkBackingFit = SkBackingFit::kExact,
                                                      int sampleCount = 1,
                                                      GrMipmapped = GrMipmapped::kNo,
                                                      GrProtected = GrProtected::kNo,
                                                      GrSurfaceOrigin = kTopLeft_GrSurfaceOrigin,
                                                      SkBudgeted = SkBudgeted::kYes);

    /**
     * Like the above but uses GetFallbackColorTypeAndFormat to find a fallback color type (and
     * compatible format) if the passed GrImageInfo's color type is not renderable.
     */
    static std::unique_ptr<GrSurfaceFillContext> MakeWithFallback(
            GrRecordingContext*,
            GrImageInfo,
            SkBackingFit = SkBackingFit::kExact,
            int sampleCount = 1,
            GrMipmapped = GrMipmapped::kNo,
            GrProtected = GrProtected::kNo,
            GrSurfaceOrigin = kTopLeft_GrSurfaceOrigin,
            SkBudgeted = SkBudgeted::kYes);

    /**
     * Makes a custom configured GrSurfaceFillContext where the caller specifies the specific
     * texture format and swizzles. The color type will be kUnknown. Returns a GrSurfaceDrawContext
     * if possible.
     */
    static std::unique_ptr<GrSurfaceFillContext> Make(GrRecordingContext*,
                                                      SkAlphaType,
                                                      sk_sp<SkColorSpace>,
                                                      SkISize dimensions,
                                                      SkBackingFit,
                                                      const GrBackendFormat&,
                                                      int sampleCount,
                                                      GrMipmapped,
                                                      GrProtected,
                                                      GrSwizzle readSwizzle,
                                                      GrSwizzle writeSwizzle,
                                                      GrSurfaceOrigin,
                                                      SkBudgeted);

    /**
     * Creates a GrSurfaceFillContext from an existing GrBackendTexture. The GrColorInfo's color
     * type must be compatible with backend texture's format or this will fail. All formats are
     * considered compatible with kUnknown. Returns a GrSurfaceDrawContext if possible.
     */
    static std::unique_ptr<GrSurfaceFillContext> MakeFromBackendTexture(
            GrRecordingContext*,
            GrColorInfo,
            const GrBackendTexture&,
            int sampleCount,
            GrSurfaceOrigin,
            sk_sp<GrRefCntedCallback> releaseHelper);

    GrSurfaceFillContext* asFillContext() override { return this; }

    /**
     * Provides a performance hint that the render target's contents are allowed
     * to become undefined.
     */
    void discard();

    /**
     * Clear the rect of the render target to the given color.
     * @param rect  the rect to clear to
     * @param color the color to clear to.
     */
    template <SkAlphaType AlphaType>
    void clear(const SkIRect& rect, const SkRGBA4f<AlphaType>& color) {
        this->internalClear(&rect, this->adjustColorAlphaType(color));
    }

    /** Clears the entire render target to the color. */
    template <SkAlphaType AlphaType> void clear(const SkRGBA4f<AlphaType>& color) {
        this->internalClear(nullptr, this->adjustColorAlphaType(color));
    }

    /**
     * Clear at minimum the pixels within 'scissor', but is allowed to clear the full render target
     * if that is the more performant option.
     */
    template <SkAlphaType AlphaType>
    void clearAtLeast(const SkIRect& scissor, const SkRGBA4f<AlphaType>& color) {
        this->internalClear(&scissor,
                            this->adjustColorAlphaType(color),
                            /* upgrade to full */ true);
    }

    /** Fills 'dstRect' with 'fp' */
    void fillRectWithFP(const SkIRect& dstRect, std::unique_ptr<GrFragmentProcessor> fp);

    /**
     * A convenience version of fillRectWithFP that applies a coordinate transformation via
     * GrMatrixEffect.
     */
    void fillRectWithFP(const SkIRect& dstRect,
                        const SkMatrix& localMatrix,
                        std::unique_ptr<GrFragmentProcessor> fp) {
        fp = GrMatrixEffect::Make(localMatrix, std::move(fp));
        this->fillRectWithFP(dstRect, std::move(fp));
    }

    /** Fills 'dstRect' with 'fp' using a local matrix that maps 'srcRect' to 'dstRect' */
    void fillRectToRectWithFP(const SkRect& srcRect,
                              const SkIRect& dstRect,
                              std::unique_ptr<GrFragmentProcessor> fp) {
        SkMatrix lm = SkMatrix::RectToRect(SkRect::Make(dstRect), srcRect);
        this->fillRectWithFP(dstRect, lm, std::move(fp));
    }

    /** Fills 'dstRect' with 'fp' using a local matrix that maps 'srcRect' to 'dstRect' */
    void fillRectToRectWithFP(const SkIRect& srcRect,
                              const SkIRect& dstRect,
                              std::unique_ptr<GrFragmentProcessor> fp) {
        this->fillRectToRectWithFP(SkRect::Make(srcRect), dstRect, std::move(fp));
    }

    /** Fills the entire render target with the passed FP. */
    void fillWithFP(std::unique_ptr<GrFragmentProcessor> fp) {
        this->fillRectWithFP(SkIRect::MakeSize(fWriteView.proxy()->dimensions()), std::move(fp));
    }

    /**
     * A convenience version of fillWithFP that applies a coordinate transformation via
     * GrMatrixEffect and fills the entire render target.
     */
    void fillWithFP(const SkMatrix& localMatrix, std::unique_ptr<GrFragmentProcessor> fp) {
        this->fillRectWithFP(
                SkIRect::MakeSize(fWriteView.proxy()->dimensions()), localMatrix, std::move(fp));
    }

    /**
     * Draws the src texture with no matrix. The dstRect is the dstPoint with the width and height
     * of the srcRect. The srcRect and dstRect are clipped to the bounds of the src and dst surfaces
     * respectively.
     */
    bool blitTexture(GrSurfaceProxyView view, const SkIRect& srcRect, const SkIPoint& dstPoint);

    GrOpsTask* getOpsTask();

    int numSamples() const { return this->asRenderTargetProxy()->numSamples(); }
    bool wrapsVkSecondaryCB() const { return this->asRenderTargetProxy()->wrapsVkSecondaryCB(); }

    SkArenaAlloc* arenaAlloc() { return this->arenas()->arenaAlloc(); }
    GrSubRunAllocator* subRunAlloc() { return this->arenas()->subRunAlloc(); }

#if GR_TEST_UTILS
    GrOpsTask* testingOnly_PeekLastOpsTask() { return fOpsTask.get(); }
#endif

    const GrSurfaceProxyView& writeSurfaceView() const { return fWriteView; }

protected:
    /**
     * Creates a constant color paint for a clear, using src-over if possible to improve batching.
     */
    static void ClearToGrPaint(std::array<float, 4> color, GrPaint* paint);

    void addOp(GrOp::Owner);

    GrOpsTask* replaceOpsTask();

private:
    sk_sp<GrArenas> arenas() { return fWriteView.proxy()->asRenderTargetProxy()->arenas(); }

    template <SkAlphaType AlphaType>
    static std::array<float, 4> ConvertColor(SkRGBA4f<AlphaType> color);

    template <SkAlphaType AlphaType>
    std::array<float, 4> adjustColorAlphaType(SkRGBA4f<AlphaType> color) const;

    /** Override to be notified in subclass before the current ops task is replaced. */
    virtual void willReplaceOpsTask(GrOpsTask* prevTask, GrOpsTask* nextTask) {}

    /**
     * Override to be called to participate in the decision to discard all previous ops if a
     * fullscreen clear occurs.
     */
    virtual GrOpsTask::CanDiscardPreviousOps canDiscardPreviousOpsOnFullClear() const {
        return GrOpsTask::CanDiscardPreviousOps::kYes;
    }

    void internalClear(const SkIRect* scissor,
                       std::array<float, 4> color,
                       bool upgradePartialToFull = false);

    void addDrawOp(GrOp::Owner);

    SkDEBUGCODE(void onValidate() const override;)

    GrSurfaceProxyView fWriteView;

    // The GrOpsTask can be closed by some other surface context that has picked it up. For this
    // reason, the GrOpsTask should only ever be accessed via 'getOpsTask'.
    sk_sp<GrOpsTask> fOpsTask;

    bool fFlushTimeOpsTask;

    using INHERITED = GrSurfaceContext;
};

template<>
inline std::array<float, 4> GrSurfaceFillContext::ConvertColor<kPremul_SkAlphaType>(
        SkPMColor4f color) {
    return color.unpremul().array();
}

template<>
inline std::array<float, 4> GrSurfaceFillContext::ConvertColor<kUnpremul_SkAlphaType>(
        SkColor4f color) {
    return color.premul().array();
}

template <SkAlphaType AlphaType>
std::array<float, 4> GrSurfaceFillContext::adjustColorAlphaType(SkRGBA4f<AlphaType> color) const {
    if (AlphaType == kUnknown_SkAlphaType ||
        this->colorInfo().alphaType() == kUnknown_SkAlphaType) {
        return color.array();
    }
    return (AlphaType == this->colorInfo().alphaType()) ? color.array() : ConvertColor(color);
}

#endif
