blob: 29068b2c4a995c3528d9bb9aa5166e81bf2cd913 [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
mtklein59c12e32016-05-02 07:19:41 -07008#include "SkAtomics.h"
reed@google.com9ea5a3b2012-07-30 21:03:46 +00009#include "SkSurface_Base.h"
reed@google.com889b09e2012-07-27 21:10:42 +000010#include "SkImagePriv.h"
11#include "SkCanvas.h"
12
reed4a8126e2014-09-22 07:29:03 -070013#include "SkFontLCDConfig.h"
14static SkPixelGeometry compute_default_geometry() {
15 SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder();
16 if (SkFontLCDConfig::kNONE_LCDOrder == order) {
17 return kUnknown_SkPixelGeometry;
18 } else {
19 // Bit0 is RGB(0), BGR(1)
20 // Bit1 is H(0), V(1)
21 const SkPixelGeometry gGeo[] = {
22 kRGB_H_SkPixelGeometry,
23 kBGR_H_SkPixelGeometry,
24 kRGB_V_SkPixelGeometry,
25 kBGR_V_SkPixelGeometry,
26 };
27 int index = 0;
28 if (SkFontLCDConfig::kBGR_LCDOrder == order) {
29 index |= 1;
30 }
31 if (SkFontLCDConfig::kVertical_LCDOrientation == SkFontLCDConfig::GetSubpixelOrientation()){
32 index |= 2;
33 }
34 return gGeo[index];
35 }
36}
37
38SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
39
40SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
41
42SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
43 : fFlags(flags)
44 , fPixelGeometry(compute_default_geometry())
45{}
46
47SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
48 : fFlags(flags), fPixelGeometry(pg)
49{}
50
reed4af267b2014-11-21 08:46:37 -080051SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
52 : fFlags(other.fFlags)
53 , fPixelGeometry(other.fPixelGeometry)
54{}
55
reed@google.com889b09e2012-07-27 21:10:42 +000056///////////////////////////////////////////////////////////////////////////////
57
reed4a8126e2014-09-22 07:29:03 -070058SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
Robert Phillipsa54ccb22017-01-31 07:40:33 -050059 : INHERITED(width, height, props) {
reed@google.com9ea5a3b2012-07-30 21:03:46 +000060}
reed@google.com889b09e2012-07-27 21:10:42 +000061
reed4a8126e2014-09-22 07:29:03 -070062SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
Robert Phillipsa54ccb22017-01-31 07:40:33 -050063 : INHERITED(info, props) {
reed@google.com1360c522014-01-08 21:25:26 +000064}
65
reed@google.com9ea5a3b2012-07-30 21:03:46 +000066SkSurface_Base::~SkSurface_Base() {
reed@google.com97af1a62012-08-28 12:19:02 +000067 // in case the canvas outsurvives us, we null the callback
68 if (fCachedCanvas) {
halcanary96fcdcc2015-08-27 07:41:13 -070069 fCachedCanvas->setSurfaceBase(nullptr);
reed@google.com97af1a62012-08-28 12:19:02 +000070 }
reed@google.com9ea5a3b2012-07-30 21:03:46 +000071}
reed@google.com889b09e2012-07-27 21:10:42 +000072
reed4a8126e2014-09-22 07:29:03 -070073void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
Robert Phillipsac6b1fa2017-03-20 08:38:50 -040074 auto image = this->makeImageSnapshot();
reed@google.com889b09e2012-07-27 21:10:42 +000075 if (image) {
piotaixrb5fae932014-09-24 13:03:30 -070076 canvas->drawImage(image, x, y, paint);
reed@google.com889b09e2012-07-27 21:10:42 +000077 }
78}
79
reedc83a2972015-07-16 07:40:45 -070080bool SkSurface_Base::outstandingImageSnapshot() const {
81 return fCachedImage && !fCachedImage->unique();
82}
83
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +000084void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
reed@google.com97af1a62012-08-28 12:19:02 +000085 this->dirtyGenerationID();
86
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +000087 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
reed@google.com97af1a62012-08-28 12:19:02 +000088
bsalomon49f085d2014-09-05 13:34:00 -070089 if (fCachedImage) {
reed@google.com97af1a62012-08-28 12:19:02 +000090 // the surface may need to fork its backend, if its sharing it with
91 // the cached image. Note: we only call if there is an outstanding owner
92 // on the image (besides us).
reed26e0e582015-07-29 11:44:52 -070093 bool unique = fCachedImage->unique();
94 if (!unique) {
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +000095 this->onCopyOnWrite(mode);
reed@google.com97af1a62012-08-28 12:19:02 +000096 }
97
98 // regardless of copy-on-write, we must drop our cached image now, so
99 // that the next request will get our new contents.
Robert Phillipsa54ccb22017-01-31 07:40:33 -0500100 fCachedImage.reset();
reed26e0e582015-07-29 11:44:52 -0700101
102 if (unique) {
103 // Our content isn't held by any image now, so we can consider that content mutable.
104 // Raster surfaces need to be told it's safe to consider its pixels mutable again.
105 // We make this call after the ->unref() so the subclass can assert there are no images.
106 this->onRestoreBackingMutability();
107 }
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000108 } else if (kDiscard_ContentChangeMode == mode) {
109 this->onDiscard();
reed@google.com97af1a62012-08-28 12:19:02 +0000110 }
111}
112
113uint32_t SkSurface_Base::newGenerationID() {
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000114 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
reed@google.com97af1a62012-08-28 12:19:02 +0000115 static int32_t gID;
116 return sk_atomic_inc(&gID) + 1;
117}
118
reed@google.com889b09e2012-07-27 21:10:42 +0000119static SkSurface_Base* asSB(SkSurface* surface) {
120 return static_cast<SkSurface_Base*>(surface);
121}
122
123///////////////////////////////////////////////////////////////////////////////
124
reed4a8126e2014-09-22 07:29:03 -0700125SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
126 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
127{
reedb2497c22014-12-31 12:31:43 -0800128 SkASSERT(fWidth > 0);
129 SkASSERT(fHeight > 0);
reed@google.com1360c522014-01-08 21:25:26 +0000130 fGenerationID = 0;
131}
132
reed4a8126e2014-09-22 07:29:03 -0700133SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
134 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
135{
reedb2497c22014-12-31 12:31:43 -0800136 SkASSERT(fWidth > 0);
137 SkASSERT(fHeight > 0);
reed@google.com889b09e2012-07-27 21:10:42 +0000138 fGenerationID = 0;
139}
140
reed@google.com97af1a62012-08-28 12:19:02 +0000141uint32_t SkSurface::generationID() {
142 if (0 == fGenerationID) {
143 fGenerationID = asSB(this)->newGenerationID();
144 }
145 return fGenerationID;
146}
147
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000148void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
149 asSB(this)->aboutToDraw(mode);
reed@google.com97af1a62012-08-28 12:19:02 +0000150}
151
reed@google.com9ea5a3b2012-07-30 21:03:46 +0000152SkCanvas* SkSurface::getCanvas() {
153 return asSB(this)->getCachedCanvas();
reed@google.com889b09e2012-07-27 21:10:42 +0000154}
155
Robert Phillipsac6b1fa2017-03-20 08:38:50 -0400156sk_sp<SkImage> SkSurface::makeImageSnapshot() {
157 return asSB(this)->refCachedImage();
reed@google.com889b09e2012-07-27 21:10:42 +0000158}
159
reede8f30622016-03-23 18:59:25 -0700160sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
mike@reedtribe.orgb9476252012-11-15 02:37:45 +0000161 return asSB(this)->onNewSurface(info);
reed@google.com889b09e2012-07-27 21:10:42 +0000162}
163
164void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
165 const SkPaint* paint) {
166 return asSB(this)->onDraw(canvas, x, y, paint);
167}
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000168
reed6ceeebd2016-03-09 14:26:26 -0800169bool SkSurface::peekPixels(SkPixmap* pmap) {
170 return this->getCanvas()->peekPixels(pmap);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000171}
reed4a8126e2014-09-22 07:29:03 -0700172
Mike Reed353196f2017-07-21 11:01:18 -0400173bool SkSurface::readPixels(const SkPixmap& pm, int srcX, int srcY) {
174 return this->getCanvas()->readPixels(pm, srcX, srcY);
175}
176
reed7543aa22014-12-09 14:39:44 -0800177bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
178 int srcX, int srcY) {
Mike Reed353196f2017-07-21 11:01:18 -0400179 return this->readPixels({dstInfo, dstPixels, dstRowBytes}, srcX, srcY);
180}
181
182bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) {
183 SkPixmap pm;
184 return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY);
reed7543aa22014-12-09 14:39:44 -0800185}
186
joshualitt81793412015-07-08 12:54:04 -0700187GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) {
reedfa5e68e2015-06-29 07:37:01 -0700188 return asSB(this)->onGetTextureHandle(access);
189}
190
joshualitt81793412015-07-08 12:54:04 -0700191bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) {
192 return asSB(this)->onGetRenderTargetHandle(obj, access);
193}
194
ericrkf7b8b8a2016-02-24 14:49:51 -0800195void SkSurface::prepareForExternalIO() {
Greg Daniela5cb7812017-06-16 09:45:32 -0400196 this->flush();
197}
198
199void SkSurface::flush() {
200 asSB(this)->onFlush(0, nullptr);
201}
202
Greg Danielc64ee462017-06-15 16:59:49 -0400203bool SkSurface::flushAndSignalSemaphores(int numSemaphores, GrBackendSemaphore* signalSemaphores) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400204 return asSB(this)->onFlush(numSemaphores, signalSemaphores);
205}
206
Greg Danielc64ee462017-06-15 16:59:49 -0400207bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
208 return asSB(this)->onWait(numSemaphores, waitSemaphores);
ericrkf7b8b8a2016-02-24 14:49:51 -0800209}
210
reed4a8126e2014-09-22 07:29:03 -0700211//////////////////////////////////////////////////////////////////////////////////////
Mike Reed44d04bd2017-06-28 19:57:21 -0400212#include "SkNoDrawCanvas.h"
213
214class SkNullSurface : public SkSurface_Base {
215public:
216 SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {}
217
218protected:
219 SkCanvas* onNewCanvas() override {
220 return new SkNoDrawCanvas(this->width(), this->height());
221 }
222 sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override {
223 return MakeNull(info.width(), info.height());
224 }
225 sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; }
226 void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
227 void onCopyOnWrite(ContentChangeMode) override {}
228};
229
230sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {
231 if (width < 1 || height < 1) {
232 return nullptr;
233 }
234 return sk_sp<SkSurface>(new SkNullSurface(width, height));
235}
236
237//////////////////////////////////////////////////////////////////////////////////////
reed4a8126e2014-09-22 07:29:03 -0700238
239#if !SK_SUPPORT_GPU
240
robertphillips7e922762016-07-26 11:38:17 -0700241sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&,
242 int, GrSurfaceOrigin, const SkSurfaceProps*) {
halcanary96fcdcc2015-08-27 07:41:13 -0700243 return nullptr;
reed4a8126e2014-09-22 07:29:03 -0700244}
245
Greg Daniel94403452017-04-18 15:52:36 -0400246sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
247 GrSurfaceOrigin origin, int sampleCnt,
248 sk_sp<SkColorSpace>, const SkSurfaceProps*) {
249 return nullptr;
250}
251
reede8f30622016-03-23 18:59:25 -0700252sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
Brian Salomon807371c2017-07-20 20:48:12 +0000253 const GrBackendRenderTargetDesc&,
254 sk_sp<SkColorSpace>,
255 const SkSurfaceProps*) {
256 return nullptr;
257}
258
259sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
Greg Daniel94403452017-04-18 15:52:36 -0400260 const GrBackendRenderTarget&,
261 GrSurfaceOrigin origin,
262 sk_sp<SkColorSpace>,
263 const SkSurfaceProps*) {
264 return nullptr;
265}
266
267sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
Greg Daniel94403452017-04-18 15:52:36 -0400268 const GrBackendTexture&,
269 GrSurfaceOrigin origin,
270 int sampleCnt,
271 sk_sp<SkColorSpace>,
272 const SkSurfaceProps*) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800273 return nullptr;
274}
275
reed4a8126e2014-09-22 07:29:03 -0700276#endif