Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/core/SkBitmap.cpp

Issue 271693002: remove dead mipmap code from SkBitmap (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « include/core/SkBitmap.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2008 The Android Open Source Project 3 * Copyright 2008 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
(...skipping 11 matching lines...) Expand all
22 #include "SkUtils.h" 22 #include "SkUtils.h"
23 #include "SkValidationUtils.h" 23 #include "SkValidationUtils.h"
24 #include "SkPackBits.h" 24 #include "SkPackBits.h"
25 #include <new> 25 #include <new>
26 26
27 static bool reset_return_false(SkBitmap* bm) { 27 static bool reset_return_false(SkBitmap* bm) {
28 bm->reset(); 28 bm->reset();
29 return false; 29 return false;
30 } 30 }
31 31
32 struct MipLevel {
33 void* fPixels;
34 uint32_t fRowBytes;
35 uint32_t fWidth, fHeight;
36 };
37
38 struct SkBitmap::MipMap : SkNoncopyable {
39 int32_t fRefCnt;
40 int fLevelCount;
41 // MipLevel fLevel[fLevelCount];
42 // Pixels[]
43
44 static MipMap* Alloc(int levelCount, size_t pixelSize) {
45 if (levelCount < 0) {
46 return NULL;
47 }
48 int64_t size = (levelCount + 1) * sizeof(MipLevel);
49 size += sizeof(MipMap) + pixelSize;
50 if (!sk_64_isS32(size)) {
51 return NULL;
52 }
53 MipMap* mm = (MipMap*)sk_malloc_throw(sk_64_asS32(size));
54 mm->fRefCnt = 1;
55 mm->fLevelCount = levelCount;
56 return mm;
57 }
58
59 const MipLevel* levels() const { return (const MipLevel*)(this + 1); }
60 MipLevel* levels() { return (MipLevel*)(this + 1); }
61
62 const void* pixels() const { return levels() + fLevelCount; }
63 void* pixels() { return levels() + fLevelCount; }
64
65 void ref() {
66 if (SK_MaxS32 == sk_atomic_inc(&fRefCnt)) {
67 sk_throw();
68 }
69 }
70 void unref() {
71 SkASSERT(fRefCnt > 0);
72 if (sk_atomic_dec(&fRefCnt) == 1) {
73 sk_free(this);
74 }
75 }
76 };
77
78 ///////////////////////////////////////////////////////////////////////////////
79 ///////////////////////////////////////////////////////////////////////////////
80
81 SkBitmap::SkBitmap() { 32 SkBitmap::SkBitmap() {
82 sk_bzero(this, sizeof(*this)); 33 sk_bzero(this, sizeof(*this));
83 } 34 }
84 35
85 SkBitmap::SkBitmap(const SkBitmap& src) { 36 SkBitmap::SkBitmap(const SkBitmap& src) {
86 SkDEBUGCODE(src.validate();) 37 SkDEBUGCODE(src.validate();)
87 sk_bzero(this, sizeof(*this)); 38 sk_bzero(this, sizeof(*this));
88 *this = src; 39 *this = src;
89 SkDEBUGCODE(this->validate();) 40 SkDEBUGCODE(this->validate();)
90 } 41 }
91 42
92 SkBitmap::~SkBitmap() { 43 SkBitmap::~SkBitmap() {
93 SkDEBUGCODE(this->validate();) 44 SkDEBUGCODE(this->validate();)
94 this->freePixels(); 45 this->freePixels();
95 } 46 }
96 47
97 SkBitmap& SkBitmap::operator=(const SkBitmap& src) { 48 SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
98 if (this != &src) { 49 if (this != &src) {
99 this->freePixels(); 50 this->freePixels();
100 memcpy(this, &src, sizeof(src)); 51 memcpy(this, &src, sizeof(src));
101 52
102 // inc src reference counts 53 // inc src reference counts
103 SkSafeRef(src.fPixelRef); 54 SkSafeRef(src.fPixelRef);
104 SkSafeRef(src.fMipMap);
105 55
106 // we reset our locks if we get blown away 56 // we reset our locks if we get blown away
107 fPixelLockCount = 0; 57 fPixelLockCount = 0;
108 58
109 if (fPixelRef) { 59 if (fPixelRef) {
110 // ignore the values from the memcpy 60 // ignore the values from the memcpy
111 fPixels = NULL; 61 fPixels = NULL;
112 fColorTable = NULL; 62 fColorTable = NULL;
113 // Note that what to for genID is somewhat arbitrary. We have no 63 // Note that what to for genID is somewhat arbitrary. We have no
114 // way to track changes to raw pixels across multiple SkBitmaps. 64 // way to track changes to raw pixels across multiple SkBitmaps.
115 // Would benefit from an SkRawPixelRef type created by 65 // Would benefit from an SkRawPixelRef type created by
116 // setPixels. 66 // setPixels.
117 // Just leave the memcpy'ed one but they'll get out of sync 67 // Just leave the memcpy'ed one but they'll get out of sync
118 // as soon either is modified. 68 // as soon either is modified.
119 } 69 }
120 } 70 }
121 71
122 SkDEBUGCODE(this->validate();) 72 SkDEBUGCODE(this->validate();)
123 return *this; 73 return *this;
124 } 74 }
125 75
126 void SkBitmap::swap(SkBitmap& other) { 76 void SkBitmap::swap(SkBitmap& other) {
127 SkTSwap(fColorTable, other.fColorTable); 77 SkTSwap(fColorTable, other.fColorTable);
128 SkTSwap(fPixelRef, other.fPixelRef); 78 SkTSwap(fPixelRef, other.fPixelRef);
129 SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin); 79 SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin);
130 SkTSwap(fPixelLockCount, other.fPixelLockCount); 80 SkTSwap(fPixelLockCount, other.fPixelLockCount);
131 SkTSwap(fMipMap, other.fMipMap);
132 SkTSwap(fPixels, other.fPixels); 81 SkTSwap(fPixels, other.fPixels);
133 SkTSwap(fInfo, other.fInfo); 82 SkTSwap(fInfo, other.fInfo);
134 SkTSwap(fRowBytes, other.fRowBytes); 83 SkTSwap(fRowBytes, other.fRowBytes);
135 SkTSwap(fFlags, other.fFlags); 84 SkTSwap(fFlags, other.fFlags);
136 85
137 SkDEBUGCODE(this->validate();) 86 SkDEBUGCODE(this->validate();)
138 } 87 }
139 88
140 void SkBitmap::reset() { 89 void SkBitmap::reset() {
141 this->freePixels(); 90 this->freePixels();
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 return false; 484 return false;
536 } 485 }
537 486
538 SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 487 SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
539 return this->allocPixels(SkImageInfo::Make(width, height, ct, at)); 488 return this->allocPixels(SkImageInfo::Make(width, height, ct, at));
540 } 489 }
541 490
542 /////////////////////////////////////////////////////////////////////////////// 491 ///////////////////////////////////////////////////////////////////////////////
543 492
544 void SkBitmap::freePixels() { 493 void SkBitmap::freePixels() {
545 // if we're gonna free the pixels, we certainly need to free the mipmap
546 this->freeMipMap();
547
548 if (NULL != fPixelRef) { 494 if (NULL != fPixelRef) {
549 if (fPixelLockCount > 0) { 495 if (fPixelLockCount > 0) {
550 fPixelRef->unlockPixels(); 496 fPixelRef->unlockPixels();
551 } 497 }
552 fPixelRef->unref(); 498 fPixelRef->unref();
553 fPixelRef = NULL; 499 fPixelRef = NULL;
554 fPixelRefOrigin.setZero(); 500 fPixelRefOrigin.setZero();
555 } 501 }
556 fPixelLockCount = 0; 502 fPixelLockCount = 0;
557 fPixels = NULL; 503 fPixels = NULL;
558 fColorTable = NULL; 504 fColorTable = NULL;
559 } 505 }
560 506
561 void SkBitmap::freeMipMap() {
562 if (fMipMap) {
563 fMipMap->unref();
564 fMipMap = NULL;
565 }
566 }
567
568 uint32_t SkBitmap::getGenerationID() const { 507 uint32_t SkBitmap::getGenerationID() const {
569 return (fPixelRef) ? fPixelRef->getGenerationID() : 0; 508 return (fPixelRef) ? fPixelRef->getGenerationID() : 0;
570 } 509 }
571 510
572 void SkBitmap::notifyPixelsChanged() const { 511 void SkBitmap::notifyPixelsChanged() const {
573 SkASSERT(!this->isImmutable()); 512 SkASSERT(!this->isImmutable());
574 if (fPixelRef) { 513 if (fPixelRef) {
575 fPixelRef->notifyPixelsChanged(); 514 fPixelRef->notifyPixelsChanged();
576 } 515 }
577 } 516 }
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 } 1121 }
1183 1122
1184 if (this->getTexture()) { 1123 if (this->getTexture()) {
1185 return false; 1124 return false;
1186 } else { 1125 } else {
1187 return this->copyTo(dst, dstCT, NULL); 1126 return this->copyTo(dst, dstCT, NULL);
1188 } 1127 }
1189 } 1128 }
1190 1129
1191 /////////////////////////////////////////////////////////////////////////////// 1130 ///////////////////////////////////////////////////////////////////////////////
1192 ///////////////////////////////////////////////////////////////////////////////
1193
1194 static void downsampleby2_proc32(SkBitmap* dst, int x, int y,
1195 const SkBitmap& src) {
1196 x <<= 1;
1197 y <<= 1;
1198 const SkPMColor* p = src.getAddr32(x, y);
1199 const SkPMColor* baseP = p;
1200 SkPMColor c, ag, rb;
1201
1202 c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF;
1203 if (x < src.width() - 1) {
1204 p += 1;
1205 }
1206 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
1207
1208 p = baseP;
1209 if (y < src.height() - 1) {
1210 p += src.rowBytes() >> 2;
1211 }
1212 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
1213 if (x < src.width() - 1) {
1214 p += 1;
1215 }
1216 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
1217
1218 *dst->getAddr32(x >> 1, y >> 1) =
1219 ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
1220 }
1221
1222 static inline uint32_t expand16(U16CPU c) {
1223 return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16);
1224 }
1225
1226 // returns dirt in the top 16bits, but we don't care, since we only
1227 // store the low 16bits.
1228 static inline U16CPU pack16(uint32_t c) {
1229 return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE);
1230 }
1231
1232 static void downsampleby2_proc16(SkBitmap* dst, int x, int y,
1233 const SkBitmap& src) {
1234 x <<= 1;
1235 y <<= 1;
1236 const uint16_t* p = src.getAddr16(x, y);
1237 const uint16_t* baseP = p;
1238 SkPMColor c;
1239
1240 c = expand16(*p);
1241 if (x < src.width() - 1) {
1242 p += 1;
1243 }
1244 c += expand16(*p);
1245
1246 p = baseP;
1247 if (y < src.height() - 1) {
1248 p += src.rowBytes() >> 1;
1249 }
1250 c += expand16(*p);
1251 if (x < src.width() - 1) {
1252 p += 1;
1253 }
1254 c += expand16(*p);
1255
1256 *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2);
1257 }
1258
1259 static uint32_t expand4444(U16CPU c) {
1260 return (c & 0xF0F) | ((c & ~0xF0F) << 12);
1261 }
1262
1263 static U16CPU collaps4444(uint32_t c) {
1264 return (c & 0xF0F) | ((c >> 12) & ~0xF0F);
1265 }
1266
1267 static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
1268 const SkBitmap& src) {
1269 x <<= 1;
1270 y <<= 1;
1271 const uint16_t* p = src.getAddr16(x, y);
1272 const uint16_t* baseP = p;
1273 uint32_t c;
1274
1275 c = expand4444(*p);
1276 if (x < src.width() - 1) {
1277 p += 1;
1278 }
1279 c += expand4444(*p);
1280
1281 p = baseP;
1282 if (y < src.height() - 1) {
1283 p += src.rowBytes() >> 1;
1284 }
1285 c += expand4444(*p);
1286 if (x < src.width() - 1) {
1287 p += 1;
1288 }
1289 c += expand4444(*p);
1290
1291 *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
1292 }
1293
1294 void SkBitmap::buildMipMap(bool forceRebuild) {
1295 if (forceRebuild)
1296 this->freeMipMap();
1297 else if (fMipMap)
1298 return; // we're already built
1299
1300 SkASSERT(NULL == fMipMap);
1301
1302 void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
1303
1304 const SkBitmap::Config config = this->config();
1305
1306 switch (config) {
1307 case kARGB_8888_Config:
1308 proc = downsampleby2_proc32;
1309 break;
1310 case kRGB_565_Config:
1311 proc = downsampleby2_proc16;
1312 break;
1313 case kARGB_4444_Config:
1314 proc = downsampleby2_proc4444;
1315 break;
1316 case kIndex8_Config:
1317 case kA8_Config:
1318 default:
1319 return; // don't build mipmaps for these configs
1320 }
1321
1322 SkAutoLockPixels alp(*this);
1323 if (!this->readyToDraw()) {
1324 return;
1325 }
1326
1327 // whip through our loop to compute the exact size needed
1328 size_t size = 0;
1329 int maxLevels = 0;
1330 {
1331 int width = this->width();
1332 int height = this->height();
1333 for (;;) {
1334 width >>= 1;
1335 height >>= 1;
1336 if (0 == width || 0 == height) {
1337 break;
1338 }
1339 size += ComputeRowBytes(config, width) * height;
1340 maxLevels += 1;
1341 }
1342 }
1343
1344 // nothing to build
1345 if (0 == maxLevels) {
1346 return;
1347 }
1348
1349 SkBitmap srcBM(*this);
1350 srcBM.lockPixels();
1351 if (!srcBM.readyToDraw()) {
1352 return;
1353 }
1354
1355 MipMap* mm = MipMap::Alloc(maxLevels, size);
1356 if (NULL == mm) {
1357 return;
1358 }
1359
1360 MipLevel* level = mm->levels();
1361 uint8_t* addr = (uint8_t*)mm->pixels();
1362 int width = this->width();
1363 int height = this->height();
1364 uint32_t rowBytes;
1365 SkBitmap dstBM;
1366
1367 for (int i = 0; i < maxLevels; i++) {
1368 width >>= 1;
1369 height >>= 1;
1370 rowBytes = SkToU32(ComputeRowBytes(config, width));
1371
1372 level[i].fPixels = addr;
1373 level[i].fWidth = width;
1374 level[i].fHeight = height;
1375 level[i].fRowBytes = rowBytes;
1376
1377 dstBM.setConfig(config, width, height, rowBytes);
1378 dstBM.setPixels(addr);
1379
1380 srcBM.lockPixels();
1381 for (int y = 0; y < height; y++) {
1382 for (int x = 0; x < width; x++) {
1383 proc(&dstBM, x, y, srcBM);
1384 }
1385 }
1386 srcBM.unlockPixels();
1387
1388 srcBM = dstBM;
1389 addr += height * rowBytes;
1390 }
1391 SkASSERT(addr == (uint8_t*)mm->pixels() + size);
1392 fMipMap = mm;
1393 }
1394
1395 bool SkBitmap::hasMipMap() const {
1396 return fMipMap != NULL;
1397 }
1398
1399 int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) {
1400 if (NULL == fMipMap) {
1401 return 0;
1402 }
1403
1404 int level = ComputeMipLevel(sx, sy) >> 16;
1405 SkASSERT(level >= 0);
1406 if (level <= 0) {
1407 return 0;
1408 }
1409
1410 if (level >= fMipMap->fLevelCount) {
1411 level = fMipMap->fLevelCount - 1;
1412 }
1413 if (dst) {
1414 const MipLevel& mip = fMipMap->levels()[level - 1];
1415 dst->setConfig((SkBitmap::Config)this->config(),
1416 mip.fWidth, mip.fHeight, mip.fRowBytes);
1417 dst->setPixels(mip.fPixels);
1418 }
1419 return level;
1420 }
1421
1422 SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) {
1423 sx = SkAbs32(sx);
1424 sy = SkAbs32(sy);
1425 if (sx < sy) {
1426 sx = sy;
1427 }
1428 if (sx < SK_Fixed1) {
1429 return 0;
1430 }
1431 int clz = SkCLZ(sx);
1432 SkASSERT(clz >= 1 && clz <= 15);
1433 return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16);
1434 }
1435
1436 ///////////////////////////////////////////////////////////////////////////////
1437 1131
1438 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, 1132 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
1439 int alphaRowBytes) { 1133 int alphaRowBytes) {
1440 SkASSERT(alpha != NULL); 1134 SkASSERT(alpha != NULL);
1441 SkASSERT(alphaRowBytes >= src.width()); 1135 SkASSERT(alphaRowBytes >= src.width());
1442 1136
1443 SkBitmap::Config config = src.config(); 1137 SkBitmap::Config config = src.config();
1444 int w = src.width(); 1138 int w = src.width();
1445 int h = src.height(); 1139 int h = src.height();
1446 size_t rb = src.rowBytes(); 1140 size_t rb = src.rowBytes();
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1729 /////////////////////////////////////////////////////////////////////////////// 1423 ///////////////////////////////////////////////////////////////////////////////
1730 1424
1731 #ifdef SK_DEBUG 1425 #ifdef SK_DEBUG
1732 void SkImageInfo::validate() const { 1426 void SkImageInfo::validate() const {
1733 SkASSERT(fWidth >= 0); 1427 SkASSERT(fWidth >= 0);
1734 SkASSERT(fHeight >= 0); 1428 SkASSERT(fHeight >= 0);
1735 SkASSERT(SkColorTypeIsValid(fColorType)); 1429 SkASSERT(SkColorTypeIsValid(fColorType));
1736 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); 1430 SkASSERT(SkAlphaTypeIsValid(fAlphaType));
1737 } 1431 }
1738 #endif 1432 #endif
OLDNEW
« no previous file with comments | « include/core/SkBitmap.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698