blob: 216903a6ac901bc52101c6db42a7552d9e421eab [file] [log] [blame]
scroggo@google.com9f686f32012-11-29 21:05:37 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
scroggo@google.comf8d7d272013-02-22 21:38:35 +00008#ifdef SK_DEBUG
9
scroggo@google.com9f686f32012-11-29 21:05:37 +000010#include "SkBitmap.h"
11#include "SkBitmapFactory.h"
12#include "SkCanvas.h"
13#include "SkColor.h"
14#include "SkData.h"
scroggo@google.comf8d7d272013-02-22 21:38:35 +000015#include "SkImageDecoder.h"
scroggo@google.com9f686f32012-11-29 21:05:37 +000016#include "SkImageEncoder.h"
scroggo@google.comf8d7d272013-02-22 21:38:35 +000017#include "SkLazyPixelRef.h"
18#include "SkLruImageCache.h"
scroggo@google.com9f686f32012-11-29 21:05:37 +000019#include "SkPaint.h"
scroggo@google.combb281f72013-03-18 21:37:39 +000020#include "SkPurgeableImageCache.h"
scroggo@google.com9f686f32012-11-29 21:05:37 +000021#include "SkStream.h"
22#include "SkTemplates.h"
23#include "Test.h"
24
25static SkBitmap* create_bitmap() {
26 SkBitmap* bm = SkNEW(SkBitmap);
scroggo@google.combb281f72013-03-18 21:37:39 +000027 // Use a large bitmap.
28 const int W = 1000, H = 1000;
scroggo@google.com9f686f32012-11-29 21:05:37 +000029 bm->setConfig(SkBitmap::kARGB_8888_Config, W, H);
30 bm->allocPixels();
31 bm->eraseColor(SK_ColorBLACK);
32 SkCanvas canvas(*bm);
33 SkPaint paint;
34 paint.setColor(SK_ColorBLUE);
35 canvas.drawRectCoords(0, 0, SkIntToScalar(W/2), SkIntToScalar(H/2), paint);
36 return bm;
37}
38
39static SkData* create_data_from_bitmap(const SkBitmap& bm) {
40 SkDynamicMemoryWStream stream;
41 if (SkImageEncoder::EncodeStream(&stream, bm, SkImageEncoder::kPNG_Type, 100)) {
42 return stream.copyToData();
43 }
44 return NULL;
45}
46
47static void assert_bounds_equal(skiatest::Reporter* reporter, const SkBitmap& bm1,
48 const SkBitmap& bm2) {
49 REPORTER_ASSERT(reporter, bm1.width() == bm2.width());
50 REPORTER_ASSERT(reporter, bm1.height() == bm2.height());
51}
52
scroggo@google.combb281f72013-03-18 21:37:39 +000053static void test_cache(skiatest::Reporter* reporter, SkImageCache* cache) {
54 // Test the cache directly:
55 cache->purgeAllUnpinnedCaches();
56 intptr_t ID = SkImageCache::UNINITIALIZED_ID;
57 const size_t size = 1000;
58 char buffer[size];
59 sk_bzero((void*) buffer, size);
60 void* memory = cache->allocAndPinCache(size, &ID);
61 if (memory != NULL) {
62 memcpy(memory, (void*)buffer, size);
63 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) == SkImageCache::kPinned_MemoryStatus);
64 cache->releaseCache(ID);
65 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID) != SkImageCache::kPinned_MemoryStatus);
66 SkImageCache::DataStatus dataStatus;
67 memory = cache->pinCache(ID, &dataStatus);
68 if (memory != NULL) {
69 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
70 == SkImageCache::kPinned_MemoryStatus);
71 if (SkImageCache::kRetained_DataStatus == dataStatus) {
72 REPORTER_ASSERT(reporter, !memcmp(memory, (void*) buffer, size));
73 }
74 cache->releaseCache(ID);
75 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
76 != SkImageCache::kPinned_MemoryStatus);
77 cache->purgeAllUnpinnedCaches();
78 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
79 != SkImageCache::kPinned_MemoryStatus);
80 memory = cache->pinCache(ID, &dataStatus);
81 if (memory != NULL) {
82 // Since the cache was thrown away, and ID was not pinned, it should have
83 // been purged.
84 REPORTER_ASSERT(reporter, SkImageCache::kUninitialized_DataStatus == dataStatus);
85 cache->releaseCache(ID);
86 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
87 != SkImageCache::kPinned_MemoryStatus);
88 cache->throwAwayCache(ID);
89 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
90 == SkImageCache::kFreed_MemoryStatus);
91 } else {
92 REPORTER_ASSERT(reporter, cache->getMemoryStatus(ID)
93 == SkImageCache::kFreed_MemoryStatus);
94 }
95 }
96 }
97}
98
99static void test_factory(skiatest::Reporter* reporter, SkImageCache* cache, SkData* encodedData,
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000100 const SkBitmap& origBitmap) {
101 SkBitmapFactory factory(&SkImageDecoder::DecodeMemoryToTarget);
102 factory.setImageCache(cache);
103 SkAutoTDelete<SkBitmap> bitmapFromFactory(SkNEW(SkBitmap));
104 bool success = factory.installPixelRef(encodedData, bitmapFromFactory.get());
105 // This assumes that if the encoder worked, the decoder should also work, so the above call
106 // should not fail.
107 REPORTER_ASSERT(reporter, success);
108 assert_bounds_equal(reporter, origBitmap, *bitmapFromFactory.get());
109
110 SkPixelRef* pixelRef = bitmapFromFactory->pixelRef();
111 REPORTER_ASSERT(reporter, pixelRef != NULL);
112 if (NULL == cache) {
113 // This assumes that installPixelRef called lockPixels.
114 REPORTER_ASSERT(reporter, bitmapFromFactory->readyToDraw());
115 } else {
116 // Lazy decoding
117 REPORTER_ASSERT(reporter, !bitmapFromFactory->readyToDraw());
118 SkLazyPixelRef* lazyRef = static_cast<SkLazyPixelRef*>(pixelRef);
scroggo@google.combb281f72013-03-18 21:37:39 +0000119 intptr_t cacheID = lazyRef->getCacheId();
120 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID)
121 != SkImageCache::kPinned_MemoryStatus);
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000122 {
123 SkAutoLockPixels alp(*bitmapFromFactory.get());
124 REPORTER_ASSERT(reporter, bitmapFromFactory->readyToDraw());
125 cacheID = lazyRef->getCacheId();
scroggo@google.combb281f72013-03-18 21:37:39 +0000126 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID)
127 == SkImageCache::kPinned_MemoryStatus);
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000128 }
129 REPORTER_ASSERT(reporter, !bitmapFromFactory->readyToDraw());
scroggo@google.combb281f72013-03-18 21:37:39 +0000130 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID)
131 != SkImageCache::kPinned_MemoryStatus);
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000132 bitmapFromFactory.free();
scroggo@google.combb281f72013-03-18 21:37:39 +0000133 REPORTER_ASSERT(reporter, cache->getMemoryStatus(cacheID)
134 == SkImageCache::kFreed_MemoryStatus);
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000135 }
136}
137
scroggo@google.combb281f72013-03-18 21:37:39 +0000138class ImageCacheHolder : public SkNoncopyable {
139
140public:
141 ~ImageCacheHolder() {
142 fCaches.safeUnrefAll();
143 }
144
145 void addImageCache(SkImageCache* cache) {
146 SkSafeRef(cache);
147 *fCaches.append() = cache;
148 }
149
150 int count() const { return fCaches.count(); }
151
152 SkImageCache* getAt(int i) {
153 if (i < 0 || i > fCaches.count()) {
154 return NULL;
155 }
156 return fCaches.getAt(i);
157 }
158
159private:
160 SkTDArray<SkImageCache*> fCaches;
161};
162
scroggo@google.com9f686f32012-11-29 21:05:37 +0000163static void TestBitmapFactory(skiatest::Reporter* reporter) {
164 SkAutoTDelete<SkBitmap> bitmap(create_bitmap());
165 SkASSERT(bitmap.get() != NULL);
166
167 SkAutoDataUnref encodedBitmap(create_data_from_bitmap(*bitmap.get()));
scroggo@google.combb281f72013-03-18 21:37:39 +0000168 bool encodeSucceeded = encodedBitmap.get() != NULL;
169 SkASSERT(encodeSucceeded);
170
171 ImageCacheHolder cacheHolder;
scroggo@google.com9f686f32012-11-29 21:05:37 +0000172
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000173 SkAutoTUnref<SkLruImageCache> lruCache(SkNEW_ARGS(SkLruImageCache, (1024 * 1024)));
scroggo@google.combb281f72013-03-18 21:37:39 +0000174 cacheHolder.addImageCache(lruCache);
175
176 cacheHolder.addImageCache(NULL);
177
178 SkImageCache* purgeableCache = SkPurgeableImageCache::Create();
179 if (purgeableCache != NULL) {
180 cacheHolder.addImageCache(purgeableCache);
181 purgeableCache->unref();
182 }
183
184 for (int i = 0; i < cacheHolder.count(); i++) {
185 SkImageCache* cache = cacheHolder.getAt(i);
186 if (cache != NULL) {
187 test_cache(reporter, cache);
188 }
189 if (encodeSucceeded) {
190 test_factory(reporter, cache, encodedBitmap, *bitmap.get());
191 }
192 }
scroggo@google.com9f686f32012-11-29 21:05:37 +0000193}
194
195#include "TestClassDef.h"
196DEFINE_TESTCLASS("BitmapFactory", TestBitmapFactoryClass, TestBitmapFactory)
scroggo@google.comf8d7d272013-02-22 21:38:35 +0000197
198#endif // SK_DEBUG