Use RasterPipeline to support full precision on 16-bit RGBA pngs
Reland of Original Change: https://skia-review.googlesource.com/6260 CQ_INCLUDE_TRYBOTS=skia.primary:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD Change-Id: I809984dd9af225103bfbe83492a17c19da7c5e40 Reviewed-on: https://skia-review.googlesource.com/6980 Reviewed-by: Matt Sarett <msarett@google.com> Commit-Queue: Matt Sarett <msarett@google.com>
This commit is contained in:
parent
ac42aebb7b
commit
379938e47b
@ -27,8 +27,12 @@ public:
|
||||
enum ColorFormat {
|
||||
kRGBA_8888_ColorFormat,
|
||||
kBGRA_8888_ColorFormat,
|
||||
kRGBA_F16_ColorFormat,
|
||||
kRGBA_F32_ColorFormat,
|
||||
|
||||
// Unsigned, big-endian, 16-bit integer
|
||||
kRGBA_U16_BE_ColorFormat, // Src only
|
||||
|
||||
kRGBA_F16_ColorFormat, // Dst only
|
||||
kRGBA_F32_ColorFormat, // Dst only
|
||||
};
|
||||
|
||||
/**
|
||||
@ -42,7 +46,6 @@ public:
|
||||
* @param len Number of pixels in the buffers
|
||||
* @param dstColorFormat Describes color format of |dst|
|
||||
* @param srcColorFormat Describes color format of |src|
|
||||
* Must be kRGBA_8888 or kBGRA_8888
|
||||
* @param alphaType Describes alpha properties of the |dst| (and |src|)
|
||||
* kUnpremul preserves input alpha values
|
||||
* kPremul performs a premultiplication and also preserves alpha values
|
||||
|
@ -1 +1 @@
|
||||
17
|
||||
18
|
File diff suppressed because it is too large
Load Diff
@ -419,16 +419,28 @@ void SkPngCodec::allocateStorage(const SkImageInfo& dstInfo) {
|
||||
// be created later if we are sampling. We'll go ahead and allocate
|
||||
// enough memory to swizzle if necessary.
|
||||
case kSwizzleColor_XformMode: {
|
||||
const size_t colorXformBytes = dstInfo.width() * sizeof(uint32_t);
|
||||
const size_t bpp = (this->getEncodedInfo().bitsPerPixel() > 32) ? 8 : 4;
|
||||
const size_t colorXformBytes = dstInfo.width() * bpp;
|
||||
fStorage.reset(colorXformBytes);
|
||||
fColorXformSrcRow = (uint32_t*) fStorage.get();
|
||||
fColorXformSrcRow = fStorage.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SkColorSpaceXform::ColorFormat png_select_xform_format(const SkEncodedInfo& info) {
|
||||
// We always use kRGBA because color PNGs are always RGB or RGBA.
|
||||
// TODO (msarett): Support kRGB_U16 inputs as well.
|
||||
if (16 == info.bitsPerComponent() && SkEncodedInfo::kRGBA_Color == info.color()) {
|
||||
return SkColorSpaceXform::kRGBA_U16_BE_ColorFormat;
|
||||
}
|
||||
|
||||
return SkColorSpaceXform::kRGBA_8888_ColorFormat;
|
||||
}
|
||||
|
||||
void SkPngCodec::applyXformRow(void* dst, const void* src) {
|
||||
const SkColorSpaceXform::ColorFormat srcColorFormat = select_xform_format(kXformSrcColorType);
|
||||
const SkColorSpaceXform::ColorFormat srcColorFormat =
|
||||
png_select_xform_format(this->getEncodedInfo());
|
||||
switch (fXformMode) {
|
||||
case kSwizzleOnly_XformMode:
|
||||
fSwizzler->swizzle(dst, (const uint8_t*) src);
|
||||
@ -1073,10 +1085,10 @@ bool SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& opt
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the image is 32-bit RGBA and we have a color xform, we can skip the swizzler.
|
||||
if (this->colorXform() && SkEncodedInfo::kRGBA_Color == this->getEncodedInfo().color() &&
|
||||
8 == this->getEncodedInfo().bitsPerComponent() && !options.fSubset)
|
||||
{
|
||||
// If the image is RGBA and we have a color xform, we can skip the swizzler.
|
||||
const bool skipFormatConversion = this->colorXform() &&
|
||||
SkEncodedInfo::kRGBA_Color == this->getEncodedInfo().color();
|
||||
if (skipFormatConversion && !options.fSubset) {
|
||||
fXformMode = kColorOnly_XformMode;
|
||||
return true;
|
||||
}
|
||||
@ -1090,7 +1102,7 @@ bool SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& opt
|
||||
// Copy the color table to the client if they request kIndex8 mode.
|
||||
copy_color_table(dstInfo, fColorTable.get(), ctable, ctableCount);
|
||||
|
||||
this->initializeSwizzler(dstInfo, options);
|
||||
this->initializeSwizzler(dstInfo, options, skipFormatConversion);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1113,7 +1125,8 @@ void SkPngCodec::initializeXformParams() {
|
||||
}
|
||||
}
|
||||
|
||||
void SkPngCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options) {
|
||||
void SkPngCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options,
|
||||
bool skipFormatConversion) {
|
||||
SkImageInfo swizzlerInfo = dstInfo;
|
||||
Options swizzlerOptions = options;
|
||||
fXformMode = kSwizzleOnly_XformMode;
|
||||
@ -1135,7 +1148,7 @@ void SkPngCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& o
|
||||
|
||||
const SkPMColor* colors = get_color_ptr(fColorTable.get());
|
||||
fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(), colors, swizzlerInfo,
|
||||
swizzlerOptions));
|
||||
swizzlerOptions, nullptr, skipFormatConversion));
|
||||
SkASSERT(fSwizzler);
|
||||
}
|
||||
|
||||
@ -1144,7 +1157,7 @@ SkSampler* SkPngCodec::getSampler(bool createIfNecessary) {
|
||||
return fSwizzler.get();
|
||||
}
|
||||
|
||||
this->initializeSwizzler(this->dstInfo(), this->options());
|
||||
this->initializeSwizzler(this->dstInfo(), this->options(), true);
|
||||
return fSwizzler.get();
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ protected:
|
||||
sk_sp<SkColorTable> fColorTable; // May be unpremul.
|
||||
std::unique_ptr<SkSwizzler> fSwizzler;
|
||||
SkAutoTMalloc<uint8_t> fStorage;
|
||||
uint32_t* fColorXformSrcRow;
|
||||
void* fColorXformSrcRow;
|
||||
const int fBitDepth;
|
||||
|
||||
private:
|
||||
@ -119,7 +119,7 @@ private:
|
||||
// Helper to set up swizzler, color xforms, and color table. Also calls png_read_update_info.
|
||||
bool initializeXforms(const SkImageInfo& dstInfo, const Options&, SkPMColor* colorPtr,
|
||||
int* colorCount);
|
||||
void initializeSwizzler(const SkImageInfo& dstInfo, const Options&);
|
||||
void initializeSwizzler(const SkImageInfo& dstInfo, const Options&, bool skipFormatConversion);
|
||||
void allocateStorage(const SkImageInfo& dstInfo);
|
||||
void destroyReadStruct();
|
||||
|
||||
|
@ -51,6 +51,16 @@ static void sample4(void* dst, const uint8_t* src, int width, int bpp, int delta
|
||||
}
|
||||
}
|
||||
|
||||
static void sample8(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
|
||||
const SkPMColor ctable[]) {
|
||||
src += offset;
|
||||
uint64_t* dst64 = (uint64_t*) dst;
|
||||
for (int x = 0; x < width; x++) {
|
||||
dst64[x] = *((const uint64_t*) src);
|
||||
src += deltaSrc;
|
||||
}
|
||||
}
|
||||
|
||||
// kBit
|
||||
// These routines exclusively choose between white and black
|
||||
|
||||
@ -796,7 +806,10 @@ SkSwizzler* SkSwizzler::CreateSwizzler(const SkEncodedInfo& encodedInfo,
|
||||
|
||||
RowProc fastProc = nullptr;
|
||||
RowProc proc = nullptr;
|
||||
int srcBPP;
|
||||
const int dstBPP = SkColorTypeBytesPerPixel(dstInfo.colorType());
|
||||
if (skipFormatConversion) {
|
||||
srcBPP = dstBPP;
|
||||
switch (dstInfo.colorType()) {
|
||||
case kGray_8_SkColorType:
|
||||
proc = &sample1;
|
||||
@ -808,7 +821,14 @@ SkSwizzler* SkSwizzler::CreateSwizzler(const SkEncodedInfo& encodedInfo,
|
||||
break;
|
||||
case kRGBA_8888_SkColorType:
|
||||
case kBGRA_8888_SkColorType:
|
||||
proc = &sample4;
|
||||
SkASSERT(16 == encodedInfo.bitsPerComponent() ||
|
||||
8 == encodedInfo.bitsPerComponent());
|
||||
if (8 == encodedInfo.bitsPerComponent()) {
|
||||
proc = &sample4;
|
||||
} else {
|
||||
srcBPP = 8;
|
||||
proc = &sample8;
|
||||
}
|
||||
fastProc = ©
|
||||
break;
|
||||
default:
|
||||
@ -1137,13 +1157,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(const SkEncodedInfo& encodedInfo,
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int srcBPP;
|
||||
const int dstBPP = SkColorTypeBytesPerPixel(dstInfo.colorType());
|
||||
if (skipFormatConversion) {
|
||||
srcBPP = dstBPP;
|
||||
} else {
|
||||
// Store bpp in bytes if it is an even multiple, otherwise use bits
|
||||
uint8_t bitsPerPixel = encodedInfo.bitsPerPixel();
|
||||
srcBPP = SkIsAlign8(bitsPerPixel) ? bitsPerPixel / 8 : bitsPerPixel;
|
||||
|
@ -327,110 +327,14 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace
|
||||
|
||||
switch (csm) {
|
||||
case kNone_ColorSpaceMatch:
|
||||
switch (dstSpaceXYZ->gammaNamed()) {
|
||||
case kSRGB_SkGammaNamed:
|
||||
if (srcSpaceXYZ->gammaIsLinear()) {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kLinear_SrcGamma, kSRGB_DstGamma, kNone_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
} else {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, kSRGB_DstGamma, kNone_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
}
|
||||
case k2Dot2Curve_SkGammaNamed:
|
||||
if (srcSpaceXYZ->gammaIsLinear()) {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kLinear_SrcGamma, k2Dot2_DstGamma, kNone_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
} else {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, k2Dot2_DstGamma, kNone_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
}
|
||||
case kLinear_SkGammaNamed:
|
||||
if (srcSpaceXYZ->gammaIsLinear()) {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kLinear_SrcGamma, kLinear_DstGamma, kNone_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
} else {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, kLinear_DstGamma, kNone_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
}
|
||||
default:
|
||||
if (srcSpaceXYZ->gammaIsLinear()) {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kLinear_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
} else {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
}
|
||||
}
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kNone_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
case kGamut_ColorSpaceMatch:
|
||||
switch (dstSpaceXYZ->gammaNamed()) {
|
||||
case kSRGB_SkGammaNamed:
|
||||
if (srcSpaceXYZ->gammaIsLinear()) {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kLinear_SrcGamma, kSRGB_DstGamma, kGamut_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
} else {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, kSRGB_DstGamma, kGamut_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
}
|
||||
case k2Dot2Curve_SkGammaNamed:
|
||||
if (srcSpaceXYZ->gammaIsLinear()) {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kLinear_SrcGamma, k2Dot2_DstGamma, kGamut_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
} else {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, k2Dot2_DstGamma, kGamut_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
}
|
||||
case kLinear_SkGammaNamed:
|
||||
if (srcSpaceXYZ->gammaIsLinear()) {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kLinear_SrcGamma, kLinear_DstGamma, kGamut_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
} else {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, kLinear_DstGamma, kGamut_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
}
|
||||
default:
|
||||
if (srcSpaceXYZ->gammaIsLinear()) {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kLinear_SrcGamma, kTable_DstGamma, kGamut_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
} else {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, kTable_DstGamma, kGamut_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
}
|
||||
}
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kGamut_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
case kFull_ColorSpaceMatch:
|
||||
switch (dstSpaceXYZ->gammaNamed()) {
|
||||
case kSRGB_SkGammaNamed:
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, kSRGB_DstGamma, kFull_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
case k2Dot2Curve_SkGammaNamed:
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, k2Dot2_DstGamma, kFull_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
case kLinear_SkGammaNamed:
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kLinear_SrcGamma, kLinear_DstGamma, kFull_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
default:
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, kTable_DstGamma, kFull_ColorSpaceMatch>
|
||||
(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
}
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kFull_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ));
|
||||
default:
|
||||
SkASSERT(false);
|
||||
return nullptr;
|
||||
@ -1065,8 +969,8 @@ static AI int num_tables(SkColorSpace_XYZ* space) {
|
||||
}
|
||||
}
|
||||
|
||||
template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
|
||||
SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
template <ColorSpaceMatch kCSM>
|
||||
SkColorSpaceXform_XYZ<kCSM>
|
||||
::SkColorSpaceXform_XYZ(SkColorSpace_XYZ* srcSpace, const SkMatrix44& srcToDst,
|
||||
SkColorSpace_XYZ* dstSpace)
|
||||
{
|
||||
@ -1093,6 +997,29 @@ SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
|
||||
const int numDstTables = num_tables(dstSpace);
|
||||
dstSpace->toDstGammaTables(fDstGammaTables, &fDstStorage, numDstTables);
|
||||
|
||||
if (srcSpace->gammaIsLinear()) {
|
||||
fSrcGamma = kLinear_SrcGamma;
|
||||
} else if (kSRGB_SkGammaNamed == srcSpace->gammaNamed()) {
|
||||
fSrcGamma = kSRGB_SrcGamma;
|
||||
} else {
|
||||
fSrcGamma = kTable_SrcGamma;
|
||||
}
|
||||
|
||||
switch (dstSpace->gammaNamed()) {
|
||||
case kSRGB_SkGammaNamed:
|
||||
fDstGamma = kSRGB_DstGamma;
|
||||
break;
|
||||
case k2Dot2Curve_SkGammaNamed:
|
||||
fDstGamma = k2Dot2_DstGamma;
|
||||
break;
|
||||
case kLinear_SkGammaNamed:
|
||||
fDstGamma = kLinear_DstGamma;
|
||||
break;
|
||||
default:
|
||||
fDstGamma = kTable_DstGamma;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -1119,27 +1046,28 @@ static AI bool apply_set_alpha(void* dst, const void* src, int len, SkAlphaType
|
||||
}
|
||||
}
|
||||
|
||||
template <SrcGamma kSrc, DstFormat kDst, ColorSpaceMatch kCSM>
|
||||
template <DstFormat kDst, ColorSpaceMatch kCSM>
|
||||
static AI bool apply_set_src(void* dst, const void* src, int len, SkAlphaType alphaType,
|
||||
const float* const srcTables[3], const float matrix[13],
|
||||
const uint8_t* const dstTables[3],
|
||||
SkColorSpaceXform::ColorFormat srcColorFormat) {
|
||||
SkColorSpaceXform::ColorFormat srcColorFormat,
|
||||
SrcGamma srcGamma) {
|
||||
switch (srcColorFormat) {
|
||||
case SkColorSpaceXform::kRGBA_8888_ColorFormat:
|
||||
switch (kSrc) {
|
||||
switch (srcGamma) {
|
||||
case kLinear_SrcGamma:
|
||||
return apply_set_alpha<kRGBA_8888_Linear_SrcFormat, kDst, kCSM>
|
||||
(dst, src, len, alphaType, nullptr, matrix, dstTables);
|
||||
case kTable_SrcGamma:
|
||||
default:
|
||||
return apply_set_alpha<kRGBA_8888_Table_SrcFormat, kDst, kCSM>
|
||||
(dst, src, len, alphaType, srcTables, matrix, dstTables);
|
||||
}
|
||||
case SkColorSpaceXform::kBGRA_8888_ColorFormat:
|
||||
switch (kSrc) {
|
||||
switch (srcGamma) {
|
||||
case kLinear_SrcGamma:
|
||||
return apply_set_alpha<kBGRA_8888_Linear_SrcFormat, kDst, kCSM>
|
||||
(dst, src, len, alphaType, nullptr, matrix, dstTables);
|
||||
case kTable_SrcGamma:
|
||||
default:
|
||||
return apply_set_alpha<kBGRA_8888_Table_SrcFormat, kDst, kCSM>
|
||||
(dst, src, len, alphaType, srcTables, matrix, dstTables);
|
||||
}
|
||||
@ -1150,8 +1078,8 @@ static AI bool apply_set_src(void* dst, const void* src, int len, SkAlphaType al
|
||||
|
||||
#undef AI
|
||||
|
||||
template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
|
||||
bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
template <ColorSpaceMatch kCSM>
|
||||
bool SkColorSpaceXform_XYZ<kCSM>
|
||||
::onApply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat, const void* src,
|
||||
int len, SkAlphaType alphaType) const
|
||||
{
|
||||
@ -1176,55 +1104,55 @@ bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
}
|
||||
}
|
||||
|
||||
if (kRGBA_F32_ColorFormat == dstColorFormat) {
|
||||
if (kRGBA_F32_ColorFormat == dstColorFormat || kRGBA_U16_BE_ColorFormat == srcColorFormat) {
|
||||
return this->applyPipeline(dstColorFormat, dst, srcColorFormat, src, len, alphaType);
|
||||
}
|
||||
|
||||
switch (dstColorFormat) {
|
||||
case kRGBA_8888_ColorFormat:
|
||||
switch (kDst) {
|
||||
switch (fDstGamma) {
|
||||
case kLinear_DstGamma:
|
||||
return apply_set_src<kSrc, kRGBA_8888_Linear_DstFormat, kCSM>
|
||||
return apply_set_src<kRGBA_8888_Linear_DstFormat, kCSM>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
|
||||
srcColorFormat);
|
||||
srcColorFormat, fSrcGamma);
|
||||
case kSRGB_DstGamma:
|
||||
return apply_set_src<kSrc, kRGBA_8888_SRGB_DstFormat, kCSM>
|
||||
return apply_set_src<kRGBA_8888_SRGB_DstFormat, kCSM>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
|
||||
srcColorFormat);
|
||||
srcColorFormat, fSrcGamma);
|
||||
case k2Dot2_DstGamma:
|
||||
return apply_set_src<kSrc, kRGBA_8888_2Dot2_DstFormat, kCSM>
|
||||
return apply_set_src<kRGBA_8888_2Dot2_DstFormat, kCSM>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
|
||||
srcColorFormat);
|
||||
srcColorFormat, fSrcGamma);
|
||||
case kTable_DstGamma:
|
||||
return apply_set_src<kSrc, kRGBA_8888_Table_DstFormat, kCSM>
|
||||
return apply_set_src<kRGBA_8888_Table_DstFormat, kCSM>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables,
|
||||
srcColorFormat);
|
||||
srcColorFormat, fSrcGamma);
|
||||
}
|
||||
case kBGRA_8888_ColorFormat:
|
||||
switch (kDst) {
|
||||
switch (fDstGamma) {
|
||||
case kLinear_DstGamma:
|
||||
return apply_set_src<kSrc, kBGRA_8888_Linear_DstFormat, kCSM>
|
||||
return apply_set_src<kBGRA_8888_Linear_DstFormat, kCSM>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
|
||||
srcColorFormat);
|
||||
srcColorFormat, fSrcGamma);
|
||||
case kSRGB_DstGamma:
|
||||
return apply_set_src<kSrc, kBGRA_8888_SRGB_DstFormat, kCSM>
|
||||
return apply_set_src<kBGRA_8888_SRGB_DstFormat, kCSM>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
|
||||
srcColorFormat);
|
||||
srcColorFormat, fSrcGamma);
|
||||
case k2Dot2_DstGamma:
|
||||
return apply_set_src<kSrc, kBGRA_8888_2Dot2_DstFormat, kCSM>
|
||||
return apply_set_src<kBGRA_8888_2Dot2_DstFormat, kCSM>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
|
||||
srcColorFormat);
|
||||
srcColorFormat, fSrcGamma);
|
||||
case kTable_DstGamma:
|
||||
return apply_set_src<kSrc, kBGRA_8888_Table_DstFormat, kCSM>
|
||||
return apply_set_src<kBGRA_8888_Table_DstFormat, kCSM>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables,
|
||||
srcColorFormat);
|
||||
srcColorFormat, fSrcGamma);
|
||||
}
|
||||
case kRGBA_F16_ColorFormat:
|
||||
switch (kDst) {
|
||||
switch (fDstGamma) {
|
||||
case kLinear_DstGamma:
|
||||
return apply_set_src<kSrc, kF16_Linear_DstFormat, kCSM>
|
||||
return apply_set_src<kF16_Linear_DstFormat, kCSM>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
|
||||
srcColorFormat);
|
||||
srcColorFormat, fSrcGamma);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -1242,8 +1170,8 @@ bool SkColorSpaceXform::apply(ColorFormat dstColorFormat, void* dst, ColorFormat
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
|
||||
bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
template <ColorSpaceMatch kCSM>
|
||||
bool SkColorSpaceXform_XYZ<kCSM>
|
||||
::applyPipeline(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat,
|
||||
const void* src, int len, SkAlphaType alphaType) const {
|
||||
SkRasterPipeline pipeline;
|
||||
@ -1251,10 +1179,10 @@ bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
LoadTablesContext loadTables;
|
||||
switch (srcColorFormat) {
|
||||
case kRGBA_8888_ColorFormat:
|
||||
if (kLinear_SrcGamma == kSrc) {
|
||||
if (kLinear_SrcGamma == fSrcGamma) {
|
||||
pipeline.append(SkRasterPipeline::load_8888, &src);
|
||||
} else {
|
||||
loadTables.fSrc = (const uint32_t*) src;
|
||||
loadTables.fSrc = src;
|
||||
loadTables.fR = fSrcGammaTables[0];
|
||||
loadTables.fG = fSrcGammaTables[1];
|
||||
loadTables.fB = fSrcGammaTables[2];
|
||||
@ -1263,10 +1191,10 @@ bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
|
||||
break;
|
||||
case kBGRA_8888_ColorFormat:
|
||||
if (kLinear_SrcGamma == kSrc) {
|
||||
if (kLinear_SrcGamma == fSrcGamma) {
|
||||
pipeline.append(SkRasterPipeline::load_8888, &src);
|
||||
} else {
|
||||
loadTables.fSrc = (const uint32_t*) src;
|
||||
loadTables.fSrc = src;
|
||||
loadTables.fR = fSrcGammaTables[2];
|
||||
loadTables.fG = fSrcGammaTables[1];
|
||||
loadTables.fB = fSrcGammaTables[0];
|
||||
@ -1275,6 +1203,24 @@ bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
|
||||
pipeline.append(SkRasterPipeline::swap_rb);
|
||||
break;
|
||||
case kRGBA_U16_BE_ColorFormat:
|
||||
switch (fSrcGamma) {
|
||||
case kLinear_SrcGamma:
|
||||
pipeline.append(SkRasterPipeline::load_u16_be, &src);
|
||||
break;
|
||||
case kSRGB_SrcGamma:
|
||||
pipeline.append(SkRasterPipeline::load_u16_be, &src);
|
||||
pipeline.append_from_srgb(kUnpremul_SkAlphaType);
|
||||
break;
|
||||
case kTable_SrcGamma:
|
||||
loadTables.fSrc = src;
|
||||
loadTables.fR = fSrcGammaTables[0];
|
||||
loadTables.fG = fSrcGammaTables[1];
|
||||
loadTables.fB = fSrcGammaTables[2];
|
||||
pipeline.append(SkRasterPipeline::load_tables_u16_be, &loadTables);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -1296,7 +1242,7 @@ bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
}
|
||||
|
||||
StoreTablesContext storeTables;
|
||||
switch (kDst) {
|
||||
switch (fDstGamma) {
|
||||
case kSRGB_DstGamma:
|
||||
pipeline.append(SkRasterPipeline::to_srgb);
|
||||
break;
|
||||
@ -1309,7 +1255,7 @@ bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
|
||||
switch (dstColorFormat) {
|
||||
case kRGBA_8888_ColorFormat:
|
||||
if (kTable_DstGamma == kDst) {
|
||||
if (kTable_DstGamma == fDstGamma) {
|
||||
storeTables.fDst = (uint32_t*) dst;
|
||||
storeTables.fR = fDstGammaTables[0];
|
||||
storeTables.fG = fDstGammaTables[1];
|
||||
@ -1321,7 +1267,7 @@ bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
}
|
||||
break;
|
||||
case kBGRA_8888_ColorFormat:
|
||||
if (kTable_DstGamma == kDst) {
|
||||
if (kTable_DstGamma == fDstGamma) {
|
||||
storeTables.fDst = (uint32_t*) dst;
|
||||
storeTables.fR = fDstGammaTables[2];
|
||||
storeTables.fG = fDstGammaTables[1];
|
||||
@ -1335,17 +1281,19 @@ bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
}
|
||||
break;
|
||||
case kRGBA_F16_ColorFormat:
|
||||
if (kLinear_DstGamma != kDst) {
|
||||
if (kLinear_DstGamma != fDstGamma) {
|
||||
return false;
|
||||
}
|
||||
pipeline.append(SkRasterPipeline::store_f16, &dst);
|
||||
break;
|
||||
case kRGBA_F32_ColorFormat:
|
||||
if (kLinear_DstGamma != kDst) {
|
||||
if (kLinear_DstGamma != fDstGamma) {
|
||||
return false;
|
||||
}
|
||||
pipeline.append(SkRasterPipeline::store_f32, &dst);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
pipeline.run(0, 0, len);
|
||||
@ -1356,6 +1304,5 @@ bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
|
||||
|
||||
std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space) {
|
||||
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
|
||||
<kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
|
||||
(space, SkMatrix::I(), space));
|
||||
<kNone_ColorSpaceMatch>(space, SkMatrix::I(), space));
|
||||
}
|
||||
|
@ -32,6 +32,9 @@ bool SkColorSpaceXform_A2B::onApply(ColorFormat dstFormat, void* dst, ColorForma
|
||||
case kRGBA_8888_ColorFormat:
|
||||
pipeline.append(SkRasterPipeline::load_8888, &src);
|
||||
break;
|
||||
case kRGBA_U16_BE_ColorFormat:
|
||||
pipeline.append(SkRasterPipeline::load_u16_be, &src);
|
||||
break;
|
||||
default:
|
||||
SkCSXformPrintf("F16/F32 source color format not supported\n");
|
||||
return false;
|
||||
@ -63,6 +66,8 @@ bool SkColorSpaceXform_A2B::onApply(ColorFormat dstFormat, void* dst, ColorForma
|
||||
}
|
||||
pipeline.append(SkRasterPipeline::store_f32, &dst);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
pipeline.run(0,0, count);
|
||||
|
||||
|
@ -34,6 +34,7 @@ private:
|
||||
enum SrcGamma {
|
||||
kLinear_SrcGamma,
|
||||
kTable_SrcGamma,
|
||||
kSRGB_SrcGamma,
|
||||
};
|
||||
|
||||
enum DstGamma {
|
||||
@ -49,7 +50,7 @@ enum ColorSpaceMatch {
|
||||
kFull_ColorSpaceMatch,
|
||||
};
|
||||
|
||||
template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
|
||||
template <ColorSpaceMatch kCSM>
|
||||
class SkColorSpaceXform_XYZ : public SkColorSpaceXform_Base {
|
||||
protected:
|
||||
bool onApply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, const void* src,
|
||||
@ -63,23 +64,26 @@ private:
|
||||
SkColorSpace_XYZ* dstSpace);
|
||||
|
||||
// Contain pointers into storage or pointers into precomputed tables.
|
||||
const float* fSrcGammaTables[3];
|
||||
SkAutoTMalloc<float> fSrcStorage;
|
||||
const uint8_t* fDstGammaTables[3];
|
||||
sk_sp<SkData> fDstStorage;
|
||||
const float* fSrcGammaTables[3];
|
||||
SkAutoTMalloc<float> fSrcStorage;
|
||||
const uint8_t* fDstGammaTables[3];
|
||||
sk_sp<SkData> fDstStorage;
|
||||
|
||||
// Holds a 3x4 matrix. Padding is useful for vector loading.
|
||||
float fSrcToDst[13];
|
||||
float fSrcToDst[13];
|
||||
|
||||
SrcGamma fSrcGamma;
|
||||
DstGamma fDstGamma;
|
||||
|
||||
friend class SkColorSpaceXform;
|
||||
friend std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space);
|
||||
};
|
||||
|
||||
struct LoadTablesContext {
|
||||
const uint32_t* fSrc;
|
||||
const float* fR;
|
||||
const float* fG;
|
||||
const float* fB;
|
||||
const void* fSrc;
|
||||
const float* fR;
|
||||
const float* fG;
|
||||
const float* fB;
|
||||
};
|
||||
|
||||
struct StoreTablesContext {
|
||||
|
@ -68,7 +68,8 @@
|
||||
M(load_565) M(store_565) \
|
||||
M(load_f16) M(store_f16) \
|
||||
M(load_8888) M(store_8888) \
|
||||
M(load_tables) M(store_tables) \
|
||||
M(load_u16_be) \
|
||||
M(load_tables) M(load_tables_u16_be) M(store_tables) \
|
||||
M(scale_u8) M(scale_1_float) \
|
||||
M(lerp_u8) M(lerp_565) M(lerp_1_float) \
|
||||
M(dstatop) M(dstin) M(dstout) M(dstover) \
|
||||
|
@ -255,6 +255,8 @@ public:
|
||||
AI SkNx operator + (const SkNx& o) const { return vadd_u16(fVec, o.fVec); }
|
||||
AI SkNx operator - (const SkNx& o) const { return vsub_u16(fVec, o.fVec); }
|
||||
AI SkNx operator * (const SkNx& o) const { return vmul_u16(fVec, o.fVec); }
|
||||
AI SkNx operator & (const SkNx& o) const { return vand_u16(fVec, o.fVec); }
|
||||
AI SkNx operator | (const SkNx& o) const { return vorr_u16(fVec, o.fVec); }
|
||||
|
||||
AI SkNx operator << (int bits) const { return fVec << SkNx(bits).fVec; }
|
||||
AI SkNx operator >> (int bits) const { return fVec >> SkNx(bits).fVec; }
|
||||
@ -293,6 +295,8 @@ public:
|
||||
AI SkNx operator + (const SkNx& o) const { return vaddq_u16(fVec, o.fVec); }
|
||||
AI SkNx operator - (const SkNx& o) const { return vsubq_u16(fVec, o.fVec); }
|
||||
AI SkNx operator * (const SkNx& o) const { return vmulq_u16(fVec, o.fVec); }
|
||||
AI SkNx operator & (const SkNx& o) const { return vandq_u16(fVec, o.fVec); }
|
||||
AI SkNx operator | (const SkNx& o) const { return vorrq_u16(fVec, o.fVec); }
|
||||
|
||||
AI SkNx operator << (int bits) const { return fVec << SkNx(bits).fVec; }
|
||||
AI SkNx operator >> (int bits) const { return fVec >> SkNx(bits).fVec; }
|
||||
|
@ -283,6 +283,8 @@ public:
|
||||
AI SkNx operator + (const SkNx& o) const { return _mm_add_epi16(fVec, o.fVec); }
|
||||
AI SkNx operator - (const SkNx& o) const { return _mm_sub_epi16(fVec, o.fVec); }
|
||||
AI SkNx operator * (const SkNx& o) const { return _mm_mullo_epi16(fVec, o.fVec); }
|
||||
AI SkNx operator & (const SkNx& o) const { return _mm_and_si128(fVec, o.fVec); }
|
||||
AI SkNx operator | (const SkNx& o) const { return _mm_or_si128(fVec, o.fVec); }
|
||||
|
||||
AI SkNx operator << (int bits) const { return _mm_slli_epi16(fVec, bits); }
|
||||
AI SkNx operator >> (int bits) const { return _mm_srli_epi16(fVec, bits); }
|
||||
@ -348,6 +350,8 @@ public:
|
||||
AI SkNx operator + (const SkNx& o) const { return _mm_add_epi16(fVec, o.fVec); }
|
||||
AI SkNx operator - (const SkNx& o) const { return _mm_sub_epi16(fVec, o.fVec); }
|
||||
AI SkNx operator * (const SkNx& o) const { return _mm_mullo_epi16(fVec, o.fVec); }
|
||||
AI SkNx operator & (const SkNx& o) const { return _mm_and_si128(fVec, o.fVec); }
|
||||
AI SkNx operator | (const SkNx& o) const { return _mm_or_si128(fVec, o.fVec); }
|
||||
|
||||
AI SkNx operator << (int bits) const { return _mm_slli_epi16(fVec, bits); }
|
||||
AI SkNx operator >> (int bits) const { return _mm_srli_epi16(fVec, bits); }
|
||||
@ -634,6 +638,14 @@ public:
|
||||
return _mm256_cvtepi32_ps(SkNx_cast<int>(src).fVec);
|
||||
}
|
||||
|
||||
template<> AI /*static*/ Sk8i SkNx_cast<int>(const Sk8h& src) {
|
||||
return _mm256_cvtepu16_epi32(src.fVec);
|
||||
}
|
||||
|
||||
template<> AI /*static*/ Sk8f SkNx_cast<float>(const Sk8h& src) {
|
||||
return _mm256_cvtepi32_ps(SkNx_cast<int>(src).fVec);
|
||||
}
|
||||
|
||||
template<> AI /*static*/ Sk8f SkNx_cast<float>(const Sk8i& src) {
|
||||
return _mm256_cvtepi32_ps(src.fVec);
|
||||
}
|
||||
@ -642,9 +654,6 @@ public:
|
||||
return _mm256_cvttps_epi32(src.fVec);
|
||||
}
|
||||
|
||||
template<> AI /*static*/ Sk8i SkNx_cast<int>(const Sk8h& src) {
|
||||
return _mm256_cvtepu16_epi32(src.fVec);
|
||||
}
|
||||
template<> AI /*static*/ Sk8h SkNx_cast<uint16_t>(const Sk8i& src) {
|
||||
__m128i lo = _mm256_extractf128_si256(src.fVec, 0),
|
||||
hi = _mm256_extractf128_si256(src.fVec, 1);
|
||||
|
@ -564,8 +564,25 @@ STAGE_CTX(store_8888, uint32_t**) {
|
||||
store(tail, byte(r,0)|byte(g,1)|byte(b,2)|byte(a,3), (int*)ptr);
|
||||
}
|
||||
|
||||
STAGE_CTX(load_u16_be, const uint64_t**) {
|
||||
auto ptr = *ctx + x;
|
||||
const void* src = ptr;
|
||||
SkNx<N, uint64_t> px;
|
||||
if (tail) {
|
||||
px = load(tail, ptr);
|
||||
src = &px;
|
||||
}
|
||||
|
||||
SkNh rh, gh, bh, ah;
|
||||
SkNh::Load4(src, &rh, &gh, &bh, &ah);
|
||||
r = (1.0f / 65535.0f) * SkNx_cast<float>((rh << 8) | (rh >> 8));
|
||||
g = (1.0f / 65535.0f) * SkNx_cast<float>((gh << 8) | (gh >> 8));
|
||||
b = (1.0f / 65535.0f) * SkNx_cast<float>((bh << 8) | (bh >> 8));
|
||||
a = (1.0f / 65535.0f) * SkNx_cast<float>((ah << 8) | (ah >> 8));
|
||||
}
|
||||
|
||||
STAGE_CTX(load_tables, const LoadTablesContext*) {
|
||||
auto ptr = ctx->fSrc + x;
|
||||
auto ptr = (const uint32_t*)ctx->fSrc + x;
|
||||
|
||||
SkNu rgba = load(tail, ptr);
|
||||
auto to_int = [](const SkNu& v) { return SkNi::Load(&v); };
|
||||
@ -575,6 +592,19 @@ STAGE_CTX(load_tables, const LoadTablesContext*) {
|
||||
a = SkNf_from_byte(rgba >> 24);
|
||||
}
|
||||
|
||||
STAGE_CTX(load_tables_u16_be, const LoadTablesContext*) {
|
||||
auto ptr = (const uint64_t*)ctx->fSrc + x;
|
||||
|
||||
SkNh rh, gh, bh, ah;
|
||||
SkNh::Load4(ptr, &rh, &gh, &bh, &ah);
|
||||
|
||||
// ctx->fSrc is big-endian, so "& 0xff" grabs the 8 most significant bits of each component.
|
||||
r = gather(tail, ctx->fR, SkNx_cast<int>(rh & 0xff));
|
||||
g = gather(tail, ctx->fG, SkNx_cast<int>(gh & 0xff));
|
||||
b = gather(tail, ctx->fB, SkNx_cast<int>(bh & 0xff));
|
||||
a = (1.0f / 65535.0f) * SkNx_cast<float>((ah << 8) | (ah >> 8));
|
||||
}
|
||||
|
||||
STAGE_CTX(store_tables, const StoreTablesContext*) {
|
||||
auto ptr = ctx->fDst + x;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user