mirror of
https://github.com/love2d/love.git
synced 2026-08-12 16:40:57 +02:00
e71f95595c
Currently exposed formats are rgba8 and rgba16 (normalized), and rgba16f and rgba32f (floating-point). Some systems, especially mobile ones, won't support every format when creating a love.graphics Image. Use love.graphics.getRawImageFormats to check for support. love.image.newImageData now takes an optional format parameter as its third argument when creating an empty sized ImageData. It defaults to rgba8. 16-bit PNGs, .hdr images, and floating-point OpenEXR images can now be loaded via love.image.newImageData and love.graphics.newImage. --HG-- branch : minor
157 lines
3.8 KiB
C++
157 lines
3.8 KiB
C++
/**
|
|
* Copyright (c) 2006-2016 LOVE Development Team
|
|
*
|
|
* This software is provided 'as-is', without any express or implied
|
|
* warranty. In no event will the authors be held liable for any damages
|
|
* arising from the use of this software.
|
|
*
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
* including commercial applications, and to alter it and redistribute it
|
|
* freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software
|
|
* in a product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
* misrepresented as being the original software.
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
**/
|
|
|
|
#include "halffloat.h"
|
|
|
|
namespace love
|
|
{
|
|
|
|
// Code from ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf
|
|
|
|
static bool initialized = false;
|
|
|
|
// tables for half -> float conversions
|
|
static uint32 mantissatable[2048];
|
|
static uint16 offsettable[64];
|
|
static uint32 exponenttable[64];
|
|
|
|
// tables for float -> half conversions
|
|
static uint16 basetable[512];
|
|
static uint8 shifttable[512];
|
|
|
|
|
|
static uint32 convertMantissa(uint32 i)
|
|
{
|
|
uint32 m = i << 13; // Zero pad mantissa bits
|
|
uint32 e = 0; // Zero exponent
|
|
|
|
while (!(m & 0x00800000)) // While not normalized
|
|
{
|
|
e -= 0x00800000; // Decrement exponent (1<<23)
|
|
m <<= 1; // Shift mantissa
|
|
}
|
|
|
|
m &= ~(0x00800000); // Clear leading 1 bit
|
|
e += 0x38800000; // Adjust bias ((127-14)<<23)
|
|
|
|
return m | e; // Return combined number
|
|
}
|
|
|
|
void halfInit()
|
|
{
|
|
if (initialized)
|
|
return;
|
|
|
|
initialized = true;
|
|
|
|
|
|
// tables for half -> float conversions.
|
|
|
|
mantissatable[0] = 0;
|
|
|
|
for (uint32 i = 1; i < 1024; i++)
|
|
mantissatable[i] = convertMantissa(i);
|
|
|
|
for (uint32 i = 1024; i < 2048; i++)
|
|
mantissatable[i] = 0x38000000 + ((i - 1024) << 13);
|
|
|
|
exponenttable[0] = 0;
|
|
exponenttable[32] = 0x80000000;
|
|
|
|
for (uint32 i = 0; i < 31; i++)
|
|
exponenttable[i] = i << 23;
|
|
|
|
for (uint32 i = 33; i < 63; i++)
|
|
exponenttable[i] = 0x80000000 + ((i - 32) << 23);
|
|
|
|
exponenttable[31] = 0x47800000;
|
|
exponenttable[63] = 0xC7800000;
|
|
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
if (i == 0 || i == 32)
|
|
offsettable[i] = 0;
|
|
else
|
|
offsettable[i] = 1024;
|
|
}
|
|
|
|
|
|
// tables for float -> half conversions.
|
|
|
|
for (uint32 i = 0; i < 256; i++)
|
|
{
|
|
int e = (int) i - 127;
|
|
|
|
if (e < -24) // Very small numbers map to zero
|
|
{
|
|
basetable[i | 0x000] = 0x0000;
|
|
basetable[i | 0x100] = 0x8000;
|
|
shifttable[i | 0x000] = 24;
|
|
shifttable[i | 0x100] = 24;
|
|
}
|
|
else if (e < -14) // Small numbers map to denorms
|
|
{
|
|
basetable[i | 0x000] = (0x0400 >> (-e - 14));
|
|
basetable[i | 0x100] = (0x0400 >> (-e - 14)) | 0x8000;
|
|
shifttable[i | 0x000] = -e - 1;
|
|
shifttable[i | 0x100] = -e - 1;
|
|
}
|
|
else if (e <= 15) // Normal numbers just lose precision
|
|
{
|
|
basetable[i | 0x000] = ((e + 15) << 10);
|
|
basetable[i | 0x100] = ((e + 15) << 10) | 0x8000;
|
|
shifttable[i | 0x000] = 13;
|
|
shifttable[i | 0x100] = 13;
|
|
}
|
|
else if (e < 128) // Large numbers map to Infinity
|
|
{
|
|
basetable[i | 0x000] = 0x7C00;
|
|
basetable[i | 0x100] = 0xFC00;
|
|
shifttable[i | 0x000] = 24;
|
|
shifttable[i | 0x100] = 24;
|
|
}
|
|
else // Infinity and NaN's stay Infinity and NaN's
|
|
{
|
|
basetable[i | 0x000] = 0x7C00;
|
|
basetable[i | 0x100] = 0xFC00;
|
|
shifttable[i | 0x000] = 13;
|
|
shifttable[i | 0x100] = 13;
|
|
}
|
|
}
|
|
}
|
|
|
|
float halfToFloat(half h)
|
|
{
|
|
union { float f; uint32 i; } conv;
|
|
|
|
conv.i = mantissatable[offsettable[h >> 10] + (h & 0x3FF)] + exponenttable[h >> 10];
|
|
return conv.f;
|
|
}
|
|
|
|
half floatToHalf(float f)
|
|
{
|
|
union { float f; uint32 i; } conv;
|
|
conv.f = f;
|
|
|
|
return basetable[(conv.i >> 23) & 0x1FF] + ((conv.i & 0x007FFFFF) >> shifttable[(conv.i >> 23) & 0x1FF]);
|
|
}
|
|
|
|
} // love
|