/*
 * 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:
    /**
     * Checks whether the passed color type is renderable with the passed context. If so, the
     * same color type is passed back along with the default format used for the color type. If
     * not, provides an alternative (perhaps lower bit depth and/or unorm instead of float) color
     * type that is supported along with it's default format or kUnknown if there no renderable
     * fallback format.
     */
    static std::tuple<GrColorType, GrBackendFormat> GetFallbackColorTypeAndFormat(GrImageContext*,
                                                                                  GrColorType,
                                                                                  int sampleCount);

    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(); }
    GrMipmapped mipmapped() const;

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

#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);

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
