From 4d6cc442b2d6952cd0dcb9d942ef2e9b417c1663 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Sun, 12 Jan 2020 20:00:16 -0800 Subject: [PATCH] libobs: Add basic support for half floats --- libobs/CMakeLists.txt | 1 + libobs/graphics/half.h | 102 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 libobs/graphics/half.h diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt index a0d9eef78..e7a5387d5 100644 --- a/libobs/CMakeLists.txt +++ b/libobs/CMakeLists.txt @@ -289,6 +289,7 @@ set(libobs_graphics_SOURCES graphics/math-extra.c graphics/graphics-imports.c) set(libobs_graphics_HEADERS + graphics/half.h graphics/plane.h graphics/quat.h graphics/input.h diff --git a/libobs/graphics/half.h b/libobs/graphics/half.h new file mode 100644 index 000000000..6d45b3f84 --- /dev/null +++ b/libobs/graphics/half.h @@ -0,0 +1,102 @@ +/****************************************************************************** + Copyright (C) 2020 by Hugh Bailey + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +/****************************************************************************** + The MIT License (MIT) + +Copyright (c) 2011-2019 Microsoft Corp + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be included in all copies +or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + +#pragma once + +#include "math-defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct half { + uint16_t u; +}; + +/* adapted from DirectXMath XMConvertFloatToHalf */ +inline struct half half_from_float(float f) +{ + uint32_t Result; + + uint32_t IValue; + memcpy(&IValue, &f, sizeof(IValue)); + uint32_t Sign = (IValue & 0x80000000U) >> 16U; + IValue = IValue & 0x7FFFFFFFU; // Hack off the sign + + if (IValue > 0x477FE000U) { + // The number is too large to be represented as a half. Saturate to infinity. + if (((IValue & 0x7F800000) == 0x7F800000) && + ((IValue & 0x7FFFFF) != 0)) { + Result = 0x7FFF; // NAN + } else { + Result = 0x7C00U; // INF + } + } else if (!IValue) { + Result = 0; + } else { + if (IValue < 0x38800000U) { + // The number is too small to be represented as a normalized half. + // Convert it to a denormalized value. + uint32_t Shift = 113U - (IValue >> 23U); + IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift; + } else { + // Rebias the exponent to represent the value as a normalized half. + IValue += 0xC8000000U; + } + + Result = ((IValue + 0x0FFFU + ((IValue >> 13U) & 1U)) >> 13U) & + 0x7FFFU; + } + + struct half h; + h.u = (uint16_t)(Result | Sign); + return h; +} + +inline struct half half_from_bits(uint16_t u) +{ + struct half h; + h.u = u; + return h; +} + +#ifdef __cplusplus +} +#endif