}
}
+static void fast_swizzle_grayalpha_to_n32_unpremul(
+ void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
+ const SkPMColor ctable[]) {
+
+ // This function must not be called if we are sampling. If we are not
+ // sampling, deltaSrc should equal bpp.
+ SkASSERT(deltaSrc == bpp);
+
+ // Note that there is no need to distinguish between RGB and BGR.
+ // Each color channel will get the same value.
+ SkOpts::grayA_to_RGBA((uint32_t*) dst, src + offset, width);
+}
+
static void swizzle_grayalpha_to_n32_premul(
void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
const SkPMColor ctable[]) {
}
}
+static void fast_swizzle_grayalpha_to_n32_premul(
+ void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
+ const SkPMColor ctable[]) {
+
+ // This function must not be called if we are sampling. If we are not
+ // sampling, deltaSrc should equal bpp.
+ SkASSERT(deltaSrc == bpp);
+
+ // Note that there is no need to distinguish between rgb and bgr.
+ // Each color channel will get the same value.
+ SkOpts::grayA_to_rgbA((uint32_t*) dst, src + offset, width);
+}
+
// kBGRX
static void swizzle_bgrx_to_n32(
if (SkCodec::kYes_ZeroInitialized == zeroInit) {
proc = &SkipLeadingGrayAlphaZerosThen
<swizzle_grayalpha_to_n32_unpremul>;
+ fastProc = &SkipLeadingGrayAlphaZerosThen
+ <fast_swizzle_grayalpha_to_n32_unpremul>;
} else {
proc = &swizzle_grayalpha_to_n32_unpremul;
+ fastProc = &fast_swizzle_grayalpha_to_n32_unpremul;
}
} else {
if (SkCodec::kYes_ZeroInitialized == zeroInit) {
proc = &SkipLeadingGrayAlphaZerosThen<swizzle_grayalpha_to_n32_premul>;
+ fastProc = &SkipLeadingGrayAlphaZerosThen
+ <fast_swizzle_grayalpha_to_n32_premul>;
} else {
proc = &swizzle_grayalpha_to_n32_premul;
+ fastProc = &fast_swizzle_grayalpha_to_n32_premul;
}
}
break;
decltype(matrix_scale_translate) matrix_scale_translate = sk_default::matrix_scale_translate;
decltype(matrix_affine) matrix_affine = sk_default::matrix_affine;
- decltype(RGBA_to_BGRA) RGBA_to_BGRA = sk_default::RGBA_to_BGRA;
- decltype(RGBA_to_rgbA) RGBA_to_rgbA = sk_default::RGBA_to_rgbA;
- decltype(RGBA_to_bgrA) RGBA_to_bgrA = sk_default::RGBA_to_bgrA;
- decltype(RGB_to_RGB1) RGB_to_RGB1 = sk_default::RGB_to_RGB1;
- decltype(RGB_to_BGR1) RGB_to_BGR1 = sk_default::RGB_to_BGR1;
- decltype(gray_to_RGB1) gray_to_RGB1 = sk_default::gray_to_RGB1;
+ decltype(RGBA_to_BGRA) RGBA_to_BGRA = sk_default::RGBA_to_BGRA;
+ decltype(RGBA_to_rgbA) RGBA_to_rgbA = sk_default::RGBA_to_rgbA;
+ decltype(RGBA_to_bgrA) RGBA_to_bgrA = sk_default::RGBA_to_bgrA;
+ decltype(RGB_to_RGB1) RGB_to_RGB1 = sk_default::RGB_to_RGB1;
+ decltype(RGB_to_BGR1) RGB_to_BGR1 = sk_default::RGB_to_BGR1;
+ decltype(gray_to_RGB1) gray_to_RGB1 = sk_default::gray_to_RGB1;
+ decltype(grayA_to_RGBA) grayA_to_RGBA = sk_default::grayA_to_RGBA;
+ decltype(grayA_to_rgbA) grayA_to_rgbA = sk_default::grayA_to_rgbA;
// Each Init_foo() is defined in src/opts/SkOpts_foo.cpp.
void Init_ssse3();
RGBA_to_bgrA, // i.e. swap RB and premultiply
RGB_to_RGB1, // i.e. insert an opaque alpha
RGB_to_BGR1, // i.e. swap RB and insert an opaque alpha
- gray_to_RGB1; // i.e. set color channels to same value + an opaque alpha
+ gray_to_RGB1, // i.e. expand to color channels + an opaque alpha
+ grayA_to_RGBA, // i.e. expand to color channels
+ grayA_to_rgbA; // i.e. expand to color channels and premultiply
}
#endif//SkOpts_DEFINED
matrix_scale_translate = sk_neon::matrix_scale_translate;
matrix_affine = sk_neon::matrix_affine;
- RGBA_to_BGRA = sk_neon::RGBA_to_BGRA;
- RGBA_to_rgbA = sk_neon::RGBA_to_rgbA;
- RGBA_to_bgrA = sk_neon::RGBA_to_bgrA;
- RGB_to_RGB1 = sk_neon::RGB_to_RGB1;
- RGB_to_BGR1 = sk_neon::RGB_to_BGR1;
- gray_to_RGB1 = sk_neon::gray_to_RGB1;
+ RGBA_to_BGRA = sk_neon::RGBA_to_BGRA;
+ RGBA_to_rgbA = sk_neon::RGBA_to_rgbA;
+ RGBA_to_bgrA = sk_neon::RGBA_to_bgrA;
+ RGB_to_RGB1 = sk_neon::RGB_to_RGB1;
+ RGB_to_BGR1 = sk_neon::RGB_to_BGR1;
+ gray_to_RGB1 = sk_neon::gray_to_RGB1;
+ grayA_to_RGBA = sk_neon::grayA_to_RGBA;
+ grayA_to_rgbA = sk_neon::grayA_to_rgbA;
}
}
blit_mask_d32_a8 = sk_ssse3::blit_mask_d32_a8;
color_cube_filter_span = sk_ssse3::color_cube_filter_span;
- RGBA_to_BGRA = sk_ssse3::RGBA_to_BGRA;
- RGBA_to_rgbA = sk_ssse3::RGBA_to_rgbA;
- RGBA_to_bgrA = sk_ssse3::RGBA_to_bgrA;
- RGB_to_RGB1 = sk_ssse3::RGB_to_RGB1;
- RGB_to_BGR1 = sk_ssse3::RGB_to_BGR1;
- gray_to_RGB1 = sk_ssse3::gray_to_RGB1;
+ RGBA_to_BGRA = sk_ssse3::RGBA_to_BGRA;
+ RGBA_to_rgbA = sk_ssse3::RGBA_to_rgbA;
+ RGBA_to_bgrA = sk_ssse3::RGBA_to_bgrA;
+ RGB_to_RGB1 = sk_ssse3::RGB_to_RGB1;
+ RGB_to_BGR1 = sk_ssse3::RGB_to_BGR1;
+ gray_to_RGB1 = sk_ssse3::gray_to_RGB1;
+ grayA_to_RGBA = sk_ssse3::grayA_to_RGBA;
+ grayA_to_rgbA = sk_ssse3::grayA_to_rgbA;
}
}
}
}
+static void grayA_to_RGBA_portable(uint32_t dst[], const void* vsrc, int count) {
+ const uint8_t* src = (const uint8_t*)vsrc;
+ for (int i = 0; i < count; i++) {
+ uint8_t g = src[0],
+ a = src[1];
+ src += 2;
+ dst[i] = (uint32_t)a << 24
+ | (uint32_t)g << 16
+ | (uint32_t)g << 8
+ | (uint32_t)g << 0;
+ }
+}
+
+static void grayA_to_rgbA_portable(uint32_t dst[], const void* vsrc, int count) {
+ const uint8_t* src = (const uint8_t*)vsrc;
+ for (int i = 0; i < count; i++) {
+ uint8_t g = src[0],
+ a = src[1];
+ src += 2;
+ g = (g*a+127)/255;
+ dst[i] = (uint32_t)a << 24
+ | (uint32_t)g << 16
+ | (uint32_t)g << 8
+ | (uint32_t)g << 0;
+ }
+}
+
#if defined(SK_ARM_HAS_NEON)
// Rounded divide by 255, (x + 127) / 255
gray_to_RGB1_portable(dst, src, count);
}
+template <bool kPremul>
+static void expand_grayA(uint32_t dst[], const void* vsrc, int count) {
+ const uint8_t* src = (const uint8_t*) vsrc;
+ while (count >= 16) {
+ // Load 16 pixels.
+ uint8x16x2_t ga = vld2q_u8(src);
+
+ // Premultiply if requested.
+ if (kPremul) {
+ ga.val[0] = vcombine_u8(
+ scale(vget_low_u8(ga.val[0]), vget_low_u8(ga.val[1])),
+ scale(vget_high_u8(ga.val[0]), vget_high_u8(ga.val[1])));
+ }
+
+ // Set each of the color channels.
+ uint8x16x4_t rgba;
+ rgba.val[0] = ga.val[0];
+ rgba.val[1] = ga.val[0];
+ rgba.val[2] = ga.val[0];
+ rgba.val[3] = ga.val[1];
+
+ // Store 16 pixels.
+ vst4q_u8((uint8_t*) dst, rgba);
+ src += 16*2;
+ dst += 16;
+ count -= 16;
+ }
+
+ if (count >= 8) {
+ // Load 8 pixels.
+ uint8x8x2_t ga = vld2_u8(src);
+
+ // Premultiply if requested.
+ if (kPremul) {
+ ga.val[0] = scale(ga.val[0], ga.val[1]);
+ }
+
+ // Set each of the color channels.
+ uint8x8x4_t rgba;
+ rgba.val[0] = ga.val[0];
+ rgba.val[1] = ga.val[0];
+ rgba.val[2] = ga.val[0];
+ rgba.val[3] = ga.val[1];
+
+ // Store 8 pixels.
+ vst4_u8((uint8_t*) dst, rgba);
+ src += 8*2;
+ dst += 8;
+ count -= 8;
+ }
+
+ auto proc = kPremul ? grayA_to_rgbA_portable : grayA_to_RGBA_portable;
+ proc(dst, src, count);
+}
+
+static void grayA_to_RGBA(uint32_t dst[], const void* src, int count) {
+ expand_grayA<false>(dst, src, count);
+}
+
+static void grayA_to_rgbA(uint32_t dst[], const void* src, int count) {
+ expand_grayA<true>(dst, src, count);
+}
+
#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
template <bool kSwapRB>
gray_to_RGB1_portable(dst, src, count);
}
+static void grayA_to_RGBA(uint32_t dst[], const void* src, int count) {
+ grayA_to_RGBA_portable(dst, src, count);
+}
+
+static void grayA_to_rgbA(uint32_t dst[], const void* src, int count) {
+ grayA_to_rgbA_portable(dst, src, count);
+}
+
#else
static void RGBA_to_rgbA(uint32_t* dst, const void* src, int count) {
gray_to_RGB1_portable(dst, src, count);
}
+static void grayA_to_RGBA(uint32_t dst[], const void* src, int count) {
+ grayA_to_RGBA_portable(dst, src, count);
+}
+
+static void grayA_to_rgbA(uint32_t dst[], const void* src, int count) {
+ grayA_to_rgbA_portable(dst, src, count);
+}
+
#endif
}