LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkHalf.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 18 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2014 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkHalf_DEFINED
       9             : #define SkHalf_DEFINED
      10             : 
      11             : #include "SkNx.h"
      12             : #include "SkTypes.h"
      13             : 
      14             : // 16-bit floating point value
      15             : // format is 1 bit sign, 5 bits exponent, 10 bits mantissa
      16             : // only used for storage
      17             : typedef uint16_t SkHalf;
      18             : 
      19             : static constexpr uint16_t SK_HalfMin     = 0x0400; // 2^-24  (minimum positive normal value)
      20             : static constexpr uint16_t SK_HalfMax     = 0x7bff; // 65504
      21             : static constexpr uint16_t SK_HalfEpsilon = 0x1400; // 2^-10
      22             : static constexpr uint16_t SK_Half1       = 0x3C00; // 1
      23             : 
      24             : // convert between half and single precision floating point
      25             : float SkHalfToFloat(SkHalf h);
      26             : SkHalf SkFloatToHalf(float f);
      27             : 
      28             : // Convert between half and single precision floating point,
      29             : // assuming inputs and outputs are both finite, and may
      30             : // flush values which would be denormal half floats to zero.
      31             : static inline Sk4f SkHalfToFloat_finite_ftz(uint64_t);
      32             : static inline Sk4h SkFloatToHalf_finite_ftz(const Sk4f&);
      33             : 
      34             : // ~~~~~~~~~~~ impl ~~~~~~~~~~~~~~ //
      35             : 
      36             : // Like the serial versions in SkHalf.cpp, these are based on
      37             : // https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
      38             : 
      39             : // GCC 4.9 lacks the intrinsics to use ARMv8 f16<->f32 instructions, so we use inline assembly.
      40             : 
      41           0 : static inline Sk4f SkHalfToFloat_finite_ftz(const Sk4h& hs) {
      42             : #if !defined(SKNX_NO_SIMD) && defined(SK_CPU_ARM64)
      43             :     float32x4_t fs;
      44             :     asm ("fcvtl %[fs].4s, %[hs].4h   \n"   // vcvt_f32_f16(...)
      45             :         : [fs] "=w" (fs)                   // =w: write-only NEON register
      46             :         : [hs] "w" (hs.fVec));             //  w: read-only NEON register
      47             :     return fs;
      48             : #else
      49           0 :     Sk4i bits     = SkNx_cast<int>(hs),  // Expand to 32 bit.
      50           0 :          sign     = bits & 0x00008000,   // Save the sign bit for later...
      51           0 :          positive = bits ^ sign,         // ...but strip it off for now.
      52           0 :          is_norm  = 0x03ff < positive;   // Exponent > 0?
      53             : 
      54             :     // For normal half floats, extend the mantissa by 13 zero bits,
      55             :     // then adjust the exponent from 15 bias to 127 bias.
      56           0 :     Sk4i norm = (positive << 13) + ((127 - 15) << 23);
      57             : 
      58           0 :     Sk4i merged = (sign << 16) | (norm & is_norm);
      59           0 :     return Sk4f::Load(&merged);
      60             : #endif
      61             : }
      62             : 
      63           0 : static inline Sk4f SkHalfToFloat_finite_ftz(uint64_t hs) {
      64           0 :     return SkHalfToFloat_finite_ftz(Sk4h::Load(&hs));
      65             : }
      66             : 
      67           0 : static inline Sk4h SkFloatToHalf_finite_ftz(const Sk4f& fs) {
      68             : #if !defined(SKNX_NO_SIMD) && defined(SK_CPU_ARM64)
      69             :     float32x4_t vec = fs.fVec;
      70             :     asm ("fcvtn %[vec].4h, %[vec].4s  \n"   // vcvt_f16_f32(vec)
      71             :         : [vec] "+w" (vec));                // +w: read-write NEON register
      72             :     return vreinterpret_u16_f32(vget_low_f32(vec));
      73             : #else
      74           0 :     Sk4i bits         = Sk4i::Load(&fs),
      75           0 :          sign         = bits & 0x80000000,      // Save the sign bit for later...
      76           0 :          positive     = bits ^ sign,            // ...but strip it off for now.
      77           0 :          will_be_norm = 0x387fdfff < positive;  // greater than largest denorm half?
      78             : 
      79             :     // For normal half floats, adjust the exponent from 127 bias to 15 bias,
      80             :     // then drop the bottom 13 mantissa bits.
      81           0 :     Sk4i norm = (positive - ((127 - 15) << 23)) >> 13;
      82             : 
      83           0 :     Sk4i merged = (sign >> 16) | (will_be_norm & norm);
      84           0 :     return SkNx_cast<uint16_t>(merged);
      85             : #endif
      86             : }
      87             : 
      88             : #endif

Generated by: LCOV version 1.13