• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
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 
38 SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
39 
40 SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
41 
42 SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
43     : fFlags(flags)
44     , fPixelGeometry(compute_default_geometry())
45 {}
46 
47 SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
48     : fFlags(flags), fPixelGeometry(pg)
49 {}
50 
51 SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
52     : fFlags(other.fFlags)
53     , fPixelGeometry(other.fPixelGeometry)
54 {}
55 
56 ///////////////////////////////////////////////////////////////////////////////
57 
58 SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
59     : INHERITED(width, height, props) {
60 }
61 
62 SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
63     : INHERITED(info, props) {
64 }
65 
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 
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 
80 bool SkSurface_Base::outstandingImageSnapshot() const {
81     return fCachedImage && !fCachedImage->unique();
82 }
83 
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 
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 
119 static SkSurface_Base* asSB(SkSurface* surface) {
120     return static_cast<SkSurface_Base*>(surface);
121 }
122 
123 ///////////////////////////////////////////////////////////////////////////////
124 
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 
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 
141 uint32_t SkSurface::generationID() {
142     if (0 == fGenerationID) {
143         fGenerationID = asSB(this)->newGenerationID();
144     }
145     return fGenerationID;
146 }
147 
148 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
149     asSB(this)->aboutToDraw(mode);
150 }
151 
152 SkCanvas* SkSurface::getCanvas() {
153     return asSB(this)->getCachedCanvas();
154 }
155 
156 sk_sp<SkImage> SkSurface::makeImageSnapshot() {
157     return asSB(this)->refCachedImage();
158 }
159 
160 sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
161     return asSB(this)->onNewSurface(info);
162 }
163 
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 
169 bool SkSurface::peekPixels(SkPixmap* pmap) {
170     return this->getCanvas()->peekPixels(pmap);
171 }
172 
173 bool SkSurface::readPixels(const SkPixmap& pm, int srcX, int srcY) {
174     return this->getCanvas()->readPixels(pm, srcX, srcY);
175 }
176 
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 
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 
187 void SkSurface::writePixels(const SkPixmap& pmap, int x, int y) {
188     if (pmap.addr() == nullptr || pmap.width() <= 0 || pmap.height() <= 0) {
189         return;
190     }
191 
192     const SkIRect srcR = SkIRect::MakeXYWH(x, y, pmap.width(), pmap.height());
193     const SkIRect dstR = SkIRect::MakeWH(this->width(), this->height());
194     if (SkIRect::Intersects(srcR, dstR)) {
195         ContentChangeMode mode = kRetain_ContentChangeMode;
196         if (srcR.contains(dstR)) {
197             mode = kDiscard_ContentChangeMode;
198         }
199         asSB(this)->aboutToDraw(mode);
200         asSB(this)->onWritePixels(pmap, x, y);
201     }
202 }
203 
204 void SkSurface::writePixels(const SkBitmap& src, int x, int y) {
205     SkPixmap pm;
206     if (src.peekPixels(&pm)) {
207         this->writePixels(pm, x, y);
208     }
209 }
210 
211 GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) {
212     return asSB(this)->onGetTextureHandle(access);
213 }
214 
215 bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) {
216     return asSB(this)->onGetRenderTargetHandle(obj, access);
217 }
218 
219 void SkSurface::prepareForExternalIO() {
220     this->flush();
221 }
222 
223 void SkSurface::flush() {
224     asSB(this)->onFlush(0, nullptr);
225 }
226 
227 GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores,
228                                                           GrBackendSemaphore signalSemaphores[]) {
229     return asSB(this)->onFlush(numSemaphores, signalSemaphores);
230 }
231 
232 bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
233     return asSB(this)->onWait(numSemaphores, waitSemaphores);
234 }
235 
236 bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const {
237     return asSB(const_cast<SkSurface*>(this))->onCharacterize(characterization);
238 }
239 
240 bool SkSurface::draw(SkDeferredDisplayList* ddl) {
241     return asSB(this)->onDraw(ddl);
242 }
243 
244 //////////////////////////////////////////////////////////////////////////////////////
245 #include "SkNoDrawCanvas.h"
246 
247 class SkNullSurface : public SkSurface_Base {
248 public:
249     SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {}
250 
251 protected:
252     SkCanvas* onNewCanvas() override {
253         return new SkNoDrawCanvas(this->width(), this->height());
254     }
255     sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override {
256         return MakeNull(info.width(), info.height());
257     }
258     sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; }
259     void onWritePixels(const SkPixmap&, int x, int y) override {}
260     void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
261     void onCopyOnWrite(ContentChangeMode) override {}
262 };
263 
264 sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {
265     if (width < 1 || height < 1) {
266         return nullptr;
267     }
268     return sk_sp<SkSurface>(new SkNullSurface(width, height));
269 }
270 
271 //////////////////////////////////////////////////////////////////////////////////////
272 
273 #if !SK_SUPPORT_GPU
274 
275 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int,
276                                              GrSurfaceOrigin, const SkSurfaceProps*, bool) {
277     return nullptr;
278 }
279 
280 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
281                                                    GrSurfaceOrigin origin, int sampleCnt,
282                                                    sk_sp<SkColorSpace>, const SkSurfaceProps*) {
283     return nullptr;
284 }
285 
286 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
287                                                    GrSurfaceOrigin origin, int sampleCnt,
288                                                    SkColorType, sk_sp<SkColorSpace>,
289                                                    const SkSurfaceProps*) {
290     return nullptr;
291 }
292 
293 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
294                                                         const GrBackendRenderTarget&,
295                                                         GrSurfaceOrigin origin,
296                                                         sk_sp<SkColorSpace>,
297                                                         const SkSurfaceProps*) {
298     return nullptr;
299 }
300 
301 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
302                                                         const GrBackendRenderTarget&,
303                                                         GrSurfaceOrigin origin,
304                                                         SkColorType,
305                                                         sk_sp<SkColorSpace>,
306                                                         const SkSurfaceProps*) {
307     return nullptr;
308 }
309 
310 sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
311                                                                  const GrBackendTexture&,
312                                                                  GrSurfaceOrigin origin,
313                                                                  int sampleCnt,
314                                                                  sk_sp<SkColorSpace>,
315                                                                  const SkSurfaceProps*) {
316     return nullptr;
317 }
318 
319 sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
320                                                                  const GrBackendTexture&,
321                                                                  GrSurfaceOrigin origin,
322                                                                  int sampleCnt,
323                                                                  SkColorType,
324                                                                  sk_sp<SkColorSpace>,
325                                                                  const SkSurfaceProps*) {
326     return nullptr;
327 }
328 
329 #endif
330