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 SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
174                           int srcX, int srcY) {
175    return this->getCanvas()->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
176}
177
178GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) {
179    return asSB(this)->onGetTextureHandle(access);
180}
181
182bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) {
183    return asSB(this)->onGetRenderTargetHandle(obj, access);
184}
185
186void SkSurface::prepareForExternalIO() {
187    this->flush();
188}
189
190void SkSurface::flush() {
191    asSB(this)->onFlush(0, nullptr);
192}
193
194bool SkSurface::flushAndSignalSemaphores(int numSemaphores, GrBackendSemaphore* signalSemaphores) {
195    return asSB(this)->onFlush(numSemaphores, signalSemaphores);
196}
197
198bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
199    return asSB(this)->onWait(numSemaphores, waitSemaphores);
200}
201
202//////////////////////////////////////////////////////////////////////////////////////
203#include "SkNoDrawCanvas.h"
204
205class SkNullSurface : public SkSurface_Base {
206public:
207    SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {}
208
209protected:
210    SkCanvas* onNewCanvas() override {
211        return new SkNoDrawCanvas(this->width(), this->height());
212    }
213    sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override {
214        return MakeNull(info.width(), info.height());
215    }
216    sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; }
217    void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
218    void onCopyOnWrite(ContentChangeMode) override {}
219};
220
221sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {
222    if (width < 1 || height < 1) {
223        return nullptr;
224    }
225    return sk_sp<SkSurface>(new SkNullSurface(width, height));
226}
227
228//////////////////////////////////////////////////////////////////////////////////////
229
230#if !SK_SUPPORT_GPU
231
232sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&,
233                                             int, GrSurfaceOrigin, const SkSurfaceProps*) {
234    return nullptr;
235}
236
237sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
238                                                   sk_sp<SkColorSpace>, const SkSurfaceProps*) {
239    return nullptr;
240}
241
242sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
243                                                   GrSurfaceOrigin origin, int sampleCnt,
244                                                   sk_sp<SkColorSpace>, const SkSurfaceProps*) {
245    return nullptr;
246}
247
248sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
249                                                        const GrBackendRenderTargetDesc&,
250                                                        sk_sp<SkColorSpace>,
251                                                        const SkSurfaceProps*) {
252    return nullptr;
253}
254
255sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
256                                                        const GrBackendRenderTarget&,
257                                                        GrSurfaceOrigin origin,
258                                                        sk_sp<SkColorSpace>,
259                                                        const SkSurfaceProps*) {
260    return nullptr;
261}
262
263sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
264                                                                 const GrBackendTextureDesc&,
265                                                                 sk_sp<SkColorSpace>,
266                                                                 const SkSurfaceProps*) {
267    return nullptr;
268}
269
270sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
271                                                                 const GrBackendTexture&,
272                                                                 GrSurfaceOrigin origin,
273                                                                 int sampleCnt,
274                                                                 sk_sp<SkColorSpace>,
275                                                                 const SkSurfaceProps*) {
276    return nullptr;
277}
278
279#endif
280