/*
 * Copyright 2021 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/graphite/Surface_Graphite.h"

#include "include/core/SkCapabilities.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkRecorder.h"
#include "include/gpu/graphite/BackendTexture.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Surface.h"
#include "include/private/SkLog.h"
#include "src/core/SkSurfacePriv.h"
#include "src/gpu/RefCntedCallback.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/Device.h"
#include "src/gpu/graphite/Image_Graphite.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/Texture.h"
#include "src/gpu/graphite/TextureFormat.h"
#include "src/gpu/graphite/TextureInfoPriv.h"

namespace skgpu::graphite {

Surface::Surface(sk_sp<Device> device)
        : SkSurface_Base(device->width(), device->height(), &device->surfaceProps(),
                         device->target().refProxy())
        , fDevice(std::move(device))
        , fImageView(Image::WrapDevice(fDevice)) {}

Surface::~Surface() {
    // Mark the device immutable when the Surface is destroyed to flush any pending work to the
    // recorder and to flag the device so that any linked image views can detach from the Device
    // when they are next drawn.
    fDevice->setImmutable();
}

SkImageInfo Surface::imageInfo() const {
    return fDevice->imageInfo();
}

Recorder* Surface::onGetRecorder() const { return fDevice->recorder(); }

SkRecorder* Surface::onGetBaseRecorder() const { return fDevice->recorder(); }

const TextureProxyView& Surface::target() const {
    return fDevice->target();
}

SkCanvas* Surface::onNewCanvas() { return new SkCanvas(fDevice); }

sk_sp<SkSurface> Surface::onNewSurface(const SkImageInfo& ii) {
    return fDevice->makeSurface(ii, this->props());
}

sk_sp<SkImage> Surface::onNewImageSnapshot(const SkIRect* subset) {
    return this->makeImageCopy(subset, fDevice->target().mipmapped());
}

sk_sp<Image> Surface::asImage() const {
    if (this->hasCachedImage()) {
        SKIA_LOG_W("Intermingling makeImageSnapshot and asImage calls may produce "
                    "unexpected results. Please use either the old _or_ new API.");
    }
    return fImageView;
}

sk_sp<Image> Surface::asImage(SkColorType otherCT, SkAlphaType otherAT) const {
    // No conversion, save a malloc.
    if (otherCT == fImageView->colorType() && otherAT == fImageView->alphaType()) {
        return fImageView;
    }
    // Override the color info for sampling the texture
    return Image::WrapDevice(fDevice,
                             SkColorInfo{otherCT, otherAT, fDevice->imageInfo().refColorSpace()});
}


sk_sp<SkImage> Surface::onMakeTemporaryImage() {
    if (this->hasCachedImage()) {
        SKIA_LOG_W("Intermingling makeImageSnapshot and makeTemporaryImage calls may produce "
                    "unexpected results. Please use either the old _or_ new API.");
    }
    return this->asImage();
}

sk_sp<Image> Surface::makeImageCopy(const SkIRect* subset, Mipmapped mipmapped) const {
    if (this->hasCachedImage()) {
        SKIA_LOG_W("Intermingling makeImageSnapshot and asImage calls may produce "
                    "unexpected results. Please use either the old _or_ new API.");
    }

    SkIRect srcRect = subset ? *subset : SkIRect::MakeSize(this->imageInfo().dimensions());
    // NOTE: Must copy through fDevice and not fImageView if the surface's texture is not sampleable
    return fDevice->makeImageCopy(srcRect, Budgeted::kNo, mipmapped, SkBackingFit::kExact);
}

void Surface::onWritePixels(const SkPixmap& pixmap, int x, int y) {
    fDevice->writePixels(pixmap, x, y);
}

bool Surface::onCopyOnWrite(ContentChangeMode) { return true; }

void Surface::onAsyncRescaleAndReadPixels(const SkImageInfo& info,
                                          SkIRect srcRect,
                                          RescaleGamma rescaleGamma,
                                          RescaleMode rescaleMode,
                                          ReadPixelsCallback callback,
                                          ReadPixelsContext context) {
    // Not supported for Graphite. Use Context::asyncRescaleAndReadPixels instead.
    callback(context, nullptr);
}

void Surface::onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
                                                bool readAlpha,
                                                sk_sp<SkColorSpace> dstColorSpace,
                                                SkIRect srcRect,
                                                SkISize dstSize,
                                                RescaleGamma rescaleGamma,
                                                RescaleMode rescaleMode,
                                                ReadPixelsCallback callback,
                                                ReadPixelsContext context) {
    // Not supported for Graphite. Use Context::asyncRescaleAndReadPixelsYUV420 instead.
    callback(context, nullptr);
}

sk_sp<const SkCapabilities> Surface::onCapabilities() {
    return fDevice->recorder()->priv().caps()->capabilities();
}

// Note, devices flushed with this method add their tasks to the provided drawContext's task list,
// but no last task is tracked. If no drawContext is provided, the task is added to the root task
// list and if the device is a scratch device, the last task is recorded.
void Surface::flushToDrawContext(DrawContext* drawContext) {
    this->fDevice->flushPendingWork(drawContext);
}

sk_sp<Surface> Surface::Make(Recorder* recorder,
                             const SkImageInfo& info,
                             std::string_view label,
                             Budgeted budgeted,
                             Mipmapped mipmapped,
                             SkBackingFit backingFit,
                             const SkSurfaceProps* props,
                             LoadOp initialLoadOp,
                             bool registerWithRecorder,
                             bool allowUnpremul) {
    sk_sp<Device> device = Device::Make(recorder,
                                        info,
                                        budgeted,
                                        mipmapped,
                                        backingFit,
                                        SkSurfacePropsCopyOrDefault(props),
                                        initialLoadOp,
                                        label,
                                        registerWithRecorder,
                                        allowUnpremul);
    if (!device) {
        return nullptr;
    }
    // A non-budgeted surface should be fully instantiated before we return it
    // to the client.
    SkASSERT(budgeted == Budgeted::kYes || device->target().proxy()->isInstantiated());
    return sk_make_sp<Surface>(std::move(device));
}

void Flush(sk_sp<SkSurface> surface) {
    return Flush(surface.get());
}

void Flush(SkSurface* surface) {
    if (!surface) {
        return;
    }
    auto sb = asSB(surface);
    if (!sb->isGraphiteBacked()) {
        return;
    }
    auto gs = static_cast<Surface*>(surface);
    gs->fDevice->flushPendingWork(/*drawContext=*/nullptr);
    gs->fDevice->resetStorageCache();
}

} // namespace skgpu::graphite

