DeferredTextureImageData low-bit-depth/dithering support
Cause DeferredTextureImageData functionality to support low bit depth
(4444, 565) image formats (with dithering).
Bug: 720105
Change-Id: Ie3b5768ebc393d9b0a5322461c722bf37c80b791
Reviewed-on: https://skia-review.googlesource.com/18945
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Eric Karl <ericrk@chromium.org>
diff --git a/gm/deferredtextureimage.cpp b/gm/deferredtextureimage.cpp
index 9c1fe6a..db070fc 100644
--- a/gm/deferredtextureimage.cpp
+++ b/gm/deferredtextureimage.cpp
@@ -154,6 +154,13 @@
DrawDeferredTextureImageData(canvas, ¶ms);
}
+DEF_SIMPLE_GM(deferred_texture_image_low_dithered, canvas, 512 + 512 + 30, 512 + 20) {
+ auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
+ kLow_SkFilterQuality, 0,
+ kARGB_4444_SkColorType);
+ DrawDeferredTextureImageData(canvas, ¶ms);
+}
+
DEF_SIMPLE_GM(deferred_texture_image_medium_encoded, canvas, 512 + 512 + 30, 1110) {
sk_sp<SkImage> encodedImage = GetResourceAsImage("mandrill_512.png");
if (!encodedImage) {
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index bc0597c..b896856 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -447,11 +447,15 @@
/** Drawing params for which a deferred texture image data should be optimized. */
struct DeferredTextureImageUsageParams {
DeferredTextureImageUsageParams(const SkMatrix matrix, const SkFilterQuality quality,
- int preScaleMipLevel)
- : fMatrix(matrix), fQuality(quality), fPreScaleMipLevel(preScaleMipLevel) {}
+ int preScaleMipLevel,
+ SkColorType colorType = kN32_SkColorType)
+ : fMatrix(matrix), fQuality(quality), fPreScaleMipLevel(preScaleMipLevel),
+ fColorType(colorType) {}
SkMatrix fMatrix;
SkFilterQuality fQuality;
int fPreScaleMipLevel;
+ SkColorType fColorType;
+
};
/**
diff --git a/src/core/SkAutoPixmapStorage.cpp b/src/core/SkAutoPixmapStorage.cpp
index 865b3a6..5ad1939 100644
--- a/src/core/SkAutoPixmapStorage.cpp
+++ b/src/core/SkAutoPixmapStorage.cpp
@@ -14,6 +14,16 @@
this->freeStorage();
}
+SkAutoPixmapStorage& SkAutoPixmapStorage::operator=(SkAutoPixmapStorage&& other) {
+ this->fStorage = other.fStorage;
+ this->INHERITED::reset(other.info(), this->fStorage, other.rowBytes(), other.ctable());
+
+ other.fStorage = nullptr;
+ other.INHERITED::reset();
+
+ return *this;
+}
+
size_t SkAutoPixmapStorage::AllocSize(const SkImageInfo& info, size_t* rowBytes) {
size_t rb = info.minRowBytes();
if (rowBytes) {
diff --git a/src/core/SkAutoPixmapStorage.h b/src/core/SkAutoPixmapStorage.h
index 66c5655..6342a41 100644
--- a/src/core/SkAutoPixmapStorage.h
+++ b/src/core/SkAutoPixmapStorage.h
@@ -17,6 +17,11 @@
~SkAutoPixmapStorage();
/**
+ * Leave the moved-from object in a free-but-valid state.
+ */
+ SkAutoPixmapStorage& operator=(SkAutoPixmapStorage&& other);
+
+ /**
* Try to allocate memory for the pixels needed to match the specified Info. On success
* return true and fill out the pixmap to point to that memory. The storage will be freed
* when this object is destroyed, or if another call to tryAlloc() or alloc() is made.
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 55ceba0..4c89e8e 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -657,7 +657,8 @@
SkAutoPixmapStorage pixmap;
SkImageInfo info;
size_t pixelSize = 0;
- if (!isScaled && this->peekPixels(&pixmap) && !pixmap.ctable()) {
+ if (!isScaled && this->peekPixels(&pixmap) && !pixmap.ctable() &&
+ pixmap.info().colorType() == params[0].fColorType) {
info = pixmap.info();
pixelSize = SkAlign8(pixmap.getSafeSize());
if (!dstColorSpace) {
@@ -680,24 +681,35 @@
info = info.makeColorSpace(nullptr);
}
}
- if (kIndex_8_SkColorType == info.colorType()) {
- // Force Index8 to be N32 instead. Index8 is unsupported in Ganesh.
- info = info.makeColorType(kN32_SkColorType);
- }
+ // Force color type to be the requested type.
+ info = info.makeColorType(params->fColorType);
pixelSize = SkAlign8(SkAutoPixmapStorage::AllocSize(info, nullptr));
if (fillMode) {
- pixmap.alloc(info);
+ // Always decode to N32 and convert to the requested type if necessary.
+ SkImageInfo decodeInfo = info.makeColorType(kN32_SkColorType);
+ SkAutoPixmapStorage decodePixmap;
+ decodePixmap.alloc(decodeInfo);
+
if (isScaled) {
- if (!this->scalePixels(pixmap, scaleFilterQuality,
+ if (!this->scalePixels(decodePixmap, scaleFilterQuality,
SkImage::kDisallow_CachingHint)) {
return 0;
}
} else {
- if (!this->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHint)) {
+ if (!this->readPixels(decodePixmap, 0, 0, SkImage::kDisallow_CachingHint)) {
return 0;
}
}
- SkASSERT(!pixmap.ctable());
+ SkASSERT(!decodePixmap.ctable());
+
+ if (decodeInfo.colorType() != info.colorType()) {
+ pixmap.alloc(info);
+ // Convert and copy the decoded pixmap to the target pixmap.
+ decodePixmap.readPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(), 0,
+ 0);
+ } else {
+ pixmap = std::move(decodePixmap);
+ }
}
}
int mipMapLevelCount = 1;
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index c747b8e..a67756b 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -1078,6 +1078,13 @@
{ createLarge, {{SkMatrix::I(), kMedium_SkFilterQuality, 5},
{SkMatrix::I(), kMedium_SkFilterQuality, 4}},
kMedium_SkFilterQuality, 16, true},
+ // Create a images which are decoded to a 4444 backing.
+ { create_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0,kARGB_4444_SkColorType}},
+ kNone_SkFilterQuality, 1, true },
+ { create_codec_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0, kARGB_4444_SkColorType}},
+ kNone_SkFilterQuality, 1, true },
+ { create_data_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0, kARGB_4444_SkColorType}},
+ kNone_SkFilterQuality, 1, true },
};