blob: 3a83b45a2a8e8551db6b9f7b25a70dbd47a3f86d [file] [log] [blame]
reed@google.comc9062042012-07-30 18:06:00 +00001/*
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
Brian Salomonab32f652019-05-10 14:24:50 -04008#include <atomic>
Brian Salomon201700f2019-05-17 12:05:44 -04009#include <cmath>
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkCanvas.h"
11#include "include/core/SkFontLCDConfig.h"
12#include "include/gpu/GrBackendSurface.h"
Brian Salomonab32f652019-05-10 14:24:50 -040013#include "src/core/SkAutoPixmapStorage.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/core/SkImagePriv.h"
15#include "src/image/SkSurface_Base.h"
Robert Phillips8caf85f2018-04-05 09:30:38 -040016
reed4a8126e2014-09-22 07:29:03 -070017static 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
41SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
42
43SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
44
45SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
46 : fFlags(flags)
47 , fPixelGeometry(compute_default_geometry())
48{}
49
50SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
51 : fFlags(flags), fPixelGeometry(pg)
52{}
53
reed4af267b2014-11-21 08:46:37 -080054SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
55 : fFlags(other.fFlags)
56 , fPixelGeometry(other.fPixelGeometry)
57{}
58
reed@google.com889b09e2012-07-27 21:10:42 +000059///////////////////////////////////////////////////////////////////////////////
60
reed4a8126e2014-09-22 07:29:03 -070061SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
Robert Phillipsa54ccb22017-01-31 07:40:33 -050062 : INHERITED(width, height, props) {
reed@google.com9ea5a3b2012-07-30 21:03:46 +000063}
reed@google.com889b09e2012-07-27 21:10:42 +000064
reed4a8126e2014-09-22 07:29:03 -070065SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
Robert Phillipsa54ccb22017-01-31 07:40:33 -050066 : INHERITED(info, props) {
reed@google.com1360c522014-01-08 21:25:26 +000067}
68
reed@google.com9ea5a3b2012-07-30 21:03:46 +000069SkSurface_Base::~SkSurface_Base() {
reed@google.com97af1a62012-08-28 12:19:02 +000070 // in case the canvas outsurvives us, we null the callback
71 if (fCachedCanvas) {
halcanary96fcdcc2015-08-27 07:41:13 -070072 fCachedCanvas->setSurfaceBase(nullptr);
reed@google.com97af1a62012-08-28 12:19:02 +000073 }
reed@google.com9ea5a3b2012-07-30 21:03:46 +000074}
reed@google.com889b09e2012-07-27 21:10:42 +000075
Robert Phillips8caf85f2018-04-05 09:30:38 -040076GrBackendTexture SkSurface_Base::onGetBackendTexture(BackendHandleAccess) {
77 return GrBackendTexture(); // invalid
78}
79
80GrBackendRenderTarget SkSurface_Base::onGetBackendRenderTarget(BackendHandleAccess) {
81 return GrBackendRenderTarget(); // invalid
82}
83
Brian Salomonaad83152019-05-24 10:16:35 -040084bool SkSurface_Base::onReplaceBackendTexture(const GrBackendTexture&,
85 GrSurfaceOrigin,
86 TextureReleaseProc,
87 ReleaseContext) {
88 return false;
89}
90
reed4a8126e2014-09-22 07:29:03 -070091void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
Robert Phillipsac6b1fa2017-03-20 08:38:50 -040092 auto image = this->makeImageSnapshot();
reed@google.com889b09e2012-07-27 21:10:42 +000093 if (image) {
piotaixrb5fae932014-09-24 13:03:30 -070094 canvas->drawImage(image, x, y, paint);
reed@google.com889b09e2012-07-27 21:10:42 +000095 }
96}
97
Brian Salomon031b0ba2019-05-23 11:05:26 -040098void 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
Brian Salomonab32f652019-05-10 14:24:50 -0400198 SkAutoPixmapStorage pm;
199 pm.alloc(info);
Brian Salomon031b0ba2019-05-23 11:05:26 -0400200 if (src->readPixels(pm, srcX, srcY)) {
Brian Salomonab32f652019-05-10 14:24:50 -0400201 callback(context, pm.addr(), pm.rowBytes());
202 } else {
203 callback(context, nullptr, 0);
204 }
205}
206
reedc83a2972015-07-16 07:40:45 -0700207bool SkSurface_Base::outstandingImageSnapshot() const {
208 return fCachedImage && !fCachedImage->unique();
209}
210
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000211void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
reed@google.com97af1a62012-08-28 12:19:02 +0000212 this->dirtyGenerationID();
213
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000214 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
reed@google.com97af1a62012-08-28 12:19:02 +0000215
bsalomon49f085d2014-09-05 13:34:00 -0700216 if (fCachedImage) {
reed@google.com97af1a62012-08-28 12:19:02 +0000217 // the surface may need to fork its backend, if its sharing it with
218 // the cached image. Note: we only call if there is an outstanding owner
219 // on the image (besides us).
reed26e0e582015-07-29 11:44:52 -0700220 bool unique = fCachedImage->unique();
221 if (!unique) {
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000222 this->onCopyOnWrite(mode);
reed@google.com97af1a62012-08-28 12:19:02 +0000223 }
224
225 // regardless of copy-on-write, we must drop our cached image now, so
226 // that the next request will get our new contents.
Robert Phillipsa54ccb22017-01-31 07:40:33 -0500227 fCachedImage.reset();
reed26e0e582015-07-29 11:44:52 -0700228
229 if (unique) {
230 // Our content isn't held by any image now, so we can consider that content mutable.
231 // Raster surfaces need to be told it's safe to consider its pixels mutable again.
232 // We make this call after the ->unref() so the subclass can assert there are no images.
233 this->onRestoreBackingMutability();
234 }
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000235 } else if (kDiscard_ContentChangeMode == mode) {
236 this->onDiscard();
reed@google.com97af1a62012-08-28 12:19:02 +0000237 }
238}
239
240uint32_t SkSurface_Base::newGenerationID() {
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000241 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
Mike Klein0ec1c572018-12-04 11:52:51 -0500242 static std::atomic<uint32_t> nextID{1};
243 return nextID++;
reed@google.com97af1a62012-08-28 12:19:02 +0000244}
245
reed@google.com889b09e2012-07-27 21:10:42 +0000246static SkSurface_Base* asSB(SkSurface* surface) {
247 return static_cast<SkSurface_Base*>(surface);
248}
249
250///////////////////////////////////////////////////////////////////////////////
251
reed4a8126e2014-09-22 07:29:03 -0700252SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
253 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
254{
reedb2497c22014-12-31 12:31:43 -0800255 SkASSERT(fWidth > 0);
256 SkASSERT(fHeight > 0);
reed@google.com1360c522014-01-08 21:25:26 +0000257 fGenerationID = 0;
258}
259
reed4a8126e2014-09-22 07:29:03 -0700260SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
261 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
262{
reedb2497c22014-12-31 12:31:43 -0800263 SkASSERT(fWidth > 0);
264 SkASSERT(fHeight > 0);
reed@google.com889b09e2012-07-27 21:10:42 +0000265 fGenerationID = 0;
266}
267
reed@google.com97af1a62012-08-28 12:19:02 +0000268uint32_t SkSurface::generationID() {
269 if (0 == fGenerationID) {
270 fGenerationID = asSB(this)->newGenerationID();
271 }
272 return fGenerationID;
273}
274
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000275void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
276 asSB(this)->aboutToDraw(mode);
reed@google.com97af1a62012-08-28 12:19:02 +0000277}
278
reed@google.com9ea5a3b2012-07-30 21:03:46 +0000279SkCanvas* SkSurface::getCanvas() {
280 return asSB(this)->getCachedCanvas();
reed@google.com889b09e2012-07-27 21:10:42 +0000281}
282
Robert Phillipsac6b1fa2017-03-20 08:38:50 -0400283sk_sp<SkImage> SkSurface::makeImageSnapshot() {
284 return asSB(this)->refCachedImage();
reed@google.com889b09e2012-07-27 21:10:42 +0000285}
286
Mike Reed114bde82018-11-21 09:12:09 -0500287sk_sp<SkImage> SkSurface::makeImageSnapshot(const SkIRect& srcBounds) {
288 const SkIRect surfBounds = { 0, 0, fWidth, fHeight };
289 SkIRect bounds = srcBounds;
290 if (!bounds.intersect(surfBounds)) {
291 return nullptr;
292 }
293 SkASSERT(!bounds.isEmpty());
294 if (bounds == surfBounds) {
295 return this->makeImageSnapshot();
296 } else {
297 return asSB(this)->onNewImageSnapshot(&bounds);
298 }
299}
300
reede8f30622016-03-23 18:59:25 -0700301sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
mike@reedtribe.orgb9476252012-11-15 02:37:45 +0000302 return asSB(this)->onNewSurface(info);
reed@google.com889b09e2012-07-27 21:10:42 +0000303}
304
305void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
306 const SkPaint* paint) {
307 return asSB(this)->onDraw(canvas, x, y, paint);
308}
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000309
reed6ceeebd2016-03-09 14:26:26 -0800310bool SkSurface::peekPixels(SkPixmap* pmap) {
311 return this->getCanvas()->peekPixels(pmap);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000312}
reed4a8126e2014-09-22 07:29:03 -0700313
Mike Reed353196f2017-07-21 11:01:18 -0400314bool SkSurface::readPixels(const SkPixmap& pm, int srcX, int srcY) {
315 return this->getCanvas()->readPixels(pm, srcX, srcY);
316}
317
reed7543aa22014-12-09 14:39:44 -0800318bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
319 int srcX, int srcY) {
Mike Reed353196f2017-07-21 11:01:18 -0400320 return this->readPixels({dstInfo, dstPixels, dstRowBytes}, srcX, srcY);
321}
322
323bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) {
324 SkPixmap pm;
325 return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY);
reed7543aa22014-12-09 14:39:44 -0800326}
327
Brian Salomon201700f2019-05-17 12:05:44 -0400328void SkSurface::asyncRescaleAndReadPixels(const SkImageInfo& info, const SkIRect& srcRect,
329 RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality,
330 ReadPixelsCallback callback, ReadPixelsContext context) {
Brian Salomonab32f652019-05-10 14:24:50 -0400331 if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) ||
Brian Salomon201700f2019-05-17 12:05:44 -0400332 !SkImageInfoIsValid(info)) {
Brian Salomonab32f652019-05-10 14:24:50 -0400333 callback(context, nullptr, 0);
334 return;
335 }
Brian Salomon031b0ba2019-05-23 11:05:26 -0400336 asSB(this)->onAsyncRescaleAndReadPixels(info, srcRect, rescaleGamma, rescaleQuality, callback,
337 context);
Brian Salomonab32f652019-05-10 14:24:50 -0400338}
339
Mike Reed4c790bd2018-02-08 14:10:40 -0500340void SkSurface::writePixels(const SkPixmap& pmap, int x, int y) {
341 if (pmap.addr() == nullptr || pmap.width() <= 0 || pmap.height() <= 0) {
342 return;
343 }
344
345 const SkIRect srcR = SkIRect::MakeXYWH(x, y, pmap.width(), pmap.height());
346 const SkIRect dstR = SkIRect::MakeWH(this->width(), this->height());
347 if (SkIRect::Intersects(srcR, dstR)) {
348 ContentChangeMode mode = kRetain_ContentChangeMode;
349 if (srcR.contains(dstR)) {
350 mode = kDiscard_ContentChangeMode;
351 }
352 asSB(this)->aboutToDraw(mode);
353 asSB(this)->onWritePixels(pmap, x, y);
354 }
355}
356
357void SkSurface::writePixels(const SkBitmap& src, int x, int y) {
358 SkPixmap pm;
359 if (src.peekPixels(&pm)) {
360 this->writePixels(pm, x, y);
361 }
362}
363
Robert Phillips8caf85f2018-04-05 09:30:38 -0400364GrBackendTexture SkSurface::getBackendTexture(BackendHandleAccess access) {
365 return asSB(this)->onGetBackendTexture(access);
366}
367
368GrBackendRenderTarget SkSurface::getBackendRenderTarget(BackendHandleAccess access) {
369 return asSB(this)->onGetBackendRenderTarget(access);
370}
Robert Phillips8caf85f2018-04-05 09:30:38 -0400371
Brian Salomonaad83152019-05-24 10:16:35 -0400372bool SkSurface::replaceBackendTexture(const GrBackendTexture& backendTexture,
373 GrSurfaceOrigin origin,
374 TextureReleaseProc textureReleaseProc,
375 ReleaseContext releaseContext) {
376 return asSB(this)->onReplaceBackendTexture(backendTexture, origin, textureReleaseProc,
377 releaseContext);
378}
379
Greg Daniela5cb7812017-06-16 09:45:32 -0400380void SkSurface::flush() {
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400381 this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
Greg Danielbae71212019-03-01 15:24:35 -0500382}
383
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400384GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, const GrFlushInfo& flushInfo) {
385 return asSB(this)->onFlush(access, flushInfo);
Greg Daniela5cb7812017-06-16 09:45:32 -0400386}
387
Greg Daniel5816b3d2019-04-22 11:46:41 -0400388GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, GrFlushFlags flags,
389 int numSemaphores, GrBackendSemaphore signalSemaphores[],
390 GrGpuFinishedProc finishedProc,
391 GrGpuFinishedContext finishedContext) {
392 GrFlushInfo info;
393 info.fFlags = flags;
394 info.fNumSemaphores = numSemaphores;
395 info.fSignalSemaphores = signalSemaphores;
396 info.fFinishedProc = finishedProc;
397 info.fFinishedContext = finishedContext;
398 return this->flush(access, info);
399}
400
Greg Danielb9990e42019-04-10 16:28:52 -0400401GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, FlushFlags flags,
402 int numSemaphores, GrBackendSemaphore signalSemaphores[]) {
403 GrFlushFlags grFlags = flags == kSyncCpu_FlushFlag ? kSyncCpu_GrFlushFlag : kNone_GrFlushFlags;
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400404 GrFlushInfo info;
405 info.fFlags = grFlags;
406 info.fNumSemaphores = numSemaphores;
407 info.fSignalSemaphores = signalSemaphores;
408 return this->flush(access, info);
Greg Danielb9990e42019-04-10 16:28:52 -0400409}
410
Greg Daniel51316782017-08-02 15:10:09 +0000411GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores,
412 GrBackendSemaphore signalSemaphores[]) {
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400413 GrFlushInfo info;
414 info.fNumSemaphores = numSemaphores;
415 info.fSignalSemaphores = signalSemaphores;
416 return this->flush(BackendSurfaceAccess::kNoAccess, info);
Greg Daniela5cb7812017-06-16 09:45:32 -0400417}
418
Greg Danielc64ee462017-06-15 16:59:49 -0400419bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
420 return asSB(this)->onWait(numSemaphores, waitSemaphores);
ericrkf7b8b8a2016-02-24 14:49:51 -0800421}
422
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400423bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const {
424 return asSB(const_cast<SkSurface*>(this))->onCharacterize(characterization);
425}
426
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500427bool SkSurface::draw(SkDeferredDisplayList* ddl) {
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400428 return asSB(this)->onDraw(ddl);
429}
430
reed4a8126e2014-09-22 07:29:03 -0700431//////////////////////////////////////////////////////////////////////////////////////
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500432#include "include/utils/SkNoDrawCanvas.h"
Mike Reed44d04bd2017-06-28 19:57:21 -0400433
434class SkNullSurface : public SkSurface_Base {
435public:
436 SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {}
437
438protected:
439 SkCanvas* onNewCanvas() override {
440 return new SkNoDrawCanvas(this->width(), this->height());
441 }
442 sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override {
443 return MakeNull(info.width(), info.height());
444 }
Mike Reed114bde82018-11-21 09:12:09 -0500445 sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subsetOrNull) override { return nullptr; }
Mike Reed4c790bd2018-02-08 14:10:40 -0500446 void onWritePixels(const SkPixmap&, int x, int y) override {}
Mike Reed44d04bd2017-06-28 19:57:21 -0400447 void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
448 void onCopyOnWrite(ContentChangeMode) override {}
449};
450
451sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {
452 if (width < 1 || height < 1) {
453 return nullptr;
454 }
455 return sk_sp<SkSurface>(new SkNullSurface(width, height));
456}
457
458//////////////////////////////////////////////////////////////////////////////////////
reed4a8126e2014-09-22 07:29:03 -0700459
460#if !SK_SUPPORT_GPU
461
Brian Salomonbdecacf2018-02-02 20:32:49 -0500462sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int,
463 GrSurfaceOrigin, const SkSurfaceProps*, bool) {
halcanary96fcdcc2015-08-27 07:41:13 -0700464 return nullptr;
reed4a8126e2014-09-22 07:29:03 -0700465}
466
Robert Phillips9338c602019-02-19 12:52:29 -0500467sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext*, const SkSurfaceCharacterization&,
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400468 SkBudgeted) {
469 return nullptr;
470}
471
Greg Daniel94403452017-04-18 15:52:36 -0400472sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
473 GrSurfaceOrigin origin, int sampleCnt,
Greg Danielfaa095e2017-12-19 13:15:02 -0500474 SkColorType, sk_sp<SkColorSpace>,
Greg Daniel8ce79912019-02-05 10:08:43 -0500475 const SkSurfaceProps*,
476 TextureReleaseProc, ReleaseContext) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500477 return nullptr;
478}
479
reede8f30622016-03-23 18:59:25 -0700480sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
Greg Daniel94403452017-04-18 15:52:36 -0400481 const GrBackendRenderTarget&,
482 GrSurfaceOrigin origin,
Greg Danielfaa095e2017-12-19 13:15:02 -0500483 SkColorType,
484 sk_sp<SkColorSpace>,
Greg Daniel8ce79912019-02-05 10:08:43 -0500485 const SkSurfaceProps*,
486 RenderTargetReleaseProc, ReleaseContext) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500487 return nullptr;
488}
489
Greg Daniel94403452017-04-18 15:52:36 -0400490sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
Greg Daniel94403452017-04-18 15:52:36 -0400491 const GrBackendTexture&,
492 GrSurfaceOrigin origin,
493 int sampleCnt,
Greg Danielfaa095e2017-12-19 13:15:02 -0500494 SkColorType,
495 sk_sp<SkColorSpace>,
496 const SkSurfaceProps*) {
497 return nullptr;
498}
499
reed4a8126e2014-09-22 07:29:03 -0700500#endif