ImageData and Images now support the rg11b10f format.

This commit is contained in:
Alex Szpakowski
2019-09-21 14:46:45 -03:00
parent b5da34ffb1
commit c4fac73dc4
10 changed files with 295 additions and 133 deletions
+2 -2
View File
@@ -279,8 +279,8 @@ set(LOVE_SRC_COMMON
src/common/EnumMap.h
src/common/Exception.cpp
src/common/Exception.h
src/common/halffloat.cpp
src/common/halffloat.h
src/common/floattypes.cpp
src/common/floattypes.h
src/common/int.h
src/common/math.h
src/common/Matrix.cpp
@@ -64,6 +64,9 @@
217DFC101D9F6D490055D849 /* url.lua.h in Headers */ = {isa = PBXBuildFile; fileRef = 217DFBD41D9F6D490055D849 /* url.lua.h */; };
217DFC111D9F6D490055D849 /* usocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 217DFBD51D9F6D490055D849 /* usocket.c */; };
217DFC121D9F6D490055D849 /* usocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 217DFBD61D9F6D490055D849 /* usocket.h */; };
FA0A3A5F23366CE9001C269E /* floattypes.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0A3A5D23366CE9001C269E /* floattypes.h */; };
FA0A3A6023366CE9001C269E /* floattypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0A3A5E23366CE9001C269E /* floattypes.cpp */; };
FA0A3A6123366CE9001C269E /* floattypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0A3A5E23366CE9001C269E /* floattypes.cpp */; };
FA0B791B1A958E3B000E1D17 /* b64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B78F71A958E3B000E1D17 /* b64.cpp */; };
FA0B791C1A958E3B000E1D17 /* b64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B78F71A958E3B000E1D17 /* b64.cpp */; };
FA0B791D1A958E3B000E1D17 /* b64.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B78F81A958E3B000E1D17 /* b64.h */; };
@@ -937,9 +940,6 @@
FA8951A21AA2EDF300EC385A /* wrap_Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA8951A01AA2EDF300EC385A /* wrap_Event.cpp */; };
FA8951A31AA2EDF300EC385A /* wrap_Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA8951A01AA2EDF300EC385A /* wrap_Event.cpp */; };
FA8951A41AA2EDF300EC385A /* wrap_Event.h in Headers */ = {isa = PBXBuildFile; fileRef = FA8951A11AA2EDF300EC385A /* wrap_Event.h */; };
FA91591E1CF1ED7500A7053F /* halffloat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91591C1CF1ED7500A7053F /* halffloat.cpp */; };
FA91591F1CF1ED7500A7053F /* halffloat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91591C1CF1ED7500A7053F /* halffloat.cpp */; };
FA9159201CF1ED7500A7053F /* halffloat.h in Headers */ = {isa = PBXBuildFile; fileRef = FA91591D1CF1ED7500A7053F /* halffloat.h */; };
FA91DA8B1F377C3900C80E33 /* deprecation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91DA891F377C3900C80E33 /* deprecation.cpp */; };
FA91DA8C1F377C3900C80E33 /* deprecation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91DA891F377C3900C80E33 /* deprecation.cpp */; };
FA91DA8D1F377C3900C80E33 /* deprecation.h in Headers */ = {isa = PBXBuildFile; fileRef = FA91DA8A1F377C3900C80E33 /* deprecation.h */; };
@@ -1281,6 +1281,8 @@
217DFBD61D9F6D490055D849 /* usocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usocket.h; sourceTree = "<group>"; };
503971A86B7167A91B670FBA /* boot.lua.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = boot.lua.h; sourceTree = "<group>"; };
FA08F5AE16C7525600F007B5 /* liblove-macosx.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "liblove-macosx.plist"; path = "macosx/liblove-macosx.plist"; sourceTree = "<group>"; };
FA0A3A5D23366CE9001C269E /* floattypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = floattypes.h; sourceTree = "<group>"; };
FA0A3A5E23366CE9001C269E /* floattypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = floattypes.cpp; sourceTree = "<group>"; };
FA0B78DD1A958B90000E1D17 /* liblove.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = liblove.a; sourceTree = BUILT_PRODUCTS_DIR; };
FA0B78F71A958E3B000E1D17 /* b64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = b64.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
FA0B78F81A958E3B000E1D17 /* b64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = b64.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
@@ -1876,8 +1878,6 @@
FA7DA04C1C16874A0056B200 /* wrap_Math.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = wrap_Math.lua; sourceTree = "<group>"; };
FA8951A01AA2EDF300EC385A /* wrap_Event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Event.cpp; sourceTree = "<group>"; };
FA8951A11AA2EDF300EC385A /* wrap_Event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Event.h; sourceTree = "<group>"; };
FA91591C1CF1ED7500A7053F /* halffloat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = halffloat.cpp; sourceTree = "<group>"; };
FA91591D1CF1ED7500A7053F /* halffloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = halffloat.h; sourceTree = "<group>"; };
FA91DA891F377C3900C80E33 /* deprecation.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = deprecation.cpp; sourceTree = "<group>"; };
FA91DA8A1F377C3900C80E33 /* deprecation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = deprecation.h; sourceTree = "<group>"; };
FA93C4501F315B960087CCD4 /* FormatHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormatHandler.h; sourceTree = "<group>"; };
@@ -2164,8 +2164,8 @@
FA0B78FD1A958E3B000E1D17 /* EnumMap.h */,
FA0B78FE1A958E3B000E1D17 /* Exception.cpp */,
FA0B78FF1A958E3B000E1D17 /* Exception.h */,
FA91591C1CF1ED7500A7053F /* halffloat.cpp */,
FA91591D1CF1ED7500A7053F /* halffloat.h */,
FA0A3A5E23366CE9001C269E /* floattypes.cpp */,
FA0A3A5D23366CE9001C269E /* floattypes.h */,
FA0B79001A958E3B000E1D17 /* int.h */,
FA0B7EF01A959D2C000E1D17 /* ios.h */,
FA0B7EF11A959D2C000E1D17 /* ios.mm */,
@@ -3795,7 +3795,6 @@
217DFBEE1D9F6D490055D849 /* luasocket.h in Headers */,
FACA02F31F5E396B0084B28F /* HashFunction.h in Headers */,
FA0B7ED01A95902C000E1D17 /* wrap_LuaThread.h in Headers */,
FA9159201CF1ED7500A7053F /* halffloat.h in Headers */,
FA0B7CE41A95902C000E1D17 /* wrap_Audio.h in Headers */,
FA0B7A7F1A958EA3000E1D17 /* b2ContactSolver.h in Headers */,
FADF540F1E3D7CDD00012CC0 /* wrap_Video.h in Headers */,
@@ -3926,6 +3925,7 @@
FA0B7CD81A95902C000E1D17 /* Audio.h in Headers */,
FA0B7CF61A95902C000E1D17 /* File.h in Headers */,
FA0B7E961A95902C000E1D17 /* Mpg123Decoder.h in Headers */,
FA0A3A5F23366CE9001C269E /* floattypes.h in Headers */,
FADF54091E3D78F700012CC0 /* Video.h in Headers */,
FAA54ACB1F91660400A8FA7B /* TheoraVideoStream.h in Headers */,
FA0B7DD51A95902C000E1D17 /* BezierCurve.h in Headers */,
@@ -4271,7 +4271,6 @@
FA0B7EA41A95902C000E1D17 /* SoundData.cpp in Sources */,
FA0B7D041A95902C000E1D17 /* wrap_DroppedFile.cpp in Sources */,
FAF1406A1E20934C00F898D2 /* glslang_tab.cpp in Sources */,
FA91591F1CF1ED7500A7053F /* halffloat.cpp in Sources */,
FA8951A31AA2EDF300EC385A /* wrap_Event.cpp in Sources */,
FADF540E1E3D7CDD00012CC0 /* wrap_Video.cpp in Sources */,
FA0B7A361A958EA3000E1D17 /* b2Distance.cpp in Sources */,
@@ -4404,6 +4403,7 @@
FA0B7E791A95902C000E1D17 /* wrap_WheelJoint.cpp in Sources */,
FA0B7DDD1A95902C000E1D17 /* wrap_BezierCurve.cpp in Sources */,
FA0B7A2A1A958EA3000E1D17 /* b2BroadPhase.cpp in Sources */,
FA0A3A6123366CE9001C269E /* floattypes.cpp in Sources */,
FA0B7A811A958EA3000E1D17 /* b2EdgeAndCircleContact.cpp in Sources */,
FAF188A01E9DBC4B008C1479 /* depthstencil.cpp in Sources */,
FA0B7D071A95902C000E1D17 /* wrap_File.cpp in Sources */,
@@ -4794,6 +4794,7 @@
FAF140711E20934C00F898D2 /* Intermediate.cpp in Sources */,
FAC7CD7D1FE35E95006A60C7 /* physfs_platform_winrt.cpp in Sources */,
FA0B7E541A95902C000E1D17 /* wrap_GearJoint.cpp in Sources */,
FA0A3A6023366CE9001C269E /* floattypes.cpp in Sources */,
FA41A3C81C0A1F950084430C /* ASTCHandler.cpp in Sources */,
FA0B7E781A95902C000E1D17 /* wrap_WheelJoint.cpp in Sources */,
FA0B7DDC1A95902C000E1D17 /* wrap_BezierCurve.cpp in Sources */,
@@ -4907,7 +4908,6 @@
FAC756F51E4F99B400B91289 /* Effect.cpp in Sources */,
FA620A3A1AA305F6005DB4C2 /* types.cpp in Sources */,
FA0B7DD31A95902C000E1D17 /* BezierCurve.cpp in Sources */,
FA91591E1CF1ED7500A7053F /* halffloat.cpp in Sources */,
FA0B7E7B1A95902C000E1D17 /* wrap_World.cpp in Sources */,
FA0B7B281A958EA3000E1D17 /* simplexnoise1234.cpp in Sources */,
FA0B7D421A95902C000E1D17 /* OpenGL.cpp in Sources */,
@@ -18,14 +18,17 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "halffloat.h"
#include "floattypes.h"
#include <limits>
#include <cmath>
namespace love
{
// Code from ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf
static bool initialized = false;
static bool halfInitialized = false;
// tables for half -> float conversions
static uint32 mantissatable[2048];
@@ -54,15 +57,15 @@ static uint32 convertMantissa(uint32 i)
return m | e; // Return combined number
}
void halfInit()
void float16Init()
{
if (initialized)
if (halfInitialized)
return;
initialized = true;
halfInitialized = true;
// tables for half -> float conversions.
// tables for float16 -> float32 conversions.
mantissatable[0] = 0;
@@ -93,7 +96,7 @@ void halfInit()
}
// tables for float -> half conversions.
// tables for float32 -> float16 conversions.
for (uint32 i = 0; i < 256; i++)
{
@@ -137,20 +140,115 @@ void halfInit()
}
}
float halfToFloat(half h)
static inline uint32 asuint32(float f)
{
union { float f; uint32 i; } conv;
union { float f; uint32 u; } conv;
conv.f = f;
return conv.u;
}
conv.i = mantissatable[offsettable[h >> 10] + (h & 0x3FF)] + exponenttable[h >> 10];
static inline float asfloat32(uint32 u)
{
union { float f; uint32 u; } conv;
conv.u = u;
return conv.f;
}
half floatToHalf(float f)
float float16to32(float16 f)
{
union { float f; uint32 i; } conv;
conv.f = f;
return asfloat32(mantissatable[offsettable[f >> 10] + (f & 0x3FF)] + exponenttable[f >> 10]);
}
return basetable[(conv.i >> 23) & 0x1FF] + ((conv.i & 0x007FFFFF) >> shifttable[(conv.i >> 23) & 0x1FF]);
float16 float32to16(float f)
{
uint32 u = asuint32(f);
return basetable[(u >> 23) & 0x1FF] + ((u & 0x007FFFFF) >> shifttable[(u >> 23) & 0x1FF]);
}
// Adapted from https://stackoverflow.com/questions/41532085/how-to-pack-unpack-11-and-10-bit-floats-in-javascript-for-webgl2
float float11to32(float11 f)
{
uint16 exponent = f >> 6;
uint16 mantissa = f & 0x3F;
if (exponent == 0)
return mantissa == 0 ? 0 : powf(2.0f, -14.0f) * (mantissa / 64.0f);
if (exponent < 31)
return powf(2.0f, exponent - 15) * (1.0f + mantissa / 64.0f);
return mantissa == 0 ? std::numeric_limits<float>::infinity() : std::numeric_limits<float>::quiet_NaN();
}
float11 float32to11(float f)
{
const uint16 EXPONENT_BITS = 0x1F;
const uint16 EXPONENT_SHIFT = 6;
const uint16 EXPONENT_BIAS = 15;
const uint16 MANTISSA_BITS = 0x3F;
const uint16 MANTISSA_SHIFT = (23 - EXPONENT_SHIFT);
const uint16 MAX_EXPONENT = (EXPONENT_BITS << EXPONENT_SHIFT);
uint32 u = asuint32(f);
if (u & 0x80000000)
return 0; // Negative values go to 0.
// Map exponent to the range [-127,128]
int32 exponent = (int32)((u >> 23) & 0xFF) - 127;
uint32 mantissa = u & 0x007FFFFF;
if (exponent > 15) // Infinity or NaN
return MAX_EXPONENT | (exponent == 128 ? (mantissa & MANTISSA_BITS) : 0);
else if (exponent <= -15)
return 0;
exponent += EXPONENT_BIAS;
return ((uint16)exponent << EXPONENT_SHIFT) | (mantissa >> MANTISSA_SHIFT);
}
float float10to32(float10 f)
{
uint16 exponent = f >> 5;
uint16 mantissa = f & 0x1F;
if (exponent == 0)
return mantissa == 0 ? 0 : powf(2.0f, -14.0f) * (mantissa / 32.0f);
if (exponent < 31)
return powf(2.0f, exponent - 15) * (1.0f + mantissa / 32.0f);
return mantissa == 0 ? std::numeric_limits<float>::infinity() : std::numeric_limits<float>::quiet_NaN();
}
float10 float32to10(float f)
{
const uint16 EXPONENT_BITS = 0x1F;
const uint16 EXPONENT_SHIFT = 5;
const uint16 EXPONENT_BIAS = 15;
const uint16 MANTISSA_BITS = 0x1F;
const uint16 MANTISSA_SHIFT = (23 - EXPONENT_SHIFT);
const uint16 MAX_EXPONENT = (EXPONENT_BITS << EXPONENT_SHIFT);
uint32 u = asuint32(f);
if (u & 0x80000000)
return 0; // Negative values go to 0.
// Map exponent to the range [-127,128]
int32 exponent = (int32)((u >> 23) & 0xFF) - 127;
uint32 mantissa = u & 0x007FFFFF;
if (exponent > 15) // Infinity or NaN
return MAX_EXPONENT | (exponent == 128 ? (mantissa & MANTISSA_BITS) : 0);
else if (exponent <= -15)
return 0;
exponent += EXPONENT_BIAS;
return ((uint16)exponent << EXPONENT_SHIFT) | (mantissa >> MANTISSA_SHIFT);
}
} // love
@@ -18,21 +18,26 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_HALF_FLOAT_H
#define LOVE_HALF_FLOAT_H
#pragma once
#include "int.h"
namespace love
{
typedef uint16 half;
typedef uint16 float16;
typedef uint16 float11;
typedef uint16 float10;
void halfInit();
void float16Init();
float halfToFloat(half h);
half floatToHalf(float f);
float float16to32(float16 f);
float16 float32to16(float f);
float float11to32(float11 f);
float11 float32to11(float f);
float float10to32(float10 f);
float10 float32to10(float f);
} // love
#endif // LOVE_HALF_FLOAT_H
+1 -1
View File
@@ -43,7 +43,7 @@ Image::Image()
{
using namespace magpie;
halfInit(); // Makes sure half-float conversions can be used.
float16Init(); // Makes sure half-float conversions can be used.
formatHandlers = {
new PNGHandler,
+8 -7
View File
@@ -280,7 +280,7 @@ union Row
{
uint8 *u8;
uint16 *u16;
half *f16;
float16 *f16;
float *f32;
};
@@ -293,7 +293,7 @@ static void pasteRGBA8toRGBA16(Row src, Row dst, int w)
static void pasteRGBA8toRGBA16F(Row src, Row dst, int w)
{
for (int i = 0; i < w * 4; i++)
dst.f16[i] = floatToHalf(src.u8[i] / 255.0f);
dst.f16[i] = float32to16(src.u8[i] / 255.0f);
}
static void pasteRGBA8toRGBA32F(Row src, Row dst, int w)
@@ -311,7 +311,7 @@ static void pasteRGBA16toRGBA8(Row src, Row dst, int w)
static void pasteRGBA16toRGBA16F(Row src, Row dst, int w)
{
for (int i = 0; i < w * 4; i++)
dst.f16[i] = floatToHalf(src.u16[i] / 65535.0f);
dst.f16[i] = float32to16(src.u16[i] / 65535.0f);
}
static void pasteRGBA16toRGBA32F(Row src, Row dst, int w)
@@ -323,19 +323,19 @@ static void pasteRGBA16toRGBA32F(Row src, Row dst, int w)
static void pasteRGBA16FtoRGBA8(Row src, Row dst, int w)
{
for (int i = 0; i < w * 4; i++)
dst.u8[i] = (uint8) (halfToFloat(src.f16[i]) * 255.0f);
dst.u8[i] = (uint8) (float16to32(src.f16[i]) * 255.0f);
}
static void pasteRGBA16FtoRGBA16(Row src, Row dst, int w)
{
for (int i = 0; i < w * 4; i++)
dst.u16[i] = (uint16) (halfToFloat(src.f16[i]) * 65535.0f);
dst.u16[i] = (uint16) (float16to32(src.f16[i]) * 65535.0f);
}
static void pasteRGBA16FtoRGBA32F(Row src, Row dst, int w)
{
for (int i = 0; i < w * 4; i++)
dst.f32[i] = halfToFloat(src.f16[i]);
dst.f32[i] = float16to32(src.f16[i]);
}
static void pasteRGBA32FtoRGBA8(Row src, Row dst, int w)
@@ -353,7 +353,7 @@ static void pasteRGBA32FtoRGBA16(Row src, Row dst, int w)
static void pasteRGBA32FtoRGBA16F(Row src, Row dst, int w)
{
for (int i = 0; i < w * 4; i++)
dst.f16[i] = (uint16) floatToHalf(src.f32[i]);
dst.f16[i] = (uint16) float32to16(src.f32[i]);
}
void ImageData::paste(ImageData *src, int dx, int dy, int sx, int sy, int sw, int sh)
@@ -498,6 +498,7 @@ bool ImageData::validPixelFormat(PixelFormat format)
case PIXELFORMAT_RGB5A1:
case PIXELFORMAT_RGB565:
case PIXELFORMAT_RGB10A2:
case PIXELFORMAT_RG11B10F:
return true;
default:
return false;
+7 -7
View File
@@ -25,7 +25,7 @@
#include "common/StringMap.h"
#include "common/int.h"
#include "common/pixelformat.h"
#include "common/halffloat.h"
#include "common/floattypes.h"
#include "filesystem/FileData.h"
#include "thread/threads.h"
#include "ImageDataBase.h"
@@ -40,12 +40,12 @@ namespace image
union Pixel
{
uint8 rgba8[4];
uint16 rgba16[4];
half rgba16f[4];
float rgba32f[4];
uint16 packed16;
uint32 packed32;
uint8 rgba8[4];
uint16 rgba16[4];
float16 rgba16f[4];
float rgba32f[4];
uint16 packed16;
uint32 packed32;
};
/**
+3 -3
View File
@@ -20,7 +20,7 @@
// LOVE
#include "EXRHandler.h"
#include "common/halffloat.h"
#include "common/floattypes.h"
#include "common/Exception.h"
// zlib (for tinyexr)
@@ -157,12 +157,12 @@ FormatHandler::DecodedImage EXRHandler::decode(Data *data)
{
img.format = PIXELFORMAT_RGBA16F;
half *rgba[4] = {nullptr};
float16 *rgba[4] = {nullptr};
getEXRChannels(exrHeader, exrImage, rgba);
try
{
img.data = (unsigned char *) loadEXRChannels(img.width, img.height, rgba, floatToHalf(1.0f));
img.data = (unsigned char *) loadEXRChannels(img.width, img.height, rgba, float32to16(1.0f));
}
catch (love::Exception &)
{
+93 -62
View File
@@ -110,9 +110,9 @@ template <int components>
static void luax_checkpixel_float16(lua_State *L, int startidx, Pixel &p)
{
for (int i = 0; i < std::min(components, 3); i++)
p.rgba16f[i] = floatToHalf((float) luaL_checknumber(L, startidx + i));
p.rgba16f[i] = float32to16((float) luaL_checknumber(L, startidx + i));
if (components > 3)
p.rgba16f[3] = floatToHalf((float) luaL_optnumber(L, startidx + 3, 1.0));
p.rgba16f[3] = float32to16((float) luaL_optnumber(L, startidx + 3, 1.0));
}
template <int components>
@@ -187,40 +187,49 @@ static void luax_checkpixel_rgba32f(lua_State *L, int startidx, Pixel &p)
static void luax_checkpixel_rgba4(lua_State *L, int startidx, Pixel &p)
{
// LSB->MSB: [a, b, g, r]
uint16 r = ((uint16) ((luax_checknumberclamped01(L, startidx + 0) * 0xF) + 0.5)) << 12;
uint16 g = ((uint16) ((luax_checknumberclamped01(L, startidx + 1) * 0xF) + 0.5)) << 8;
uint16 b = ((uint16) ((luax_checknumberclamped01(L, startidx + 2) * 0xF) + 0.5)) << 4;
uint16 a = ((uint16) ((luax_optnumberclamped01(L, startidx + 3, 1.0) * 0xF) + 0.5)) << 0;
p.packed16 = r | g | b | a;
uint16 r = (uint16) ((luax_checknumberclamped01(L, startidx + 0) * 0xF) + 0.5);
uint16 g = (uint16) ((luax_checknumberclamped01(L, startidx + 1) * 0xF) + 0.5);
uint16 b = (uint16) ((luax_checknumberclamped01(L, startidx + 2) * 0xF) + 0.5);
uint16 a = (uint16) ((luax_optnumberclamped01(L, startidx + 3, 1.0) * 0xF) + 0.5);
p.packed16 = (r << 12) | (g << 8) | (b << 4) | (a << 0);
}
static void luax_checkpixel_rgb5a1(lua_State *L, int startidx, Pixel &p)
{
// LSB->MSB: [a, b, g, r]
uint16 r = ((uint16) ((luax_checknumberclamped01(L, startidx + 0) * 0x1F) + 0.5)) << 11;
uint16 g = ((uint16) ((luax_checknumberclamped01(L, startidx + 1) * 0x1F) + 0.5)) << 6;
uint16 b = ((uint16) ((luax_checknumberclamped01(L, startidx + 2) * 0x1F) + 0.5)) << 1;
uint16 a = ((uint16) ((luax_optnumberclamped01(L, startidx + 3, 1.0) * 0x1) + 0.5)) << 0;
p.packed16 = r | g | b | a;
uint16 r = (uint16) ((luax_checknumberclamped01(L, startidx + 0) * 0x1F) + 0.5);
uint16 g = (uint16) ((luax_checknumberclamped01(L, startidx + 1) * 0x1F) + 0.5);
uint16 b = (uint16) ((luax_checknumberclamped01(L, startidx + 2) * 0x1F) + 0.5);
uint16 a = (uint16) ((luax_optnumberclamped01(L, startidx + 3, 1.0) * 0x1) + 0.5);
p.packed16 = (r << 11) | (g << 6) | (b << 1) | (a << 0);
}
static void luax_checkpixel_rgb565(lua_State *L, int startidx, Pixel &p)
{
// LSB->MSB: [b, g, r]
uint16 r = ((uint16) ((luax_checknumberclamped01(L, startidx + 0) * 0x1F) + 0.5)) << 11;
uint16 g = ((uint16) ((luax_checknumberclamped01(L, startidx + 1) * 0x3F) + 0.5)) << 5;
uint16 b = ((uint16) ((luax_checknumberclamped01(L, startidx + 2) * 0x1F) + 0.5)) << 0;
p.packed16 = r | g | b;
uint16 r = (uint16) ((luax_checknumberclamped01(L, startidx + 0) * 0x1F) + 0.5);
uint16 g = (uint16) ((luax_checknumberclamped01(L, startidx + 1) * 0x3F) + 0.5);
uint16 b = (uint16) ((luax_checknumberclamped01(L, startidx + 2) * 0x1F) + 0.5);
p.packed16 = (r << 11) | (g << 5) | (b << 0);
}
static void luax_checkpixel_rgb10a2(lua_State *L, int startidx, Pixel &p)
{
// LSB->MSB: [r, g, b, a]
uint32 r = ((uint32) ((luax_checknumberclamped01(L, startidx + 0) * 0x3FF) + 0.5)) << 0;
uint32 g = ((uint32) ((luax_checknumberclamped01(L, startidx + 1) * 0x3FF) + 0.5)) << 10;
uint32 b = ((uint32) ((luax_checknumberclamped01(L, startidx + 2) * 0x3FF) + 0.5)) << 20;
uint32 a = ((uint32) ((luax_optnumberclamped01(L, startidx + 3, 1.0) * 0x3) + 0.5)) << 30;
p.packed32 = r | g | b | a;
uint32 r = (uint32) ((luax_checknumberclamped01(L, startidx + 0) * 0x3FF) + 0.5);
uint32 g = (uint32) ((luax_checknumberclamped01(L, startidx + 1) * 0x3FF) + 0.5);
uint32 b = (uint32) ((luax_checknumberclamped01(L, startidx + 2) * 0x3FF) + 0.5);
uint32 a = (uint32) ((luax_optnumberclamped01(L, startidx + 3, 1.0) * 0x3) + 0.5);
p.packed32 = (r << 0) | (g << 10) | (b << 20) | (a << 30);
}
static void luax_checkpixel_rg11b10f(lua_State *L, int startidx, Pixel &p)
{
// LSB->MSB: [r, g, b]
float11 r = float32to11((float) luaL_checknumber(L, startidx + 0));
float11 g = float32to11((float) luaL_checknumber(L, startidx + 1));
float10 b = float32to10((float) luaL_checknumber(L, startidx + 2));
p.packed32 = (r << 0) | (g << 11) | (b << 22);
}
static lua_Number fillValues[] = {0.0, 0.0, 0.0, 1.0};
@@ -249,7 +258,7 @@ template <int components>
static int luax_pushpixel_float16(lua_State *L, const Pixel &p)
{
for (int i = 0; i < components; i++)
lua_pushnumber(L, (lua_Number) halfToFloat(p.rgba16f[i]));
lua_pushnumber(L, (lua_Number) float16to32(p.rgba16f[i]));
for (int i = components; i < 4; i++)
lua_pushnumber(L, fillValues[i]);
return 4;
@@ -358,10 +367,20 @@ static int luax_pushpixel_rgb565(lua_State *L, const Pixel &p)
static int luax_pushpixel_rgb10a2(lua_State *L, const Pixel &p)
{
// LSB->MSB: [r, g, b, a]
lua_pushnumber(L, ((p.packed16 >> 0) & 0x3FF) / (double)0x3FF);
lua_pushnumber(L, ((p.packed16 >> 10) & 0x3FF) / (double)0x3FF);
lua_pushnumber(L, ((p.packed16 >> 20) & 0x3FF) / (double)0x3FF);
lua_pushnumber(L, ((p.packed16 >> 30) & 0x3) / (double)0x3);
lua_pushnumber(L, ((p.packed32 >> 0) & 0x3FF) / (double)0x3FF);
lua_pushnumber(L, ((p.packed32 >> 10) & 0x3FF) / (double)0x3FF);
lua_pushnumber(L, ((p.packed32 >> 20) & 0x3FF) / (double)0x3FF);
lua_pushnumber(L, ((p.packed32 >> 30) & 0x3) / (double)0x3);
return 4;
}
static int luax_pushpixel_rg11b10f(lua_State *L, const Pixel &p)
{
// LSB->MSB: [r, g, b]
lua_pushnumber(L, float11to32((float11) ((p.packed32 >> 0) & 0x7FF)));
lua_pushnumber(L, float11to32((float11) ((p.packed32 >> 11) & 0x7FF)));
lua_pushnumber(L, float10to32((float10) ((p.packed32 >> 22) & 0x3FF)));
lua_pushnumber(L, 1.0);
return 4;
}
@@ -526,8 +545,14 @@ struct FFI_ImageData
void (*lockMutex)(Proxy *p);
void (*unlockMutex)(Proxy *p);
float (*halfToFloat)(half h);
half (*floatToHalf)(float f);
float (*float16to32)(float16 f);
float16 (*float32to16)(float f);
float (*float11to32)(float11 f);
float11 (*float32to11)(float f);
float (*float10to32)(float10 f);
float10 (*float32to10)(float f);
};
static FFI_ImageData ffifuncs =
@@ -546,8 +571,12 @@ static FFI_ImageData ffifuncs =
i->getMutex()->unlock();
},
halfToFloat,
floatToHalf,
float16to32,
float32to16,
float11to32,
float32to11,
float10to32,
float32to10,
};
static const luaL_Reg w_ImageData_functions[] =
@@ -571,39 +600,41 @@ static const luaL_Reg w_ImageData_functions[] =
extern "C" int luaopen_imagedata(lua_State *L)
{
checkFormats[PIXELFORMAT_R8] = luax_checkpixel_r8;
checkFormats[PIXELFORMAT_RG8] = luax_checkpixel_rg8;
checkFormats[PIXELFORMAT_RGBA8] = luax_checkpixel_rgba8;
checkFormats[PIXELFORMAT_R16] = luax_checkpixel_r16;
checkFormats[PIXELFORMAT_RG16] = luax_checkpixel_rg16;
checkFormats[PIXELFORMAT_RGBA16] = luax_checkpixel_rgba16;
checkFormats[PIXELFORMAT_R16F] = luax_checkpixel_r16f;
checkFormats[PIXELFORMAT_RG16F] = luax_checkpixel_rg16f;
checkFormats[PIXELFORMAT_RGBA16F] = luax_checkpixel_rgba16f;
checkFormats[PIXELFORMAT_R32F] = luax_checkpixel_r32f;
checkFormats[PIXELFORMAT_RG32F] = luax_checkpixel_rg32f;
checkFormats[PIXELFORMAT_RGBA32F] = luax_checkpixel_rgba32f;
checkFormats[PIXELFORMAT_RGBA4] = luax_checkpixel_rgba4;
checkFormats[PIXELFORMAT_RGB5A1] = luax_checkpixel_rgb5a1;
checkFormats[PIXELFORMAT_RGB565] = luax_checkpixel_rgb565;
checkFormats[PIXELFORMAT_RGB10A2] = luax_checkpixel_rgb10a2;
checkFormats[PIXELFORMAT_R8] = luax_checkpixel_r8;
checkFormats[PIXELFORMAT_RG8] = luax_checkpixel_rg8;
checkFormats[PIXELFORMAT_RGBA8] = luax_checkpixel_rgba8;
checkFormats[PIXELFORMAT_R16] = luax_checkpixel_r16;
checkFormats[PIXELFORMAT_RG16] = luax_checkpixel_rg16;
checkFormats[PIXELFORMAT_RGBA16] = luax_checkpixel_rgba16;
checkFormats[PIXELFORMAT_R16F] = luax_checkpixel_r16f;
checkFormats[PIXELFORMAT_RG16F] = luax_checkpixel_rg16f;
checkFormats[PIXELFORMAT_RGBA16F] = luax_checkpixel_rgba16f;
checkFormats[PIXELFORMAT_R32F] = luax_checkpixel_r32f;
checkFormats[PIXELFORMAT_RG32F] = luax_checkpixel_rg32f;
checkFormats[PIXELFORMAT_RGBA32F] = luax_checkpixel_rgba32f;
checkFormats[PIXELFORMAT_RGBA4] = luax_checkpixel_rgba4;
checkFormats[PIXELFORMAT_RGB5A1] = luax_checkpixel_rgb5a1;
checkFormats[PIXELFORMAT_RGB565] = luax_checkpixel_rgb565;
checkFormats[PIXELFORMAT_RGB10A2] = luax_checkpixel_rgb10a2;
checkFormats[PIXELFORMAT_RG11B10F] = luax_checkpixel_rg11b10f;
pushFormats[PIXELFORMAT_R8] = luax_pushpixel_r8;
pushFormats[PIXELFORMAT_RG8] = luax_pushpixel_rg8;
pushFormats[PIXELFORMAT_RGBA8] = luax_pushpixel_rgba8;
pushFormats[PIXELFORMAT_R16] = luax_pushpixel_r16;
pushFormats[PIXELFORMAT_RG16] = luax_pushpixel_rg16;
pushFormats[PIXELFORMAT_RGBA16] = luax_pushpixel_rgba16;
pushFormats[PIXELFORMAT_R16F] = luax_pushpixel_r16f;
pushFormats[PIXELFORMAT_RG16F] = luax_pushpixel_rg16f;
pushFormats[PIXELFORMAT_RGBA16F] = luax_pushpixel_rgba16f;
pushFormats[PIXELFORMAT_R32F] = luax_pushpixel_r32f;
pushFormats[PIXELFORMAT_RG32F] = luax_pushpixel_rg32f;
pushFormats[PIXELFORMAT_RGBA32F] = luax_pushpixel_rgba32f;
pushFormats[PIXELFORMAT_RGBA4] = luax_pushpixel_rgba4;
pushFormats[PIXELFORMAT_RGB5A1] = luax_pushpixel_rgb5a1;
pushFormats[PIXELFORMAT_RGB565] = luax_pushpixel_rgb565;
pushFormats[PIXELFORMAT_RGB10A2] = luax_pushpixel_rgb10a2;
pushFormats[PIXELFORMAT_R8] = luax_pushpixel_r8;
pushFormats[PIXELFORMAT_RG8] = luax_pushpixel_rg8;
pushFormats[PIXELFORMAT_RGBA8] = luax_pushpixel_rgba8;
pushFormats[PIXELFORMAT_R16] = luax_pushpixel_r16;
pushFormats[PIXELFORMAT_RG16] = luax_pushpixel_rg16;
pushFormats[PIXELFORMAT_RGBA16] = luax_pushpixel_rgba16;
pushFormats[PIXELFORMAT_R16F] = luax_pushpixel_r16f;
pushFormats[PIXELFORMAT_RG16F] = luax_pushpixel_rg16f;
pushFormats[PIXELFORMAT_RGBA16F] = luax_pushpixel_rgba16f;
pushFormats[PIXELFORMAT_R32F] = luax_pushpixel_r32f;
pushFormats[PIXELFORMAT_RG32F] = luax_pushpixel_rg32f;
pushFormats[PIXELFORMAT_RGBA32F] = luax_pushpixel_rgba32f;
pushFormats[PIXELFORMAT_RGBA4] = luax_pushpixel_rgba4;
pushFormats[PIXELFORMAT_RGB5A1] = luax_pushpixel_rgb5a1;
pushFormats[PIXELFORMAT_RGB565] = luax_pushpixel_rgb565;
pushFormats[PIXELFORMAT_RGB10A2] = luax_pushpixel_rgb10a2;
pushFormats[PIXELFORMAT_RG11B10F] = luax_pushpixel_rg11b10f;
int ret = luax_register_type(L, &ImageData::type, data::w_Data_functions, w_ImageData_functions, nullptr);
+46 -19
View File
@@ -78,15 +78,23 @@ if not bitstatus then return end
pcall(ffi.cdef, [[
typedef struct Proxy Proxy;
typedef uint16_t half;
typedef uint16_t float16;
typedef uint16_t float11;
typedef uint16_t float10;
typedef struct FFI_ImageData
{
void (*lockMutex)(Proxy *p);
void (*unlockMutex)(Proxy *p);
float (*halfToFloat)(half h);
half (*floatToHalf)(float f);
float (*float16to32)(float16 f);
float16 (*float32to16)(float f);
float (*float11to32)(float11 f);
float11 (*float32to11)(float f);
float (*float10to32)(float10 f);
float10 (*float32to10)(float f);
} FFI_ImageData;
struct ImageData_Pixel_R8 { uint8_t r; };
@@ -97,9 +105,9 @@ struct ImageData_Pixel_R16 { uint16_t r; };
struct ImageData_Pixel_RG16 { uint16_t r, g; };
struct ImageData_Pixel_RGBA16 { uint16_t r, g, b, a; };
struct ImageData_Pixel_R16F { half r; };
struct ImageData_Pixel_RG16F { half r, g; };
struct ImageData_Pixel_RGBA16F { half r, g, b, a; };
struct ImageData_Pixel_R16F { float16 r; };
struct ImageData_Pixel_RG16F { float16 r, g; };
struct ImageData_Pixel_RGBA16F { float16 r, g, b, a; };
struct ImageData_Pixel_R32F { float r; };
struct ImageData_Pixel_RG32F { float r, g; };
@@ -109,6 +117,7 @@ struct ImageData_Pixel_RGBA4 { uint16_t rgba; };
struct ImageData_Pixel_RGB5A1 { uint16_t rgba; };
struct ImageData_Pixel_RGB565 { uint16_t rgb; };
struct ImageData_Pixel_RGB10A2 { uint32_t rgba; };
struct ImageData_Pixel_RG11B10F { uint32_t rgb; };
]])
local ffifuncs = ffi.cast("FFI_ImageData **", ffifuncspointer_str)[0]
@@ -179,35 +188,35 @@ local conversions = {
r16f = {
pointer = ffi.typeof("struct ImageData_Pixel_R16F *"),
tolua = function(self)
return tonumber(ffifuncs.halfToFloat(self.r)), 0, 0, 1
return tonumber(ffifuncs.float16to32(self.r)), 0, 0, 1
end,
fromlua = function(self, r)
self.r = ffifuncs.floatToHalf(r)
self.r = ffifuncs.float32to16(r)
end,
},
rg16f = {
pointer = ffi.typeof("struct ImageData_Pixel_RG16F *"),
tolua = function(self)
return tonumber(ffifuncs.halfToFloat(self.r)), tonumber(ffifuncs.halfToFloat(self.g)), 0, 1
return tonumber(ffifuncs.float16to32(self.r)), tonumber(ffifuncs.float16to32(self.g)), 0, 1
end,
fromlua = function(self, r, g, b, a)
self.r = ffifuncs.floatToHalf(r)
self.g = ffifuncs.floatToHalf(g)
self.r = ffifuncs.float32to16(r)
self.g = ffifuncs.float32to16(g)
end,
},
rgba16f = {
pointer = ffi.typeof("struct ImageData_Pixel_RGBA16F *"),
tolua = function(self)
return tonumber(ffifuncs.halfToFloat(self.r)),
tonumber(ffifuncs.halfToFloat(self.g)),
tonumber(ffifuncs.halfToFloat(self.b)),
tonumber(ffifuncs.halfToFloat(self.a))
return tonumber(ffifuncs.float16to32(self.r)),
tonumber(ffifuncs.float16to32(self.g)),
tonumber(ffifuncs.float16to32(self.b)),
tonumber(ffifuncs.float16to32(self.a))
end,
fromlua = function(self, r, g, b, a)
self.r = ffifuncs.floatToHalf(r)
self.g = ffifuncs.floatToHalf(g)
self.b = ffifuncs.floatToHalf(b)
self.a = ffifuncs.floatToHalf(a == nil and 1.0 or a)
self.r = ffifuncs.float32to16(r)
self.g = ffifuncs.float32to16(g)
self.b = ffifuncs.float32to16(b)
self.a = ffifuncs.float32to16(a == nil and 1.0 or a)
end,
},
r32f = {
@@ -319,6 +328,24 @@ local conversions = {
self.rgba = bit.bor(r, bit.lshift(g, 10), bit.lshift(b, 20), bit.lshift(a, 30))
end,
},
rg11b10f = {
-- LSB->MSB: [r, g, b]
pointer = ffi.typeof("struct ImageData_Pixel_RG11B10F *"),
tolua = function(self)
local rgb = self.rgb
local r = tonumber(ffifuncs.float11to32(bit.band(rgb, 0x7FF)))
local g = tonumber(ffifuncs.float11to32(bit.band(bit.rshift(rgb, 11), 0x7FF)))
local b = tonumber(ffifuncs.float10to32(bit.band(bit.rshift(rgb, 22), 0x3FF)))
return r, g, b, 1
end,
fromlua = function(self, r, g, b, a)
self.rgb = bit.bor(
ffifuncs.float32to11(r),
bit.lshift(ffifuncs.float32to11(g), 11),
bit.lshift(ffifuncs.float32to10(b), 22)
)
end,
},
}
local _getWidth = ImageData.getWidth