aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-02-09 16:22:39 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-02-09 22:11:13 +0000
commitc7b29089475772a51541323a93a15baad2a5feaa (patch)
tree308b5bf2b4d4b0d7bf7bd021e147028e7b7878b2 /src/core
parent5881e82060e59abe477ba34d33ada661c53d81f0 (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.cpp168
-rw-r--r--src/core/SkConfig8888.h12
-rw-r--r--src/core/SkUnPreMultiplyPriv.h43
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