diff options
author | msarett <msarett@google.com> | 2015-11-19 15:29:26 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-19 15:29:26 -0800 |
commit | 72261c0afd4f1b0718bda05213a769120baa55c9 (patch) | |
tree | b98953faaa3775c98d637dc6815b9a8acae757c0 /src | |
parent | da707bf5635c70d4c3c284a0b05d92489b76788e (diff) |
Implement SkGifCodec::onSkipScanlines()
This should give a performance improvment because we are able to skip
swizzling pixels.
This should also fix valgrind failures caused by color table lookups
with uninitialized memory.
BUG=skia:4270
Review URL: https://codereview.chromium.org/1460073002
Diffstat (limited to 'src')
-rw-r--r-- | src/codec/SkCodec_libgif.cpp | 55 | ||||
-rw-r--r-- | src/codec/SkCodec_libgif.h | 16 |
2 files changed, 60 insertions, 11 deletions
diff --git a/src/codec/SkCodec_libgif.cpp b/src/codec/SkCodec_libgif.cpp index 65503558aa..8021af95a2 100644 --- a/src/codec/SkCodec_libgif.cpp +++ b/src/codec/SkCodec_libgif.cpp @@ -506,10 +506,36 @@ SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, return this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, this->options()); } +void SkGifCodec::handleScanlineFrame(int count, int* rowsBeforeFrame, int* rowsInFrame) { + if (fFrameIsSubset) { + const int currRow = this->INHERITED::nextScanline(); + + // The number of rows that remain to be skipped before reaching rows that we + // actually must decode into. + // This must be at least zero. We also make sure that it is less than or + // equal to count, since we will skip at most count rows. + *rowsBeforeFrame = SkTMin(count, SkTMax(0, fFrameRect.top() - currRow)); + + // Rows left to decode once we reach the start of the frame. + const int rowsLeft = count - *rowsBeforeFrame; + + // Count the number of that extend beyond the bottom of the frame. We do not + // need to decode into these rows. + const int rowsAfterFrame = SkTMax(0, currRow + rowsLeft - fFrameRect.bottom()); + + // Set the actual number of source rows that we need to decode. + *rowsInFrame = rowsLeft - rowsAfterFrame; + } else { + *rowsBeforeFrame = 0; + *rowsInFrame = count; + } +} + int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { - int rowsBeforeFrame = 0; - int rowsAfterFrame = 0; - int rowsInFrame = count; + int rowsBeforeFrame; + int rowsInFrame; + this->handleScanlineFrame(count, &rowsBeforeFrame, &rowsInFrame); + if (fFrameIsSubset) { // Fill the requested rows SkImageInfo fillInfo = this->dstInfo().makeWH(this->dstInfo().width(), count); @@ -517,15 +543,8 @@ int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { this->dstInfo().alphaType()); fSwizzler->fill(fillInfo, dst, rowBytes, fillValue, this->options().fZeroInitialized); - // Do nothing for rows before the image frame - rowsBeforeFrame = SkTMax(0, fFrameRect.top() - this->INHERITED::nextScanline()); - rowsInFrame = SkTMax(0, rowsInFrame - rowsBeforeFrame); + // Start to write pixels at the start of the image frame dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame); - - // Do nothing for rows after the image frame - rowsAfterFrame = SkTMax(0, - this->INHERITED::nextScanline() + rowsInFrame - fFrameRect.bottom()); - rowsInFrame = SkTMax(0, rowsInFrame - rowsAfterFrame); } for (int i = 0; i < rowsInFrame; i++) { @@ -539,6 +558,20 @@ int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { return count; } +bool SkGifCodec::onSkipScanlines(int count) { + int rowsBeforeFrame; + int rowsInFrame; + this->handleScanlineFrame(count, &rowsBeforeFrame, &rowsInFrame); + + for (int i = 0; i < rowsInFrame; i++) { + if (!this->readRow()) { + return false; + } + } + + return true; +} + SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const { if (fGif->Image.Interlace) { return kOutOfOrder_SkScanlineOrder; diff --git a/src/codec/SkCodec_libgif.h b/src/codec/SkCodec_libgif.h index 31e0139b08..200f176e32 100644 --- a/src/codec/SkCodec_libgif.h +++ b/src/codec/SkCodec_libgif.h @@ -150,6 +150,22 @@ private: int onGetScanlines(void* dst, int count, size_t rowBytes) override; + bool onSkipScanlines(int count) override; + + /* + * For a scanline decode of "count" lines, this function indicates how + * many of the "count" lines should be skipped until we reach the top of + * the image frame and how many of the "count" lines are actually inside + * the image frame. + * + * @param count The number of scanlines requested. + * @param rowsBeforeFrame Output variable. The number of lines before + * we reach the top of the image frame. + * @param rowsInFrame Output variable. The number of lines to decode + * inside the image frame. + */ + void handleScanlineFrame(int count, int* rowsBeforeFrame, int* rowsInFrame); + SkScanlineOrder onGetScanlineOrder() const override; /* |