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 "SkSurface_Base.h"
9 #include "SkImagePriv.h"
10 #include "SkCanvas.h"
11 
12 #include "SkFontLCDConfig.h"
compute_default_geometry()13 static SkPixelGeometry compute_default_geometry() {
14     SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder();
15     if (SkFontLCDConfig::kNONE_LCDOrder == order) {
16         return kUnknown_SkPixelGeometry;
17     } else {
18         // Bit0 is RGB(0), BGR(1)
19         // Bit1 is H(0), V(1)
20         const SkPixelGeometry gGeo[] = {
21             kRGB_H_SkPixelGeometry,
22             kBGR_H_SkPixelGeometry,
23             kRGB_V_SkPixelGeometry,
24             kBGR_V_SkPixelGeometry,
25         };
26         int index = 0;
27         if (SkFontLCDConfig::kBGR_LCDOrder == order) {
28             index |= 1;
29         }
30         if (SkFontLCDConfig::kVertical_LCDOrientation == SkFontLCDConfig::GetSubpixelOrientation()){
31             index |= 2;
32         }
33         return gGeo[index];
34     }
35 }
36 
SkSurfaceProps()37 SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
38 
SkSurfaceProps(InitType)39 SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
40 
SkSurfaceProps(uint32_t flags,InitType)41 SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
42     : fFlags(flags)
43     , fPixelGeometry(compute_default_geometry())
44 {}
45 
SkSurfaceProps(uint32_t flags,SkPixelGeometry pg)46 SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
47     : fFlags(flags), fPixelGeometry(pg)
48 {}
49 
SkSurfaceProps(const SkSurfaceProps & other)50 SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
51     : fFlags(other.fFlags)
52     , fPixelGeometry(other.fPixelGeometry)
53 {}
54 
55 ///////////////////////////////////////////////////////////////////////////////
56 
SkSurface_Base(int width,int height,const SkSurfaceProps * props)57 SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
58     : INHERITED(width, height, props)
59 {
60     fCachedCanvas = nullptr;
61     fCachedImage = nullptr;
62 }
63 
SkSurface_Base(const SkImageInfo & info,const SkSurfaceProps * props)64 SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
65     : INHERITED(info, props)
66 {
67     fCachedCanvas = nullptr;
68     fCachedImage = nullptr;
69 }
70 
~SkSurface_Base()71 SkSurface_Base::~SkSurface_Base() {
72     // in case the canvas outsurvives us, we null the callback
73     if (fCachedCanvas) {
74         fCachedCanvas->setSurfaceBase(nullptr);
75     }
76 
77     SkSafeUnref(fCachedImage);
78     SkSafeUnref(fCachedCanvas);
79 }
80 
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)81 void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
82     SkImage* image = this->newImageSnapshot(SkBudgeted::kYes);
83     if (image) {
84         canvas->drawImage(image, x, y, paint);
85         image->unref();
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 
newImageSnapshot(SkBudgeted budgeted)166 SkImage* SkSurface::newImageSnapshot(SkBudgeted budgeted) {
167     // the caller will call unref() to balance this
168     return asSB(this)->refCachedImage(budgeted, kNo_ForceUnique);
169 }
170 
newImageSnapshot(SkBudgeted budgeted,ForceUnique unique)171 SkImage* SkSurface::newImageSnapshot(SkBudgeted budgeted, ForceUnique unique) {
172     // the caller will call unref() to balance this
173     return asSB(this)->refCachedImage(budgeted, unique);
174 }
175 
newSurface(const SkImageInfo & info)176 SkSurface* SkSurface::newSurface(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(SkImageInfo * info,size_t * rowBytes)185 const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) {
186     return this->getCanvas()->peekPixels(info, rowBytes);
187 }
188 
readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY)189 bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
190                            int srcX, int srcY) {
191     return this->getCanvas()->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
192 }
193 
getTextureHandle(BackendHandleAccess access)194 GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) {
195     return asSB(this)->onGetTextureHandle(access);
196 }
197 
getRenderTargetHandle(GrBackendObject * obj,BackendHandleAccess access)198 bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) {
199     return asSB(this)->onGetRenderTargetHandle(obj, access);
200 }
201 
prepareForExternalIO()202 void SkSurface::prepareForExternalIO() {
203   asSB(this)->onPrepareForExternalIO();
204 }
205 
206 //////////////////////////////////////////////////////////////////////////////////////
207 
208 #if !SK_SUPPORT_GPU
209 
NewRenderTargetDirect(GrRenderTarget *,const SkSurfaceProps *)210 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*) {
211     return nullptr;
212 }
213 
NewRenderTarget(GrContext *,SkBudgeted,const SkImageInfo &,int,const SkSurfaceProps *,GrTextureStorageAllocator)214 SkSurface* SkSurface::NewRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int,
215                                       const SkSurfaceProps*, GrTextureStorageAllocator) {
216     return nullptr;
217 }
218 
NewFromBackendTexture(GrContext *,const GrBackendTextureDesc &,const SkSurfaceProps *)219 SkSurface* SkSurface::NewFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
220                                              const SkSurfaceProps*) {
221     return nullptr;
222 }
223 
NewFromBackendRenderTarget(GrContext *,const GrBackendRenderTargetDesc &,const SkSurfaceProps *)224 SkSurface* SkSurface::NewFromBackendRenderTarget(GrContext*, const GrBackendRenderTargetDesc&,
225                                                  const SkSurfaceProps*) {
226     return nullptr;
227 }
228 
NewFromBackendTextureAsRenderTarget(GrContext *,const GrBackendTextureDesc &,const SkSurfaceProps *)229 SkSurface* NewFromBackendTextureAsRenderTarget(GrContext*, const GrBackendTextureDesc&,
230                                                const SkSurfaceProps*) {
231     return nullptr;
232 }
233 
234 #endif
235