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

#include "src/gpu/ganesh/GrRecordingContextPriv.h"

#include "include/core/SkColorSpace.h"
#include "src/gpu/ganesh/Device_v1.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrDrawingManager.h"
#include "src/gpu/ganesh/GrProxyProvider.h"
#include "src/gpu/ganesh/GrRenderTargetProxy.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/gpu/ganesh/SurfaceDrawContext.h"
#include "src/gpu/ganesh/SurfaceFillContext.h"

void GrRecordingContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
    this->context()->addOnFlushCallbackObject(onFlushCBObject);
}

sk_sp<skgpu::v1::Device> GrRecordingContextPriv::createDevice(GrColorType colorType,
                                                              sk_sp<GrSurfaceProxy> proxy,
                                                              sk_sp<SkColorSpace> colorSpace,
                                                              GrSurfaceOrigin origin,
                                                              const SkSurfaceProps& props,
                                                              skgpu::v1::Device::InitContents init) {
    return skgpu::v1::Device::Make(this->context(), colorType, std::move(proxy),
                                   std::move(colorSpace), origin, props, init);
}

sk_sp<skgpu::v1::Device> GrRecordingContextPriv::createDevice(
        skgpu::Budgeted budgeted,
        const SkImageInfo& ii,
        SkBackingFit fit,
        int sampleCount,
        GrMipmapped mipmapped,
        GrProtected isProtected,
        GrSurfaceOrigin origin,
        const SkSurfaceProps& props,
        skgpu::v1::Device::InitContents init) {
    return skgpu::v1::Device::Make(this->context(), budgeted, ii, fit, sampleCount,
                                   mipmapped, isProtected, origin, props, init);
}

void GrRecordingContextPriv::moveRenderTasksToDDL(SkDeferredDisplayList* ddl) {
    this->context()->drawingManager()->moveRenderTasksToDDL(ddl);
}

sktext::gpu::SDFTControl GrRecordingContextPriv::getSDFTControl(bool useSDFTForSmallText) const {
#if !defined(SK_DISABLE_SDF_TEXT)
    return sktext::gpu::SDFTControl{
            this->caps()->shaderCaps()->supportsDistanceFieldText(),
            useSDFTForSmallText,
            !this->caps()->disablePerspectiveSDFText(),
            this->options().fMinDistanceFieldFontSize,
            this->options().fGlyphsAsPathsFontSize};
#else
    return sktext::gpu::SDFTControl{};
#endif
}

std::unique_ptr<skgpu::v1::SurfaceContext> GrRecordingContextPriv::makeSC(
        GrSurfaceProxyView readView,
        const GrColorInfo& info) {
    // It is probably not necessary to check if the context is abandoned here since uses of the
    // SurfaceContext which need the context will mostly likely fail later on w/o an issue.
    // However having this here adds some reassurance in case there is a path that doesn't
    // handle an abandoned context correctly. It also lets us early out of some extra work.
    if (this->context()->abandoned()) {
        return nullptr;
    }
    GrSurfaceProxy* proxy = readView.proxy();
    SkASSERT(proxy && proxy->asTextureProxy());

    std::unique_ptr<skgpu::v1::SurfaceContext> sc;
    if (proxy->asRenderTargetProxy()) {
        // Will we ever want a swizzle that is not the default write swizzle for the format and
        // colorType here? If so we will need to manually pass that in.
        skgpu::Swizzle writeSwizzle;
        if (info.colorType() != GrColorType::kUnknown) {
            writeSwizzle = this->caps()->getWriteSwizzle(proxy->backendFormat(),
                                                         info.colorType());
        }
        GrSurfaceProxyView writeView(readView.refProxy(), readView.origin(), writeSwizzle);
        if (info.alphaType() == kPremul_SkAlphaType ||
            info.alphaType() == kOpaque_SkAlphaType) {
            sc = std::make_unique<skgpu::v1::SurfaceDrawContext>(this->context(),
                                                                 std::move(readView),
                                                                 std::move(writeView),
                                                                 info.colorType(),
                                                                 info.refColorSpace(),
                                                                 SkSurfaceProps());
        } else {
            sc = std::make_unique<skgpu::v1::SurfaceFillContext>(this->context(),
                                                                 std::move(readView),
                                                                 std::move(writeView),
                                                                 info);
        }
    } else {
        sc = std::make_unique<skgpu::v1::SurfaceContext>(this->context(),
                                                         std::move(readView),
                                                         info);
    }
    SkDEBUGCODE(sc->validate();)
    return sc;
}

