aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar msarett <msarett@google.com>2015-11-19 15:29:26 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-11-19 15:29:26 -0800
commit72261c0afd4f1b0718bda05213a769120baa55c9 (patch)
treeb98953faaa3775c98d637dc6815b9a8acae757c0 /src
parentda707bf5635c70d4c3c284a0b05d92489b76788e (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.cpp55
-rw-r--r--src/codec/SkCodec_libgif.h16
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;
/*