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 fCachedCanvas = nullptr;
62 fCachedImage = nullptr;
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 fCachedCanvas = nullptr;
69 fCachedImage = nullptr;
70 }
71
~SkSurface_Base()72 SkSurface_Base::~SkSurface_Base() {
73 // in case the canvas outsurvives us, we null the callback
74 if (fCachedCanvas) {
75 fCachedCanvas->setSurfaceBase(nullptr);
76 }
77
78 SkSafeUnref(fCachedImage);
79 SkSafeUnref(fCachedCanvas);
80 }
81
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)82 void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
83 auto image = this->makeImageSnapshot(SkBudgeted::kYes);
84 if (image) {
85 canvas->drawImage(image, x, y, paint);
86 }
87 }
88
outstandingImageSnapshot() const89 bool SkSurface_Base::outstandingImageSnapshot() const {
90 return fCachedImage && !fCachedImage->unique();
91 }
92
aboutToDraw(ContentChangeMode mode)93 void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
94 this->dirtyGenerationID();
95
96 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
97
98 if (fCachedImage) {
99 // 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).
102 bool unique = fCachedImage->unique();
103 if (!unique) {
104 this->onCopyOnWrite(mode);
105 }
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.
109 fCachedImage->unref();
110 fCachedImage = nullptr;
111
112 if (unique) {
113 // Our content isn't held by any image now, so we can consider that content mutable.
114 // Raster surfaces need to be told it's safe to consider its pixels mutable again.
115 // We make this call after the ->unref() so the subclass can assert there are no images.
116 this->onRestoreBackingMutability();
117 }
118 } else if (kDiscard_ContentChangeMode == mode) {
119 this->onDiscard();
120 }
121 }
122
newGenerationID()123 uint32_t SkSurface_Base::newGenerationID() {
124 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
125 static int32_t gID;
126 return sk_atomic_inc(&gID) + 1;
127 }
128
asSB(SkSurface * surface)129 static SkSurface_Base* asSB(SkSurface* surface) {
130 return static_cast<SkSurface_Base*>(surface);
131 }
132
133 ///////////////////////////////////////////////////////////////////////////////
134
SkSurface(int width,int height,const SkSurfaceProps * props)135 SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
136 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
137 {
138 SkASSERT(fWidth > 0);
139 SkASSERT(fHeight > 0);
140 fGenerationID = 0;
141 }
142
SkSurface(const SkImageInfo & info,const SkSurfaceProps * props)143 SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
144 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
145 {
146 SkASSERT(fWidth > 0);
147 SkASSERT(fHeight > 0);
148 fGenerationID = 0;
149 }
150
generationID()151 uint32_t SkSurface::generationID() {
152 if (0 == fGenerationID) {
153 fGenerationID = asSB(this)->newGenerationID();
154 }
155 return fGenerationID;
156 }
157
notifyContentWillChange(ContentChangeMode mode)158 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
159 asSB(this)->aboutToDraw(mode);
160 }
161
getCanvas()162 SkCanvas* SkSurface::getCanvas() {
163 return asSB(this)->getCachedCanvas();
164 }
165
makeImageSnapshot(SkBudgeted budgeted)166 sk_sp<SkImage> SkSurface::makeImageSnapshot(SkBudgeted budgeted) {
167 // the caller will call unref() to balance this
168 return asSB(this)->refCachedImage(budgeted, kNo_ForceUnique);
169 }
170
makeImageSnapshot(SkBudgeted budgeted,ForceUnique unique)171 sk_sp<SkImage> SkSurface::makeImageSnapshot(SkBudgeted budgeted, ForceUnique unique) {
172 // the caller will call unref() to balance this
173 return asSB(this)->refCachedImage(budgeted, unique);
174 }
175
makeSurface(const SkImageInfo & info)176 sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
177 return asSB(this)->onNewSurface(info);
178 }
179
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)180 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
181 const SkPaint* paint) {
182 return asSB(this)->onDraw(canvas, x, y, paint);
183 }
184
peekPixels(SkPixmap * pmap)185 bool SkSurface::peekPixels(SkPixmap* pmap) {
186 return this->getCanvas()->peekPixels(pmap);
187 }
188
189 #ifdef SK_SUPPORT_LEGACY_PEEKPIXELS_PARMS
peekPixels(SkImageInfo * info,size_t * rowBytes)190 const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) {
191 SkPixmap pm;
192 if (this->peekPixels(&pm)) {
193 if (info) {
194 *info = pm.info();
195 }
196 if (rowBytes) {
197 *rowBytes = pm.rowBytes();
198 }
199 return pm.addr();
200 }
201 return nullptr;
202 }
203 #endif
204
readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY)205 bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
206 int srcX, int srcY) {
207 return this->getCanvas()->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
208 }
209
getTextureHandle(BackendHandleAccess access)210 GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) {
211 return asSB(this)->onGetTextureHandle(access);
212 }
213
getRenderTargetHandle(GrBackendObject * obj,BackendHandleAccess access)214 bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) {
215 return asSB(this)->onGetRenderTargetHandle(obj, access);
216 }
217
prepareForExternalIO()218 void SkSurface::prepareForExternalIO() {
219 asSB(this)->onPrepareForExternalIO();
220 }
221
222 //////////////////////////////////////////////////////////////////////////////////////
223
224 #if !SK_SUPPORT_GPU
225
MakeRenderTarget(GrContext *,SkBudgeted,const SkImageInfo &,int,GrSurfaceOrigin,const SkSurfaceProps *)226 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&,
227 int, GrSurfaceOrigin, const SkSurfaceProps*) {
228 return nullptr;
229 }
230
MakeFromBackendTexture(GrContext *,const GrBackendTextureDesc &,sk_sp<SkColorSpace>,const SkSurfaceProps *)231 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
232 sk_sp<SkColorSpace>, const SkSurfaceProps*) {
233 return nullptr;
234 }
235
MakeFromBackendRenderTarget(GrContext *,const GrBackendRenderTargetDesc &,sk_sp<SkColorSpace>,const SkSurfaceProps *)236 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
237 const GrBackendRenderTargetDesc&,
238 sk_sp<SkColorSpace>,
239 const SkSurfaceProps*) {
240 return nullptr;
241 }
242
MakeFromBackendTextureAsRenderTarget(GrContext *,const GrBackendTextureDesc &,sk_sp<SkColorSpace>,const SkSurfaceProps *)243 sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext*, const GrBackendTextureDesc&,
244 sk_sp<SkColorSpace>, const SkSurfaceProps*) {
245 return nullptr;
246 }
247
248 #endif
249