remove dead mipmap code from SkBitmap
BUG=skia: R=fmalita@google.com, fmalita@chromium.org Author: reed@google.com Review URL: https://codereview.chromium.org/271693002 git-svn-id: http://skia.googlecode.com/svn/trunk@14611 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
f5bf3cf025
commit
eaca36b657
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gm.h"
|
||||
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkStream.h"
|
||||
|
||||
class ScaleBitmapGM : public skiagm::GM {
|
||||
|
||||
public:
|
||||
|
||||
ScaleBitmapGM(const char filename[], float scale)
|
||||
: fFilename(filename), fScale(scale)
|
||||
{
|
||||
this->setBGColor(0xFFDDDDDD);
|
||||
fName.printf("scalebitmap_%s_%f", filename, scale);
|
||||
|
||||
SkString path(skiagm::GM::gResourcePath);
|
||||
path.append("/");
|
||||
path.append(fFilename);
|
||||
|
||||
SkImageDecoder *codec = NULL;
|
||||
SkFILEStream stream(path.c_str());
|
||||
if (stream.isValid()) {
|
||||
codec = SkImageDecoder::Factory(&stream);
|
||||
}
|
||||
if (codec) {
|
||||
stream.rewind();
|
||||
codec->decode(&stream, &fBM, SkBitmap::kARGB_8888_Config,
|
||||
SkImageDecoder::kDecodePixels_Mode);
|
||||
SkDELETE(codec);
|
||||
} else {
|
||||
fBM.allocN32Pixels(1, 1);
|
||||
*(fBM.getAddr32(0,0)) = 0xFF0000FF; // red == bad
|
||||
}
|
||||
fSize = fBM.height();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
SkBitmap fBM;
|
||||
SkString fName;
|
||||
SkString fFilename;
|
||||
int fSize;
|
||||
float fScale;
|
||||
|
||||
|
||||
virtual SkString onShortName() SK_OVERRIDE {
|
||||
return fName;
|
||||
}
|
||||
|
||||
virtual SkISize onISize() SK_OVERRIDE {
|
||||
return SkISize::Make(fBM.width() * fScale, fBM.height() * fScale);
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
||||
SkBitmap dst;
|
||||
dst.allocN32Pixels(fBM.width() * fScale, fBM.height() * fScale);
|
||||
fBM.scale(&dst);
|
||||
|
||||
canvas->drawBitmap(dst, 0, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef skiagm::GM INHERITED;
|
||||
};
|
||||
|
||||
class ScaleBitmapMipmapGM: public ScaleBitmapGM {
|
||||
SkMatrix fMatrix;
|
||||
|
||||
public:
|
||||
ScaleBitmapMipmapGM(const char filename[], float scale)
|
||||
: INHERITED(filename, scale)
|
||||
{
|
||||
fName.printf("scalebitmap_mipmap_%s_%f", filename, scale);
|
||||
fBM.buildMipMap();
|
||||
fMatrix.setScale(scale, scale);
|
||||
}
|
||||
protected:
|
||||
virtual void onDraw(SkCanvas *canvas) SK_OVERRIDE {
|
||||
SkPaint paint;
|
||||
|
||||
paint.setFilterBitmap(true);
|
||||
canvas->drawBitmapMatrix(fBM, fMatrix, &paint);
|
||||
}
|
||||
private:
|
||||
typedef ScaleBitmapGM INHERITED;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DEF_GM( return new ScaleBitmapGM("mandrill_128.png", 2); )
|
||||
DEF_GM( return new ScaleBitmapGM("mandrill_64.png", 4); )
|
||||
DEF_GM( return new ScaleBitmapGM("mandrill_32.png", 8); )
|
||||
DEF_GM( return new ScaleBitmapGM("mandrill_16.png", 16); )
|
||||
|
||||
DEF_GM( return new ScaleBitmapGM("nature.jpg", 0.5f); )
|
||||
DEF_GM( return new ScaleBitmapGM("nature.jpg", 0.25f); )
|
||||
DEF_GM( return new ScaleBitmapGM("nature.jpg", 0.125f); )
|
||||
DEF_GM( return new ScaleBitmapGM("nature.jpg", 0.0625f); )
|
||||
|
||||
DEF_GM( return new ScaleBitmapMipmapGM("nature.jpg", 0.5f); )
|
||||
DEF_GM( return new ScaleBitmapMipmapGM("nature.jpg", 0.25f); )
|
||||
DEF_GM( return new ScaleBitmapMipmapGM("nature.jpg", 0.125f); )
|
||||
DEF_GM( return new ScaleBitmapMipmapGM("nature.jpg", 0.0625f); )
|
@ -16,6 +16,7 @@
|
||||
'SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1',
|
||||
'SK_SUPPORT_LEGACY_GETTOPDEVICE',
|
||||
'SK_SUPPORT_LEGACY_N32_NAME',
|
||||
'SK_SUPPORT_LEGACY_BUILDMIPMAP',
|
||||
'SK_SUPPORT_LEGACY_BLURMASKFILTER_STYLE',
|
||||
],
|
||||
},
|
||||
|
@ -647,8 +647,10 @@ public:
|
||||
*/
|
||||
bool deepCopyTo(SkBitmap* dst) const;
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_BUILDMIPMAP
|
||||
SK_ATTR_DEPRECATED("use setFilterLevel on SkPaint")
|
||||
void buildMipMap(bool forceRebuild = false);
|
||||
void buildMipMap(bool forceRebuild = false) {}
|
||||
#endif
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID
|
||||
bool hasHardwareMipMap() const {
|
||||
@ -750,9 +752,6 @@ public:
|
||||
SK_TO_STRING_NONVIRT()
|
||||
|
||||
private:
|
||||
struct MipMap;
|
||||
mutable MipMap* fMipMap;
|
||||
|
||||
mutable SkPixelRef* fPixelRef;
|
||||
mutable int fPixelLockCount;
|
||||
// These are just caches from the locked pixelref
|
||||
@ -798,16 +797,6 @@ private:
|
||||
void freePixels();
|
||||
void updatePixelsFromRef() const;
|
||||
|
||||
static SkFixed ComputeMipLevel(SkFixed sx, SkFixed dy);
|
||||
|
||||
/** Given scale factors sx, sy, determine the miplevel available in the
|
||||
bitmap, and return it (this is the amount to shift matrix iterators
|
||||
by). If dst is not null, it is set to the correct level.
|
||||
*/
|
||||
int extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy);
|
||||
bool hasMipMap() const;
|
||||
void freeMipMap();
|
||||
|
||||
friend struct SkBitmapProcState;
|
||||
};
|
||||
|
||||
|
@ -29,55 +29,6 @@ static bool reset_return_false(SkBitmap* bm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct MipLevel {
|
||||
void* fPixels;
|
||||
uint32_t fRowBytes;
|
||||
uint32_t fWidth, fHeight;
|
||||
};
|
||||
|
||||
struct SkBitmap::MipMap : SkNoncopyable {
|
||||
int32_t fRefCnt;
|
||||
int fLevelCount;
|
||||
// MipLevel fLevel[fLevelCount];
|
||||
// Pixels[]
|
||||
|
||||
static MipMap* Alloc(int levelCount, size_t pixelSize) {
|
||||
if (levelCount < 0) {
|
||||
return NULL;
|
||||
}
|
||||
int64_t size = (levelCount + 1) * sizeof(MipLevel);
|
||||
size += sizeof(MipMap) + pixelSize;
|
||||
if (!sk_64_isS32(size)) {
|
||||
return NULL;
|
||||
}
|
||||
MipMap* mm = (MipMap*)sk_malloc_throw(sk_64_asS32(size));
|
||||
mm->fRefCnt = 1;
|
||||
mm->fLevelCount = levelCount;
|
||||
return mm;
|
||||
}
|
||||
|
||||
const MipLevel* levels() const { return (const MipLevel*)(this + 1); }
|
||||
MipLevel* levels() { return (MipLevel*)(this + 1); }
|
||||
|
||||
const void* pixels() const { return levels() + fLevelCount; }
|
||||
void* pixels() { return levels() + fLevelCount; }
|
||||
|
||||
void ref() {
|
||||
if (SK_MaxS32 == sk_atomic_inc(&fRefCnt)) {
|
||||
sk_throw();
|
||||
}
|
||||
}
|
||||
void unref() {
|
||||
SkASSERT(fRefCnt > 0);
|
||||
if (sk_atomic_dec(&fRefCnt) == 1) {
|
||||
sk_free(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkBitmap::SkBitmap() {
|
||||
sk_bzero(this, sizeof(*this));
|
||||
}
|
||||
@ -101,7 +52,6 @@ SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
|
||||
|
||||
// inc src reference counts
|
||||
SkSafeRef(src.fPixelRef);
|
||||
SkSafeRef(src.fMipMap);
|
||||
|
||||
// we reset our locks if we get blown away
|
||||
fPixelLockCount = 0;
|
||||
@ -128,7 +78,6 @@ void SkBitmap::swap(SkBitmap& other) {
|
||||
SkTSwap(fPixelRef, other.fPixelRef);
|
||||
SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin);
|
||||
SkTSwap(fPixelLockCount, other.fPixelLockCount);
|
||||
SkTSwap(fMipMap, other.fMipMap);
|
||||
SkTSwap(fPixels, other.fPixels);
|
||||
SkTSwap(fInfo, other.fInfo);
|
||||
SkTSwap(fRowBytes, other.fRowBytes);
|
||||
@ -542,9 +491,6 @@ bool SkBitmap::allocConfigPixels(Config config, int width, int height,
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkBitmap::freePixels() {
|
||||
// if we're gonna free the pixels, we certainly need to free the mipmap
|
||||
this->freeMipMap();
|
||||
|
||||
if (NULL != fPixelRef) {
|
||||
if (fPixelLockCount > 0) {
|
||||
fPixelRef->unlockPixels();
|
||||
@ -558,13 +504,6 @@ void SkBitmap::freePixels() {
|
||||
fColorTable = NULL;
|
||||
}
|
||||
|
||||
void SkBitmap::freeMipMap() {
|
||||
if (fMipMap) {
|
||||
fMipMap->unref();
|
||||
fMipMap = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SkBitmap::getGenerationID() const {
|
||||
return (fPixelRef) ? fPixelRef->getGenerationID() : 0;
|
||||
}
|
||||
@ -1188,251 +1127,6 @@ bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void downsampleby2_proc32(SkBitmap* dst, int x, int y,
|
||||
const SkBitmap& src) {
|
||||
x <<= 1;
|
||||
y <<= 1;
|
||||
const SkPMColor* p = src.getAddr32(x, y);
|
||||
const SkPMColor* baseP = p;
|
||||
SkPMColor c, ag, rb;
|
||||
|
||||
c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF;
|
||||
if (x < src.width() - 1) {
|
||||
p += 1;
|
||||
}
|
||||
c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
|
||||
|
||||
p = baseP;
|
||||
if (y < src.height() - 1) {
|
||||
p += src.rowBytes() >> 2;
|
||||
}
|
||||
c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
|
||||
if (x < src.width() - 1) {
|
||||
p += 1;
|
||||
}
|
||||
c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
|
||||
|
||||
*dst->getAddr32(x >> 1, y >> 1) =
|
||||
((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
|
||||
}
|
||||
|
||||
static inline uint32_t expand16(U16CPU c) {
|
||||
return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16);
|
||||
}
|
||||
|
||||
// returns dirt in the top 16bits, but we don't care, since we only
|
||||
// store the low 16bits.
|
||||
static inline U16CPU pack16(uint32_t c) {
|
||||
return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE);
|
||||
}
|
||||
|
||||
static void downsampleby2_proc16(SkBitmap* dst, int x, int y,
|
||||
const SkBitmap& src) {
|
||||
x <<= 1;
|
||||
y <<= 1;
|
||||
const uint16_t* p = src.getAddr16(x, y);
|
||||
const uint16_t* baseP = p;
|
||||
SkPMColor c;
|
||||
|
||||
c = expand16(*p);
|
||||
if (x < src.width() - 1) {
|
||||
p += 1;
|
||||
}
|
||||
c += expand16(*p);
|
||||
|
||||
p = baseP;
|
||||
if (y < src.height() - 1) {
|
||||
p += src.rowBytes() >> 1;
|
||||
}
|
||||
c += expand16(*p);
|
||||
if (x < src.width() - 1) {
|
||||
p += 1;
|
||||
}
|
||||
c += expand16(*p);
|
||||
|
||||
*dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2);
|
||||
}
|
||||
|
||||
static uint32_t expand4444(U16CPU c) {
|
||||
return (c & 0xF0F) | ((c & ~0xF0F) << 12);
|
||||
}
|
||||
|
||||
static U16CPU collaps4444(uint32_t c) {
|
||||
return (c & 0xF0F) | ((c >> 12) & ~0xF0F);
|
||||
}
|
||||
|
||||
static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
|
||||
const SkBitmap& src) {
|
||||
x <<= 1;
|
||||
y <<= 1;
|
||||
const uint16_t* p = src.getAddr16(x, y);
|
||||
const uint16_t* baseP = p;
|
||||
uint32_t c;
|
||||
|
||||
c = expand4444(*p);
|
||||
if (x < src.width() - 1) {
|
||||
p += 1;
|
||||
}
|
||||
c += expand4444(*p);
|
||||
|
||||
p = baseP;
|
||||
if (y < src.height() - 1) {
|
||||
p += src.rowBytes() >> 1;
|
||||
}
|
||||
c += expand4444(*p);
|
||||
if (x < src.width() - 1) {
|
||||
p += 1;
|
||||
}
|
||||
c += expand4444(*p);
|
||||
|
||||
*dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
|
||||
}
|
||||
|
||||
void SkBitmap::buildMipMap(bool forceRebuild) {
|
||||
if (forceRebuild)
|
||||
this->freeMipMap();
|
||||
else if (fMipMap)
|
||||
return; // we're already built
|
||||
|
||||
SkASSERT(NULL == fMipMap);
|
||||
|
||||
void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
|
||||
|
||||
const SkBitmap::Config config = this->config();
|
||||
|
||||
switch (config) {
|
||||
case kARGB_8888_Config:
|
||||
proc = downsampleby2_proc32;
|
||||
break;
|
||||
case kRGB_565_Config:
|
||||
proc = downsampleby2_proc16;
|
||||
break;
|
||||
case kARGB_4444_Config:
|
||||
proc = downsampleby2_proc4444;
|
||||
break;
|
||||
case kIndex8_Config:
|
||||
case kA8_Config:
|
||||
default:
|
||||
return; // don't build mipmaps for these configs
|
||||
}
|
||||
|
||||
SkAutoLockPixels alp(*this);
|
||||
if (!this->readyToDraw()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// whip through our loop to compute the exact size needed
|
||||
size_t size = 0;
|
||||
int maxLevels = 0;
|
||||
{
|
||||
int width = this->width();
|
||||
int height = this->height();
|
||||
for (;;) {
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
if (0 == width || 0 == height) {
|
||||
break;
|
||||
}
|
||||
size += ComputeRowBytes(config, width) * height;
|
||||
maxLevels += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing to build
|
||||
if (0 == maxLevels) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkBitmap srcBM(*this);
|
||||
srcBM.lockPixels();
|
||||
if (!srcBM.readyToDraw()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MipMap* mm = MipMap::Alloc(maxLevels, size);
|
||||
if (NULL == mm) {
|
||||
return;
|
||||
}
|
||||
|
||||
MipLevel* level = mm->levels();
|
||||
uint8_t* addr = (uint8_t*)mm->pixels();
|
||||
int width = this->width();
|
||||
int height = this->height();
|
||||
uint32_t rowBytes;
|
||||
SkBitmap dstBM;
|
||||
|
||||
for (int i = 0; i < maxLevels; i++) {
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
rowBytes = SkToU32(ComputeRowBytes(config, width));
|
||||
|
||||
level[i].fPixels = addr;
|
||||
level[i].fWidth = width;
|
||||
level[i].fHeight = height;
|
||||
level[i].fRowBytes = rowBytes;
|
||||
|
||||
dstBM.setConfig(config, width, height, rowBytes);
|
||||
dstBM.setPixels(addr);
|
||||
|
||||
srcBM.lockPixels();
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
proc(&dstBM, x, y, srcBM);
|
||||
}
|
||||
}
|
||||
srcBM.unlockPixels();
|
||||
|
||||
srcBM = dstBM;
|
||||
addr += height * rowBytes;
|
||||
}
|
||||
SkASSERT(addr == (uint8_t*)mm->pixels() + size);
|
||||
fMipMap = mm;
|
||||
}
|
||||
|
||||
bool SkBitmap::hasMipMap() const {
|
||||
return fMipMap != NULL;
|
||||
}
|
||||
|
||||
int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) {
|
||||
if (NULL == fMipMap) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int level = ComputeMipLevel(sx, sy) >> 16;
|
||||
SkASSERT(level >= 0);
|
||||
if (level <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (level >= fMipMap->fLevelCount) {
|
||||
level = fMipMap->fLevelCount - 1;
|
||||
}
|
||||
if (dst) {
|
||||
const MipLevel& mip = fMipMap->levels()[level - 1];
|
||||
dst->setConfig((SkBitmap::Config)this->config(),
|
||||
mip.fWidth, mip.fHeight, mip.fRowBytes);
|
||||
dst->setPixels(mip.fPixels);
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) {
|
||||
sx = SkAbs32(sx);
|
||||
sy = SkAbs32(sy);
|
||||
if (sx < sy) {
|
||||
sx = sy;
|
||||
}
|
||||
if (sx < SK_Fixed1) {
|
||||
return 0;
|
||||
}
|
||||
int clz = SkCLZ(sx);
|
||||
SkASSERT(clz >= 1 && clz <= 15);
|
||||
return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
|
||||
|
Loading…
Reference in New Issue
Block a user