• Home
  • 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 "GrBackendSurface.h"
9 #include "SkCanvas.h"
10 #include "SkFontLCDConfig.h"
11 #include "SkImagePriv.h"
12 #include "SkSurface_Base.h"
13 #include <atomic>
14 
compute_default_geometry()15 static SkPixelGeometry compute_default_geometry() {
16     SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder();
17     if (SkFontLCDConfig::kNONE_LCDOrder == order) {
18         return kUnknown_SkPixelGeometry;
19     } else {
20         // Bit0 is RGB(0), BGR(1)
21         // Bit1 is H(0), V(1)
22         const SkPixelGeometry gGeo[] = {
23             kRGB_H_SkPixelGeometry,
24             kBGR_H_SkPixelGeometry,
25             kRGB_V_SkPixelGeometry,
26             kBGR_V_SkPixelGeometry,
27         };
28         int index = 0;
29         if (SkFontLCDConfig::kBGR_LCDOrder == order) {
30             index |= 1;
31         }
32         if (SkFontLCDConfig::kVertical_LCDOrientation == SkFontLCDConfig::GetSubpixelOrientation()){
33             index |= 2;
34         }
35         return gGeo[index];
36     }
37 }
38 
SkSurfaceProps()39 SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
40 
SkSurfaceProps(InitType)41 SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
42 
SkSurfaceProps(uint32_t flags,InitType)43 SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
44     : fFlags(flags)
45     , fPixelGeometry(compute_default_geometry())
46 {}
47 
SkSurfaceProps(uint32_t flags,SkPixelGeometry pg)48 SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
49     : fFlags(flags), fPixelGeometry(pg)
50 {}
51 
SkSurfaceProps(const SkSurfaceProps & other)52 SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
53     : fFlags(other.fFlags)
54     , fPixelGeometry(other.fPixelGeometry)
55 {}
56 
57 ///////////////////////////////////////////////////////////////////////////////
58 
SkSurface_Base(int width,int height,const SkSurfaceProps * props)59 SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
60     : INHERITED(width, height, props) {
61 }
62 
SkSurface_Base(const SkImageInfo & info,const SkSurfaceProps * props)63 SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
64     : INHERITED(info, props) {
65 }
66 
~SkSurface_Base()67 SkSurface_Base::~SkSurface_Base() {
68     // in case the canvas outsurvives us, we null the callback
69     if (fCachedCanvas) {
70         fCachedCanvas->setSurfaceBase(nullptr);
71     }
72 }
73 
onGetBackendTexture(BackendHandleAccess)74 GrBackendTexture SkSurface_Base::onGetBackendTexture(BackendHandleAccess) {
75     return GrBackendTexture(); // invalid
76 }
77 
onGetBackendRenderTarget(BackendHandleAccess)78 GrBackendRenderTarget SkSurface_Base::onGetBackendRenderTarget(BackendHandleAccess) {
79     return GrBackendRenderTarget(); // invalid
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();
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.reset();
110 
111         if (unique) {
112             // Our content isn't held by any image now, so we can consider that content mutable.
113             // Raster surfaces need to be told it's safe to consider its pixels mutable again.
114             // We make this call after the ->unref() so the subclass can assert there are no images.
115             this->onRestoreBackingMutability();
116         }
117     } else if (kDiscard_ContentChangeMode == mode) {
118         this->onDiscard();
119     }
120 }
121 
newGenerationID()122 uint32_t SkSurface_Base::newGenerationID() {
123     SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
124     static std::atomic<uint32_t> nextID{1};
125     return nextID++;
126 }
127 
asSB(SkSurface * surface)128 static SkSurface_Base* asSB(SkSurface* surface) {
129     return static_cast<SkSurface_Base*>(surface);
130 }
131 
132 ///////////////////////////////////////////////////////////////////////////////
133 
SkSurface(int width,int height,const SkSurfaceProps * props)134 SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
135     : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
136 {
137     SkASSERT(fWidth > 0);
138     SkASSERT(fHeight > 0);
139     fGenerationID = 0;
140 }
141 
SkSurface(const SkImageInfo & info,const SkSurfaceProps * props)142 SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
143     : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
144 {
145     SkASSERT(fWidth > 0);
146     SkASSERT(fHeight > 0);
147     fGenerationID = 0;
148 }
149 
generationID()150 uint32_t SkSurface::generationID() {
151     if (0 == fGenerationID) {
152         fGenerationID = asSB(this)->newGenerationID();
153     }
154     return fGenerationID;
155 }
156 
notifyContentWillChange(ContentChangeMode mode)157 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
158     asSB(this)->aboutToDraw(mode);
159 }
160 
getCanvas()161 SkCanvas* SkSurface::getCanvas() {
162     return asSB(this)->getCachedCanvas();
163 }
164 
makeImageSnapshot()165 sk_sp<SkImage> SkSurface::makeImageSnapshot() {
166     return asSB(this)->refCachedImage();
167 }
168 
makeImageSnapshot(const SkIRect & srcBounds)169 sk_sp<SkImage> SkSurface::makeImageSnapshot(const SkIRect& srcBounds) {
170     const SkIRect surfBounds = { 0, 0, fWidth, fHeight };
171     SkIRect bounds = srcBounds;
172     if (!bounds.intersect(surfBounds)) {
173         return nullptr;
174     }
175     SkASSERT(!bounds.isEmpty());
176     if (bounds == surfBounds) {
177         return this->makeImageSnapshot();
178     } else {
179         return asSB(this)->onNewImageSnapshot(&bounds);
180     }
181 }
182 
makeSurface(const SkImageInfo & info)183 sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
184     return asSB(this)->onNewSurface(info);
185 }
186 
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)187 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
188                      const SkPaint* paint) {
189     return asSB(this)->onDraw(canvas, x, y, paint);
190 }
191 
peekPixels(SkPixmap * pmap)192 bool SkSurface::peekPixels(SkPixmap* pmap) {
193     return this->getCanvas()->peekPixels(pmap);
194 }
195 
readPixels(const SkPixmap & pm,int srcX,int srcY)196 bool SkSurface::readPixels(const SkPixmap& pm, int srcX, int srcY) {
197     return this->getCanvas()->readPixels(pm, srcX, srcY);
198 }
199 
readPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int srcX,int srcY)200 bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
201                            int srcX, int srcY) {
202     return this->readPixels({dstInfo, dstPixels, dstRowBytes}, srcX, srcY);
203 }
204 
readPixels(const SkBitmap & bitmap,int srcX,int srcY)205 bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) {
206     SkPixmap pm;
207     return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY);
208 }
209 
writePixels(const SkPixmap & pmap,int x,int y)210 void SkSurface::writePixels(const SkPixmap& pmap, int x, int y) {
211     if (pmap.addr() == nullptr || pmap.width() <= 0 || pmap.height() <= 0) {
212         return;
213     }
214 
215     const SkIRect srcR = SkIRect::MakeXYWH(x, y, pmap.width(), pmap.height());
216     const SkIRect dstR = SkIRect::MakeWH(this->width(), this->height());
217     if (SkIRect::Intersects(srcR, dstR)) {
218         ContentChangeMode mode = kRetain_ContentChangeMode;
219         if (srcR.contains(dstR)) {
220             mode = kDiscard_ContentChangeMode;
221         }
222         asSB(this)->aboutToDraw(mode);
223         asSB(this)->onWritePixels(pmap, x, y);
224     }
225 }
226 
writePixels(const SkBitmap & src,int x,int y)227 void SkSurface::writePixels(const SkBitmap& src, int x, int y) {
228     SkPixmap pm;
229     if (src.peekPixels(&pm)) {
230         this->writePixels(pm, x, y);
231     }
232 }
233 
getBackendTexture(BackendHandleAccess access)234 GrBackendTexture SkSurface::getBackendTexture(BackendHandleAccess access) {
235     return asSB(this)->onGetBackendTexture(access);
236 }
237 
getBackendRenderTarget(BackendHandleAccess access)238 GrBackendRenderTarget SkSurface::getBackendRenderTarget(BackendHandleAccess access) {
239     return asSB(this)->onGetBackendRenderTarget(access);
240 }
241 
prepareForExternalIO()242 void SkSurface::prepareForExternalIO() {
243     this->flush();
244 }
245 
flush()246 void SkSurface::flush() {
247     asSB(this)->onFlush(BackendSurfaceAccess::kNoAccess, kNone_GrFlushFlags, 0, nullptr,
248                         nullptr, nullptr);
249 }
250 
flush(BackendSurfaceAccess access,GrFlushFlags flags,int numSemaphores,GrBackendSemaphore signalSemaphores[],GrGpuFinishedProc finishedProc,GrGpuFinishedContext finishedContext)251 GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, GrFlushFlags flags,
252                                        int numSemaphores, GrBackendSemaphore signalSemaphores[],
253                                        GrGpuFinishedProc finishedProc,
254                                        GrGpuFinishedContext finishedContext) {
255     return asSB(this)->onFlush(access, flags, numSemaphores, signalSemaphores, finishedProc,
256                                finishedContext);
257 }
258 
flush(BackendSurfaceAccess access,FlushFlags flags,int numSemaphores,GrBackendSemaphore signalSemaphores[])259 GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, FlushFlags flags,
260                                        int numSemaphores, GrBackendSemaphore signalSemaphores[]) {
261     GrFlushFlags grFlags = flags == kSyncCpu_FlushFlag ? kSyncCpu_GrFlushFlag : kNone_GrFlushFlags;
262     return this->flush(access, grFlags, numSemaphores, signalSemaphores);
263 }
264 
flushAndSignalSemaphores(int numSemaphores,GrBackendSemaphore signalSemaphores[])265 GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores,
266                                                           GrBackendSemaphore signalSemaphores[]) {
267     return asSB(this)->onFlush(BackendSurfaceAccess::kNoAccess, kNone_GrFlushFlags,
268                                numSemaphores, signalSemaphores, nullptr, nullptr);
269 }
270 
wait(int numSemaphores,const GrBackendSemaphore * waitSemaphores)271 bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
272     return asSB(this)->onWait(numSemaphores, waitSemaphores);
273 }
274 
characterize(SkSurfaceCharacterization * characterization) const275 bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const {
276     return asSB(const_cast<SkSurface*>(this))->onCharacterize(characterization);
277 }
278 
draw(SkDeferredDisplayList * ddl)279 bool SkSurface::draw(SkDeferredDisplayList* ddl) {
280     return asSB(this)->onDraw(ddl);
281 }
282 
283 //////////////////////////////////////////////////////////////////////////////////////
284 #include "SkNoDrawCanvas.h"
285 
286 class SkNullSurface : public SkSurface_Base {
287 public:
SkNullSurface(int width,int height)288     SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {}
289 
290 protected:
onNewCanvas()291     SkCanvas* onNewCanvas() override {
292         return new SkNoDrawCanvas(this->width(), this->height());
293     }
onNewSurface(const SkImageInfo & info)294     sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override {
295         return MakeNull(info.width(), info.height());
296     }
onNewImageSnapshot(const SkIRect * subsetOrNull)297     sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subsetOrNull) override { return nullptr; }
onWritePixels(const SkPixmap &,int x,int y)298     void onWritePixels(const SkPixmap&, int x, int y) override {}
onDraw(SkCanvas *,SkScalar x,SkScalar y,const SkPaint *)299     void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
onCopyOnWrite(ContentChangeMode)300     void onCopyOnWrite(ContentChangeMode) override {}
301 };
302 
MakeNull(int width,int height)303 sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {
304     if (width < 1 || height < 1) {
305         return nullptr;
306     }
307     return sk_sp<SkSurface>(new SkNullSurface(width, height));
308 }
309 
310 //////////////////////////////////////////////////////////////////////////////////////
311 
312 #if !SK_SUPPORT_GPU
313 
MakeRenderTarget(GrContext *,SkBudgeted,const SkImageInfo &,int,GrSurfaceOrigin,const SkSurfaceProps *,bool)314 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int,
315                                              GrSurfaceOrigin, const SkSurfaceProps*, bool) {
316     return nullptr;
317 }
318 
MakeRenderTarget(GrRecordingContext *,const SkSurfaceCharacterization &,SkBudgeted)319 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext*, const SkSurfaceCharacterization&,
320                                              SkBudgeted) {
321     return nullptr;
322 }
323 
MakeFromBackendTexture(GrContext *,const GrBackendTexture &,GrSurfaceOrigin origin,int sampleCnt,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *,TextureReleaseProc,ReleaseContext)324 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
325                                                    GrSurfaceOrigin origin, int sampleCnt,
326                                                    SkColorType, sk_sp<SkColorSpace>,
327                                                    const SkSurfaceProps*,
328                                                    TextureReleaseProc, ReleaseContext) {
329     return nullptr;
330 }
331 
MakeFromBackendRenderTarget(GrContext *,const GrBackendRenderTarget &,GrSurfaceOrigin origin,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *,RenderTargetReleaseProc,ReleaseContext)332 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
333                                                         const GrBackendRenderTarget&,
334                                                         GrSurfaceOrigin origin,
335                                                         SkColorType,
336                                                         sk_sp<SkColorSpace>,
337                                                         const SkSurfaceProps*,
338                                                         RenderTargetReleaseProc, ReleaseContext) {
339     return nullptr;
340 }
341 
MakeFromBackendTextureAsRenderTarget(GrContext *,const GrBackendTexture &,GrSurfaceOrigin origin,int sampleCnt,SkColorType,sk_sp<SkColorSpace>,const SkSurfaceProps *)342 sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
343                                                                  const GrBackendTexture&,
344                                                                  GrSurfaceOrigin origin,
345                                                                  int sampleCnt,
346                                                                  SkColorType,
347                                                                  sk_sp<SkColorSpace>,
348                                                                  const SkSurfaceProps*) {
349     return nullptr;
350 }
351 
352 #endif
353