diff options
author | Matt Sarett <msarett@google.com> | 2017-02-09 16:22:39 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-02-09 22:11:13 +0000 |
commit | c7b29089475772a51541323a93a15baad2a5feaa (patch) | |
tree | 308b5bf2b4d4b0d7bf7bd021e147028e7b7878b2 /src/core | |
parent | 5881e82060e59abe477ba34d33ada661c53d81f0 (diff) |
Refactor pixel conversion: premul and unpremul
Just going for simpler and more code sharing.
BUG=skia:
Change-Id: I84c20cd4dbb6950f7b4d0bc659c4b3b5a2af201c
Reviewed-on: https://skia-review.googlesource.com/8287
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Matt Sarett <msarett@google.com>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkConfig8888.cpp | 168 | ||||
-rw-r--r-- | src/core/SkConfig8888.h | 12 | ||||
-rw-r--r-- | src/core/SkUnPreMultiplyPriv.h | 43 |
3 files changed, 95 insertions, 128 deletions
diff --git a/src/core/SkConfig8888.cpp b/src/core/SkConfig8888.cpp index cae2eef408..59360e25d4 100644 --- a/src/core/SkConfig8888.cpp +++ b/src/core/SkConfig8888.cpp @@ -14,9 +14,10 @@ #include "SkDither.h" #include "SkImageInfoPriv.h" #include "SkMathPriv.h" +#include "SkOpts.h" #include "SkPM4fPriv.h" #include "SkRasterPipeline.h" -#include "SkUnPreMultiply.h" +#include "SkUnPreMultiplyPriv.h" // Fast Path 1: The memcpy() case. static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) { @@ -36,6 +37,53 @@ static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& src SkColorSpace::Equals(dstInfo.colorSpace(), srcInfo.colorSpace()); } +enum AlphaVerb { + kNothing_AlphaVerb, + kPremul_AlphaVerb, + kUnpremul_AlphaVerb, +}; + +template <bool kSwapRB> +static void wrap_unpremultiply(uint32_t* dst, const void* src, int count) { + SkUnpremultiplyRow<kSwapRB>(dst, (const uint32_t*) src, count); +} + +// Fast Path 2: Simple swizzles and premuls. +void swizzle_and_multiply(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, + const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB) { + void (*proc)(uint32_t* dst, const void* src, int count); + const bool swapRB = dstInfo.colorType() != srcInfo.colorType(); + AlphaVerb alphaVerb = kNothing_AlphaVerb; + if (kPremul_SkAlphaType == dstInfo.alphaType() && + kUnpremul_SkAlphaType == srcInfo.alphaType()) + { + alphaVerb = kPremul_AlphaVerb; + } else if (kUnpremul_SkAlphaType == dstInfo.alphaType() && + kPremul_SkAlphaType == srcInfo.alphaType()) { + alphaVerb = kUnpremul_AlphaVerb; + } + + switch (alphaVerb) { + case kNothing_AlphaVerb: + // If we do not need to swap or multiply, we should hit the memcpy case. + SkASSERT(swapRB); + proc = SkOpts::RGBA_to_BGRA; + break; + case kPremul_AlphaVerb: + proc = swapRB ? SkOpts::RGBA_to_bgrA : SkOpts::RGBA_to_rgbA; + break; + case kUnpremul_AlphaVerb: + proc = swapRB ? wrap_unpremultiply<true> : wrap_unpremultiply<false>; + break; + } + + for (int y = 0; y < dstInfo.height(); y++) { + proc((uint32_t*) dstPixels, srcPixels, dstInfo.width()); + dstPixels = SkTAddOffset<void>(dstPixels, dstRB); + srcPixels = SkTAddOffset<const void>(srcPixels, srcRB); + } +} + // Default: Use the pipeline. static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB, const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB, @@ -114,107 +162,6 @@ static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_ return true; } -enum AlphaVerb { - kNothing_AlphaVerb, - kPremul_AlphaVerb, - kUnpremul_AlphaVerb, -}; - -template <bool doSwapRB, AlphaVerb doAlpha> uint32_t convert32(uint32_t c) { - if (doSwapRB) { - c = SkSwizzle_RB(c); - } - - // Lucky for us, in both RGBA and BGRA, the alpha component is always in the same place, so - // we can perform premul or unpremul the same way without knowing the swizzles for RGB. - switch (doAlpha) { - case kNothing_AlphaVerb: - // no change - break; - case kPremul_AlphaVerb: - c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c), - SkGetPackedG32(c), SkGetPackedB32(c)); - break; - case kUnpremul_AlphaVerb: - c = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(c); - break; - } - return c; -} - -template <bool doSwapRB, AlphaVerb doAlpha> -void convert32_row(uint32_t* dst, const uint32_t* src, int count) { - // This has to be correct if src == dst (but not partial overlap) - for (int i = 0; i < count; ++i) { - dst[i] = convert32<doSwapRB, doAlpha>(src[i]); - } -} - -static bool is_32bit_colortype(SkColorType ct) { - return kRGBA_8888_SkColorType == ct || kBGRA_8888_SkColorType == ct; -} - -static AlphaVerb compute_AlphaVerb(SkAlphaType src, SkAlphaType dst) { - SkASSERT(kUnknown_SkAlphaType != src); - SkASSERT(kUnknown_SkAlphaType != dst); - - if (kOpaque_SkAlphaType == src || kOpaque_SkAlphaType == dst || src == dst) { - return kNothing_AlphaVerb; - } - if (kPremul_SkAlphaType == dst) { - SkASSERT(kUnpremul_SkAlphaType == src); - return kPremul_AlphaVerb; - } else { - SkASSERT(kPremul_SkAlphaType == src); - SkASSERT(kUnpremul_SkAlphaType == dst); - return kUnpremul_AlphaVerb; - } -} - -bool SkSrcPixelInfo::convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const { - SkASSERT(width > 0 && height > 0); - - if (!is_32bit_colortype(fColorType) || !is_32bit_colortype(dst->fColorType)) { - return false; - } - - void (*proc)(uint32_t* dst, const uint32_t* src, int count); - AlphaVerb doAlpha = compute_AlphaVerb(fAlphaType, dst->fAlphaType); - bool doSwapRB = fColorType != dst->fColorType; - - switch (doAlpha) { - case kNothing_AlphaVerb: - SkASSERT(doSwapRB); - proc = convert32_row<true, kNothing_AlphaVerb>; - break; - case kPremul_AlphaVerb: - if (doSwapRB) { - proc = convert32_row<true, kPremul_AlphaVerb>; - } else { - proc = convert32_row<false, kPremul_AlphaVerb>; - } - break; - case kUnpremul_AlphaVerb: - if (doSwapRB) { - proc = convert32_row<true, kUnpremul_AlphaVerb>; - } else { - proc = convert32_row<false, kUnpremul_AlphaVerb>; - } - break; - } - - uint32_t* dstP = static_cast<uint32_t*>(dst->fPixels); - const uint32_t* srcP = static_cast<const uint32_t*>(fPixels); - size_t srcInc = fRowBytes >> 2; - size_t dstInc = dst->fRowBytes >> 2; - for (int y = 0; y < height; ++y) { - proc(dstP, srcP, width); - dstP += dstInc; - srcP += srcInc; - } - 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; @@ -358,21 +305,10 @@ bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t const bool isColorAware = dstInfo.colorSpace(); SkASSERT(srcInfo.colorSpace() || !isColorAware); - // Handle fancy alpha swizzling if both are ARGB32 + // Fast Path 2: Simple swizzles and premuls. if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel() && !isColorAware) { - SkDstPixelInfo dstPI; - dstPI.fColorType = dstInfo.colorType(); - dstPI.fAlphaType = dstInfo.alphaType(); - dstPI.fPixels = dstPixels; - dstPI.fRowBytes = dstRB; - - SkSrcPixelInfo srcPI; - srcPI.fColorType = srcInfo.colorType(); - srcPI.fAlphaType = srcInfo.alphaType(); - srcPI.fPixels = srcPixels; - srcPI.fRowBytes = srcRB; - - return srcPI.convertPixelsTo(&dstPI, width, height); + swizzle_and_multiply(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB); + return true; } if (isColorAware && optimized_color_xform(dstInfo, srcInfo)) { diff --git a/src/core/SkConfig8888.h b/src/core/SkConfig8888.h index 3544cbe118..9c1ff4ab07 100644 --- a/src/core/SkConfig8888.h +++ b/src/core/SkConfig8888.h @@ -23,18 +23,6 @@ struct SkPixelInfo { SkColorTable* srcCTable = nullptr); }; -struct SkDstPixelInfo : SkPixelInfo { - void* fPixels; -}; - -struct SkSrcPixelInfo : SkPixelInfo { - const void* fPixels; - - // Guaranteed to work even if src.fPixels and dst.fPixels are the same - // (but not if they overlap partially) - bool convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const; -}; - static inline void SkRectMemcpy(void* dst, size_t dstRB, const void* src, size_t srcRB, size_t bytesPerRow, int rowCount) { SkASSERT(bytesPerRow <= dstRB); diff --git a/src/core/SkUnPreMultiplyPriv.h b/src/core/SkUnPreMultiplyPriv.h new file mode 100644 index 0000000000..073e239ed7 --- /dev/null +++ b/src/core/SkUnPreMultiplyPriv.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkUnPreMultiplyPriv_DEFINED +#define SkUnPreMultiplyPriv_DEFINED + +#include "SkColor.h" + +template <bool kSwapRB> +void SkUnpremultiplyRow(uint32_t* dst, const uint32_t* src, int count) { + const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); + + for (int i = 0; i < count; i++) { + uint32_t c = *src++; + uint8_t r, g, b, a; + if (kSwapRB) { + r = (c >> 16) & 0xFF; + g = (c >> 8) & 0xFF; + b = (c >> 0) & 0xFF; + a = (c >> 24) & 0xFF; + } else { + r = (c >> 0) & 0xFF; + g = (c >> 8) & 0xFF; + b = (c >> 16) & 0xFF; + a = (c >> 24) & 0xFF; + } + + if (0 != a && 255 != a) { + SkUnPreMultiply::Scale scale = table[a]; + r = SkUnPreMultiply::ApplyScale(scale, r); + g = SkUnPreMultiply::ApplyScale(scale, g); + b = SkUnPreMultiply::ApplyScale(scale, b); + } + + *dst++ = (r << 0) | (g << 8) | (b << 16) | (a << 24); + } +} + +#endif |