Revert "Revert "PixelRef now returns (nearly) everything that is currently in SkBitmap. The goal is to refactor bitmap later to remove redundancy, and more interestingly, remove the chance for a disconnect between the actual (pixelref) rowbytes and config, and the one claimed by the bitmap.""

This reverts commit 4174afb18a9746bbad2a06c0ec2d4ad35f72d790.

BUG=

Review URL: https://codereview.chromium.org/108723003

git-svn-id: http://skia.googlecode.com/svn/trunk@12547 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2013-12-06 20:31:45 +00:00
Родитель cc63b32eb8
Коммит 473f0aa2bb
38 изменённых файлов: 660 добавлений и 278 удалений

Просмотреть файл

@ -250,6 +250,13 @@ public:
bool setConfig(const SkImageInfo& info, size_t rowBytes = 0); bool setConfig(const SkImageInfo& info, size_t rowBytes = 0);
/**
* If the bitmap's config can be represented as SkImageInfo, return true,
* and if info is not-null, set it to the bitmap's info. If it cannot be
* represented as SkImageInfo, return false and ignore the info parameter.
*/
bool asImageInfo(SkImageInfo* info) const;
/** Use this to assign a new pixel address for an existing bitmap. This /** Use this to assign a new pixel address for an existing bitmap. This
will automatically release any pixelref previously installed. Only call will automatically release any pixelref previously installed. Only call
this if you are handling ownership/lifetime of the pixel memory. this if you are handling ownership/lifetime of the pixel memory.

Просмотреть файл

@ -258,6 +258,8 @@ private:
friend class SkSurface_Raster; friend class SkSurface_Raster;
void init(SkBitmap::Config config, int width, int height, bool isOpaque);
// used to change the backend's pixels (and possibly config/rowbytes) // used to change the backend's pixels (and possibly config/rowbytes)
// but cannot change the width/height, so there should be no change to // but cannot change the width/height, so there should be no change to
// any clip information. // any clip information.

Просмотреть файл

@ -10,6 +10,9 @@
#include "SkTypes.h" #include "SkTypes.h"
class SkFlattenableWriteBuffer;
class SkFlattenableReadBuffer;
/** /**
* Describes how to interpret the alpha compoent of a pixel. * Describes how to interpret the alpha compoent of a pixel.
*/ */
@ -63,6 +66,7 @@ static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {
enum SkColorType { enum SkColorType {
kAlpha_8_SkColorType, kAlpha_8_SkColorType,
kRGB_565_SkColorType, kRGB_565_SkColorType,
kARGB_4444_SkColorType,
kRGBA_8888_SkColorType, kRGBA_8888_SkColorType,
kBGRA_8888_SkColorType, kBGRA_8888_SkColorType,
kIndex8_SkColorType, kIndex8_SkColorType,
@ -82,6 +86,7 @@ static int SkColorTypeBytesPerPixel(SkColorType ct) {
static const uint8_t gSize[] = { static const uint8_t gSize[] = {
1, // Alpha_8 1, // Alpha_8
2, // RGB_565 2, // RGB_565
2, // ARGB_4444
4, // RGBA_8888 4, // RGBA_8888
4, // BGRA_8888 4, // BGRA_8888
1, // kIndex_8 1, // kIndex_8
@ -112,12 +117,26 @@ struct SkImageInfo {
return SkColorTypeBytesPerPixel(fColorType); return SkColorTypeBytesPerPixel(fColorType);
} }
size_t minRowBytes() const {
return fWidth * this->bytesPerPixel();
}
bool operator==(const SkImageInfo& other) const { bool operator==(const SkImageInfo& other) const {
return 0 == memcmp(this, &other, sizeof(other)); return 0 == memcmp(this, &other, sizeof(other));
} }
bool operator!=(const SkImageInfo& other) const { bool operator!=(const SkImageInfo& other) const {
return 0 != memcmp(this, &other, sizeof(other)); return 0 != memcmp(this, &other, sizeof(other));
} }
void unflatten(SkFlattenableReadBuffer&);
void flatten(SkFlattenableWriteBuffer&) const;
size_t getSafeSize(size_t rowBytes) const {
if (0 == fHeight) {
return 0;
}
return (fHeight - 1) * rowBytes + fWidth * this->bytesPerPixel();
}
}; };
#endif #endif

Просмотреть файл

@ -17,33 +17,52 @@
*/ */
class SkMallocPixelRef : public SkPixelRef { class SkMallocPixelRef : public SkPixelRef {
public: public:
/** Allocate the specified buffer for pixels. The memory is freed when the /**
last owner of this pixelref is gone. If addr is NULL, sk_malloc_throw() * Return a new SkMallocPixelRef with the provided pixel storage, rowBytes,
is called to allocate it. * and optional colortable. The caller is responsible for managing the
* lifetime of the pixel storage buffer, as the pixelref will not try
* to delete the storage.
*
* This pixelref will ref() the specified colortable (if not NULL).
*
* Returns NULL on failure.
*/ */
SkMallocPixelRef(void* addr, size_t size, SkColorTable* ctable, bool ownPixels = true); static SkMallocPixelRef* NewDirect(const SkImageInfo&, void* addr,
virtual ~SkMallocPixelRef(); size_t rowBytes, SkColorTable*);
/**
* Return a new SkMallocPixelRef, automatically allocating storage for the
* pixels. If rowBytes are 0, an optimal value will be chosen automatically.
* If rowBytes is > 0, then it will be respected, or NULL will be returned
* if rowBytes is invalid for the specified info.
*
* This pixelref will ref() the specified colortable (if not NULL).
*
* Returns NULL on failure.
*/
static SkMallocPixelRef* NewAllocate(const SkImageInfo& info,
size_t rowBytes, SkColorTable*);
void* getAddr() const { return fStorage; } void* getAddr() const { return fStorage; }
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMallocPixelRef) SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMallocPixelRef)
protected: protected:
// overrides from SkPixelRef virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
virtual void* onLockPixels(SkColorTable**); virtual void onUnlockPixels() SK_OVERRIDE;
virtual void onUnlockPixels(); virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
SkMallocPixelRef(SkFlattenableReadBuffer& buffer); SkMallocPixelRef(SkFlattenableReadBuffer& buffer);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; SkMallocPixelRef(const SkImageInfo&, void* addr, size_t rb, SkColorTable*,
bool ownsPixels);
// Returns the allocation size for the pixels virtual ~SkMallocPixelRef();
virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE { return fSize; }
private: private:
void* fStorage; void* fStorage;
size_t fSize; SkColorTable* fCTable;
SkColorTable* fCTable; size_t fRB;
bool fOwnPixels; const bool fOwnPixels;
typedef SkPixelRef INHERITED; typedef SkPixelRef INHERITED;
}; };

Просмотреть файл

@ -220,10 +220,11 @@ protected:
// V14: Add flags word to PathRef serialization // V14: Add flags word to PathRef serialization
// V15: Remove A1 bitmpa config (and renumber remaining configs) // V15: Remove A1 bitmpa config (and renumber remaining configs)
// V16: Move SkPath's isOval flag to SkPathRef // V16: Move SkPath's isOval flag to SkPathRef
// V17: Changes to PixelRef to store SkImageInfo
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
static const uint32_t PRIOR_PICTURE_VERSION = 15; // TODO: remove when .skps regenerated static const uint32_t PRIOR_PICTURE_VERSION = 15; // TODO: remove when .skps regenerated
#endif #endif
static const uint32_t PICTURE_VERSION = 16; static const uint32_t PICTURE_VERSION = 17;
// fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to // fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to
// install their own SkPicturePlayback-derived players,SkPictureRecord-derived // install their own SkPicturePlayback-derived players,SkPictureRecord-derived

Просмотреть файл

@ -14,8 +14,11 @@
#include "SkRefCnt.h" #include "SkRefCnt.h"
#include "SkString.h" #include "SkString.h"
#include "SkFlattenable.h" #include "SkFlattenable.h"
#include "SkImageInfo.h"
#include "SkTDArray.h" #include "SkTDArray.h"
#define SK_SUPPORT_LEGACY_ONLOCKPIXELS
#ifdef SK_DEBUG #ifdef SK_DEBUG
/** /**
* Defining SK_IGNORE_PIXELREF_SETPRELOCKED will force all pixelref * Defining SK_IGNORE_PIXELREF_SETPRELOCKED will force all pixelref
@ -49,18 +52,35 @@ class SK_API SkPixelRef : public SkFlattenable {
public: public:
SK_DECLARE_INST_COUNT(SkPixelRef) SK_DECLARE_INST_COUNT(SkPixelRef)
explicit SkPixelRef(SkBaseMutex* mutex = NULL); explicit SkPixelRef(const SkImageInfo&);
SkPixelRef(const SkImageInfo&, SkBaseMutex* mutex);
virtual ~SkPixelRef(); virtual ~SkPixelRef();
const SkImageInfo& info() const {
return fInfo;
}
/** Return the pixel memory returned from lockPixels, or null if the /** Return the pixel memory returned from lockPixels, or null if the
lockCount is 0. lockCount is 0.
*/ */
void* pixels() const { return fPixels; } void* pixels() const { return fRec.fPixels; }
/** Return the current colorTable (if any) if pixels are locked, or null. /** Return the current colorTable (if any) if pixels are locked, or null.
*/ */
SkColorTable* colorTable() const { return fColorTable; } SkColorTable* colorTable() const { return fRec.fColorTable; }
/**
* To access the actual pixels of a pixelref, it must be "locked".
* Calling lockPixels returns a LockRec struct (on success).
*/
struct LockRec {
void* fPixels;
SkColorTable* fColorTable;
size_t fRowBytes;
void zero() { sk_bzero(this, sizeof(*this)); }
};
/** /**
* Returns true if the lockcount > 0 * Returns true if the lockcount > 0
*/ */
@ -68,10 +88,19 @@ public:
SkDEBUGCODE(int getLockCount() const { return fLockCount; }) SkDEBUGCODE(int getLockCount() const { return fLockCount; })
/** Call to access the pixel memory, which is returned. Balance with a call /**
to unlockPixels(). * Call to access the pixel memory. Return true on success. Balance this
*/ * with a call to unlockPixels().
void lockPixels(); */
bool lockPixels();
/**
* Call to access the pixel memory. On success, return true and fill out
* the specified rec. On failure, return false and ignore the rec parameter.
* Balance this with a call to unlockPixels().
*/
bool lockPixels(LockRec* rec);
/** Call to balanace a previous call to lockPixels(). Returns the pixels /** Call to balanace a previous call to lockPixels(). Returns the pixels
(or null) after the unlock. NOTE: lock calls can be nested, but the (or null) after the unlock. NOTE: lock calls can be nested, but the
matching number of unlock calls must be made in order to free the matching number of unlock calls must be made in order to free the
@ -228,14 +257,28 @@ public:
void addGenIDChangeListener(GenIDChangeListener* listener); void addGenIDChangeListener(GenIDChangeListener* listener);
protected: protected:
/** Called when the lockCount goes from 0 to 1. The caller will have already #ifdef SK_SUPPORT_LEGACY_ONLOCKPIXELS
acquire a mutex for thread safety, so this method need not do that. virtual void* onLockPixels(SkColorTable**);
*/ virtual bool onNewLockPixels(LockRec*);
virtual void* onLockPixels(SkColorTable**) = 0; #else
/** Called when the lock count goes from 1 to 0. The caller will have /**
already acquire a mutex for thread safety, so this method need not do * On success, returns true and fills out the LockRec for the pixels. On
that. * failure returns false and ignores the LockRec parameter.
*/ *
* The caller will have already acquired a mutex for thread safety, so this
* method need not do that.
*/
virtual bool onNewLockPixels(LockRec*) = 0;
#endif
/**
* Balancing the previous successful call to onNewLockPixels. The locked
* pixel address will no longer be referenced, so the subclass is free to
* move or discard that memory.
*
* The caller will have already acquired a mutex for thread safety, so this
* method need not do that.
*/
virtual void onUnlockPixels() = 0; virtual void onUnlockPixels() = 0;
/** Default impl returns true */ /** Default impl returns true */
@ -279,12 +322,14 @@ protected:
// only call from constructor. Flags this to always be locked, removing // only call from constructor. Flags this to always be locked, removing
// the need to grab the mutex and call onLockPixels/onUnlockPixels. // the need to grab the mutex and call onLockPixels/onUnlockPixels.
// Performance tweak to avoid those calls (esp. in multi-thread use case). // Performance tweak to avoid those calls (esp. in multi-thread use case).
void setPreLocked(void* pixels, SkColorTable* ctable); void setPreLocked(void*, size_t rowBytes, SkColorTable*);
private: private:
SkBaseMutex* fMutex; // must remain in scope for the life of this object SkBaseMutex* fMutex; // must remain in scope for the life of this object
void* fPixels; SkImageInfo fInfo;
SkColorTable* fColorTable; // we do not track ownership, subclass does
// LockRec is only valid if we're in a locked state (isLocked())
LockRec fRec;
int fLockCount; int fLockCount;
mutable uint32_t fGenerationID; mutable uint32_t fGenerationID;

Просмотреть файл

@ -15,6 +15,7 @@
class GrTexture; class GrTexture;
class GrRenderTarget; class GrRenderTarget;
struct SkImageInfo;
class GrSurface : public GrResource { class GrSurface : public GrResource {
public: public:
@ -58,6 +59,8 @@ public:
*/ */
const GrTextureDesc& desc() const { return fDesc; } const GrTextureDesc& desc() const { return fDesc; }
void asImageInfo(SkImageInfo*) const;
/** /**
* @return the texture associated with the surface, may be NULL. * @return the texture associated with the surface, may be NULL.
*/ */

Просмотреть файл

@ -50,6 +50,7 @@ GR_STATIC_ASSERT((int)kIDA_GrBlendCoeff == (int)SkXfermode::kIDA_Coeff);
* kUnknown_PixelConfig if the conversion cannot be done. * kUnknown_PixelConfig if the conversion cannot be done.
*/ */
GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config); GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config);
bool GrPixelConfig2ColorType(GrPixelConfig, SkColorType*);
static inline GrColor SkColor2GrColor(SkColor c) { static inline GrColor SkColor2GrColor(SkColor c) {
SkPMColor pm = SkPreMultiplyColor(c); SkPMColor pm = SkPreMultiplyColor(c);

Просмотреть файл

@ -23,14 +23,13 @@
*/ */
class SK_API SkROLockPixelsPixelRef : public SkPixelRef { class SK_API SkROLockPixelsPixelRef : public SkPixelRef {
public: public:
SkROLockPixelsPixelRef(); SkROLockPixelsPixelRef(const SkImageInfo&);
virtual ~SkROLockPixelsPixelRef(); virtual ~SkROLockPixelsPixelRef();
protected: protected:
// override from SkPixelRef virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
virtual void* onLockPixels(SkColorTable** ptr); virtual void onUnlockPixels() SK_OVERRIDE;
virtual void onUnlockPixels(); virtual bool onLockPixelsAreWritable() const SK_OVERRIDE; // return false;
virtual bool onLockPixelsAreWritable() const; // return false;
private: private:
SkBitmap fBitmap; SkBitmap fBitmap;
@ -47,7 +46,7 @@ public:
* cache and would like the pixel ref to unlock it in its destructor then transferCacheLock * cache and would like the pixel ref to unlock it in its destructor then transferCacheLock
* should be set to true. * should be set to true.
*/ */
SkGrPixelRef(GrSurface* surface, bool transferCacheLock = false); SkGrPixelRef(const SkImageInfo&, GrSurface*, bool transferCacheLock = false);
virtual ~SkGrPixelRef(); virtual ~SkGrPixelRef();
// override from SkPixelRef // override from SkPixelRef

Просмотреть файл

@ -34,7 +34,7 @@ public:
@param config The preferred config of the decoded bitmap. @param config The preferred config of the decoded bitmap.
@param sampleSize Requested sampleSize for decoding. Defaults to 1. @param sampleSize Requested sampleSize for decoding. Defaults to 1.
*/ */
SkImageRef(SkStreamRewindable*, SkBitmap::Config config, int sampleSize = 1, SkImageRef(const SkImageInfo&, SkStreamRewindable*, int sampleSize = 1,
SkBaseMutex* mutex = NULL); SkBaseMutex* mutex = NULL);
virtual ~SkImageRef(); virtual ~SkImageRef();
@ -72,9 +72,9 @@ protected:
When these are called, we will have already acquired the mutex! When these are called, we will have already acquired the mutex!
*/ */
virtual void* onLockPixels(SkColorTable**); virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
// override this in your subclass to clean up when we're unlocking pixels // override this in your subclass to clean up when we're unlocking pixels
virtual void onUnlockPixels() {} virtual void onUnlockPixels() SK_OVERRIDE {}
SkImageRef(SkFlattenableReadBuffer&, SkBaseMutex* mutex = NULL); SkImageRef(SkFlattenableReadBuffer&, SkBaseMutex* mutex = NULL);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
@ -89,7 +89,6 @@ private:
SkImageDecoderFactory* fFactory; // may be null SkImageDecoderFactory* fFactory; // may be null
SkStreamRewindable* fStream; SkStreamRewindable* fStream;
SkBitmap::Config fConfig;
int fSampleSize; int fSampleSize;
bool fDoDither; bool fDoDither;
bool fErrorInDecoding; bool fErrorInDecoding;

Просмотреть файл

@ -15,7 +15,7 @@
class SkImageRef_GlobalPool : public SkImageRef { class SkImageRef_GlobalPool : public SkImageRef {
public: public:
// if pool is null, use the global pool // if pool is null, use the global pool
SkImageRef_GlobalPool(SkStreamRewindable*, SkBitmap::Config, SkImageRef_GlobalPool(const SkImageInfo&, SkStreamRewindable*,
int sampleSize = 1); int sampleSize = 1);
virtual ~SkImageRef_GlobalPool(); virtual ~SkImageRef_GlobalPool();

Просмотреть файл

@ -40,7 +40,9 @@ static SkBitmap load_bitmap() {
if (SkImageDecoder::DecodeStream(stream, &bm, SkBitmap::kNo_Config, if (SkImageDecoder::DecodeStream(stream, &bm, SkBitmap::kNo_Config,
SkImageDecoder::kDecodeBounds_Mode)) { SkImageDecoder::kDecodeBounds_Mode)) {
SkPixelRef* pr = new SkImageRef_GlobalPool(stream, bm.config(), 1); SkImageInfo info;
bm.asImageInfo(&info);
SkPixelRef* pr = new SkImageRef_GlobalPool(info, stream, 1);
bm.setPixelRef(pr)->unref(); bm.setPixelRef(pr)->unref();
} }
} }

Просмотреть файл

@ -361,6 +361,48 @@ void SkBitmap::updatePixelsFromRef() const {
} }
} }
static bool config_to_colorType(SkBitmap::Config config, SkColorType* ctOut) {
SkColorType ct;
switch (config) {
case SkBitmap::kA8_Config:
ct = kAlpha_8_SkColorType;
break;
case SkBitmap::kIndex8_Config:
ct = kIndex8_SkColorType;
break;
case SkBitmap::kRGB_565_Config:
ct = kRGB_565_SkColorType;
break;
case SkBitmap::kARGB_4444_Config:
ct = kARGB_4444_SkColorType;
break;
case SkBitmap::kARGB_8888_Config:
ct = kPMColor_SkColorType;
break;
case SkBitmap::kNo_Config:
default:
return false;
}
if (ctOut) {
*ctOut = ct;
}
return true;
}
bool SkBitmap::asImageInfo(SkImageInfo* info) const {
SkColorType ct;
if (!config_to_colorType(this->config(), &ct)) {
return false;
}
if (info) {
info->fWidth = fWidth;
info->fHeight = fHeight;
info->fAlphaType = this->alphaType();
info->fColorType = ct;
}
return true;
}
SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) { SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) {
// do this first, we that we never have a non-zero offset with a null ref // do this first, we that we never have a non-zero offset with a null ref
if (NULL == pr) { if (NULL == pr) {
@ -411,10 +453,20 @@ void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
return; return;
} }
Sk64 size = this->getSize64(); SkImageInfo info;
SkASSERT(!size.isNeg() && size.is32()); if (!this->asImageInfo(&info)) {
this->setPixelRef(NULL, 0);
return;
}
SkPixelRef* pr = SkMallocPixelRef::NewDirect(info, p, fRowBytes, ctable);
if (NULL == pr) {
this->setPixelRef(NULL, 0);
return;
}
this->setPixelRef(pr)->unref();
this->setPixelRef(new SkMallocPixelRef(p, size.get32(), ctable, false))->unref();
// since we're already allocated, we lockPixels right away // since we're already allocated, we lockPixels right away
this->lockPixels(); this->lockPixels();
SkDEBUGCODE(this->validate();) SkDEBUGCODE(this->validate();)
@ -479,17 +531,19 @@ GrTexture* SkBitmap::getTexture() const {
*/ */
bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst, bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
SkColorTable* ctable) { SkColorTable* ctable) {
Sk64 size = dst->getSize64(); SkImageInfo info;
if (size.isNeg() || !size.is32()) { if (!dst->asImageInfo(&info)) {
// SkDebugf("unsupported config for info %d\n", dst->config());
return false;
}
SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(),
ctable);
if (NULL == pr) {
return false; return false;
} }
void* addr = sk_malloc_flags(size.get32(), 0); // returns NULL on failure dst->setPixelRef(pr, 0)->unref();
if (NULL == addr) {
return false;
}
dst->setPixelRef(new SkMallocPixelRef(addr, size.get32(), ctable))->unref();
// since we're already allocated, we lockPixels right away // since we're already allocated, we lockPixels right away
dst->lockPixels(); dst->lockPixels();
return true; return true;
@ -1599,6 +1653,28 @@ SkBitmap::RLEPixels::~RLEPixels() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void SkImageInfo::unflatten(SkFlattenableReadBuffer& buffer) {
fWidth = buffer.read32();
fHeight = buffer.read32();
uint32_t packed = buffer.read32();
SkASSERT(0 == (packed >> 16));
fAlphaType = (SkAlphaType)((packed >> 8) & 0xFF);
fColorType = (SkColorType)((packed >> 0) & 0xFF);
}
void SkImageInfo::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.write32(fWidth);
buffer.write32(fHeight);
SkASSERT(0 == (fAlphaType & ~0xFF));
SkASSERT(0 == (fColorType & ~0xFF));
uint32_t packed = (fAlphaType << 8) | fColorType;
buffer.write32(packed);
}
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_DEBUG #ifdef SK_DEBUG
void SkBitmap::validate() const { void SkBitmap::validate() const {
SkASSERT(fConfig < kConfigCount); SkASSERT(fConfig < kConfigCount);

Просмотреть файл

@ -24,31 +24,30 @@ SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties&
, fBitmap(bitmap) { , fBitmap(bitmap) {
} }
SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque) { void SkBitmapDevice::init(SkBitmap::Config config, int width, int height, bool isOpaque) {
fBitmap.setConfig(config, width, height, 0, isOpaque ? fBitmap.setConfig(config, width, height, 0, isOpaque ?
kOpaque_SkAlphaType : kPremul_SkAlphaType); kOpaque_SkAlphaType : kPremul_SkAlphaType);
if (!fBitmap.allocPixels()) {
fBitmap.setConfig(config, 0, 0, 0, isOpaque ? if (SkBitmap::kNo_Config != config) {
kOpaque_SkAlphaType : kPremul_SkAlphaType); if (!fBitmap.allocPixels()) {
} // indicate failure by zeroing our bitmap
if (!isOpaque) { fBitmap.setConfig(config, 0, 0, 0, isOpaque ?
fBitmap.eraseColor(SK_ColorTRANSPARENT); kOpaque_SkAlphaType : kPremul_SkAlphaType);
} else if (!isOpaque) {
fBitmap.eraseColor(SK_ColorTRANSPARENT);
}
} }
} }
SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque) {
this->init(config, width, height, isOpaque);
}
SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque, SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
const SkDeviceProperties& deviceProperties) const SkDeviceProperties& deviceProperties)
: SkBaseDevice(deviceProperties) { : SkBaseDevice(deviceProperties)
{
fBitmap.setConfig(config, width, height, 0, isOpaque ? this->init(config, width, height, isOpaque);
kOpaque_SkAlphaType : kPremul_SkAlphaType);
if (!fBitmap.allocPixels()) {
fBitmap.setConfig(config, 0, 0, 0, isOpaque ?
kOpaque_SkAlphaType : kPremul_SkAlphaType);
}
if (!isOpaque) {
fBitmap.eraseColor(SK_ColorTRANSPARENT);
}
} }
SkBitmapDevice::~SkBitmapDevice() { SkBitmapDevice::~SkBitmapDevice() {

Просмотреть файл

@ -15,8 +15,14 @@
#include "SkGr.h" #include "SkGr.h"
bool SkImageFilterUtils::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) { bool SkImageFilterUtils::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) {
result->setConfig(SkBitmap::kARGB_8888_Config, width, height); SkImageInfo info;
result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (texture)))->unref(); info.fWidth = width;
info.fHeight = height;
info.fColorType = kPMColor_SkColorType;
info.fAlphaType = kPremul_SkAlphaType;
result->setConfig(info);
result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
return true; return true;
} }
@ -36,8 +42,12 @@ bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter:
} else { } else {
if (filter->filterImage(proxy, src, ctm, result, offset)) { if (filter->filterImage(proxy, src, ctm, result, offset)) {
if (!result->getTexture()) { if (!result->getTexture()) {
SkImageInfo info;
if (!result->asImageInfo(&info)) {
return false;
}
GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL); GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL);
result->setPixelRef(new SkGrPixelRef(resultTex))->unref(); result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref();
GrUnlockAndUnrefCachedBitmapTexture(resultTex); GrUnlockAndUnrefCachedBitmapTexture(resultTex);
} }
return true; return true;

Просмотреть файл

@ -1,27 +1,105 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "SkMallocPixelRef.h" #include "SkMallocPixelRef.h"
#include "SkBitmap.h" #include "SkBitmap.h"
#include "SkFlattenableBuffers.h" #include "SkFlattenableBuffers.h"
SkMallocPixelRef::SkMallocPixelRef(void* storage, size_t size, static bool check_info(const SkImageInfo& info, SkColorTable* ctable) {
SkColorTable* ctable, bool ownPixels) { if (info.fWidth < 0 ||
if (NULL == storage) { info.fHeight < 0 ||
SkASSERT(ownPixels); (unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType ||
storage = sk_malloc_throw(size); (unsigned)info.fAlphaType > (unsigned)kLastEnum_SkAlphaType)
{
return false;
} }
fStorage = storage;
fSize = size; // these seem like good checks, but currently we have (at least) tests
fCTable = ctable; // that expect the pixelref to succeed even when there is a mismatch
SkSafeRef(ctable); // with colortables. fix?
fOwnPixels = ownPixels; #if 0
if (kIndex8_SkColorType == info.fColorType && NULL == ctable) {
return false;
}
if (kIndex8_SkColorType != info.fColorType && NULL != ctable) {
return false;
}
#endif
return true;
}
this->setPreLocked(fStorage, fCTable); SkMallocPixelRef* SkMallocPixelRef::NewDirect(const SkImageInfo& info,
void* addr,
size_t rowBytes,
SkColorTable* ctable) {
if (!check_info(info, ctable)) {
return NULL;
}
return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, false));
}
SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
size_t requestedRowBytes,
SkColorTable* ctable) {
if (!check_info(info, ctable)) {
return NULL;
}
int32_t minRB = info.minRowBytes();
if (minRB < 0) {
return NULL; // allocation will be too large
}
if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
return NULL; // cannot meet requested rowbytes
}
int32_t rowBytes;
if (requestedRowBytes) {
rowBytes = requestedRowBytes;
} else {
rowBytes = minRB;
}
Sk64 bigSize;
bigSize.setMul(info.fHeight, rowBytes);
if (!bigSize.is32()) {
return NULL;
}
size_t size = bigSize.get32();
void* addr = sk_malloc_flags(size, 0);
if (NULL == addr) {
return NULL;
}
return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, true));
}
///////////////////////////////////////////////////////////////////////////////
SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
size_t rowBytes, SkColorTable* ctable,
bool ownsPixels)
: SkPixelRef(info)
, fOwnPixels(ownsPixels)
{
SkASSERT(check_info(info, ctable));
SkASSERT(rowBytes >= info.minRowBytes());
if (kIndex8_SkColorType != info.fColorType) {
ctable = NULL;
}
fStorage = storage;
fCTable = ctable;
fRB = rowBytes;
SkSafeRef(ctable);
this->setPreLocked(fStorage, fRB, fCTable);
} }
SkMallocPixelRef::~SkMallocPixelRef() { SkMallocPixelRef::~SkMallocPixelRef() {
@ -31,19 +109,30 @@ SkMallocPixelRef::~SkMallocPixelRef() {
} }
} }
void* SkMallocPixelRef::onLockPixels(SkColorTable** ct) { bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) {
*ct = fCTable; rec->fPixels = fStorage;
return fStorage; rec->fRowBytes = fRB;
rec->fColorTable = fCTable;
return true;
} }
void SkMallocPixelRef::onUnlockPixels() { void SkMallocPixelRef::onUnlockPixels() {
// nothing to do // nothing to do
} }
size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
return this->info().getSafeSize(fRB);
}
void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const { void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer); this->INHERITED::flatten(buffer);
buffer.writeByteArray(fStorage, fSize); buffer.write32(fRB);
// TODO: replace this bulk write with a chunky one that can trim off any
// trailing bytes on each scanline (in case rowbytes > width*size)
size_t size = this->info().getSafeSize(fRB);
buffer.writeByteArray(fStorage, size);
buffer.writeBool(fCTable != NULL); buffer.writeBool(fCTable != NULL);
if (fCTable) { if (fCTable) {
fCTable->writeToBuffer(buffer); fCTable->writeToBuffer(buffer);
@ -51,16 +140,18 @@ void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
} }
SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer) SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer, NULL) { : INHERITED(buffer, NULL)
fSize = buffer.getArrayCount(); , fOwnPixels(true)
fStorage = sk_malloc_throw(fSize); {
buffer.readByteArray(fStorage, fSize); fRB = buffer.read32();
size_t size = this->info().getSafeSize(fRB);
fStorage = sk_malloc_throw(size);
buffer.readByteArray(fStorage, size);
if (buffer.readBool()) { if (buffer.readBool()) {
fCTable = SkNEW_ARGS(SkColorTable, (buffer)); fCTable = SkNEW_ARGS(SkColorTable, (buffer));
} else { } else {
fCTable = NULL; fCTable = NULL;
} }
fOwnPixels = true;
this->setPreLocked(fStorage, fCTable); this->setPreLocked(fStorage, fRB, fCTable);
} }