using namespace skgpu::graphite;

namespace {

bool validate_backend_texture(const Caps* caps,
                              const BackendTexture& texture,
                              const SkColorInfo& info) {
    if (!texture.isValid() ||
        texture.dimensions().width() <= 0 ||
        texture.dimensions().height() <= 0) {
        return false;
    }

    if (!SkColorInfoIsValid(info)) {
        return false;
    }

    if (!caps->isRenderable(texture.info())) {
        return false;
    }

    return AreColorTypeAndFormatCompatible(info.colorType(),
                                           TextureInfoPriv::ViewFormat(texture.info()));
}

} // anonymous namespace

namespace SkSurfaces {

sk_sp<SkImage> AsImage(sk_sp<const SkSurface> surface) {
    if (!surface) {
        return nullptr;
    }
    auto sb = asConstSB(surface.get());
    if (!sb->isGraphiteBacked()) {
        return nullptr;
    }
    auto gs = static_cast<const Surface*>(surface.get());
    return gs->asImage();
}

sk_sp<SkImage> AsImageCopy(sk_sp<const SkSurface> surface,
                           const SkIRect* subset,
                           skgpu::Mipmapped mipmapped) {
    if (!surface) {
        return nullptr;
    }
    auto sb = asConstSB(surface.get());
    if (!sb->isGraphiteBacked()) {
        return nullptr;
    }
    auto gs = static_cast<const Surface*>(surface.get());
    return gs->makeImageCopy(subset, mipmapped);
}

sk_sp<SkSurface> RenderTarget(Recorder* recorder,
                              const SkImageInfo& info,
                              skgpu::Mipmapped mipmapped,
                              const SkSurfaceProps* props,
                              std::string_view label) {
    if (label.empty()) {
        label = "SkSurfaceRenderTarget";
    }
    // The client is getting the ref on this surface so it must be unbudgeted.
    return skgpu::graphite::Surface::Make(recorder, info, label, skgpu::Budgeted::kNo,
                                          mipmapped, SkBackingFit::kExact, props);
}

sk_sp<SkSurface> WrapBackendTexture(Recorder* recorder,
                                    const BackendTexture& backendTex,
                                    sk_sp<SkColorSpace> cs,
                                    const SkSurfaceProps* props,
                                    TextureReleaseProc releaseP,
                                    ReleaseContext releaseC,
                                    std::string_view label) {
    // TODO(476410476): When the SkColorType-taking WrapBackendTexture goes away, we can move its
    // function body here and construct the SkColorInfo from this getDefaultColorType call.
    auto [colorType, _] =
            TextureFormatColorTypeInfo(TextureInfoPriv::ViewFormat(backendTex.info()));

    // Force single-channel red colortypes to their alpha equivalent, which is the semantic
    // behavior expected of single-channel textures with kPremul_SkAlphaType. Currently
    // WrapBackendTexture assumes kPremul_SkAlphaType.
    // TODO(michaelludwig): Add alpha type to select between opaque (red) vs premul (alpha-only).
    switch(colorType) {
        case kR8_unorm_SkColorType:  colorType = kAlpha_8_SkColorType;   break;
        case kR16_unorm_SkColorType: colorType = kA16_unorm_SkColorType; break;
        default: break;
    }
    return WrapBackendTexture(recorder, backendTex, colorType, std::move(cs), props,
                              releaseP, releaseC, label);
}

sk_sp<SkSurface> WrapBackendTexture(Recorder* recorder,
                                    const BackendTexture& backendTex,
                                    SkColorType ct,
                                    sk_sp<SkColorSpace> cs,
                                    const SkSurfaceProps* props,
                                    TextureReleaseProc releaseP,
                                    ReleaseContext releaseC,
                                    std::string_view label) {
    auto releaseHelper = skgpu::RefCntedCallback::Make(releaseP, releaseC);

    if (!recorder) {
        return nullptr;
    }

    const Caps* caps = recorder->priv().caps();

    SkColorInfo info(ct, kPremul_SkAlphaType, std::move(cs));

    if (!validate_backend_texture(caps, backendTex, info)) {
        SKIA_LOG_E("validate_backend_texture failed: backendTex.info = %s; colorType = %d",
                    backendTex.info().toString().c_str(),
                    info.colorType());
        return nullptr;
    }

    if (label.empty()) {
        label = "SkSurfaceWrappedTexture";
    }

    sk_sp<Texture> texture =
            recorder->priv().resourceProvider()->createWrappedTexture(backendTex, label);
    if (!texture) {
        return nullptr;
    }
    texture->setReleaseCallback(std::move(releaseHelper));

    sk_sp<TextureProxy> proxy = TextureProxy::Wrap(std::move(texture));
    SkISize deviceSize = proxy->dimensions();
    // Use kLoad for this device to preserve the existing contents of the wrapped backend texture.
    sk_sp<Device> device = Device::Make(recorder,
                                        std::move(proxy),
                                        deviceSize,
                                        info,
                                        SkSurfacePropsCopyOrDefault(props),
                                        LoadOp::kLoad);
    return device ? sk_make_sp<Surface>(std::move(device)) : nullptr;
}

}  // namespace SkSurfaces
