Support Float32 output from SkColorSpaceXform
* Adds Float32 support to SkColorSpaceXform * Changes API to allows clients to ask for F32, updates clients to new API * Adds Sk4f_load4 and Sk4f_store4 to SkNx * Make use of new xform in SkGr.cpp BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2339233003 CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot Committed: https://skia.googlesource.com/skia/+/43d6651111374b5d1e4ddd9030dcf079b448ec47 Review-Url: https://codereview.chromium.org/2339233003
This commit is contained in:
parent
bfef32ff0a
commit
c0444615ed
@ -8,6 +8,7 @@
|
||||
#include "ColorCodecBench.h"
|
||||
#include "Resources.h"
|
||||
#include "SkCodec.h"
|
||||
#include "SkCodecPriv.h"
|
||||
#include "SkColorSpaceXform.h"
|
||||
#include "SkCommandLineFlags.h"
|
||||
|
||||
@ -99,8 +100,8 @@ void ColorCodecBench::xformOnly() {
|
||||
void* dst = fDst.get();
|
||||
void* src = fSrc.get();
|
||||
for (int y = 0; y < fSrcInfo.height(); y++) {
|
||||
xform->apply(dst, (uint32_t*) src, fSrcInfo.width(), fDstInfo.colorType(),
|
||||
fDstInfo.alphaType());
|
||||
xform->apply(dst, (uint32_t*) src, fSrcInfo.width(),
|
||||
select_xform_format(fDstInfo.colorType()), fDstInfo.alphaType());
|
||||
dst = SkTAddOffset<void>(dst, fDstInfo.minRowBytes());
|
||||
src = SkTAddOffset<void>(src, fSrcInfo.minRowBytes());
|
||||
}
|
||||
|
88
gm/colorspacexform.cpp
Normal file
88
gm/colorspacexform.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gm.h"
|
||||
#include "SkColor.h"
|
||||
#include "SkColorSpaceXform.h"
|
||||
#include "SkRect.h"
|
||||
|
||||
class ColorSpaceXformGM : public skiagm::GM {
|
||||
public:
|
||||
ColorSpaceXformGM() {}
|
||||
|
||||
protected:
|
||||
void onOnceBeforeDraw() override {
|
||||
SkColor colors[] = {
|
||||
SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorMAGENTA, SK_ColorCYAN, SK_ColorYELLOW,
|
||||
SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorMAGENTA,
|
||||
};
|
||||
static_assert(kNumColors == SK_ARRAY_COUNT(colors), "Fix number of colors.");
|
||||
|
||||
for (int i = 0; i < kNumColors; i++) {
|
||||
fSRGBColors[i] = SkColor4f::FromColor(colors[i]);
|
||||
|
||||
// FIXME (msarett): SkColorSpaceXform does not support BGRA.
|
||||
colors[i] = SkSwizzle_RB(colors[i]);
|
||||
}
|
||||
|
||||
static constexpr float kWideGamutRGB_toXYZD50[]{
|
||||
0.7161046f, 0.1009296f, 0.1471858f,
|
||||
0.2581874f, 0.7249378f, 0.0168748f,
|
||||
0.0000000f, 0.0517813f, 0.7734287f,
|
||||
};
|
||||
|
||||
SkMatrix44 wideGamut(SkMatrix44::kUninitialized_Constructor);
|
||||
wideGamut.set3x3RowMajorf(kWideGamutRGB_toXYZD50);
|
||||
std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(
|
||||
SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named),
|
||||
SkColorSpace::NewRGB(SkColorSpace::kLinear_RenderTargetGamma, wideGamut));
|
||||
|
||||
xform->apply(fWideGamutColors, colors, kNumColors,
|
||||
SkColorSpaceXform::kRGBA_F32_ColorFormat, kOpaque_SkAlphaType);
|
||||
}
|
||||
|
||||
SkString onShortName() override {
|
||||
return SkString("colorspacexform");
|
||||
}
|
||||
|
||||
SkISize onISize() override {
|
||||
return SkISize::Make(500, 200);
|
||||
}
|
||||
|
||||
void onDraw(SkCanvas* canvas) override {
|
||||
auto drawColors = [canvas](SkColor4f* colors) {
|
||||
SkRect r = SkRect::MakeXYWH(0.0f, 0.0f, 50.0f, 100.0f);
|
||||
|
||||
canvas->save();
|
||||
for (int i = 0; i < kNumColors; i++) {
|
||||
sk_sp<SkColorSpace> space =
|
||||
SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named)->makeLinearGamma();
|
||||
sk_sp<SkShader> s = SkShader::MakeColorShader(colors[i], space);
|
||||
SkPaint paint;
|
||||
paint.setShader(s);
|
||||
canvas->drawRect(r, paint);
|
||||
canvas->translate(50.0f, 0.0f);
|
||||
}
|
||||
canvas->restore();
|
||||
};
|
||||
|
||||
// Wide gamut colors should appear darker - we are simulating a more intense display.
|
||||
drawColors(fSRGBColors);
|
||||
canvas->translate(0.0f, 100.0f);
|
||||
drawColors(fWideGamutColors);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int kNumColors = 10;
|
||||
|
||||
SkColor4f fSRGBColors[kNumColors];
|
||||
SkColor4f fWideGamutColors[kNumColors];
|
||||
|
||||
typedef skiagm::GM INHERITED;
|
||||
};
|
||||
|
||||
DEF_GM(return new ColorSpaceXformGM;)
|
@ -21,6 +21,7 @@
|
||||
'gmslides.gypi',
|
||||
],
|
||||
'include_dirs' : [
|
||||
'../src/codec',
|
||||
'../src/image',
|
||||
],
|
||||
'dependencies': [
|
||||
|
@ -144,6 +144,20 @@ static inline const SkPMColor* get_color_ptr(SkColorTable* colorTable) {
|
||||
return nullptr != colorTable ? colorTable->readColors() : nullptr;
|
||||
}
|
||||
|
||||
static inline SkColorSpaceXform::ColorFormat select_xform_format(SkColorType colorType) {
|
||||
switch (colorType) {
|
||||
case kRGBA_8888_SkColorType:
|
||||
return SkColorSpaceXform::kRGBA_8888_ColorFormat;
|
||||
case kBGRA_8888_SkColorType:
|
||||
return SkColorSpaceXform::kBGRA_8888_ColorFormat;
|
||||
case kRGBA_F16_SkColorType:
|
||||
return SkColorSpaceXform::kRGBA_F16_ColorFormat;
|
||||
default:
|
||||
SkASSERT(false);
|
||||
return SkColorSpaceXform::kRGBA_8888_ColorFormat;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given that the encoded image uses a color table, return the fill value
|
||||
*/
|
||||
@ -162,7 +176,7 @@ static inline uint64_t get_color_table_fill_value(SkColorType colorType, SkAlpha
|
||||
SkASSERT(colorXform);
|
||||
uint64_t dstColor;
|
||||
uint32_t srcColor = colorPtr[fillIndex];
|
||||
colorXform->apply(&dstColor, &srcColor, 1, colorType, alphaType);
|
||||
colorXform->apply(&dstColor, &srcColor, 1, select_xform_format(colorType), alphaType);
|
||||
return dstColor;
|
||||
}
|
||||
default:
|
||||
@ -343,7 +357,7 @@ static inline bool needs_color_xform(const SkImageInfo& dstInfo, const SkImageIn
|
||||
return !isLegacy && (needsPremul || isF16 || srcDstNotEqual);
|
||||
}
|
||||
|
||||
static inline SkAlphaType select_alpha_xform(SkAlphaType dstAlphaType, SkAlphaType srcAlphaType) {
|
||||
static inline SkAlphaType select_xform_alpha(SkAlphaType dstAlphaType, SkAlphaType srcAlphaType) {
|
||||
return (kOpaque_SkAlphaType == srcAlphaType) ? kOpaque_SkAlphaType : dstAlphaType;
|
||||
}
|
||||
|
||||
|
@ -517,7 +517,8 @@ int SkJpegCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes
|
||||
}
|
||||
|
||||
if (fColorXform) {
|
||||
fColorXform->apply(dst, swizzleDst, dstWidth, dstInfo.colorType(), kOpaque_SkAlphaType);
|
||||
fColorXform->apply(dst, swizzleDst, dstWidth, select_xform_format(dstInfo.colorType()),
|
||||
kOpaque_SkAlphaType);
|
||||
dst = SkTAddOffset<void>(dst, rowBytes);
|
||||
}
|
||||
|
||||
|
@ -267,11 +267,12 @@ bool SkPngCodec::createColorTable(const SkImageInfo& dstInfo, int* ctableCount)
|
||||
// If we are not decoding to F16, we can color xform now and store the results
|
||||
// in the color table.
|
||||
if (fColorXform && kRGBA_F16_SkColorType != dstInfo.colorType()) {
|
||||
SkColorType xformColorType = is_rgba(dstInfo.colorType()) ?
|
||||
kRGBA_8888_SkColorType : kBGRA_8888_SkColorType;
|
||||
SkAlphaType xformAlphaType = select_alpha_xform(dstInfo.alphaType(),
|
||||
SkColorSpaceXform::ColorFormat xformColorFormat = is_rgba(dstInfo.colorType()) ?
|
||||
SkColorSpaceXform::kRGBA_8888_ColorFormat :
|
||||
SkColorSpaceXform::kBGRA_8888_ColorFormat;
|
||||
SkAlphaType xformAlphaType = select_xform_alpha(dstInfo.alphaType(),
|
||||
this->getInfo().alphaType());
|
||||
fColorXform->apply(colorTable, colorTable, numColors, xformColorType, xformAlphaType);
|
||||
fColorXform->apply(colorTable, colorTable, numColors, xformColorFormat, xformAlphaType);
|
||||
}
|
||||
|
||||
// Pad the color table with the last color in the table (or black) in the case that
|
||||
@ -492,17 +493,18 @@ void SkPngCodec::allocateStorage(const SkImageInfo& dstInfo) {
|
||||
}
|
||||
|
||||
void SkPngCodec::applyXformRow(void* dst, const void* src) {
|
||||
const SkColorType colorType = this->dstInfo().colorType();
|
||||
switch (fXformMode) {
|
||||
case kSwizzleOnly_XformMode:
|
||||
fSwizzler->swizzle(dst, (const uint8_t*) src);
|
||||
break;
|
||||
case kColorOnly_XformMode:
|
||||
fColorXform->apply(dst, (const uint32_t*) src, fXformWidth, colorType, fXformAlphaType);
|
||||
fColorXform->apply(dst, (const uint32_t*) src, fXformWidth, fXformColorFormat,
|
||||
fXformAlphaType);
|
||||
break;
|
||||
case kSwizzleColor_XformMode:
|
||||
fSwizzler->swizzle(fColorXformSrcRow, (const uint8_t*) src);
|
||||
fColorXform->apply(dst, fColorXformSrcRow, fXformWidth, colorType, fXformAlphaType);
|
||||
fColorXform->apply(dst, fColorXformSrcRow, fXformWidth, fXformColorFormat,
|
||||
fXformAlphaType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1137,9 +1139,23 @@ bool SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& opt
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkPngCodec::initializeXformAlphaAndWidth() {
|
||||
fXformAlphaType = select_alpha_xform(this->dstInfo().alphaType(), this->getInfo().alphaType());
|
||||
fXformWidth = this->swizzler() ? this->swizzler()->swizzleWidth() : this->dstInfo().width();
|
||||
void SkPngCodec::initializeXformParams() {
|
||||
switch (fXformMode) {
|
||||
case kColorOnly_XformMode:
|
||||
fXformColorFormat = select_xform_format(this->dstInfo().colorType());
|
||||
fXformAlphaType = select_xform_alpha(this->dstInfo().alphaType(),
|
||||
this->getInfo().alphaType());
|
||||
fXformWidth = this->dstInfo().width();
|
||||
break;
|
||||
case kSwizzleColor_XformMode:
|
||||
fXformColorFormat = select_xform_format(this->dstInfo().colorType());
|
||||
fXformAlphaType = select_xform_alpha(this->dstInfo().alphaType(),
|
||||
this->getInfo().alphaType());
|
||||
fXformWidth = this->swizzler()->swizzleWidth();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool apply_xform_on_decode(SkColorType dstColorType, SkEncodedInfo::Color srcColor) {
|
||||
@ -1226,7 +1242,7 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst,
|
||||
}
|
||||
|
||||
this->allocateStorage(dstInfo);
|
||||
this->initializeXformAlphaAndWidth();
|
||||
this->initializeXformParams();
|
||||
return this->decodeAllRows(dst, rowBytes, rowsDecoded);
|
||||
}
|
||||
|
||||
@ -1261,7 +1277,7 @@ SkCodec::Result SkPngCodec::onStartIncrementalDecode(const SkImageInfo& dstInfo,
|
||||
|
||||
SkCodec::Result SkPngCodec::onIncrementalDecode(int* rowsDecoded) {
|
||||
// FIXME: Only necessary on the first call.
|
||||
this->initializeXformAlphaAndWidth();
|
||||
this->initializeXformParams();
|
||||
|
||||
return this->decode(rowsDecoded);
|
||||
}
|
||||
@ -1269,7 +1285,7 @@ SkCodec::Result SkPngCodec::onIncrementalDecode(int* rowsDecoded) {
|
||||
uint64_t SkPngCodec::onGetFillValue(const SkImageInfo& dstInfo) const {
|
||||
const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
|
||||
if (colorPtr) {
|
||||
SkAlphaType alphaType = select_alpha_xform(dstInfo.alphaType(),
|
||||
SkAlphaType alphaType = select_xform_alpha(dstInfo.alphaType(),
|
||||
this->getInfo().alphaType());
|
||||
return get_color_table_fill_value(dstInfo.colorType(), alphaType, colorPtr, 0,
|
||||
fColorXform.get());
|
||||
|
@ -64,7 +64,7 @@ protected:
|
||||
SkSwizzler* swizzler() { return fSwizzler; }
|
||||
|
||||
// Initialize variables used by applyXformRow.
|
||||
void initializeXformAlphaAndWidth();
|
||||
void initializeXformParams();
|
||||
|
||||
/**
|
||||
* Pass available input to libpng to process it.
|
||||
@ -128,9 +128,10 @@ private:
|
||||
virtual void setRange(int firstRow, int lastRow, void* dst, size_t rowBytes) = 0;
|
||||
virtual Result decode(int* rowsDecoded) = 0;
|
||||
|
||||
XformMode fXformMode;
|
||||
SkAlphaType fXformAlphaType;
|
||||
int fXformWidth;
|
||||
XformMode fXformMode;
|
||||
SkColorSpaceXform::ColorFormat fXformColorFormat;
|
||||
SkAlphaType fXformAlphaType;
|
||||
int fXformWidth;
|
||||
|
||||
#ifdef SK_GOOGLE3_PNG_HACK
|
||||
bool fNeedsToRereadHeader;
|
||||
|
@ -307,13 +307,14 @@ SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst,
|
||||
}
|
||||
|
||||
if (colorXform) {
|
||||
SkAlphaType xformAlphaType = select_alpha_xform(dstInfo.alphaType(),
|
||||
SkColorSpaceXform::ColorFormat colorFormat = select_xform_format(dstInfo.colorType());
|
||||
SkAlphaType xformAlphaType = select_xform_alpha(dstInfo.alphaType(),
|
||||
this->getInfo().alphaType());
|
||||
|
||||
uint32_t* src = (uint32_t*) config.output.u.RGBA.rgba;
|
||||
size_t srcRowBytes = config.output.u.RGBA.stride;
|
||||
for (int y = 0; y < rowsDecoded; y++) {
|
||||
colorXform->apply(dst, src, dstInfo.width(), dstInfo.colorType(), xformAlphaType);
|
||||
colorXform->apply(dst, src, dstInfo.width(), colorFormat, xformAlphaType);
|
||||
dst = SkTAddOffset<void>(dst, rowBytes);
|
||||
src = SkTAddOffset<uint32_t>(src, srcRowBytes);
|
||||
}
|
||||
|
@ -907,9 +907,24 @@ static inline void store_f16_1(void* dst, const uint32_t* src,
|
||||
SkFloatToHalf_finite_ftz(rgba).store((uint64_t*) dst);
|
||||
}
|
||||
|
||||
template <SwapRB kSwapRB>
|
||||
static inline void store_f32(void* dst, const uint32_t* src,
|
||||
Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da,
|
||||
const uint8_t* const[3]) {
|
||||
Sk4f_store4(dst, dr, dg, db, da);
|
||||
}
|
||||
|
||||
template <SwapRB kSwapRB>
|
||||
static inline void store_f32_1(void* dst, const uint32_t* src,
|
||||
Sk4f& rgba, const Sk4f& a,
|
||||
const uint8_t* const[3]) {
|
||||
rgba = Sk4f(rgba[0], rgba[1], rgba[2], a[3]);
|
||||
rgba.store((float*) dst);
|
||||
}
|
||||
|
||||
template <SwapRB kSwapRB>
|
||||
static inline void store_f16_opaque(void* dst, const uint32_t* src,
|
||||
Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da,
|
||||
Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&,
|
||||
const uint8_t* const[3]) {
|
||||
Sk4h_store4(dst, SkFloatToHalf_finite_ftz(dr),
|
||||
SkFloatToHalf_finite_ftz(dg),
|
||||
@ -919,7 +934,7 @@ static inline void store_f16_opaque(void* dst, const uint32_t* src,
|
||||
|
||||
template <SwapRB kSwapRB>
|
||||
static inline void store_f16_1_opaque(void* dst, const uint32_t* src,
|
||||
Sk4f& rgba, const Sk4f& a,
|
||||
Sk4f& rgba, const Sk4f&,
|
||||
const uint8_t* const[3]) {
|
||||
uint64_t tmp;
|
||||
SkFloatToHalf_finite_ftz(rgba).store(&tmp);
|
||||
@ -1089,6 +1104,7 @@ enum DstFormat {
|
||||
k8888_2Dot2_DstFormat,
|
||||
k8888_Table_DstFormat,
|
||||
kF16_Linear_DstFormat,
|
||||
kF32_Linear_DstFormat,
|
||||
};
|
||||
|
||||
template <SrcFormat kSrc,
|
||||
@ -1101,9 +1117,12 @@ static void color_xform_RGBA(void* dst, const uint32_t* src, int len,
|
||||
const uint8_t* const dstTables[3]) {
|
||||
LoadFn load;
|
||||
Load1Fn load_1;
|
||||
static constexpr bool loadAlpha = (kPremul_SkAlphaType == kAlphaType) ||
|
||||
(kF16_Linear_DstFormat == kDst) ||
|
||||
(kF32_Linear_DstFormat == kDst);
|
||||
switch (kSrc) {
|
||||
case kRGBA_8888_Linear_SrcFormat:
|
||||
if (kPremul_SkAlphaType == kAlphaType || kF16_Linear_DstFormat == kDst) {
|
||||
if (loadAlpha) {
|
||||
load = load_rgba_linear;
|
||||
load_1 = load_rgba_linear_1;
|
||||
} else {
|
||||
@ -1112,7 +1131,7 @@ static void color_xform_RGBA(void* dst, const uint32_t* src, int len,
|
||||
}
|
||||
break;
|
||||
case kRGBA_8888_Table_SrcFormat:
|
||||
if (kPremul_SkAlphaType == kAlphaType || kF16_Linear_DstFormat == kDst) {
|
||||
if (loadAlpha) {
|
||||
load = load_rgba_from_tables;
|
||||
load_1 = load_rgba_from_tables_1;
|
||||
} else {
|
||||
@ -1153,6 +1172,11 @@ static void color_xform_RGBA(void* dst, const uint32_t* src, int len,
|
||||
store_f16_1<kSwapRB>;
|
||||
sizeOfDstPixel = 8;
|
||||
break;
|
||||
case kF32_Linear_DstFormat:
|
||||
store = store_f32<kSwapRB>;
|
||||
store_1 = store_f32_1<kSwapRB>;
|
||||
sizeOfDstPixel = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
do_color_xform<kAlphaType, kCSM>
|
||||
@ -1245,7 +1269,7 @@ static inline void apply_set_src(void* dst, const uint32_t* src, int len, SkAlph
|
||||
|
||||
template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
|
||||
void SkColorSpaceXform_Base<kSrc, kDst, kCSM>
|
||||
::apply(void* dst, const uint32_t* src, int len, SkColorType dstColorType, SkAlphaType alphaType)
|
||||
::apply(void* dst, const uint32_t* src, int len, ColorFormat dstColorFormat, SkAlphaType alphaType)
|
||||
const
|
||||
{
|
||||
if (kFull_ColorSpaceMatch == kCSM) {
|
||||
@ -1255,13 +1279,14 @@ const
|
||||
// linear space.
|
||||
break;
|
||||
default:
|
||||
switch (dstColorType) {
|
||||
case kRGBA_8888_SkColorType:
|
||||
switch (dstColorFormat) {
|
||||
case kRGBA_8888_ColorFormat:
|
||||
return (void) memcpy(dst, src, len * sizeof(uint32_t));
|
||||
case kBGRA_8888_SkColorType:
|
||||
case kBGRA_8888_ColorFormat:
|
||||
return SkOpts::RGBA_to_BGRA((uint32_t*) dst, src, len);
|
||||
case kRGBA_F16_SkColorType:
|
||||
// There's still work to do to xform to linear F16.
|
||||
case kRGBA_F16_ColorFormat:
|
||||
case kRGBA_F32_ColorFormat:
|
||||
// There's still work to do to xform to linear floats.
|
||||
break;
|
||||
default:
|
||||
SkASSERT(false);
|
||||
@ -1283,8 +1308,8 @@ const
|
||||
src = (const uint32_t*) storage.get();
|
||||
}
|
||||
|
||||
switch (dstColorType) {
|
||||
case kRGBA_8888_SkColorType:
|
||||
switch (dstColorFormat) {
|
||||
case kRGBA_8888_ColorFormat:
|
||||
switch (kDst) {
|
||||
case kLinear_DstGamma:
|
||||
return apply_set_src<kSrc, k8888_Linear_DstFormat, kCSM, kNo_SwapRB>
|
||||
@ -1299,7 +1324,7 @@ const
|
||||
return apply_set_src<kSrc, k8888_Table_DstFormat, kCSM, kNo_SwapRB>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables);
|
||||
}
|
||||
case kBGRA_8888_SkColorType:
|
||||
case kBGRA_8888_ColorFormat:
|
||||
switch (kDst) {
|
||||
case kLinear_DstGamma:
|
||||
return apply_set_src<kSrc, k8888_Linear_DstFormat, kCSM, kYes_SwapRB>
|
||||
@ -1314,7 +1339,7 @@ const
|
||||
return apply_set_src<kSrc, k8888_Table_DstFormat, kCSM, kYes_SwapRB>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables);
|
||||
}
|
||||
case kRGBA_F16_SkColorType:
|
||||
case kRGBA_F16_ColorFormat:
|
||||
switch (kDst) {
|
||||
case kLinear_DstGamma:
|
||||
return apply_set_src<kSrc, kF16_Linear_DstFormat, kCSM, kNo_SwapRB>
|
||||
@ -1323,6 +1348,15 @@ const
|
||||
SkASSERT(false);
|
||||
return;
|
||||
}
|
||||
case kRGBA_F32_ColorFormat:
|
||||
switch (kDst) {
|
||||
case kLinear_DstGamma:
|
||||
return apply_set_src<kSrc, kF32_Linear_DstFormat, kCSM, kNo_SwapRB>
|
||||
(dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr);
|
||||
default:
|
||||
SkASSERT(false);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
SkASSERT(false);
|
||||
return;
|
||||
|
@ -25,20 +25,27 @@ public:
|
||||
static std::unique_ptr<SkColorSpaceXform> New(const sk_sp<SkColorSpace>& srcSpace,
|
||||
const sk_sp<SkColorSpace>& dstSpace);
|
||||
|
||||
enum ColorFormat : uint8_t {
|
||||
kRGBA_8888_ColorFormat,
|
||||
kBGRA_8888_ColorFormat,
|
||||
kRGBA_F16_ColorFormat,
|
||||
kRGBA_F32_ColorFormat,
|
||||
};
|
||||
|
||||
/**
|
||||
* Apply the color conversion to a |src| buffer, storing the output in the |dst| buffer.
|
||||
*
|
||||
* @param dst Stored in the format described by |dstColorType| and |dstAlphaType|
|
||||
* @param src Stored as RGBA_8888, kUnpremul (note kOpaque is a form of kUnpremul)
|
||||
* @param len Number of pixels in the buffers
|
||||
* @param dstColorType Describes color type of |dst|
|
||||
* @param dstAlphaType Describes alpha type of |dst|
|
||||
* kUnpremul preserves input alpha values
|
||||
* kPremul performs a premultiplication and also preserves alpha values
|
||||
* kOpaque optimization hint, |dst| alphas set to 1
|
||||
* @param dst Stored in the format described by |dstColorType| and |dstAlphaType|
|
||||
* @param src Stored as RGBA_8888, kUnpremul (note kOpaque is a form of kUnpremul)
|
||||
* @param len Number of pixels in the buffers
|
||||
* @param dstColorFormat Describes color format of |dst|
|
||||
* @param dstAlphaType Describes alpha type of |dst|
|
||||
* kUnpremul preserves input alpha values
|
||||
* kPremul performs a premultiplication and also preserves alpha values
|
||||
* kOpaque optimization hint, |dst| alphas set to 1
|
||||
*
|
||||
*/
|
||||
virtual void apply(void* dst, const uint32_t* src, int len, SkColorType dstColorType,
|
||||
virtual void apply(void* dst, const uint32_t* src, int len, ColorFormat dstColorFormat,
|
||||
SkAlphaType dstAlphaType) const = 0;
|
||||
|
||||
virtual ~SkColorSpaceXform() {}
|
||||
@ -66,7 +73,7 @@ template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
|
||||
class SkColorSpaceXform_Base : public SkColorSpaceXform {
|
||||
public:
|
||||
|
||||
void apply(void* dst, const uint32_t* src, int len, SkColorType dstColorType,
|
||||
void apply(void* dst, const uint32_t* src, int len, ColorFormat dstColorFormat,
|
||||
SkAlphaType dstAlphaType) const override;
|
||||
|
||||
static constexpr int kDstGammaTableSize = 1024;
|
||||
|
@ -332,6 +332,28 @@ SI void Sk4h_store4(void* dst, const Sk4h& r, const Sk4h& g, const Sk4h& b, cons
|
||||
Sk4h(r[3], g[3], b[3], a[3]).store(dst64 + 3);
|
||||
}
|
||||
|
||||
// Load 4 Sk4f and transpose them (512 bits total).
|
||||
SI void Sk4f_load4(const void* vptr, Sk4f* r, Sk4f* g, Sk4f* b, Sk4f* a) {
|
||||
const float* ptr = (const float*) vptr;
|
||||
auto p0 = Sk4f::Load(ptr + 0),
|
||||
p1 = Sk4f::Load(ptr + 4),
|
||||
p2 = Sk4f::Load(ptr + 8),
|
||||
p3 = Sk4f::Load(ptr + 12);
|
||||
*r = { p0[0], p1[0], p2[0], p3[0] };
|
||||
*g = { p0[1], p1[1], p2[1], p3[1] };
|
||||
*b = { p0[2], p1[2], p2[2], p3[2] };
|
||||
*a = { p0[3], p1[3], p2[3], p3[3] };
|
||||
}
|
||||
|
||||
// Transpose 4 Sk4f and store (512 bits total).
|
||||
SI void Sk4f_store4(void* vdst, const Sk4f& r, const Sk4f& g, const Sk4f& b, const Sk4f& a) {
|
||||
float* dst = (float*) vdst;
|
||||
Sk4f(r[0], g[0], b[0], a[0]).store(dst + 0);
|
||||
Sk4f(r[1], g[1], b[1], a[1]).store(dst + 4);
|
||||
Sk4f(r[2], g[2], b[2], a[2]).store(dst + 8);
|
||||
Sk4f(r[3], g[3], b[3], a[3]).store(dst + 12);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SI void Sk4f_ToBytes(uint8_t p[16], const Sk4f& a, const Sk4f& b, const Sk4f& c, const Sk4f& d) {
|
||||
|
@ -534,4 +534,23 @@ static inline void Sk4h_store4(void* dst, const Sk4h& r, const Sk4h& g, const Sk
|
||||
vst4_u16((uint16_t*) dst, rgba);
|
||||
}
|
||||
|
||||
static inline void Sk4f_load4(const void* ptr, Sk4f* r, Sk4f* g, Sk4f* b, Sk4f* a) {
|
||||
float32x4x4_t rgba = vld4q_f32((const float*) ptr);
|
||||
*r = rgba.val[0];
|
||||
*g = rgba.val[1];
|
||||
*b = rgba.val[2];
|
||||
*a = rgba.val[3];
|
||||
}
|
||||
|
||||
static inline void Sk4f_store4(void* dst, const Sk4f& r, const Sk4f& g, const Sk4f& b,
|
||||
const Sk4f& a) {
|
||||
float32x4x4_t rgba = {{
|
||||
r.fVec,
|
||||
g.fVec,
|
||||
b.fVec,
|
||||
a.fVec,
|
||||
}};
|
||||
vst4q_f32((float*) dst, rgba);
|
||||
}
|
||||
|
||||
#endif//SkNx_neon_DEFINED
|
||||
|
@ -478,4 +478,29 @@ static inline void Sk4h_store4(void* dst, const Sk4h& r, const Sk4h& g, const Sk
|
||||
_mm_storeu_si128(((__m128i*) dst) + 1, hi);
|
||||
}
|
||||
|
||||
static inline void Sk4f_load4(const void* ptr, Sk4f* r, Sk4f* g, Sk4f* b, Sk4f* a) {
|
||||
__m128 v0 = _mm_loadu_ps(((float*)ptr) + 0),
|
||||
v1 = _mm_loadu_ps(((float*)ptr) + 4),
|
||||
v2 = _mm_loadu_ps(((float*)ptr) + 8),
|
||||
v3 = _mm_loadu_ps(((float*)ptr) + 12);
|
||||
_MM_TRANSPOSE4_PS(v0, v1, v2, v3);
|
||||
*r = v0;
|
||||
*g = v1;
|
||||
*b = v2;
|
||||
*a = v3;
|
||||
}
|
||||
|
||||
static inline void Sk4f_store4(void* dst, const Sk4f& r, const Sk4f& g, const Sk4f& b,
|
||||
const Sk4f& a) {
|
||||
__m128 v0 = r.fVec,
|
||||
v1 = g.fVec,
|
||||
v2 = b.fVec,
|
||||
v3 = a.fVec;
|
||||
_MM_TRANSPOSE4_PS(v0, v1, v2, v3);
|
||||
_mm_storeu_ps(((float*) dst) + 0, v0);
|
||||
_mm_storeu_ps(((float*) dst) + 4, v1);
|
||||
_mm_storeu_ps(((float*) dst) + 8, v2);
|
||||
_mm_storeu_ps(((float*) dst) + 12, v3);
|
||||
}
|
||||
|
||||
#endif//SkNx_sse_DEFINED
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "Resources.h"
|
||||
#include "SkCodec.h"
|
||||
#include "SkCodecPriv.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkColorSpace.h"
|
||||
#include "SkColorSpace_Base.h"
|
||||
@ -39,7 +40,8 @@ static void test_identity_xform(skiatest::Reporter* r, const sk_sp<SkGammas>& ga
|
||||
|
||||
// Create and perform an identity xform.
|
||||
std::unique_ptr<SkColorSpaceXform> xform = ColorSpaceXformTest::CreateIdentityXform(gammas);
|
||||
xform->apply(dstPixels, srcPixels, width, kN32_SkColorType, kOpaque_SkAlphaType);
|
||||
xform->apply(dstPixels, srcPixels, width, select_xform_format(kN32_SkColorType),
|
||||
kOpaque_SkAlphaType);
|
||||
|
||||
// Since the src->dst matrix is the identity, and the gamma curves match,
|
||||
// the pixels should be unchanged.
|
||||
|
@ -307,3 +307,35 @@ DEF_TEST(SkNx_int_u16, r) {
|
||||
REPORTER_ASSERT(r, expected == actual);
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(SkNx_4fLoad4Store4, r) {
|
||||
float src[] = {
|
||||
0.0f, 1.0f, 2.0f, 3.0f,
|
||||
4.0f, 5.0f, 6.0f, 7.0f,
|
||||
8.0f, 9.0f, 10.0f, 11.0f,
|
||||
12.0f, 13.0f, 14.0f, 15.0f
|
||||
};
|
||||
|
||||
Sk4f a, b, c, d;
|
||||
Sk4f_load4(src, &a, &b, &c, &d);
|
||||
REPORTER_ASSERT(r, 0.0f == a[0]);
|
||||
REPORTER_ASSERT(r, 4.0f == a[1]);
|
||||
REPORTER_ASSERT(r, 8.0f == a[2]);
|
||||
REPORTER_ASSERT(r, 12.0f == a[3]);
|
||||
REPORTER_ASSERT(r, 1.0f == b[0]);
|
||||
REPORTER_ASSERT(r, 5.0f == b[1]);
|
||||
REPORTER_ASSERT(r, 9.0f == b[2]);
|
||||
REPORTER_ASSERT(r, 13.0f == b[3]);
|
||||
REPORTER_ASSERT(r, 2.0f == c[0]);
|
||||
REPORTER_ASSERT(r, 6.0f == c[1]);
|
||||
REPORTER_ASSERT(r, 10.0f == c[2]);
|
||||
REPORTER_ASSERT(r, 14.0f == c[3]);
|
||||
REPORTER_ASSERT(r, 3.0f == d[0]);
|
||||
REPORTER_ASSERT(r, 7.0f == d[1]);
|
||||
REPORTER_ASSERT(r, 11.0f == d[2]);
|
||||
REPORTER_ASSERT(r, 15.0f == d[3]);
|
||||
|
||||
float dst[16];
|
||||
Sk4f_store4(dst, a, b, c, d);
|
||||
REPORTER_ASSERT(r, 0 == memcmp(dst, src, 16 * sizeof(float)));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user