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 "SkAtomics.h"
9 #include "SkSurface_Base.h"
10 #include "SkImagePriv.h"
11 #include "SkCanvas.h"
12
13 #include "SkFontLCDConfig.h"
compute_default_geometry()14 static 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
SkSurfaceProps()38 SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
39
SkSurfaceProps(InitType)40 SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
41
SkSurfaceProps(uint32_t flags,InitType)42 SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
43 : fFlags(flags)
44 , fPixelGeometry(compute_default_geometry())
45 {}
46
SkSurfaceProps(uint32_t flags,SkPixelGeometry pg)47 SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
48 : fFlags(flags), fPixelGeometry(pg)
49 {}
50
SkSurfaceProps(const SkSurfaceProps & other)51 SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
52 : fFlags(other.fFlags)
53 , fPixelGeometry(other.fPixelGeometry)
54 {}
55
56 ///////////////////////////////////////////////////////////////////////////////
57
SkSurface_Base(int width,int height,const SkSurfaceProps * props)58 SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
59 : INHERITED(width, height, props) {
60 }
61
SkSurface_Base(const SkImageInfo & info,const SkSurfaceProps * props)62 SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
63 : INHERITED(info, props) {
64 }
65
~SkSurface_Base()66 SkSurface_Base::~SkSurface_Base() {
67 // in case the canvas outsurvives us, we null the callback
68 if (fCachedCanvas) {
69 fCachedCanvas->setSurfaceBase(nullptr);
70 }
71 }
72
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)73 void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
74 auto image = this->makeImageSnapshot();
75 if (image) {
76 canvas->drawImage(image, x, y, paint);
77 }
78 }
79
outstandingImageSnapshot() const80 bool SkSurface_Base::outstandingImageSnapshot() const {
81 return fCachedImage && !fCachedImage->unique();
82 }
83
aboutToDraw(ContentChangeMode mode)84 void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
85 this->dirtyGenerationID();
86
87 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
88
89 if (fCachedImage) {
90 // 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).
93 bool unique = fCachedImage->unique();
94 if (!unique) {
95 this->onCopyOnWrite(mode);
96 }
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.
100 fCachedImage.reset();
101
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 }
108 } else if (kDiscard_ContentChangeMode == mode) {
109 this->onDiscard();
110 }
111 }
112
newGenerationID()113 uint32_t SkSurface_Base::newGenerationID() {
114 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
115 static int32_t gID;
116 return sk_atomic_inc(&gID) + 1;
117 }
118
asSB(SkSurface * surface)119 static SkSurface_Base* asSB(SkSurface* surface) {
120 return static_cast<SkSurface_Base*>(surface);
121 }
122
123 ///////////////////////////////////////////////////////////////////////////////
124
SkSurface(int width,int height,const SkSurfaceProps * props)125 SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
126 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
127 {
128 SkASSERT(fWidth > 0);
129 SkASSERT(fHeight > 0);
130 fGenerationID = 0;
131 }
132
SkSurface(const SkImageInfo & info,const SkSurfaceProps * props)133 SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
134 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
135 {
136 SkASSERT(fWidth > 0);
137 SkASSERT(fHeight > 0);
138 fGenerationID = 0;
139 }
140
generationID()141 uint32_t SkSurface::generationID() {
142 if (0 == fGenerationID) {
143 fGenerationID = asSB(this)->newGenerationID();
144 }
145 return fGenerationID;
146 }
147
notifyContentWillChange(ContentChangeMode mode)148 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
149 asSB(this)->aboutToDraw(mode);
150 }
151
getCanvas()152 SkCanvas* SkSurface::getCanvas() {
153 return asSB(this)->getCachedCanvas();
154 }
155
makeImageSnapshot()156 sk_sp<SkImage> SkSurface::makeImageSnapshot() {
157 return asSB(this)->refCachedImage();
158 }
159
makeSurface(const SkImageInfo & info)160 sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
161 return asSB(this)->onNewSurface(info);
162 }
163
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)164 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
165 const SkPaint* paint) {
166 return asSB(this)->onDraw(canvas, x, y, paint);
167 }
168
peekPixels(SkPixmap * pmap)169 bool SkSurface::peekPixels(SkPixmap* pmap) {
170 return this->getCanvas()->peekPixels(pmap);
171 }
172
readPixels(const SkPixmap & pm,int srcX,int srcY)173 bool SkSurface::readPixels(const SkPixmap& pm, int srcX, int srcY) {
174 return this->getCanvas()->readPixels(pm, srcX, srcY);
175 }
176
readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY)177 bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
178 int srcX, int srcY) {
179 return this->readPixels({dstInfo, dstPixels, dstRowBytes}, srcX, srcY);
180 }
181
readPixels(const SkBitmap & bitmap,int srcX,int srcY)182 bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) {
183 SkPixmap pm;
184 return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY);
185 }
186
getTextureHandle(BackendHandleAccess access)187 GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) {
188 return asSB(this)->onGetTextureHandle(access);
189 }
190
getRenderTargetHandle(GrBackendObject * obj,BackendHandleAccess access)191 bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) {
192 return asSB(this)->onGetRenderTargetHandle(obj, access);
193 }
194
prepareForExternalIO()195 void SkSurface::prepareForExternalIO() {
196 this->flush();
197 }
198
flush()199 void SkSurface::flush() {
200 asSB(this)->onFlush(0, nullptr);
201 }
202
flushAndSignalSemaphores(int numSemaphores,GrBackendSemaphore signalSemaphores[])203 GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores,
204 GrBackendSemaphore signalSemaphores[]) {
205 return asSB(this)->onFlush(numSemaphores, signalSemaphores);
206 }
207
wait(int numSemaphores,const GrBackendSemaphore * waitSemaphores)208 bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
209 return asSB(this)->onWait(numSemaphores, waitSemaphores);
210 }
211
characterize(SkSurfaceCharacterization * characterization) const212 bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const {
213 return asSB(const_cast<SkSurface*>(this))->onCharacterize(characterization);
214 }
215
draw(SkDeferredDisplayList * ddl)216 bool SkSurface::draw(SkDeferredDisplayList* ddl) {
217 return asSB(this)->onDraw(ddl);
218 }
219
220 //////////////////////////////////////////////////////////////////////////////////////
221 #include "SkNoDrawCanvas.h"
222
223 class SkNullSurface : public SkSurface_Base {
224 public:
SkNullSurface(int width,int height)225 SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {}
226
227 protected:
onNewCanvas()228 SkCanvas* onNewCanvas() override {
229 return new SkNoDrawCanvas(this->width(), this->height());
230 }
onNewSurface(const SkImageInfo & info)231 sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override {
232 return MakeNull(info.width(), info.height());
233 }
onNewImageSnapshot()234 sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; }
onDraw(SkCanvas *,SkScalar x,SkScalar y,const SkPaint *)235 void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
onCopyOnWrite(ContentChangeMode)236 void onCopyOnWrite(ContentChangeMode) override {}
237 };
238
MakeNull(int width,int height)239 sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {
240 if (width < 1 || height < 1) {
241 return nullptr;
242 }
243 return sk_sp<SkSurface>(new SkNullSurface(width, height));
244 }
245
246 //////////////////////////////////////////////////////////////////////////////////////
247
248 #if !SK_SUPPORT_GPU
249
MakeRenderTarget(GrContext *,SkBudgeted,const SkImageInfo &,int,GrSurfaceOrigin,const SkSurfaceProps *,bool)250 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int,
251 GrSurfaceOrigin, const SkSurfaceProps*, bool) {
252 return nullptr;
253 }
254
MakeFromBackendTexture(GrContext *,const GrBackendTexture &,GrSurfaceOrigin origin,int sampleCnt,sk_sp<SkColorSpace>,const SkSurfaceProps *)255 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
256 GrSurfaceOrigin origin, int sampleCnt,
257 sk_sp<SkColorSpace>, const SkSurfaceProps*) {
258 return nullptr;
259 }
260
MakeFromBackendTexture(GrContext *,const GrBackendTexture &,GrSurfaceOrigin origin,int sampleCnt,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *)261 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
262 GrSurfaceOrigin origin, int sampleCnt,
263 SkColorType, sk_sp<SkColorSpace>,
264 const SkSurfaceProps*) {
265 return nullptr;
266 }
267
MakeFromBackendRenderTarget(GrContext *,const GrBackendRenderTarget &,GrSurfaceOrigin origin,sk_sp<SkColorSpace>,const SkSurfaceProps *)268 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
269 const GrBackendRenderTarget&,
270 GrSurfaceOrigin origin,
271 sk_sp<SkColorSpace>,
272 const SkSurfaceProps*) {
273 return nullptr;
274 }
275
MakeFromBackendRenderTarget(GrContext *,const GrBackendRenderTarget &,GrSurfaceOrigin origin,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *)276 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
277 const GrBackendRenderTarget&,
278 GrSurfaceOrigin origin,
279 SkColorType,
280 sk_sp<SkColorSpace>,
281 const SkSurfaceProps*) {
282 return nullptr;
283 }
284
MakeFromBackendTextureAsRenderTarget(GrContext *,const GrBackendTexture &,GrSurfaceOrigin origin,int sampleCnt,sk_sp<SkColorSpace>,const SkSurfaceProps *)285 sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
286 const GrBackendTexture&,
287 GrSurfaceOrigin origin,
288 int sampleCnt,
289 sk_sp<SkColorSpace>,
290 const SkSurfaceProps*) {
291 return nullptr;
292 }
293
MakeFromBackendTextureAsRenderTarget(GrContext *,const GrBackendTexture &,GrSurfaceOrigin origin,int sampleCnt,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *)294 sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
295 const GrBackendTexture&,
296 GrSurfaceOrigin origin,
297 int sampleCnt,
298 SkColorType,
299 sk_sp<SkColorSpace>,
300 const SkSurfaceProps*) {
301 return nullptr;
302 }
303
304 #endif
305