Chromium Code Reviews| Index: src/opts/SkColorXform_opts.h |
| diff --git a/src/opts/SkColorXform_opts.h b/src/opts/SkColorXform_opts.h |
| index 74aa53ce7afe6880a24aee6ddfb0b268ac47c64b..01aa1e1e6ee0556ac6e7dad4d632053cdd51ce7b 100644 |
| --- a/src/opts/SkColorXform_opts.h |
| +++ b/src/opts/SkColorXform_opts.h |
| @@ -28,7 +28,7 @@ static Sk4f linear_to_2dot2(const Sk4f& x) { |
| static Sk4f linear_to_srgb(const Sk4f& x) { |
| // Approximation of the sRGB gamma curve (within 1 when scaled to 8-bit pixels). |
| - // For 0.00000f <= x < 0.00349f, 12.92 * x |
| + // For 0.00000f <= x < 0.00349f, 12.92*x |
| // For 0.00349f <= x <= 1.00000f, 0.679*(x.^0.5) + 0.423*x.^(0.25) - 0.101 |
| // Note that 0.00349 was selected because it is a point where both functions produce the |
| // same pixel value when rounded. |
| @@ -52,28 +52,35 @@ static Sk4f clamp_0_to_255(const Sk4f& x) { |
| return Sk4f::Min(Sk4f::Max(x, 0.0f), 255.0f); |
| } |
| -template <const float (&linear_from_curve)[256], Sk4f (*linear_to_curve)(const Sk4f&)> |
| +enum DstGamma { |
| + kSRGB_DstGamma, |
| + k2Dot2_DstGamma, |
| + kTable_DstGamma, |
| +}; |
| + |
| +template <DstGamma kDstGamma> |
| static void color_xform_RGB1(uint32_t* dst, const uint32_t* src, int len, |
| - const float matrix[16]) { |
| + const float* const srcTables[3], const float matrix[16], |
| + const uint8_t* const dstTables[3]) { |
| Sk4f rXgXbX = Sk4f::Load(matrix + 0), |
| rYgYbY = Sk4f::Load(matrix + 4), |
| rZgZbZ = Sk4f::Load(matrix + 8); |
| if (len >= 4) { |
| Sk4f reds, greens, blues; |
| - auto load_next_4 = [&reds, &greens, &blues, &src, &len] { |
| - reds = Sk4f{linear_from_curve[(src[0] >> 0) & 0xFF], |
| - linear_from_curve[(src[1] >> 0) & 0xFF], |
| - linear_from_curve[(src[2] >> 0) & 0xFF], |
| - linear_from_curve[(src[3] >> 0) & 0xFF]}; |
| - greens = Sk4f{linear_from_curve[(src[0] >> 8) & 0xFF], |
| - linear_from_curve[(src[1] >> 8) & 0xFF], |
| - linear_from_curve[(src[2] >> 8) & 0xFF], |
| - linear_from_curve[(src[3] >> 8) & 0xFF]}; |
| - blues = Sk4f{linear_from_curve[(src[0] >> 16) & 0xFF], |
| - linear_from_curve[(src[1] >> 16) & 0xFF], |
| - linear_from_curve[(src[2] >> 16) & 0xFF], |
| - linear_from_curve[(src[3] >> 16) & 0xFF]}; |
| + auto load_next_4 = [&reds, &greens, &blues, &src, &len, &srcTables] { |
| + reds = Sk4f{srcTables[0][(src[0] >> 0) & 0xFF], |
| + srcTables[0][(src[1] >> 0) & 0xFF], |
| + srcTables[0][(src[2] >> 0) & 0xFF], |
| + srcTables[0][(src[3] >> 0) & 0xFF]}; |
| + greens = Sk4f{srcTables[1][(src[0] >> 8) & 0xFF], |
| + srcTables[1][(src[1] >> 8) & 0xFF], |
| + srcTables[1][(src[2] >> 8) & 0xFF], |
| + srcTables[1][(src[3] >> 8) & 0xFF]}; |
| + blues = Sk4f{srcTables[2][(src[0] >> 16) & 0xFF], |
| + srcTables[2][(src[1] >> 16) & 0xFF], |
| + srcTables[2][(src[2] >> 16) & 0xFF], |
| + srcTables[2][(src[3] >> 16) & 0xFF]}; |
| src += 4; |
| len -= 4; |
| }; |
| @@ -86,20 +93,51 @@ static void color_xform_RGB1(uint32_t* dst, const uint32_t* src, int len, |
| dstBlues = rXgXbX[2]*reds + rYgYbY[2]*greens + rZgZbZ[2]*blues; |
| }; |
| - auto store_4 = [&dstReds, &dstGreens, &dstBlues, &dst] { |
| - dstReds = linear_to_curve(dstReds); |
| - dstGreens = linear_to_curve(dstGreens); |
| - dstBlues = linear_to_curve(dstBlues); |
| - |
| - dstReds = clamp_0_to_255(dstReds); |
| - dstGreens = clamp_0_to_255(dstGreens); |
| - dstBlues = clamp_0_to_255(dstBlues); |
| + auto store_4 = [&dstReds, &dstGreens, &dstBlues, &dst, &dstTables] { |
| + if (kSRGB_DstGamma == kDstGamma || k2Dot2_DstGamma == kDstGamma) { |
| + Sk4f (*linear_to_curve)(const Sk4f&) = |
| + (kSRGB_DstGamma == kDstGamma) ? linear_to_srgb : linear_to_2dot2; |
| + |
| + dstReds = linear_to_curve(dstReds); |
| + dstGreens = linear_to_curve(dstGreens); |
| + dstBlues = linear_to_curve(dstBlues); |
| + |
| + dstReds = clamp_0_to_255(dstReds); |
| + dstGreens = clamp_0_to_255(dstGreens); |
| + dstBlues = clamp_0_to_255(dstBlues); |
| + |
| + auto rgba = (SkNx_cast<int>(dstReds) ) |
| + | (SkNx_cast<int>(dstGreens) << 8) |
| + | (SkNx_cast<int>(dstBlues) << 16) |
| + | (Sk4i{ 0xFF << 24}); |
| + rgba.store(dst); |
| + } else { |
| + Sk4f scaledReds = Sk4f::Min(Sk4f::Max(1023.0f * dstReds, 0.0f), 1023.0f); |
| + Sk4f scaledGreens = Sk4f::Min(Sk4f::Max(1023.0f * dstGreens, 0.0f), 1023.0f); |
| + Sk4f scaledBlues = Sk4f::Min(Sk4f::Max(1023.0f * dstBlues, 0.0f), 1023.0f); |
| + |
| + Sk4i indicesReds = SkNx_cast<int>(scaledReds); |
|
mtklein_C
2016/07/08 13:47:24
Is there any benefit to rounding here? SkNx_cast<
msarett
2016/07/09 13:15:52
I think we should round. I'll follow up with a fi
|
| + Sk4i indicesGreens = SkNx_cast<int>(scaledGreens); |
| + Sk4i indicesBlues = SkNx_cast<int>(scaledBlues); |
| + |
| + dst[0] = dstTables[0][indicesReds [0]] |
| + | dstTables[1][indicesGreens[0]] << 8 |
| + | dstTables[2][indicesBlues [0]] << 16 |
| + | 0xFF << 24; |
| + dst[1] = dstTables[0][indicesReds [1]] |
| + | dstTables[1][indicesGreens[1]] << 8 |
| + | dstTables[2][indicesBlues [1]] << 16 |
| + | 0xFF << 24; |
| + dst[2] = dstTables[0][indicesReds [2]] |
| + | dstTables[1][indicesGreens[2]] << 8 |
| + | dstTables[2][indicesBlues [2]] << 16 |
| + | 0xFF << 24; |
| + dst[3] = dstTables[0][indicesReds [3]] |
| + | dstTables[1][indicesGreens[3]] << 8 |
| + | dstTables[2][indicesBlues [3]] << 16 |
| + | 0xFF << 24; |
| + } |
| - auto rgba = (Sk4i{(int)0xFF000000} ) |
| - | (SkNx_cast<int>(dstReds) ) |
| - | (SkNx_cast<int>(dstGreens) << 8) |
| - | (SkNx_cast<int>(dstBlues) << 16); |
| - rgba.store(dst); |
| dst += 4; |
| }; |
| @@ -117,24 +155,35 @@ static void color_xform_RGB1(uint32_t* dst, const uint32_t* src, int len, |
| while (len > 0) { |
| // Splat r,g,b across a register each. |
| - auto r = Sk4f{linear_from_curve[(*src >> 0) & 0xFF]}, |
| - g = Sk4f{linear_from_curve[(*src >> 8) & 0xFF]}, |
| - b = Sk4f{linear_from_curve[(*src >> 16) & 0xFF]}; |
| + auto r = Sk4f{srcTables[0][(*src >> 0) & 0xFF]}, |
| + g = Sk4f{srcTables[1][(*src >> 8) & 0xFF]}, |
| + b = Sk4f{srcTables[2][(*src >> 16) & 0xFF]}; |
| // Apply transformation matrix to dst gamut. |
| auto dstPixel = rXgXbX*r + rYgYbY*g + rZgZbZ*b; |
| - // Convert to dst gamma. |
| - dstPixel = linear_to_curve(dstPixel); |
| + if (kSRGB_DstGamma == kDstGamma || k2Dot2_DstGamma == kDstGamma) { |
| + Sk4f (*linear_to_curve)(const Sk4f&) = |
| + (kSRGB_DstGamma == kDstGamma) ? linear_to_srgb : linear_to_2dot2; |
| + |
| + dstPixel = linear_to_curve(dstPixel); |
| + |
| + dstPixel = clamp_0_to_255(dstPixel); |
| - // Clamp floats to byte range. |
| - dstPixel = clamp_0_to_255(dstPixel); |
| + uint32_t rgba; |
| + SkNx_cast<uint8_t>(dstPixel).store(&rgba); |
| + rgba |= 0xFF000000; |
| + *dst = rgba; |
| + } else { |
| + Sk4f scaledPixel = Sk4f::Min(Sk4f::Max(1023.0f * dstPixel, 0.0f), 1023.0f); |
| - // Convert to bytes and store to memory. |
| - uint32_t rgba; |
| - SkNx_cast<uint8_t>(dstPixel).store(&rgba); |
| - rgba |= 0xFF000000; |
| - *dst = rgba; |
| + Sk4i indices = SkNx_cast<int>(scaledPixel); |
| + |
| + *dst = dstTables[0][indices[0]] |
| + | dstTables[1][indices[1]] << 8 |
| + | dstTables[2][indices[2]] << 16 |
| + | 0xFF << 24; |
| + } |
| dst += 1; |
| src += 1; |
| @@ -142,24 +191,20 @@ static void color_xform_RGB1(uint32_t* dst, const uint32_t* src, int len, |
| } |
| } |
| -static void color_xform_RGB1_srgb_to_2dot2(uint32_t* dst, const uint32_t* src, int len, |
| - const float matrix[16]) { |
| - color_xform_RGB1<sk_linear_from_srgb, linear_to_2dot2>(dst, src, len, matrix); |
| -} |
| - |
| -static void color_xform_RGB1_2dot2_to_2dot2(uint32_t* dst, const uint32_t* src, int len, |
| - const float matrix[16]) { |
| - color_xform_RGB1<sk_linear_from_2dot2, linear_to_2dot2>(dst, src, len, matrix); |
| +static void color_xform_RGB1_to_2dot2(uint32_t* dst, const uint32_t* src, int len, |
| + const float* const srcTables[3], const float matrix[16]) { |
| + color_xform_RGB1<k2Dot2_DstGamma>(dst, src, len, srcTables, matrix, nullptr); |
| } |
| -static void color_xform_RGB1_srgb_to_srgb(uint32_t* dst, const uint32_t* src, int len, |
| - const float matrix[16]) { |
| - color_xform_RGB1<sk_linear_from_srgb, linear_to_srgb>(dst, src, len, matrix); |
| +static void color_xform_RGB1_to_srgb(uint32_t* dst, const uint32_t* src, int len, |
| + const float* const srcTables[3], const float matrix[16]) { |
| + color_xform_RGB1<kSRGB_DstGamma>(dst, src, len, srcTables, matrix, nullptr); |
| } |
| -static void color_xform_RGB1_2dot2_to_srgb(uint32_t* dst, const uint32_t* src, int len, |
| - const float matrix[16]) { |
| - color_xform_RGB1<sk_linear_from_2dot2, linear_to_srgb>(dst, src, len, matrix); |
| +static void color_xform_RGB1_to_table(uint32_t* dst, const uint32_t* src, int len, |
| + const float* const srcTables[3], const float matrix[16], |
| + const uint8_t* const dstTables[3]) { |
| + color_xform_RGB1<kTable_DstGamma>(dst, src, len, srcTables, matrix, dstTables); |
| } |
| } // namespace SK_OPTS_NS |