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

#include "src/gpu/GrSurfaceFillContext.h"

#include "include/private/GrImageContext.h"
#include "src/gpu/GrImageContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrSurfaceDrawContext.h"
#include "src/gpu/ops/GrClearOp.h"
#include "src/gpu/ops/GrFillRectOp.h"

#define ASSERT_SINGLE_OWNER        GR_ASSERT_SINGLE_OWNER(this->singleOwner())
#define RETURN_IF_ABANDONED        if (fContext->abandoned()) { return; }

class AutoCheckFlush {
public:
    AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
        SkASSERT(fDrawingManager);
    }
    ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }

private:
    GrDrawingManager* fDrawingManager;
};

static inline GrColorType color_type_fallback(GrColorType ct) {
    switch (ct) {
        // kRGBA_8888 is our default fallback for many color types that may not have renderable
        // backend formats.
        case GrColorType::kAlpha_8:
        case GrColorType::kBGR_565:
        case GrColorType::kABGR_4444:
        case GrColorType::kBGRA_8888:
        case GrColorType::kRGBA_1010102:
        case GrColorType::kBGRA_1010102:
        case GrColorType::kRGBA_F16:
        case GrColorType::kRGBA_F16_Clamped:
            return GrColorType::kRGBA_8888;
        case GrColorType::kAlpha_F16:
            return GrColorType::kRGBA_F16;
        case GrColorType::kGray_8:
            return GrColorType::kRGB_888x;
        default:
            return GrColorType::kUnknown;
    }
}

std::tuple<GrColorType, GrBackendFormat> GrSurfaceFillContext::GetFallbackColorTypeAndFormat(
        GrImageContext* context, GrColorType colorType, int sampleCnt) {
    auto caps = context->priv().caps();
    do {
        auto format = caps->getDefaultBackendFormat(colorType, GrRenderable::kYes);
        // We continue to the fallback color type if there no default renderable format or we
        // requested msaa and the format doesn't support msaa.
        if (format.isValid() && caps->isFormatRenderable(format, sampleCnt)) {
            return {colorType, format};
        }
        colorType = color_type_fallback(colorType);
    } while (colorType != GrColorType::kUnknown);
    return {GrColorType::kUnknown, {}};
}

std::unique_ptr<GrSurfaceFillContext> GrSurfaceFillContext::Make(GrRecordingContext* context,
                                                                 SkAlphaType alphaType,
                                                                 sk_sp<SkColorSpace> colorSpace,
                                                                 SkISize dimensions,
                                                                 SkBackingFit fit,
                                                                 const GrBackendFormat& format,
                                                                 int sampleCount,
                                                                 GrMipmapped mipmapped,
                                                                 GrProtected isProtected,
                                                                 GrSwizzle readSwizzle,
                                                                 GrSwizzle writeSwizzle,
                                                                 GrSurfaceOrigin origin,
                                                                 SkBudgeted budgeted) {
    SkASSERT(context);
    SkASSERT(!dimensions.isEmpty());
    SkASSERT(sampleCount >= 1);
    SkASSERT(format.isValid() && format.backend() == context->backend());
    if (alphaType == kPremul_SkAlphaType || alphaType == kOpaque_SkAlphaType) {
        return GrSurfaceDrawContext::Make(context,
                                          std::move(colorSpace),
                                          fit,
                                          dimensions,
                                          format,
                                          sampleCount,
                                          mipmapped,
                                          isProtected,
                                          readSwizzle,
                                          writeSwizzle,
                                          origin,
                                          budgeted,
                                          /* surface props*/ nullptr);
    }

    sk_sp<GrTextureProxy> proxy = context->priv().proxyProvider()->createProxy(format,
                                                                               dimensions,
                                                                               GrRenderable::kYes,
                                                                               sampleCount,
                                                                               mipmapped,
                                                                               fit,
                                                                               budgeted,
                                                                               isProtected);
    if (!proxy) {
        return nullptr;
    }
    GrImageInfo info(GrColorType::kUnknown, alphaType, std::move(colorSpace), dimensions);
    GrSurfaceProxyView readView(            proxy, origin,  readSwizzle);
    GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);
    auto fillContext = std::make_unique<GrSurfaceFillContext>(context,
                                                              std::move(readView),
                                                              std::move(writeView),
                                                              info.colorInfo());
    fillContext->discard();
    return fillContext;
}

