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