aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-02-14 11:21:02 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-02-14 17:50:52 +0000
commit8572d853514e3c73077540341edbf62a3f486605 (patch)
tree66341d4ede6a9532d30142a68301e6c04c92cdab /src/core
parent4bf560a056d7ba5b3051ebc87e687d4997928ff6 (diff)
Make raster pipeline support all pixel conversions
BUG=skia: CQ_INCLUDE_TRYBOTS=skia.primary:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD Change-Id: Idc76999d0f5591a567b3976cb9db829c350e4be2 Reviewed-on: https://skia-review.googlesource.com/8304 Reviewed-by: Mike Klein <mtklein@chromium.org> Commit-Queue: Matt Sarett <msarett@google.com>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkBitmap.cpp5
-rw-r--r--src/core/SkConfig8888.cpp220
-rw-r--r--src/core/SkConfig8888.h12
-rw-r--r--src/core/SkImageInfoPriv.h39
-rw-r--r--src/core/SkPixmap.cpp5
-rw-r--r--src/core/SkRasterPipeline.h1
6 files changed, 117 insertions, 165 deletions
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index f54488d0a5..33575499e6 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -726,8 +726,9 @@ bool SkBitmap::writePixels(const SkPixmap& src, int dstX, int dstY) {
void* dstPixels = this->getAddr(rec.fX, rec.fY);
const SkImageInfo dstInfo = fInfo.makeWH(rec.fInfo.width(), rec.fInfo.height());
- return SkPixelInfo::CopyPixels(dstInfo, dstPixels, this->rowBytes(),
- rec.fInfo, rec.fPixels, rec.fRowBytes, src.ctable());
+ SkPixelInfo::CopyPixels(dstInfo, dstPixels, this->rowBytes(), rec.fInfo, rec.fPixels,
+ rec.fRowBytes, src.ctable());
+ return true;
}
bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc) const {
diff --git a/src/core/SkConfig8888.cpp b/src/core/SkConfig8888.cpp
index c1cd16aeb6..616ba192a7 100644
--- a/src/core/SkConfig8888.cpp
+++ b/src/core/SkConfig8888.cpp
@@ -25,6 +25,10 @@ static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& src
return false;
}
+ if (kAlpha_8_SkColorType == dstInfo.colorType()) {
+ return true;
+ }
+
if (dstInfo.alphaType() != srcInfo.alphaType() &&
kOpaque_SkAlphaType != dstInfo.alphaType() &&
kOpaque_SkAlphaType != srcInfo.alphaType())
@@ -85,7 +89,7 @@ void swizzle_and_multiply(const SkImageInfo& dstInfo, void* dstPixels, size_t ds
}
// Default: Use the pipeline.
-static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB,
+static void copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB,
const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB,
bool isColorAware) {
SkRasterPipeline pipeline;
@@ -106,8 +110,12 @@ static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_
case kGray_8_SkColorType:
pipeline.append(SkRasterPipeline::load_g8, &srcRow);
break;
+ case kARGB_4444_SkColorType:
+ pipeline.append(SkRasterPipeline::load_4444, &srcRow);
+ break;
default:
- return false;
+ SkASSERT(false);
+ break;
}
if (isColorAware && srcInfo.gammaCloseToSRGB()) {
@@ -146,8 +154,15 @@ static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_
case kRGBA_F16_SkColorType:
pipeline.append(SkRasterPipeline::store_f16, &dstRow);
break;
+ case kAlpha_8_SkColorType:
+ pipeline.append(SkRasterPipeline::store_a8, &dstRow);
+ break;
+ case kARGB_4444_SkColorType:
+ pipeline.append(SkRasterPipeline::store_4444, &dstRow);
+ break;
default:
- return false;
+ SkASSERT(false);
+ break;
}
auto p = pipeline.compile();
@@ -159,67 +174,9 @@ static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_
dstRow = SkTAddOffset<void>(dstRow, dstRB);
srcRow = SkTAddOffset<const void>(srcRow, srcRB);
}
- return true;
-}
-
-static bool extract_alpha(void* dst, size_t dstRB, const void* src, size_t srcRB,
- const SkImageInfo& srcInfo, SkColorTable* ctable) {
- uint8_t* SK_RESTRICT dst8 = (uint8_t*)dst;
-
- const int w = srcInfo.width();
- const int h = srcInfo.height();
- if (srcInfo.isOpaque()) {
- // src is opaque, so just fill alpha with 0xFF
- for (int y = 0; y < h; ++y) {
- memset(dst8, 0xFF, w);
- dst8 += dstRB;
- }
- return true;
- }
- switch (srcInfo.colorType()) {
- case kN32_SkColorType: {
- const SkPMColor* SK_RESTRICT src32 = (const SkPMColor*)src;
- for (int y = 0; y < h; ++y) {
- for (int x = 0; x < w; ++x) {
- dst8[x] = SkGetPackedA32(src32[x]);
- }
- dst8 += dstRB;
- src32 = (const SkPMColor*)((const char*)src32 + srcRB);
- }
- break;
- }
- case kARGB_4444_SkColorType: {
- const SkPMColor16* SK_RESTRICT src16 = (const SkPMColor16*)src;
- for (int y = 0; y < h; ++y) {
- for (int x = 0; x < w; ++x) {
- dst8[x] = SkPacked4444ToA32(src16[x]);
- }
- dst8 += dstRB;
- src16 = (const SkPMColor16*)((const char*)src16 + srcRB);
- }
- break;
- }
- case kIndex_8_SkColorType: {
- if (nullptr == ctable) {
- return false;
- }
- const SkPMColor* SK_RESTRICT table = ctable->readColors();
- const uint8_t* SK_RESTRICT src8 = (const uint8_t*)src;
- for (int y = 0; y < h; ++y) {
- for (int x = 0; x < w; ++x) {
- dst8[x] = SkGetPackedA32(table[src8[x]]);
- }
- dst8 += dstRB;
- src8 += srcRB;
- }
- break;
- }
- default:
- return false;
- }
- return true;
}
+// Fast Path 3: Color space xform.
static inline bool optimized_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
if (kUnpremul_SkAlphaType == dstInfo.alphaType() && kPremul_SkAlphaType == srcInfo.alphaType())
{
@@ -287,19 +244,61 @@ static inline void apply_color_xform(const SkImageInfo& dstInfo, void* dstPixels
}
}
-bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
+// Fast Path 4: Index 8 sources.
+template <typename T>
+void do_index8(const SkImageInfo& dstInfo, T* dstPixels, size_t dstRB,
+ const SkImageInfo& srcInfo, const uint8_t* srcPixels, size_t srcRB,
+ SkColorTable* ctable) {
+ T dstCTable[256];
+ int count = ctable->count();
+ SkImageInfo srcInfo8888 = srcInfo.makeColorType(kN32_SkColorType).makeWH(count, 1);
+ SkImageInfo dstInfoCT = dstInfo.makeWH(count, 1);
+ size_t rowBytes = count * sizeof(T);
+ SkPixelInfo::CopyPixels(dstInfoCT, dstCTable, rowBytes, srcInfo8888, ctable->readColors(),
+ rowBytes, nullptr);
+
+ for (int y = 0; y < dstInfo.height(); y++) {
+ for (int x = 0; x < dstInfo.width(); x++) {
+ dstPixels[x] = dstCTable[srcPixels[x]];
+ }
+ dstPixels = SkTAddOffset<T>(dstPixels, dstRB);
+ srcPixels = SkTAddOffset<const uint8_t>(srcPixels, srcRB);
+ }
+}
+
+void xform_from_index8(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
+ const SkImageInfo& srcInfo, const uint8_t* srcPixels, size_t srcRB,
+ SkColorTable* ctable) {
+ switch (dstInfo.colorType()) {
+ case kAlpha_8_SkColorType:
+ do_index8(dstInfo, (uint8_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable);
+ break;
+ case kRGB_565_SkColorType:
+ case kARGB_4444_SkColorType:
+ do_index8(dstInfo, (uint16_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable);
+ break;
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType:
+ do_index8(dstInfo, (uint32_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable);
+ break;
+ case kRGBA_F16_SkColorType:
+ do_index8(dstInfo, (uint64_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable);
+ break;
+ default:
+ SkASSERT(false);
+ }
+}
+
+void SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
SkColorTable* ctable) {
SkASSERT(dstInfo.dimensions() == srcInfo.dimensions());
SkASSERT(SkImageInfoValidConversion(dstInfo, srcInfo));
- const int width = srcInfo.width();
- const int height = srcInfo.height();
-
// Fast Path 1: The memcpy() case.
if (can_memcpy(dstInfo, srcInfo)) {
SkRectMemcpy(dstPixels, dstRB, srcPixels, srcRB, dstInfo.minRowBytes(), dstInfo.height());
- return true;
+ return;
}
const bool isColorAware = dstInfo.colorSpace();
@@ -308,88 +307,23 @@ bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t
// Fast Path 2: Simple swizzles and premuls.
if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel() && !isColorAware) {
swizzle_and_multiply(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB);
- return true;
+ return;
}
+ // Fast Path 3: Color space xform.
if (isColorAware && optimized_color_xform(dstInfo, srcInfo)) {
apply_color_xform(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB);
- return true;
- }
-
- /*
- * Begin section where we try to change colorTypes along the way. Not all combinations
- * are supported.
- */
-
- if (kAlpha_8_SkColorType == dstInfo.colorType() &&
- extract_alpha(dstPixels, dstRB, srcPixels, srcRB, srcInfo, ctable)) {
- return true;
+ return;
}
- // Try the pipeline
- //
- if (copy_pipeline_pixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, isColorAware)) {
- return true;
+ // Fast Path 4: Index 8 sources.
+ if (kIndex_8_SkColorType == srcInfo.colorType()) {
+ SkASSERT(ctable);
+ xform_from_index8(dstInfo, dstPixels, dstRB, srcInfo, (const uint8_t*) srcPixels, srcRB,
+ ctable);
+ return;
}
- // Can no longer draw directly into 4444, but we can manually whack it for a few combinations
- if (kARGB_4444_SkColorType == dstInfo.colorType() &&
- (kN32_SkColorType == srcInfo.colorType() || kIndex_8_SkColorType == srcInfo.colorType())) {
- if (srcInfo.alphaType() == kUnpremul_SkAlphaType) {
- // Our method for converting to 4444 assumes premultiplied.
- return false;
- }
-
- const SkPMColor* table = nullptr;
- if (kIndex_8_SkColorType == srcInfo.colorType()) {
- SkASSERT(ctable);
- table = ctable->readColors();
- }
-
- for (int y = 0; y < height; ++y) {
- DITHER_4444_SCAN(y);
- SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*)dstPixels;
- if (table) {
- const uint8_t* SK_RESTRICT srcRow = (const uint8_t*)srcPixels;
- for (int x = 0; x < width; ++x) {
- dstRow[x] = SkDitherARGB32To4444(table[srcRow[x]], DITHER_VALUE(x));
- }
- } else {
- const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)srcPixels;
- for (int x = 0; x < width; ++x) {
- dstRow[x] = SkDitherARGB32To4444(srcRow[x], DITHER_VALUE(x));
- }
- }
- dstPixels = (char*)dstPixels + dstRB;
- srcPixels = (const char*)srcPixels + srcRB;
- }
- return true;
- }
-
- if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
- // We do not support drawing to unpremultiplied bitmaps.
- return false;
- }
-
- // Final fall-back, draw with a canvas
- //
- // Always clear the dest in case one of the blitters accesses it
- // TODO: switch the allocation of tmpDst to call sk_calloc_throw
- {
- SkBitmap bm;
- if (!bm.installPixels(srcInfo, const_cast<void*>(srcPixels), srcRB, ctable, nullptr, nullptr)) {
- return false;
- }
- std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(dstInfo, dstPixels, dstRB);
- if (!canvas) {
- return false;
- }
-
- SkPaint paint;
- paint.setDither(true);
-
- canvas->clear(0);
- canvas->drawBitmap(bm, 0, 0, &paint);
- return true;
- }
+ // Default: Use the pipeline.
+ copy_pipeline_pixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, isColorAware);
}
diff --git a/src/core/SkConfig8888.h b/src/core/SkConfig8888.h
index 9c1ff4ab07..ae42242ad5 100644
--- a/src/core/SkConfig8888.h
+++ b/src/core/SkConfig8888.h
@@ -13,14 +13,10 @@
class SkColorTable;
-struct SkPixelInfo {
- SkColorType fColorType;
- SkAlphaType fAlphaType;
- size_t fRowBytes;
-
- static bool CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
- const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes,
- SkColorTable* srcCTable = nullptr);
+namespace SkPixelInfo {
+ void CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes,
+ SkColorTable* srcCTable = nullptr);
};
static inline void SkRectMemcpy(void* dst, size_t dstRB, const void* src, size_t srcRB,
diff --git a/src/core/SkImageInfoPriv.h b/src/core/SkImageInfoPriv.h
index 40209f8946..855e506bb2 100644
--- a/src/core/SkImageInfoPriv.h
+++ b/src/core/SkImageInfoPriv.h
@@ -19,6 +19,11 @@ static inline bool SkImageInfoIsValid(const SkImageInfo& info) {
return false;
}
+ const int kMaxDimension = SK_MaxS32 >> 2;
+ if (info.width() > kMaxDimension || info.height() > kMaxDimension) {
+ return false;
+ }
+
if (kUnknown_SkColorType == info.colorType() || kUnknown_SkAlphaType == info.alphaType()) {
return false;
}
@@ -44,8 +49,8 @@ static inline bool SkImageInfoIsValid(const SkImageInfo& info) {
/**
* Returns true if Skia has defined a pixel conversion from the |src| to the |dst|.
* Returns false otherwise. Some discussion of false cases:
- * We will not convert to kIndex8 when the |src| is not kIndex8 in the same color space
- * (color tables are immutable).
+ * We will not convert to kIndex8 unless it exactly matches the src, since color tables
+ * are immutable.
* We do not convert to kGray8 when the |src| is not kGray8 in the same color space.
* We may add this feature - it just requires some work to convert to luminance while
* handling color spaces correctly. Currently no one is asking for this.
@@ -64,16 +69,30 @@ static inline bool SkImageInfoValidConversion(const SkImageInfo& dst, const SkIm
return false;
}
- if (kIndex_8_SkColorType == dst.colorType() && kIndex_8_SkColorType != src.colorType() &&
- dst.colorSpace() && !SkColorSpace::Equals(dst.colorSpace(), src.colorSpace()))
- {
- return false;
+ if (kIndex_8_SkColorType == dst.colorType()) {
+ if (kIndex_8_SkColorType != src.colorType()) {
+ return false;
+ }
+
+ if ((kPremul_SkAlphaType == dst.alphaType() && kUnpremul_SkAlphaType == src.alphaType()) ||
+ (kUnpremul_SkAlphaType == dst.alphaType() && kPremul_SkAlphaType == src.alphaType()))
+ {
+ return false;
+ }
+
+ if (dst.colorSpace() && !SkColorSpace::Equals(dst.colorSpace(), src.colorSpace())) {
+ return false;
+ }
}
- if (kGray_8_SkColorType == dst.colorType() && kGray_8_SkColorType != src.colorType() &&
- dst.colorSpace() && !SkColorSpace::Equals(dst.colorSpace(), src.colorSpace()))
- {
- return false;
+ if (kGray_8_SkColorType == dst.colorType()) {
+ if (kGray_8_SkColorType != src.colorType()) {
+ return false;
+ }
+
+ if (dst.colorSpace() && !SkColorSpace::Equals(dst.colorSpace(), src.colorSpace())) {
+ return false;
+ }
}
if (kAlpha_8_SkColorType != dst.colorType() && kAlpha_8_SkColorType == src.colorType()) {
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index c0889cfd84..8b7171f96f 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -97,8 +97,9 @@ const {
const void* srcPixels = this->addr(rec.fX, rec.fY);
const SkImageInfo srcInfo = fInfo.makeWH(rec.fInfo.width(), rec.fInfo.height());
- return SkPixelInfo::CopyPixels(rec.fInfo, rec.fPixels, rec.fRowBytes,
- srcInfo, srcPixels, this->rowBytes(), this->ctable());
+ SkPixelInfo::CopyPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, srcInfo, srcPixels,
+ this->rowBytes(), this->ctable());
+ return true;
}
static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) {
diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h
index e507b28e7c..9afe2fdd29 100644
--- a/src/core/SkRasterPipeline.h
+++ b/src/core/SkRasterPipeline.h
@@ -68,6 +68,7 @@
M(load_a8) M(store_a8) \
M(load_g8) \
M(load_565) M(store_565) \
+ M(load_4444) M(store_4444) \
M(load_f16) M(store_f16) \
M(load_8888) M(store_8888) \
M(load_u16_be) M(load_rgb_u16_be) M(store_u16_be) \