/*
 * 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/gpu/graphite/BackendTexture.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Surface.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"

namespace skgpu::graphite {

Surface::Surface(sk_sp<Device> device)
        : SkSurface_Base(device->width(), device->height(), &device->surfaceProps())
        , fDevice(std::move(device)) {
}

Surface::~Surface() {}

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

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

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

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

sk_sp<SkSurface> Surface::onNewSurface(const SkImageInfo& ii) {
    return SkSurfaces::RenderTarget(fDevice->recorder(), ii, Mipmapped::kNo, &this->props());
}

sk_sp<SkImage> Surface::onNewImageSnapshot(const SkIRect* subset) {
    TextureProxyView srcView = fDevice->readSurfaceView();
    if (!srcView) {
        return nullptr;
    }

    return this->onMakeImageCopy(subset, srcView.mipmapped());
}

sk_sp<SkImage> Surface::onAsImage() {
    TextureProxyView srcView = fDevice->readSurfaceView();
    if (!srcView) {
        return nullptr;
    }

    return sk_sp<Image>(new Image(std::move(srcView), this->imageInfo().colorInfo()));
}

sk_sp<SkImage> Surface::onMakeImageCopy(const SkIRect* subset, Mipmapped mipmapped) {
    TextureProxyView srcView = fDevice->createCopy(subset, mipmapped);
    if (!srcView) {
        return nullptr;
    }

    return sk_sp<Image>(new Image(std::move(srcView), this->imageInfo().colorInfo()));
}

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) {
    fDevice->asyncRescaleAndReadPixels(info,
                                       srcRect,
                                       rescaleGamma,
                                       rescaleMode,
                                       callback,
                                       context);
}

void Surface::onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
                                                sk_sp<SkColorSpace> dstColorSpace,
                                                SkIRect srcRect,
                                                SkISize dstSize,
                                                RescaleGamma rescaleGamma,
                                                RescaleMode rescaleMode,
                                                ReadPixelsCallback callback,
                                                ReadPixelsContext context) {
    fDevice->asyncRescaleAndReadPixelsYUV420(yuvColorSpace,
                                             dstColorSpace,
                                             srcRect,
                                             dstSize,
                                             rescaleGamma,
                                             rescaleMode,
                                             callback,
                                             context);
}

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

#if GRAPHITE_TEST_UTILS && defined(SK_GANESH)
GrSemaphoresSubmitted Surface::onFlush(BackendSurfaceAccess,
                                       const GrFlushInfo&,
                                       const skgpu::MutableTextureState*) {
    fDevice->flushPendingWorkToRecorder();
    return GrSemaphoresSubmitted::kNo;
}
#endif

TextureProxy* Surface::backingTextureProxy() { return fDevice->target(); }

sk_sp<SkSurface> Surface::MakeGraphite(Recorder* recorder,
                                       const SkImageInfo& info,
                                       skgpu::Budgeted budgeted,
                                       Mipmapped mipmapped,
                                       const SkSurfaceProps* props) {
    sk_sp<Device> device = Device::Make(recorder, info, budgeted, mipmapped,
                                        SkSurfacePropsCopyOrDefault(props),
                                        /* addInitialClear= */ true);
    if (!device) {
        return nullptr;
    }

    if (!device->target()->instantiate(recorder->priv().resourceProvider())) {
        return nullptr;
    }
    return sk_make_sp<Surface>(std::move(device));
}

} // 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 caps->areColorTypeAndTextureInfoCompatible(info.colorType(), texture.info());
}

} // anonymous namespace

namespace SkSurfaces {
sk_sp<SkSurface> RenderTarget(Recorder* recorder,
                              const SkImageInfo& info,
                              skgpu::Mipmapped mipmapped,
                              const SkSurfaceProps* props) {
    // The client is getting the ref on this surface so it must be unbudgeted.
    return skgpu::graphite::Surface::MakeGraphite(
            recorder, info, skgpu::Budgeted::kNo, mipmapped, props);
}

sk_sp<SkSurface> WrapBackendTexture(Recorder* recorder,
                                    const BackendTexture& backendTex,
                                    SkColorType ct,
                                    sk_sp<SkColorSpace> cs,
                                    const SkSurfaceProps* props) {
    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)) {
        return nullptr;
    }

    sk_sp<Texture> texture = recorder->priv().resourceProvider()->createWrappedTexture(backendTex);
    if (!texture) {
        return nullptr;
    }

    sk_sp<TextureProxy> proxy(new TextureProxy(std::move(texture)));

    sk_sp<Device> device = Device::Make(recorder,
                                        std::move(proxy),
                                        info,
                                        SkSurfacePropsCopyOrDefault(props),
                                        /* addInitialClear= */ false);
    if (!device) {
        return nullptr;
    }

    return sk_make_sp<Surface>(std::move(device));
}

}  // namespace SkSurfaces

#if !defined(SK_DISABLE_LEGACY_SKSURFACE_FACTORIES)
sk_sp<SkSurface> SkSurface::MakeGraphite(skgpu::graphite::Recorder* recorder,
                                         const SkImageInfo& imageInfo,
                                         skgpu::Mipmapped mipmapped,
                                         const SkSurfaceProps* surfaceProps) {
    return SkSurfaces::RenderTarget(recorder, imageInfo, mipmapped, surfaceProps);
}

sk_sp<SkSurface> SkSurface::MakeGraphiteFromBackendTexture(
        skgpu::graphite::Recorder* recorder,
        const skgpu::graphite::BackendTexture& tex,
        SkColorType colorType,
        sk_sp<SkColorSpace> colorSpace,
        const SkSurfaceProps* props) {
    return SkSurfaces::WrapBackendTexture(recorder, tex, colorType, colorSpace, props);
}
#endif
