зеркало из 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);
|
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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче