aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/ColorCodecBench.cpp4
-rw-r--r--dm/DM.cpp15
-rw-r--r--dm/DMSrcSink.cpp48
-rw-r--r--dm/DMSrcSink.h3
-rw-r--r--src/core/SkColorSpaceXform.cpp42
-rw-r--r--src/core/SkColorSpaceXform.h19
-rw-r--r--src/core/SkOpts.cpp1
-rw-r--r--src/core/SkOpts.h5
-rw-r--r--src/opts/SkColorXform_opts.h106
-rw-r--r--src/opts/SkOpts_sse41.cpp1
-rw-r--r--tests/ColorSpaceXformTest.cpp2
-rw-r--r--tools/viewer/ImageSlide.cpp2
12 files changed, 165 insertions, 83 deletions
diff --git a/bench/ColorCodecBench.cpp b/bench/ColorCodecBench.cpp
index 9dde5da813..edad759860 100644
--- a/bench/ColorCodecBench.cpp
+++ b/bench/ColorCodecBench.cpp
@@ -61,7 +61,7 @@ void ColorCodecBench::decodeAndXform() {
codec->getScanlines(fSrc.get(), 1, 0);
SkASSERT(1 == rows);
- xform->xform_RGB1_8888((uint32_t*) dst, (uint32_t*) fSrc.get(), fInfo.width());
+ xform->applyTo8888((SkPMColor*) dst, (uint32_t*) fSrc.get(), fInfo.width());
dst = SkTAddOffset<void>(dst, fInfo.minRowBytes());
}
}
@@ -116,7 +116,7 @@ void ColorCodecBench::xformOnly() {
void* src = fSrc.get();
for (int y = 0; y < fInfo.height(); y++) {
// Transform in place
- xform->xform_RGB1_8888((uint32_t*) dst, (uint32_t*) src, fInfo.width());
+ xform->applyTo8888((SkPMColor*) dst, (uint32_t*) src, fInfo.width());
dst = SkTAddOffset<void>(dst, fInfo.minRowBytes());
src = SkTAddOffset<void>(src, fInfo.minRowBytes());
}
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 78b403b8d0..cccc92b9fa 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -740,17 +740,22 @@ static bool gather_srcs() {
}
for (auto colorImage : colorImages) {
- ColorCodecSrc* src = new ColorCodecSrc(colorImage, ColorCodecSrc::kBaseline_Mode);
+ ColorCodecSrc* src = new ColorCodecSrc(colorImage, ColorCodecSrc::kBaseline_Mode,
+ kN32_SkColorType);
push_src("image", "color_codec_baseline", src);
- src = new ColorCodecSrc(colorImage, ColorCodecSrc::kDst_HPZR30w_Mode);
+ src = new ColorCodecSrc(colorImage, ColorCodecSrc::kDst_HPZR30w_Mode, kN32_SkColorType);
push_src("image", "color_codec_HPZR30w", src);
+ // TODO (msarett):
+ // Should we test this Dst in F16 mode (even though the Dst gamma is 2.2 instead of sRGB)?
- src = new ColorCodecSrc(colorImage, ColorCodecSrc::kDst_sRGB_Mode);
- push_src("image", "color_codec_sRGB", src);
+ src = new ColorCodecSrc(colorImage, ColorCodecSrc::kDst_sRGB_Mode, kN32_SkColorType);
+ push_src("image", "color_codec_sRGB_kN32", src);
+ src = new ColorCodecSrc(colorImage, ColorCodecSrc::kDst_sRGB_Mode, kRGBA_F16_SkColorType);
+ push_src("image", "color_codec_sRGB_kF16", src);
#if defined(SK_TEST_QCMS)
- src = new ColorCodecSrc(colorImage, ColorCodecSrc::kQCMS_HPZR30w_Mode);
+ src = new ColorCodecSrc(colorImage, ColorCodecSrc::kQCMS_HPZR30w_Mode, kN32_SkColorType);
push_src("image", "color_codec_QCMS_HPZR30w", src);
#endif
}
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 78fa140b31..932d80f570 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -837,9 +837,10 @@ Name ImageGenSrc::name() const {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-ColorCodecSrc::ColorCodecSrc(Path path, Mode mode)
+ColorCodecSrc::ColorCodecSrc(Path path, Mode mode, SkColorType colorType)
: fPath(path)
, fMode(mode)
+ , fColorType(colorType)
{}
bool ColorCodecSrc::veto(SinkFlags flags) const {
@@ -852,6 +853,10 @@ Error ColorCodecSrc::draw(SkCanvas* canvas) const {
return Error::Nonfatal("No need to test color correction to 565 backend.");
}
+ if (nullptr == canvas->imageInfo().colorSpace() && kRGBA_F16_SkColorType == fColorType) {
+ return Error::Nonfatal("F16 does not draw in legacy mode.");
+ }
+
SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
if (!encoded) {
return SkStringPrintf("Couldn't read %s.", fPath.c_str());
@@ -862,7 +867,7 @@ Error ColorCodecSrc::draw(SkCanvas* canvas) const {
return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
}
- SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
+ SkImageInfo info = codec->getInfo().makeColorType(fColorType);
SkBitmap bitmap;
if (!bitmap.tryAllocPixels(info)) {
return SkStringPrintf("Image(%s) is too large (%d x %d)", fPath.c_str(),
@@ -870,11 +875,16 @@ Error ColorCodecSrc::draw(SkCanvas* canvas) const {
}
SkImageInfo decodeInfo = info;
- if (kBaseline_Mode != fMode) {
+ size_t srcRowBytes = sizeof(SkPMColor) * info.width();
+ SkAutoMalloc src(srcRowBytes * info.height());
+ void* srcPixels = src.get();
+ if (kBaseline_Mode == fMode) {
+ srcPixels = bitmap.getPixels();
+ } else {
decodeInfo = decodeInfo.makeColorType(kRGBA_8888_SkColorType);
}
- SkCodec::Result r = codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes());
+ SkCodec::Result r = codec->getPixels(decodeInfo, srcPixels, srcRowBytes);
if (SkCodec::kSuccess != r) {
return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_str(), r);
}
@@ -903,10 +913,24 @@ Error ColorCodecSrc::draw(SkCanvas* canvas) const {
return "Unimplemented color conversion.";
}
- uint32_t* row = (uint32_t*) bitmap.getPixels();
- for (int y = 0; y < info.height(); y++) {
- xform->xform_RGB1_8888(row, row, info.width());
- row = SkTAddOffset<uint32_t>(row, bitmap.rowBytes());
+ if (kN32_SkColorType == fColorType) {
+ uint32_t* srcRow = (uint32_t*) srcPixels;
+ uint32_t* dstRow = (uint32_t*) bitmap.getPixels();
+ for (int y = 0; y < info.height(); y++) {
+ xform->applyTo8888(dstRow, srcRow, info.width());
+ srcRow = SkTAddOffset<uint32_t>(srcRow, srcRowBytes);
+ dstRow = SkTAddOffset<uint32_t>(dstRow, bitmap.rowBytes());
+ }
+ } else {
+ SkASSERT(kRGBA_F16_SkColorType == fColorType);
+
+ uint32_t* srcRow = (uint32_t*) srcPixels;
+ uint64_t* dstRow = (uint64_t*) bitmap.getPixels();
+ for (int y = 0; y < info.height(); y++) {
+ xform->applyToF16(dstRow, srcRow, info.width());
+ srcRow = SkTAddOffset<uint32_t>(srcRow, srcRowBytes);
+ dstRow = SkTAddOffset<uint64_t>(dstRow, bitmap.rowBytes());
+ }
}
canvas->drawBitmap(bitmap, 0, 0);
@@ -943,10 +967,12 @@ Error ColorCodecSrc::draw(SkCanvas* canvas) const {
#endif
// Perform color correction.
- uint32_t* row = (uint32_t*) bitmap.getPixels();
+ uint32_t* srcRow = (uint32_t*) srcPixels;
+ uint32_t* dstRow = (uint32_t*) bitmap.getPixels();
for (int y = 0; y < info.height(); y++) {
- qcms_transform_data_type(transform, row, row, info.width(), outType);
- row = SkTAddOffset<uint32_t>(row, bitmap.rowBytes());
+ qcms_transform_data_type(transform, srcRow, dstRow, info.width(), outType);
+ srcRow = SkTAddOffset<uint32_t>(srcRow, srcRowBytes);
+ dstRow = SkTAddOffset<uint32_t>(dstRow, bitmap.rowBytes());
}
canvas->drawBitmap(bitmap, 0, 0);
diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h
index 50a3b5a41a..b05fdb0439 100644
--- a/dm/DMSrcSink.h
+++ b/dm/DMSrcSink.h
@@ -225,7 +225,7 @@ public:
#endif
};
- ColorCodecSrc(Path, Mode);
+ ColorCodecSrc(Path, Mode, SkColorType);
Error draw(SkCanvas*) const override;
SkISize size() const override;
@@ -234,6 +234,7 @@ public:
private:
Path fPath;
Mode fMode;
+ SkColorType fColorType;
};
class SKPSrc : public Src {
diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp
index 634fcb6325..8b23d18e1a 100644
--- a/src/core/SkColorSpaceXform.cpp
+++ b/src/core/SkColorSpaceXform.cpp
@@ -394,26 +394,13 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpa
///////////////////////////////////////////////////////////////////////////////////////////////////
+// TODO (msarett):
+// Once SkFastXform supports translation, delete this function and use asRowMajorf().
static void build_src_to_dst(float srcToDstArray[12], const SkMatrix44& srcToDstMatrix) {
// Build the following row major matrix:
// rX gX bX 0
// rY gY bY 0
// rZ gZ bZ 0
- // Swap R and B if necessary to make sure that we output SkPMColor order.
-#ifdef SK_PMCOLOR_IS_BGRA
- srcToDstArray[0] = srcToDstMatrix.getFloat(0, 2);
- srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1);
- srcToDstArray[2] = srcToDstMatrix.getFloat(0, 0);
- srcToDstArray[3] = 0.0f;
- srcToDstArray[4] = srcToDstMatrix.getFloat(1, 2);
- srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1);
- srcToDstArray[6] = srcToDstMatrix.getFloat(1, 0);
- srcToDstArray[7] = 0.0f;
- srcToDstArray[8] = srcToDstMatrix.getFloat(2, 2);
- srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1);
- srcToDstArray[10] = srcToDstMatrix.getFloat(2, 0);
- srcToDstArray[11] = 0.0f;
-#else
srcToDstArray[0] = srcToDstMatrix.getFloat(0, 0);
srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1);
srcToDstArray[2] = srcToDstMatrix.getFloat(0, 2);
@@ -426,7 +413,6 @@ static void build_src_to_dst(float srcToDstArray[12], const SkMatrix44& srcToDst
srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1);
srcToDstArray[10] = srcToDstMatrix.getFloat(2, 2);
srcToDstArray[11] = 0.0f;
-#endif
}
template <SkColorSpace::GammaNamed Dst>
@@ -506,6 +492,9 @@ SkFastXform<Dst>::SkFastXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatri
}
// Build tables to transform linear to dst gamma.
+ // FIXME (msarett):
+ // Should we spend all of this time bulding the dst gamma tables when the client only
+ // wants to convert to F16?
switch (dstSpace->gammaNamed()) {
case SkColorSpace::kSRGB_GammaNamed:
case SkColorSpace::k2Dot2Curve_GammaNamed:
@@ -579,25 +568,32 @@ SkFastXform<Dst>::SkFastXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatri
template <>
void SkFastXform<SkColorSpace::kSRGB_GammaNamed>
-::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const
+::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const
{
SkOpts::color_xform_RGB1_to_srgb(dst, src, len, fSrcGammaTables, fSrcToDst);
}
template <>
void SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed>
-::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const
+::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const
{
SkOpts::color_xform_RGB1_to_2dot2(dst, src, len, fSrcGammaTables, fSrcToDst);
}
template <>
void SkFastXform<SkColorSpace::kNonStandard_GammaNamed>
-::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const
+::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const
{
SkOpts::color_xform_RGB1_to_table(dst, src, len, fSrcGammaTables, fSrcToDst, fDstGammaTables);
}
+template <SkColorSpace::GammaNamed T>
+void SkFastXform<T>
+::applyToF16(RGBAF16* dst, const RGBA32* src, int len) const
+{
+ SkOpts::color_xform_RGB1_to_linear(dst, src, len, fSrcGammaTables, fSrcToDst);
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////
SkDefaultXform::SkDefaultXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatrix44& srcToDst,
@@ -857,7 +853,7 @@ static void interp_3d_clut(float dst[3], float src[3], const SkColorLookUpTable*
}
}
-void SkDefaultXform::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const {
+void SkDefaultXform::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const {
while (len-- > 0) {
uint8_t r = (*src >> 0) & 0xFF,
g = (*src >> 8) & 0xFF,
@@ -912,3 +908,9 @@ void SkDefaultXform::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_
src++;
}
}
+
+void SkDefaultXform::applyToF16(RGBAF16* dst, const RGBA32* src, int len) const {
+ // FIXME (msarett):
+ // Planning to delete SkDefaultXform. Not going to bother to implement this.
+ memset(dst, 0, len * sizeof(RGBAF16));
+}
diff --git a/src/core/SkColorSpaceXform.h b/src/core/SkColorSpaceXform.h
index e09a7252ba..16b8cfaa33 100644
--- a/src/core/SkColorSpaceXform.h
+++ b/src/core/SkColorSpaceXform.h
@@ -14,6 +14,9 @@
class SkColorSpaceXform : SkNoncopyable {
public:
+ typedef uint32_t RGBA32;
+ typedef uint64_t RGBAF16;
+
/**
* Create an object to handle color space conversions.
*
@@ -26,10 +29,11 @@ public:
/**
* Apply the color conversion to a src buffer, storing the output in the dst buffer.
- * The src is opaque and stored in RGBA_8888, and the dst is also opaque and stored
- * in 8888 platform format.
+ * The src is stored as RGBA (8888) and is treated as opaque.
+ * TODO (msarett): Support non-opaque srcs.
*/
- virtual void xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const = 0;
+ virtual void applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const = 0;
+ virtual void applyToF16(RGBAF16* dst, const RGBA32* src, int len) const = 0;
virtual ~SkColorSpaceXform() {}
};
@@ -38,7 +42,8 @@ template <SkColorSpace::GammaNamed Dst>
class SkFastXform : public SkColorSpaceXform {
public:
- void xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const override;
+ void applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const override;
+ void applyToF16(RGBAF16* dst, const RGBA32* src, int len) const override;
private:
SkFastXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatrix44& srcToDst,
@@ -62,10 +67,14 @@ private:
/**
* Works for any valid src and dst profiles.
*/
+// TODO (msarett):
+// Merge with SkFastXform and delete this. SkFastXform can almost do everything that
+// this does.
class SkDefaultXform : public SkColorSpaceXform {
public:
- void xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const override;
+ void applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const override;
+ void applyToF16(RGBAF16* dst, const RGBA32* src, int len) const override;
private:
SkDefaultXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatrix44& srcToDst,
diff --git a/src/core/SkOpts.cpp b/src/core/SkOpts.cpp
index bc9ec536ac..c577bf9603 100644
--- a/src/core/SkOpts.cpp
+++ b/src/core/SkOpts.cpp
@@ -75,6 +75,7 @@ namespace SkOpts {
DEFINE_DEFAULT(color_xform_RGB1_to_2dot2);
DEFINE_DEFAULT(color_xform_RGB1_to_srgb);
DEFINE_DEFAULT(color_xform_RGB1_to_table);
+ DEFINE_DEFAULT(color_xform_RGB1_to_linear);
#undef DEFINE_DEFAULT
// Each Init_foo() is defined in src/opts/SkOpts_foo.cpp.
diff --git a/src/core/SkOpts.h b/src/core/SkOpts.h
index 2bf4bdabde..7acceef6a6 100644
--- a/src/core/SkOpts.h
+++ b/src/core/SkOpts.h
@@ -66,7 +66,7 @@ namespace SkOpts {
// If nsrc < ndst, we loop over src to create a pattern.
extern void (*srcover_srgb_srgb)(uint32_t* dst, const uint32_t* src, int ndst, int nsrc);
- // Color xform RGB1 pixels into SkPMColor order.
+ // Color xform RGB1 pixels.
extern void (*color_xform_RGB1_to_2dot2) (uint32_t* dst, const uint32_t* src, int len,
const float* const srcTables[3],
const float srcToDstMatrix[12]);
@@ -77,6 +77,9 @@ namespace SkOpts {
const float* const srcTables[3],
const float srcToDstMatrix[12],
const uint8_t* const dstTables[3]);
+ extern void (*color_xform_RGB1_to_linear)(uint64_t* dst, const uint32_t* src, int len,
+ const float* const srcTables[3],
+ const float srcToDstMatrix[12]);
}
diff --git a/src/opts/SkColorXform_opts.h b/src/opts/SkColorXform_opts.h
index 72ef35381e..e7a2b45946 100644
--- a/src/opts/SkColorXform_opts.h
+++ b/src/opts/SkColorXform_opts.h
@@ -10,7 +10,9 @@
#include "SkNx.h"
#include "SkColorPriv.h"
+#include "SkHalf.h"
#include "SkSRGB.h"
+#include "SkTemplates.h"
namespace SK_OPTS_NS {
@@ -31,13 +33,17 @@ static Sk4f clamp_0_to_255(const Sk4f& x) {
}
enum DstGamma {
+ // 8888
kSRGB_DstGamma,
k2Dot2_DstGamma,
kTable_DstGamma,
+
+ // F16
+ kLinear_DstGamma,
};
template <DstGamma kDstGamma>
-static void color_xform_RGB1(uint32_t* dst, const uint32_t* src, int len,
+static void color_xform_RGB1(void* dst, const uint32_t* src, int len,
const float* const srcTables[3], const float matrix[16],
const uint8_t* const dstTables[3]) {
Sk4f rXgXbX = Sk4f::Load(matrix + 0),
@@ -84,12 +90,14 @@ static void color_xform_RGB1(uint32_t* dst, const uint32_t* src, int len,
dstGreens = clamp_0_to_255(dstGreens);
dstBlues = clamp_0_to_255(dstBlues);
- auto rgba = (Sk4f_round(dstReds) )
- | (Sk4f_round(dstGreens) << 8)
- | (Sk4f_round(dstBlues) << 16)
- | (Sk4i{ 0xFF << 24});
- rgba.store(dst);
- } else {
+ auto rgba = (Sk4f_round(dstReds) << SK_R32_SHIFT)
+ | (Sk4f_round(dstGreens) << SK_G32_SHIFT)
+ | (Sk4f_round(dstBlues) << SK_B32_SHIFT)
+ | (Sk4i{ 0xFF << SK_A32_SHIFT});
+ rgba.store((uint32_t*) dst);
+
+ dst = SkTAddOffset<void>(dst, 4 * sizeof(uint32_t));
+ } else if (kTable_DstGamma == kDstGamma) {
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);
@@ -98,25 +106,38 @@ static void color_xform_RGB1(uint32_t* dst, const uint32_t* src, int len,
Sk4i indicesGreens = Sk4f_round(scaledGreens);
Sk4i indicesBlues = Sk4f_round(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;
+ uint32_t* dst32 = (uint32_t*) dst;
+ dst32[0] = dstTables[0][indicesReds [0]] << SK_R32_SHIFT
+ | dstTables[1][indicesGreens[0]] << SK_G32_SHIFT
+ | dstTables[2][indicesBlues [0]] << SK_B32_SHIFT
+ | 0xFF << SK_A32_SHIFT;
+ dst32[1] = dstTables[0][indicesReds [1]] << SK_R32_SHIFT
+ | dstTables[1][indicesGreens[1]] << SK_G32_SHIFT
+ | dstTables[2][indicesBlues [1]] << SK_B32_SHIFT
+ | 0xFF << SK_A32_SHIFT;
+ dst32[2] = dstTables[0][indicesReds [2]] << SK_R32_SHIFT
+ | dstTables[1][indicesGreens[2]] << SK_G32_SHIFT
+ | dstTables[2][indicesBlues [2]] << SK_B32_SHIFT
+ | 0xFF << SK_A32_SHIFT;
+ dst32[3] = dstTables[0][indicesReds [3]] << SK_R32_SHIFT
+ | dstTables[1][indicesGreens[3]] << SK_G32_SHIFT
+ | dstTables[2][indicesBlues [3]] << SK_B32_SHIFT
+ | 0xFF << SK_A32_SHIFT;
+
+ dst = SkTAddOffset<void>(dst, 4 * sizeof(uint32_t));
+ } else {
+ // FIXME (msarett):
+ // Can we do better here? Should we store half floats as planar?
+ // Should we write Intel/Arm specific code? Should we add a transpose
+ // function to SkNx? Should we rewrite the algorithm to be interleaved?
+ uint64_t* dst64 = (uint64_t*) dst;
+ dst64[0] = SkFloatToHalf_finite(Sk4f(dstReds[0], dstGreens[0], dstBlues[0], 1.0f));
+ dst64[1] = SkFloatToHalf_finite(Sk4f(dstReds[1], dstGreens[1], dstBlues[1], 1.0f));
+ dst64[2] = SkFloatToHalf_finite(Sk4f(dstReds[2], dstGreens[2], dstBlues[2], 1.0f));
+ dst64[3] = SkFloatToHalf_finite(Sk4f(dstReds[3], dstGreens[3], dstBlues[3], 1.0f));
+
+ dst = SkTAddOffset<void>(dst, 4 * sizeof(uint64_t));
}
-
- dst += 4;
};
load_next_4();
@@ -137,7 +158,6 @@ static void color_xform_RGB1(uint32_t* dst, const uint32_t* src, int len,
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;
if (kSRGB_DstGamma == kDstGamma || k2Dot2_DstGamma == kDstGamma) {
@@ -151,40 +171,54 @@ static void color_xform_RGB1(uint32_t* dst, const uint32_t* src, int len,
uint32_t rgba;
SkNx_cast<uint8_t>(Sk4f_round(dstPixel)).store(&rgba);
rgba |= 0xFF000000;
- *dst = rgba;
- } else {
+ *((uint32_t*) dst) = SkSwizzle_RGBA_to_PMColor(rgba);
+ dst = SkTAddOffset<void>(dst, sizeof(uint32_t));
+ } else if (kTable_DstGamma == kDstGamma) {
Sk4f scaledPixel = Sk4f::Min(Sk4f::Max(1023.0f * dstPixel, 0.0f), 1023.0f);
Sk4i indices = Sk4f_round(scaledPixel);
- *dst = dstTables[0][indices[0]]
- | dstTables[1][indices[1]] << 8
- | dstTables[2][indices[2]] << 16
- | 0xFF << 24;
+ *((uint32_t*) dst) = dstTables[0][indices[0]] << SK_R32_SHIFT
+ | dstTables[1][indices[1]] << SK_G32_SHIFT
+ | dstTables[2][indices[2]] << SK_B32_SHIFT
+ | 0xFF << SK_A32_SHIFT;
+
+ dst = SkTAddOffset<void>(dst, sizeof(uint32_t));
+ } else {
+ uint64_t rgba = SkFloatToHalf_finite(dstPixel);
+
+ // Set alpha to 1.0
+ rgba |= 0x3C00000000000000;
+ *((uint64_t*) dst) = rgba;
+ dst = SkTAddOffset<void>(dst, sizeof(uint64_t));
}
- dst += 1;
src += 1;
len -= 1;
}
}
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]) {
+ const float* const srcTables[3], const float matrix[12]) {
color_xform_RGB1<k2Dot2_DstGamma>(dst, src, len, srcTables, matrix, nullptr);
}
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]) {
+ const float* const srcTables[3], const float matrix[12]) {
color_xform_RGB1<kSRGB_DstGamma>(dst, src, len, srcTables, matrix, nullptr);
}
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 float* const srcTables[3], const float matrix[12],
const uint8_t* const dstTables[3]) {
color_xform_RGB1<kTable_DstGamma>(dst, src, len, srcTables, matrix, dstTables);
}
+static void color_xform_RGB1_to_linear(uint64_t* dst, const uint32_t* src, int len,
+ const float* const srcTables[3], const float matrix[12]) {
+ color_xform_RGB1<kLinear_DstGamma>(dst, src, len, srcTables, matrix, nullptr);
+}
+
} // namespace SK_OPTS_NS
#endif // SkColorXform_opts_DEFINED
diff --git a/src/opts/SkOpts_sse41.cpp b/src/opts/SkOpts_sse41.cpp
index 56ac386333..e1e024d948 100644
--- a/src/opts/SkOpts_sse41.cpp
+++ b/src/opts/SkOpts_sse41.cpp
@@ -24,5 +24,6 @@ namespace SkOpts {
color_xform_RGB1_to_2dot2 = sse41::color_xform_RGB1_to_2dot2;
color_xform_RGB1_to_srgb = sse41::color_xform_RGB1_to_srgb;
color_xform_RGB1_to_table = sse41::color_xform_RGB1_to_table;
+ color_xform_RGB1_to_linear = sse41::color_xform_RGB1_to_linear;
}
}
diff --git a/tests/ColorSpaceXformTest.cpp b/tests/ColorSpaceXformTest.cpp
index b5df1e1e72..2b5db2bbe4 100644
--- a/tests/ColorSpaceXformTest.cpp
+++ b/tests/ColorSpaceXformTest.cpp
@@ -45,7 +45,7 @@ static void test_xform(skiatest::Reporter* r, const sk_sp<SkGammas>& gammas) {
// Create and perform xform
std::unique_ptr<SkColorSpaceXform> xform =
ColorSpaceXformTest::CreateDefaultXform(gammas, srcToDst, gammas);
- xform->xform_RGB1_8888(dstPixels, srcPixels, width);
+ xform->applyTo8888(dstPixels, srcPixels, width);
// Since the matrix is the identity, and the gamma curves match, the pixels
// should be unchanged.
diff --git a/tools/viewer/ImageSlide.cpp b/tools/viewer/ImageSlide.cpp
index 0eb3b0a6ce..3ba6b58460 100644
--- a/tools/viewer/ImageSlide.cpp
+++ b/tools/viewer/ImageSlide.cpp
@@ -47,7 +47,7 @@ void ImageSlide::load(SkScalar, SkScalar) {
fOriginalBitmap.deepCopyTo(&fXformedBitmap);
uint32_t* row = (uint32_t*) fXformedBitmap.getPixels();
for (int y = 0; y < fXformedBitmap.height(); y++) {
- xform->xform_RGB1_8888(row, row, fXformedBitmap.width());
+ xform->applyTo8888(row, row, fXformedBitmap.width());
row = SkTAddOffset<uint32_t>(row, fXformedBitmap.rowBytes());
}
fXformedBitmap.notifyPixelsChanged(); // This is needed for the deepCopy