std::unique_ptr<GrSurfaceFillContext> GrSurfaceFillContext::Make(GrRecordingContext* context,
                                                                 GrImageInfo info,
                                                                 SkBackingFit fit,
                                                                 int sampleCount,
                                                                 GrMipmapped mipmapped,
                                                                 GrProtected isProtected,
                                                                 GrSurfaceOrigin origin,
                                                                 SkBudgeted budgeted) {
    if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) {
        return GrSurfaceDrawContext::Make(context,
                                          info.colorType(),
                                          info.refColorSpace(),
                                          fit,
                                          info.dimensions(),
                                          sampleCount,
                                          mipmapped,
                                          isProtected,
                                          origin,
                                          budgeted,
                                          nullptr);
    }
    GrBackendFormat format = context->priv().caps()->getDefaultBackendFormat(info.colorType(),
                                                                             GrRenderable::kYes);
    sk_sp<GrTextureProxy> proxy = context->priv().proxyProvider()->createProxy(format,
                                                                               info.dimensions(),
                                                                               GrRenderable::kYes,
                                                                               sampleCount,
                                                                               mipmapped,
                                                                               fit,
                                                                               budgeted,
                                                                               isProtected);
    if (!proxy) {
        return nullptr;
    }
    GrSwizzle readSwizzle  = context->priv().caps()->getReadSwizzle (format, info.colorType());
    GrSwizzle writeSwizzle = context->priv().caps()->getWriteSwizzle(format, info.colorType());

    GrSurfaceProxyView readView(            proxy, origin,  readSwizzle);
    GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);
    auto fillContext = std::make_unique<GrSurfaceFillContext>(context,
                                                              std::move(readView),
                                                              std::move(writeView),
                                                              info.colorInfo());
    fillContext->discard();
    return fillContext;
}

std::unique_ptr<GrSurfaceFillContext> GrSurfaceFillContext::MakeWithFallback(
        GrRecordingContext* context,
        GrImageInfo info,
        SkBackingFit fit,
        int sampleCount,
        GrMipmapped mipmapped,
        GrProtected isProtected,
        GrSurfaceOrigin origin,
        SkBudgeted budgeted) {
    if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) {
        return GrSurfaceDrawContext::MakeWithFallback(context,
                                                      info.colorType(),
                                                      info.refColorSpace(),
                                                      fit,
                                                      info.dimensions(),
                                                      sampleCount,
                                                      mipmapped,
                                                      isProtected,
                                                      origin,
                                                      budgeted,
                                                      nullptr);
    }
    auto [ct, _] = GetFallbackColorTypeAndFormat(context, info.colorType(), sampleCount);
    if (ct == GrColorType::kUnknown) {
        return nullptr;
    }
    info = info.makeColorType(ct);
    return GrSurfaceFillContext::Make(context,
                                      info,
                                      fit,
                                      sampleCount,
                                      mipmapped,
                                      isProtected,
                                      origin,
                                      budgeted);
}

std::unique_ptr<GrSurfaceFillContext> GrSurfaceFillContext::MakeFromBackendTexture(
        GrRecordingContext* context,
        GrColorInfo info,
        const GrBackendTexture& tex,
        int sampleCount,
        GrSurfaceOrigin origin,
        sk_sp<GrRefCntedCallback> releaseHelper) {
    SkASSERT(sampleCount > 0);

    if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) {
        return GrSurfaceDrawContext::MakeFromBackendTexture(context,
                                                            info.colorType(),
                                                            info.refColorSpace(),
                                                            tex,
                                                            sampleCount,
                                                            origin,
                                                            nullptr,
                                                            std::move(releaseHelper));
    }
    const GrBackendFormat& format = tex.getBackendFormat();
    GrSwizzle readSwizzle, writeSwizzle;
    if (info.colorType() != GrColorType::kUnknown) {
        if (!context->priv().caps()->areColorTypeAndFormatCompatible(info.colorType(), format)) {
            return nullptr;
        }
        readSwizzle  = context->priv().caps()->getReadSwizzle (format, info.colorType());
        writeSwizzle = context->priv().caps()->getWriteSwizzle(format, info.colorType());
    }

    sk_sp<GrTextureProxy> proxy(context->priv().proxyProvider()->wrapRenderableBackendTexture(
            tex, sampleCount, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
            std::move(releaseHelper)));
    if (!proxy) {
        return nullptr;
    }

    GrSurfaceProxyView readView(            proxy, origin,  readSwizzle);
    GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);

    return std::make_unique<GrSurfaceFillContext>(context,
                                                  std::move(readView),
                                                  std::move(writeView),
                                                  std::move(info));

}

