2012-11-29 21:05:37 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2012 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2013-02-22 21:38:35 +00:00
|
|
|
#ifdef SK_DEBUG
|
|
|
|
|
2012-11-29 21:05:37 +00:00
|
|
|
#include "SkBitmap.h"
|
|
|
|
#include "SkBitmapFactory.h"
|
|
|
|
#include "SkCanvas.h"
|
|
|
|
#include "SkColor.h"
|
|
|
|
#include "SkData.h"
|
2013-02-22 21:38:35 +00:00
|
|
|
#include "SkImageDecoder.h"
|
2012-11-29 21:05:37 +00:00
|
|
|
#include "SkImageEncoder.h"
|
2013-02-22 21:38:35 +00:00
|
|
|
#include "SkLazyPixelRef.h"
|
|
|
|
#include "SkLruImageCache.h"
|
2012-11-29 21:05:37 +00:00
|
|
|
#include "SkPaint.h"
|
2013-03-18 21:37:39 +00:00
|
|
|
#include "SkPurgeableImageCache.h"
|
2012-11-29 21:05:37 +00:00
|
|
|
#include "SkStream.h"
|
|
|
|
#include "SkTemplates.h"
|
|
|
|
#include "Test.h"
|
|
|
|
|
|
|
|
static SkBitmap* create_bitmap() {
|
|
|
|
SkBitmap* bm = SkNEW(SkBitmap);
|
2013-03-18 21:37:39 +00:00
|
|
|
// Use a large bitmap.
|
|
|
|
const int W = 1000, H = 1000;
|
2012-11-29 21:05:37 +00:00
|
|
|
bm->setConfig(SkBitmap::kARGB_8888_Config, W, H);
|
|
|
|
bm->allocPixels();
|
|
|
|
bm->eraseColor(SK_ColorBLACK);
|
|
|
|
SkCanvas canvas(*bm);
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setColor(SK_ColorBLUE);
|
|
|
|
canvas.drawRectCoords(0, 0, SkIntToScalar(W/2), SkIntToScalar(H/2), paint);
|
|
|
|
return bm;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SkData* create_data_from_bitmap(const SkBitmap& bm) {
|
|
|
|
SkDynamicMemoryWStream stream;
|
|
|
|
if (SkImageEncoder::EncodeStream(&stream, bm, SkImageEncoder::kPNG_Type, 100)) {
|
|
|
|
return stream.copyToData();
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void assert_bounds_equal(skiatest::Reporter* reporter, const SkBitmap& bm1,
|
|
|
|
const SkBitmap& bm2) {
|
|
|
|
REPORTER_ASSERT(reporter, bm1.width() == bm2.width());
|
|
|
|
REPORTER_ASSERT(reporter, bm1.height() == bm2.height());
|
|
|
|
}
|
|
|
|
|
2013-03-18 21:37:39 +00:00
|
|
|
static void test_cache(skiatest::Reporter* reporter, SkImageCache* cache) {
|
|
|
|
// Test the cache directly:
|
|
|
|
cache->purgeAllUnpinnedCaches();
|
|
|
|
intptr_t ID = SkImageCache::UNINITIALIZED_ID;
|
|
|
|
const size_t size = 1000;
|
|
|
|
char buffer[size];
|
|
|
|
sk_bzero((void*) buffer, size);
|
|
|
|
void* memory = cache->allocAndPinCache(size, &ID);
|
|
|
|
if (memory != NULL) {
|
|
|
|
memcpy(memory, (void*)buffer, size);
|
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) == SkImageCache::kPinned_MemoryStatus);
|
|
|
|
cache->releaseCache(ID);
|
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) != SkImageCache::kPinned_MemoryStatus);
|
|
|
|
SkImageCache::DataStatus dataStatus;
|
|
|
|
memory = cache->pinCache(ID, &dataStatus);
|
|
|
|
if (memory != NULL) {
|
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
|
|
|
|
== SkImageCache::kPinned_MemoryStatus);
|
|
|
|
if (SkImageCache::kRetained_DataStatus == dataStatus) {
|
|
|
|
REPORTER_ASSERT(reporter, !memcmp(memory, (void*) buffer, size));
|
|
|
|
}
|
|
|
|
cache->releaseCache(ID);
|
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
|
|
|
|
!= SkImageCache::kPinned_MemoryStatus);
|
|
|
|
cache->purgeAllUnpinnedCaches();
|
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
|
|
|
|
!= SkImageCache::kPinned_MemoryStatus);
|
|
|
|
memory = cache->pinCache(ID, &dataStatus);
|
|
|
|
if (memory != NULL) {
|
2013-03-21 20:54:42 +00:00
|
|
|
// The memory block may or may not have survived the purging (at the
|
|
|
|
// memory manager's whim) so we cannot check dataStatus here.
|
2013-03-18 21:37:39 +00:00
|
|
|
cache->releaseCache(ID);
|
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
|
|
|
|
!= SkImageCache::kPinned_MemoryStatus);
|
|
|
|
cache->throwAwayCache(ID);
|
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
|
|
|
|
== SkImageCache::kFreed_MemoryStatus);
|
|
|
|
} else {
|
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
|
|
|
|
== SkImageCache::kFreed_MemoryStatus);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_factory(skiatest::Reporter* reporter, SkImageCache* cache, SkData* encodedData,
|
2013-02-22 21:38:35 +00:00
|
|
|
const SkBitmap& origBitmap) {
|
|
|
|
SkBitmapFactory factory(&SkImageDecoder::DecodeMemoryToTarget);
|
|
|
|
factory.setImageCache(cache);
|
|
|
|
SkAutoTDelete<SkBitmap> bitmapFromFactory(SkNEW(SkBitmap));
|
|
|
|
bool success = factory.installPixelRef(encodedData, bitmapFromFactory.get());
|
|
|
|
// This assumes that if the encoder worked, the decoder should also work, so the above call
|
|
|
|
// should not fail.
|
|
|
|
REPORTER_ASSERT(reporter, success);
|
|
|
|
assert_bounds_equal(reporter, origBitmap, *bitmapFromFactory.get());
|
|
|
|
|
|
|
|
SkPixelRef* pixelRef = bitmapFromFactory->pixelRef();
|
|
|
|
REPORTER_ASSERT(reporter, pixelRef != NULL);
|
|
|
|
if (NULL == cache) {
|
|
|
|
// This assumes that installPixelRef called lockPixels.
|
|
|
|
REPORTER_ASSERT(reporter, bitmapFromFactory->readyToDraw());
|
|
|
|
} else {
|
|
|
|
// Lazy decoding
|
|
|
|
REPORTER_ASSERT(reporter, !bitmapFromFactory->readyToDraw());
|
|
|
|
SkLazyPixelRef* lazyRef = static_cast<SkLazyPixelRef*>(pixelRef);
|
2013-03-18 21:37:39 +00:00
|
|
|
intptr_t cacheID = lazyRef->getCacheId();
|
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID)
|
|
|
|
!= SkImageCache::kPinned_MemoryStatus);
|
2013-02-22 21:38:35 +00:00
|
|
|
{
|
|
|
|
SkAutoLockPixels alp(*bitmapFromFactory.get());
|
|
|
|
REPORTER_ASSERT(reporter, bitmapFromFactory->readyToDraw());
|
|
|
|
cacheID = lazyRef->getCacheId();
|
2013-03-18 21:37:39 +00:00
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID)
|
|
|
|
== SkImageCache::kPinned_MemoryStatus);
|
2013-02-22 21:38:35 +00:00
|
|
|
}
|
|
|
|
REPORTER_ASSERT(reporter, !bitmapFromFactory->readyToDraw());
|
2013-03-18 21:37:39 +00:00
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID)
|
|
|
|
!= SkImageCache::kPinned_MemoryStatus);
|
2013-02-22 21:38:35 +00:00
|
|
|
bitmapFromFactory.free();
|
2013-03-18 21:37:39 +00:00
|
|
|
REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID)
|
|
|
|
== SkImageCache::kFreed_MemoryStatus);
|
2013-02-22 21:38:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-18 21:37:39 +00:00
|
|
|
class ImageCacheHolder : public SkNoncopyable {
|
|
|
|
|
|
|
|
public:
|
|
|
|
~ImageCacheHolder() {
|
|
|
|
fCaches.safeUnrefAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
void addImageCache(SkImageCache* cache) {
|
|
|
|
SkSafeRef(cache);
|
|
|
|
*fCaches.append() = cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
int count() const { return fCaches.count(); }
|
|
|
|
|
|
|
|
SkImageCache* getAt(int i) {
|
|
|
|
if (i < 0 || i > fCaches.count()) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return fCaches.getAt(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
SkTDArray<SkImageCache*> fCaches;
|
|
|
|
};
|
|
|
|
|
2012-11-29 21:05:37 +00:00
|
|
|
static void TestBitmapFactory(skiatest::Reporter* reporter) {
|
|
|
|
SkAutoTDelete<SkBitmap> bitmap(create_bitmap());
|
|
|
|
SkASSERT(bitmap.get() != NULL);
|
|
|
|
|
|
|
|
SkAutoDataUnref encodedBitmap(create_data_from_bitmap(*bitmap.get()));
|
2013-03-18 21:37:39 +00:00
|
|
|
bool encodeSucceeded = encodedBitmap.get() != NULL;
|
|
|
|
SkASSERT(encodeSucceeded);
|
|
|
|
|
|
|
|
ImageCacheHolder cacheHolder;
|
2012-11-29 21:05:37 +00:00
|
|
|
|
2013-02-22 21:38:35 +00:00
|
|
|
SkAutoTUnref<SkLruImageCache> lruCache(SkNEW_ARGS(SkLruImageCache, (1024 * 1024)));
|
2013-03-18 21:37:39 +00:00
|
|
|
cacheHolder.addImageCache(lruCache);
|
|
|
|
|
|
|
|
cacheHolder.addImageCache(NULL);
|
|
|
|
|
|
|
|
SkImageCache* purgeableCache = SkPurgeableImageCache::Create();
|
|
|
|
if (purgeableCache != NULL) {
|
|
|
|
cacheHolder.addImageCache(purgeableCache);
|
|
|
|
purgeableCache->unref();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < cacheHolder.count(); i++) {
|
|
|
|
SkImageCache* cache = cacheHolder.getAt(i);
|
|
|
|
if (cache != NULL) {
|
|
|
|
test_cache(reporter, cache);
|
|
|
|
}
|
|
|
|
if (encodeSucceeded) {
|
|
|
|
test_factory(reporter, cache, encodedBitmap, *bitmap.get());
|
|
|
|
}
|
|
|
|
}
|
2012-11-29 21:05:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#include "TestClassDef.h"
|
|
|
|
DEFINE_TESTCLASS("BitmapFactory", TestBitmapFactoryClass, TestBitmapFactory)
|
2013-02-22 21:38:35 +00:00
|
|
|
|
|
|
|
#endif // SK_DEBUG
|