add installPixels

BUG=skia:
R=halcanary@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13174 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2014-01-24 18:53:42 +00:00
parent bde4ba2ce6
commit 9ebcac5463
24 changed files with 143 additions and 51 deletions

View File

@ -18,6 +18,7 @@ struct SkIRect;
struct SkRect;
class SkPaint;
class SkPixelRef;
class SkPixelRefFactory;
class SkRegion;
class SkString;
@ -249,6 +250,35 @@ public:
bool setConfig(const SkImageInfo& info, size_t rowBytes = 0);
/**
* Allocate a pixelref to match the specified image info. If the Factory
* is non-null, call it to allcoate the pixelref. If the ImageInfo requires
* a colortable, then ColorTable must be non-null, and will be ref'd.
* On failure, the bitmap will be set to empty and return false.
*/
bool allocPixels(const SkImageInfo&, SkPixelRefFactory*, SkColorTable*);
/**
* Allocate a pixelref to match the specified image info, using the default
* allocator.
* On success, the bitmap's pixels will be "locked", and return true.
* On failure, the bitmap will be set to empty and return false.
*/
bool allocPixels(const SkImageInfo& info) {
return this->allocPixels(info, NULL, NULL);
}
/**
* Install a pixelref that wraps the specified pixels and rowBytes, and
* optional ReleaseProc and context. When the pixels are no longer
* referenced, if ReleaseProc is not null, it will be called with the
* pixels and context as parameters.
* On failure, the bitmap will be set to empty and return false.
*/
bool installPixels(const SkImageInfo&, void* pixels, size_t rowBytes,
void (*ReleaseProc)(void* addr, void* context),
void* context);
/**
* 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
@ -637,7 +667,7 @@ public:
*/
class HeapAllocator : public Allocator {
public:
virtual bool allocPixelRef(SkBitmap*, SkColorTable*);
virtual bool allocPixelRef(SkBitmap*, SkColorTable*) SK_OVERRIDE;
};
class RLEPixels {

View File

@ -79,6 +79,12 @@ public:
void* getAddr() const { return fStorage; }
class PRFactory : public SkPixelRefFactory {
public:
virtual SkPixelRef* create(const SkImageInfo&,
SkColorTable*) SK_OVERRIDE;
};
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMallocPixelRef)
protected:

View File

@ -364,4 +364,15 @@ private:
typedef SkFlattenable INHERITED;
};
class SkPixelRefFactory : public SkRefCnt {
public:
/**
* Allocate a new pixelref matching the specified ImageInfo, allocating
* the memory for the pixels. If the ImageInfo requires a ColorTable,
* the pixelref will ref() the colortable.
* On failure return NULL.
*/
virtual SkPixelRef* create(const SkImageInfo&, SkColorTable*) = 0;
};
#endif

View File

