blob: d7a05eecd10961bfd9c4cc1796c8d6e931f48575 [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
Mike Klein0ec1c572018-12-04 11:52:51 -05008#include "GrBackendSurface.h"
reed@google.com889b09e2012-07-27 21:10:42 +00009#include "SkCanvas.h"
reed4a8126e2014-09-22 07:29:03 -070010#include "SkFontLCDConfig.h"
Robert Phillips8caf85f2018-04-05 09:30:38 -040011#include "SkImagePriv.h"
12#include "SkSurface_Base.h"
Mike Klein0ec1c572018-12-04 11:52:51 -050013#include <atomic>
Robert Phillips8caf85f2018-04-05 09:30:38 -040014
reed4a8126e2014-09-22 07:29:03 -070015static SkPixelGeometry compute_default_geometry() {
16 SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder();
17 if (SkFontLCDConfig::kNONE_LCDOrder == order) {
18 return kUnknown_SkPixelGeometry;
19 } else {
20 // Bit0 is RGB(0), BGR(1)
21 // Bit1 is H(0), V(1)
22 const SkPixelGeometry gGeo[] = {
23 kRGB_H_SkPixelGeometry,
24 kBGR_H_SkPixelGeometry,
25 kRGB_V_SkPixelGeometry,
26 kBGR_V_SkPixelGeometry,
27 };
28 int index = 0;
29 if (SkFontLCDConfig::kBGR_LCDOrder == order) {
30 index |= 1;
31 }
32 if (SkFontLCDConfig::kVertical_LCDOrientation == SkFontLCDConfig::GetSubpixelOrientation()){
33 index |= 2;
34 }
35 return gGeo[index];
36 }
37}
38
39SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
40
41SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
42
43SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
44 : fFlags(flags)
45 , fPixelGeometry(compute_default_geometry())
46{}
47
48SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
49 : fFlags(flags), fPixelGeometry(pg)
50{}
51
reed4af267b2014-11-21 08:46:37 -080052SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
53 : fFlags(other.fFlags)
54 , fPixelGeometry(other.fPixelGeometry)
55{}
56
reed@google.com889b09e2012-07-27 21:10:42 +000057///////////////////////////////////////////////////////////////////////////////
58
reed4a8126e2014-09-22 07:29:03 -070059SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
Robert Phillipsa54ccb22017-01-31 07:40:33 -050060 : INHERITED(width, height, props) {
reed@google.com9ea5a3b2012-07-30 21:03:46 +000061}
reed@google.com889b09e2012-07-27 21:10:42 +000062
reed4a8126e2014-09-22 07:29:03 -070063SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
Robert Phillipsa54ccb22017-01-31 07:40:33 -050064 : INHERITED(info, props) {
reed@google.com1360c522014-01-08 21:25:26 +000065}
66
reed@google.com9ea5a3b2012-07-30 21:03:46 +000067SkSurface_Base::~SkSurface_Base() {
reed@google.com97af1a62012-08-28 12:19:02 +000068 // in case the canvas outsurvives us, we null the callback
69 if (fCachedCanvas) {
halcanary96fcdcc2015-08-27 07:41:13 -070070 fCachedCanvas->setSurfaceBase(nullptr);
reed@google.com97af1a62012-08-28 12:19:02 +000071 }
reed@google.com9ea5a3b2012-07-30 21:03:46 +000072}
reed@google.com889b09e2012-07-27 21:10:42 +000073
Robert Phillips8caf85f2018-04-05 09:30:38 -040074GrBackendTexture SkSurface_Base::onGetBackendTexture(BackendHandleAccess) {
75 return GrBackendTexture(); // invalid
76}
77
78GrBackendRenderTarget SkSurface_Base::onGetBackendRenderTarget(BackendHandleAccess) {
79 return GrBackendRenderTarget(); // invalid
80}
81
reed4a8126e2014-09-22 07:29:03 -070082void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
Robert Phillipsac6b1fa2017-03-20 08:38:50 -040083 auto image = this->makeImageSnapshot();
reed@google.com889b09e2012-07-27 21:10:42 +000084 if (image) {
piotaixrb5fae932014-09-24 13:03:30 -070085 canvas->drawImage(image, x, y, paint);
reed@google.com889b09e2012-07-27 21:10:42 +000086 }
87}
88
reedc83a2972015-07-16 07:40:45 -070089bool SkSurface_Base::outstandingImageSnapshot() const {
90 return fCachedImage && !fCachedImage->unique();
91}
92
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +000093void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
reed@google.com97af1a62012-08-28 12:19:02 +000094 this->dirtyGenerationID();
95
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +000096 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
reed@google.com97af1a62012-08-28 12:19:02 +000097
bsalomon49f085d2014-09-05 13:34:00 -070098 if (fCachedImage) {
reed@google.com97af1a62012-08-28 12:19:02 +000099 // the surface may need to fork its backend, if its sharing it with
100 // the cached image. Note: we only call if there is an outstanding owner
101 // on the image (besides us).
reed26e0e582015-07-29 11:44:52 -0700102 bool unique = fCachedImage->unique();
103 if (!unique) {
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000104 this->onCopyOnWrite(mode);
reed@google.com97af1a62012-08-28 12:19:02 +0000105 }
106
107 // regardless of copy-on-write, we must drop our cached image now, so
108 // that the next request will get our new contents.
Robert Phillipsa54ccb22017-01-31 07:40:33 -0500109 fCachedImage.reset();
reed26e0e582015-07-29 11:44:52 -0700110
111 if (unique) {
112 // Our content isn't held by any image now, so we can consider that content mutable.
113 // Raster surfaces need to be told it's safe to consider its pixels mutable again.
114 // We make this call after the ->unref() so the subclass can assert there are no images.
115 this->onRestoreBackingMutability();
116 }
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000117 } else if (kDiscard_ContentChangeMode == mode) {
118 this->onDiscard();
reed@google.com97af1a62012-08-28 12:19:02 +0000119 }
120}
121
122uint32_t SkSurface_Base::newGenerationID() {
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000123 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
Mike Klein0ec1c572018-12-04 11:52:51 -0500124 static std::atomic<uint32_t> nextID{1};
125 return nextID++;
reed@google.com97af1a62012-08-28 12:19:02 +0000126}
127
reed@google.com889b09e2012-07-27 21:10:42 +0000128static SkSurface_Base* asSB(SkSurface* surface) {
129 return static_cast<SkSurface_Base*>(surface);
130}
131
132///////////////////////////////////////////////////////////////////////////////
133
reed4a8126e2014-09-22 07:29:03 -0700134SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
135 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
136{
reedb2497c22014-12-31 12:31:43 -0800137 SkASSERT(fWidth > 0);
138 SkASSERT(fHeight > 0);
reed@google.com1360c522014-01-08 21:25:26 +0000139 fGenerationID = 0;
140}
141
reed4a8126e2014-09-22 07:29:03 -0700142SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
143 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
144{
reedb2497c22014-12-31 12:31:43 -0800145 SkASSERT(fWidth > 0);
146 SkASSERT(fHeight > 0);
reed@google.com889b09e2012-07-27 21:10:42 +0000147 fGenerationID = 0;
148}
149
reed@google.com97af1a62012-08-28 12:19:02 +0000150uint32_t SkSurface::generationID() {
151 if (0 == fGenerationID) {
152 fGenerationID = asSB(this)->newGenerationID();
153 }
154 return fGenerationID;
155}
156
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000157void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
158 asSB(this)->aboutToDraw(mode);
reed@google.com97af1a62012-08-28 12:19:02 +0000159}
160
reed@google.com9ea5a3b2012-07-30 21:03:46 +0000161SkCanvas* SkSurface::getCanvas() {
162 return asSB(this)->getCachedCanvas();
reed@google.com889b09e2012-07-27 21:10:42 +0000163}
164
Robert Phillipsac6b1fa2017-03-20 08:38:50 -0400165sk_sp<SkImage> SkSurface::makeImageSnapshot() {
166 return asSB(this)->refCachedImage();
reed@google.com889b09e2012-07-27 21:10:42 +0000167}
168
Mike Reed114bde82018-11-21 09:12:09 -0500169sk_sp<SkImage> SkSurface::makeImageSnapshot(const SkIRect& srcBounds) {
170 const SkIRect surfBounds = { 0, 0, fWidth, fHeight };
171 SkIRect bounds = srcBounds;
172 if (!bounds.intersect(surfBounds)) {
173 return nullptr;
174 }
175 SkASSERT(!bounds.isEmpty());
176 if (bounds == surfBounds) {
177 return this->makeImageSnapshot();
178 } else {
179 return asSB(this)->onNewImageSnapshot(&bounds);
180 }
181}
182
reede8f30622016-03-23 18:59:25 -0700183sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
mike@reedtribe.orgb9476252012-11-15 02:37:45 +0000184 return asSB(this)->onNewSurface(info);
reed@google.com889b09e2012-07-27 21:10:42 +0000185}
186
187void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
188 const SkPaint* paint) {
189 return asSB(this)->onDraw(canvas, x, y, paint);
190}
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000191
reed6ceeebd2016-03-09 14:26:26 -0800192bool SkSurface::peekPixels(SkPixmap* pmap) {
193 return this->getCanvas()->peekPixels(pmap);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000194}
reed4a8126e2014-09-22 07:29:03 -0700195
Mike Reed353196f2017-07-21 11:01:18 -0400196bool SkSurface::readPixels(const SkPixmap& pm, int srcX, int srcY) {
197 return this->getCanvas()->readPixels(pm, srcX, srcY);
198}
199
reed7543aa22014-12-09 14:39:44 -0800200bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
201 int srcX, int srcY) {
Mike Reed353196f2017-07-21 11:01:18 -0400202 return this->readPixels({dstInfo, dstPixels, dstRowBytes}, srcX, srcY);
203}
204
205bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) {
206 SkPixmap pm;
207 return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY);
reed7543aa22014-12-09 14:39:44 -0800208}
209
Mike Reed4c790bd2018-02-08 14:10:40 -0500210void SkSurface::writePixels(const SkPixmap& pmap, int x, int y) {
211 if (pmap.addr() == nullptr || pmap.width() <= 0 || pmap.height() <= 0) {
212 return;
213 }
214
215 const SkIRect srcR = SkIRect::MakeXYWH(x, y, pmap.width(), pmap.height());
216 const SkIRect dstR = SkIRect::MakeWH(this->width(), this->height());
217 if (SkIRect::Intersects(srcR, dstR)) {
218 ContentChangeMode mode = kRetain_ContentChangeMode;
219 if (srcR.contains(dstR)) {
220 mode = kDiscard_ContentChangeMode;
221 }
222 asSB(this)->aboutToDraw(mode);
223 asSB(this)->onWritePixels(pmap, x, y);
224 }
225}
226
227void SkSurface::writePixels(const SkBitmap& src, int x, int y) {
228 SkPixmap pm;
229 if (src.peekPixels(&pm)) {
230 this->writePixels(pm, x, y);
231 }
232}
233
Robert Phillips8caf85f2018-04-05 09:30:38 -0400234GrBackendTexture SkSurface::getBackendTexture(BackendHandleAccess access) {
235 return asSB(this)->onGetBackendTexture(access);
236}
237
238GrBackendRenderTarget SkSurface::getBackendRenderTarget(BackendHandleAccess access) {
239 return asSB(this)->onGetBackendRenderTarget(access);
240}
Robert Phillips8caf85f2018-04-05 09:30:38 -0400241
ericrkf7b8b8a2016-02-24 14:49:51 -0800242void SkSurface::prepareForExternalIO() {
Greg Daniela5cb7812017-06-16 09:45:32 -0400243 this->flush();
244}
245
246void SkSurface::flush() {
Greg Danielb9990e42019-04-10 16:28:52 -0400247 asSB(this)->onFlush(BackendSurfaceAccess::kNoAccess, kNone_GrFlushFlags, 0, nullptr);
Greg Danielbae71212019-03-01 15:24:35 -0500248}
249
Greg Danielb9990e42019-04-10 16:28:52 -0400250GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, GrFlushFlags flags,
Greg Danielbae71212019-03-01 15:24:35 -0500251 int numSemaphores, GrBackendSemaphore signalSemaphores[]) {
252 return asSB(this)->onFlush(access, flags, numSemaphores, signalSemaphores);
Greg Daniela5cb7812017-06-16 09:45:32 -0400253}
254
Greg Danielb9990e42019-04-10 16:28:52 -0400255GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, FlushFlags flags,
256 int numSemaphores, GrBackendSemaphore signalSemaphores[]) {
257 GrFlushFlags grFlags = flags == kSyncCpu_FlushFlag ? kSyncCpu_GrFlushFlag : kNone_GrFlushFlags;
258 return this->flush(access, grFlags, numSemaphores, signalSemaphores);
259}
260
Greg Daniel51316782017-08-02 15:10:09 +0000261GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores,
262 GrBackendSemaphore signalSemaphores[]) {
Greg Danielb9990e42019-04-10 16:28:52 -0400263 return asSB(this)->onFlush(BackendSurfaceAccess::kNoAccess, kNone_GrFlushFlags,
Greg Danielbae71212019-03-01 15:24:35 -0500264 numSemaphores, signalSemaphores);
Greg Daniela5cb7812017-06-16 09:45:32 -0400265}
266
Greg Danielc64ee462017-06-15 16:59:49 -0400267bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
268 return asSB(this)->onWait(numSemaphores, waitSemaphores);
ericrkf7b8b8a2016-02-24 14:49:51 -0800269}
270
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400271bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const {
272 return asSB(const_cast<SkSurface*>(this))->onCharacterize(characterization);
273}
274
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500275bool SkSurface::draw(SkDeferredDisplayList* ddl) {
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400276 return asSB(this)->onDraw(ddl);
277}
278
reed4a8126e2014-09-22 07:29:03 -0700279//////////////////////////////////////////////////////////////////////////////////////
Mike Reed44d04bd2017-06-28 19:57:21 -0400280#include "SkNoDrawCanvas.h"
281
282class SkNullSurface : public SkSurface_Base {
283public:
284 SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {}
285
286protected:
287 SkCanvas* onNewCanvas() override {
288 return new SkNoDrawCanvas(this->width(), this->height());
289 }
290 sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override {
291 return MakeNull(info.width(), info.height());
292 }
Mike Reed114bde82018-11-21 09:12:09 -0500293 sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subsetOrNull) override { return nullptr; }
Mike Reed4c790bd2018-02-08 14:10:40 -0500294 void onWritePixels(const SkPixmap&, int x, int y) override {}
Mike Reed44d04bd2017-06-28 19:57:21 -0400295 void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
296 void onCopyOnWrite(ContentChangeMode) override {}
297};
298
299sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {
300 if (width < 1 || height < 1) {
301 return nullptr;
302 }
303 return sk_sp<SkSurface>(new SkNullSurface(width, height));
304}
305
306//////////////////////////////////////////////////////////////////////////////////////
reed4a8126e2014-09-22 07:29:03 -0700307
308#if !SK_SUPPORT_GPU
309
Brian Salomonbdecacf2018-02-02 20:32:49 -0500310sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int,
311 GrSurfaceOrigin, const SkSurfaceProps*, bool) {
halcanary96fcdcc2015-08-27 07:41:13 -0700312 return nullptr;
reed4a8126e2014-09-22 07:29:03 -0700313}
314
Robert Phillips9338c602019-02-19 12:52:29 -0500315sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext*, const SkSurfaceCharacterization&,
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400316 SkBudgeted) {
317 return nullptr;
318}
319
Greg Daniel94403452017-04-18 15:52:36 -0400320sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
321 GrSurfaceOrigin origin, int sampleCnt,
Greg Danielfaa095e2017-12-19 13:15:02 -0500322 SkColorType, sk_sp<SkColorSpace>,
Greg Daniel8ce79912019-02-05 10:08:43 -0500323 const SkSurfaceProps*,
324 TextureReleaseProc, ReleaseContext) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500325 return nullptr;
326}
327
reede8f30622016-03-23 18:59:25 -0700328sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
Greg Daniel94403452017-04-18 15:52:36 -0400329 const GrBackendRenderTarget&,
330 GrSurfaceOrigin origin,
Greg Danielfaa095e2017-12-19 13:15:02 -0500331 SkColorType,
332 sk_sp<SkColorSpace>,
Greg Daniel8ce79912019-02-05 10:08:43 -0500333 const SkSurfaceProps*,
334 RenderTargetReleaseProc, ReleaseContext) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500335 return nullptr;
336}
337
Greg Daniel94403452017-04-18 15:52:36 -0400338sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
Greg Daniel94403452017-04-18 15:52:36 -0400339 const GrBackendTexture&,
340 GrSurfaceOrigin origin,
341 int sampleCnt,
Greg Danielfaa095e2017-12-19 13:15:02 -0500342 SkColorType,
343 sk_sp<SkColorSpace>,
344 const SkSurfaceProps*) {
345 return nullptr;
346}
347
reed4a8126e2014-09-22 07:29:03 -0700348#endif