mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1205168 - Part 5: Texel Conversion - RGB11F11F10F format. r=jgilbert
This commit is contained in:
parent
eb973f8e9f
commit
19cfcee763
@ -47,6 +47,7 @@ class WebGLImageConverter
|
||||
case WebGLTexelFormat::R16F:
|
||||
case WebGLTexelFormat::R32F:
|
||||
case WebGLTexelFormat::RGB565:
|
||||
case WebGLTexelFormat::RGB11F11F10F:
|
||||
case WebGLTexelFormat::RGBA4444:
|
||||
case WebGLTexelFormat::RGBA5551:
|
||||
return 1;
|
||||
@ -266,6 +267,7 @@ class WebGLImageConverter
|
||||
// 3-channel formats
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB565)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB8)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB11F11F10F)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB16F)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB32F)
|
||||
// 4-channel formats
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "WebGLTypes.h"
|
||||
#include <stdint.h>
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Casting.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -155,6 +156,150 @@ unpackFromFloat16(uint16_t v)
|
||||
return f32Value;
|
||||
}
|
||||
|
||||
// These routines come from angle/common/mathutil.h
|
||||
// They are copied here to remove the dependency on ANGLE headers
|
||||
// included from mathutil.h
|
||||
MOZ_ALWAYS_INLINE uint16_t
|
||||
packToFloat11(float fp32)
|
||||
{
|
||||
const unsigned int float32MantissaMask = 0x7FFFFF;
|
||||
const unsigned int float32ExponentMask = 0x7F800000;
|
||||
const unsigned int float32SignMask = 0x80000000;
|
||||
const unsigned int float32ValueMask = ~float32SignMask;
|
||||
const unsigned int float32ExponentFirstBit = 23;
|
||||
const unsigned int float32ExponentBias = 127;
|
||||
|
||||
const unsigned short float11Max = 0x7BF;
|
||||
const unsigned short float11MantissaMask = 0x3F;
|
||||
const unsigned short float11ExponentMask = 0x7C0;
|
||||
const unsigned short float11BitMask = 0x7FF;
|
||||
const unsigned int float11ExponentBias = 14;
|
||||
|
||||
const unsigned int float32Maxfloat11 = 0x477E0000;
|
||||
const unsigned int float32Minfloat11 = 0x38800000;
|
||||
|
||||
const unsigned int float32Bits = BitwiseCast<unsigned int>(fp32);
|
||||
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
|
||||
|
||||
unsigned int float32Val = float32Bits & float32ValueMask;
|
||||
|
||||
if ((float32Val & float32ExponentMask) == float32ExponentMask)
|
||||
{
|
||||
// INF or NAN
|
||||
if ((float32Val & float32MantissaMask) != 0)
|
||||
{
|
||||
return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask);
|
||||
}
|
||||
else if (float32Sign)
|
||||
{
|
||||
// -INF is clamped to 0 since float11 is positive only
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return float11ExponentMask;
|
||||
}
|
||||
}
|
||||
else if (float32Sign)
|
||||
{
|
||||
// float11 is positive only, so clamp to zero
|
||||
return 0;
|
||||
}
|
||||
else if (float32Val > float32Maxfloat11)
|
||||
{
|
||||
// The number is too large to be represented as a float11, set to max
|
||||
return float11Max;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (float32Val < float32Minfloat11)
|
||||
{
|
||||
// The number is too small to be represented as a normalized float11
|
||||
// Convert it to a denormalized value.
|
||||
const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit);
|
||||
float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rebias the exponent to represent the value as a normalized float11
|
||||
float32Val += 0xC8000000;
|
||||
}
|
||||
|
||||
return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE uint16_t
|
||||
packToFloat10(float fp32)
|
||||
{
|
||||
const unsigned int float32MantissaMask = 0x7FFFFF;
|
||||
const unsigned int float32ExponentMask = 0x7F800000;
|
||||
const unsigned int float32SignMask = 0x80000000;
|
||||
const unsigned int float32ValueMask = ~float32SignMask;
|
||||
const unsigned int float32ExponentFirstBit = 23;
|
||||
const unsigned int float32ExponentBias = 127;
|
||||
|
||||
const unsigned short float10Max = 0x3DF;
|
||||
const unsigned short float10MantissaMask = 0x1F;
|
||||
const unsigned short float10ExponentMask = 0x3E0;
|
||||
const unsigned short float10BitMask = 0x3FF;
|
||||
const unsigned int float10ExponentBias = 14;
|
||||
|
||||
const unsigned int float32Maxfloat10 = 0x477C0000;
|
||||
const unsigned int float32Minfloat10 = 0x38800000;
|
||||
|
||||
const unsigned int float32Bits = BitwiseCast<unsigned int>(fp32);
|
||||
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
|
||||
|
||||
unsigned int float32Val = float32Bits & float32ValueMask;
|
||||
|
||||
if ((float32Val & float32ExponentMask) == float32ExponentMask)
|
||||
{
|
||||
// INF or NAN
|
||||
if ((float32Val & float32MantissaMask) != 0)
|
||||
{
|
||||
return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask);
|
||||
}
|
||||
else if (float32Sign)
|
||||
{
|
||||
// -INF is clamped to 0 since float11 is positive only
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return float10ExponentMask;
|
||||
}
|
||||
}
|
||||
else if (float32Sign)
|
||||
{
|
||||
// float10 is positive only, so clamp to zero
|
||||
return 0;
|
||||
}
|
||||
else if (float32Val > float32Maxfloat10)
|
||||
{
|
||||
// The number is too large to be represented as a float11, set to max
|
||||
return float10Max;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (float32Val < float32Minfloat10)
|
||||
{
|
||||
// The number is too small to be represented as a normalized float11
|
||||
// Convert it to a denormalized value.
|
||||
const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit);
|
||||
float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rebias the exponent to represent the value as a normalized float11
|
||||
float32Val += 0xC8000000;
|
||||
}
|
||||
|
||||
return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum class WebGLTexelPremultiplicationOp : int {
|
||||
None,
|
||||
Premultiply,
|
||||
@ -171,6 +316,7 @@ struct IsFloatFormat
|
||||
Format == WebGLTexelFormat::R32F ||
|
||||
Format == WebGLTexelFormat::RA32F ||
|
||||
Format == WebGLTexelFormat::RG32F ||
|
||||
Format == WebGLTexelFormat::RGB11F11F10F ||
|
||||
Format == WebGLTexelFormat::RGB32F ||
|
||||
Format == WebGLTexelFormat::RGBA32F;
|
||||
};
|
||||
@ -223,6 +369,12 @@ struct DataTypeForFormat<Format, false, false, true>
|
||||
typedef uint16_t Type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct DataTypeForFormat<WebGLTexelFormat::RGB11F11F10F, true, false, false>
|
||||
{
|
||||
typedef uint32_t Type;
|
||||
};
|
||||
|
||||
template<WebGLTexelFormat Format>
|
||||
struct IntermediateFormat
|
||||
{
|
||||
@ -287,6 +439,7 @@ inline size_t TexelBytesForFormat(WebGLTexelFormat format) {
|
||||
case WebGLTexelFormat::R32F:
|
||||
case WebGLTexelFormat::RA16F:
|
||||
case WebGLTexelFormat::RG16F:
|
||||
case WebGLTexelFormat::RGB11F11F10F:
|
||||
case WebGLTexelFormat::RGBA8:
|
||||
case WebGLTexelFormat::BGRX8:
|
||||
case WebGLTexelFormat::BGRA8:
|
||||
@ -334,6 +487,7 @@ MOZ_ALWAYS_INLINE bool HasColor(WebGLTexelFormat format) {
|
||||
format == WebGLTexelFormat::RG32F ||
|
||||
format == WebGLTexelFormat::RGB565 ||
|
||||
format == WebGLTexelFormat::RGB8 ||
|
||||
format == WebGLTexelFormat::RGB11F11F10F ||
|
||||
format == WebGLTexelFormat::RGB16F ||
|
||||
format == WebGLTexelFormat::RGB32F ||
|
||||
format == WebGLTexelFormat::RGBA4444 ||
|
||||
@ -915,6 +1069,32 @@ pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8
|
||||
dst[2] = srcB;
|
||||
}
|
||||
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB11F11F10F, WebGLTexelPremultiplicationOp::None, float, uint32_t>(const float* __restrict src, uint32_t* __restrict dst)
|
||||
{
|
||||
dst[0] = ((packToFloat11(src[0]) << 0) |
|
||||
(packToFloat11(src[1]) << 11) |
|
||||
(packToFloat10(src[2]) << 22));
|
||||
}
|
||||
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB11F11F10F, WebGLTexelPremultiplicationOp::Premultiply, float, uint32_t>(const float* __restrict src, uint32_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3];
|
||||
dst[0] = ((packToFloat11(src[0] * scaleFactor) << 0) |
|
||||
(packToFloat11(src[1] * scaleFactor) << 11) |
|
||||
(packToFloat10(src[2] * scaleFactor) << 22));
|
||||
}
|
||||
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB11F11F10F, WebGLTexelPremultiplicationOp::Unpremultiply, float, uint32_t>(const float* __restrict src, uint32_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
|
||||
dst[0] = ((packToFloat11(src[0] * scaleFactor) << 0) |
|
||||
(packToFloat11(src[1] * scaleFactor) << 11) |
|
||||
(packToFloat10(src[2] * scaleFactor) << 22));
|
||||
}
|
||||
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
|
||||
{
|
||||
|
@ -106,6 +106,7 @@ enum class WebGLTexelFormat : uint8_t {
|
||||
// 3-channel formats
|
||||
RGB8,
|
||||
RGB565,
|
||||
RGB11F11F10F,
|
||||
RGB16F, // OES_texture_half_float
|
||||
RGB32F, // OES_texture_float
|
||||
// 4-channel formats
|
||||
|
Loading…
Reference in New Issue
Block a user