std::unique_ptr<skgpu::v1::SurfaceContext> GrRecordingContextPriv::makeSC(
        const GrImageInfo& info,
        const GrBackendFormat& format,
        std::string_view label,
        SkBackingFit fit,
        GrSurfaceOrigin origin,
        GrRenderable renderable,
        int sampleCount,
        GrMipmapped mipmapped,
        GrProtected isProtected,
        skgpu::Budgeted budgeted) {
    SkASSERT(renderable == GrRenderable::kYes || sampleCount == 1);
    if (this->abandoned()) {
        return nullptr;
    }
    sk_sp<GrTextureProxy> proxy =
            this->proxyProvider()->createProxy(format,
                                               info.dimensions(),
                                               renderable,
                                               sampleCount,
                                               mipmapped,
                                               fit,
                                               budgeted,
                                               isProtected,
                                               label);
    if (!proxy) {
        return nullptr;
    }

    skgpu::Swizzle swizzle;
    if (info.colorType() != GrColorType::kUnknown &&
        !this->caps()->isFormatCompressed(format)) {
        swizzle = this->caps()->getReadSwizzle(format, info.colorType());
    }

    GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
    return this->makeSC(std::move(view), info.colorInfo());
}

std::unique_ptr<skgpu::v1::SurfaceFillContext> GrRecordingContextPriv::makeSFC(
        GrImageInfo info,
        std::string_view label,
        SkBackingFit fit,
        int sampleCount,
        GrMipmapped mipmapped,
        GrProtected isProtected,
        GrSurfaceOrigin origin,
        skgpu::Budgeted budgeted) {
    if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) {
        return skgpu::v1::SurfaceDrawContext::Make(this->context(),
                                                   info.colorType(),
                                                   info.refColorSpace(),
                                                   fit,
                                                   info.dimensions(),
                                                   SkSurfaceProps(),
                                                   label,
                                                   sampleCount,
                                                   mipmapped,
                                                   isProtected,
                                                   origin,
                                                   budgeted);
    }
    GrBackendFormat format = this->caps()->getDefaultBackendFormat(info.colorType(),
                                                                   GrRenderable::kYes);
    sk_sp<GrTextureProxy> proxy =
            this->proxyProvider()->createProxy(format,
                                               info.dimensions(),
                                               GrRenderable::kYes,
                                               sampleCount,
                                               mipmapped,
                                               fit,
                                               budgeted,
                                               isProtected,
                                               label);
    if (!proxy) {
        return nullptr;
    }
    skgpu::Swizzle readSwizzle  = this->caps()->getReadSwizzle (format, info.colorType());
    skgpu::Swizzle writeSwizzle = this->caps()->getWriteSwizzle(format, info.colorType());

    GrSurfaceProxyView readView(            proxy, origin,  readSwizzle);
    GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);
    std::unique_ptr<skgpu::v1::SurfaceFillContext> sfc;
    sfc = std::make_unique<skgpu::v1::SurfaceFillContext>(this->context(),
                                                          std::move(readView),
                                                          std::move(writeView),
                                                          info.colorInfo());
    sfc->discard();
    return sfc;
}