Просмотреть файл

@ -349,10 +349,14 @@ bool SkMaskFilter::filterMaskGPU(GrContext* context,
if (!result) { if (!result) {
return false; return false;
} }
SkAutoUnref aur(dst);
SkImageInfo info;
resultBM->setConfig(srcBM.config(), dst->width(), dst->height()); resultBM->setConfig(srcBM.config(), dst->width(), dst->height());
resultBM->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (dst)))->unref(); if (resultBM->asImageInfo(&info)) {
dst->unref(); return false;
}
resultBM->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, dst)))->unref();
return true; return true;
} }

Просмотреть файл

@ -82,10 +82,20 @@ void SkPixelRef::setMutex(SkBaseMutex* mutex) {
// just need a > 0 value, so pick a funny one to aid in debugging // just need a > 0 value, so pick a funny one to aid in debugging
#define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789 #define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789
SkPixelRef::SkPixelRef(SkBaseMutex* mutex) { SkPixelRef::SkPixelRef(const SkImageInfo& info) {
this->setMutex(NULL);
fInfo = info;
fRec.zero();
fLockCount = 0;
this->needsNewGenID();
fIsImmutable = false;
fPreLocked = false;
}
SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex) {
this->setMutex(mutex); this->setMutex(mutex);
fPixels = NULL; fInfo = info;
fColorTable = NULL; // we do not track ownership of this fRec.zero();
fLockCount = 0; fLockCount = 0;
this->needsNewGenID(); this->needsNewGenID();
fIsImmutable = false; fIsImmutable = false;
@ -95,8 +105,9 @@ SkPixelRef::SkPixelRef(SkBaseMutex* mutex) {
SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex) SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
: INHERITED(buffer) { : INHERITED(buffer) {
this->setMutex(mutex); this->setMutex(mutex);
fPixels = NULL;
fColorTable = NULL; // we do not track ownership of this fInfo.unflatten(buffer);
fRec.zero();
fLockCount = 0; fLockCount = 0;
fIsImmutable = buffer.readBool(); fIsImmutable = buffer.readBool();
fGenerationID = buffer.readUInt(); fGenerationID = buffer.readUInt();
@ -120,12 +131,13 @@ void SkPixelRef::cloneGenID(const SkPixelRef& that) {
that.fUniqueGenerationID = false; that.fUniqueGenerationID = false;
} }
void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) { void SkPixelRef::setPreLocked(void* pixels, size_t rowBytes, SkColorTable* ctable) {
#ifndef SK_IGNORE_PIXELREF_SETPRELOCKED #ifndef SK_IGNORE_PIXELREF_SETPRELOCKED
// only call me in your constructor, otherwise fLockCount tracking can get // only call me in your constructor, otherwise fLockCount tracking can get
// out of sync. // out of sync.
fPixels = pixels; fRec.fPixels = pixels;
fColorTable = ctable; fRec.fColorTable = ctable;
fRec.fRowBytes = rowBytes;
fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT;
fPreLocked = true; fPreLocked = true;
#endif #endif
@ -133,6 +145,8 @@ void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) {
void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const { void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer); this->INHERITED::flatten(buffer);
fInfo.flatten(buffer);
buffer.writeBool(fIsImmutable); buffer.writeBool(fIsImmutable);
// We write the gen ID into the picture for within-process recording. This // We write the gen ID into the picture for within-process recording. This
// is safe since the same genID will never refer to two different sets of // is safe since the same genID will never refer to two different sets of
@ -147,16 +161,27 @@ void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
} }
} }
void SkPixelRef::lockPixels() { bool SkPixelRef::lockPixels(LockRec* rec) {
SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
if (!fPreLocked) { if (!fPreLocked) {
SkAutoMutexAcquire ac(*fMutex); SkAutoMutexAcquire ac(*fMutex);
if (1 == ++fLockCount) { if (1 == ++fLockCount) {
fPixels = this->onLockPixels(&fColorTable); LockRec rec;
if (!this->onNewLockPixels(&rec)) {
return false;
}
fRec = rec;
} }
} }
*rec = fRec;
return true;
}
bool SkPixelRef::lockPixels() {
LockRec rec;
return this->lockPixels(&rec);
} }
void SkPixelRef::unlockPixels() { void SkPixelRef::unlockPixels() {
@ -168,8 +193,7 @@ void SkPixelRef::unlockPixels() {
SkASSERT(fLockCount > 0); SkASSERT(fLockCount > 0);
if (0 == --fLockCount) { if (0 == --fLockCount) {
this->onUnlockPixels(); this->onUnlockPixels();
fPixels = NULL; fRec.zero();
fColorTable = NULL;
} }
} }
} }
@ -250,6 +274,29 @@ size_t SkPixelRef::getAllocatedSizeInBytes() const {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifdef SK_SUPPORT_LEGACY_ONLOCKPIXELS
void* SkPixelRef::onLockPixels(SkColorTable** ctable) {
return NULL;
}
bool SkPixelRef::onNewLockPixels(LockRec* rec) {
SkColorTable* ctable;
void* pixels = this->onLockPixels(&ctable);
if (!pixels) {
return false;
}
rec->fPixels = pixels;
rec->fColorTable = ctable;
rec->fRowBytes = 0; // callers don't currently need this (thank goodness)
return true;
}
#endif
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_BUILD_FOR_ANDROID #ifdef SK_BUILD_FOR_ANDROID
void SkPixelRef::globalRef(void* data) { void SkPixelRef::globalRef(void* data) {
this->ref(); this->ref();

Просмотреть файл

@ -513,13 +513,14 @@ const uint16_t* SkGradientShaderBase::getCache16() const {
const SkPMColor* SkGradientShaderBase::getCache32() const { const SkPMColor* SkGradientShaderBase::getCache32() const {
if (fCache32 == NULL) { if (fCache32 == NULL) {
// double the count for dither entries SkImageInfo info;
const int entryCount = kCache32Count * 4; info.fWidth = kCache32Count;
const size_t allocSize = sizeof(SkPMColor) * entryCount; info.fHeight = 4; // for our 4 dither rows
info.fAlphaType = kPremul_SkAlphaType;
info.fColorType = kPMColor_SkColorType;
if (NULL == fCache32PixelRef) { if (NULL == fCache32PixelRef) {
fCache32PixelRef = SkNEW_ARGS(SkMallocPixelRef, fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL);
(NULL, allocSize, NULL));
} }
fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); fCache32 = (SkPMColor*)fCache32PixelRef->getAddr();
if (fColorCount == 2) { if (fColorCount == 2) {
@ -541,8 +542,7 @@ const SkPMColor* SkGradientShaderBase::getCache32() const {
} }
if (fMapper) { if (fMapper) {
SkMallocPixelRef* newPR = SkNEW_ARGS(SkMallocPixelRef, SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NULL);
(NULL, allocSize, NULL));
SkPMColor* linear = fCache32; // just computed linear data SkPMColor* linear = fCache32; // just computed linear data
SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data
SkUnitMapper* map = fMapper; SkUnitMapper* map = fMapper;

Просмотреть файл

@ -8,9 +8,19 @@
#include "GrSurface.h" #include "GrSurface.h"
#include "SkBitmap.h" #include "SkBitmap.h"
#include "SkGr.h"
#include "SkImageEncoder.h" #include "SkImageEncoder.h"
#include <stdio.h> #include <stdio.h>
void GrSurface::asImageInfo(SkImageInfo* info) const {
if (!GrPixelConfig2ColorType(this->config(), &info->fColorType)) {
sk_throw();
}
info->fWidth = this->width();
info->fHeight = this->height();
info->fAlphaType = kPremul_SkAlphaType;
}
bool GrSurface::savePixels(const char* filename) { bool GrSurface::savePixels(const char* filename) {
SkBitmap bm; SkBitmap bm;
bm.setConfig(SkBitmap::kARGB_8888_Config, this->width(), this->height()); bm.setConfig(SkBitmap::kARGB_8888_Config, this->width(), this->height());

Просмотреть файл

@ -200,7 +200,10 @@ void SkGpuDevice::initFromRenderTarget(GrContext* context,
if (NULL == surface) { if (NULL == surface) {
surface = fRenderTarget; surface = fRenderTarget;
} }
SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (surface, cached));
SkImageInfo info;
surface->asImageInfo(&info);
SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, surface, cached));
this->setPixelRef(pr, 0)->unref(); this->setPixelRef(pr, 0)->unref();
} }
@ -210,8 +213,8 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
int width, int width,
int height, int height,
int sampleCount) int sampleCount)
: SkBitmapDevice(config, width, height, false /*isOpaque*/) { : SkBitmapDevice(config, width, height, false /*isOpaque*/)
{
fDrawProcs = NULL; fDrawProcs = NULL;
fContext = context; fContext = context;
@ -231,6 +234,14 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
desc.fConfig = SkBitmapConfig2GrPixelConfig(config); desc.fConfig = SkBitmapConfig2GrPixelConfig(config);
desc.fSampleCnt = sampleCount; desc.fSampleCnt = sampleCount;
SkImageInfo info;
if (!GrPixelConfig2ColorType(desc.fConfig, &info.fColorType)) {
sk_throw();
}
info.fWidth = width;
info.fHeight = height;
info.fAlphaType = kPremul_SkAlphaType;
SkAutoTUnref<GrTexture> texture(fContext->createUncachedTexture(desc, NULL, 0)); SkAutoTUnref<GrTexture> texture(fContext->createUncachedTexture(desc, NULL, 0));
if (NULL != texture) { if (NULL != texture) {
@ -240,7 +251,7 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
SkASSERT(NULL != fRenderTarget); SkASSERT(NULL != fRenderTarget);
// wrap the bitmap with a pixelref to expose our texture // wrap the bitmap with a pixelref to expose our texture
SkGrPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (texture)); SkGrPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, texture));
this->setPixelRef(pr, 0)->unref(); this->setPixelRef(pr, 0)->unref();
} else { } else {
GrPrintf("--- failed to create gpu-offscreen [%d %d]\n", GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
@ -826,11 +837,12 @@ bool create_mask_GPU(GrContext* context,
} }
SkBitmap wrap_texture(GrTexture* texture) { SkBitmap wrap_texture(GrTexture* texture) {
SkImageInfo info;
texture->asImageInfo(&info);
SkBitmap result; SkBitmap result;
bool dummy; result.setConfig(info);
SkBitmap::Config config = grConfig2skConfig(texture->config(), &dummy); result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
result.setConfig(config, texture->width(), texture->height());
result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (texture)))->unref();
return result; return result;
} }

Просмотреть файл

@ -258,3 +258,33 @@ GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config config) {
return kUnknown_GrPixelConfig; return kUnknown_GrPixelConfig;
} }
} }
bool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) {
SkColorType ct;
switch (config) {
case kAlpha_8_GrPixelConfig:
ct = kAlpha_8_SkColorType;
break;
case kIndex_8_GrPixelConfig:
ct = kIndex8_SkColorType;
break;
case kRGB_565_GrPixelConfig:
ct = kRGB_565_SkColorType;
break;
case kRGBA_4444_GrPixelConfig:
ct = kARGB_4444_SkColorType;
break;
case kRGBA_8888_GrPixelConfig:
ct = kRGBA_8888_SkColorType;
break;
case kBGRA_8888_GrPixelConfig:
ct = kBGRA_8888_SkColorType;
break;
default:
return false;
}
if (ctOut) {
*ctOut = ct;
}
return true;
}

