/*
 * 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/v2/Device_v2.h"

#include "include/gpu/GrRecordingContext.h"
#include "src/core/SkImageFilterCache.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrTracing.h"
#include "src/gpu/v2/SurfaceDrawContext_v2.h"

#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fContext->priv().singleOwner())

namespace skgpu::v2 {

sk_sp<BaseDevice> Device::Make(std::unique_ptr<SurfaceDrawContext> sdc,
                               SkAlphaType alphaType,
                               InitContents init) {
    if (!sdc) {
        return nullptr;
    }

    GrRecordingContext* rContext = sdc->recordingContext();
    if (rContext->abandoned()) {
        return nullptr;
    }

    SkColorType ct = GrColorTypeToSkColorType(sdc->colorInfo().colorType());

    DeviceFlags flags;
    if (!rContext->colorTypeSupportedAsSurface(ct) ||
        !CheckAlphaTypeAndGetFlags(alphaType, init, &flags)) {
        return nullptr;
    }
    return sk_sp<Device>(new Device(std::move(sdc), flags));
}

sk_sp<BaseDevice> Device::Make(GrRecordingContext* rContext,
                               GrColorType colorType,
                               sk_sp<GrSurfaceProxy> proxy,
                               sk_sp<SkColorSpace> colorSpace,
                               GrSurfaceOrigin origin,
                               const SkSurfaceProps& surfaceProps,
                               InitContents init) {
    if (!rContext || rContext->abandoned()) {
        return nullptr;
    }

    std::unique_ptr<SurfaceDrawContext> sdc = SurfaceDrawContext::Make(rContext,
                                                                       colorType,
                                                                       std::move(proxy),
                                                                       std::move(colorSpace),
                                                                       origin,
                                                                       surfaceProps);

    return Device::Make(std::move(sdc), kPremul_SkAlphaType, init);
}

sk_sp<BaseDevice> Device::Make(GrRecordingContext* rContext,
                               SkBudgeted budgeted,
                               const SkImageInfo& ii,
                               SkBackingFit fit,
                               int sampleCount,
                               GrMipmapped mipMapped,
                               GrProtected isProtected,
                               GrSurfaceOrigin origin,
                               const SkSurfaceProps& surfaceProps,
                               InitContents init) {
    if (!rContext || rContext->abandoned()) {
        return nullptr;
    }

    auto sdc = SurfaceDrawContext::Make(rContext,
                                        SkColorTypeToGrColorType(ii.colorType()),
                                        ii.refColorSpace(),
                                        fit,
                                        ii.dimensions(),
                                        surfaceProps,
                                        sampleCount,
                                        mipMapped,
                                        isProtected,
                                        origin,
                                        budgeted);

    return Device::Make(std::move(sdc), ii.alphaType(), init);
}

Device::Device(std::unique_ptr<SurfaceDrawContext> sdc, DeviceFlags flags)
        : BaseDevice(sk_ref_sp(sdc->recordingContext()),
                     MakeInfo(sdc.get(), flags),
                     sdc->surfaceProps())
        , fSurfaceDrawContext(std::move(sdc)) {
    if (flags & DeviceFlags::kNeedClear) {
        // TODO: re-enable this once we decide what the V2 SDC does with clearAll calls
//        this->clearAll();
    }
}

Device::~Device() {}

skgpu::SurfaceFillContext* Device::surfaceFillContext() { return fSurfaceDrawContext.get(); }

void Device::asyncRescaleAndReadPixels(const SkImageInfo& info,
                                       const SkIRect& srcRect,
                                       RescaleGamma rescaleGamma,
                                       RescaleMode rescaleMode,
                                       ReadPixelsCallback callback,
                                       ReadPixelsContext context) {
    // Context TODO: Elevate direct context requirement to public API.
    auto dContext = this->recordingContext()->asDirectContext();
    if (!dContext) {
        return;
    }
}

void Device::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
                                             sk_sp<SkColorSpace> dstColorSpace,
                                             const SkIRect& srcRect,
                                             SkISize dstSize,
                                             RescaleGamma rescaleGamma,
                                             RescaleMode,
                                             ReadPixelsCallback callback,
                                             ReadPixelsContext context) {
    // Context TODO: Elevate direct context requirement to public API.
    auto dContext = this->recordingContext()->asDirectContext();
    if (!dContext) {
        return;
    }
}

void Device::onSave() {
}

void Device::onRestore() {
}

void Device::onClipRect(const SkRect& rect, SkClipOp op, bool aa) {
}

void Device::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
}

void Device::onClipPath(const SkPath& path, SkClipOp op, bool aa) {
    SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference);
}

void Device::onClipShader(sk_sp<SkShader> shader) {
}

void Device::onClipRegion(const SkRegion& globalRgn, SkClipOp op) {
    SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference);
}

void Device::onReplaceClip(const SkIRect& rect) {
}

bool Device::onClipIsAA() const {
    return false;
}

bool Device::onClipIsWideOpen() const {
    return false;
}

void Device::onAsRgnClip(SkRegion* region) const {
}

SkBaseDevice::ClipType Device::onGetClipType() const {
    return ClipType::kEmpty;
}

SkIRect Device::onDevClipBounds() const {
    return SkIRect::MakeEmpty();
}

void Device::drawPaint(const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawPaint", fContext.get());
}

void Device::drawPoints(SkCanvas::PointMode mode,
                                 size_t count,
                                 const SkPoint points[],
                                 const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawPoints", fContext.get());

}

void Device::drawRect(const SkRect& rect, const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawRect", fContext.get());
}

void Device::drawRegion(const SkRegion& r, const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawRegion", fContext.get());
}

void Device::drawOval(const SkRect& oval, const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawOval", fContext.get());
}

void Device::drawArc(const SkRect& oval,
                     SkScalar startAngle,
                     SkScalar sweepAngle,
                     bool useCenter,
                     const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawArc", fContext.get());
}

void Device::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawRRect", fContext.get());
}

void Device::drawDRRect(const SkRRect& outer,
                        const SkRRect& inner,
                        const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawDRRect", fContext.get());
}

void Device::drawPath(const SkPath& path, const SkPaint& paint, bool pathIsMutable) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawPath", fContext.get());
}

void Device::drawImageRect(const SkImage* image,
                           const SkRect* src,
                           const SkRect& dst,
                           const SkSamplingOptions& sampling,
                           const SkPaint& paint,
                           SkCanvas::SrcRectConstraint constraint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawImageRect", fContext.get());
}

void Device::drawImageLattice(const SkImage* image,
                              const SkCanvas::Lattice& lattice,
                              const SkRect& dst,
                              SkFilterMode filter,
                              const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawImageLattice", fContext.get());
}

void Device::drawVertices(const SkVertices* vertices,
                          SkBlendMode mode,
                          const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawVertices", fContext.get());
}

void Device::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawShadow", fContext.get());
}

void Device::drawAtlas(const SkRSXform xform[],
                       const SkRect texRect[],
                       const SkColor colors[],
                       int count,
                       SkBlendMode mode,
                       const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawAtlas", fContext.get());
}

void Device::drawEdgeAAQuad(const SkRect& rect,
                            const SkPoint clip[4],
                            SkCanvas::QuadAAFlags aaFlags,
                            const SkColor4f& color,
                            SkBlendMode mode) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawEdgeAAQuad", fContext.get());
}

void Device::drawEdgeAAImageSet(const SkCanvas::ImageSetEntry set[],
                                int count,
                                const SkPoint dstClips[],
                                const SkMatrix preViewMatrices[],
                                const SkSamplingOptions& sampling,
                                const SkPaint& paint,
                                SkCanvas::SrcRectConstraint constraint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawEdgeAAImageSet", fContext.get());
}

void Device::drawDrawable(SkDrawable* drawable,
                          const SkMatrix* matrix,
                          SkCanvas* canvas) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawDrawable", fContext.get());

    this->INHERITED::drawDrawable(drawable, matrix, canvas);
}

void Device::onDrawGlyphRunList(const SkGlyphRunList& glyphRunList, const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "onDrawGlyphRunList", fContext.get());
}

void Device::drawDevice(SkBaseDevice* device,
                        const SkSamplingOptions& sampling,
                        const SkPaint& paint) {
    ASSERT_SINGLE_OWNER
    GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v2::Device", "drawDevice", fContext.get());
}

void Device::drawSpecial(SkSpecialImage* special,
                         const SkMatrix& localToDevice,
                         const SkSamplingOptions& sampling,
                         const SkPaint& paint) {
}

sk_sp<SkSpecialImage> Device::makeSpecial(const SkBitmap& bitmap) {
    ASSERT_SINGLE_OWNER
    return nullptr;
}

sk_sp<SkSpecialImage> Device::makeSpecial(const SkImage* image) {
    ASSERT_SINGLE_OWNER
    return nullptr;
}

sk_sp<SkSpecialImage> Device::snapSpecial(const SkIRect& subset, bool forceCopy) {
    ASSERT_SINGLE_OWNER
    return nullptr;
}

sk_sp<SkSurface> Device::makeSurface(const SkImageInfo& ii,
                                     const SkSurfaceProps& props) {
    ASSERT_SINGLE_OWNER
    return nullptr;
}

bool Device::onReadPixels(const SkPixmap& pm, int x, int y) {
    ASSERT_SINGLE_OWNER
    return false;
}

bool Device::onWritePixels(const SkPixmap& pm, int x, int y) {
    ASSERT_SINGLE_OWNER
    return false;
}

bool Device::onAccessPixels(SkPixmap*) {
    ASSERT_SINGLE_OWNER
    return false;
}

SkBaseDevice* Device::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
    ASSERT_SINGLE_OWNER
    return nullptr;
}

bool Device::forceConservativeRasterClip() const {
    return true;
}

SkImageFilterCache* Device::getImageFilterCache() {
    ASSERT_SINGLE_OWNER

    // We always return a transient cache, so it is freed after each filter traversal.
    return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize);
}

} // namespace skgpu::v2
