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

#ifndef skgpu_graphite_Surface_Graphite_DEFINED
#define skgpu_graphite_Surface_Graphite_DEFINED

#include "include/core/SkRecorder.h"
#include "src/image/SkSurface_Base.h"

#include "include/gpu/GpuTypes.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/graphite/ResourceTypes.h"
#include "src/gpu/graphite/TextureProxyView.h"

namespace skgpu::graphite {

class Context;
class Device;
class Image;
class Recorder;
class TextureProxy;

class Surface final : public SkSurface_Base {
public:
    // Convenience factory to create a Device, instantiate its target proxy and return as a Surface.
    static sk_sp<Surface> Make(Recorder* recorder,
                               const SkImageInfo& info,
                               std::string_view label,
                               Budgeted budgeted,
                               Mipmapped mipmapped = Mipmapped::kNo,
                               SkBackingFit backingFit = SkBackingFit::kExact,
                               const SkSurfaceProps* props = nullptr) {
        return Make(recorder, info, std::move(label), budgeted, mipmapped, backingFit, props,
                    LoadOp::kClear, /*registerWithRecorder=*/true);
    }
    // Make a surface that is not registered with the provided recorder. This surface should be
    // short-lived and it must be flushed manually for its draw commands to be recorded. Most
    // scratch surfaces will be budgeted, but if the underlying texture is being returned as a
    // client-owned image, that may not be the case.
    static sk_sp<Surface> MakeScratch(Recorder* recorder,
                                      const SkImageInfo& info,
                                      std::string_view label,
                                      Budgeted budgeted = Budgeted::kYes,
                                      Mipmapped mipmapped = Mipmapped::kNo,
                                      SkBackingFit backingFit = SkBackingFit::kApprox) {
        return Make(recorder, info, std::move(label), budgeted, mipmapped, backingFit,
                    /*props=*/nullptr, LoadOp::kDiscard, /*registerWithRecorder=*/false);
    }

    Surface(sk_sp<Device>);
    ~Surface() override;

    // From SkSurface.h
    SkImageInfo imageInfo() const override;

    // From SkSurface_Base.h
    SkSurface_Base::Type type() const override { return SkSurface_Base::Type::kGraphite; }

    Recorder* onGetRecorder() const override;
    SkRecorder* onGetBaseRecorder() const override;
    SkCanvas* onNewCanvas() override;
    sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override;
    sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subset) override;
    sk_sp<SkImage> onMakeTemporaryImage() override;
    void onWritePixels(const SkPixmap&, int x, int y) override;
    void onAsyncRescaleAndReadPixels(const SkImageInfo& info,
                                     SkIRect srcRect,
                                     RescaleGamma rescaleGamma,
                                     RescaleMode rescaleMode,
                                     ReadPixelsCallback callback,
                                     ReadPixelsContext context) override;
    void onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
                                           bool readAlpha,
                                           sk_sp<SkColorSpace> dstColorSpace,
                                           SkIRect srcRect,
                                           SkISize dstSize,
                                           RescaleGamma rescaleGamma,
                                           RescaleMode,
                                           ReadPixelsCallback callback,
                                           ReadPixelsContext context) override;
    bool onCopyOnWrite(ContentChangeMode) override;
    sk_sp<const SkCapabilities> onCapabilities() override;

    TextureProxyView readSurfaceView() const;
    sk_sp<Image> asImage() const;
    sk_sp<Image> makeImageCopy(const SkIRect* subset, Mipmapped) const;
    TextureProxy* backingTextureProxy() const;

private:
    // Regular and scratch surfaces differ by initial clear and if they are registered or not,
    // otherwise are constructed the same.
    static sk_sp<Surface> Make(Recorder* recorder,
                               const SkImageInfo&,
                               std::string_view label,
                               Budgeted,
                               Mipmapped,
                               SkBackingFit,
                               const SkSurfaceProps* props,
                               LoadOp initialLoadOp,
                               bool registerWithRecorder);

    sk_sp<Device> fDevice;
    sk_sp<Image>  fImageView; // the image object returned by asImage()

    friend void Flush(SkSurface*);
};

// TODO: The long-term for the public API around surfaces and flushing/submitting will likely
// be replaced with explicit control over Recorders and submitting Recordings to the Context
// directly. For now, internal tools often rely on surface/canvas flushing to control what's
// being timed (nanobench or viewer's stats layer), so we flush any pending draws to a DrawPass.
// While this won't measure actual conversion of the task list to backend command buffers, that
// should be fairly negligible since most of the work is handled in DrawPass::Make().
// Additionally flushing pending work here ensures we don't batch across or clear prior recorded
// work when looping in a benchmark, as the controlling code expects.
void Flush(sk_sp<SkSurface> surface);
void Flush(SkSurface* surface);

} // namespace skgpu::graphite

#endif // skgpu_graphite_Surface_Graphite_DEFINED
