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 = NULL;
61     fCachedImage = NULL;
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 = NULL;
68     fCachedImage = NULL;
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(NULL);
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(kYes_Budgeted);
83     if (image) {
84         canvas->drawImage(image, x, y, paint);
85         image->unref();
86     }
87 }
88 
aboutToDraw(ContentChangeMode mode)89 void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
90     this->dirtyGenerationID();
91 
92     SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
93 
94     if (fCachedImage) {
95         // the surface may need to fork its backend, if its sharing it with
96         // the cached image. Note: we only call if there is an outstanding owner
97         // on the image (besides us).
98         if (!fCachedImage->unique()) {
99             this->onCopyOnWrite(mode);
100         }
101 
102         // regardless of copy-on-write, we must drop our cached image now, so
103         // that the next request will get our new contents.
104         fCachedImage->unref();
105         fCachedImage = NULL;
106     } else if (kDiscard_ContentChangeMode == mode) {
107         this->onDiscard();
108     }
109 }
110 
newGenerationID()111 uint32_t SkSurface_Base::newGenerationID() {
112     SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
113     static int32_t gID;
114     return sk_atomic_inc(&gID) + 1;
115 }
116 
asSB(SkSurface * surface)117 static SkSurface_Base* asSB(SkSurface* surface) {
118     return static_cast<SkSurface_Base*>(surface);
119 }
120 
121 ///////////////////////////////////////////////////////////////////////////////
122 
SkSurface(int width,int height,const SkSurfaceProps * props)123 SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
124     : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
125 {
126     SkASSERT(fWidth > 0);
127     SkASSERT(fHeight > 0);
128     fGenerationID = 0;
129 }
130 
SkSurface(const SkImageInfo & info,const SkSurfaceProps * props)131 SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
132     : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
133 {
134     SkASSERT(fWidth > 0);
135     SkASSERT(fHeight > 0);
136     fGenerationID = 0;
137 }
138 
generationID()139 uint32_t SkSurface::generationID() {
140     if (0 == fGenerationID) {
141         fGenerationID = asSB(this)->newGenerationID();
142     }
143     return fGenerationID;
144 }
145 
notifyContentWillChange(ContentChangeMode mode)146 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
147     asSB(this)->aboutToDraw(mode);
148 }
149 
getCanvas()150 SkCanvas* SkSurface::getCanvas() {
151     return asSB(this)->getCachedCanvas();
152 }
153 
newImageSnapshot(Budgeted budgeted)154 SkImage* SkSurface::newImageSnapshot(Budgeted budgeted) {
155     SkImage* image = asSB(this)->getCachedImage(budgeted);
156     SkSafeRef(image);   // the caller will call unref() to balance this
157     return image;
158 }
159 
newSurface(const SkImageInfo & info)160 SkSurface* SkSurface::newSurface(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(SkImageInfo * info,size_t * rowBytes)169 const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) {
170     return this->getCanvas()->peekPixels(info, rowBytes);
171 }
172 
readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY)173 bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
174                            int srcX, int srcY) {
175     return this->getCanvas()->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
176 }
177 
178 //////////////////////////////////////////////////////////////////////////////////////
179 
180 #if !SK_SUPPORT_GPU
181 
NewRenderTargetDirect(GrRenderTarget *,const SkSurfaceProps *)182 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*) {
183     return NULL;
184 }
185 
NewRenderTarget(GrContext *,Budgeted,const SkImageInfo &,int,const SkSurfaceProps *)186 SkSurface* SkSurface::NewRenderTarget(GrContext*, Budgeted, const SkImageInfo&, int,
187                                       const SkSurfaceProps*) {
188     return NULL;
189 }
190 
NewWrappedRenderTarget(GrContext *,GrBackendTextureDesc,const SkSurfaceProps *)191 SkSurface* SkSurface::NewWrappedRenderTarget(GrContext*, GrBackendTextureDesc,
192                                              const SkSurfaceProps*) {
193     return NULL;
194 }
195 
196 #endif
197