@ -495,6 +495,60 @@ bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) {
return allocator->allocPixelRef(this, ctable);
}
///////////////////////////////////////////////////////////////////////////////
static bool reset_return_false(SkBitmap* bm) {
bm->reset();
return false;
}
bool SkBitmap::allocPixels(const SkImageInfo& info, SkPixelRefFactory* factory,
SkColorTable* ctable) {
if (kIndex_8_SkColorType == info.fColorType && NULL == ctable) {
return reset_return_false(this);
}
if (!this->setConfig(info)) {
return reset_return_false(this);
}
SkMallocPixelRef::PRFactory defaultFactory;
if (NULL == factory) {
factory = &defaultFactory;
}
SkPixelRef* pr = factory->create(info, ctable);
if (NULL == pr) {
return reset_return_false(this);
}
this->setPixelRef(pr)->unref();
// TODO: lockPixels could/should return bool or void*/NULL
this->lockPixels();
if (NULL == this->getPixels()) {
return reset_return_false(this);
}
return true;
}
bool SkBitmap::installPixels(const SkImageInfo& info, void* pixels, size_t rb,
void (*releaseProc)(void* addr, void* context),
void* context) {
if (!this->setConfig(info)) {
this->reset();
return false;
}
SkPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rb, NULL, pixels,
releaseProc, context);
if (!pr) {
this->reset();
return false;
}
this->setPixelRef(pr)->unref();
return true;
}
void SkBitmap::freePixels() {
// if we're gonna free the pixels, we certainly need to free the mipmap
this->freeMipMap();

View File

@ -164,10 +164,8 @@ void SkBitmapDevice::writePixels(const SkBitmap& bitmap,
drawSprite = false;
} else {
// we convert to a temporary bitmap and draw that as a sprite
dstBmp.setConfig(SkBitmap::kARGB_8888_Config,
spriteRect.width(),
spriteRect.height());
if (!dstBmp.allocPixels()) {
if (!dstBmp.allocPixels(SkImageInfo::MakeN32Premul(spriteRect.width(),
spriteRect.height()))) {
return;
}
drawSprite = true;

View File

@ -92,9 +92,8 @@ bool SkBaseDevice::readPixels(SkBitmap* bitmap, int x, int y,
SkBitmap tmp;
SkBitmap* bmp;
if (bitmap->isNull()) {
tmp.setConfig(SkBitmap::kARGB_8888_Config, bitmap->width(),
bitmap->height());
if (!tmp.allocPixels()) {
if (!tmp.allocPixels(SkImageInfo::MakeN32Premul(bitmap->width(),
bitmap->height()))) {
return false;
}
bmp = &tmp;

View File

@ -238,3 +238,11 @@ SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
this->setPreLocked(fStorage, fRB, fCTable);
}
///////////////////////////////////////////////////////////////////////////////
SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info,
SkColorTable* ctable) {
return SkMallocPixelRef::NewAllocate(info, info.minRowBytes(), ctable);
}

View File

@ -252,8 +252,7 @@ void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) {
}
}
// Could not read the SkBitmap. Use a placeholder bitmap.
bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
bitmap->allocPixels();
bitmap->allocPixels(SkImageInfo::MakeN32Premul(width, height));
bitmap->eraseColor(SK_ColorRED);
}

View File

@ -323,8 +323,7 @@ bool SkAlphaThresholdFilterImpl::onFilterImage(Proxy*, const SkBitmap& src,
}
dst->setConfig(src.config(), src.width(), src.height());
dst->allocPixels();
if (!dst->getPixels()) {
if (!dst->allocPixels()) {
return false;
}

View File

@ -108,8 +108,7 @@ bool SkBicubicImageFilter::onFilterImage(Proxy* proxy,
return false;
}
result->setConfig(src.config(), dstIRect.width(), dstIRect.height());
result->allocPixels();
if (!result->getPixels()) {
if (!result->allocPixels()) {
return false;
}

View File

@ -160,8 +160,7 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
dst->setConfig(src.config(), srcBounds.width(), srcBounds.height());
dst->getBounds(&dstBounds);
dst->allocPixels();
if (!dst->getPixels()) {
if (!dst->allocPixels()) {
return false;
}

View File

@ -229,8 +229,7 @@ bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy,
}
dst->setConfig(color.config(), bounds.width(), bounds.height());
dst->allocPixels();
if (!dst->getPixels()) {
if (!dst->allocPixels()) {
return false;
}

View File

@ -952,8 +952,7 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
}
dst->setConfig(src.config(), bounds.width(), bounds.height());
dst->allocPixels();
if (!dst->getPixels()) {
if (!dst->allocPixels()) {
return false;
}

View File

@ -241,8 +241,7 @@ public:
{
if (!fPermutationsBitmap) {
fPermutationsBitmap = SkNEW(SkBitmap);
fPermutationsBitmap->setConfig(SkBitmap::kA8_Config, kBlockSize, 1);
fPermutationsBitmap->allocPixels();
fPermutationsBitmap->allocPixels(SkImageInfo::MakeA8(kBlockSize, 1));
uint8_t* bitmapPixels = fPermutationsBitmap->getAddr8(0, 0);
memcpy(bitmapPixels, fLatticeSelector, sizeof(uint8_t) * kBlockSize);
}
@ -253,8 +252,7 @@ public:
{
if (!fNoiseBitmap) {
fNoiseBitmap = SkNEW(SkBitmap);
fNoiseBitmap->setConfig(SkBitmap::kARGB_8888_Config, kBlockSize, 4);
fNoiseBitmap->allocPixels();
fNoiseBitmap->allocPixels(SkImageInfo::MakeN32Premul(kBlockSize, 4));
uint32_t* bitmapPixels = fNoiseBitmap->getAddr32(0, 0);
memcpy(bitmapPixels, fNoise[0][0], sizeof(uint16_t) * kBlockSize * 4 * 2);
}

View File

@ -203,8 +203,7 @@ bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const {
if (table) {
if (NULL == fBitmap) {
SkBitmap* bmp = SkNEW(SkBitmap);
bmp->setConfig(SkBitmap::kA8_Config, 256, 4, 256);
bmp->allocPixels();
bmp->allocPixels(SkImageInfo::MakeA8(256, 4));
uint8_t* bitmapPixels = bmp->getAddr8(0, 0);
int offset = 0;
static const unsigned kFlags[] = { kA_Flag, kR_Flag, kG_Flag, kB_Flag };

View File

@ -99,8 +99,7 @@ bool GrSWMaskHelper::init(const SkIRect& resultBounds,
SkIRect bounds = SkIRect::MakeWH(resultBounds.width(),
resultBounds.height());
fBM.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom);
if (!fBM.allocPixels()) {
if (!fBM.allocPixels(SkImageInfo::MakeA8(bounds.fRight, bounds.fBottom))) {
return false;
}
sk_bzero(fBM.getPixels(), fBM.getSafeSize());

View File

@ -23,8 +23,10 @@ void GrSurface::asImageInfo(SkImageInfo* info) const {
bool GrSurface::savePixels(const char* filename) {
SkBitmap bm;
bm.setConfig(SkBitmap::kARGB_8888_Config, this->width(), this->height());
bm.allocPixels();
if (!bm.allocPixels(SkImageInfo::MakeN32Premul(this->width(),
this->height()))) {
return false;
}
bool result = readPixels(0, 0, this->width(), this->height(), kSkia8888_GrPixelConfig,
bm.getPixels());

View File

@ -178,8 +178,7 @@ bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
top = 0;
height = fSurface->height();
}
dst->setConfig(SkBitmap::kARGB_8888_Config, width, height);
if (!dst->allocPixels()) {
if (!dst->allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n");
return false;
}

View File

@ -364,13 +364,11 @@ bool SkGIFMovie::onGetBitmap(SkBitmap* bm)
startIndex = 0;
// create bitmap
bm->setConfig(SkBitmap::kARGB_8888_Config, width, height, 0);
if (!bm->allocPixels(NULL)) {
if (!bm->allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
return false;
}
// create bitmap for backup
fBackup.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0);
if (!fBackup.allocPixels(NULL)) {
if (!fBackup.allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
return false;
}
} else if (startIndex > fCurrIndex) {

View File

@ -89,7 +89,7 @@ bool SkInstallDiscardablePixelRef(SkImageGenerator* generator,
}
SkASSERT(dst->config() != SkBitmap::kNo_Config);
if (dst->empty()) { // Use a normal pixelref.
return dst->allocPixels(NULL, NULL);
return dst->allocPixels();
}
SkAutoTUnref<SkDiscardablePixelRef> ref(
SkNEW_ARGS(SkDiscardablePixelRef,

View File

@ -2250,13 +2250,11 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
// the image. Avoiding alpha will reduce the pdf size and generation
// CPU time some.
perspectiveBitmap.setConfig(
SkBitmap::kARGB_8888_Config,
SkScalarCeilToInt(
physicalPerspectiveOutline.getBounds().width()),
SkScalarCeilToInt(
physicalPerspectiveOutline.getBounds().height()));
perspectiveBitmap.allocPixels();
const int w = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().width());
const int h = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().height());
if (!perspectiveBitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) {
return;
}
perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT);
SkBitmapDevice device(perspectiveBitmap);

View File

@ -50,8 +50,7 @@ bool SkPopplerRasterizePDF(SkStream* pdf, SkBitmap* output) {
char *imgData = image.data();
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
if (!bitmap.allocPixels()) {
if (!bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
return false;
}
bitmap.eraseColor(SK_ColorWHITE);

View File

@ -74,8 +74,7 @@ void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) {
int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
bitmap.allocPixels();
bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
SkCanvas canvas(bitmap);
canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y));

View File

@ -209,8 +209,9 @@ bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output) {
int h = (int)CGRectGetHeight(bounds);
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, w, h);
bitmap.allocPixels();
if (!bitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) {
return false;
}
bitmap.eraseColor(SK_ColorWHITE);
size_t bitsPerComponent;