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