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