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

#include "src/core/SkSpecialSurface.h"

#include <memory>

#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkMallocPixelRef.h"
#include "src/core/SkBitmapDevice.h"
#include "src/core/SkCanvasPriv.h"
#include "src/core/SkDevice.h"
#include "src/core/SkSpecialImage.h"
#include "src/core/SkSurfacePriv.h"

SkSpecialSurface::SkSpecialSurface(sk_sp<SkBaseDevice> device, const SkIRect& subset)
        : fSubset(subset) {
    SkASSERT(fSubset.width() > 0);
    SkASSERT(fSubset.height() > 0);

    fCanvas = std::make_unique<SkCanvas>(std::move(device));
    fCanvas->clipRect(SkRect::Make(subset));
#ifdef SK_IS_BOT
    fCanvas->clear(SK_ColorRED);  // catch any imageFilter sloppiness
#endif
}

sk_sp<SkSpecialImage> SkSpecialSurface::makeImageSnapshot() {
    fCanvas->restoreToCount(0);

    // Because of the above 'restoreToCount(0)' we know we're getting the base device here.
    SkBaseDevice* baseDevice = SkCanvasPriv::TopDevice(fCanvas.get());
    if (!baseDevice) {
        return nullptr;
    }

    sk_sp<SkSpecialImage> image = baseDevice->snapSpecial(this->subset());

    fCanvas.reset();
    return image;
}

///////////////////////////////////////////////////////////////////////////////
sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRaster(const SkImageInfo& info,
                                                     const SkSurfaceProps& props) {
    if (!SkSurfaceValidateRasterInfo(info)) {
        return nullptr;
    }

    sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, 0);
    if (!pr) {
        return nullptr;
    }

    SkBitmap bitmap;
    bitmap.setInfo(info, info.minRowBytes());
    bitmap.setPixelRef(std::move(pr), 0, 0);

    sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap,
                                                  { props.flags(), kUnknown_SkPixelGeometry }));
    if (!device) {
        return nullptr;
    }

    const SkIRect subset = SkIRect::MakeSize(info.dimensions());

    return sk_make_sp<SkSpecialSurface>(std::move(device), subset);
}

///////////////////////////////////////////////////////////////////////////////
#if defined(SK_GANESH)
#include "include/gpu/GrRecordingContext.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/ganesh/GrColorInfo.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"

sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRenderTarget(GrRecordingContext* rContext,
                                                           const SkImageInfo& ii,
                                                           const SkSurfaceProps& props,
                                                           GrSurfaceOrigin surfaceOrigin) {
    if (!rContext) {
        return nullptr;
    }

    auto device = rContext->priv().createDevice(skgpu::Budgeted::kYes,
                                                ii,
                                                SkBackingFit::kApprox,
                                                1,
                                                GrMipmapped::kNo,
                                                GrProtected::kNo,
                                                surfaceOrigin,
                                                {props.flags(), kUnknown_SkPixelGeometry},
                                                skgpu::v1::Device::InitContents::kUninit);
    if (!device) {
        return nullptr;
    }

    const SkIRect subset = SkIRect::MakeSize(ii.dimensions());

    return sk_make_sp<SkSpecialSurface>(std::move(device), subset);
}

#endif // defined(SK_GANESH)

///////////////////////////////////////////////////////////////////////////////
#if defined(SK_GRAPHITE)
#include "src/gpu/graphite/Device.h"

sk_sp<SkSpecialSurface> SkSpecialSurface::MakeGraphite(skgpu::graphite::Recorder* recorder,
                                                       const SkImageInfo& ii,
                                                       const SkSurfaceProps& props) {
    using namespace skgpu::graphite;

    if (!recorder) {
        return nullptr;
    }

    sk_sp<Device> device = Device::Make(recorder,
                                        ii,
                                        skgpu::Budgeted::kYes,
                                        skgpu::Mipmapped::kNo,
                                        {props.flags(), kUnknown_SkPixelGeometry},
                                        /* addInitialClear= */ false);
    if (!device) {
        return nullptr;
    }

    const SkIRect subset = SkIRect::MakeSize(ii.dimensions());

    return sk_make_sp<SkSpecialSurface>(std::move(device), subset);
}

#endif // SK_GRAPHITE
