• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 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 <atomic>
9 #include <cmath>
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkFontLCDConfig.h"
12 #include "include/gpu/GrBackendSurface.h"
13 #include "src/core/SkAutoPixmapStorage.h"
14 #include "src/core/SkImagePriv.h"
15 #include "src/image/SkSurface_Base.h"
16 
compute_default_geometry()17 static SkPixelGeometry compute_default_geometry() {
18     SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder();
19     if (SkFontLCDConfig::kNONE_LCDOrder == order) {
20         return kUnknown_SkPixelGeometry;
21     } else {
22         // Bit0 is RGB(0), BGR(1)
23         // Bit1 is H(0), V(1)
24         const SkPixelGeometry gGeo[] = {
25             kRGB_H_SkPixelGeometry,
26             kBGR_H_SkPixelGeometry,
27             kRGB_V_SkPixelGeometry,
28             kBGR_V_SkPixelGeometry,
29         };
30         int index = 0;
31         if (SkFontLCDConfig::kBGR_LCDOrder == order) {
32             index |= 1;
33         }
34         if (SkFontLCDConfig::kVertical_LCDOrientation == SkFontLCDConfig::GetSubpixelOrientation()){
35             index |= 2;
36         }
37         return gGeo[index];
38     }
39 }
40 
SkSurfaceProps()41 SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
42 
SkSurfaceProps(InitType)43 SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
44 
SkSurfaceProps(uint32_t flags,InitType)45 SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
46     : fFlags(flags)
47     , fPixelGeometry(compute_default_geometry())
48 {}
49 
SkSurfaceProps(uint32_t flags,SkPixelGeometry pg)50 SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
51     : fFlags(flags), fPixelGeometry(pg)
52 {}
53 
SkSurfaceProps(const SkSurfaceProps & other)54 SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
55     : fFlags(other.fFlags)
56     , fPixelGeometry(other.fPixelGeometry)
57 {}
58 
59 ///////////////////////////////////////////////////////////////////////////////
60 
SkSurface_Base(int width,int height,const SkSurfaceProps * props)61 SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
62     : INHERITED(width, height, props) {
63 }
64 
SkSurface_Base(const SkImageInfo & info,const SkSurfaceProps * props)65 SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
66     : INHERITED(info, props) {
67 }
68 
~SkSurface_Base()69 SkSurface_Base::~SkSurface_Base() {
70     // in case the canvas outsurvives us, we null the callback
71     if (fCachedCanvas) {
72         fCachedCanvas->setSurfaceBase(nullptr);
73     }
74 }
75 
onGetBackendTexture(BackendHandleAccess)76 GrBackendTexture SkSurface_Base::onGetBackendTexture(BackendHandleAccess) {
77     return GrBackendTexture(); // invalid
78 }
79 
onGetBackendRenderTarget(BackendHandleAccess)80 GrBackendRenderTarget SkSurface_Base::onGetBackendRenderTarget(BackendHandleAccess) {
81     return GrBackendRenderTarget(); // invalid
82 }
83 
onReplaceBackendTexture(const GrBackendTexture &,GrSurfaceOrigin,TextureReleaseProc,ReleaseContext)84 bool SkSurface_Base::onReplaceBackendTexture(const GrBackendTexture&,
85                                              GrSurfaceOrigin,
86                                              TextureReleaseProc,
87                                              ReleaseContext) {
88     return false;
89 }
90 
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)91 void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
92     auto image = this->makeImageSnapshot();
93     if (image) {
94         canvas->drawImage(image, x, y, paint);
95     }
96 }
97 
onAsyncRescaleAndReadPixels(const SkImageInfo & info,const SkIRect & srcRect,SkSurface::RescaleGamma rescaleGamma,SkFilterQuality rescaleQuality,SkSurface::ReadPixelsCallback callback,SkSurface::ReadPixelsContext context)98 void SkSurface_Base::onAsyncRescaleAndReadPixels(const SkImageInfo& info, const SkIRect& srcRect,
99                                                  SkSurface::RescaleGamma rescaleGamma,
100                                                  SkFilterQuality rescaleQuality,
101                                                  SkSurface::ReadPixelsCallback callback,
102                                                  SkSurface::ReadPixelsContext context) {
103     int srcW = srcRect.width();
104     int srcH = srcRect.height();
105     float sx = (float)info.width() / srcW;
106     float sy = (float)info.height() / srcH;
107     // How many bilerp/bicubic steps to do in X and Y. + means upscaling, - means downscaling.
108     int stepsX;
109     int stepsY;
110     if (rescaleQuality > kNone_SkFilterQuality) {
111         stepsX = static_cast<int>((sx > 1.f) ? std::ceil(std::log2f(sx))
112                                              : std::floor(std::log2f(sx)));
113         stepsY = static_cast<int>((sy > 1.f) ? std::ceil(std::log2f(sy))
114                                              : std::floor(std::log2f(sy)));
115     } else {
116         stepsX = sx != 1.f;
117         stepsY = sy != 1.f;
118     }
119 
120     SkPaint paint;
121     paint.setBlendMode(SkBlendMode::kSrc);
122     if (stepsX < 0 || stepsY < 0) {
123         // Don't trigger MIP generation. We don't currently have a way to trigger bicubic for
124         // downscaling draws.
125         rescaleQuality = std::min(rescaleQuality, kLow_SkFilterQuality);
126     }
127     paint.setFilterQuality(rescaleQuality);
128     sk_sp<SkSurface> src(SkRef(this));
129     int srcX = srcRect.fLeft;
130     int srcY = srcRect.fTop;
131     SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
132     // Assume we should ignore the rescale linear request if the surface has no color space since
133     // it's unclear how we'd linearize from an unknown color space.
134     if (rescaleGamma == SkSurface::RescaleGamma::kLinear &&
135         this->getCanvas()->imageInfo().colorSpace() &&
136         !this->getCanvas()->imageInfo().colorSpace()->gammaIsLinear()) {
137         auto cs = this->getCanvas()->imageInfo().colorSpace()->makeLinearGamma();
138         // Promote to F16 color type to preserve precision.
139         auto ii = SkImageInfo::Make(srcW, srcH, kRGBA_F16_SkColorType,
140                                     this->getCanvas()->imageInfo().alphaType(), std::move(cs));
141         auto linearSurf = this->makeSurface(ii);
142         if (!linearSurf) {
143             // Maybe F16 isn't supported? Try again with original color type.
144             ii = ii.makeColorType(this->getCanvas()->imageInfo().colorType());
145             linearSurf = this->makeSurface(ii);
146             if (!linearSurf) {
147                 callback(context, nullptr, 0);
148                 return;
149             }
150         }
151         this->draw(linearSurf->getCanvas(), -srcX, -srcY, &paint);
152         src = std::move(linearSurf);
153         srcX = 0;
154         srcY = 0;
155         constraint = SkCanvas::kFast_SrcRectConstraint;
156     }
157     while (stepsX || stepsY) {
158         int nextW = info.width();
159         int nextH = info.height();
160         if (stepsX < 0) {
161             nextW = info.width() << (-stepsX - 1);
162             stepsX++;
163         } else if (stepsX != 0) {
164             if (stepsX > 1) {
165                 nextW = srcW * 2;
166             }
167             --stepsX;
168         }
169         if (stepsY < 0) {
170             nextH = info.height() << (-stepsY - 1);
171             stepsY++;
172         } else if (stepsY != 0) {
173             if (stepsY > 1) {
174                 nextH = srcH * 2;
175             }
176             --stepsY;
177         }
178         auto ii = src->getCanvas()->imageInfo().makeWH(nextW, nextH);
179         if (!stepsX && !stepsY) {
180             // Might as well fold conversion to final info in the last step.
181             ii = info;
182         }
183         auto next = this->makeSurface(ii);
184         if (!next) {
185             callback(context, nullptr, 0);
186             return;
187         }
188         next->getCanvas()->drawImageRect(
189                 src->makeImageSnapshot(), SkIRect::MakeXYWH(srcX, srcY, srcW, srcH),
190                 SkRect::MakeWH((float)nextW, (float)nextH), &paint, constraint);
191         src = std::move(next);
192         srcX = srcY = 0;
193         srcW = nextW;
194         srcH = nextH;
195         constraint = SkCanvas::kFast_SrcRectConstraint;
196     }
197 
198     SkAutoPixmapStorage pm;
199     pm.alloc(info);
200     if (src->readPixels(pm, srcX, srcY)) {
201         callback(context, pm.addr(), pm.rowBytes());
202     } else {
203         callback(context, nullptr, 0);
204     }
205 }
206 
onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,sk_sp<SkColorSpace> dstColorSpace,const SkIRect & srcRect,int dstW,int dstH,RescaleGamma rescaleGamma,SkFilterQuality rescaleQuality,ReadPixelsCallbackYUV420 callback,ReadPixelsContext context)207 void SkSurface_Base::onAsyncRescaleAndReadPixelsYUV420(
208         SkYUVColorSpace yuvColorSpace, sk_sp<SkColorSpace> dstColorSpace, const SkIRect& srcRect,
209         int dstW, int dstH, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality,
210         ReadPixelsCallbackYUV420 callback, ReadPixelsContext context) {
211     // TODO: Call non-YUV asyncRescaleAndReadPixels and then make our callback convert to YUV and
212     // call client's callback.
213     callback(context, nullptr, nullptr);
214 }
215 
outstandingImageSnapshot() const216 bool SkSurface_Base::outstandingImageSnapshot() const {
217     return fCachedImage && !fCachedImage->unique();
218 }
219 
aboutToDraw(ContentChangeMode mode)220 void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
221     this->dirtyGenerationID();
222 
223     SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
224 
225     if (fCachedImage) {
226         // the surface may need to fork its backend, if its sharing it with
227         // the cached image. Note: we only call if there is an outstanding owner
228         // on the image (besides us).
229         bool unique = fCachedImage->unique();
230         if (!unique) {
231             this->onCopyOnWrite(mode);
232         }
233 
234         // regardless of copy-on-write, we must drop our cached image now, so
235         // that the next request will get our new contents.
236         fCachedImage.reset();
237 
238         if (unique) {
239             // Our content isn't held by any image now, so we can consider that content mutable.
240             // Raster surfaces need to be told it's safe to consider its pixels mutable again.
241             // We make this call after the ->unref() so the subclass can assert there are no images.
242             this->onRestoreBackingMutability();
243         }
244     } else if (kDiscard_ContentChangeMode == mode) {
245         this->onDiscard();
246     }
247 }
248 
newGenerationID()249 uint32_t SkSurface_Base::newGenerationID() {
250     SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
251     static std::atomic<uint32_t> nextID{1};
252     return nextID++;
253 }
254 
asSB(SkSurface * surface)255 static SkSurface_Base* asSB(SkSurface* surface) {
256     return static_cast<SkSurface_Base*>(surface);
257 }
258 
asConstSB(const SkSurface * surface)259 static const SkSurface_Base* asConstSB(const SkSurface* surface) {
260     return static_cast<const SkSurface_Base*>(surface);
261 }
262 
263 ///////////////////////////////////////////////////////////////////////////////
264 
SkSurface(int width,int height,const SkSurfaceProps * props)265 SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
266     : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
267 {
268     SkASSERT(fWidth > 0);
269     SkASSERT(fHeight > 0);
270     fGenerationID = 0;
271 }
272 
SkSurface(const SkImageInfo & info,const SkSurfaceProps * props)273 SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
274     : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
275 {
276     SkASSERT(fWidth > 0);
277     SkASSERT(fHeight > 0);
278     fGenerationID = 0;
279 }
280 
imageInfo()281 SkImageInfo SkSurface::imageInfo() {
282     // TODO: do we need to go through canvas for this?
283     return this->getCanvas()->imageInfo();
284 }
285 
generationID()286 uint32_t SkSurface::generationID() {
287     if (0 == fGenerationID) {
288         fGenerationID = asSB(this)->newGenerationID();
289     }
290     return fGenerationID;
291 }
292 
notifyContentWillChange(ContentChangeMode mode)293 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
294     asSB(this)->aboutToDraw(mode);
295 }
296 
getCanvas()297 SkCanvas* SkSurface::getCanvas() {
298     return asSB(this)->getCachedCanvas();
299 }
300 
makeImageSnapshot()301 sk_sp<SkImage> SkSurface::makeImageSnapshot() {
302     return asSB(this)->refCachedImage();
303 }
304 
makeImageSnapshot(const SkIRect & srcBounds)305 sk_sp<SkImage> SkSurface::makeImageSnapshot(const SkIRect& srcBounds) {
306     const SkIRect surfBounds = { 0, 0, fWidth, fHeight };
307     SkIRect bounds = srcBounds;
308     if (!bounds.intersect(surfBounds)) {
309         return nullptr;
310     }
311     SkASSERT(!bounds.isEmpty());
312     if (bounds == surfBounds) {
313         return this->makeImageSnapshot();
314     } else {
315         return asSB(this)->onNewImageSnapshot(&bounds);
316     }
317 }
318 
makeSurface(const SkImageInfo & info)319 sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
320     return asSB(this)->onNewSurface(info);
321 }
322 
makeSurface(int width,int height)323 sk_sp<SkSurface> SkSurface::makeSurface(int width, int height) {
324     return this->makeSurface(this->imageInfo().makeWH(width, height));
325 }
326 
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)327 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
328                      const SkPaint* paint) {
329     return asSB(this)->onDraw(canvas, x, y, paint);
330 }
331 
peekPixels(SkPixmap * pmap)332 bool SkSurface::peekPixels(SkPixmap* pmap) {
333     return this->getCanvas()->peekPixels(pmap);
334 }
335 
readPixels(const SkPixmap & pm,int srcX,int srcY)336 bool SkSurface::readPixels(const SkPixmap& pm, int srcX, int srcY) {
337     return this->getCanvas()->readPixels(pm, srcX, srcY);
338 }
339 
readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY)340 bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
341                            int srcX, int srcY) {
342     return this->readPixels({dstInfo, dstPixels, dstRowBytes}, srcX, srcY);
343 }
344 
readPixels(const SkBitmap & bitmap,int srcX,int srcY)345 bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) {
346     SkPixmap pm;
347     return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY);
348 }
349 
asyncRescaleAndReadPixels(const SkImageInfo & info,const SkIRect & srcRect,RescaleGamma rescaleGamma,SkFilterQuality rescaleQuality,ReadPixelsCallback callback,ReadPixelsContext context)350 void SkSurface::asyncRescaleAndReadPixels(const SkImageInfo& info, const SkIRect& srcRect,
351                                           RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality,
352                                           ReadPixelsCallback callback, ReadPixelsContext context) {
353     if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) ||
354         !SkImageInfoIsValid(info)) {
355         callback(context, nullptr, 0);
356         return;
357     }
358     asSB(this)->onAsyncRescaleAndReadPixels(info, srcRect, rescaleGamma, rescaleQuality, callback,
359                                             context);
360 }
361 
asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,sk_sp<SkColorSpace> dstColorSpace,const SkIRect & srcRect,int dstW,int dstH,RescaleGamma rescaleGamma,SkFilterQuality rescaleQuality,ReadPixelsCallbackYUV420 callback,ReadPixelsContext context)362 void SkSurface::asyncRescaleAndReadPixelsYUV420(
363         SkYUVColorSpace yuvColorSpace, sk_sp<SkColorSpace> dstColorSpace, const SkIRect& srcRect,
364         int dstW, int dstH, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality,
365         ReadPixelsCallbackYUV420 callback, ReadPixelsContext context) {
366     if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) || (dstW & 0b1) ||
367         (dstH & 0b1)) {
368         callback(context, nullptr, nullptr);
369         return;
370     }
371     asSB(this)->onAsyncRescaleAndReadPixelsYUV420(yuvColorSpace, std::move(dstColorSpace), srcRect,
372                                                   dstW, dstH, rescaleGamma, rescaleQuality,
373                                                   callback, context);
374 }
375 
writePixels(const SkPixmap & pmap,int x,int y)376 void SkSurface::writePixels(const SkPixmap& pmap, int x, int y) {
377     if (pmap.addr() == nullptr || pmap.width() <= 0 || pmap.height() <= 0) {
378         return;
379     }
380 
381     const SkIRect srcR = SkIRect::MakeXYWH(x, y, pmap.width(), pmap.height());
382     const SkIRect dstR = SkIRect::MakeWH(this->width(), this->height());
383     if (SkIRect::Intersects(srcR, dstR)) {
384         ContentChangeMode mode = kRetain_ContentChangeMode;
385         if (srcR.contains(dstR)) {
386             mode = kDiscard_ContentChangeMode;
387         }
388         asSB(this)->aboutToDraw(mode);
389         asSB(this)->onWritePixels(pmap, x, y);
390     }
391 }
392 
writePixels(const SkBitmap & src,int x,int y)393 void SkSurface::writePixels(const SkBitmap& src, int x, int y) {
394     SkPixmap pm;
395     if (src.peekPixels(&pm)) {
396         this->writePixels(pm, x, y);
397     }
398 }
399 
getBackendTexture(BackendHandleAccess access)400 GrBackendTexture SkSurface::getBackendTexture(BackendHandleAccess access) {
401     return asSB(this)->onGetBackendTexture(access);
402 }
403 
getBackendRenderTarget(BackendHandleAccess access)404 GrBackendRenderTarget SkSurface::getBackendRenderTarget(BackendHandleAccess access) {
405     return asSB(this)->onGetBackendRenderTarget(access);
406 }
407 
replaceBackendTexture(const GrBackendTexture & backendTexture,GrSurfaceOrigin origin,TextureReleaseProc textureReleaseProc,ReleaseContext releaseContext)408 bool SkSurface::replaceBackendTexture(const GrBackendTexture& backendTexture,
409                                       GrSurfaceOrigin origin,
410                                       TextureReleaseProc textureReleaseProc,
411                                       ReleaseContext releaseContext) {
412     return asSB(this)->onReplaceBackendTexture(backendTexture, origin, textureReleaseProc,
413                                                releaseContext);
414 }
415 
flush()416 void SkSurface::flush() {
417     this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
418 }
419 
flush(BackendSurfaceAccess access,const GrFlushInfo & flushInfo)420 GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, const GrFlushInfo& flushInfo) {
421     return asSB(this)->onFlush(access, flushInfo);
422 }
423 
flush(BackendSurfaceAccess access,GrFlushFlags flags,int numSemaphores,GrBackendSemaphore signalSemaphores[],GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)424 GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, GrFlushFlags flags,
425                                        int numSemaphores, GrBackendSemaphore signalSemaphores[],
426                                        GrGpuFinishedProc finishedProc,
427                                        GrGpuFinishedContext finishedContext) {
428     GrFlushInfo info;
429     info.fFlags = flags;
430     info.fNumSemaphores = numSemaphores;
431     info.fSignalSemaphores = signalSemaphores;
432     info.fFinishedProc = finishedProc;
433     info.fFinishedContext = finishedContext;
434     return this->flush(access, info);
435 }
436 
flush(BackendSurfaceAccess access,FlushFlags flags,int numSemaphores,GrBackendSemaphore signalSemaphores[])437 GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, FlushFlags flags,
438                                        int numSemaphores, GrBackendSemaphore signalSemaphores[]) {
439     GrFlushFlags grFlags = flags == kSyncCpu_FlushFlag ? kSyncCpu_GrFlushFlag : kNone_GrFlushFlags;
440     GrFlushInfo info;
441     info.fFlags = grFlags;
442     info.fNumSemaphores = numSemaphores;
443     info.fSignalSemaphores = signalSemaphores;
444     return this->flush(access, info);
445 }
446 
flushAndSignalSemaphores(int numSemaphores,GrBackendSemaphore signalSemaphores[])447 GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores,
448                                                           GrBackendSemaphore signalSemaphores[]) {
449     GrFlushInfo info;
450     info.fNumSemaphores = numSemaphores;
451     info.fSignalSemaphores = signalSemaphores;
452     return this->flush(BackendSurfaceAccess::kNoAccess, info);
453 }
454 
wait(int numSemaphores,const GrBackendSemaphore * waitSemaphores)455 bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
456     return asSB(this)->onWait(numSemaphores, waitSemaphores);
457 }
458 
characterize(SkSurfaceCharacterization * characterization) const459 bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const {
460     return asConstSB(this)->onCharacterize(characterization);
461 }
462 
isCompatible(const SkSurfaceCharacterization & characterization) const463 bool SkSurface::isCompatible(const SkSurfaceCharacterization& characterization) const {
464     return asConstSB(this)->onIsCompatible(characterization);
465 }
466 
draw(SkDeferredDisplayList * ddl)467 bool SkSurface::draw(SkDeferredDisplayList* ddl) {
468     return asSB(this)->onDraw(ddl);
469 }
470 
471 //////////////////////////////////////////////////////////////////////////////////////
472 #include "include/utils/SkNoDrawCanvas.h"
473 
474 class SkNullSurface : public SkSurface_Base {
475 public:
SkNullSurface(int width,int height)476     SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {}
477 
478 protected:
onNewCanvas()479     SkCanvas* onNewCanvas() override {
480         return new SkNoDrawCanvas(this->width(), this->height());
481     }
onNewSurface(const SkImageInfo & info)482     sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override {
483         return MakeNull(info.width(), info.height());
484     }
onNewImageSnapshot(const SkIRect * subsetOrNull)485     sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subsetOrNull) override { return nullptr; }
onWritePixels(const SkPixmap &,int x,int y)486     void onWritePixels(const SkPixmap&, int x, int y) override {}
onDraw(SkCanvas *,SkScalar x,SkScalar y,const SkPaint *)487     void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
onCopyOnWrite(ContentChangeMode)488     void onCopyOnWrite(ContentChangeMode) override {}
489 };
490 
MakeNull(int width,int height)491 sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {
492     if (width < 1 || height < 1) {
493         return nullptr;
494     }
495     return sk_sp<SkSurface>(new SkNullSurface(width, height));
496 }
497 
498 //////////////////////////////////////////////////////////////////////////////////////
499 
500 #if !SK_SUPPORT_GPU
501 
MakeRenderTarget(GrContext *,SkBudgeted,const SkImageInfo &,int,GrSurfaceOrigin,const SkSurfaceProps *,bool)502 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int,
503                                              GrSurfaceOrigin, const SkSurfaceProps*, bool) {
504     return nullptr;
505 }
506 
MakeRenderTarget(GrRecordingContext *,const SkSurfaceCharacterization &,SkBudgeted)507 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext*, const SkSurfaceCharacterization&,
508                                              SkBudgeted) {
509     return nullptr;
510 }
511 
MakeFromBackendTexture(GrContext *,const GrBackendTexture &,GrSurfaceOrigin origin,int sampleCnt,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *,TextureReleaseProc,ReleaseContext)512 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
513                                                    GrSurfaceOrigin origin, int sampleCnt,
514                                                    SkColorType, sk_sp<SkColorSpace>,
515                                                    const SkSurfaceProps*,
516                                                    TextureReleaseProc, ReleaseContext) {
517     return nullptr;
518 }
519 
MakeFromBackendRenderTarget(GrContext *,const GrBackendRenderTarget &,GrSurfaceOrigin origin,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *,RenderTargetReleaseProc,ReleaseContext)520 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
521                                                         const GrBackendRenderTarget&,
522                                                         GrSurfaceOrigin origin,
523                                                         SkColorType,
524                                                         sk_sp<SkColorSpace>,
525                                                         const SkSurfaceProps*,
526                                                         RenderTargetReleaseProc, ReleaseContext) {
527     return nullptr;
528 }
529 
MakeFromBackendTextureAsRenderTarget(GrContext *,const GrBackendTexture &,GrSurfaceOrigin origin,int sampleCnt,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *)530 sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
531                                                                  const GrBackendTexture&,
532                                                                  GrSurfaceOrigin origin,
533                                                                  int sampleCnt,
534                                                                  SkColorType,
535                                                                  sk_sp<SkColorSpace>,
536                                                                  const SkSurfaceProps*) {
537     return nullptr;
538 }
539 
540 #endif
541