1
2/*
3 * Copyright 2008 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#ifndef SkPixelRef_DEFINED
11#define SkPixelRef_DEFINED
12
13#include "SkBitmap.h"
14#include "SkRefCnt.h"
15#include "SkString.h"
16
17class SkColorTable;
18struct SkIRect;
19class SkMutex;
20class SkFlattenableReadBuffer;
21class SkFlattenableWriteBuffer;
22
23// this is an opaque class, not interpreted by skia
24class SkGpuTexture;
25
26#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
27
28#define SK_DECLARE_PIXEL_REF_REGISTRAR()
29
30#define SK_DEFINE_PIXEL_REF_REGISTRAR(pixelRef) \
31    static SkPixelRef::Registrar g##pixelRef##Reg(#pixelRef, \
32                                                  pixelRef::Create);
33
34#else
35
36#define SK_DECLARE_PIXEL_REF_REGISTRAR() static void Init();
37
38#define SK_DEFINE_PIXEL_REF_REGISTRAR(pixelRef) \
39    void pixelRef::Init() { \
40        SkPixelRef::Registrar(#pixelRef, Create); \
41    }
42
43#endif
44
45/** \class SkPixelRef
46
47    This class is the smart container for pixel memory, and is used with
48    SkBitmap. A pixelref is installed into a bitmap, and then the bitmap can
49    access the actual pixel memory by calling lockPixels/unlockPixels.
50
51    This class can be shared/accessed between multiple threads.
52*/
53class SK_API SkPixelRef : public SkRefCnt {
54public:
55    explicit SkPixelRef(SkBaseMutex* mutex = NULL);
56
57    /** Return the pixel memory returned from lockPixels, or null if the
58        lockCount is 0.
59    */
60    void* pixels() const { return fPixels; }
61
62    /** Return the current colorTable (if any) if pixels are locked, or null.
63    */
64    SkColorTable* colorTable() const { return fColorTable; }
65
66    /**
67     *  Returns true if the lockcount > 0
68     */
69    bool isLocked() const { return fLockCount > 0; }
70
71    /** Call to access the pixel memory, which is returned. Balance with a call
72        to unlockPixels().
73    */
74    void lockPixels();
75    /** Call to balanace a previous call to lockPixels(). Returns the pixels
76        (or null) after the unlock. NOTE: lock calls can be nested, but the
77        matching number of unlock calls must be made in order to free the
78        memory (if the subclass implements caching/deferred-decoding.)
79    */
80    void unlockPixels();
81
82    /**
83     *  Some bitmaps can return a copy of their pixels for lockPixels(), but
84     *  that copy, if modified, will not be pushed back. These bitmaps should
85     *  not be used as targets for a raster device/canvas (since all pixels
86     *  modifications will be lost when unlockPixels() is called.)
87     */
88    bool lockPixelsAreWritable() const;
89
90    /** Returns a non-zero, unique value corresponding to the pixels in this
91        pixelref. Each time the pixels are changed (and notifyPixelsChanged is
92        called), a different generation ID will be returned.
93    */
94    uint32_t getGenerationID() const;
95
96    /** Call this if you have changed the contents of the pixels. This will in-
97        turn cause a different generation ID value to be returned from
98        getGenerationID().
99    */
100    void notifyPixelsChanged();
101
102    /** Returns true if this pixelref is marked as immutable, meaning that the
103        contents of its pixels will not change for the lifetime of the pixelref.
104    */
105    bool isImmutable() const { return fIsImmutable; }
106
107    /** Marks this pixelref is immutable, meaning that the contents of its
108        pixels will not change for the lifetime of the pixelref. This state can
109        be set on a pixelref, but it cannot be cleared once it is set.
110    */
111    void setImmutable();
112
113    /** Return the optional URI string associated with this pixelref. May be
114        null.
115    */
116    const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
117
118    /** Copy a URI string to this pixelref, or clear the URI if the uri is null
119     */
120    void setURI(const char uri[]) {
121        fURI.set(uri);
122    }
123
124    /** Copy a URI string to this pixelref
125     */
126    void setURI(const char uri[], size_t len) {
127        fURI.set(uri, len);
128    }
129
130    /** Assign a URI string to this pixelref.
131    */
132    void setURI(const SkString& uri) { fURI = uri; }
133
134    /** Are we really wrapping a texture instead of a bitmap?
135     */
136    virtual SkGpuTexture* getTexture() { return NULL; }
137
138    bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
139
140    /** Makes a deep copy of this PixelRef, respecting the requested config.
141        Returns NULL if either there is an error (e.g. the destination could
142        not be created with the given config), or this PixelRef does not
143        support deep copies.  */
144    virtual SkPixelRef* deepCopy(SkBitmap::Config config) { return NULL; }
145
146    // serialization
147
148    typedef SkPixelRef* (*Factory)(SkFlattenableReadBuffer&);
149
150    virtual Factory getFactory() const { return NULL; }
151    virtual void flatten(SkFlattenableWriteBuffer&) const;
152
153#ifdef SK_BUILD_FOR_ANDROID
154    /**
155     *  Acquire a "global" ref on this object.
156     *  The default implementation just calls ref(), but subclasses can override
157     *  this method to implement additional behavior.
158     */
159    virtual void globalRef(void* data=NULL);
160
161    /**
162     *  Release a "global" ref on this object.
163     *  The default implementation just calls unref(), but subclasses can override
164     *  this method to implement additional behavior.
165     */
166    virtual void globalUnref();
167#endif
168
169    static Factory NameToFactory(const char name[]);
170    static const char* FactoryToName(Factory);
171    static void Register(const char name[], Factory);
172
173    class Registrar {
174    public:
175        Registrar(const char name[], Factory factory) {
176            SkPixelRef::Register(name, factory);
177        }
178    };
179
180protected:
181    /** Called when the lockCount goes from 0 to 1. The caller will have already
182        acquire a mutex for thread safety, so this method need not do that.
183    */
184    virtual void* onLockPixels(SkColorTable**) = 0;
185    /** Called when the lock count goes from 1 to 0. The caller will have
186        already acquire a mutex for thread safety, so this method need not do
187        that.
188    */
189    virtual void onUnlockPixels() = 0;
190
191    /** Default impl returns true */
192    virtual bool onLockPixelsAreWritable() const;
193
194    /**
195     *  For pixelrefs that don't have access to their raw pixels, they may be
196     *  able to make a copy of them (e.g. if the pixels are on the GPU).
197     *
198     *  The base class implementation returns false;
199     */
200    virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull);
201
202    /** Return the mutex associated with this pixelref. This value is assigned
203        in the constructor, and cannot change during the lifetime of the object.
204    */
205    SkBaseMutex* mutex() const { return fMutex; }
206
207    SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*);
208
209    // only call from constructor. Flags this to always be locked, removing
210    // the need to grab the mutex and call onLockPixels/onUnlockPixels.
211    // Performance tweak to avoid those calls (esp. in multi-thread use case).
212    void setPreLocked(void* pixels, SkColorTable* ctable);
213
214    // only call from constructor. Specify a (possibly) different mutex, or
215    // null to use the default. Use with caution.
216    // The default logic is to provide a mutex, but possibly one that is
217    // shared with other instances, though this sharing is implementation
218    // specific, and it is legal for each instance to have its own mutex.
219    void useDefaultMutex() { this->setMutex(NULL); }
220
221private:
222#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
223    static void InitializeFlattenables();
224#endif
225
226    SkBaseMutex*    fMutex; // must remain in scope for the life of this object
227    void*           fPixels;
228    SkColorTable*   fColorTable;    // we do not track ownership, subclass does
229    int             fLockCount;
230
231    mutable uint32_t fGenerationID;
232
233    SkString    fURI;
234
235    // can go from false to true, but never from true to false
236    bool    fIsImmutable;
237    // only ever set in constructor, const after that
238    bool    fPreLocked;
239
240    void setMutex(SkBaseMutex* mutex);
241
242    friend class SkGraphics;
243};
244
245#endif
246