Просмотреть файл

@ -18,24 +18,29 @@
// to avoid deadlock with the default one provided by SkPixelRef. // to avoid deadlock with the default one provided by SkPixelRef.
SK_DECLARE_STATIC_MUTEX(gROLockPixelsPixelRefMutex); SK_DECLARE_STATIC_MUTEX(gROLockPixelsPixelRefMutex);
SkROLockPixelsPixelRef::SkROLockPixelsPixelRef() : INHERITED(&gROLockPixelsPixelRefMutex) { SkROLockPixelsPixelRef::SkROLockPixelsPixelRef(const SkImageInfo& info)
: INHERITED(info, &gROLockPixelsPixelRefMutex) {
} }
SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() { SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {
} }
void* SkROLockPixelsPixelRef::onLockPixels(SkColorTable** ctable) { bool SkROLockPixelsPixelRef::onNewLockPixels(LockRec* rec) {
if (ctable) {
*ctable = NULL;
}
fBitmap.reset(); fBitmap.reset();
// SkDebugf("---------- calling readpixels in support of lockpixels\n"); // SkDebugf("---------- calling readpixels in support of lockpixels\n");
if (!this->onReadPixels(&fBitmap, NULL)) { if (!this->onReadPixels(&fBitmap, NULL)) {
SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n"); SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n");
return NULL; return false;
} }
fBitmap.lockPixels(); fBitmap.lockPixels();
return fBitmap.getPixels(); if (NULL == fBitmap.getPixels()) {
return false;
}
rec->fPixels = fBitmap.getPixels();
rec->fColorTable = NULL;
rec->fRowBytes = fBitmap.rowBytes();
return true;
} }
void SkROLockPixelsPixelRef::onUnlockPixels() { void SkROLockPixelsPixelRef::onUnlockPixels() {
@ -76,6 +81,14 @@ static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config
desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
desc.fConfig = SkBitmapConfig2GrPixelConfig(dstConfig); desc.fConfig = SkBitmapConfig2GrPixelConfig(dstConfig);
SkImageInfo info;
if (!GrPixelConfig2ColorType(desc.fConfig, &info.fColorType)) {
return NULL;
}
info.fWidth = desc.fWidth;
info.fHeight = desc.fHeight;
info.fAlphaType = kPremul_SkAlphaType;
GrTexture* dst = context->createUncachedTexture(desc, NULL, 0); GrTexture* dst = context->createUncachedTexture(desc, NULL, 0);
if (NULL == dst) { if (NULL == dst) {
return NULL; return NULL;
@ -93,14 +106,17 @@ static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config
dst->releaseRenderTarget(); dst->releaseRenderTarget();
#endif #endif
SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (dst)); SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst));
SkSafeUnref(dst); SkSafeUnref(dst);
return pixelRef; return pixelRef;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
SkGrPixelRef::SkGrPixelRef(GrSurface* surface, bool transferCacheLock) { SkGrPixelRef::SkGrPixelRef(const SkImageInfo& info, GrSurface* surface,
bool transferCacheLock)
: INHERITED(info)
{
// TODO: figure out if this is responsible for Chrome canvas errors // TODO: figure out if this is responsible for Chrome canvas errors
#if 0 #if 0
// The GrTexture has a ref to the GrRenderTarget but not vice versa. // The GrTexture has a ref to the GrRenderTarget but not vice versa.

Просмотреть файл

@ -9,18 +9,25 @@
#include "SkData.h" #include "SkData.h"
#include "SkFlattenableBuffers.h" #include "SkFlattenableBuffers.h"
SkDataPixelRef::SkDataPixelRef(SkData* data) : fData(data) { SkDataPixelRef::SkDataPixelRef(const SkImageInfo& info,
SkData* data, size_t rowBytes)
: INHERITED(info)
, fData(data)
, fRB(rowBytes)
{
fData->ref(); fData->ref();
this->setPreLocked(const_cast<void*>(fData->data()), NULL); this->setPreLocked(const_cast<void*>(fData->data()), rowBytes, NULL);
} }
SkDataPixelRef::~SkDataPixelRef() { SkDataPixelRef::~SkDataPixelRef() {
fData->unref(); fData->unref();
} }
void* SkDataPixelRef::onLockPixels(SkColorTable** ct) { bool SkDataPixelRef::onNewLockPixels(LockRec* rec) {
*ct = NULL; rec->fPixels = const_cast<void*>(fData->data());
return const_cast<void*>(fData->data()); rec->fColorTable = NULL;
rec->fRowBytes = fRB;
return true;
} }
void SkDataPixelRef::onUnlockPixels() { void SkDataPixelRef::onUnlockPixels() {
@ -33,11 +40,15 @@ size_t SkDataPixelRef::getAllocatedSizeInBytes() const {
void SkDataPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const { void SkDataPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer); this->INHERITED::flatten(buffer);
buffer.writeDataAsByteArray(fData); buffer.writeDataAsByteArray(fData);
buffer.write32(fRB);
} }
SkDataPixelRef::SkDataPixelRef(SkFlattenableReadBuffer& buffer) SkDataPixelRef::SkDataPixelRef(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer, NULL) { : INHERITED(buffer, NULL)
{
fData = buffer.readByteArrayAsData(); fData = buffer.readByteArrayAsData();
this->setPreLocked(const_cast<void*>(fData->data()), NULL); fRB = buffer.read32();
this->setPreLocked(const_cast<void*>(fData->data()), fRB, NULL);
} }

Просмотреть файл

@ -14,13 +14,13 @@ class SkData;
class SkDataPixelRef : public SkPixelRef { class SkDataPixelRef : public SkPixelRef {
public: public:
SkDataPixelRef(SkData* data); SkDataPixelRef(const SkImageInfo&, SkData* data, size_t rowBytes);
virtual ~SkDataPixelRef(); virtual ~SkDataPixelRef();
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDataPixelRef) SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDataPixelRef)
protected: protected:
virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE; virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
virtual void onUnlockPixels() SK_OVERRIDE; virtual void onUnlockPixels() SK_OVERRIDE;
virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE; virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
@ -28,7 +28,8 @@ protected:
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
private: private:
SkData* fData; SkData* fData;
size_t fRB;
typedef SkPixelRef INHERITED; typedef SkPixelRef INHERITED;
}; };

Просмотреть файл

@ -84,10 +84,8 @@ SkImage* SkImage_Raster::NewEmpty() {
SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes) SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes)
: INHERITED(info.fWidth, info.fHeight) { : INHERITED(info.fWidth, info.fHeight) {
SkBitmap::Config config = SkImageInfoToBitmapConfig(info); fBitmap.setConfig(info, rowBytes);
fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (info, data, rowBytes)))->unref();
fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes, info.fAlphaType);
fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (data)))->unref();
fBitmap.setImmutable(); fBitmap.setImmutable();
} }

