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

Unified Diff: src/codec/SkPngCodec.cpp

Issue 1671003004: Skip memcpy() swizzles in SkPngCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: First Approach Created 4 years, 10 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/codec/SkPngCodec.cpp
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
index 232373c04407c63c2b391c148a7053db9e9d62e9..797178948fba8c6d05b07d96fabbb6e5a49811c8 100644
--- a/src/codec/SkPngCodec.cpp
+++ b/src/codec/SkPngCodec.cpp
@@ -426,6 +426,11 @@ SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
SkASSERT(false);
}
+ // If we are not performing a subset decode, and the swizzle will not change the
+ // number of bytes per pixel, we can swizzle in place.
+ fInPlaceSwizzle = (SkSwizzler::BytesPerPixel(fSrcConfig) ==
+ SkColorTypeBytesPerPixel(requestedInfo.colorType()) && !options.fSubset);
+
// Copy the color table to the client if they request kIndex8 mode
copy_color_table(requestedInfo, fColorTable, ctable, ctableCount);
@@ -475,6 +480,11 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
if (result != kSuccess) {
return result;
}
+
+ const int width = requestedInfo.width();
+ const int height = requestedInfo.height();
+ const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig);
+
// FIXME: Could we use the return value of setjmp to specify the type of
// error?
int row = 0;
@@ -484,7 +494,7 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
// Assume that any error that occurs while reading rows is caused by an incomplete input.
if (fNumberPasses > 1) {
// FIXME (msarett): Handle incomplete interlaced pngs.
- return kInvalidInput;
+ return row == height ? kSuccess : kInvalidInput;
}
// FIXME: We do a poor job on incomplete pngs compared to other decoders (ex: Chromium,
// Ubuntu Image Viewer). This is because we use the default buffer size in libpng (8192
@@ -498,25 +508,20 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
// it have on regular decode performance? Should we investigate using a different API
// instead of png_read_row(s)? Chromium uses png_process_data.
*rowsDecoded = row;
- return kIncompleteInput;
+ return row == height ? kSuccess : kIncompleteInput;
}
// FIXME: We could split these out based on subclass.
void* dstRow = dst;
if (fNumberPasses > 1) {
- const int width = requestedInfo.width();
- const int height = requestedInfo.height();
- const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig);
- const size_t srcRowBytes = width * bpp;
-
- storage.reset(width * height * bpp);
- uint8_t* const base = storage.get();
+ uint8_t* const base = fInPlaceSwizzle ? (uint8_t*) dstRow :
+ storage.reset(width * height * bpp);
+ const size_t srcRowBytes = fInPlaceSwizzle ? dstRowBytes : width * bpp;
for (int i = 0; i < fNumberPasses; i++) {
uint8_t* srcRow = base;
for (int y = 0; y < height; y++) {
- uint8_t* bmRow = srcRow;
- png_read_rows(fPng_ptr, &bmRow, nullptr, 1);
+ png_read_rows(fPng_ptr, &srcRow, nullptr, 1);
srcRow += srcRowBytes;
}
}
@@ -529,21 +534,16 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
srcRow += srcRowBytes;
}
} else {
- storage.reset(requestedInfo.width() * SkSwizzler::BytesPerPixel(fSrcConfig));
- uint8_t* srcRow = storage.get();
+ uint8_t* srcRow = fInPlaceSwizzle ? (uint8_t*) dstRow : storage.reset(width * bpp);
+ const size_t srcRowBytes = fInPlaceSwizzle ? dstRowBytes : 0;
for (; row < requestedInfo.height(); row++) {
png_read_rows(fPng_ptr, &srcRow, nullptr, 1);
- // FIXME: Only call IsOpaque once, outside the loop. Same for onGetScanlines.
fSwizzler->swizzle(dstRow, srcRow);
dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
+ srcRow += srcRowBytes;
}
}
- if (setjmp(png_jmpbuf(fPng_ptr))) {
- // We've already read all the scanlines. This is a success.
- return kSuccess;
- }
-
// read rest of file, and get additional comment and time chunks in info_ptr
png_read_end(fPng_ptr, fInfo_ptr);
@@ -595,8 +595,9 @@ public:
void* dstRow = dst;
for (; row < count; row++) {
- png_read_rows(this->png_ptr(), &fSrcRow, nullptr, 1);
- this->swizzler()->swizzle(dstRow, fSrcRow);
+ uint8_t* srcRow = this->inPlaceSwizzle() ? (uint8_t*) dstRow : fSrcRow;
+ png_read_rows(this->png_ptr(), &srcRow, nullptr, 1);
+ this->swizzler()->swizzle(dstRow, srcRow);
dstRow = SkTAddOffset<void>(dstRow, rowBytes);
}
@@ -690,8 +691,10 @@ public:
// fail on the first pass, we can still report than some scanlines are initialized.
return 0;
}
- SkAutoTMalloc<uint8_t> storage(count * fSrcRowBytes);
- uint8_t* storagePtr = storage.get();
+ SkAutoTMalloc<uint8_t> storage;
+ uint8_t* const base = this->inPlaceSwizzle() ? (uint8_t*) dst :
+ storage.reset(count * fSrcRowBytes);
+ const size_t srcRowBytes = this->inPlaceSwizzle() ? dstRowBytes : fSrcRowBytes;
uint8_t* srcRow;
const int startRow = this->nextScanline();
for (int i = 0; i < this->numberPasses(); i++) {
@@ -700,10 +703,10 @@ public:
png_read_rows(this->png_ptr(), &fGarbageRowPtr, nullptr, 1);
}
// read rows we care about into buffer
- srcRow = storagePtr;
+ uint8_t* srcRow = base;
for (int y = 0; y < count; y++) {
png_read_rows(this->png_ptr(), &srcRow, nullptr, 1);
- srcRow += fSrcRowBytes;
+ srcRow += srcRowBytes;
}
// read rows we don't want into garbage buffer
for (int y = 0; y < fHeight - startRow - count; y++) {
@@ -711,12 +714,12 @@ public:
}
}
//swizzle the rows we care about
- srcRow = storagePtr;
+ srcRow = base;
void* dstRow = dst;
for (int y = 0; y < count; y++) {
this->swizzler()->swizzle(dstRow, srcRow);
dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
- srcRow += fSrcRowBytes;
+ srcRow += srcRowBytes;
}
return count;

Powered by Google App Engine
This is Rietveld 408576698