/*
 * 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 SK_SUPPORT_GPU
#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 // SK_SUPPORT_GPU

///////////////////////////////////////////////////////////////////////////////
#if SK_GRAPHITE_ENABLED
#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,
                                        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_ENABLED
