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

Unified Diff: src/core/SkBitmap.cpp

Issue 1074983003: add SkPixmap and external locking to bitmaps (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase Created 5 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 side-by-side diff with in-line comments
Download patch
Index: src/core/SkBitmap.cpp
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index 6f90b710540ff69832a0c851c45c69a90554ad22..01f79f2707493060666d5129f32cbf1a0915f23a 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -430,43 +430,41 @@ bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
///////////////////////////////////////////////////////////////////////////////
-bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
- size_t dstRowBytes, bool preserveDstPad) const {
+static bool copy_pixels_to(const SkPixmap& src, void* const dst, size_t dstSize,
+ size_t dstRowBytes, bool preserveDstPad) {
+ const SkImageInfo& info = src.info();
if (0 == dstRowBytes) {
- dstRowBytes = fRowBytes;
+ dstRowBytes = src.rowBytes();
}
-
- if (dstRowBytes < fInfo.minRowBytes() ||
- dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) {
+ if (dstRowBytes < info.minRowBytes()) {
return false;
}
- if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) {
- size_t safeSize = this->getSafeSize();
+ if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == src.rowBytes()) {
+ size_t safeSize = src.getSafeSize();
if (safeSize > dstSize || safeSize == 0)
return false;
else {
- SkAutoLockPixels lock(*this);
// This implementation will write bytes beyond the end of each row,
// excluding the last row, if the bitmap's stride is greater than
// strictly required by the current config.
- memcpy(dst, getPixels(), safeSize);
-
+ memcpy(dst, src.addr(), safeSize);
return true;
}
} else {
// If destination has different stride than us, then copy line by line.
- if (fInfo.getSafeSize(dstRowBytes) > dstSize) {
+ if (info.getSafeSize(dstRowBytes) > dstSize) {
return false;
} else {
// Just copy what we need on each line.
- size_t rowBytes = fInfo.minRowBytes();
- SkAutoLockPixels lock(*this);
- const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels());
+ size_t rowBytes = info.minRowBytes();
+ const uint8_t* srcP = reinterpret_cast<const uint8_t*>(src.addr());
uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
- for (int row = 0; row < fInfo.height(); row++, srcP += fRowBytes, dstP += dstRowBytes) {
+ for (int row = 0; row < info.height(); ++row) {
memcpy(dstP, srcP, rowBytes);
+ srcP += src.rowBytes();
+ dstP += dstRowBytes;
}
return true;
@@ -474,6 +472,17 @@ bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
}
}
+bool SkBitmap::copyPixelsTo(void* dst, size_t dstSize, size_t dstRB, bool preserveDstPad) const {
+ if (NULL == dst) {
+ return false;
+ }
+ SkAutoPixmapUnlock result;
+ if (!this->requestLock(&result)) {
+ return false;
+ }
+ return copy_pixels_to(result.pixmap(), dst, dstSize, dstRB, preserveDstPad);
+}
+
///////////////////////////////////////////////////////////////////////////////
bool SkBitmap::isImmutable() const {
@@ -567,20 +576,15 @@ SkColor SkBitmap::getColor(int x, int y) const {
return 0;
}
-bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
- SkAutoLockPixels alp(bm);
- if (!bm.getPixels()) {
- return false;
- }
+static bool compute_is_opaque(const SkPixmap& pmap) {
+ const int height = pmap.height();
+ const int width = pmap.width();
- const int height = bm.height();
- const int width = bm.width();
-
- switch (bm.colorType()) {
+ switch (pmap.colorType()) {
case kAlpha_8_SkColorType: {
unsigned a = 0xFF;
for (int y = 0; y < height; ++y) {
- const uint8_t* row = bm.getAddr8(0, y);
+ const uint8_t* row = pmap.addr8(0, y);
for (int x = 0; x < width; ++x) {
a &= row[x];
}
@@ -591,12 +595,13 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
return true;
} break;
case kIndex_8_SkColorType: {
- if (!bm.getColorTable()) {
+ const SkColorTable* ctable = pmap.ctable();
+ if (NULL == ctable) {
return false;
}
- const SkPMColor* table = bm.getColorTable()->readColors();
+ const SkPMColor* table = ctable->readColors();
SkPMColor c = (SkPMColor)~0;
- for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) {
+ for (int i = ctable->count() - 1; i >= 0; --i) {
c &= table[i];
}
return 0xFF == SkGetPackedA32(c);
@@ -608,7 +613,7 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
case kARGB_4444_SkColorType: {
unsigned c = 0xFFFF;
for (int y = 0; y < height; ++y) {
- const SkPMColor16* row = bm.getAddr16(0, y);
+ const SkPMColor16* row = pmap.addr16(0, y);
for (int x = 0; x < width; ++x) {
c &= row[x];
}
@@ -622,7 +627,7 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
case kRGBA_8888_SkColorType: {
SkPMColor c = (SkPMColor)~0;
for (int y = 0; y < height; ++y) {
- const SkPMColor* row = bm.getAddr32(0, y);
+ const SkPMColor* row = pmap.addr32(0, y);
for (int x = 0; x < width; ++x) {
c &= row[x];
}
@@ -638,6 +643,14 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
return false;
}
+bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
+ SkAutoPixmapUnlock result;
+ if (!bm.requestLock(&result)) {
+ return false;
+ }
+ return compute_is_opaque(result.pixmap());
+}
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
@@ -650,36 +663,13 @@ static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b
return SkToU16(pixel);
}
-void SkBitmap::internalErase(const SkIRect& area,
- U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
-#ifdef SK_DEBUG
- SkDEBUGCODE(this->validate();)
- SkASSERT(!area.isEmpty());
- {
- SkIRect total = { 0, 0, this->width(), this->height() };
- SkASSERT(total.contains(area));
- }
-#endif
-
- switch (fInfo.colorType()) {
- case kUnknown_SkColorType:
- case kIndex_8_SkColorType:
- return; // can't erase. Should we bzero so the memory is not uninitialized?
- default:
- break;
- }
-
- SkAutoLockPixels alp(*this);
- // perform this check after the lock call
- if (!this->readyToDraw()) {
- return;
- }
-
+static bool internal_erase(const SkPixmap& pmap, const SkIRect& area,
+ U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
int height = area.height();
const int width = area.width();
- const int rowBytes = fRowBytes;
+ const int rowBytes = pmap.rowBytes();
- switch (this->colorType()) {
+ switch (pmap.colorType()) {
case kGray_8_SkColorType: {
if (255 != a) {
r = SkMulDiv255Round(r, a);
@@ -687,7 +677,7 @@ void SkBitmap::internalErase(const SkIRect& area,
b = SkMulDiv255Round(b, a);
}
int gray = SkComputeLuminance(r, g, b);
- uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
+ uint8_t* p = pmap.writable_addr8(area.fLeft, area.fTop);
while (--height >= 0) {
memset(p, gray, width);
p += rowBytes;
@@ -695,7 +685,7 @@ void SkBitmap::internalErase(const SkIRect& area,
break;
}
case kAlpha_8_SkColorType: {
- uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
+ uint8_t* p = pmap.writable_addr8(area.fLeft, area.fTop);
while (--height >= 0) {
memset(p, a, width);
p += rowBytes;
@@ -704,7 +694,7 @@ void SkBitmap::internalErase(const SkIRect& area,
}
case kARGB_4444_SkColorType:
case kRGB_565_SkColorType: {
- uint16_t* p = this->getAddr16(area.fLeft, area.fTop);
+ uint16_t* p = pmap.writable_addr16(area.fLeft, area.fTop);
uint16_t v;
// make rgb premultiplied
@@ -714,7 +704,7 @@ void SkBitmap::internalErase(const SkIRect& area,
b = SkAlphaMul(b, a);
}
- if (kARGB_4444_SkColorType == this->colorType()) {
+ if (kARGB_4444_SkColorType == pmap.colorType()) {
v = pack_8888_to_4444(a, r, g, b);
} else {
v = SkPackRGB16(r >> (8 - SK_R16_BITS),
@@ -729,15 +719,15 @@ void SkBitmap::internalErase(const SkIRect& area,
}
case kBGRA_8888_SkColorType:
case kRGBA_8888_SkColorType: {
- uint32_t* p = this->getAddr32(area.fLeft, area.fTop);
+ uint32_t* p = pmap.writable_addr32(area.fLeft, area.fTop);
- if (255 != a && kPremul_SkAlphaType == this->alphaType()) {
+ if (255 != a && kPremul_SkAlphaType == pmap.alphaType()) {
r = SkAlphaMul(r, a);
g = SkAlphaMul(g, a);
b = SkAlphaMul(b, a);
}
- uint32_t v = kRGBA_8888_SkColorType == this->colorType() ?
- SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b);
+ uint32_t v = kRGBA_8888_SkColorType == pmap.colorType() ?
+ SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b);
while (--height >= 0) {
sk_memset32(p, v, width);
@@ -746,10 +736,38 @@ void SkBitmap::internalErase(const SkIRect& area,
break;
}
default:
- return; // no change, so don't call notifyPixelsChanged()
+ return false; // no change, so don't call notifyPixelsChanged()
+ }
+ return true;
+}
+
+void SkBitmap::internalErase(const SkIRect& area, U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
+#ifdef SK_DEBUG
+ SkDEBUGCODE(this->validate();)
+ SkASSERT(!area.isEmpty());
+ {
+ SkIRect total = { 0, 0, this->width(), this->height() };
+ SkASSERT(total.contains(area));
+ }
+#endif
+
+ switch (fInfo.colorType()) {
+ case kUnknown_SkColorType:
+ case kIndex_8_SkColorType:
+ // TODO: can we ASSERT that we never get here?
+ return; // can't erase. Should we bzero so the memory is not uninitialized?
+ default:
+ break;
+ }
+
+ SkAutoPixmapUnlock result;
+ if (!this->requestLock(&result)) {
+ return;
}
- this->notifyPixelsChanged();
+ if (internal_erase(result.pixmap(), area, a, r, g, b)) {
+ this->notifyPixelsChanged();
+ }
}
void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
@@ -898,18 +916,16 @@ bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels,
//////////////
- SkAutoLockPixels alp(*this);
-
- // since we don't stop creating un-pixeled devices yet, check for no pixels here
- if (NULL == this->getPixels()) {
+ SkAutoPixmapUnlock result;
+ if (!this->requestLock(&result)) {
return false;
}
+ const SkPixmap& pmap = result.pixmap();
+ const SkImageInfo srcInfo = pmap.info().makeWH(dstInfo.width(), dstInfo.height());
- const SkImageInfo srcInfo = this->info().makeWH(dstInfo.width(), dstInfo.height());
-
- const void* srcPixels = this->getAddr(srcR.x(), srcR.y());
- return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, this->rowBytes(),
- this->getColorTable());
+ const void* srcPixels = pmap.addr(srcR.x(), srcR.y());
+ return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, pmap.rowBytes(),
+ pmap.ctable());
}
bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc) const {
@@ -1048,35 +1064,28 @@ bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
///////////////////////////////////////////////////////////////////////////////
-static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
- int alphaRowBytes) {
- SkASSERT(alpha != NULL);
- SkASSERT(alphaRowBytes >= src.width());
-
- SkColorType colorType = src.colorType();
- int w = src.width();
- int h = src.height();
- size_t rb = src.rowBytes();
-
- SkAutoLockPixels alp(src);
- if (!src.readyToDraw()) {
- // zero out the alpha buffer and return
- while (--h >= 0) {
- memset(alpha, 0, w);
- alpha += alphaRowBytes;
- }
- return false;
+static void rect_memset(uint8_t* array, U8CPU value, SkISize size, size_t rowBytes) {
+ for (int y = 0; y < size.height(); ++y) {
+ memset(array, value, size.width());
+ array += rowBytes;
}
+}
+
+static void get_bitmap_alpha(const SkPixmap& pmap, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
+ SkColorType colorType = pmap.colorType();
+ int w = pmap.width();
+ int h = pmap.height();
+ size_t rb = pmap.rowBytes();
- if (kAlpha_8_SkColorType == colorType && !src.isOpaque()) {
- const uint8_t* s = src.getAddr8(0, 0);
+ if (kAlpha_8_SkColorType == colorType && !pmap.isOpaque()) {
+ const uint8_t* s = pmap.addr8(0, 0);
while (--h >= 0) {
memcpy(alpha, s, w);
s += rb;
alpha += alphaRowBytes;
}
- } else if (kN32_SkColorType == colorType && !src.isOpaque()) {
- const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
+ } else if (kN32_SkColorType == colorType && !pmap.isOpaque()) {
+ const SkPMColor* SK_RESTRICT s = pmap.addr32(0, 0);
while (--h >= 0) {
for (int x = 0; x < w; x++) {
alpha[x] = SkGetPackedA32(s[x]);
@@ -1084,8 +1093,8 @@ static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
s = (const SkPMColor*)((const char*)s + rb);
alpha += alphaRowBytes;
}
- } else if (kARGB_4444_SkColorType == colorType && !src.isOpaque()) {
- const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
+ } else if (kARGB_4444_SkColorType == colorType && !pmap.isOpaque()) {
+ const SkPMColor16* SK_RESTRICT s = pmap.addr16(0, 0);
while (--h >= 0) {
for (int x = 0; x < w; x++) {
alpha[x] = SkPacked4444ToA32(s[x]);
@@ -1093,11 +1102,11 @@ static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
s = (const SkPMColor16*)((const char*)s + rb);
alpha += alphaRowBytes;
}
- } else if (kIndex_8_SkColorType == colorType && !src.isOpaque()) {
- SkColorTable* ct = src.getColorTable();
+ } else if (kIndex_8_SkColorType == colorType && !pmap.isOpaque()) {
+ const SkColorTable* ct = pmap.ctable();
if (ct) {
const SkPMColor* SK_RESTRICT table = ct->readColors();
- const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0);
+ const uint8_t* SK_RESTRICT s = pmap.addr8(0, 0);
while (--h >= 0) {
for (int x = 0; x < w; x++) {
alpha[x] = SkGetPackedA32(table[s[x]]);
@@ -1107,8 +1116,20 @@ static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
}
}
} else { // src is opaque, so just fill alpha[] with 0xFF
- memset(alpha, 0xFF, h * alphaRowBytes);
+ rect_memset(alpha, 0xFF, pmap.info().dimensions(), alphaRowBytes);
+ }
+}
+
+static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
+ SkASSERT(alpha != NULL);
+ SkASSERT(alphaRowBytes >= src.width());
+
+ SkAutoPixmapUnlock apl;
+ if (!src.requestLock(&apl)) {
+ rect_memset(alpha, 0, src.info().dimensions(), alphaRowBytes);
+ return false;
}
+ get_bitmap_alpha(apl.pixmap(), alpha, alphaRowBytes);
return true;
}
@@ -1183,17 +1204,11 @@ bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
///////////////////////////////////////////////////////////////////////////////
-void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
- const SkImageInfo info = bitmap.info();
- SkAutoLockPixels alp(bitmap);
- if (0 == info.width() || 0 == info.height() || NULL == bitmap.getPixels()) {
- buffer->writeUInt(0); // instead of snugRB, signaling no pixels
- return;
- }
-
+static void write_raw_pixels(SkWriteBuffer* buffer, const SkPixmap& pmap) {
+ const SkImageInfo& info = pmap.info();
const size_t snugRB = info.width() * info.bytesPerPixel();
- const char* src = (const char*)bitmap.getPixels();
- const size_t ramRB = bitmap.rowBytes();
+ const char* src = (const char*)pmap.addr();
+ const size_t ramRB = pmap.rowBytes();
buffer->write32(SkToU32(snugRB));
info.flatten(*buffer);
@@ -1208,7 +1223,7 @@ void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
}
buffer->writeByteArray(storage.get(), size);
- SkColorTable* ct = bitmap.getColorTable();
+ const SkColorTable* ct = pmap.ctable();
if (kIndex_8_SkColorType == info.colorType() && ct) {
buffer->writeBool(true);
ct->writeToBuffer(*buffer);
@@ -1217,6 +1232,22 @@ void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
}
}
+void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
+ const SkImageInfo info = bitmap.info();
+ if (0 == info.width() || 0 == info.height() || NULL == bitmap.pixelRef()) {
+ buffer->writeUInt(0); // instead of snugRB, signaling no pixels
+ return;
+ }
+
+ SkAutoPixmapUnlock result;
+ if (!bitmap.requestLock(&result)) {
+ buffer->writeUInt(0); // instead of snugRB, signaling no pixels
+ return;
+ }
+
+ write_raw_pixels(buffer, result.pixmap());
+}
+
bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) {
const size_t snugRB = buffer->readUInt();
if (0 == snugRB) { // no pixels
@@ -1364,6 +1395,34 @@ void SkBitmap::toString(SkString* str) const {
///////////////////////////////////////////////////////////////////////////////
+bool SkBitmap::requestLock(SkAutoPixmapUnlock* result) const {
+ SkASSERT(result);
+
+ SkPixelRef* pr = fPixelRef;
+ if (NULL == pr) {
+ return false;
+ }
+
+ SkPixelRef::LockRequest req = { fInfo.dimensions(), kNone_SkFilterQuality };
+ SkPixelRef::LockResult res;
+ if (pr->requestLock(req, &res)) {
+ // The bitmap may be a subset of the pixelref's dimensions
+ SkASSERT(fPixelRefOrigin.x() + fInfo.width() <= res.fSize.width());
+ SkASSERT(fPixelRefOrigin.y() + fInfo.height() <= res.fSize.height());
+ const void* addr = (const char*)res.fPixels + SkColorTypeComputeOffset(fInfo.colorType(),
+ fPixelRefOrigin.x(),
+ fPixelRefOrigin.y(),
+ res.fRowBytes);
+
+ result->reset(SkPixmap(this->info(), addr, res.fRowBytes, res.fCTable),
+ res.fUnlockProc, res.fUnlockContext);
+ return true;
+ }
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
#ifdef SK_DEBUG
void SkImageInfo::validate() const {
SkASSERT(fWidth >= 0);

Powered by Google App Engine
This is Rietveld 408576698