diff options
author | reed <reed@google.com> | 2016-02-05 11:18:39 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-05 11:18:39 -0800 |
commit | 3601f280dc400cb75167393b0a2b6670b5f25ea4 (patch) | |
tree | a8aa9ff7658b049ca0aec0ea1729921122fe22d0 | |
parent | 06604b95622359640a1c2028b885646deda28d52 (diff) |
add kRGBA_F16_SkColorType
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1666343002
Review URL: https://codereview.chromium.org/1666343002
-rw-r--r-- | include/core/SkColor.h | 5 | ||||
-rw-r--r-- | include/core/SkImageInfo.h | 5 | ||||
-rw-r--r-- | include/core/SkPixmap.h | 59 | ||||
-rw-r--r-- | src/core/SkColor.cpp | 38 | ||||
-rw-r--r-- | src/core/SkPixmap.cpp | 35 | ||||
-rw-r--r-- | src/gpu/SkGr.cpp | 2 | ||||
-rw-r--r-- | tests/Float16Test.cpp | 52 |
7 files changed, 171 insertions, 25 deletions
diff --git a/include/core/SkColor.h b/include/core/SkColor.h index 90453f548c..b1571c7009 100644 --- a/include/core/SkColor.h +++ b/include/core/SkColor.h @@ -180,6 +180,11 @@ struct SkPM4f { static SkPM4f FromPMColor(SkPMColor); + // half-float routines + void toF16(uint16_t[4]) const; + uint64_t toF16() const; // 4 float16 values packed into uint64_t + static SkPM4f FromF16(const uint16_t[4]); + #ifdef SK_DEBUG void assertIsUnit() const; #else diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h index 4b82ae6e2f..b2dda3f021 100644 --- a/include/core/SkImageInfo.h +++ b/include/core/SkImageInfo.h @@ -73,8 +73,9 @@ enum SkColorType { kBGRA_8888_SkColorType, kIndex_8_SkColorType, kGray_8_SkColorType, + kRGBA_F16_SkColorType, - kLastEnum_SkColorType = kGray_8_SkColorType, + kLastEnum_SkColorType = kRGBA_F16_SkColorType, #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) kN32_SkColorType = kBGRA_8888_SkColorType, @@ -95,6 +96,7 @@ static int SkColorTypeBytesPerPixel(SkColorType ct) { 4, // BGRA_8888 1, // kIndex_8 1, // kGray_8 + 8, // kRGBA_F16 }; static_assert(SK_ARRAY_COUNT(gSize) == (size_t)(kLastEnum_SkColorType + 1), "size_mismatch_with_SkColorType_enum"); @@ -114,6 +116,7 @@ static inline bool SkColorTypeIsValid(unsigned value) { static inline size_t SkColorTypeComputeOffset(SkColorType ct, int x, int y, size_t rowBytes) { int shift = 0; switch (SkColorTypeBytesPerPixel(ct)) { + case 8: shift = 3; break; case 4: shift = 2; break; case 2: shift = 1; break; case 1: shift = 0; break; diff --git a/include/core/SkPixmap.h b/include/core/SkPixmap.h index 523c40f294..894b238196 100644 --- a/include/core/SkPixmap.h +++ b/include/core/SkPixmap.h @@ -75,51 +75,75 @@ public: uint64_t getSafeSize64() const { return fInfo.getSafeSize64(fRowBytes); } size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); } + const void* addr(int x, int y) const { + return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes); + } + const uint8_t* addr8() const { + SkASSERT(1 == SkColorTypeBytesPerPixel(fInfo.colorType())); + return reinterpret_cast<const uint8_t*>(fPixels); + } + const uint16_t* addr16() const { + SkASSERT(2 == SkColorTypeBytesPerPixel(fInfo.colorType())); + return reinterpret_cast<const uint16_t*>(fPixels); + } const uint32_t* addr32() const { SkASSERT(4 == SkColorTypeBytesPerPixel(fInfo.colorType())); return reinterpret_cast<const uint32_t*>(fPixels); } - - const uint16_t* addr16() const { - SkASSERT(2 == SkColorTypeBytesPerPixel(fInfo.colorType())); + const uint64_t* addr64() const { + SkASSERT(8 == SkColorTypeBytesPerPixel(fInfo.colorType())); + return reinterpret_cast<const uint64_t*>(fPixels); + } + const uint16_t* addrF16() const { + SkASSERT(8 == SkColorTypeBytesPerPixel(fInfo.colorType())); + SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType()); return reinterpret_cast<const uint16_t*>(fPixels); } - const uint8_t* addr8() const { - SkASSERT(1 == SkColorTypeBytesPerPixel(fInfo.colorType())); - return reinterpret_cast<const uint8_t*>(fPixels); - } + // Offset by the specified x,y coordinates - const uint32_t* addr32(int x, int y) const { + const uint8_t* addr8(int x, int y) const { SkASSERT((unsigned)x < (unsigned)fInfo.width()); SkASSERT((unsigned)y < (unsigned)fInfo.height()); - return (const uint32_t*)((const char*)this->addr32() + y * fRowBytes + (x << 2)); + return (const uint8_t*)((const char*)this->addr8() + y * fRowBytes + (x << 0)); } const uint16_t* addr16(int x, int y) const { SkASSERT((unsigned)x < (unsigned)fInfo.width()); SkASSERT((unsigned)y < (unsigned)fInfo.height()); return (const uint16_t*)((const char*)this->addr16() + y * fRowBytes + (x << 1)); } - const uint8_t* addr8(int x, int y) const { + const uint32_t* addr32(int x, int y) const { SkASSERT((unsigned)x < (unsigned)fInfo.width()); SkASSERT((unsigned)y < (unsigned)fInfo.height()); - return (const uint8_t*)((const char*)this->addr8() + y * fRowBytes + (x << 0)); + return (const uint32_t*)((const char*)this->addr32() + y * fRowBytes + (x << 2)); } - const void* addr(int x, int y) const { - return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes); + const uint64_t* addr64(int x, int y) const { + SkASSERT((unsigned)x < (unsigned)fInfo.width()); + SkASSERT((unsigned)y < (unsigned)fInfo.height()); + return (const uint64_t*)((const char*)this->addr64() + y * fRowBytes + (x << 3)); + } + const uint16_t* addrF16(int x, int y) const { + SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType()); + return reinterpret_cast<const uint16_t*>(this->addr64(x, y)); } // Writable versions void* writable_addr() const { return const_cast<void*>(fPixels); } - uint32_t* writable_addr32(int x, int y) const { - return const_cast<uint32_t*>(this->addr32(x, y)); + uint8_t* writable_addr8(int x, int y) const { + return const_cast<uint8_t*>(this->addr8(x, y)); } uint16_t* writable_addr16(int x, int y) const { return const_cast<uint16_t*>(this->addr16(x, y)); } - uint8_t* writable_addr8(int x, int y) const { - return const_cast<uint8_t*>(this->addr8(x, y)); + uint32_t* writable_addr32(int x, int y) const { + return const_cast<uint32_t*>(this->addr32(x, y)); + } + uint64_t* writable_addr64(int x, int y) const { + return const_cast<uint64_t*>(this->addr64(x, y)); + } + uint16_t* writable_addrF16(int x, int y) const { + return reinterpret_cast<uint16_t*>(writable_addr64(x, y)); } // copy methods @@ -152,6 +176,7 @@ public: bool erase(SkColor, const SkIRect& subset) const; bool erase(SkColor color) const { return this->erase(color, this->bounds()); } + bool erase(const SkColor4f&, const SkIRect* subset = nullptr) const; private: const void* fPixels; diff --git a/src/core/SkColor.cpp b/src/core/SkColor.cpp index 87e3a9d60e..c0a3895bbe 100644 --- a/src/core/SkColor.cpp +++ b/src/core/SkColor.cpp @@ -103,6 +103,7 @@ SkColor SkHSVToColor(U8CPU a, const SkScalar hsv[3]) { /////////////////////////////////////////////////////////////////////////////////////////////////// #include "SkNx.h" +#include "SkHalf.h" SkPM4f SkPM4f::FromPMColor(SkPMColor c) { Sk4f value = SkNx_cast<float>(Sk4b::Load(&c)); @@ -121,6 +122,36 @@ SkColor4f SkPM4f::unpremul() const { } } +void SkPM4f::toF16(uint16_t half[4]) const { + for (int i = 0; i < 4; ++i) { + half[i] = SkFloatToHalf(fVec[i]); + } +} + +uint64_t SkPM4f::toF16() const { + uint64_t value; + this->toF16(reinterpret_cast<uint16_t*>(&value)); + return value; +} + +SkPM4f SkPM4f::FromF16(const uint16_t half[4]) { + return {{ + SkHalfToFloat(half[0]), + SkHalfToFloat(half[1]), + SkHalfToFloat(half[2]), + SkHalfToFloat(half[3]) + }}; +} + +#ifdef SK_DEBUG +void SkPM4f::assertIsUnit() const { + auto c4 = Sk4f::Load(fVec); + SkASSERT((c4 >= Sk4f(0)).allTrue() && (c4 <= Sk4f(1)).allTrue()); +} +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////// + SkColor4f SkColor4f::FromColor(SkColor c) { Sk4f value = SkNx_shuffle<3,2,1,0>(SkNx_cast<float>(Sk4b::Load(&c))); SkColor4f c4; @@ -151,10 +182,3 @@ SkPM4f SkColor4f::premul() const { dst.store(&pm4); return pm4; } - -#ifdef SK_DEBUG -void SkPM4f::assertIsUnit() const { - auto c4 = Sk4f::Load(fVec); - SkASSERT((c4 >= Sk4f(0)).allTrue() && (c4 <= Sk4f(1)).allTrue()); -} -#endif diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp index e2d4d30ebf..f28566871a 100644 --- a/src/core/SkPixmap.cpp +++ b/src/core/SkPixmap.cpp @@ -207,6 +207,41 @@ bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const { return true; } +#include "SkNx.h" +#include "SkHalf.h" + +static void sk_memset64(uint64_t dst[], uint64_t value, int count) { + for (int i = 0; i < count; ++i) { + dst[i] = value; + } +} + +bool SkPixmap::erase(const SkColor4f& origColor, const SkIRect* subset) const { + SkPixmap pm; + if (subset) { + if (!this->extractSubset(&pm, *subset)) { + return false; + } + } else { + pm = *this; + } + + const SkColor4f color = origColor.pin(); + + if (kRGBA_F16_SkColorType != pm.colorType()) { + Sk4f c4 = Sk4f::Load(color.vec()); + SkColor c; + (c4 * Sk4f(255) + Sk4f(0.5f)).store(&c); + return pm.erase(c); + } + + const uint64_t half4 = color.premul().toF16(); + for (int y = 0; y < pm.height(); ++y) { + sk_memset64(pm.writable_addr64(0, y), half4, pm.width()); + } + return true; +} + #include "SkBitmap.h" #include "SkCanvas.h" #include "SkSurface.h" diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index 62b7ff14ea..e4dc467e7f 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -318,6 +318,8 @@ GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProf return kIndex_8_GrPixelConfig; case kGray_8_SkColorType: return kAlpha_8_GrPixelConfig; // TODO: gray8 support on gpu + case kRGBA_F16_SkColorType: + return kRGBA_half_GrPixelConfig; } SkASSERT(0); // shouldn't get here return kUnknown_GrPixelConfig; diff --git a/tests/Float16Test.cpp b/tests/Float16Test.cpp new file mode 100644 index 0000000000..0a2c3d5d6b --- /dev/null +++ b/tests/Float16Test.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "Test.h" +#include "SkColor.h" +#include "SkHalf.h" +#include "SkPixmap.h" + +static bool eq_within_half_float(float a, float b) { + const float kTolerance = 1.0f / (1 << (8 + 10)); + + SkHalf ha = SkFloatToHalf(a); + SkHalf hb = SkFloatToHalf(b); + float a2 = SkHalfToFloat(ha); + float b2 = SkHalfToFloat(hb); + return fabsf(a2 - b2) <= kTolerance; +} + +static bool eq_within_half_float(const SkPM4f& a, const SkPM4f& b) { + for (int i = 0; i < 4; ++i) { + if (!eq_within_half_float(a.fVec[i], b.fVec[i])) { + return false; + } + } + return true; +} + +DEF_TEST(color_half_float, reporter) { + const int w = 100; + const int h = 100; + + SkImageInfo info = SkImageInfo::Make(w, h, kRGBA_F16_SkColorType, kPremul_SkAlphaType); + + SkAutoPixmapStorage pm; + pm.alloc(info); + REPORTER_ASSERT(reporter, pm.getSafeSize() == SkToSizeT(w * h * sizeof(uint64_t))); + + SkColor4f c4 { 0.5f, 1, 0.5f, 0.25f }; + pm.erase(c4); + + SkPM4f origpm4 = c4.premul(); + for (int y = 0; y < pm.height(); ++y) { + for (int x = 0; x < pm.width(); ++x) { + SkPM4f pm4 = SkPM4f::FromF16(pm.addrF16(x, y)); + REPORTER_ASSERT(reporter, eq_within_half_float(origpm4, pm4)); + } + } +} |