blob: 6bb82e336fd03f893ffb43116218df7d78c7f4b4 [file] [log] [blame]
/*
* 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/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(SkBudgeted::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, SkBudgeted::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