diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/core/SkBitmap.h | 3 | ||||
-rw-r--r-- | include/core/SkImageInfo.h | 17 | ||||
-rw-r--r-- | include/core/SkPixelRef.h | 32 | ||||
-rw-r--r-- | include/core/SkPixmap.h | 152 |
4 files changed, 202 insertions, 2 deletions
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h index a39c8688ae..144e93ba88 100644 --- a/include/core/SkBitmap.h +++ b/include/core/SkBitmap.h @@ -11,6 +11,7 @@ #include "SkColor.h" #include "SkColorTable.h" #include "SkImageInfo.h" +#include "SkPixmap.h" #include "SkPoint.h" #include "SkRefCnt.h" @@ -428,6 +429,8 @@ public: */ bool lockPixelsAreWritable() const; + bool requestLock(SkAutoPixmapUnlock* result) const; + /** Call this to be sure that the bitmap is valid enough to be drawn (i.e. it has non-null pixels, and if required by its colortype, it has a non-null colortable. Returns true if all of the above are met. diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h index 01318fd1aa..daa50dcdb2 100644 --- a/include/core/SkImageInfo.h +++ b/include/core/SkImageInfo.h @@ -111,6 +111,17 @@ static inline bool SkColorTypeIsValid(unsigned value) { return value <= kLastEnum_SkColorType; } +static inline size_t SkColorTypeComputeOffset(SkColorType ct, int x, int y, size_t rowBytes) { + int shift = 0; + switch (SkColorTypeBytesPerPixel(ct)) { + case 4: shift = 2; break; + case 2: shift = 1; break; + case 1: shift = 0; break; + default: return 0; + } + return y * rowBytes + (x << shift); +} + /////////////////////////////////////////////////////////////////////////////// /** @@ -247,6 +258,12 @@ public: return (size_t)this->minRowBytes64(); } + size_t computeOffset(int x, int y, size_t rowBytes) const { + SkASSERT((unsigned)x < (unsigned)fWidth); + SkASSERT((unsigned)y < (unsigned)fHeight); + return SkColorTypeComputeOffset(fColorType, x, y, rowBytes); + } + bool operator==(const SkImageInfo& other) const { return 0 == memcmp(this, &other, sizeof(other)); } diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h index 8a1e3db2b6..7c3156ee74 100644 --- a/include/core/SkPixelRef.h +++ b/include/core/SkPixelRef.h @@ -10,15 +10,15 @@ #include "SkAtomics.h" #include "SkBitmap.h" +#include "SkFilterQuality.h" #include "SkImageInfo.h" #include "SkMutex.h" +#include "SkPixmap.h" #include "SkRefCnt.h" #include "SkSize.h" #include "SkString.h" #include "SkTDArray.h" -//#define xed - #ifdef SK_DEBUG /** * Defining SK_IGNORE_PIXELREF_SETPRELOCKED will force all pixelref @@ -193,6 +193,30 @@ public: return this->onRefEncodedData(); } + struct LockRequest { + SkISize fSize; + SkFilterQuality fQuality; + }; + + struct LockResult { + void (*fUnlockProc)(void* ctx); + void* fUnlockContext; + + SkColorTable* fCTable; // should be NULL unless colortype is kIndex8 + const void* fPixels; + size_t fRowBytes; + SkISize fSize; + + void unlock() { + if (fUnlockProc) { + fUnlockProc(fUnlockContext); + fUnlockProc = NULL; // can't unlock twice! + } + } + }; + + bool requestLock(const LockRequest&, LockResult*); + /** Are we really wrapping a texture instead of a bitmap? */ virtual GrTexture* getTexture() { return NULL; } @@ -299,6 +323,8 @@ protected: */ virtual size_t getAllocatedSizeInBytes() const; + virtual bool onRequestLock(const LockRequest&, LockResult*); + /** Return the mutex associated with this pixelref. This value is assigned in the constructor, and cannot change during the lifetime of the object. */ @@ -319,6 +345,8 @@ private: LockRec fRec; int fLockCount; + bool lockPixelsInsideMutex(LockRec* rec); + // Bottom bit indicates the Gen ID is unique. bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); } mutable SkAtomic<uint32_t> fTaggedGenID; diff --git a/include/core/SkPixmap.h b/include/core/SkPixmap.h new file mode 100644 index 0000000000..a2ce6cd788 --- /dev/null +++ b/include/core/SkPixmap.h @@ -0,0 +1,152 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkPixmap_DEFINED +#define SkPixmap_DEFINED + +#include "SkImageInfo.h" + +class SkColorTable; + +/** + * Pairs SkImageInfo with actual pixels and rowbytes. This class does not try to manage the + * lifetime of the pixel memory (nor the colortable if provided). + */ +class SkPixmap { +public: + SkPixmap() + : fPixels(NULL), fCTable(NULL), fRowBytes(0), fInfo(SkImageInfo::MakeUnknown(0, 0)) + {} + + SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes, + SkColorTable* ctable = NULL) + : fPixels(addr), fCTable(ctable), fRowBytes(rowBytes), fInfo(info) + { + if (kIndex_8_SkColorType == info.colorType()) { + SkASSERT(ctable); + } else { + SkASSERT(NULL == ctable); + } + } + + const SkImageInfo& info() const { return fInfo; } + size_t rowBytes() const { return fRowBytes; } + const void* addr() const { return fPixels; } + SkColorTable* ctable() const { return fCTable; } + + int width() const { return fInfo.width(); } + int height() const { return fInfo.height(); } + SkColorType colorType() const { return fInfo.colorType(); } + SkAlphaType alphaType() const { return fInfo.alphaType(); } + bool isOpaque() const { return fInfo.isOpaque(); } + + int64_t getSafeSize64() const { return fInfo.getSafeSize64(fRowBytes); } + size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); } + + const uint32_t* addr32() const { + SkASSERT(4 == SkColorTypeBytesPerPixel(fInfo.colorType())); + return reinterpret_cast<const uint32_t*>(fPixels); + } + + const uint16_t* addr16() const { + SkASSERT(2 == SkColorTypeBytesPerPixel(fInfo.colorType())); + return reinterpret_cast<const uint16_t*>(fPixels); + } + + const uint8_t* addr8() const { + SkASSERT(1 == SkColorTypeBytesPerPixel(fInfo.colorType())); + return reinterpret_cast<const uint8_t*>(fPixels); + } + + const uint32_t* addr32(int x, int y) const { + SkASSERT((unsigned)x < (unsigned)fInfo.width()); + SkASSERT((unsigned)y < (unsigned)fInfo.height()); + return (const uint32_t*)((const char*)this->addr32() + y * fRowBytes + (x << 2)); + } + const uint16_t* addr16(int x, int y) const { + SkASSERT((unsigned)x < (unsigned)fInfo.width()); + SkASSERT((unsigned)y < (unsigned)fInfo.height()); + return (const uint16_t*)((const char*)this->addr16() + y * fRowBytes + (x << 1)); + } + const uint8_t* addr8(int x, int y) const { + SkASSERT((unsigned)x < (unsigned)fInfo.width()); + SkASSERT((unsigned)y < (unsigned)fInfo.height()); + return (const uint8_t*)((const char*)this->addr8() + y * fRowBytes + (x << 0)); + } + const void* addr(int x, int y) const { + return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes); + } + + // Writable versions + + void* writable_addr() const { return const_cast<void*>(fPixels); } + uint32_t* writable_addr32(int x, int y) const { + return const_cast<uint32_t*>(this->addr32(x, y)); + } + uint16_t* writable_addr16(int x, int y) const { + return const_cast<uint16_t*>(this->addr16(x, y)); + } + uint8_t* writable_addr8(int x, int y) const { + return const_cast<uint8_t*>(this->addr8(x, y)); + } + +private: + const void* fPixels; + SkColorTable* fCTable; + size_t fRowBytes; + SkImageInfo fInfo; +}; + +///////////////////////////////////////////////////////////////////////////////////////////// + +class SkAutoPixmapUnlock : ::SkNoncopyable { +public: + SkAutoPixmapUnlock() : fUnlockProc(NULL), fIsLocked(false) {} + SkAutoPixmapUnlock(const SkPixmap& pm, void (*unlock)(void*), void* ctx) + : fUnlockProc(unlock), fUnlockContext(ctx), fPixmap(pm), fIsLocked(true) + {} + ~SkAutoPixmapUnlock() { this->unlock(); } + + /** + * Return the currently locked pixmap. Undefined if it has been unlocked. + */ + const SkPixmap& pixmap() const { + SkASSERT(this->isLocked()); + return fPixmap; + } + + bool isLocked() const { return fIsLocked; } + + /** + * Unlocks the pixmap. Can safely be called more than once as it will only call the underlying + * unlock-proc once. + */ + void unlock() { + if (fUnlockProc) { + SkASSERT(fIsLocked); + fUnlockProc(fUnlockContext); + fUnlockProc = NULL; + fIsLocked = false; + } + } + + /** + * If there is a currently locked pixmap, unlock it, then copy the specified pixmap + * and (optional) unlock proc/context. + */ + void reset(const SkPixmap& pm, void (*unlock)(void*), void* ctx); + +private: + void (*fUnlockProc)(void*); + void* fUnlockContext; + SkPixmap fPixmap; + bool fIsLocked; + + friend class SkBitmap; +}; + +#endif |