/*
 * 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/base/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/ResourceProvider.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())
        , 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();
}

uint32_t Surface::getPixelStorageID() const {
    return this->target().proxy()->getPixelStorageId();
}


// 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) {
    sk_sp<Device> device = Device::Make(recorder,
                                        info,
                                        budgeted,
                                        mipmapped,
                                        backingFit,
                                        SkSurfacePropsCopyOrDefault(props),
                                        initialLoadOp,
                                        label,
                                        registerWithRecorder);
    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);
}

} // 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
