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"
14static 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
38SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
39
40SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
41
42SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
43    : fFlags(flags)
44    , fPixelGeometry(compute_default_geometry())
45{}
46
47SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
48    : fFlags(flags), fPixelGeometry(pg)
49{}
50
51SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
52    : fFlags(other.fFlags)
53    , fPixelGeometry(other.fPixelGeometry)
54{}
55
56///////////////////////////////////////////////////////////////////////////////
57
58SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
59    : INHERITED(width, height, props) {
60}
61
62SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
63    : INHERITED(info, props) {
64}
65
66SkSurface_Base::~SkSurface_Base() {
67    // in case the canvas outsurvives us, we null the callback
68    if (fCachedCanvas) {
69        fCachedCanvas->setSurfaceBase(nullptr);
70    }
71}
72
73void 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
80bool SkSurface_Base::outstandingImageSnapshot() const {
81    return fCachedImage && !fCachedImage->unique();
82}
83
84void 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
113uint32_t SkSurface_Base::newGenerationID() {
114    SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
115    static int32_t gID;
116    return sk_atomic_inc(&gID) + 1;
117}
118
119static SkSurface_Base* asSB(SkSurface* surface) {
120    return static_cast<SkSurface_Base*>(surface);
121}
122
123///////////////////////////////////////////////////////////////////////////////
124
125SkSurface::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
133SkSurface::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
141uint32_t SkSurface::generationID() {
142    if (0 == fGenerationID) {
143        fGenerationID = asSB(this)->newGenerationID();
144    }
145    return fGenerationID;
146}
147
148void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
149    asSB(this)->aboutToDraw(mode);
150}
151
152SkCanvas* SkSurface::getCanvas() {
153    return asSB(this)->getCachedCanvas();
154}
155
156sk_sp<SkImage> SkSurface::makeImageSnapshot() {
157    return asSB(this)->refCachedImage();
158}
159
160sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
161    return asSB(this)->onNewSurface(info);
162}
163
164void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
165                     const SkPaint* paint) {
166    return asSB(this)->onDraw(canvas, x, y, paint);
167}
168
169bool SkSurface::peekPixels(SkPixmap* pmap) {
170    return this->getCanvas()->peekPixels(pmap);
171}
172
173bool SkSurface::readPixels(const SkPixmap& pm, int srcX, int srcY) {
174    return this->getCanvas()->readPixels(pm, srcX, srcY);
175}
176
177bool 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
182bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) {
183    SkPixmap pm;
184    return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY);
185}
186
187GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) {
188    return asSB(this)->onGetTextureHandle(access);
189}
190
191bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) {
192    return asSB(this)->onGetRenderTargetHandle(obj, access);
193}
194
195void SkSurface::prepareForExternalIO() {
196    this->flush();
197}
198
199void SkSurface::flush() {
200    asSB(this)->onFlush(0, nullptr);
201}
202
203GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores,
204                                                          GrBackendSemaphore signalSemaphores[]) {
205    return asSB(this)->onFlush(numSemaphores, signalSemaphores);
206}
207
208bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
209    return asSB(this)->onWait(numSemaphores, waitSemaphores);
210}
211
212bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const {
213    return asSB(const_cast<SkSurface*>(this))->onCharacterize(characterization);
214}
215
216bool SkSurface::draw(SkDeferredDisplayList* ddl) {
217    return asSB(this)->onDraw(ddl);
218}
219
220//////////////////////////////////////////////////////////////////////////////////////
221#include "SkNoDrawCanvas.h"
222
223class SkNullSurface : public SkSurface_Base {
224public:
225    SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {}
226
227protected:
228    SkCanvas* onNewCanvas() override {
229        return new SkNoDrawCanvas(this->width(), this->height());
230    }
231    sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override {
232        return MakeNull(info.width(), info.height());
233    }
234    sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; }
235    void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
236    void onCopyOnWrite(ContentChangeMode) override {}
237};
238
239sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {
240    if (width < 1 || height < 1) {
241        return nullptr;
242    }
243    return sk_sp<SkSurface>(new SkNullSurface(width, height));
244}
245
246//////////////////////////////////////////////////////////////////////////////////////
247
248#if !SK_SUPPORT_GPU
249
250sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int,
251                                             GrSurfaceOrigin, const SkSurfaceProps*, bool) {
252    return nullptr;
253}
254
255sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
256                                                   GrSurfaceOrigin origin, int sampleCnt,
257                                                   sk_sp<SkColorSpace>, const SkSurfaceProps*) {
258    return nullptr;
259}
260
261sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
262                                                   GrSurfaceOrigin origin, int sampleCnt,
263                                                   SkColorType, sk_sp<SkColorSpace>,
264                                                   const SkSurfaceProps*) {
265    return nullptr;
266}
267
268sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
269                                                        const GrBackendRenderTarget&,
270                                                        GrSurfaceOrigin origin,
271                                                        sk_sp<SkColorSpace>,
272                                                        const SkSurfaceProps*) {
273    return nullptr;
274}
275
276sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
277                                                        const GrBackendRenderTarget&,
278                                                        GrSurfaceOrigin origin,
279                                                        SkColorType,
280                                                        sk_sp<SkColorSpace>,
281                                                        const SkSurfaceProps*) {
282    return nullptr;
283}
284
285sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
286                                                                 const GrBackendTexture&,
287                                                                 GrSurfaceOrigin origin,
288                                                                 int sampleCnt,
289                                                                 sk_sp<SkColorSpace>,
290                                                                 const SkSurfaceProps*) {
291    return nullptr;
292}
293
294sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
295                                                                 const GrBackendTexture&,
296                                                                 GrSurfaceOrigin origin,
297                                                                 int sampleCnt,
298                                                                 SkColorType,
299                                                                 sk_sp<SkColorSpace>,
300                                                                 const SkSurfaceProps*) {
301    return nullptr;
302}
303
304#endif
305