// In MDB mode the reffing of the 'getLastOpsTask' call's result allows in-progress
// GrOpsTask to be picked up and added to by GrSurfaceFillContext lower in the call
// stack. When this occurs with a closed GrOpsTask, a new one will be allocated
// when the GrSurfaceFillContext attempts to use it (via getOpsTask).
GrSurfaceFillContext::GrSurfaceFillContext(GrRecordingContext* context,
                                           GrSurfaceProxyView readView,
                                           GrSurfaceProxyView writeView,
                                           const GrColorInfo& colorInfo,
                                           bool flushTimeOpsTask)
        : GrSurfaceContext(context, std::move(readView), std::move(colorInfo))
        , fWriteView(std::move(writeView))
        , fFlushTimeOpsTask(flushTimeOpsTask) {
    fOpsTask = sk_ref_sp(context->priv().drawingManager()->getLastOpsTask(this->asSurfaceProxy()));
    SkASSERT(this->asSurfaceProxy() == fWriteView.proxy());
    SkASSERT(this->origin() == fWriteView.origin());

    SkDEBUGCODE(this->validate();)
}

void GrSurfaceFillContext::fillRectWithFP(const SkIRect& dstRect,
                                          std::unique_ptr<GrFragmentProcessor> fp) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("GrSurfaceFillContext", "fillRectWithFP", fContext);

    AutoCheckFlush acf(this->drawingManager());

    GrPaint paint;
    paint.setColorFragmentProcessor(std::move(fp));
    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
    auto op = GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
                                          SkRect::Make(dstRect));
    this->addDrawOp(std::move(op));
}

void GrSurfaceFillContext::addDrawOp(GrOp::Owner owner) {
    GrDrawOp* op = static_cast<GrDrawOp*>(owner.get());
    GrClampType clampType = GrColorTypeClampType(this->colorInfo().colorType());
    auto clip = GrAppliedClip::Disabled();
    const GrCaps& caps = *this->caps();
    GrProcessorSet::Analysis analysis = op->finalize(caps,
                                                     &clip,
                                                     /*mixed sample coverage*/ false,
                                                     clampType);
    SkASSERT(!(op->fixedFunctionFlags() & GrDrawOp::FixedFunctionFlags::kUsesStencil));
    SkASSERT(!analysis.requiresDstTexture());
    SkRect bounds = owner->bounds();
    // We shouldn't have coverage AA or hairline draws in fill contexts.
    SkASSERT(!op->hasAABloat() && !op->hasZeroArea());
    if (!bounds.intersect(this->asSurfaceProxy()->getBoundsRect())) {
        return;
    }
    op->setClippedBounds(op->bounds());
    SkDEBUGCODE(op->fAddDrawOpCalled = true;)

    GrXferProcessor::DstProxyView dstProxyView;
    this->getOpsTask()->addDrawOp(fContext->priv().drawingManager(),
                                  std::move(owner),
                                  analysis,
                                  std::move(clip),
                                  dstProxyView,
                                  GrTextureResolveManager(this->drawingManager()),
                                  caps);
}

void GrSurfaceFillContext::ClearToGrPaint(std::array<float, 4> color, GrPaint* paint) {
    paint->setColor4f({color[0], color[1], color[2], color[3]});
    if (color[3] == 1.f) {
        // Can just rely on the src-over blend mode to do the right thing.
        // This may improve batching.
        paint->setPorterDuffXPFactory(SkBlendMode::kSrcOver);
    } else {
        // A clear overwrites the prior color, so even if it's transparent, it behaves as if it
        // were src blended
        paint->setPorterDuffXPFactory(SkBlendMode::kSrc);
    }
}

void GrSurfaceFillContext::addOp(GrOp::Owner op) {
    GrDrawingManager* drawingMgr = this->drawingManager();
    this->getOpsTask()->addOp(drawingMgr,
                              std::move(op),
                              GrTextureResolveManager(drawingMgr),
                              *this->caps());
}

GrOpsTask* GrSurfaceFillContext::getOpsTask() {
    ASSERT_SINGLE_OWNER
    SkDEBUGCODE(this->validate();)

    if (!fOpsTask || fOpsTask->isClosed()) {
        sk_sp<GrOpsTask> newOpsTask = this->drawingManager()->newOpsTask(
                this->writeSurfaceView(), this->arenas(), fFlushTimeOpsTask);
        if (fOpsTask) {
            this->willReplaceOpsTask(fOpsTask.get(), newOpsTask.get());
        }
        fOpsTask = std::move(newOpsTask);
    }
    SkASSERT(!fOpsTask->isClosed());
    return fOpsTask.get();
}

