From 7a0248f738dff64b95dc8e3f13e10984c3c27ebc Mon Sep 17 00:00:00 2001 From: Ben Wagner Date: Wed, 18 Oct 2017 11:30:56 -0400 Subject: [PATCH] Compute inverse gamma table at compile time. This introduces skstd::index_sequence and skstd::make_index_sequence so that these can be used in C++11. These are mostly equivalent to their std:: counterparts. This also introduces SkMakeArray which is constexpr and creates a std::array with N elements with each element being initialized with the value of C(i) where i is the index of the element. These are then used to create inverse gamma table at compile time. This avoids threading issues. BUG=skia:7187 Change-Id: I61fb10a778898652e546d54c104a08d6e6bf88d3 Reviewed-on: https://skia-review.googlesource.com/61380 Commit-Queue: Ben Wagner Reviewed-by: Mike Klein --- include/private/SkTLogic.h | 22 ++++++++++++++++++++++ include/private/SkTemplates.h | 11 +++++++++++ src/ports/SkFontHost_mac.cpp | 22 +++++----------------- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/include/private/SkTLogic.h b/include/private/SkTLogic.h index 6d6dc49535..cc76d7b618 100644 --- a/include/private/SkTLogic.h +++ b/include/private/SkTLogic.h @@ -14,6 +14,7 @@ #ifndef SkTLogic_DEFINED #define SkTLogic_DEFINED +#include #include #include #include @@ -39,6 +40,8 @@ template using add_cv_t = typename std::add_cv::type; template using add_pointer_t = typename std::add_pointer::type; template using add_lvalue_reference_t = typename std::add_lvalue_reference::type; +template using result_of_t = typename std::result_of::type; + template using common_type_t = typename std::common_type::type; // Chromium currently requires gcc 4.8.2 or a recent clang compiler, but uses libstdc++4.6.4. @@ -64,6 +67,25 @@ template using is_trivially_destructible = std::is_trivially_destru #endif template using underlying_type_t = typename skstd::underlying_type::type; + +template struct index_sequence { + using type = index_sequence; + using value_type = size_t; + static constexpr std::size_t size() noexcept { return sizeof...(Ints); } +}; + +template struct make_index_sequence_combine; +template +struct make_index_sequence_combine, skstd::index_sequence> + : skstd::index_sequence +{ }; + +template struct make_index_sequence + : make_index_sequence_combine::type, + typename skstd::make_index_sequence::type>{}; +template<> struct make_index_sequence<0> : skstd::index_sequence< >{}; +template<> struct make_index_sequence<1> : skstd::index_sequence<0>{}; + } // namespace skstd // The sknonstd namespace contains things we would like to be proposed and feel std-ish. diff --git a/include/private/SkTemplates.h b/include/private/SkTemplates.h index 5ebf13ac36..efe2ed306b 100644 --- a/include/private/SkTemplates.h +++ b/include/private/SkTemplates.h @@ -483,4 +483,15 @@ private: using SkAutoFree = std::unique_ptr>; +template +constexpr auto SkMakeArrayFromIndexSequence(C c, skstd::index_sequence) +-> std::array, sizeof...(Is)> { + return {{ c(Is)... }}; +} + +template constexpr auto SkMakeArray(C c) +-> std::array, N> { + return SkMakeArrayFromIndexSequence(c, skstd::make_index_sequence{}); +} + #endif diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp index 8fadb805a2..57a37a11f7 100644 --- a/src/ports/SkFontHost_mac.cpp +++ b/src/ports/SkFontHost_mac.cpp @@ -1056,12 +1056,8 @@ void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { #include "SkColorData.h" -static void build_power_table(uint8_t table[]) { - for (int i = 0; i < 256; i++) { - float x = i / 255.f; - int xx = SkScalarRoundToInt(x * x * 255); - table[i] = SkToU8(xx); - } +static constexpr uint8_t sk_pow2_table(size_t i) { + return SkToU8(((i * i + 128) / 255)); } /** @@ -1071,15 +1067,7 @@ static void build_power_table(uint8_t table[]) { * CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value. * The color space used does not appear to affect this choice. */ -static const uint8_t* getInverseGammaTableCoreGraphicSmoothing() { - static bool gInited; - static uint8_t gTableCoreGraphicsSmoothing[256]; - if (!gInited) { - build_power_table(gTableCoreGraphicsSmoothing); - gInited = true; - } - return gTableCoreGraphicsSmoothing; -} +static constexpr auto gLinearCoverageFromCGLCDValue = SkMakeArray<256>(sk_pow2_table); static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) { while (count > 0) { @@ -1179,7 +1167,7 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { if ((glyph.fMaskFormat == SkMask::kLCD16_Format) || (glyph.fMaskFormat == SkMask::kA8_Format && supports_LCD() && generateA8FromLCD)) { - const uint8_t* table = getInverseGammaTableCoreGraphicSmoothing(); + const uint8_t* linear = gLinearCoverageFromCGLCDValue.data(); //Note that the following cannot really be integrated into the //pre-blend, since we may not be applying the pre-blend; when we aren't @@ -1192,7 +1180,7 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { int r = (addr[x] >> 16) & 0xFF; int g = (addr[x] >> 8) & 0xFF; int b = (addr[x] >> 0) & 0xFF; - addr[x] = (table[r] << 16) | (table[g] << 8) | table[b]; + addr[x] = (linear[r] << 16) | (linear[g] << 8) | linear[b]; } addr = SkTAddOffset(addr, cgRowBytes); }