1/* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file 6 */ 7 8#include "src/core/SkSpecialSurface.h" 9 10#include <memory> 11 12#include "include/core/SkCanvas.h" 13#include "src/core/SkSpecialImage.h" 14#include "src/core/SkSurfacePriv.h" 15 16 /////////////////////////////////////////////////////////////////////////////// 17class SkSpecialSurface_Base : public SkSpecialSurface { 18public: 19 SkSpecialSurface_Base(const SkIRect& subset, const SkSurfaceProps& props) 20 : INHERITED(subset, props) 21 , fCanvas(nullptr) { 22 } 23 24 // reset is called after an SkSpecialImage has been snapped 25 void reset() { fCanvas.reset(); } 26 27 // This can return nullptr if reset has already been called or something when wrong in the ctor 28 SkCanvas* onGetCanvas() { return fCanvas.get(); } 29 30 virtual sk_sp<SkSpecialImage> onMakeImageSnapshot() = 0; 31 32protected: 33 std::unique_ptr<SkCanvas> fCanvas; // initialized by derived classes in ctors 34 35private: 36 using INHERITED = SkSpecialSurface; 37}; 38 39/////////////////////////////////////////////////////////////////////////////// 40static SkSpecialSurface_Base* as_SB(SkSpecialSurface* surface) { 41 return static_cast<SkSpecialSurface_Base*>(surface); 42} 43 44SkSpecialSurface::SkSpecialSurface(const SkIRect& subset, 45 const SkSurfaceProps& props) 46 : fProps(props.flags(), kUnknown_SkPixelGeometry) 47 , fSubset(subset) { 48 SkASSERT(fSubset.width() > 0); 49 SkASSERT(fSubset.height() > 0); 50} 51 52SkCanvas* SkSpecialSurface::getCanvas() { 53 return as_SB(this)->onGetCanvas(); 54} 55 56sk_sp<SkSpecialImage> SkSpecialSurface::makeImageSnapshot() { 57 sk_sp<SkSpecialImage> image(as_SB(this)->onMakeImageSnapshot()); 58 as_SB(this)->reset(); 59 return image; // the caller gets the creation ref 60} 61 62/////////////////////////////////////////////////////////////////////////////// 63#include "include/core/SkMallocPixelRef.h" 64 65class SkSpecialSurface_Raster : public SkSpecialSurface_Base { 66public: 67 SkSpecialSurface_Raster(const SkImageInfo& info, 68 sk_sp<SkPixelRef> pr, 69 const SkIRect& subset, 70 const SkSurfaceProps& props) 71 : INHERITED(subset, props) { 72 SkASSERT(info.width() == pr->width() && info.height() == pr->height()); 73 fBitmap.setInfo(info, info.minRowBytes()); 74 fBitmap.setPixelRef(std::move(pr), 0, 0); 75 76 fCanvas = std::make_unique<SkCanvas>(fBitmap, this->props()); 77 fCanvas->clipRect(SkRect::Make(subset)); 78#ifdef SK_IS_BOT 79 fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness 80#endif 81 } 82 83 ~SkSpecialSurface_Raster() override { } 84 85 sk_sp<SkSpecialImage> onMakeImageSnapshot() override { 86 return SkSpecialImage::MakeFromRaster(this->subset(), fBitmap, this->props()); 87 } 88 89private: 90 SkBitmap fBitmap; 91 92 using INHERITED = SkSpecialSurface_Base; 93}; 94 95sk_sp<SkSpecialSurface> SkSpecialSurface::MakeFromBitmap(const SkIRect& subset, SkBitmap& bm, 96 const SkSurfaceProps& props) { 97 if (subset.isEmpty() || !SkSurfaceValidateRasterInfo(bm.info(), bm.rowBytes())) { 98 return nullptr; 99 } 100 return sk_make_sp<SkSpecialSurface_Raster>(bm.info(), sk_ref_sp(bm.pixelRef()), subset, props); 101} 102 103sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRaster(const SkImageInfo& info, 104 const SkSurfaceProps& props) { 105 if (!SkSurfaceValidateRasterInfo(info)) { 106 return nullptr; 107 } 108 109 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, 0); 110 if (!pr) { 111 return nullptr; 112 } 113 114 const SkIRect subset = SkIRect::MakeWH(info.width(), info.height()); 115 116 return sk_make_sp<SkSpecialSurface_Raster>(info, std::move(pr), subset, props); 117} 118 119#if SK_SUPPORT_GPU 120/////////////////////////////////////////////////////////////////////////////// 121#include "include/gpu/GrRecordingContext.h" 122#include "src/gpu/GrRecordingContextPriv.h" 123 124class SkSpecialSurface_Gpu : public SkSpecialSurface_Base { 125public: 126 SkSpecialSurface_Gpu(sk_sp<skgpu::BaseDevice> device, SkIRect subset) 127 : INHERITED(subset, device->surfaceProps()) 128 , fReadView(device->readSurfaceView()) { 129 130 fCanvas = std::make_unique<SkCanvas>(std::move(device)); 131 fCanvas->clipRect(SkRect::Make(subset)); 132#ifdef SK_IS_BOT 133 fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness 134#endif 135 } 136 137 sk_sp<SkSpecialImage> onMakeImageSnapshot() override { 138 if (!fReadView.asTextureProxy()) { 139 return nullptr; 140 } 141 GrColorType ct = SkColorTypeToGrColorType(fCanvas->imageInfo().colorType()); 142 143 // Note: SkSpecialImages can only be snapShotted once, so this call is destructive and we 144 // move fReadMove. 145 return SkSpecialImage::MakeDeferredFromGpu(fCanvas->recordingContext(), 146 this->subset(), 147 kNeedNewImageUniqueID_SpecialImage, 148 std::move(fReadView), ct, 149 fCanvas->imageInfo().refColorSpace(), 150 this->props()); 151 } 152 153private: 154 GrSurfaceProxyView fReadView; 155 using INHERITED = SkSpecialSurface_Base; 156}; 157 158sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRenderTarget(GrRecordingContext* rContext, 159 const SkImageInfo& ii, 160 const SkSurfaceProps& props) { 161 if (!rContext) { 162 return nullptr; 163 } 164 165 auto device = rContext->priv().createDevice(SkBudgeted::kYes, ii, SkBackingFit::kApprox, 1, 166 GrMipmapped::kNo, GrProtected::kNo, 167 kBottomLeft_GrSurfaceOrigin, props, 168 skgpu::BaseDevice::InitContents::kUninit); 169 if (!device) { 170 return nullptr; 171 } 172 173 const SkIRect subset = SkIRect::MakeSize(ii.dimensions()); 174 175 return sk_make_sp<SkSpecialSurface_Gpu>(std::move(device), subset); 176} 177 178#endif 179