Module: wine Branch: master Commit: a6b40624dbc457ba7b0b4b307b1eb88617c67197 URL: http://source.winehq.org/git/wine.git/?a=commit;h=a6b40624dbc457ba7b0b4b307b...
Author: Misha Koshelev misha680@gmail.com Date: Wed Jun 29 11:16:29 2011 -0400
d3dx9_36: Implement and add tests for D3DXFloat16To32Array.
---
dlls/d3dx9_36/d3dx9_36.spec | 2 +- dlls/d3dx9_36/math.c | 32 +++++++++++++++++++++++ dlls/d3dx9_36/tests/math.c | 60 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec index a9b98a7..5973d20 100644 --- a/dlls/d3dx9_36/d3dx9_36.spec +++ b/dlls/d3dx9_36/d3dx9_36.spec @@ -130,7 +130,7 @@ @ stub D3DXFillVolumeTextureTX(ptr ptr) @ stdcall D3DXFilterTexture(ptr ptr long long) @ stdcall D3DXFindShaderComment(ptr long ptr ptr) -@ stub D3DXFloat16To32Array(ptr ptr long) +@ stdcall D3DXFloat16To32Array(ptr ptr long) @ stub D3DXFloat32To16Array(ptr ptr long) @ stub D3DXFrameAppendChild(ptr ptr) @ stub D3DXFrameCalculateBoundingSphere(ptr ptr ptr) diff --git a/dlls/d3dx9_36/math.c b/dlls/d3dx9_36/math.c index fdb5f92..fde3e4e 100644 --- a/dlls/d3dx9_36/math.c +++ b/dlls/d3dx9_36/math.c @@ -1769,3 +1769,35 @@ D3DXVECTOR4* WINAPI D3DXVec4TransformArray(D3DXVECTOR4* out, UINT outstride, CON } return out; } + +/* Native d3dx9's D3DXFloat16to32Array lacks support for NaN and Inf. Specifically, e = 16 is treated as a + * regular number - e.g., 0x7fff is converted to 131008.0 and 0xffff to -131008.0. */ +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) * (m / 1024.0f); + } + else + { + return sgn * powf(2, e - 15.0f) * (1.0f + (m / 1024.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 5ad1924..aa3f135 100644 --- a/dlls/d3dx9_36/tests/math.c +++ b/dlls/d3dx9_36/tests/math.c @@ -21,6 +21,7 @@
#include "wine/test.h" #include "d3dx9.h" +#include <math.h>
#define ARRAY_SIZE 5
@@ -2215,6 +2216,64 @@ static void test_D3DXVec_Array(void) compare_planes(exp_plane, out_plane); }
+static void test_D3DXFloat_Array(void) +{ + unsigned int i; + void *out = NULL; + D3DXFLOAT16 half; + FLOAT single; + struct + { + FLOAT single_in; + + /* half_ver2 occurs on WXPPROSP3 (32 bit math), WVISTAADM (32 bit math), W7PRO (32 bit math) */ + WORD half_ver1, half_ver2; + + /* single_out_ver2 confirms that half -> single conversion is consistent across platforms */ + FLOAT single_out_ver1, single_out_ver2; + } testdata[] = { + { 80000.0f, 0x7c00, 0x7ce2, 65536.0f, 80000.0f }, + { 65503.0f, 0x7bff, 0x7bff, 65504.0f, 65504.0f }, + { 65504.0f, 0x7bff, 0x7bff, 65504.0f, 65504.0f }, + { 65520.0f, 0x7bff, 0x7c00, 65504.0f, 65536.0f }, + { 65521.0f, 0x7c00, 0x7c00, 65536.0f, 65536.0f }, + { 65534.0f, 0x7c00, 0x7c00, 65536.0f, 65536.0f }, + { 65535.0f, 0x7c00, 0x7c00, 65535.0f, 65536.0f }, + { 65536.0f, 0x7c00, 0x7c00, 65536.0f, 65536.0f }, + { -80000.0f, 0xfc00, 0xfce2, -65536.0f, -80000.0f }, + { -65503.0f, 0xfbff, 0xfbff, -65504.0f, -65504.0f }, + { -65504.0f, 0xfbff, 0xfbff, -65504.0f, -65504.0f }, + { -65520.0f, 0xfbff, 0xfc00, -65504.0f, -65536.0f }, + { -65521.0f, 0xfc00, 0xfc00, -65536.0f, -65536.0f }, + { -65534.0f, 0xfc00, 0xfc00, -65536.0f, -65536.0f }, + { -65535.0f, 0xfc00, 0xfc00, -65535.0f, -65536.0f }, + { -65536.0f, 0xfc00, 0xfc00, -65536.0f, -65536.0f }, + { INFINITY, 0x7c00, 0x7fff, 65536.0f, 131008.0f }, + { -INFINITY, 0xffff, 0xffff, -131008.0f, -131008.0f }, + { NAN, 0x7fff, 0x7fff, 131008.0f, 131008.0f }, + { -NAN, 0xffff, 0xffff, -131008.0f, -131008.0f }, + { 0.0f, 0x0, 0x0, 0.0f, 0.0f }, + { -0.0f, 0x8000, 0x8000, 0.0f, 0.0f }, + }; + + /* exception on NULL out or in parameter */ + out = D3DXFloat16To32Array(&single, (D3DXFLOAT16 *)&half, 0); + ok(out == &single, "Got %p, expected %p.\n", out, &single); + + for (i = 0; i < sizeof(testdata)/sizeof(testdata[0]); i++) + { + out = D3DXFloat16To32Array(&single, (D3DXFLOAT16 *)&testdata[i].half_ver1, 1); + ok(out == &single, "Got %p, expected %p.\n", out, &single); + ok(relative_error(single, testdata[i].single_out_ver1) < admitted_error, + "Got %g, expected %g for index %d.\n", single, testdata[i].single_out_ver1, i); + + out = D3DXFloat16To32Array(&single, (D3DXFLOAT16 *)&testdata[i].half_ver2, 1); + ok(out == &single, "Got %p, expected %p.\n", out, &single); + ok(relative_error(single, testdata[i].single_out_ver2) < admitted_error, + "Got %g, expected %g for index %d.\n", single, testdata[i].single_out_ver2, i); + } +} + START_TEST(math) { D3DXColorTest(); @@ -2230,4 +2289,5 @@ START_TEST(math) test_Matrix_Decompose(); test_Matrix_Transformation2D(); test_D3DXVec_Array(); + test_D3DXFloat_Array(); }