• 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,ContentChangeMode,TextureReleaseProc,ReleaseContext)84 bool SkSurface_Base::onReplaceBackendTexture(const GrBackendTexture&,
85                                              GrSurfaceOrigin, ContentChangeMode,
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);
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);
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     size_t rowBytes = info.minRowBytes();
199     std::unique_ptr<char[]> data(new char[info.height() * rowBytes]);
200     SkPixmap pm(info, data.get(), rowBytes);
201     if (src->readPixels(pm, srcX, srcY)) {
202         class Result : public AsyncReadResult {
203         public:
204             Result(std::unique_ptr<const char[]> data, size_t rowBytes)
205                     : fData(std::move(data)), fRowBytes(rowBytes) {}
206             int count() const override { return 1; }
207             const void* data(int i) const override { return fData.get(); }
208             size_t rowBytes(int i) const override { return fRowBytes; }
209 
210         private:
211             std::unique_ptr<const char[]> fData;
212             size_t fRowBytes;
213         };
214         callback(context, std::make_unique<Result>(std::move(data), rowBytes));
215     } else {
216         callback(context, nullptr);
217     }
218 }
219 
onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,sk_sp<SkColorSpace> dstColorSpace,const SkIRect & srcRect,const SkISize & dstSize,RescaleGamma rescaleGamma,SkFilterQuality rescaleQuality,ReadPixelsCallback callback,ReadPixelsContext context)220 void SkSurface_Base::onAsyncRescaleAndReadPixelsYUV420(
221         SkYUVColorSpace yuvColorSpace, sk_sp<SkColorSpace> dstColorSpace, const SkIRect& srcRect,
222         const SkISize& dstSize, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality,
223         ReadPixelsCallback callback, ReadPixelsContext context) {
224     // TODO: Call non-YUV asyncRescaleAndReadPixels and then make our callback convert to YUV and
225     // call client's callback.
226     callback(context, nullptr);
227 }
228 
outstandingImageSnapshot() const229 bool SkSurface_Base::outstandingImageSnapshot() const {
230     return fCachedImage && !fCachedImage->unique();
231 }
232 
aboutToDraw(ContentChangeMode mode)233 void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
234     this->dirtyGenerationID();
235 
236     SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
237 
238     if (fCachedImage) {
239         // the surface may need to fork its backend, if its sharing it with
240         // the cached image. Note: we only call if there is an outstanding owner
241         // on the image (besides us).
242         bool unique = fCachedImage->unique();
243         if (!unique) {
244             this->onCopyOnWrite(mode);
245         }
246 
247         // regardless of copy-on-write, we must drop our cached image now, so
248         // that the next request will get our new contents.
249         fCachedImage.reset();
250 
251         if (unique) {
252             // Our content isn't held by any image now, so we can consider that content mutable.
253             // Raster surfaces need to be told it's safe to consider its pixels mutable again.
254             // We make this call after the ->unref() so the subclass can assert there are no images.
255             this->onRestoreBackingMutability();
256         }
257     } else if (kDiscard_ContentChangeMode == mode) {
258         this->onDiscard();
259     }
260 }
261 
newGenerationID()262 uint32_t SkSurface_Base::newGenerationID() {
263     SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
264     static std::atomic<uint32_t> nextID{1};
265     return nextID++;
266 }
267 
asSB(SkSurface * surface)268 static SkSurface_Base* asSB(SkSurface* surface) {
269     return static_cast<SkSurface_Base*>(surface);
270 }
271 
asConstSB(const SkSurface * surface)272 static const SkSurface_Base* asConstSB(const SkSurface* surface) {
273     return static_cast<const SkSurface_Base*>(surface);
274 }
275 
276 ///////////////////////////////////////////////////////////////////////////////
277 
SkSurface(int width,int height,const SkSurfaceProps * props)278 SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
279     : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
280 {
281     SkASSERT(fWidth > 0);
282     SkASSERT(fHeight > 0);
283     fGenerationID = 0;
284 }
285 
SkSurface(const SkImageInfo & info,const SkSurfaceProps * props)286 SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
287     : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
288 {
289     SkASSERT(fWidth > 0);
290     SkASSERT(fHeight > 0);
291     fGenerationID = 0;
292 }
293 
imageInfo()294 SkImageInfo SkSurface::imageInfo() {
295     // TODO: do we need to go through canvas for this?
296     return this->getCanvas()->imageInfo();
297 }
298 
generationID()299 uint32_t SkSurface::generationID() {
300     if (0 == fGenerationID) {
301         fGenerationID = asSB(this)->newGenerationID();
302     }
303     return fGenerationID;
304 }
305 
notifyContentWillChange(ContentChangeMode mode)306 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
307     asSB(this)->aboutToDraw(mode);
308 }
309 
getCanvas()310 SkCanvas* SkSurface::getCanvas() {
311     return asSB(this)->getCachedCanvas();
312 }
313 
makeImageSnapshot()314 sk_sp<SkImage> SkSurface::makeImageSnapshot() {
315     return asSB(this)->refCachedImage();
316 }
317 
makeImageSnapshot(const SkIRect & srcBounds)318 sk_sp<SkImage> SkSurface::makeImageSnapshot(const SkIRect& srcBounds) {
319     const SkIRect surfBounds = { 0, 0, fWidth, fHeight };
320     SkIRect bounds = srcBounds;
321     if (!bounds.intersect(surfBounds)) {
322         return nullptr;
323     }
324     SkASSERT(!bounds.isEmpty());
325     if (bounds == surfBounds) {
326         return this->makeImageSnapshot();
327     } else {
328         return asSB(this)->onNewImageSnapshot(&bounds);
329     }
330 }
331 
makeSurface(const SkImageInfo & info)332 sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
333     return asSB(this)->onNewSurface(info);
334 }
335 
makeSurface(int width,int height)336 sk_sp<SkSurface> SkSurface::makeSurface(int width, int height) {
337     return this->makeSurface(this->imageInfo().makeWH(width, height));
338 }
339 
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)340 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
341                      const SkPaint* paint) {
342     return asSB(this)->onDraw(canvas, x, y, paint);
343 }
344 
peekPixels(SkPixmap * pmap)345 bool SkSurface::peekPixels(SkPixmap* pmap) {
346     return this->getCanvas()->peekPixels(pmap);
347 }
348 
readPixels(const SkPixmap & pm,int srcX,int srcY)349 bool SkSurface::readPixels(const SkPixmap& pm, int srcX, int srcY) {
350     return this->getCanvas()->readPixels(pm, srcX, srcY);
351 }
352 
readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY)353 bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
354                            int srcX, int srcY) {
355     return this->readPixels({dstInfo, dstPixels, dstRowBytes}, srcX, srcY);
356 }
357 
readPixels(const SkBitmap & bitmap,int srcX,int srcY)358 bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) {
359     SkPixmap pm;
360     return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY);
361 }
362 
asyncRescaleAndReadPixels(const SkImageInfo & info,const SkIRect & srcRect,RescaleGamma rescaleGamma,SkFilterQuality rescaleQuality,ReadPixelsCallback callback,ReadPixelsContext context)363 void SkSurface::asyncRescaleAndReadPixels(const SkImageInfo& info,
364                                           const SkIRect& srcRect,
365                                           RescaleGamma rescaleGamma,
366                                           SkFilterQuality rescaleQuality,
367                                           ReadPixelsCallback callback,
368                                           ReadPixelsContext context) {
369     if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) ||
370         !SkImageInfoIsValid(info)) {
371         callback(context, nullptr);
372         return;
373     }
374     asSB(this)->onAsyncRescaleAndReadPixels(
375             info, srcRect, rescaleGamma, rescaleQuality, callback, context);
376 }
377 
asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,sk_sp<SkColorSpace> dstColorSpace,const SkIRect & srcRect,const SkISize & dstSize,RescaleGamma rescaleGamma,SkFilterQuality rescaleQuality,ReadPixelsCallback callback,ReadPixelsContext context)378 void SkSurface::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
379                                                 sk_sp<SkColorSpace> dstColorSpace,
380                                                 const SkIRect& srcRect,
381                                                 const SkISize& dstSize,
382                                                 RescaleGamma rescaleGamma,
383                                                 SkFilterQuality rescaleQuality,
384                                                 ReadPixelsCallback callback,
385                                                 ReadPixelsContext context) {
386     if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) || dstSize.isZero() ||
387         (dstSize.width() & 0b1) || (dstSize.height() & 0b1)) {
388         callback(context, nullptr);
389         return;
390     }
391     asSB(this)->onAsyncRescaleAndReadPixelsYUV420(yuvColorSpace,
392                                                   std::move(dstColorSpace),
393                                                   srcRect,
394                                                   dstSize,
395                                                   rescaleGamma,
396                                                   rescaleQuality,
397                                                   callback,
398                                                   context);
399 }
400 
writePixels(const SkPixmap & pmap,int x,int y)401 void SkSurface::writePixels(const SkPixmap& pmap, int x, int y) {
402     if (pmap.addr() == nullptr || pmap.width() <= 0 || pmap.height() <= 0) {
403         return;
404     }
405 
406     const SkIRect srcR = SkIRect::MakeXYWH(x, y, pmap.width(), pmap.height());
407     const SkIRect dstR = SkIRect::MakeWH(this->width(), this->height());
408     if (SkIRect::Intersects(srcR, dstR)) {
409         ContentChangeMode mode = kRetain_ContentChangeMode;
410         if (srcR.contains(dstR)) {
411             mode = kDiscard_ContentChangeMode;
412         }
413         asSB(this)->aboutToDraw(mode);
414         asSB(this)->onWritePixels(pmap, x, y);
415     }
416 }
417 
writePixels(const SkBitmap & src,int x,int y)418 void SkSurface::writePixels(const SkBitmap& src, int x, int y) {
419     SkPixmap pm;
420     if (src.peekPixels(&pm)) {
421         this->writePixels(pm, x, y);
422     }
423 }
424 
getBackendTexture(BackendHandleAccess access)425 GrBackendTexture SkSurface::getBackendTexture(BackendHandleAccess access) {
426     return asSB(this)->onGetBackendTexture(access);
427 }
428 
getBackendRenderTarget(BackendHandleAccess access)429 GrBackendRenderTarget SkSurface::getBackendRenderTarget(BackendHandleAccess access) {
430     return asSB(this)->onGetBackendRenderTarget(access);
431 }
432 
replaceBackendTexture(const GrBackendTexture & backendTexture,GrSurfaceOrigin origin,ContentChangeMode mode,TextureReleaseProc textureReleaseProc,ReleaseContext releaseContext)433 bool SkSurface::replaceBackendTexture(const GrBackendTexture& backendTexture,
434                                       GrSurfaceOrigin origin, ContentChangeMode mode,
435                                       TextureReleaseProc textureReleaseProc,
436                                       ReleaseContext releaseContext) {
437     return asSB(this)->onReplaceBackendTexture(backendTexture, origin, mode, textureReleaseProc,
438                                                releaseContext);
439 }
440 
flush()441 void SkSurface::flush() {
442     this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
443 }
444 
flush(BackendSurfaceAccess access,const GrFlushInfo & flushInfo)445 GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, const GrFlushInfo& flushInfo) {
446     return asSB(this)->onFlush(access, flushInfo);
447 }
448 
flush(BackendSurfaceAccess access,GrFlushFlags flags,int numSemaphores,GrBackendSemaphore signalSemaphores[],GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)449 GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, GrFlushFlags flags,
450                                        int numSemaphores, GrBackendSemaphore signalSemaphores[],
451                                        GrGpuFinishedProc finishedProc,
452                                        GrGpuFinishedContext finishedContext) {
453     GrFlushInfo info;
454     info.fFlags = flags;
455     info.fNumSemaphores = numSemaphores;
456     info.fSignalSemaphores = signalSemaphores;
457     info.fFinishedProc = finishedProc;
458     info.fFinishedContext = finishedContext;
459     return this->flush(access, info);
460 }
461 
flush(BackendSurfaceAccess access,FlushFlags flags,int numSemaphores,GrBackendSemaphore signalSemaphores[])462 GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, FlushFlags flags,
463                                        int numSemaphores, GrBackendSemaphore signalSemaphores[]) {
464     GrFlushFlags grFlags = flags == kSyncCpu_FlushFlag ? kSyncCpu_GrFlushFlag : kNone_GrFlushFlags;
465     GrFlushInfo info;
466     info.fFlags = grFlags;
467     info.fNumSemaphores = numSemaphores;
468     info.fSignalSemaphores = signalSemaphores;
469     return this->flush(access, info);
470 }
471 
flushAndSignalSemaphores(int numSemaphores,GrBackendSemaphore signalSemaphores[])472 GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores,
473                                                           GrBackendSemaphore signalSemaphores[]) {
474     GrFlushInfo info;
475     info.fNumSemaphores = numSemaphores;
476     info.fSignalSemaphores = signalSemaphores;
477     return this->flush(BackendSurfaceAccess::kNoAccess, info);
478 }
479 
wait(int numSemaphores,const GrBackendSemaphore * waitSemaphores)480 bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
481     return asSB(this)->onWait(numSemaphores, waitSemaphores);
482 }
483 
characterize(SkSurfaceCharacterization * characterization) const484 bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const {
485     return asConstSB(this)->onCharacterize(characterization);
486 }
487 
isCompatible(const SkSurfaceCharacterization & characterization) const488 bool SkSurface::isCompatible(const SkSurfaceCharacterization& characterization) const {
489     return asConstSB(this)->onIsCompatible(characterization);
490 }
491 
draw(SkDeferredDisplayList * ddl)492 bool SkSurface::draw(SkDeferredDisplayList* ddl) {
493     return asSB(this)->onDraw(ddl);
494 }
495 
496 //////////////////////////////////////////////////////////////////////////////////////
497 #include "include/utils/SkNoDrawCanvas.h"
498 
499 class SkNullSurface : public SkSurface_Base {
500 public:
SkNullSurface(int width,int height)501     SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {}
502 
503 protected:
onNewCanvas()504     SkCanvas* onNewCanvas() override {
505         return new SkNoDrawCanvas(this->width(), this->height());
506     }
onNewSurface(const SkImageInfo & info)507     sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override {
508         return MakeNull(info.width(), info.height());
509     }
onNewImageSnapshot(const SkIRect * subsetOrNull)510     sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subsetOrNull) override { return nullptr; }
onWritePixels(const SkPixmap &,int x,int y)511     void onWritePixels(const SkPixmap&, int x, int y) override {}
onDraw(SkCanvas *,SkScalar x,SkScalar y,const SkPaint *)512     void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
onCopyOnWrite(ContentChangeMode)513     void onCopyOnWrite(ContentChangeMode) override {}
514 };
515 
MakeNull(int width,int height)516 sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {
517     if (width < 1 || height < 1) {
518         return nullptr;
519     }
520     return sk_sp<SkSurface>(new SkNullSurface(width, height));
521 }
522 
523 //////////////////////////////////////////////////////////////////////////////////////
524 
525 #if !SK_SUPPORT_GPU
526 
MakeRenderTarget(GrContext *,SkBudgeted,const SkImageInfo &,int,GrSurfaceOrigin,const SkSurfaceProps *,bool)527 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int,
528                                              GrSurfaceOrigin, const SkSurfaceProps*, bool) {
529     return nullptr;
530 }
531 
MakeRenderTarget(GrRecordingContext *,const SkSurfaceCharacterization &,SkBudgeted)532 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext*, const SkSurfaceCharacterization&,
533                                              SkBudgeted) {
534     return nullptr;
535 }
536 
MakeFromBackendTexture(GrContext *,const GrBackendTexture &,GrSurfaceOrigin origin,int sampleCnt,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *,TextureReleaseProc,ReleaseContext)537 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
538                                                    GrSurfaceOrigin origin, int sampleCnt,
539                                                    SkColorType, sk_sp<SkColorSpace>,
540                                                    const SkSurfaceProps*,
541                                                    TextureReleaseProc, ReleaseContext) {
542     return nullptr;
543 }
544 
MakeFromBackendRenderTarget(GrContext *,const GrBackendRenderTarget &,GrSurfaceOrigin origin,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *,RenderTargetReleaseProc,ReleaseContext)545 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
546                                                         const GrBackendRenderTarget&,
547                                                         GrSurfaceOrigin origin,
548                                                         SkColorType,
549                                                         sk_sp<SkColorSpace>,
550                                                         const SkSurfaceProps*,
551                                                         RenderTargetReleaseProc, ReleaseContext) {
552     return nullptr;
553 }
554 
MakeFromBackendTextureAsRenderTarget(GrContext *,const GrBackendTexture &,GrSurfaceOrigin origin,int sampleCnt,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *)555 sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
556                                                                  const GrBackendTexture&,
557                                                                  GrSurfaceOrigin origin,
558                                                                  int sampleCnt,
559                                                                  SkColorType,
560                                                                  sk_sp<SkColorSpace>,
561                                                                  const SkSurfaceProps*) {
562     return nullptr;
563 }
564 
565 #endif
566