std::unique_ptr<skgpu::v1::SurfaceFillContext> GrRecordingContextPriv::makeSFC(
        SkAlphaType alphaType,
        sk_sp<SkColorSpace> colorSpace,
        SkISize dimensions,
        SkBackingFit fit,
        const GrBackendFormat& format,
        int sampleCount,
        GrMipmapped mipmapped,
        GrProtected isProtected,
        skgpu::Swizzle readSwizzle,
        skgpu::Swizzle writeSwizzle,
        GrSurfaceOrigin origin,
        skgpu::Budgeted budgeted,
        std::string_view label) {
    SkASSERT(!dimensions.isEmpty());
    SkASSERT(sampleCount >= 1);
    SkASSERT(format.isValid() && format.backend() == fContext->backend());
    if (alphaType == kPremul_SkAlphaType || alphaType == kOpaque_SkAlphaType) {
        return skgpu::v1::SurfaceDrawContext::Make(
                this->context(),
                std::move(colorSpace),
                fit,
                dimensions,
                format,
                sampleCount,
                mipmapped,
                isProtected,
                readSwizzle,
                writeSwizzle,
                origin,
                budgeted,
                SkSurfaceProps(),
                label);
    }

    sk_sp<GrTextureProxy> proxy =
            this->proxyProvider()->createProxy(format,
                                               dimensions,
                                               GrRenderable::kYes,
                                               sampleCount,
                                               mipmapped,
                                               fit,
                                               budgeted,
                                               isProtected,
                                               label);
    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);
    std::unique_ptr<skgpu::v1::SurfaceFillContext> sfc;
    sfc = std::make_unique<skgpu::v1::SurfaceFillContext>(this->context(),
                                                          std::move(readView),
                                                          std::move(writeView),
                                                          info.colorInfo());
    sfc->discard();
    return sfc;
}

std::unique_ptr<skgpu::v1::SurfaceFillContext> GrRecordingContextPriv::makeSFCWithFallback(
        GrImageInfo info,
        SkBackingFit fit,
        int sampleCount,
        GrMipmapped mipmapped,
        GrProtected isProtected,
        GrSurfaceOrigin origin,
        skgpu::Budgeted budgeted) {
    if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) {
        return skgpu::v1::SurfaceDrawContext::MakeWithFallback(this->context(),
                                                               info.colorType(),
                                                               info.refColorSpace(),
                                                               fit,
                                                               info.dimensions(),
                                                               SkSurfaceProps(),
                                                               sampleCount,
                                                               mipmapped,
                                                               isProtected,
                                                               origin,
                                                               budgeted);
    }
    const GrCaps* caps = this->caps();

    auto [ct, _] = caps->getFallbackColorTypeAndFormat(info.colorType(), sampleCount);
    if (ct == GrColorType::kUnknown) {
        return nullptr;
    }
    info = info.makeColorType(ct);
    return this->makeSFC(info, "MakeSurfaceContextWithFallback",
                         fit,
                         sampleCount,
                         mipmapped,
                         isProtected,
                         origin,
                         budgeted);
}

std::unique_ptr<skgpu::v1::SurfaceFillContext> GrRecordingContextPriv::makeSFCFromBackendTexture(
        GrColorInfo info,
        const GrBackendTexture& tex,
        int sampleCount,
        GrSurfaceOrigin origin,
        sk_sp<skgpu::RefCntedCallback> releaseHelper) {

    SkASSERT(sampleCount > 0);

    if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) {
        return skgpu::v1::SurfaceDrawContext::MakeFromBackendTexture(this->context(),
                                                                     info.colorType(),
                                                                     info.refColorSpace(),
                                                                     tex,
                                                                     sampleCount,
                                                                     origin,
                                                                     SkSurfaceProps(),
                                                                     std::move(releaseHelper));
    }

    if (info.colorType() == GrColorType::kUnknown) {
        return nullptr;
    }

    const GrBackendFormat& format = tex.getBackendFormat();
    if (!this->caps()->areColorTypeAndFormatCompatible(info.colorType(), format)) {
        return nullptr;
    }
    skgpu::Swizzle readSwizzle  = this->caps()->getReadSwizzle (format, info.colorType());
    skgpu::Swizzle writeSwizzle = this->caps()->getWriteSwizzle(format, info.colorType());

    sk_sp<GrTextureProxy> proxy(this->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<skgpu::v1::SurfaceFillContext>(this->context(),
                                                           std::move(readView),
                                                           std::move(writeView),
                                                           std::move(info));
}
