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