#ifdef SK_DEBUG
void GrSurfaceFillContext::onValidate() const {
    if (fOpsTask && !fOpsTask->isClosed()) {
        SkASSERT(this->drawingManager()->getLastRenderTask(fWriteView.proxy()) == fOpsTask.get());
    }
}
#endif

void GrSurfaceFillContext::discard() {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("GrSurfaceDrawContext", "discard", fContext);

    AutoCheckFlush acf(this->drawingManager());

    this->getOpsTask()->discard();
}

void GrSurfaceFillContext::internalClear(const SkIRect* scissor,
                                         std::array<float, 4> color,
                                         bool upgradePartialToFull) {
    ASSERT_SINGLE_OWNER
    RETURN_IF_ABANDONED
    SkDEBUGCODE(this->validate();)
    GR_CREATE_TRACE_MARKER_CONTEXT("GrSurfaceDrawContext", "clear", fContext);

    // There are three ways clears are handled: load ops, native clears, and draws. Load ops are
    // only for fullscreen clears; native clears can be fullscreen or with scissors if the backend
    // supports then. Drawing an axis-aligned rect is the fallback path.
    GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions());
    if (scissor && !scissorState.set(*scissor)) {
        // The clear is offscreen, so skip it (normally this would be handled by addDrawOp,
        // except clear ops are not draw ops).
        return;
    }

    // If we have a scissor but it's okay to clear beyond it for performance reasons, then disable
    // the test. We only do this when the clear would be handled by a load op or natively.
    if (scissorState.enabled() && !this->caps()->performColorClearsAsDraws()) {
        if (upgradePartialToFull && (this->caps()->preferFullscreenClears() ||
                                     this->caps()->shouldInitializeTextures())) {
            // TODO: wrt the shouldInitializeTextures path, it would be more performant to
            // only clear the entire target if we knew it had not been cleared before. As
            // is this could end up doing a lot of redundant clears.
            scissorState.setDisabled();
        } else {
            // Unlike with stencil clears, we also allow clears up to the logical dimensions of the
            // render target to overflow into any approx-fit padding of the backing store dimensions
            scissorState.relaxTest(this->dimensions());
        }
    }

    if (!scissorState.enabled()) {
        // This is a fullscreen clear, so could be handled as a load op. Regardless, we can also
        // discard all prior ops in the current task since the color buffer will be overwritten.
        GrOpsTask* opsTask = this->getOpsTask();
        if (opsTask->resetForFullscreenClear(this->canDiscardPreviousOpsOnFullClear()) &&
            !this->caps()->performColorClearsAsDraws()) {
            color = this->writeSurfaceView().swizzle().applyTo(color);
            // The op list was emptied and native clears are allowed, so just use the load op
            opsTask->setColorLoadOp(GrLoadOp::kClear, color);
            return;
        } else {
            // Will use an op for the clear, reset the load op to discard since the op will
            // blow away the color buffer contents
            opsTask->setColorLoadOp(GrLoadOp::kDiscard);
        }
    }

    // At this point we are either a partial clear or a fullscreen clear that couldn't be applied
    // as a load op.
    bool clearAsDraw = this->caps()->performColorClearsAsDraws() ||
                       (scissorState.enabled() && this->caps()->performPartialClearsAsDraws());
    if (clearAsDraw) {
        GrPaint paint;
        ClearToGrPaint(color, &paint);
        auto op = GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
                                              SkRect::Make(scissorState.rect()));
        this->addDrawOp(std::move(op));
    } else {
        color = this->writeSurfaceView().swizzle().applyTo(color);
        this->addOp(GrClearOp::MakeColor(fContext, scissorState, color));
    }
}

bool GrSurfaceFillContext::blitTexture(GrSurfaceProxyView view,
                                       const SkIRect& srcRect,
                                       const SkIPoint& dstPoint) {
    SkASSERT(view.asTextureProxy());
    SkIRect clippedSrcRect;
    SkIPoint clippedDstPoint;
    if (!GrClipSrcRectAndDstPoint(this->dimensions(),
                                  view.dimensions(),
                                  srcRect,
                                  dstPoint,
                                  &clippedSrcRect,
                                  &clippedDstPoint)) {
        return false;
    }

    auto fp = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
    auto dstRect = SkIRect::MakePtSize(clippedDstPoint, clippedSrcRect.size());
    auto srcRectF = SkRect::Make(clippedSrcRect);
    this->fillRectToRectWithFP(srcRectF, dstRect, std::move(fp));
    return true;
}
