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 "SkCanvas.h" 9#include "SkSpecialImage.h" 10#include "SkSpecialSurface.h" 11#include "SkSurfacePriv.h" 12 13 /////////////////////////////////////////////////////////////////////////////// 14class SkSpecialSurface_Base : public SkSpecialSurface { 15public: 16 SkSpecialSurface_Base(const SkIRect& subset, const SkSurfaceProps* props) 17 : INHERITED(subset, props) 18 , fCanvas(nullptr) { 19 } 20 21 virtual ~SkSpecialSurface_Base() { } 22 23 // reset is called after an SkSpecialImage has been snapped 24 void reset() { fCanvas.reset(); } 25 26 // This can return nullptr if reset has already been called or something when wrong in the ctor 27 SkCanvas* onGetCanvas() { return fCanvas.get(); } 28 29 virtual sk_sp<SkSpecialImage> onMakeImageSnapshot() = 0; 30 31protected: 32 std::unique_ptr<SkCanvas> fCanvas; // initialized by derived classes in ctors 33 34private: 35 typedef SkSpecialSurface INHERITED; 36}; 37 38/////////////////////////////////////////////////////////////////////////////// 39static SkSpecialSurface_Base* as_SB(SkSpecialSurface* surface) { 40 return static_cast<SkSpecialSurface_Base*>(surface); 41} 42 43SkSpecialSurface::SkSpecialSurface(const SkIRect& subset, 44 const SkSurfaceProps* props) 45 : fProps(SkSurfacePropsCopyOrDefault(props).flags(), kUnknown_SkPixelGeometry) 46 , fSubset(subset) { 47 SkASSERT(fSubset.width() > 0); 48 SkASSERT(fSubset.height() > 0); 49} 50 51SkCanvas* SkSpecialSurface::getCanvas() { 52 return as_SB(this)->onGetCanvas(); 53} 54 55sk_sp<SkSpecialImage> SkSpecialSurface::makeImageSnapshot() { 56 sk_sp<SkSpecialImage> image(as_SB(this)->onMakeImageSnapshot()); 57 as_SB(this)->reset(); 58 return image; // the caller gets the creation ref 59} 60 61/////////////////////////////////////////////////////////////////////////////// 62#include "SkMallocPixelRef.h" 63 64class SkSpecialSurface_Raster : public SkSpecialSurface_Base { 65public: 66 SkSpecialSurface_Raster(const SkImageInfo& info, 67 sk_sp<SkPixelRef> pr, 68 const SkIRect& subset, 69 const SkSurfaceProps* props) 70 : INHERITED(subset, props) { 71 SkASSERT(info.width() == pr->width() && info.height() == pr->height()); 72 fBitmap.setInfo(info, info.minRowBytes()); 73 fBitmap.setPixelRef(std::move(pr), 0, 0); 74 75 fCanvas.reset(new SkCanvas(fBitmap, this->props())); 76 fCanvas->clipRect(SkRect::Make(subset)); 77#ifdef SK_IS_BOT 78 fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness 79#endif 80 } 81 82 ~SkSpecialSurface_Raster() override { } 83 84 sk_sp<SkSpecialImage> onMakeImageSnapshot() override { 85 return SkSpecialImage::MakeFromRaster(this->subset(), fBitmap, &this->props()); 86 } 87 88private: 89 SkBitmap fBitmap; 90 91 typedef SkSpecialSurface_Base INHERITED; 92}; 93 94sk_sp<SkSpecialSurface> SkSpecialSurface::MakeFromBitmap(const SkIRect& subset, SkBitmap& bm, 95 const SkSurfaceProps* props) { 96 if (subset.isEmpty() || !SkSurfaceValidateRasterInfo(bm.info(), bm.rowBytes())) { 97 return nullptr; 98 } 99 return sk_make_sp<SkSpecialSurface_Raster>(bm.info(), sk_ref_sp(bm.pixelRef()), subset, props); 100} 101 102sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRaster(const SkImageInfo& info, 103 const SkSurfaceProps* props) { 104 if (!SkSurfaceValidateRasterInfo(info)) { 105 return nullptr; 106 } 107 108 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeZeroed(info, 0); 109 if (!pr) { 110 return nullptr; 111 } 112 113 const SkIRect subset = SkIRect::MakeWH(info.width(), info.height()); 114 115 return sk_make_sp<SkSpecialSurface_Raster>(info, std::move(pr), subset, props); 116} 117 118#if SK_SUPPORT_GPU 119/////////////////////////////////////////////////////////////////////////////// 120#include "GrContext.h" 121#include "SkGpuDevice.h" 122 123class SkSpecialSurface_Gpu : public SkSpecialSurface_Base { 124public: 125 SkSpecialSurface_Gpu(GrContext* context, sk_sp<GrRenderTargetContext> renderTargetContext, 126 int width, int height, const SkIRect& subset) 127 : INHERITED(subset, &renderTargetContext->surfaceProps()) 128 , fRenderTargetContext(std::move(renderTargetContext)) { 129 130 sk_sp<SkBaseDevice> device(SkGpuDevice::Make(context, fRenderTargetContext, width, height, 131 SkGpuDevice::kUninit_InitContents)); 132 if (!device) { 133 return; 134 } 135 136 fCanvas.reset(new SkCanvas(device.get())); 137 fCanvas->clipRect(SkRect::Make(subset)); 138#ifdef SK_IS_BOT 139 fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness 140#endif 141 } 142 143 ~SkSpecialSurface_Gpu() override { } 144 145 sk_sp<SkSpecialImage> onMakeImageSnapshot() override { 146 if (!fRenderTargetContext->asTextureProxy()) { 147 return nullptr; 148 } 149 sk_sp<SkSpecialImage> tmp(SkSpecialImage::MakeDeferredFromGpu( 150 fCanvas->getGrContext(), 151 this->subset(), 152 kNeedNewImageUniqueID_SpecialImage, 153 fRenderTargetContext->asTextureProxyRef(), 154 fRenderTargetContext->colorSpaceInfo().refColorSpace(), 155 &this->props())); 156 fRenderTargetContext = nullptr; 157 return tmp; 158 } 159 160private: 161 sk_sp<GrRenderTargetContext> fRenderTargetContext; 162 163 typedef SkSpecialSurface_Base INHERITED; 164}; 165 166sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRenderTarget(GrContext* context, 167 int width, int height, 168 GrPixelConfig config, 169 sk_sp<SkColorSpace> colorSpace) { 170 if (!context) { 171 return nullptr; 172 } 173 174 sk_sp<GrRenderTargetContext> renderTargetContext(context->makeDeferredRenderTargetContext( 175 SkBackingFit::kApprox, width, height, config, std::move(colorSpace))); 176 if (!renderTargetContext) { 177 return nullptr; 178 } 179 180 const SkIRect subset = SkIRect::MakeWH(width, height); 181 182 return sk_make_sp<SkSpecialSurface_Gpu>(context, std::move(renderTargetContext), 183 width, height, subset); 184} 185 186#endif 187