diff options
author | 2017-02-14 11:21:02 -0500 | |
---|---|---|
committer | 2017-02-14 17:50:52 +0000 | |
commit | 8572d853514e3c73077540341edbf62a3f486605 (patch) | |
tree | 66341d4ede6a9532d30142a68301e6c04c92cdab /src/core | |
parent | 4bf560a056d7ba5b3051ebc87e687d4997928ff6 (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.cpp | 5 | ||||
-rw-r--r-- | src/core/SkConfig8888.cpp | 220 | ||||
-rw-r--r-- | src/core/SkConfig8888.h | 12 | ||||
-rw-r--r-- | src/core/SkImageInfoPriv.h | 39 | ||||
-rw-r--r-- | src/core/SkPixmap.cpp | 5 | ||||
-rw-r--r-- | src/core/SkRasterPipeline.h | 1 |
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) \ |