зеркало из https://github.com/mozilla/moz-skia.git
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:
Родитель
cc63b32eb8
Коммит
473f0aa2bb
|
@ -250,6 +250,13 @@ public:
|
|||
|
||||
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
|
||||
will automatically release any pixelref previously installed. Only call
|
||||
this if you are handling ownership/lifetime of the pixel memory.
|
||||
|
|
|
@ -258,6 +258,8 @@ private:
|
|||
|
||||
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)
|
||||
// but cannot change the width/height, so there should be no change to
|
||||
// any clip information.
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
|
||||
#include "SkTypes.h"
|
||||
|
||||
class SkFlattenableWriteBuffer;
|
||||
class SkFlattenableReadBuffer;
|
||||
|
||||
/**
|
||||
* Describes how to interpret the alpha compoent of a pixel.
|
||||
*/
|
||||
|
@ -63,6 +66,7 @@ static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {
|
|||
enum SkColorType {
|
||||
kAlpha_8_SkColorType,
|
||||
kRGB_565_SkColorType,
|
||||
kARGB_4444_SkColorType,
|
||||
kRGBA_8888_SkColorType,
|
||||
kBGRA_8888_SkColorType,
|
||||
kIndex8_SkColorType,
|
||||
|
@ -82,6 +86,7 @@ static int SkColorTypeBytesPerPixel(SkColorType ct) {
|
|||
static const uint8_t gSize[] = {
|
||||
1, // Alpha_8
|
||||
2, // RGB_565
|
||||
2, // ARGB_4444
|
||||
4, // RGBA_8888
|
||||
4, // BGRA_8888
|
||||
1, // kIndex_8
|
||||
|
@ -112,12 +117,26 @@ struct SkImageInfo {
|
|||
return SkColorTypeBytesPerPixel(fColorType);
|
||||
}
|
||||
|
||||
size_t minRowBytes() const {
|
||||
return fWidth * this->bytesPerPixel();
|
||||
}
|
||||
|
||||
bool operator==(const SkImageInfo& other) const {
|
||||
return 0 == memcmp(this, &other, sizeof(other));
|
||||
}
|
||||
bool operator!=(const SkImageInfo& other) const {
|
||||
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
|
||||
|
|
|
@ -17,33 +17,52 @@
|
|||
*/
|
||||
class SkMallocPixelRef : public SkPixelRef {
|
||||
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()
|
||||
is called to allocate it.
|
||||
/**
|
||||
* Return a new SkMallocPixelRef with the provided pixel storage, rowBytes,
|
||||
* 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);
|
||||
virtual ~SkMallocPixelRef();
|
||||
static SkMallocPixelRef* NewDirect(const SkImageInfo&, void* addr,
|
||||
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; }
|
||||
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMallocPixelRef)
|
||||
|
||||
protected:
|
||||
// overrides from SkPixelRef
|
||||
virtual void* onLockPixels(SkColorTable**);
|
||||
virtual void onUnlockPixels();
|
||||
virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
|
||||
virtual void onUnlockPixels() SK_OVERRIDE;
|
||||
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
|
||||
virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
|
||||
|
||||
SkMallocPixelRef(SkFlattenableReadBuffer& buffer);
|
||||
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
|
||||
|
||||
// Returns the allocation size for the pixels
|
||||
virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE { return fSize; }
|
||||
SkMallocPixelRef(const SkImageInfo&, void* addr, size_t rb, SkColorTable*,
|
||||
bool ownsPixels);
|
||||
virtual ~SkMallocPixelRef();
|
||||
|
||||
private:
|
||||
void* fStorage;
|
||||
size_t fSize;
|
||||
SkColorTable* fCTable;
|
||||
bool fOwnPixels;
|
||||
void* fStorage;
|
||||
SkColorTable* fCTable;
|
||||
size_t fRB;
|
||||
const bool fOwnPixels;
|
||||
|
||||
typedef SkPixelRef INHERITED;
|
||||
};
|
||||
|
|
|
@ -220,10 +220,11 @@ protected:
|
|||
// V14: Add flags word to PathRef serialization
|
||||
// V15: Remove A1 bitmpa config (and renumber remaining configs)
|
||||
// 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
|
||||
static const uint32_t PRIOR_PICTURE_VERSION = 15; // TODO: remove when .skps regenerated
|
||||
#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
|
||||
// install their own SkPicturePlayback-derived players,SkPictureRecord-derived
|
||||
|
|
|
@ -14,8 +14,11 @@
|
|||
#include "SkRefCnt.h"
|
||||
#include "SkString.h"
|
||||
#include "SkFlattenable.h"
|
||||
#include "SkImageInfo.h"
|
||||
#include "SkTDArray.h"
|
||||
|
||||
#define SK_SUPPORT_LEGACY_ONLOCKPIXELS
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
/**
|
||||
* Defining SK_IGNORE_PIXELREF_SETPRELOCKED will force all pixelref
|
||||
|
@ -49,18 +52,35 @@ class SK_API SkPixelRef : public SkFlattenable {
|
|||
public:
|
||||
SK_DECLARE_INST_COUNT(SkPixelRef)
|
||||
|
||||
explicit SkPixelRef(SkBaseMutex* mutex = NULL);
|
||||
explicit SkPixelRef(const SkImageInfo&);
|
||||
SkPixelRef(const SkImageInfo&, SkBaseMutex* mutex);
|
||||
virtual ~SkPixelRef();
|
||||
|
||||
const SkImageInfo& info() const {
|
||||
return fInfo;
|
||||
}
|
||||
|
||||
/** Return the pixel memory returned from lockPixels, or null if the
|
||||
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.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
@ -68,10 +88,19 @@ public:
|
|||
|
||||
SkDEBUGCODE(int getLockCount() const { return fLockCount; })
|
||||
|
||||
/** Call to access the pixel memory, which is returned. Balance with a call
|
||||
to unlockPixels().
|
||||
*/
|
||||
void lockPixels();
|
||||
/**
|
||||
* Call to access the pixel memory. Return true on success. Balance this
|
||||
* with a call to unlockPixels().
|
||||
*/
|
||||
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
|
||||
(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
|
||||
|
@ -228,14 +257,28 @@ public:
|
|||
void addGenIDChangeListener(GenIDChangeListener* listener);
|
||||
|
||||
protected:
|
||||
/** Called when the lockCount goes from 0 to 1. The caller will have already
|
||||
acquire a mutex for thread safety, so this method need not do that.
|
||||
*/
|
||||
virtual void* onLockPixels(SkColorTable**) = 0;
|
||||
/** 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
|
||||
that.
|
||||
*/
|
||||
#ifdef SK_SUPPORT_LEGACY_ONLOCKPIXELS
|
||||
virtual void* onLockPixels(SkColorTable**);
|
||||
virtual bool onNewLockPixels(LockRec*);
|
||||
#else
|
||||
/**
|
||||
* On success, returns true and fills out the LockRec for the pixels. On
|
||||
* 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;
|
||||
|
||||
/** Default impl returns true */
|
||||
|
@ -279,12 +322,14 @@ protected:
|
|||
// only call from constructor. Flags this to always be locked, removing
|
||||
// the need to grab the mutex and call onLockPixels/onUnlockPixels.
|
||||
// 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:
|
||||
SkBaseMutex* fMutex; // must remain in scope for the life of this object
|
||||
void* fPixels;
|
||||
SkColorTable* fColorTable; // we do not track ownership, subclass does
|
||||
SkImageInfo fInfo;
|
||||
|
||||
// LockRec is only valid if we're in a locked state (isLocked())
|
||||
LockRec fRec;
|
||||
int fLockCount;
|
||||
|
||||
mutable uint32_t fGenerationID;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
class GrTexture;
|
||||
class GrRenderTarget;
|
||||
struct SkImageInfo;
|
||||
|
||||
class GrSurface : public GrResource {
|
||||
public:
|
||||
|
@ -58,6 +59,8 @@ public:
|
|||
*/
|
||||
const GrTextureDesc& desc() const { return fDesc; }
|
||||
|
||||
void asImageInfo(SkImageInfo*) const;
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config);
|
||||
bool GrPixelConfig2ColorType(GrPixelConfig, SkColorType*);
|
||||
|
||||
static inline GrColor SkColor2GrColor(SkColor c) {
|
||||
SkPMColor pm = SkPreMultiplyColor(c);
|
||||
|
|
|
@ -23,14 +23,13 @@
|
|||
*/
|
||||
class SK_API SkROLockPixelsPixelRef : public SkPixelRef {
|
||||
public:
|
||||
SkROLockPixelsPixelRef();
|
||||
SkROLockPixelsPixelRef(const SkImageInfo&);
|
||||
virtual ~SkROLockPixelsPixelRef();
|
||||
|
||||
protected:
|
||||
// override from SkPixelRef
|
||||
virtual void* onLockPixels(SkColorTable** ptr);
|
||||
virtual void onUnlockPixels();
|
||||
virtual bool onLockPixelsAreWritable() const; // return false;
|
||||
virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
|
||||
virtual void onUnlockPixels() SK_OVERRIDE;
|
||||
virtual bool onLockPixelsAreWritable() const SK_OVERRIDE; // return false;
|
||||
|
||||
private:
|
||||
SkBitmap fBitmap;
|
||||
|
@ -47,7 +46,7 @@ public:
|
|||
* cache and would like the pixel ref to unlock it in its destructor then transferCacheLock
|
||||
* should be set to true.
|
||||
*/
|
||||
SkGrPixelRef(GrSurface* surface, bool transferCacheLock = false);
|
||||
SkGrPixelRef(const SkImageInfo&, GrSurface*, bool transferCacheLock = false);
|
||||
virtual ~SkGrPixelRef();
|
||||
|
||||
// override from SkPixelRef
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
@param config The preferred config of the decoded bitmap.
|
||||
@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);
|
||||
virtual ~SkImageRef();
|
||||
|
||||
|
@ -72,9 +72,9 @@ protected:
|
|||
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
|
||||
virtual void onUnlockPixels() {}
|
||||
virtual void onUnlockPixels() SK_OVERRIDE {}
|
||||
|
||||
SkImageRef(SkFlattenableReadBuffer&, SkBaseMutex* mutex = NULL);
|
||||
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
|
||||
|
@ -89,7 +89,6 @@ private:
|
|||
|
||||
SkImageDecoderFactory* fFactory; // may be null
|
||||
SkStreamRewindable* fStream;
|
||||
SkBitmap::Config fConfig;
|
||||
int fSampleSize;
|
||||
bool fDoDither;
|
||||
bool fErrorInDecoding;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
class SkImageRef_GlobalPool : public SkImageRef {
|
||||
public:
|
||||
// if pool is null, use the global pool
|
||||
SkImageRef_GlobalPool(SkStreamRewindable*, SkBitmap::Config,
|
||||
SkImageRef_GlobalPool(const SkImageInfo&, SkStreamRewindable*,
|
||||
int sampleSize = 1);
|
||||
virtual ~SkImageRef_GlobalPool();
|
||||
|
||||
|
|
|
@ -40,7 +40,9 @@ static SkBitmap load_bitmap() {
|
|||
|
||||
if (SkImageDecoder::DecodeStream(stream, &bm, SkBitmap::kNo_Config,
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
// do this first, we that we never have a non-zero offset with a null ref
|
||||
if (NULL == pr) {
|
||||
|
@ -411,10 +453,20 @@ void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
|
|||
return;
|
||||
}
|
||||
|
||||
Sk64 size = this->getSize64();
|
||||
SkASSERT(!size.isNeg() && size.is32());
|
||||
SkImageInfo info;
|
||||
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
|
||||
this->lockPixels();
|
||||
SkDEBUGCODE(this->validate();)
|
||||
|
@ -479,17 +531,19 @@ GrTexture* SkBitmap::getTexture() const {
|
|||
*/
|
||||
bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
|
||||
SkColorTable* ctable) {
|
||||
Sk64 size = dst->getSize64();
|
||||
if (size.isNeg() || !size.is32()) {
|
||||
SkImageInfo info;
|
||||
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;
|
||||
}
|
||||
|
||||
void* addr = sk_malloc_flags(size.get32(), 0); // returns NULL on failure
|
||||
if (NULL == addr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dst->setPixelRef(new SkMallocPixelRef(addr, size.get32(), ctable))->unref();
|
||||
dst->setPixelRef(pr, 0)->unref();
|
||||
// since we're already allocated, we lockPixels right away
|
||||
dst->lockPixels();
|
||||
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
|
||||
void SkBitmap::validate() const {
|
||||
SkASSERT(fConfig < kConfigCount);
|
||||
|
|
|
@ -24,31 +24,30 @@ SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties&
|
|||
, 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 ?
|
||||
kOpaque_SkAlphaType : kPremul_SkAlphaType);
|
||||
if (!fBitmap.allocPixels()) {
|
||||
fBitmap.setConfig(config, 0, 0, 0, isOpaque ?
|
||||
kOpaque_SkAlphaType : kPremul_SkAlphaType);
|
||||
}
|
||||
if (!isOpaque) {
|
||||
fBitmap.eraseColor(SK_ColorTRANSPARENT);
|
||||
|
||||
if (SkBitmap::kNo_Config != config) {
|
||||
if (!fBitmap.allocPixels()) {
|
||||
// indicate failure by zeroing our bitmap
|
||||
fBitmap.setConfig(config, 0, 0, 0, isOpaque ?
|
||||
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,
|
||||
const SkDeviceProperties& deviceProperties)
|
||||
: SkBaseDevice(deviceProperties) {
|
||||
|
||||
fBitmap.setConfig(config, width, height, 0, 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);
|
||||
}
|
||||
: SkBaseDevice(deviceProperties)
|
||||
{
|
||||
this->init(config, width, height, isOpaque);
|
||||
}
|
||||
|
||||
SkBitmapDevice::~SkBitmapDevice() {
|
||||
|
|
|
@ -15,8 +15,14 @@
|
|||
#include "SkGr.h"
|
||||
|
||||
bool SkImageFilterUtils::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) {
|
||||
result->setConfig(SkBitmap::kARGB_8888_Config, width, height);
|
||||
result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (texture)))->unref();
|
||||
SkImageInfo info;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -36,8 +42,12 @@ bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter:
|
|||
} else {
|
||||
if (filter->filterImage(proxy, src, ctm, result, offset)) {
|
||||
if (!result->getTexture()) {
|
||||
SkImageInfo info;
|
||||
if (!result->asImageInfo(&info)) {
|
||||
return false;
|
||||
}
|
||||
GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL);
|
||||
result->setPixelRef(new SkGrPixelRef(resultTex))->unref();
|
||||
result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref();
|
||||
GrUnlockAndUnrefCachedBitmapTexture(resultTex);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -1,27 +1,105 @@
|
|||
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkMallocPixelRef.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkFlattenableBuffers.h"
|
||||
|
||||
SkMallocPixelRef::SkMallocPixelRef(void* storage, size_t size,
|
||||
SkColorTable* ctable, bool ownPixels) {
|
||||
if (NULL == storage) {
|
||||
SkASSERT(ownPixels);
|
||||
storage = sk_malloc_throw(size);
|
||||
static bool check_info(const SkImageInfo& info, SkColorTable* ctable) {
|
||||
if (info.fWidth < 0 ||
|
||||
info.fHeight < 0 ||
|
||||
(unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType ||
|
||||
(unsigned)info.fAlphaType > (unsigned)kLastEnum_SkAlphaType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fStorage = storage;
|
||||
fSize = size;
|
||||
fCTable = ctable;
|
||||
SkSafeRef(ctable);
|
||||
fOwnPixels = ownPixels;
|
||||
|
||||
// these seem like good checks, but currently we have (at least) tests
|
||||
// that expect the pixelref to succeed even when there is a mismatch
|
||||
// with colortables. fix?
|
||||
#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() {
|
||||
|
@ -31,19 +109,30 @@ SkMallocPixelRef::~SkMallocPixelRef() {
|
|||
}
|
||||
}
|
||||
|
||||
void* SkMallocPixelRef::onLockPixels(SkColorTable** ct) {
|
||||
*ct = fCTable;
|
||||
return fStorage;
|
||||
bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) {
|
||||
rec->fPixels = fStorage;
|
||||
rec->fRowBytes = fRB;
|
||||
rec->fColorTable = fCTable;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkMallocPixelRef::onUnlockPixels() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
|
||||
return this->info().getSafeSize(fRB);
|
||||
}
|
||||
|
||||
void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
|
||||
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);
|
||||
if (fCTable) {
|
||||
fCTable->writeToBuffer(buffer);
|
||||
|
@ -51,16 +140,18 @@ void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
|
|||
}
|
||||
|
||||
SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
|
||||
: INHERITED(buffer, NULL) {
|
||||
fSize = buffer.getArrayCount();
|
||||
fStorage = sk_malloc_throw(fSize);
|
||||
buffer.readByteArray(fStorage, fSize);
|
||||
: INHERITED(buffer, NULL)
|
||||
, fOwnPixels(true)
|
||||
{
|
||||
fRB = buffer.read32();
|
||||
size_t size = this->info().getSafeSize(fRB);
|
||||
fStorage = sk_malloc_throw(size);
|
||||
buffer.readByteArray(fStorage, size);
|
||||
if (buffer.readBool()) {
|
||||
fCTable = SkNEW_ARGS(SkColorTable, (buffer));
|
||||
} else {
|
||||
fCTable = NULL;
|
||||
}
|
||||
fOwnPixels = true;
|
||||
|
||||
this->setPreLocked(fStorage, fCTable);
|
||||
this->setPreLocked(fStorage, fRB, fCTable);
|
||||
}
|
||||
|
|
|
@ -349,10 +349,14 @@ bool SkMaskFilter::filterMaskGPU(GrContext* context,
|
|||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
SkAutoUnref aur(dst);
|
||||
|
||||
SkImageInfo info;
|
||||
resultBM->setConfig(srcBM.config(), dst->width(), dst->height());
|
||||
resultBM->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (dst)))->unref();
|
||||
dst->unref();
|
||||
if (resultBM->asImageInfo(&info)) {
|
||||
return false;
|
||||
}
|
||||
resultBM->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, dst)))->unref();
|
||||
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
|
||||
#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);
|
||||
fPixels = NULL;
|
||||
fColorTable = NULL; // we do not track ownership of this
|
||||
fInfo = info;
|
||||
fRec.zero();
|
||||
fLockCount = 0;
|
||||
this->needsNewGenID();
|
||||
fIsImmutable = false;
|
||||
|
@ -95,8 +105,9 @@ SkPixelRef::SkPixelRef(SkBaseMutex* mutex) {
|
|||
SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
|
||||
: INHERITED(buffer) {
|
||||
this->setMutex(mutex);
|
||||
fPixels = NULL;
|
||||
fColorTable = NULL; // we do not track ownership of this
|
||||
|
||||
fInfo.unflatten(buffer);
|
||||
fRec.zero();
|
||||
fLockCount = 0;
|
||||
fIsImmutable = buffer.readBool();
|
||||
fGenerationID = buffer.readUInt();
|
||||
|
@ -120,12 +131,13 @@ void SkPixelRef::cloneGenID(const SkPixelRef& that) {
|
|||
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
|
||||
// only call me in your constructor, otherwise fLockCount tracking can get
|
||||
// out of sync.
|
||||
fPixels = pixels;
|
||||
fColorTable = ctable;
|
||||
fRec.fPixels = pixels;
|
||||
fRec.fColorTable = ctable;
|
||||
fRec.fRowBytes = rowBytes;
|
||||
fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT;
|
||||
fPreLocked = true;
|
||||
#endif
|
||||
|
@ -133,6 +145,8 @@ void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) {
|
|||
|
||||
void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
|
||||
this->INHERITED::flatten(buffer);
|
||||
|
||||
fInfo.flatten(buffer);
|
||||
buffer.writeBool(fIsImmutable);
|
||||
// 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
|
||||
|
@ -147,16 +161,27 @@ void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
|
|||
}
|
||||
}
|
||||
|
||||
void SkPixelRef::lockPixels() {
|
||||
bool SkPixelRef::lockPixels(LockRec* rec) {
|
||||
SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
|
||||
|
||||
|
||||
if (!fPreLocked) {
|
||||
SkAutoMutexAcquire ac(*fMutex);
|
||||
|
||||
|
||||
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() {
|
||||
|
@ -168,8 +193,7 @@ void SkPixelRef::unlockPixels() {
|
|||
SkASSERT(fLockCount > 0);
|
||||
if (0 == --fLockCount) {
|
||||
this->onUnlockPixels();
|
||||
fPixels = NULL;
|
||||
fColorTable = NULL;
|
||||
fRec.zero();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
void SkPixelRef::globalRef(void* data) {
|
||||
this->ref();
|
||||
|
|
|
@ -513,13 +513,14 @@ const uint16_t* SkGradientShaderBase::getCache16() const {
|
|||
|
||||
const SkPMColor* SkGradientShaderBase::getCache32() const {
|
||||
if (fCache32 == NULL) {
|
||||
// double the count for dither entries
|
||||
const int entryCount = kCache32Count * 4;
|
||||
const size_t allocSize = sizeof(SkPMColor) * entryCount;
|
||||
SkImageInfo info;
|
||||
info.fWidth = kCache32Count;
|
||||
info.fHeight = 4; // for our 4 dither rows
|
||||
info.fAlphaType = kPremul_SkAlphaType;
|
||||
info.fColorType = kPMColor_SkColorType;
|
||||
|
||||
if (NULL == fCache32PixelRef) {
|
||||
fCache32PixelRef = SkNEW_ARGS(SkMallocPixelRef,
|
||||
(NULL, allocSize, NULL));
|
||||
fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL);
|
||||
}
|
||||
fCache32 = (SkPMColor*)fCache32PixelRef->getAddr();
|
||||
if (fColorCount == 2) {
|
||||
|
@ -541,8 +542,7 @@ const SkPMColor* SkGradientShaderBase::getCache32() const {
|
|||
}
|
||||
|
||||
if (fMapper) {
|
||||
SkMallocPixelRef* newPR = SkNEW_ARGS(SkMallocPixelRef,
|
||||
(NULL, allocSize, NULL));
|
||||
SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NULL);
|
||||
SkPMColor* linear = fCache32; // just computed linear data
|
||||
SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data
|
||||
SkUnitMapper* map = fMapper;
|
||||
|
|
|
@ -8,9 +8,19 @@
|
|||
#include "GrSurface.h"
|
||||
|
||||
#include "SkBitmap.h"
|
||||
#include "SkGr.h"
|
||||
#include "SkImageEncoder.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) {
|
||||
SkBitmap bm;
|
||||
bm.setConfig(SkBitmap::kARGB_8888_Config, this->width(), this->height());
|
||||
|
|
|
@ -200,7 +200,10 @@ void SkGpuDevice::initFromRenderTarget(GrContext* context,
|
|||
if (NULL == surface) {
|
||||
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();
|
||||
}
|
||||
|
@ -210,8 +213,8 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
|
|||
int width,
|
||||
int height,
|
||||
int sampleCount)
|
||||
: SkBitmapDevice(config, width, height, false /*isOpaque*/) {
|
||||
|
||||
: SkBitmapDevice(config, width, height, false /*isOpaque*/)
|
||||
{
|
||||
fDrawProcs = NULL;
|
||||
|
||||
fContext = context;
|
||||
|
@ -231,6 +234,14 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
|
|||
desc.fConfig = SkBitmapConfig2GrPixelConfig(config);
|
||||
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));
|
||||
|
||||
if (NULL != texture) {
|
||||
|
@ -240,7 +251,7 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
|
|||
SkASSERT(NULL != fRenderTarget);
|
||||
|
||||
// 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();
|
||||
} else {
|
||||
GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
|
||||
|
@ -826,11 +837,12 @@ bool create_mask_GPU(GrContext* context,
|
|||
}
|
||||
|
||||
SkBitmap wrap_texture(GrTexture* texture) {
|
||||
SkImageInfo info;
|
||||
texture->asImageInfo(&info);
|
||||
|
||||
SkBitmap result;
|
||||
bool dummy;
|
||||
SkBitmap::Config config = grConfig2skConfig(texture->config(), &dummy);
|
||||
result.setConfig(config, texture->width(), texture->height());
|
||||
result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (texture)))->unref();
|
||||
result.setConfig(info);
|
||||
result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -258,3 +258,33 @@ GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config config) {
|
|||
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.
|
||||
SK_DECLARE_STATIC_MUTEX(gROLockPixelsPixelRefMutex);
|
||||
|
||||
SkROLockPixelsPixelRef::SkROLockPixelsPixelRef() : INHERITED(&gROLockPixelsPixelRefMutex) {
|
||||
SkROLockPixelsPixelRef::SkROLockPixelsPixelRef(const SkImageInfo& info)
|
||||
: INHERITED(info, &gROLockPixelsPixelRefMutex) {
|
||||
}
|
||||
|
||||
SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {
|
||||
}
|
||||
|
||||
void* SkROLockPixelsPixelRef::onLockPixels(SkColorTable** ctable) {
|
||||
if (ctable) {
|
||||
*ctable = NULL;
|
||||
}
|
||||
bool SkROLockPixelsPixelRef::onNewLockPixels(LockRec* rec) {
|
||||
fBitmap.reset();
|
||||
// SkDebugf("---------- calling readpixels in support of lockpixels\n");
|
||||
if (!this->onReadPixels(&fBitmap, NULL)) {
|
||||
SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n");
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
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() {
|
||||
|
@ -76,6 +81,14 @@ static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config
|
|||
desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
|
||||
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);
|
||||
if (NULL == dst) {
|
||||
return NULL;
|
||||
|
@ -93,14 +106,17 @@ static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config
|
|||
dst->releaseRenderTarget();
|
||||
#endif
|
||||
|
||||
SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (dst));
|
||||
SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst));
|
||||
SkSafeUnref(dst);
|
||||
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
|
||||
#if 0
|
||||
// The GrTexture has a ref to the GrRenderTarget but not vice versa.
|
||||
|
|
|
@ -9,18 +9,25 @@
|
|||
#include "SkData.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();
|
||||
this->setPreLocked(const_cast<void*>(fData->data()), NULL);
|
||||
this->setPreLocked(const_cast<void*>(fData->data()), rowBytes, NULL);
|
||||
}
|
||||
|
||||
SkDataPixelRef::~SkDataPixelRef() {
|
||||
fData->unref();
|
||||
}
|
||||
|
||||
void* SkDataPixelRef::onLockPixels(SkColorTable** ct) {
|
||||
*ct = NULL;
|
||||
return const_cast<void*>(fData->data());
|
||||
bool SkDataPixelRef::onNewLockPixels(LockRec* rec) {
|
||||
rec->fPixels = const_cast<void*>(fData->data());
|
||||
rec->fColorTable = NULL;
|
||||
rec->fRowBytes = fRB;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkDataPixelRef::onUnlockPixels() {
|
||||
|
@ -33,11 +40,15 @@ size_t SkDataPixelRef::getAllocatedSizeInBytes() const {
|
|||
|
||||
void SkDataPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
|
||||
this->INHERITED::flatten(buffer);
|
||||
|
||||
buffer.writeDataAsByteArray(fData);
|
||||
buffer.write32(fRB);
|
||||
}
|
||||
|
||||
SkDataPixelRef::SkDataPixelRef(SkFlattenableReadBuffer& buffer)
|
||||
: INHERITED(buffer, NULL) {
|
||||
: INHERITED(buffer, NULL)
|
||||
{
|
||||
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 {
|
||||
public:
|
||||
SkDataPixelRef(SkData* data);
|
||||
SkDataPixelRef(const SkImageInfo&, SkData* data, size_t rowBytes);
|
||||
virtual ~SkDataPixelRef();
|
||||
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDataPixelRef)
|
||||
|
||||
protected:
|
||||
virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
|
||||
virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
|
||||
virtual void onUnlockPixels() SK_OVERRIDE;
|
||||
virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
|
||||
|
||||
|
@ -28,7 +28,8 @@ protected:
|
|||
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
SkData* fData;
|
||||
SkData* fData;
|
||||
size_t fRB;
|
||||
|
||||
typedef SkPixelRef INHERITED;
|
||||
};
|
||||
|
|
|
@ -84,10 +84,8 @@ SkImage* SkImage_Raster::NewEmpty() {
|
|||
|
||||
SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes)
|
||||
: INHERITED(info.fWidth, info.fHeight) {
|
||||
SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
|
||||
|
||||
fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes, info.fAlphaType);
|
||||
fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (data)))->unref();
|
||||
fBitmap.setConfig(info, rowBytes);
|
||||
fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (info, data, rowBytes)))->unref();
|
||||
fBitmap.setImmutable();
|
||||
}
|
||||
|
||||
|
|
|
@ -155,19 +155,9 @@ SkSurface* SkSurface::NewRaster(const SkImageInfo& info) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const size_t kMaxTotalSize = SK_MaxS32;
|
||||
size_t rowBytes = SkImageMinRowBytes(info);
|
||||
uint64_t size64 = (uint64_t)info.fHeight * rowBytes;
|
||||
if (size64 > kMaxTotalSize) {
|
||||
SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewAllocate(info, 0, NULL));
|
||||
if (NULL == pr.get()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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));
|
||||
return SkNEW_ARGS(SkSurface_Raster, (info, pr, info.minRowBytes()));
|
||||
}
|
||||
|
|
|
@ -15,16 +15,14 @@
|
|||
|
||||
//#define DUMP_IMAGEREF_LIFECYCLE
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkImageRef::SkImageRef(SkStreamRewindable* stream, SkBitmap::Config config,
|
||||
SkImageRef::SkImageRef(const SkImageInfo& info, SkStreamRewindable* stream,
|
||||
int sampleSize, SkBaseMutex* mutex)
|
||||
: SkPixelRef(mutex), fErrorInDecoding(false) {
|
||||
: INHERITED(info, mutex), fErrorInDecoding(false) {
|
||||
SkASSERT(stream);
|
||||
stream->ref();
|
||||
fStream = stream;
|
||||
fConfig = config;
|
||||
fSampleSize = sampleSize;
|
||||
fDoDither = true;
|
||||
fPrev = fNext = NULL;
|
||||
|
@ -40,7 +38,7 @@ SkImageRef::~SkImageRef() {
|
|||
|
||||
#ifdef DUMP_IMAGEREF_LIFECYCLE
|
||||
SkDebugf("delete ImageRef %p [%d] data=%d\n",
|
||||
this, fConfig, (int)fStream->getLength());
|
||||
this, this->info().fColorType, (int)fStream->getLength());
|
||||
#endif
|
||||
|
||||
fStream->unref();
|
||||
|
@ -92,14 +90,6 @@ bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
|
|||
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() ||
|
||||
(SkBitmap::kNo_Config != fBitmap.config() &&
|
||||
SkImageDecoder::kDecodeBounds_Mode == mode)) {
|
||||
|
@ -125,7 +115,7 @@ bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
|
|||
|
||||
codec->setSampleSize(fSampleSize);
|
||||
codec->setDitherImage(fDoDither);
|
||||
if (this->onDecode(codec, fStream, &fBitmap, fConfig, mode)) {
|
||||
if (this->onDecode(codec, fStream, &fBitmap, fBitmap.config(), mode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -143,15 +133,18 @@ bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void* SkImageRef::onLockPixels(SkColorTable** ct) {
|
||||
bool SkImageRef::onNewLockPixels(LockRec* rec) {
|
||||
if (NULL == fBitmap.getPixels()) {
|
||||
(void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode);
|
||||
}
|
||||
|
||||
if (ct) {
|
||||
*ct = fBitmap.getColorTable();
|
||||
if (NULL == fBitmap.getPixels()) {
|
||||
return false;
|
||||
}
|
||||
return fBitmap.getPixels();
|
||||
rec->fPixels = fBitmap.getPixels();
|
||||
rec->fColorTable = NULL;
|
||||
rec->fRowBytes = fBitmap.rowBytes();
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t SkImageRef::ramUsed() const {
|
||||
|
@ -170,7 +163,6 @@ size_t SkImageRef::ramUsed() const {
|
|||
|
||||
SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
|
||||
: INHERITED(buffer, mutex), fErrorInDecoding(false) {
|
||||
fConfig = (SkBitmap::Config)buffer.readUInt();
|
||||
fSampleSize = buffer.readInt();
|
||||
fDoDither = buffer.readBool();
|
||||
|
||||
|
@ -185,7 +177,6 @@ SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
|
|||
void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const {
|
||||
this->INHERITED::flatten(buffer);
|
||||
|
||||
buffer.writeUInt(fConfig);
|
||||
buffer.writeInt(fSampleSize);
|
||||
buffer.writeBool(fDoDither);
|
||||
// FIXME: Consider moving this logic should go into writeStream itself.
|
||||
|
|
|
@ -24,10 +24,10 @@ static SkImageRefPool* GetGlobalPool() {
|
|||
return gPool;
|
||||
}
|
||||
|
||||
SkImageRef_GlobalPool::SkImageRef_GlobalPool(SkStreamRewindable* stream,
|
||||
SkBitmap::Config config,
|
||||
SkImageRef_GlobalPool::SkImageRef_GlobalPool(const SkImageInfo& info,
|
||||
SkStreamRewindable* stream,
|
||||
int sampleSize)
|
||||
: SkImageRef(stream, config, sampleSize, &gGlobalPoolMutex) {
|
||||
: SkImageRef(info, stream, sampleSize, &gGlobalPoolMutex) {
|
||||
SkASSERT(&gGlobalPoolMutex == this->mutex());
|
||||
SkAutoMutexAcquire ac(gGlobalPoolMutex);
|
||||
GetGlobalPool()->addToHead(this);
|
||||
|
|
|
@ -31,10 +31,10 @@ static size_t roundToPageSize(size_t size) {
|
|||
return newsize;
|
||||
}
|
||||
|
||||
SkImageRef_ashmem::SkImageRef_ashmem(SkStreamRewindable* stream,
|
||||
SkBitmap::Config config,
|
||||
int sampleSize)
|
||||
: SkImageRef(stream, config, sampleSize) {
|
||||
SkImageRef_ashmem::SkImageRef_ashmem(const SkImageInfo& info,
|
||||
SkStreamRewindable* stream,
|
||||
int sampleSize)
|
||||
: SkImageRef(info, stream, sampleSize) {
|
||||
|
||||
fRec.fFD = -1;
|
||||
fRec.fAddr = NULL;
|
||||
|
|
|
@ -19,7 +19,7 @@ struct SkAshmemRec {
|
|||
|
||||
class SkImageRef_ashmem : public SkImageRef {
|
||||
public:
|
||||
SkImageRef_ashmem(SkStreamRewindable*, SkBitmap::Config, int sampleSize = 1);
|
||||
SkImageRef_ashmem(const SkImageInfo&, SkStreamRewindable*, int sampleSize = 1);
|
||||
virtual ~SkImageRef_ashmem();
|
||||
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkImageRef_ashmem)
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "SkCachingPixelRef.h"
|
||||
#include "SkScaledImageCache.h"
|
||||
|
||||
|
||||
bool SkCachingPixelRef::Install(SkImageGenerator* generator,
|
||||
SkBitmap* dst) {
|
||||
SkImageInfo info;
|
||||
|
@ -31,10 +30,10 @@ bool SkCachingPixelRef::Install(SkImageGenerator* generator,
|
|||
SkCachingPixelRef::SkCachingPixelRef(SkImageGenerator* generator,
|
||||
const SkImageInfo& info,
|
||||
size_t rowBytes)
|
||||
: fImageGenerator(generator)
|
||||
: INHERITED(info)
|
||||
, fImageGenerator(generator)
|
||||
, fErrorInDecoding(false)
|
||||
, fScaledCacheId(NULL)
|
||||
, fInfo(info)
|
||||
, fRowBytes(rowBytes) {
|
||||
SkASSERT(fImageGenerator != NULL);
|
||||
}
|
||||
|
@ -44,31 +43,32 @@ SkCachingPixelRef::~SkCachingPixelRef() {
|
|||
// Assert always unlock before unref.
|
||||
}
|
||||
|
||||
void* SkCachingPixelRef::onLockPixels(SkColorTable** colorTable) {
|
||||
(void)colorTable;
|
||||
bool SkCachingPixelRef::onNewLockPixels(LockRec* rec) {
|
||||
if (fErrorInDecoding) {
|
||||
return NULL; // don't try again.
|
||||
return false; // don't try again.
|
||||
}
|
||||
|
||||
const SkImageInfo& info = this->info();
|
||||
SkBitmap bitmap;
|
||||
SkASSERT(NULL == fScaledCacheId);
|
||||
fScaledCacheId = SkScaledImageCache::FindAndLock(this->getGenerationID(),
|
||||
fInfo.fWidth,
|
||||
fInfo.fHeight,
|
||||
info.fWidth,
|
||||
info.fHeight,
|
||||
&bitmap);
|
||||
if (NULL == fScaledCacheId) {
|
||||
// Cache has been purged, must re-decode.
|
||||
if ((!bitmap.setConfig(fInfo, fRowBytes)) || !bitmap.allocPixels()) {
|
||||
if ((!bitmap.setConfig(info, fRowBytes)) || !bitmap.allocPixels()) {
|
||||
fErrorInDecoding = true;
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
SkAutoLockPixels autoLockPixels(bitmap);
|
||||
if (!fImageGenerator->getPixels(fInfo, bitmap.getPixels(), fRowBytes)) {
|
||||
if (!fImageGenerator->getPixels(info, bitmap.getPixels(), fRowBytes)) {
|
||||
fErrorInDecoding = true;
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
fScaledCacheId = SkScaledImageCache::AddAndLock(this->getGenerationID(),
|
||||
fInfo.fWidth,
|
||||
fInfo.fHeight,
|
||||
info.fWidth,
|
||||
info.fHeight,
|
||||
bitmap);
|
||||
SkASSERT(fScaledCacheId != NULL);
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ void* SkCachingPixelRef::onLockPixels(SkColorTable** colorTable) {
|
|||
SkAutoLockPixels autoLockPixels(bitmap);
|
||||
void* pixels = bitmap.getPixels();
|
||||
SkASSERT(pixels != NULL);
|
||||
|
||||
// At this point, the autoLockPixels will unlockPixels()
|
||||
// to remove bitmap's lock on the pixels. We will then
|
||||
// destroy bitmap. The *only* guarantee that this pointer
|
||||
|
@ -86,7 +87,10 @@ void* SkCachingPixelRef::onLockPixels(SkColorTable** colorTable) {
|
|||
// bitmap (SkScaledImageCache::Rec.fBitmap) that holds a
|
||||
// reference to the concrete PixelRef while this record is
|
||||
// locked.
|
||||
return pixels;
|
||||
rec->fPixels = pixels;
|
||||
rec->fColorTable = NULL;
|
||||
rec->fRowBytes = bitmap.rowBytes();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkCachingPixelRef::onUnlockPixels() {
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual ~SkCachingPixelRef();
|
||||
virtual void* onLockPixels(SkColorTable** colorTable) SK_OVERRIDE;
|
||||
virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
|
||||
virtual void onUnlockPixels() SK_OVERRIDE;
|
||||
virtual bool onLockPixelsAreWritable() const SK_OVERRIDE { return false; }
|
||||
|
||||
|
@ -58,12 +58,12 @@ private:
|
|||
SkImageGenerator* const fImageGenerator;
|
||||
bool fErrorInDecoding;
|
||||
void* fScaledCacheId;
|
||||
const SkImageInfo fInfo;
|
||||
const size_t fRowBytes;
|
||||
|
||||
SkCachingPixelRef(SkImageGenerator* imageGenerator,
|
||||
const SkImageInfo& info,
|
||||
size_t rowBytes);
|
||||
|
||||
typedef SkPixelRef INHERITED;
|
||||
};
|
||||
|
||||
|
|
|
@ -10,17 +10,15 @@
|
|||
|
||||
SkDiscardablePixelRef::SkDiscardablePixelRef(SkImageGenerator* generator,
|
||||
const SkImageInfo& info,
|
||||
size_t size,
|
||||
size_t rowBytes,
|
||||
SkDiscardableMemory::Factory* fact)
|
||||
: fGenerator(generator)
|
||||
: INHERITED(info)
|
||||
, fGenerator(generator)
|
||||
, fDMFactory(fact)
|
||||
, fInfo(info)
|
||||
, fSize(size)
|
||||
, fRowBytes(rowBytes)
|
||||
, fDiscardableMemory(NULL) {
|
||||
, fDiscardableMemory(NULL)
|
||||
{
|
||||
SkASSERT(fGenerator != NULL);
|
||||
SkASSERT(fSize > 0);
|
||||
SkASSERT(fRowBytes > 0);
|
||||
// The SkImageGenerator contract requires fGenerator to always
|
||||
// decode the same image on each call to getPixels().
|
||||
|
@ -34,28 +32,39 @@ SkDiscardablePixelRef::~SkDiscardablePixelRef() {
|
|||
SkDELETE(fGenerator);
|
||||
}
|
||||
|
||||
void* SkDiscardablePixelRef::onLockPixels(SkColorTable**) {
|
||||
bool SkDiscardablePixelRef::onNewLockPixels(LockRec* rec) {
|
||||
if (fDiscardableMemory != NULL) {
|
||||
if (fDiscardableMemory->lock()) {
|
||||
return fDiscardableMemory->data();
|
||||
rec->fPixels = fDiscardableMemory->data();
|
||||
rec->fColorTable = NULL;
|
||||
rec->fRowBytes = fRowBytes;
|
||||
return true;
|
||||
}
|
||||
SkDELETE(fDiscardableMemory);
|
||||
fDiscardableMemory = NULL;
|
||||
}
|
||||
|
||||
const size_t size = this->info().getSafeSize(fRowBytes);
|
||||
if (fDMFactory != NULL) {
|
||||
fDiscardableMemory = fDMFactory->create(fSize);
|
||||
fDiscardableMemory = fDMFactory->create(size);
|
||||
} else {
|
||||
fDiscardableMemory = SkDiscardableMemory::Create(fSize);
|
||||
fDiscardableMemory = SkDiscardableMemory::Create(size);
|
||||
}
|
||||
if (NULL == fDiscardableMemory) {
|
||||
return NULL; // Memory allocation failed.
|
||||
return false; // Memory allocation failed.
|
||||
}
|
||||
|
||||
void* pixels = fDiscardableMemory->data();
|
||||
if (!fGenerator->getPixels(fInfo, pixels, fRowBytes)) {
|
||||
return NULL; // TODO(halcanary) Find out correct thing to do.
|
||||
if (!fGenerator->getPixels(this->info(), pixels, fRowBytes)) {
|
||||
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() {
|
||||
if (fDiscardableMemory != NULL) {
|
||||
fDiscardableMemory->unlock();
|
||||
|
@ -76,7 +85,6 @@ bool SkDiscardablePixelRef::Install(SkImageGenerator* generator,
|
|||
}
|
||||
SkAutoTUnref<SkDiscardablePixelRef> ref(SkNEW_ARGS(SkDiscardablePixelRef,
|
||||
(generator, info,
|
||||
dst->getSize(),
|
||||
dst->rowBytes(),
|
||||
factory)));
|
||||
dst->setPixelRef(ref);
|
||||
|
|
|
@ -50,7 +50,8 @@ public:
|
|||
|
||||
protected:
|
||||
~SkDiscardablePixelRef();
|
||||
virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
|
||||
|
||||
virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
|
||||
virtual void onUnlockPixels() SK_OVERRIDE;
|
||||
virtual bool onLockPixelsAreWritable() const SK_OVERRIDE { return false; }
|
||||
|
||||
|
@ -61,8 +62,6 @@ protected:
|
|||
private:
|
||||
SkImageGenerator* const fGenerator;
|
||||
SkDiscardableMemory::Factory* const fDMFactory;
|
||||
const SkImageInfo fInfo;
|
||||
const size_t fSize; // size of memory to be allocated
|
||||
const size_t fRowBytes;
|
||||
// These const members should not change over the life of the
|
||||
// PixelRef, since the SkBitmap doesn't expect them to change.
|
||||
|
@ -72,8 +71,10 @@ private:
|
|||
/* Takes ownership of SkImageGenerator. */
|
||||
SkDiscardablePixelRef(SkImageGenerator* generator,
|
||||
const SkImageInfo& info,
|
||||
size_t size,
|
||||
size_t rowBytes,
|
||||
SkDiscardableMemory::Factory* factory);
|
||||
|
||||
typedef SkPixelRef INHERITED;
|
||||
};
|
||||
|
||||
#endif // SkDiscardablePixelRef_DEFINED
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "SkCanvas.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkData.h"
|
||||
#include "SkDecodingImageGenerator.h"
|
||||
#include "SkError.h"
|
||||
#include "SkPaint.h"
|
||||
#include "SkPicture.h"
|
||||
|
@ -335,32 +336,6 @@ static void test_bad_bitmap() {
|
|||
}
|
||||
#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"
|
||||
|
||||
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;
|
||||
}
|
||||
SkAutoDataUnref data(wStream.copyToData());
|
||||
SkMemoryStream memStream;
|
||||
memStream.setData(data);
|
||||
|
||||
// Use the encoded bitmap as the data for an image ref.
|
||||
SkBitmap bm;
|
||||
SkAutoTUnref<SkDataImageRef> imageRef(SkNEW_ARGS(SkDataImageRef, (&memStream)));
|
||||
imageRef->getInfo(&bm);
|
||||
bm.setPixelRef(imageRef);
|
||||
bool installSuccess = SkDecodingImageGenerator::Install(data, &bm);
|
||||
REPORTER_ASSERT(reporter, installSuccess);
|
||||
|
||||
// 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
|
||||
|
|
|
@ -17,33 +17,35 @@ private:
|
|||
} // namespace
|
||||
|
||||
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.
|
||||
int count = 0;
|
||||
pixelRef.addGenIDChangeListener(SkNEW_ARGS(TestListener, (&count)));
|
||||
pixelRef->addGenIDChangeListener(SkNEW_ARGS(TestListener, (&count)));
|
||||
REPORTER_ASSERT(r, 0 == count);
|
||||
|
||||
// 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?)
|
||||
pixelRef.notifyPixelsChanged();
|
||||
pixelRef->notifyPixelsChanged();
|
||||
REPORTER_ASSERT(r, 0 == count);
|
||||
|
||||
// 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.
|
||||
pixelRef.notifyPixelsChanged();
|
||||
pixelRef->notifyPixelsChanged();
|
||||
REPORTER_ASSERT(r, 0 == count);
|
||||
|
||||
// Force the generation ID to be recalculated, then add a listener.
|
||||
REPORTER_ASSERT(r, 0 != pixelRef.getGenerationID());
|
||||
pixelRef.addGenIDChangeListener(SkNEW_ARGS(TestListener, (&count)));
|
||||
pixelRef.notifyPixelsChanged();
|
||||
REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID());
|
||||
pixelRef->addGenIDChangeListener(SkNEW_ARGS(TestListener, (&count)));
|
||||
pixelRef->notifyPixelsChanged();
|
||||
REPORTER_ASSERT(r, 1 == count);
|
||||
|
||||
// Quick check that NULL is safe.
|
||||
REPORTER_ASSERT(r, 0 != pixelRef.getGenerationID());
|
||||
pixelRef.addGenIDChangeListener(NULL);
|
||||
pixelRef.notifyPixelsChanged();
|
||||
REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID());
|
||||
pixelRef->addGenIDChangeListener(NULL);
|
||||
pixelRef->notifyPixelsChanged();
|
||||
}
|
||||
|
|
|
@ -148,6 +148,7 @@ static T* TestFlattenableSerialization(T* testObj, bool shouldSucceed,
|
|||
REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten);
|
||||
|
||||
unsigned char dataWritten[1024];
|
||||
SkASSERT(bytesWritten <= sizeof(dataWritten));
|
||||
writer.writeToMemory(dataWritten);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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;
|
||||
invalidBitmap2.setConfig(SkBitmap::kARGB_8888_Config, 256, 256);
|
||||
invalidBitmap2.setPixelRef(SkNEW_ARGS(SkMallocPixelRef,
|
||||
(NULL, 256, NULL)))->unref();
|
||||
invalidBitmap2.setConfig(info);
|
||||
|
||||
// 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
|
||||
TestBitmapSerialization(validBitmap, invalidBitmap2, false, reporter);
|
||||
|
|
Загрузка…
Ссылка в новой задаче