Просмотреть файл

@ -155,19 +155,9 @@ SkSurface* SkSurface::NewRaster(const SkImageInfo& info) {
return NULL; return NULL;
} }
static const size_t kMaxTotalSize = SK_MaxS32; SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewAllocate(info, 0, NULL));
size_t rowBytes = SkImageMinRowBytes(info); if (NULL == pr.get()) {
uint64_t size64 = (uint64_t)info.fHeight * rowBytes;
if (size64 > kMaxTotalSize) {
return NULL; return NULL;
} }
return SkNEW_ARGS(SkSurface_Raster, (info, pr, info.minRowBytes()));
size_t size = (size_t)size64;
void* pixels = sk_malloc_throw(size);
if (NULL == pixels) {
return NULL;
}
SkAutoTUnref<SkPixelRef> pr(SkNEW_ARGS(SkMallocPixelRef, (pixels, size, NULL, true)));
return SkNEW_ARGS(SkSurface_Raster, (info, pr, rowBytes));
} }

Просмотреть файл

@ -15,16 +15,14 @@
//#define DUMP_IMAGEREF_LIFECYCLE //#define DUMP_IMAGEREF_LIFECYCLE
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
SkImageRef::SkImageRef(SkStreamRewindable* stream, SkBitmap::Config config, SkImageRef::SkImageRef(const SkImageInfo& info, SkStreamRewindable* stream,
int sampleSize, SkBaseMutex* mutex) int sampleSize, SkBaseMutex* mutex)
: SkPixelRef(mutex), fErrorInDecoding(false) { : INHERITED(info, mutex), fErrorInDecoding(false) {
SkASSERT(stream); SkASSERT(stream);
stream->ref(); stream->ref();
fStream = stream; fStream = stream;
fConfig = config;
fSampleSize = sampleSize; fSampleSize = sampleSize;
fDoDither = true; fDoDither = true;
fPrev = fNext = NULL; fPrev = fNext = NULL;
@ -40,7 +38,7 @@ SkImageRef::~SkImageRef() {
#ifdef DUMP_IMAGEREF_LIFECYCLE #ifdef DUMP_IMAGEREF_LIFECYCLE
SkDebugf("delete ImageRef %p [%d] data=%d\n", SkDebugf("delete ImageRef %p [%d] data=%d\n",
this, fConfig, (int)fStream->getLength()); this, this->info().fColorType, (int)fStream->getLength());
#endif #endif
fStream->unref(); fStream->unref();
@ -92,14 +90,6 @@ bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
return false; return false;
} }
/* As soon as we really know our config, we record it, so that on
subsequent calls to the codec, we are sure we will always get the same
result.
*/
if (SkBitmap::kNo_Config != fBitmap.config()) {
fConfig = fBitmap.config();
}
if (NULL != fBitmap.getPixels() || if (NULL != fBitmap.getPixels() ||
(SkBitmap::kNo_Config != fBitmap.config() && (SkBitmap::kNo_Config != fBitmap.config() &&
SkImageDecoder::kDecodeBounds_Mode == mode)) { SkImageDecoder::kDecodeBounds_Mode == mode)) {
@ -125,7 +115,7 @@ bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
codec->setSampleSize(fSampleSize); codec->setSampleSize(fSampleSize);
codec->setDitherImage(fDoDither); codec->setDitherImage(fDoDither);
if (this->onDecode(codec, fStream, &fBitmap, fConfig, mode)) { if (this->onDecode(codec, fStream, &fBitmap, fBitmap.config(), mode)) {
return true; return true;
} }
} }
@ -143,15 +133,18 @@ bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
return false; return false;
} }
void* SkImageRef::onLockPixels(SkColorTable** ct) { bool SkImageRef::onNewLockPixels(LockRec* rec) {
if (NULL == fBitmap.getPixels()) { if (NULL == fBitmap.getPixels()) {
(void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode); (void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode);
} }
if (ct) { if (NULL == fBitmap.getPixels()) {
*ct = fBitmap.getColorTable(); return false;
} }
return fBitmap.getPixels(); rec->fPixels = fBitmap.getPixels();
rec->fColorTable = NULL;
rec->fRowBytes = fBitmap.rowBytes();
return true;
} }
size_t SkImageRef::ramUsed() const { size_t SkImageRef::ramUsed() const {
@ -170,7 +163,6 @@ size_t SkImageRef::ramUsed() const {
SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex) SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
: INHERITED(buffer, mutex), fErrorInDecoding(false) { : INHERITED(buffer, mutex), fErrorInDecoding(false) {
fConfig = (SkBitmap::Config)buffer.readUInt();
fSampleSize = buffer.readInt(); fSampleSize = buffer.readInt();
fDoDither = buffer.readBool(); fDoDither = buffer.readBool();
@ -185,7 +177,6 @@ SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const { void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer); this->INHERITED::flatten(buffer);
buffer.writeUInt(fConfig);
buffer.writeInt(fSampleSize); buffer.writeInt(fSampleSize);
buffer.writeBool(fDoDither); buffer.writeBool(fDoDither);
// FIXME: Consider moving this logic should go into writeStream itself. // FIXME: Consider moving this logic should go into writeStream itself.

Просмотреть файл

@ -24,10 +24,10 @@ static SkImageRefPool* GetGlobalPool() {
return gPool; return gPool;
} }
SkImageRef_GlobalPool::SkImageRef_GlobalPool(SkStreamRewindable* stream, SkImageRef_GlobalPool::SkImageRef_GlobalPool(const SkImageInfo& info,
SkBitmap::Config config, SkStreamRewindable* stream,
int sampleSize) int sampleSize)
: SkImageRef(stream, config, sampleSize, &gGlobalPoolMutex) { : SkImageRef(info, stream, sampleSize, &gGlobalPoolMutex) {
SkASSERT(&gGlobalPoolMutex == this->mutex()); SkASSERT(&gGlobalPoolMutex == this->mutex());
SkAutoMutexAcquire ac(gGlobalPoolMutex); SkAutoMutexAcquire ac(gGlobalPoolMutex);
GetGlobalPool()->addToHead(this); GetGlobalPool()->addToHead(this);

Просмотреть файл

@ -31,10 +31,10 @@ static size_t roundToPageSize(size_t size) {
return newsize; return newsize;
} }
SkImageRef_ashmem::SkImageRef_ashmem(SkStreamRewindable* stream, SkImageRef_ashmem::SkImageRef_ashmem(const SkImageInfo& info,
SkBitmap::Config config, SkStreamRewindable* stream,
int sampleSize) int sampleSize)
: SkImageRef(stream, config, sampleSize) { : SkImageRef(info, stream, sampleSize) {
fRec.fFD = -1; fRec.fFD = -1;
fRec.fAddr = NULL; fRec.fAddr = NULL;

Просмотреть файл

@ -19,7 +19,7 @@ struct SkAshmemRec {
class SkImageRef_ashmem : public SkImageRef { class SkImageRef_ashmem : public SkImageRef {
public: public:
SkImageRef_ashmem(SkStreamRewindable*, SkBitmap::Config, int sampleSize = 1); SkImageRef_ashmem(const SkImageInfo&, SkStreamRewindable*, int sampleSize = 1);
virtual ~SkImageRef_ashmem(); virtual ~SkImageRef_ashmem();
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkImageRef_ashmem) SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkImageRef_ashmem)

Просмотреть файл

@ -8,7 +8,6 @@
#include "SkCachingPixelRef.h" #include "SkCachingPixelRef.h"
#include "SkScaledImageCache.h" #include "SkScaledImageCache.h"
bool SkCachingPixelRef::Install(SkImageGenerator* generator, bool SkCachingPixelRef::Install(SkImageGenerator* generator,
SkBitmap* dst) { SkBitmap* dst) {
SkImageInfo info; SkImageInfo info;
@ -31,10 +30,10 @@ bool SkCachingPixelRef::Install(SkImageGenerator* generator,
SkCachingPixelRef::SkCachingPixelRef(SkImageGenerator* generator, SkCachingPixelRef::SkCachingPixelRef(SkImageGenerator* generator,
const SkImageInfo& info, const SkImageInfo& info,
size_t rowBytes) size_t rowBytes)
: fImageGenerator(generator) : INHERITED(info)
, fImageGenerator(generator)
, fErrorInDecoding(false) , fErrorInDecoding(false)
, fScaledCacheId(NULL) , fScaledCacheId(NULL)
, fInfo(info)
, fRowBytes(rowBytes) { , fRowBytes(rowBytes) {
SkASSERT(fImageGenerator != NULL); SkASSERT(fImageGenerator != NULL);
} }
@ -44,31 +43,32 @@ SkCachingPixelRef::~SkCachingPixelRef() {
// Assert always unlock before unref. // Assert always unlock before unref.
} }
void* SkCachingPixelRef::onLockPixels(SkColorTable** colorTable) { bool SkCachingPixelRef::onNewLockPixels(LockRec* rec) {
(void)colorTable;
if (fErrorInDecoding) { if (fErrorInDecoding) {
return NULL; // don't try again. return false; // don't try again.
} }
const SkImageInfo& info = this->info();
SkBitmap bitmap; SkBitmap bitmap;
SkASSERT(NULL == fScaledCacheId); SkASSERT(NULL == fScaledCacheId);
fScaledCacheId = SkScaledImageCache::FindAndLock(this->getGenerationID(), fScaledCacheId = SkScaledImageCache::FindAndLock(this->getGenerationID(),
fInfo.fWidth, info.fWidth,
fInfo.fHeight, info.fHeight,
&bitmap); &bitmap);
if (NULL == fScaledCacheId) { if (NULL == fScaledCacheId) {
// Cache has been purged, must re-decode. // Cache has been purged, must re-decode.
if ((!bitmap.setConfig(fInfo, fRowBytes)) || !bitmap.allocPixels()) { if ((!bitmap.setConfig(info, fRowBytes)) || !bitmap.allocPixels()) {
fErrorInDecoding = true; fErrorInDecoding = true;
return NULL; return false;
} }
SkAutoLockPixels autoLockPixels(bitmap); SkAutoLockPixels autoLockPixels(bitmap);
if (!fImageGenerator->getPixels(fInfo, bitmap.getPixels(), fRowBytes)) { if (!fImageGenerator->getPixels(info, bitmap.getPixels(), fRowBytes)) {
fErrorInDecoding = true; fErrorInDecoding = true;
return NULL; return false;
} }
fScaledCacheId = SkScaledImageCache::AddAndLock(this->getGenerationID(), fScaledCacheId = SkScaledImageCache::AddAndLock(this->getGenerationID(),
fInfo.fWidth, info.fWidth,
fInfo.fHeight, info.fHeight,
bitmap); bitmap);
SkASSERT(fScaledCacheId != NULL); SkASSERT(fScaledCacheId != NULL);
} }
@ -78,6 +78,7 @@ void* SkCachingPixelRef::onLockPixels(SkColorTable** colorTable) {
SkAutoLockPixels autoLockPixels(bitmap); SkAutoLockPixels autoLockPixels(bitmap);
void* pixels = bitmap.getPixels(); void* pixels = bitmap.getPixels();
SkASSERT(pixels != NULL); SkASSERT(pixels != NULL);
// At this point, the autoLockPixels will unlockPixels() // At this point, the autoLockPixels will unlockPixels()
// to remove bitmap's lock on the pixels. We will then // to remove bitmap's lock on the pixels. We will then
// destroy bitmap. The *only* guarantee that this pointer // destroy bitmap. The *only* guarantee that this pointer
@ -86,7 +87,10 @@ void* SkCachingPixelRef::onLockPixels(SkColorTable** colorTable) {
// bitmap (SkScaledImageCache::Rec.fBitmap) that holds a // bitmap (SkScaledImageCache::Rec.fBitmap) that holds a
// reference to the concrete PixelRef while this record is // reference to the concrete PixelRef while this record is
// locked. // locked.
return pixels; rec->fPixels = pixels;
rec->fColorTable = NULL;
rec->fRowBytes = bitmap.rowBytes();
return true;
} }
void SkCachingPixelRef::onUnlockPixels() { void SkCachingPixelRef::onUnlockPixels() {

Просмотреть файл

@ -40,7 +40,7 @@ public:
protected: protected:
virtual ~SkCachingPixelRef(); virtual ~SkCachingPixelRef();
virtual void* onLockPixels(SkColorTable** colorTable) SK_OVERRIDE; virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
virtual void onUnlockPixels() SK_OVERRIDE; virtual void onUnlockPixels() SK_OVERRIDE;
virtual bool onLockPixelsAreWritable() const SK_OVERRIDE { return false; } virtual bool onLockPixelsAreWritable() const SK_OVERRIDE { return false; }
@ -58,12 +58,12 @@ private:
SkImageGenerator* const fImageGenerator; SkImageGenerator* const fImageGenerator;
bool fErrorInDecoding; bool fErrorInDecoding;
void* fScaledCacheId; void* fScaledCacheId;
const SkImageInfo fInfo;
const size_t fRowBytes; const size_t fRowBytes;
SkCachingPixelRef(SkImageGenerator* imageGenerator, SkCachingPixelRef(SkImageGenerator* imageGenerator,
const SkImageInfo& info, const SkImageInfo& info,
size_t rowBytes); size_t rowBytes);
typedef SkPixelRef INHERITED; typedef SkPixelRef INHERITED;
}; };

Просмотреть файл

@ -10,17 +10,15 @@
SkDiscardablePixelRef::SkDiscardablePixelRef(SkImageGenerator* generator, SkDiscardablePixelRef::SkDiscardablePixelRef(SkImageGenerator* generator,
const SkImageInfo& info, const SkImageInfo& info,
size_t size,
size_t rowBytes, size_t rowBytes,
SkDiscardableMemory::Factory* fact) SkDiscardableMemory::Factory* fact)
: fGenerator(generator) : INHERITED(info)
, fGenerator(generator)
, fDMFactory(fact) , fDMFactory(fact)
, fInfo(info)
, fSize(size)
, fRowBytes(rowBytes) , fRowBytes(rowBytes)
, fDiscardableMemory(NULL) { , fDiscardableMemory(NULL)
{
SkASSERT(fGenerator != NULL); SkASSERT(fGenerator != NULL);
SkASSERT(fSize > 0);
SkASSERT(fRowBytes > 0); SkASSERT(fRowBytes > 0);
// The SkImageGenerator contract requires fGenerator to always // The SkImageGenerator contract requires fGenerator to always
// decode the same image on each call to getPixels(). // decode the same image on each call to getPixels().
@ -34,28 +32,39 @@ SkDiscardablePixelRef::~SkDiscardablePixelRef() {
SkDELETE(fGenerator); SkDELETE(fGenerator);
} }
void* SkDiscardablePixelRef::onLockPixels(SkColorTable**) { bool SkDiscardablePixelRef::onNewLockPixels(LockRec* rec) {
if (fDiscardableMemory != NULL) { if (fDiscardableMemory != NULL) {
if (fDiscardableMemory->lock()) { if (fDiscardableMemory->lock()) {
return fDiscardableMemory->data(); rec->fPixels = fDiscardableMemory->data();
rec->fColorTable = NULL;
rec->fRowBytes = fRowBytes;
return true;
} }
SkDELETE(fDiscardableMemory); SkDELETE(fDiscardableMemory);
fDiscardableMemory = NULL; fDiscardableMemory = NULL;
} }
const size_t size = this->info().getSafeSize(fRowBytes);
if (fDMFactory != NULL) { if (fDMFactory != NULL) {
fDiscardableMemory = fDMFactory->create(fSize); fDiscardableMemory = fDMFactory->create(size);
} else { } else {
fDiscardableMemory = SkDiscardableMemory::Create(fSize); fDiscardableMemory = SkDiscardableMemory::Create(size);
} }
if (NULL == fDiscardableMemory) { if (NULL == fDiscardableMemory) {
return NULL; // Memory allocation failed. return false; // Memory allocation failed.
} }
void* pixels = fDiscardableMemory->data(); void* pixels = fDiscardableMemory->data();
if (!fGenerator->getPixels(fInfo, pixels, fRowBytes)) { if (!fGenerator->getPixels(this->info(), pixels, fRowBytes)) {
return NULL; // TODO(halcanary) Find out correct thing to do. return false; // TODO(halcanary) Find out correct thing to do.
} }
return pixels;
rec->fPixels = pixels;
rec->fColorTable = NULL;
rec->fRowBytes = fRowBytes;
return true;
} }
void SkDiscardablePixelRef::onUnlockPixels() { void SkDiscardablePixelRef::onUnlockPixels() {
if (fDiscardableMemory != NULL) { if (fDiscardableMemory != NULL) {
fDiscardableMemory->unlock(); fDiscardableMemory->unlock();
@ -76,7 +85,6 @@ bool SkDiscardablePixelRef::Install(SkImageGenerator* generator,
} }
SkAutoTUnref<SkDiscardablePixelRef> ref(SkNEW_ARGS(SkDiscardablePixelRef, SkAutoTUnref<SkDiscardablePixelRef> ref(SkNEW_ARGS(SkDiscardablePixelRef,
(generator, info, (generator, info,
dst->getSize(),
dst->rowBytes(), dst->rowBytes(),
factory))); factory)));
dst->setPixelRef(ref); dst->setPixelRef(ref);

Просмотреть файл

@ -50,7 +50,8 @@ public:
protected: protected:
~SkDiscardablePixelRef(); ~SkDiscardablePixelRef();
virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
virtual void onUnlockPixels() SK_OVERRIDE; virtual void onUnlockPixels() SK_OVERRIDE;
virtual bool onLockPixelsAreWritable() const SK_OVERRIDE { return false; } virtual bool onLockPixelsAreWritable() const SK_OVERRIDE { return false; }
@ -61,8 +62,6 @@ protected:
private: private:
SkImageGenerator* const fGenerator; SkImageGenerator* const fGenerator;
SkDiscardableMemory::Factory* const fDMFactory; SkDiscardableMemory::Factory* const fDMFactory;
const SkImageInfo fInfo;
const size_t fSize; // size of memory to be allocated
const size_t fRowBytes; const size_t fRowBytes;
// These const members should not change over the life of the // These const members should not change over the life of the
// PixelRef, since the SkBitmap doesn't expect them to change. // PixelRef, since the SkBitmap doesn't expect them to change.
@ -72,8 +71,10 @@ private:
/* Takes ownership of SkImageGenerator. */ /* Takes ownership of SkImageGenerator. */
SkDiscardablePixelRef(SkImageGenerator* generator, SkDiscardablePixelRef(SkImageGenerator* generator,
const SkImageInfo& info, const SkImageInfo& info,
size_t size,
size_t rowBytes, size_t rowBytes,
SkDiscardableMemory::Factory* factory); SkDiscardableMemory::Factory* factory);
typedef SkPixelRef INHERITED;
}; };
#endif // SkDiscardablePixelRef_DEFINED #endif // SkDiscardablePixelRef_DEFINED

Просмотреть файл

@ -9,6 +9,7 @@
#include "SkCanvas.h" #include "SkCanvas.h"
#include "SkColorPriv.h" #include "SkColorPriv.h"
#include "SkData.h" #include "SkData.h"
#include "SkDecodingImageGenerator.h"
#include "SkError.h" #include "SkError.h"
#include "SkPaint.h" #include "SkPaint.h"
#include "SkPicture.h" #include "SkPicture.h"
@ -335,32 +336,6 @@ static void test_bad_bitmap() {
} }
#endif #endif
#include "SkData.h"
#include "SkImageRef_GlobalPool.h"
// Class to test SkPixelRef::onRefEncodedData, since there are currently no implementations in skia.
class SkDataImageRef : public SkImageRef_GlobalPool {
public:
SkDataImageRef(SkMemoryStream* stream)
: SkImageRef_GlobalPool(stream, SkBitmap::kNo_Config) {
SkASSERT(stream != NULL);
fData = stream->copyToData();
this->setImmutable();
}
~SkDataImageRef() {
fData->unref();
}
virtual SkData* onRefEncodedData() SK_OVERRIDE {
fData->ref();
return fData;
}
private:
SkData* fData;
};
#include "SkImageEncoder.h" #include "SkImageEncoder.h"
static SkData* encode_bitmap_to_data(size_t* offset, const SkBitmap& bm) { static SkData* encode_bitmap_to_data(size_t* offset, const SkBitmap& bm) {
@ -402,14 +377,10 @@ static void test_bitmap_with_encoded_data(skiatest::Reporter* reporter) {
return; return;
} }
SkAutoDataUnref data(wStream.copyToData()); SkAutoDataUnref data(wStream.copyToData());
SkMemoryStream memStream;
memStream.setData(data);
// Use the encoded bitmap as the data for an image ref.
SkBitmap bm; SkBitmap bm;
SkAutoTUnref<SkDataImageRef> imageRef(SkNEW_ARGS(SkDataImageRef, (&memStream))); bool installSuccess = SkDecodingImageGenerator::Install(data, &bm);
imageRef->getInfo(&bm); REPORTER_ASSERT(reporter, installSuccess);
bm.setPixelRef(imageRef);
// Write both bitmaps to pictures, and ensure that the resulting data streams are the same. // Write both bitmaps to pictures, and ensure that the resulting data streams are the same.
// Flattening original will follow the old path of performing an encode, while flattening bm // Flattening original will follow the old path of performing an encode, while flattening bm

Просмотреть файл

@ -17,33 +17,35 @@ private:
} // namespace } // namespace
DEF_TEST(PixelRef_GenIDChange, r) { DEF_TEST(PixelRef_GenIDChange, r) {
SkMallocPixelRef pixelRef(NULL, 0, NULL); // We don't really care about the pixels here. SkImageInfo info = { 10, 10, kPMColor_SkColorType, kPremul_SkAlphaType };
SkAutoTUnref<SkPixelRef> pixelRef(SkMallocPixelRef::NewAllocate(info, 0, NULL));
// Register a listener. // Register a listener.
int count = 0; int count = 0;
pixelRef.addGenIDChangeListener(SkNEW_ARGS(TestListener, (&count))); pixelRef->addGenIDChangeListener(SkNEW_ARGS(TestListener, (&count)));
REPORTER_ASSERT(r, 0 == count); REPORTER_ASSERT(r, 0 == count);
// No one has looked at our pixelRef's generation ID, so invalidating it doesn't make sense. // No one has looked at our pixelRef's generation ID, so invalidating it doesn't make sense.
// (An SkPixelRef tree falls in the forest but there's nobody around to hear it. Do we care?) // (An SkPixelRef tree falls in the forest but there's nobody around to hear it. Do we care?)
pixelRef.notifyPixelsChanged(); pixelRef->notifyPixelsChanged();
REPORTER_ASSERT(r, 0 == count); REPORTER_ASSERT(r, 0 == count);
// Force the generation ID to be calculated. // Force the generation ID to be calculated.
REPORTER_ASSERT(r, 0 != pixelRef.getGenerationID()); REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID());
// Our listener was dropped in the first call to notifyPixelsChanged(). This is a no-op. // Our listener was dropped in the first call to notifyPixelsChanged(). This is a no-op.
pixelRef.notifyPixelsChanged(); pixelRef->notifyPixelsChanged();
REPORTER_ASSERT(r, 0 == count); REPORTER_ASSERT(r, 0 == count);
// Force the generation ID to be recalculated, then add a listener. // Force the generation ID to be recalculated, then add a listener.
REPORTER_ASSERT(r, 0 != pixelRef.getGenerationID()); REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID());
pixelRef.addGenIDChangeListener(SkNEW_ARGS(TestListener, (&count))); pixelRef->addGenIDChangeListener(SkNEW_ARGS(TestListener, (&count)));
pixelRef.notifyPixelsChanged(); pixelRef->notifyPixelsChanged();
REPORTER_ASSERT(r, 1 == count); REPORTER_ASSERT(r, 1 == count);
// Quick check that NULL is safe. // Quick check that NULL is safe.
REPORTER_ASSERT(r, 0 != pixelRef.getGenerationID()); REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID());
pixelRef.addGenIDChangeListener(NULL); pixelRef->addGenIDChangeListener(NULL);
pixelRef.notifyPixelsChanged(); pixelRef->notifyPixelsChanged();
} }

Просмотреть файл

@ -148,6 +148,7 @@ static T* TestFlattenableSerialization(T* testObj, bool shouldSucceed,
REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten); REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten);
unsigned char dataWritten[1024]; unsigned char dataWritten[1024];
SkASSERT(bytesWritten <= sizeof(dataWritten));
writer.writeToMemory(dataWritten); writer.writeToMemory(dataWritten);
// Make sure this fails when it should (test with smaller size, but still multiple of 4) // Make sure this fails when it should (test with smaller size, but still multiple of 4)
@ -307,10 +308,22 @@ static void Tests(skiatest::Reporter* reporter) {
TestBitmapSerialization(validBitmap, invalidBitmap, true, reporter); TestBitmapSerialization(validBitmap, invalidBitmap, true, reporter);
// Create a bitmap with a pixel ref too small // Create a bitmap with a pixel ref too small
SkImageInfo info;
info.fWidth = 256;
info.fHeight = 256;
info.fColorType = kPMColor_SkColorType;
info.fAlphaType = kPremul_SkAlphaType;
SkBitmap invalidBitmap2; SkBitmap invalidBitmap2;
invalidBitmap2.setConfig(SkBitmap::kARGB_8888_Config, 256, 256); invalidBitmap2.setConfig(info);
invalidBitmap2.setPixelRef(SkNEW_ARGS(SkMallocPixelRef,
(NULL, 256, NULL)))->unref(); // Hack to force invalid, by making the pixelref smaller than its
// owning bitmap.
info.fWidth = 32;
info.fHeight = 1;
invalidBitmap2.setPixelRef(SkMallocPixelRef::NewAllocate(
info, invalidBitmap2.rowBytes(), NULL))->unref();
// The deserialization should detect the pixel ref being too small and fail // The deserialization should detect the pixel ref being too small and fail
TestBitmapSerialization(validBitmap, invalidBitmap2, false, reporter); TestBitmapSerialization(validBitmap, invalidBitmap2, false, reporter);