Pixel conversion refactors: use raster pipeline for 565 and gray

I'm trying not to do too much in one CL.  But, in general, I hope
to drop (non-performance important/optimized) special cases and
use the pipeline.

BUG=skia:

CQ_INCLUDE_TRYBOTS=skia.primary:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD

Change-Id: I724d3982f1467f6232371360b860484f13b1ede8
Reviewed-on: https://skia-review.googlesource.com/8271
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Matt Sarett <msarett@google.com>
This commit is contained in:
Matt Sarett 2017-02-09 13:50:45 -05:00 committed by Skia Commit-Bot
parent a04bb45b23
commit 5101448ebb
4 changed files with 48 additions and 69 deletions

View File

@ -32,59 +32,44 @@ static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& src
return false;
}
return !dstInfo.colorSpace() || !srcInfo.colorSpace() ||
return !dstInfo.colorSpace() ||
SkColorSpace::Equals(dstInfo.colorSpace(), srcInfo.colorSpace());
}
// For now disable 565 in the pipeline. Its (higher) quality is so different its too much to
// rebase (for now)
//
//#define PIPELINE_HANDLES_565
static bool is_srgb(const SkImageInfo& info) {
return info.colorSpace() && info.colorSpace()->gammaCloseToSRGB();
}
// 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,
SkColorTable* ctable) {
SkASSERT(srcInfo.width() == dstInfo.width());
SkASSERT(srcInfo.height() == dstInfo.height());
bool src_srgb = is_srgb(srcInfo);
const bool dst_srgb = is_srgb(dstInfo);
if (!dstInfo.colorSpace()) {
src_srgb = false; // untagged dst means ignore tags on src
}
bool isColorAware) {
SkRasterPipeline pipeline;
switch (srcInfo.colorType()) {
case kRGBA_8888_SkColorType:
pipeline.append(SkRasterPipeline::load_8888, &srcRow);
break;
case kBGRA_8888_SkColorType:
pipeline.append(SkRasterPipeline::load_8888, &srcRow);
if (src_srgb) {
pipeline.append_from_srgb(srcInfo.alphaType());
}
if (kBGRA_8888_SkColorType == srcInfo.colorType()) {
pipeline.append(SkRasterPipeline::swap_rb);
}
pipeline.append(SkRasterPipeline::swap_rb);
break;
#ifdef PIPELINE_HANDLES_565
case kRGB_565_SkColorType:
pipeline.append(SkRasterPipeline::load_565, &srcRow);
break;
#endif
case kRGBA_F16_SkColorType:
pipeline.append(SkRasterPipeline::load_f16, &srcRow);
break;
case kGray_8_SkColorType:
pipeline.append(SkRasterPipeline::load_g8, &srcRow);
break;
default:
return false; // src colortype unsupported
return false;
}
if (isColorAware && srcInfo.gammaCloseToSRGB()) {
pipeline.append_from_srgb(srcInfo.alphaType());
}
float matrix[12];
if (!append_gamut_transform(&pipeline, matrix, srcInfo.colorSpace(), dstInfo.colorSpace())) {
return false;
if (isColorAware) {
SkAssertResult(append_gamut_transform(&pipeline, matrix, srcInfo.colorSpace(),
dstInfo.colorSpace()));
}
SkAlphaType sat = srcInfo.alphaType();
@ -95,27 +80,26 @@ static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_
pipeline.append(SkRasterPipeline::premul);
}
if (isColorAware && dstInfo.gammaCloseToSRGB()) {
pipeline.append(SkRasterPipeline::to_srgb);
}
switch (dstInfo.colorType()) {
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
if (kBGRA_8888_SkColorType == dstInfo.colorType()) {
pipeline.append(SkRasterPipeline::swap_rb);
}
if (dst_srgb) {
pipeline.append(SkRasterPipeline::to_srgb);
}
pipeline.append(SkRasterPipeline::store_8888, &dstRow);
break;
#ifdef PIPELINE_HANDLES_565
case kBGRA_8888_SkColorType:
pipeline.append(SkRasterPipeline::swap_rb);
pipeline.append(SkRasterPipeline::store_8888, &dstRow);
break;
case kRGB_565_SkColorType:
pipeline.append(SkRasterPipeline::store_565, &dstRow);
break;
#endif
case kRGBA_F16_SkColorType:
pipeline.append(SkRasterPipeline::store_f16, &dstRow);
break;
default:
return false; // dst colortype unsupported
return false;
}
auto p = pipeline.compile();
@ -124,8 +108,8 @@ static bool copy_pipeline_pixels(const SkImageInfo& dstInfo, void* dstRow, size_
p(0,srcInfo.width());
// The pipeline has pointers to srcRow and dstRow, so we just need to update them in the
// loop to move between rows of src/dst.
srcRow = (const char*)srcRow + srcRB;
dstRow = (char*)dstRow + dstRB;
dstRow = SkTAddOffset<void>(dstRow, dstRB);
srcRow = SkTAddOffset<const void>(srcRow, srcRB);
}
return true;
}
@ -231,19 +215,6 @@ bool SkSrcPixelInfo::convertPixelsTo(SkDstPixelInfo* dst, int width, int height)
return true;
}
static void copy_g8_to_32(void* dst, size_t dstRB, const void* src, size_t srcRB, int w, int h) {
uint32_t* dst32 = (uint32_t*)dst;
const uint8_t* src8 = (const uint8_t*)src;
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
dst32[x] = SkPackARGB32(0xFF, src8[x], src8[x], src8[x]);
}
dst32 = (uint32_t*)((char*)dst32 + dstRB);
src8 += srcRB;
}
}
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;
@ -384,7 +355,8 @@ bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t
return true;
}
const bool isColorAware = srcInfo.colorSpace() && dstInfo.colorSpace();
const bool isColorAware = dstInfo.colorSpace();
SkASSERT(srcInfo.colorSpace() || !isColorAware);
// Handle fancy alpha swizzling if both are ARGB32
if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel() && !isColorAware) {
@ -413,11 +385,6 @@ bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t
* are supported.
*/
if (kGray_8_SkColorType == srcInfo.colorType() && 4 == dstInfo.bytesPerPixel()) {
copy_g8_to_32(dstPixels, dstRB, srcPixels, srcRB, width, height);
return true;
}
if (kAlpha_8_SkColorType == dstInfo.colorType() &&
extract_alpha(dstPixels, dstRB, srcPixels, srcRB, srcInfo, ctable)) {
return true;

View File

@ -39,10 +39,11 @@ 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.
* We do not convert to kGray8 when the |src| is not kGray8. 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.
* We will not convert to kIndex8 when the |src| is not kIndex8 in the same color space
* (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.
* We will not convert from kAlpha8 when the |dst| is not kAlpha8. This would require
* inventing color information.
* We will not convert to kOpaque when the |src| is not kOpaque. This could be
@ -58,11 +59,15 @@ static inline bool SkImageInfoValidConversion(const SkImageInfo& dst, const SkIm
return false;
}
if (kIndex_8_SkColorType == dst.colorType() && kIndex_8_SkColorType != src.colorType()) {
if (kIndex_8_SkColorType == dst.colorType() && kIndex_8_SkColorType != src.colorType() &&
dst.colorSpace() && !SkColorSpace::Equals(dst.colorSpace(), src.colorSpace()))
{
return false;
}
if (kGray_8_SkColorType == dst.colorType() && kGray_8_SkColorType != src.colorType()) {
if (kGray_8_SkColorType == dst.colorType() && kGray_8_SkColorType != src.colorType() &&
dst.colorSpace() && !SkColorSpace::Equals(dst.colorSpace(), src.colorSpace()))
{
return false;
}

View File

@ -66,6 +66,7 @@
M(from_2dot2) M(to_2dot2) \
M(constant_color) M(seed_shader) M(store_f32) \
M(load_a8) M(store_a8) \
M(load_g8) \
M(load_565) M(store_565) \
M(load_f16) M(store_f16) \
M(load_8888) M(store_8888) \

View File

@ -520,6 +520,12 @@ STAGE_CTX(store_a8, uint8_t**) {
store(tail, SkNx_cast<uint8_t>(SkNf_round(255.0f, a)), ptr);
}
STAGE_CTX(load_g8, const uint8_t**) {
auto ptr = *ctx + x;
r = g = b = SkNf_from_byte(load(tail, ptr));
a = 1.0f;
}
STAGE_CTX(load_565, const uint16_t**) {
auto ptr = *ctx + x;
from_565(load(tail, ptr), &r,&g,&b);