use allocator (if present) when we allocate our cache bitmap

Remove some bogus tests on the cache, as they are not thread-reliable. Running w/ discardable these are racy.

BUG=532981

Review URL: https://codereview.chromium.org/1351453004
This commit is contained in:
reed 2015-09-17 13:35:19 -07:00 committed by Commit bot
parent 2ed7d50307
commit 4b3d3bebda
4 changed files with 81 additions and 32 deletions

View File

@ -67,6 +67,17 @@ private:
void init(const SkPMColor* colors, int count);
friend class SkImageGenerator;
// Only call if no other thread or cache has seen this table.
void dangerous_overwriteColors(const SkPMColor newColors[], int count) {
if (count < 0 || count > fCount) {
sk_throw();
}
// assumes that f16BitCache nas NOT been initialized yet, so we don't try to update it
memcpy(fColors, newColors, count * sizeof(SkPMColor));
fCount = count; // update fCount, in case count is smaller
}
typedef SkRefCnt INHERITED;
};

View File

@ -8,6 +8,7 @@
#ifndef SkImageGenerator_DEFINED
#define SkImageGenerator_DEFINED
#include "SkBitmap.h"
#include "SkColor.h"
#include "SkImageInfo.h"
@ -166,18 +167,18 @@ public:
const SkPaint*);
bool tryGenerateBitmap(SkBitmap* bm) {
return this->tryGenerateBitmap(bm, nullptr);
return this->tryGenerateBitmap(bm, nullptr, nullptr);
}
bool tryGenerateBitmap(SkBitmap* bm, const SkImageInfo& info) {
return this->tryGenerateBitmap(bm, &info);
bool tryGenerateBitmap(SkBitmap* bm, const SkImageInfo& info, SkBitmap::Allocator* allocator) {
return this->tryGenerateBitmap(bm, &info, allocator);
}
void generateBitmap(SkBitmap* bm) {
if (!this->tryGenerateBitmap(bm, nullptr)) {
if (!this->tryGenerateBitmap(bm, nullptr, nullptr)) {
sk_throw();
}
}
void generateBitmap(SkBitmap* bm, const SkImageInfo& info) {
if (!this->tryGenerateBitmap(bm, &info)) {
if (!this->tryGenerateBitmap(bm, &info, nullptr)) {
sk_throw();
}
}
@ -197,7 +198,7 @@ protected:
return nullptr;
}
bool tryGenerateBitmap(SkBitmap* bm, const SkImageInfo* optionalInfo);
bool tryGenerateBitmap(SkBitmap* bm, const SkImageInfo* optionalInfo, SkBitmap::Allocator*);
private:
const SkImageInfo fInfo;

View File

@ -11,6 +11,7 @@
#include "SkMallocPixelRef.h"
#include "SkNextID.h"
#include "SkPixelRef.h"
#include "SkResourceCache.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
@ -82,18 +83,20 @@ static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) {
// If you want the immutable bitmap with the same ID as our cacherator, call tryLockAsBitmap()
//
bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) {
SkBitmap::Allocator* allocator = SkResourceCache::GetAllocator();
ScopedGenerator generator(this);
const SkImageInfo& genInfo = generator->getInfo();
if (fInfo.dimensions() == genInfo.dimensions()) {
SkASSERT(fOrigin.x() == 0 && fOrigin.y() == 0);
// fast-case, no copy needed
return generator->tryGenerateBitmap(bitmap, fInfo);
return generator->tryGenerateBitmap(bitmap, fInfo, allocator);
} else {
// need to handle subsetting, so we first generate the full size version, and then
// "read" from it to get our subset. See skbug.com/4213
SkBitmap full;
if (!generator->tryGenerateBitmap(&full, genInfo)) {
if (!generator->tryGenerateBitmap(&full, genInfo, allocator)) {
return false;
}
if (!bitmap->tryAllocPixels(fInfo, nullptr, full.getColorTable())) {

View File

@ -128,41 +128,75 @@ bool SkImageGenerator::onGetPixels(const SkImageInfo& info, void* dst, size_t rb
#include "SkBitmap.h"
#include "SkColorTable.h"
static void release_malloc_proc(void* pixels, void* ctx) {
sk_free(pixels);
static bool reset_and_return_false(SkBitmap* bitmap) {
bitmap->reset();
return false;
}
bool SkImageGenerator::tryGenerateBitmap(SkBitmap* bitmap, const SkImageInfo* infoPtr) {
const SkImageInfo info = infoPtr ? *infoPtr : this->getInfo();
const size_t rowBytes = info.minRowBytes();
const size_t pixelSize = info.getSafeSize(rowBytes);
if (0 == pixelSize) {
bool SkImageGenerator::tryGenerateBitmap(SkBitmap* bitmap, const SkImageInfo* infoPtr,
SkBitmap::Allocator* allocator) {
SkImageInfo info = infoPtr ? *infoPtr : this->getInfo();
if (0 == info.getSafeSize(info.minRowBytes())) {
return false;
}
SkAutoFree pixelStorage(sk_malloc_flags(pixelSize, 0));
void* pixels = pixelStorage.get();
if (!pixels) {
return false;
if (!bitmap->setInfo(info)) {
return reset_and_return_false(bitmap);
}
SkPMColor ctStorage[256];
memset(ctStorage, 0xFF, sizeof(ctStorage)); // init with opaque-white for the moment
SkAutoTUnref<SkColorTable> ctable(new SkColorTable(ctStorage, 256));
if (!bitmap->tryAllocPixels(allocator, ctable)) {
// SkResourceCache's custom allcator can'thandle ctables, so it may fail on
// kIndex_8_SkColorTable.
// skbug.com/4355
#if 1
// ignroe the allocator, and see if we can succeed without it
if (!bitmap->tryAllocPixels(nullptr, ctable)) {
return reset_and_return_false(bitmap);
}
#else
// this is the up-scale technique, not fully debugged, but we keep it here at the moment
// to remind ourselves that this might be better than ignoring the allocator.
info = SkImageInfo::MakeN32(info.width(), info.height(), info.alphaType());
if (!bitmap->setInfo(info)) {
return reset_and_return_false(bitmap);
}
// we pass nullptr for the ctable arg, since we are now explicitly N32
if (!bitmap->tryAllocPixels(allocator, nullptr)) {
return reset_and_return_false(bitmap);
}
#endif
}
bitmap->lockPixels();
if (!bitmap->getPixels()) {
return reset_and_return_false(bitmap);
}
int ctCount = 0;
if (!this->getPixels(info, pixels, rowBytes, ctStorage, &ctCount)) {
return false;
if (!this->getPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(),
ctStorage, &ctCount)) {
return reset_and_return_false(bitmap);
}
SkAutoTUnref<SkColorTable> ctable;
if (ctCount > 0) {
SkASSERT(kIndex_8_SkColorType == info.colorType());
ctable.reset(new SkColorTable(ctStorage, ctCount));
} else {
SkASSERT(kIndex_8_SkColorType != info.colorType());
}
SkASSERT(kIndex_8_SkColorType == bitmap->colorType());
// we and bitmap should be owners
SkASSERT(!ctable->unique());
return bitmap->installPixels(info, pixelStorage.detach(), rowBytes, ctable,
release_malloc_proc, nullptr);
// Now we need to overwrite the ctable we built earlier, with the correct colors.
// This does mean that we may have made the table too big, but that cannot be avoided
// until we can change SkImageGenerator's API to return us the ctable *before* we have to
// allocate space for all the pixels.
ctable->dangerous_overwriteColors(ctStorage, ctCount);
} else {
SkASSERT(kIndex_8_SkColorType != bitmap->colorType());
// we should be the only owner
SkASSERT(ctable->unique());
}
return true;
}
#include "SkGraphics.h"