d3dx9: Implement D3DXFloat16to32Array and D3DXFloat32to16Array.
Misha Koshelev
misha680 at gmail.com
Mon Feb 7 12:37:09 CST 2011
On Mon, Feb 7, 2011 at 3:32 AM, Stefan Dösinger <stefandoesinger at gmx.at> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
>
> Am 07.02.2011 um 03:37 schrieb Misha Koshelev:
>> + FLOAT full[10] = { 1.0f, -2.0f, 6.55e4, 6.10352e-5, 5.96046e-8, 0.0f, -0.0f, INFINITY, -INFINITY, NAN },
>> + full_exp[10] = { 1.0f, -2.0f, 6.55e4, 6.10352e-5, 5.96046e-8, 0.0f, -0.0f, 65536.0f, -131008.0f, 131008.0f },
>> + full_res[10];
> I'd rather call them "single" instead of full because 32 bit floats are usually referred to as single precision(doubles are double precision, and 16 bit floats half precision)
Done.
>
>> math.c:2238: Test failed: Got 7fff, expected 7c00 for index 7.
> Looks like Windows doesn't do INF, and returns NaN instead. Your -INF value test already expects NaN as return value, but with the sign bit set. INF or -INF should have all mantissa bits set to 0. NaN looks like +/- INF, just with mantissa != 0(so there are many possible encodings of NaN).
>
> However, it is also possible that Windows doesn't support those special values at all. This is suggested by the fact that +/- NaN is happily converted into a proper single precision value.
Stefan: I believe this is actually a _difference_ between Windows versions.
As you will note on the full results from winetestbot as well as my
own testing on XP (what I _thought_ was SP3) is that only 3/9
platforms have this error. The rest pass fine. Thus, it seems a
variance in the tests.
Please see http://testbot.winehq.org/JobDetails.pl?Key=8981.
I have attached a patch that passes all tests:
https://testbot.winehq.org/JobDetails.pl?Key=8985
What do you think?
If I am missing something please do let me know.
Thank you
Misha
p.s. I heard down the grapevine that Henri might be on vacation for a
week. If so, please wish him the best for me and I hope he enjoys his
time. If I am mistaken, would be great to know. Thank you.
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
>
> iQIcBAEBAgAGBQJNT64vAAoJEN0/YqbEcdMwHskP/2UvtNtsTuC6wL9skKbAhMxf
> 9AyjSx+k8BOb2fQpkLrrR8gPC3feERax+MCrprPDgjSWftWKxWezfRDSAL9eR/+E
> BQNRq0v+NfEITVCHVbMee3CNV+acWv2rXViz2HT03JCbuTe3htBytf8XPGPcrfUj
> ls1KjNPVoYxH5cQJ4sVwAxbMR7CVI9F++B9LiLV8UzJkeYhztilKC3Qu+PLj1QFh
> jXhfbwHMgCo4cunLIPTxZFndFcLvKwHVUSpZcFmY/OQBxWDAKqlo4fQKVw8Gonlb
> Q0AbwKMbWQeOPq8Wlyb0XFV35qdUdDkAkJ0139SiyMCakgzmnebAmpx2Ur5/LNQl
> t82jG+30Ajvnq43oXyczrmoueLtCdOqrXUiEl8wSpcQqFdC13N67NzzGNRvhBfNK
> wJw25P9VZZCvpw5Wx3iqVXpk1Honrjmrn/hgLLHCKOA1Iv4mByp1svu263n4mfIq
> Ga3gUdKzcv++1qr9eOfFfG7waGxrNZ8+X2q5Pp6f0SmeoX2nlhYjzOlCOdFDbFA1
> yEjHXFYkeZw9PD83c7fOkpLkrEcyDCEol9reDzzQXqmFKYoYP2JLLvRjjnPWoxk0
> LviYxmFQ1kZMBhR6WojGx1WjEPVEa+uQxmrK4n6H8fymsXVGu5TfbFgJvmrmg2hG
> hRDKzYpNRuUYojjHKP6N
> =EhgD
> -----END PGP SIGNATURE-----
>
-------------- next part --------------
From 4495cd387784a57b8671245d1960f884b36f9fd9 Mon Sep 17 00:00:00 2001
From: Misha Koshelev <misha680 at gmail.com>
Date: Mon, 7 Feb 2011 13:25:07 -0500
Subject: d3dx9: Implement D3DXFloat16to32Array and D3DXFloat32to16Array.
To: wine-patches <wine-patches at winehq.org>
Reply-To: wine-devel <wine-devel at winehq.org>
---
dlls/d3dx9_36/d3dx9_36.spec | 4 +-
dlls/d3dx9_36/math.c | 90 +++++++++++++++++++++++++++++++++++++++++++
dlls/d3dx9_36/tests/math.c | 39 ++++++++++++++++++
include/d3dx9math.h | 18 +++++++++
include/d3dx9math.inl | 31 +++++++++++++++
5 files changed, 180 insertions(+), 2 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec
index cbb6d20..55fe0cb 100644
--- a/dlls/d3dx9_36/d3dx9_36.spec
+++ b/dlls/d3dx9_36/d3dx9_36.spec
@@ -130,8 +130,8 @@
@ stub D3DXFillVolumeTextureTX
@ stdcall D3DXFilterTexture(ptr ptr long long)
@ stdcall D3DXFindShaderComment(ptr long ptr ptr)
-@ stub D3DXFloat16To32Array
-@ stub D3DXFloat32To16Array
+@ stdcall D3DXFloat16To32Array(ptr ptr long)
+@ stdcall D3DXFloat32To16Array(ptr ptr long)
@ stub D3DXFrameAppendChild
@ stub D3DXFrameCalculateBoundingSphere
@ stub D3DXFrameDestroy
diff --git a/dlls/d3dx9_36/math.c b/dlls/d3dx9_36/math.c
index fdb5f92..6d9b9b2 100644
--- a/dlls/d3dx9_36/math.c
+++ b/dlls/d3dx9_36/math.c
@@ -1769,3 +1769,93 @@ D3DXVECTOR4* WINAPI D3DXVec4TransformArray(D3DXVECTOR4* out, UINT outstride, CON
}
return out;
}
+
+static inline unsigned short float_32_to_16(const float *in)
+{
+ int exp = 0;
+ float tmp = fabs(*in);
+ unsigned int mantissa;
+ unsigned short ret;
+
+ /* Deal with special numbers */
+ if (*((unsigned int *) in) == 0x00000000) return 0x0000;
+ if (*((unsigned int *) in) == 0x80000000) return 0x8000;
+ if (isnan(*in)) return 0x7FFF;
+ if (isinf(*in)) return (*in < 0.0f ? 0xFFFF : 0x7c00);
+
+ if (tmp < powf(2, 10)) {
+ do
+ {
+ tmp = tmp * 2.0f;
+ exp--;
+ } while (tmp < powf(2, 10));
+ } else if (tmp >= powf(2, 11)) {
+ do
+ {
+ tmp /= 2.0f;
+ exp++;
+ } while (tmp >= powf(2, 11));
+ }
+
+ mantissa = (unsigned int) tmp;
+ if (tmp - mantissa >= 0.5f) mantissa++; /* round to nearest, away from zero */
+
+ exp += 10; /* Normalize the mantissa */
+ exp += 15; /* Exponent is encoded with excess 15 */
+
+ if (exp > 30) { /* too big */
+ ret = 0x7c00; /* INF */
+ } else if (exp <= 0) {
+ /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers */
+ while (exp <= 0) {
+ mantissa = mantissa >> 1;
+ exp++;
+ }
+ ret = mantissa & 0x3ff;
+ } else {
+ ret = (exp << 10) | (mantissa & 0x3ff);
+ }
+
+ ret |= ((*in < 0.0f ? 1 : 0) << 15); /* Add the sign */
+ return ret;
+}
+
+D3DXFLOAT16 *WINAPI D3DXFloat32To16Array(D3DXFLOAT16 *pout, CONST FLOAT *pin, UINT n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; ++i) {
+ pout[i].value = float_32_to_16(&pin[i]);
+ }
+
+ return pout;
+}
+
+static inline float float_16_to_32(const unsigned short *in) {
+ const unsigned short s = ((*in) & 0x8000);
+ const unsigned short e = ((*in) & 0x7C00) >> 10;
+ const unsigned short m = (*in) & 0x3FF;
+ const float sgn = (s ? -1.0f : 1.0f);
+
+ if (e == 0) {
+ if (m == 0) return sgn * 0.0f; /* +0.0 or -0.0 */
+ else return sgn * powf(2, -14.0f) * ((float)m / 1024.0f);
+ } else if (e < 31) {
+ return sgn * powf(2, (float)e - 15.0f) * (1.0f + ((float)m / 1024.0f));
+ } else {
+ if (m == 0) return 65536.0f;
+ else if (s) return -131008.0f;
+ else return 131008.0f;
+ }
+}
+
+FLOAT *WINAPI D3DXFloat16To32Array(FLOAT *pout, CONST D3DXFLOAT16 *pin, UINT n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; ++i) {
+ pout[i] = float_16_to_32(&pin[i].value);
+ }
+
+ return pout;
+}
diff --git a/dlls/d3dx9_36/tests/math.c b/dlls/d3dx9_36/tests/math.c
index e455a96..4d86c2d 100644
--- a/dlls/d3dx9_36/tests/math.c
+++ b/dlls/d3dx9_36/tests/math.c
@@ -2216,6 +2216,44 @@ static void test_D3DXVec_Array(void)
compare_planes(exp_plane, out_plane);
}
+#include <math.h>
+static void test_D3DXFloat_Array(void)
+{
+ unsigned int i;
+ void *out = NULL;
+ D3DXFLOAT16 half_res[10];
+ FLOAT single[10] = { 1.0f, -2.0f, 6.55e4, 6.10352e-5, 5.96046e-8, 0.0f, -0.0f, INFINITY, -INFINITY, NAN },
+ single_exp[10] = { 1.0f, -2.0f, 6.55e4, 6.10352e-5, 5.96046e-8, 0.0f, -0.0f, 65536.0f, -131008.0f, 131008.0f },
+ single_res[10];
+ WORD half_ver1[10] = { 0x3c00, 0xc000, 0x7bff, 0x0400, 0x0001, 0x0000, 0x8000, 0x7c00, 0xffff, 0x7fff };
+ WORD half_ver2[10] = { 0x3c00, 0xc000, 0x7bff, 0x0400, 0x0001, 0x0000, 0x8000, 0x7fff, 0xffff, 0x7fff };
+
+ /* exception on NULL out or in parameter */
+ out = D3DXFloat32To16Array(half_res, single, 0);
+ ok(out == half_res, "Got %p, expected %p.\n", out, half_res);
+
+ out = D3DXFloat32To16Array(half_res, single, 10);
+ ok(out == half_res, "Got %p, expected %p.\n", out, half_res);
+
+ for (i = 0; i < 10; i++) {
+ ok(half_res[i].value == half_ver1[i] ||
+ half_res[i].value == half_ver2[i], "Got %x, expected %x or %x for index %d.\n",
+ half_res[i].value, half_ver1[i], half_ver2[i], i);
+ }
+
+ /* exception on NULL out or in parameter */
+ out = D3DXFloat16To32Array(single_res, (D3DXFLOAT16 *)half_ver1, 0);
+ ok(out == single_res, "Got %p, expected %p.\n", out, single_res);
+
+ out = D3DXFloat16To32Array(single_res, (D3DXFLOAT16 *)half_ver1, 10);
+ ok(out == single_res, "Got %p, expected %p.\n", out, single_res);
+
+ for (i = 0; i < 10; i++) {
+ ok(relative_error(single_res[i], single_exp[i]) < admitted_error, "Got %f, expected %f for index %d.\n",
+ single_res[i], single_exp[i], i);
+ }
+}
+
START_TEST(math)
{
D3DXColorTest();
@@ -2231,4 +2269,5 @@ START_TEST(math)
test_Matrix_Decompose();
test_Matrix_Transformation2D();
test_D3DXVec_Array();
+ test_D3DXFloat_Array();
}
diff --git a/include/d3dx9math.h b/include/d3dx9math.h
index f842e3e..cdb1deb 100644
--- a/include/d3dx9math.h
+++ b/include/d3dx9math.h
@@ -261,6 +261,21 @@ typedef struct D3DXCOLOR
FLOAT r, g, b, a;
} D3DXCOLOR, *LPD3DXCOLOR;
+typedef struct D3DXFLOAT16
+{
+#ifdef __cplusplus
+ D3DXFLOAT16();
+ D3DXFLOAT16(FLOAT f);
+ D3DXFLOAT16(CONST D3DXFLOAT16 &f);
+
+ operator FLOAT ();
+
+ BOOL operator == (CONST D3DXFLOAT16 &) const;
+ BOOL operator != (CONST D3DXFLOAT16 &) const;
+#endif /* __cplusplus */
+ WORD value;
+} D3DXFLOAT16, *LPD3DXFLOAT16;
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -358,6 +373,9 @@ D3DXVECTOR4* WINAPI D3DXVec4Normalize(D3DXVECTOR4 *pout, CONST D3DXVECTOR4 *pv);
D3DXVECTOR4* WINAPI D3DXVec4Transform(D3DXVECTOR4 *pout, CONST D3DXVECTOR4 *pv, CONST D3DXMATRIX *pm);
D3DXVECTOR4* WINAPI D3DXVec4TransformArray(D3DXVECTOR4 *pout, UINT outstride, CONST D3DXVECTOR4 *pv, UINT vstride, CONST D3DXMATRIX *pm, UINT n);
+D3DXFLOAT16 *WINAPI D3DXFloat32To16Array(D3DXFLOAT16 *pout, CONST FLOAT *pin, UINT n);
+FLOAT *WINAPI D3DXFloat16To32Array(FLOAT *pout, CONST D3DXFLOAT16 *pin, UINT n);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/d3dx9math.inl b/include/d3dx9math.inl
index 3cd078a..3f55aef 100644
--- a/include/d3dx9math.inl
+++ b/include/d3dx9math.inl
@@ -851,6 +851,37 @@ inline BOOL D3DXCOLOR::operator != (CONST D3DXCOLOR& col) const
return r != col.r || g != col.g || b != col.b || a != col.a;
}
+inline D3DXFLOAT16::D3DXFLOAT16()
+{
+}
+
+inline D3DXFLOAT16::D3DXFLOAT16(FLOAT f)
+{
+ D3DXFloat32To16Array(this, &f, 1);
+}
+
+inline D3DXFLOAT16::D3DXFLOAT16(CONST D3DXFLOAT16 &f)
+{
+ value = f.value;
+}
+
+inline D3DXFLOAT16::operator FLOAT ()
+{
+ FLOAT f;
+ D3DXFloat16To32Array(&f, this, 1);
+ return f;
+}
+
+inline BOOL D3DXFLOAT16::operator == (CONST D3DXFLOAT16 &f) const
+{
+ return value == f.value;
+}
+
+inline BOOL D3DXFLOAT16::operator != (CONST D3DXFLOAT16 &f) const
+{
+ return value != f.value;
+}
+
#endif /* __cplusplus */
/*_______________D3DXCOLOR_____________________*/
--
1.7.4
More information about the wine-devel
mailing list