[PATCH] d3dx9: Implement D3DXSHProjectCubeMap().

Zebediah Figura zfigura at codeweavers.com
Sat Jan 29 19:46:43 CST 2022


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46284
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/d3dx9_24/d3dx9_24.spec   |   2 +-
 dlls/d3dx9_25/d3dx9_25.spec   |   2 +-
 dlls/d3dx9_26/d3dx9_26.spec   |   2 +-
 dlls/d3dx9_27/d3dx9_27.spec   |   2 +-
 dlls/d3dx9_28/d3dx9_28.spec   |   2 +-
 dlls/d3dx9_29/d3dx9_29.spec   |   2 +-
 dlls/d3dx9_30/d3dx9_30.spec   |   2 +-
 dlls/d3dx9_31/d3dx9_31.spec   |   2 +-
 dlls/d3dx9_32/d3dx9_32.spec   |   2 +-
 dlls/d3dx9_33/d3dx9_33.spec   |   2 +-
 dlls/d3dx9_34/d3dx9_34.spec   |   2 +-
 dlls/d3dx9_35/d3dx9_35.spec   |   2 +-
 dlls/d3dx9_36/d3dx9_36.spec   |   2 +-
 dlls/d3dx9_36/d3dx9_private.h |   2 +
 dlls/d3dx9_36/math.c          | 143 ++++++++++++++++++++++++
 dlls/d3dx9_36/surface.c       |   2 +-
 dlls/d3dx9_36/tests/math.c    | 199 ++++++++++++++++++++++++++++++++++
 dlls/d3dx9_37/d3dx9_37.spec   |   2 +-
 dlls/d3dx9_38/d3dx9_38.spec   |   2 +-
 dlls/d3dx9_39/d3dx9_39.spec   |   2 +-
 dlls/d3dx9_40/d3dx9_40.spec   |   2 +-
 dlls/d3dx9_41/d3dx9_41.spec   |   2 +-
 dlls/d3dx9_42/d3dx9_42.spec   |   2 +-
 dlls/d3dx9_43/d3dx9_43.spec   |   2 +-
 include/d3dx9math.h           |   1 +
 25 files changed, 366 insertions(+), 21 deletions(-)

diff --git a/dlls/d3dx9_24/d3dx9_24.spec b/dlls/d3dx9_24/d3dx9_24.spec
index d617d766f85..8791e4ec044 100644
--- a/dlls/d3dx9_24/d3dx9_24.spec
+++ b/dlls/d3dx9_24/d3dx9_24.spec
@@ -256,7 +256,7 @@
 @ stdcall D3DXSHEvalSphericalLight(long ptr float float float float ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_25/d3dx9_25.spec b/dlls/d3dx9_25/d3dx9_25.spec
index f13923dcb3a..0431a9f7f75 100644
--- a/dlls/d3dx9_25/d3dx9_25.spec
+++ b/dlls/d3dx9_25/d3dx9_25.spec
@@ -256,7 +256,7 @@
 @ stdcall D3DXSHEvalSphericalLight(long ptr float float float float ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_26/d3dx9_26.spec b/dlls/d3dx9_26/d3dx9_26.spec
index 286a9a094a0..5ab0a1d9fea 100644
--- a/dlls/d3dx9_26/d3dx9_26.spec
+++ b/dlls/d3dx9_26/d3dx9_26.spec
@@ -260,7 +260,7 @@
 @ stdcall D3DXSHEvalSphericalLight(long ptr float float float float ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_27/d3dx9_27.spec b/dlls/d3dx9_27/d3dx9_27.spec
index 286a9a094a0..5ab0a1d9fea 100644
--- a/dlls/d3dx9_27/d3dx9_27.spec
+++ b/dlls/d3dx9_27/d3dx9_27.spec
@@ -260,7 +260,7 @@
 @ stdcall D3DXSHEvalSphericalLight(long ptr float float float float ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_28/d3dx9_28.spec b/dlls/d3dx9_28/d3dx9_28.spec
index 06ced20df61..af5b6077202 100644
--- a/dlls/d3dx9_28/d3dx9_28.spec
+++ b/dlls/d3dx9_28/d3dx9_28.spec
@@ -265,7 +265,7 @@
 @ stdcall D3DXSHEvalSphericalLight(long ptr float float float float ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_29/d3dx9_29.spec b/dlls/d3dx9_29/d3dx9_29.spec
index 06ced20df61..af5b6077202 100644
--- a/dlls/d3dx9_29/d3dx9_29.spec
+++ b/dlls/d3dx9_29/d3dx9_29.spec
@@ -265,7 +265,7 @@
 @ stdcall D3DXSHEvalSphericalLight(long ptr float float float float ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_30/d3dx9_30.spec b/dlls/d3dx9_30/d3dx9_30.spec
index 06ced20df61..af5b6077202 100644
--- a/dlls/d3dx9_30/d3dx9_30.spec
+++ b/dlls/d3dx9_30/d3dx9_30.spec
@@ -265,7 +265,7 @@
 @ stdcall D3DXSHEvalSphericalLight(long ptr float float float float ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_31/d3dx9_31.spec b/dlls/d3dx9_31/d3dx9_31.spec
index c9aca309a35..8f77dc666a2 100644
--- a/dlls/d3dx9_31/d3dx9_31.spec
+++ b/dlls/d3dx9_31/d3dx9_31.spec
@@ -262,7 +262,7 @@
 @ stdcall D3DXSHEvalSphericalLight(long ptr float float float float ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_32/d3dx9_32.spec b/dlls/d3dx9_32/d3dx9_32.spec
index f541f6f2ef1..2fdd2a00615 100644
--- a/dlls/d3dx9_32/d3dx9_32.spec
+++ b/dlls/d3dx9_32/d3dx9_32.spec
@@ -267,7 +267,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_33/d3dx9_33.spec b/dlls/d3dx9_33/d3dx9_33.spec
index f541f6f2ef1..2fdd2a00615 100644
--- a/dlls/d3dx9_33/d3dx9_33.spec
+++ b/dlls/d3dx9_33/d3dx9_33.spec
@@ -267,7 +267,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_34/d3dx9_34.spec b/dlls/d3dx9_34/d3dx9_34.spec
index f541f6f2ef1..2fdd2a00615 100644
--- a/dlls/d3dx9_34/d3dx9_34.spec
+++ b/dlls/d3dx9_34/d3dx9_34.spec
@@ -267,7 +267,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_35/d3dx9_35.spec b/dlls/d3dx9_35/d3dx9_35.spec
index f541f6f2ef1..2fdd2a00615 100644
--- a/dlls/d3dx9_35/d3dx9_35.spec
+++ b/dlls/d3dx9_35/d3dx9_35.spec
@@ -267,7 +267,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec
index e1f44261610..5b7070145de 100644
--- a/dlls/d3dx9_36/d3dx9_36.spec
+++ b/dlls/d3dx9_36/d3dx9_36.spec
@@ -269,7 +269,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h
index c3308b04d44..2d286b04694 100644
--- a/dlls/d3dx9_36/d3dx9_private.h
+++ b/dlls/d3dx9_36/d3dx9_private.h
@@ -100,6 +100,8 @@ HRESULT write_buffer_to_file(const WCHAR *filename, ID3DXBuffer *buffer) DECLSPE
 const struct pixel_format_desc *get_format_info(D3DFORMAT format) DECLSPEC_HIDDEN;
 const struct pixel_format_desc *get_format_info_idx(int idx) DECLSPEC_HIDDEN;
 
+void format_to_vec4(const struct pixel_format_desc *format, const BYTE *src, struct vec4 *dst);
+
 void copy_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch,
     BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *size,
     const struct pixel_format_desc *format) DECLSPEC_HIDDEN;
diff --git a/dlls/d3dx9_36/math.c b/dlls/d3dx9_36/math.c
index a7b0a018680..0dde552d45f 100644
--- a/dlls/d3dx9_36/math.c
+++ b/dlls/d3dx9_36/math.c
@@ -2969,6 +2969,149 @@ static void rotate_X(FLOAT *out, UINT order, FLOAT a, FLOAT *in)
     out[35] = 0.9057110548f * in[31] - 0.4192627370f * in[33] + 0.0624999329f * in[35];
 }
 
+static void set_vec3(D3DXVECTOR3 *v, float x, float y, float z)
+{
+    v->x = x;
+    v->y = y;
+    v->z = z;
+}
+
+/*
+ * The following implementation of D3DXSHProjectCubeMap is based on the
+ * SHProjectCubeMap() implementation from Microsoft's DirectXMath library,
+ * covered under the following copyright:
+ *
+ * Copyright (c) Microsoft Corporation.
+ * Licensed under the MIT License.
+ */
+HRESULT WINAPI D3DXSHProjectCubeMap(unsigned int order, IDirect3DCubeTexture9 *texture, float *red, float *green, float *blue)
+{
+    const unsigned int order_square = order * order;
+    const struct pixel_format_desc *format;
+    unsigned int x, y, i, face;
+    float B, S, proj_normal;
+    D3DSURFACE_DESC desc;
+    float Wt = 0.0f;
+    float *temp;
+    HRESULT hr;
+
+    TRACE("order %u, texture %p, red %p, green %p, blue %p.\n", order, texture, red, green, blue);
+
+    if (!texture || !red || order < D3DXSH_MINORDER || order > D3DXSH_MAXORDER)
+        return D3DERR_INVALIDCALL;
+
+    memset(red, 0, order_square * sizeof(float));
+    if (green)
+        memset(green, 0, order_square * sizeof(float));
+    if (blue)
+        memset(blue, 0, order_square * sizeof(float));
+
+    if (FAILED(hr = IDirect3DCubeTexture9_GetLevelDesc(texture, 0, &desc)))
+    {
+        ERR("Failed to get level desc, hr %#x.\n", hr);
+        return hr;
+    }
+
+    format = get_format_info(desc.Format);
+    if (format->type != FORMAT_ARGB && format->type != FORMAT_ARGBF16 && format->type != FORMAT_ARGBF)
+    {
+        FIXME("Unsupported texture format %#x.\n", desc.Format);
+        return D3DERR_INVALIDCALL;
+    }
+
+    if (!(temp = malloc(order_square * sizeof(*temp))))
+        return E_OUTOFMEMORY;
+
+    B = -1.0f + 1.0f / desc.Width;
+    if (desc.Width > 1)
+        S = 2.0f * (1.0f - 1.0f / desc.Width) / (desc.Width - 1.0f);
+    else
+        S = 0.0f;
+
+    for (face = 0; face < 6; ++face)
+    {
+        D3DLOCKED_RECT map_desc;
+
+        if (FAILED(hr = IDirect3DCubeTexture9_LockRect(texture, face, 0, &map_desc, NULL, D3DLOCK_READONLY)))
+        {
+            ERR("Failed to map texture, hr %#x.\n", hr);
+            return hr;
+        }
+
+        for (y = 0; y < desc.Height; ++y)
+        {
+            const BYTE *row = (const BYTE *)map_desc.pBits + y * map_desc.Pitch;
+
+            for (x = 0; x < desc.Width; ++x)
+            {
+                float diff_solid, x_3d, y_3d;
+                const float u = x * S + B;
+                const float v = y * S + B;
+                struct vec4 colour;
+                D3DXVECTOR3 dir;
+
+                x_3d = (x * 2.0f + 1.0f) / desc.Width - 1.0f;
+                y_3d = (y * 2.0f + 1.0f) / desc.Width - 1.0f;
+
+                switch (face)
+                {
+                    case D3DCUBEMAP_FACE_POSITIVE_X:
+                        set_vec3(&dir, 1.0f, -y_3d, -x_3d);
+                        break;
+
+                    case D3DCUBEMAP_FACE_NEGATIVE_X:
+                        set_vec3(&dir, -1.0f, -y_3d, x_3d);
+                        break;
+
+                    case D3DCUBEMAP_FACE_POSITIVE_Y:
+                        set_vec3(&dir, x_3d, 1.0f, y_3d);
+                        break;
+
+                    case D3DCUBEMAP_FACE_NEGATIVE_Y:
+                        set_vec3(&dir, x_3d, -1.0f, -y_3d);
+                        break;
+
+                    case D3DCUBEMAP_FACE_POSITIVE_Z:
+                        set_vec3(&dir, x_3d, -y_3d, 1.0f);
+                        break;
+
+                    case D3DCUBEMAP_FACE_NEGATIVE_Z:
+                        set_vec3(&dir, -x_3d, -y_3d, -1.0f);
+                        break;
+                }
+
+                diff_solid = 4.0f / ((1.0f + u * u + v * v) * sqrtf(1.0f + u * u + v * v));
+                Wt += diff_solid;
+
+                D3DXVec3Normalize(&dir, &dir);
+                D3DXSHEvalDirection(temp, order, &dir);
+
+                format_to_vec4(format, &row[x * format->block_byte_count], &colour);
+
+                for (i = 0; i < order_square; ++i)
+                {
+                    red[i] += temp[i] * colour.x * diff_solid;
+                    if (green)
+                        green[i] += temp[i] * colour.y * diff_solid;
+                    if (blue)
+                        blue[i] += temp[i] * colour.z * diff_solid;
+                }
+            }
+        }
+
+        IDirect3DCubeTexture9_UnlockRect(texture, face, 0);
+    }
+
+    proj_normal = (4.0f * M_PI) / Wt;
+    D3DXSHScale(red, order, red, proj_normal);
+    if (green)
+        D3DXSHScale(green, order, green, proj_normal);
+    if (blue)
+        D3DXSHScale(blue, order, blue, proj_normal);
+
+    return D3D_OK;
+}
+
 FLOAT* WINAPI D3DXSHRotate(FLOAT *out, UINT order, const D3DXMATRIX *matrix, const FLOAT *in)
 {
     FLOAT alpha, beta, gamma, sinb, temp[36], temp1[36];
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c
index c3f9f84a789..2ca6f093b55 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -1564,7 +1564,7 @@ static DWORD make_argb_color(const struct argb_conversion_info *info, const DWOR
 }
 
 /* It doesn't work for components bigger than 32 bits (or somewhat smaller but unaligned). */
-static void format_to_vec4(const struct pixel_format_desc *format, const BYTE *src, struct vec4 *dst)
+void format_to_vec4(const struct pixel_format_desc *format, const BYTE *src, struct vec4 *dst)
 {
     DWORD mask, tmp;
     unsigned int c;
diff --git a/dlls/d3dx9_36/tests/math.c b/dlls/d3dx9_36/tests/math.c
index 6f64e25d200..40193f50fcc 100644
--- a/dlls/d3dx9_36/tests/math.c
+++ b/dlls/d3dx9_36/tests/math.c
@@ -22,6 +22,7 @@
 #include "wine/test.h"
 #include "d3dx9.h"
 #include <math.h>
+#include <stdint.h>
 
 static BOOL compare_float(float f, float g, unsigned int ulps)
 {
@@ -205,6 +206,53 @@ static void set_matrix(D3DXMATRIX* mat,
     U(mat)->m[3][0] = m30; U(mat)->m[3][1] = m31; U(mat)->m[3][2] = m32; U(mat)->m[3][3] = m33;
 }
 
+static HWND create_window(void)
+{
+    RECT r = {0, 0, 640, 480};
+
+    AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
+
+    return CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+            0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
+}
+
+static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window)
+{
+    D3DPRESENT_PARAMETERS present_parameters = {0};
+    unsigned int adapter_ordinal;
+    IDirect3DDevice9 *device;
+    DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
+
+    adapter_ordinal = D3DADAPTER_DEFAULT;
+    present_parameters.BackBufferWidth = 640;
+    present_parameters.BackBufferHeight = 480;
+    present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
+    present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    present_parameters.hDeviceWindow = focus_window;
+    present_parameters.Windowed = TRUE;
+    present_parameters.EnableAutoDepthStencil = TRUE;
+    present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
+
+    if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, adapter_ordinal, D3DDEVTYPE_HAL, focus_window,
+            behavior_flags, &present_parameters, &device)))
+        return device;
+
+    present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
+    if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, adapter_ordinal, D3DDEVTYPE_HAL, focus_window,
+            behavior_flags, &present_parameters, &device)))
+        return device;
+
+    behavior_flags = (behavior_flags
+            & ~(D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING))
+            | D3DCREATE_HARDWARE_VERTEXPROCESSING;
+
+    if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, adapter_ordinal, D3DDEVTYPE_HAL, focus_window,
+            behavior_flags, &present_parameters, &device)))
+        return device;
+
+    return NULL;
+}
+
 static void D3DXColorTest(void)
 {
     D3DXCOLOR color, color1, color2, expected, got;
@@ -4364,6 +4412,156 @@ static void test_D3DXSHScale(void)
     }
 }
 
+static void test_D3DXSHProjectCubeMap(void)
+{
+    float red[4], green[4], blue[4];
+    IDirect3DCubeTexture9 *texture;
+    unsigned int i, j, face, x, y;
+    IDirect3DDevice9 *device;
+    D3DLOCKED_RECT map_desc;
+    IDirect3D9 *d3d;
+    ULONG refcount;
+    HWND window;
+    HRESULT hr;
+
+    static const struct
+    {
+        D3DFORMAT format;
+        float red[4];
+        float green[4];
+        float blue[4];
+    }
+    tests[] =
+    {
+        {D3DFMT_A8R8G8B8,
+            {1.77656245f, -1.11197047e-2f,  2.08763797e-2f, -2.10229922e-2f},
+            {1.75811982f, -4.82511893e-2f,  1.67397819e-2f, -1.71497762e-2f},
+            {1.75515056f, -4.07523997e-2f,  1.05397226e-2f, -2.46812664e-2f}},
+        {D3DFMT_X8R8G8B8,
+            {1.77656245f, -1.11197047e-2f,  2.08763797e-2f, -2.10229922e-2f},
+            {1.75811982f, -4.82511893e-2f,  1.67397819e-2f, -1.71497762e-2f},
+            {1.75515056f, -4.07523997e-2f,  1.05397226e-2f, -2.46812664e-2f}},
+        {D3DFMT_A8B8G8R8,
+            {1.75515056f, -4.07523997e-2f,  1.05397226e-2f, -2.46812664e-2f},
+            {1.75811982f, -4.82511893e-2f,  1.67397819e-2f, -1.71497762e-2f},
+            {1.77656245f, -1.11197047e-2f,  2.08763797e-2f, -2.10229922e-2f}},
+        {D3DFMT_R5G6B5,
+            {1.77099848f, -3.88867334e-2f,  6.73775524e-2f, -1.26888147e-2f},
+            {1.77244151f, -5.64723741e-4f, -2.77878426e-4f, -9.10691451e-3f},
+            {1.78902030f,  2.79005636e-2f,  1.62461456e-2f,  2.21668324e-3f}},
+        {D3DFMT_A1R5G5B5,
+            {1.78022826f,  1.46923587e-2f,  3.58058624e-2f,  2.51076911e-2f},
+            {1.77233493f, -7.58088892e-4f, -2.03727093e-3f, -1.34809706e-2f},
+            {1.78902030f,  2.79005636e-2f,  1.62461456e-2f,  2.21668324e-3f}},
+        {D3DFMT_X1R5G5B5,
+            {1.78022826f,  1.46923587e-2f,  3.58058624e-2f,  2.51076911e-2f},
+            {1.77233493f, -7.58088892e-4f, -2.03727093e-3f, -1.34809706e-2f},
+            {1.78902030f,  2.79005636e-2f,  1.62461456e-2f,  2.21668324e-3f}},
+        {D3DFMT_A2R10G10B10,
+            {1.79359019f, -7.74506712e-4f,  8.65613017e-3f,  5.75336441e-3f},
+            {1.77067971f,  6.42523961e-3f,  1.35379164e-2f,  2.24088971e-3f},
+            {1.76601243f, -4.94002625e-2f,  1.28124524e-2f, -7.69229094e-3f}},
+        {D3DFMT_A2B10G10R10,
+            {1.76601243f, -4.94002625e-2f,  1.28124524e-2f, -7.69229094e-3f},
+            {1.77067971f,  6.42523961e-3f,  1.35379164e-2f,  2.24088971e-3f},
+            {1.79359019f, -7.74506712e-4f,  8.65613017e-3f,  5.75336441e-3f}},
+        {D3DFMT_A16B16G16R16,
+            {1.75979614f,  1.44450525e-2f, -3.25212209e-3f,  2.98178056e-3f},
+            {1.78080165f, -2.63770130e-2f,  6.31967233e-3f,  3.66022950e-3f},
+            {1.77588308f, -1.93727610e-3f, -3.22831096e-3f, -6.18841546e-3f}},
+        {D3DFMT_A16B16G16R16F,
+            { 5.17193642e+1f, -3.41681671e+2f, -8.82221741e+2f,  7.77049316e+2f},
+            {-2.08198950e+3f,  5.24323584e+3f, -3.42663379e+3f,  3.80999243e+3f},
+            {-1.10743945e+3f, -9.43649292e+2f,  5.48424316e+2f,  1.65352710e+3f}},
+    };
+
+    window = create_window();
+    d3d = Direct3DCreate9(D3D_SDK_VERSION);
+    ok(!!d3d, "Failed to create a D3D object.\n");
+    if (!(device = create_device(d3d, window)))
+    {
+        skip("Failed to create a D3D device, skipping tests.\n");
+        IDirect3D9_Release(d3d);
+        DestroyWindow(window);
+        return;
+    }
+
+    for (i = 0; i < ARRAY_SIZE(tests); ++i)
+    {
+        winetest_push_context("Format %#x", tests[i].format);
+
+        hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 1, D3DUSAGE_DYNAMIC,
+                tests[i].format, D3DPOOL_DEFAULT, &texture, NULL);
+        if (FAILED(hr))
+        {
+            skip("Failed to create cube texture.\n");
+            winetest_pop_context();
+            continue;
+        }
+        ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+        for (face = 0; face < 6; ++face)
+        {
+            hr = IDirect3DCubeTexture9_LockRect(texture, face, 0, &map_desc, NULL, 0);
+            ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+            for (y = 0; y < 8; ++y)
+            {
+                uint8_t *row = (uint8_t *)map_desc.pBits + y * map_desc.Pitch;
+
+                for (x = 0; x < map_desc.Pitch; ++x)
+                    row[x] = face * 111 + y * 39 + x * 7;
+            }
+
+            hr = IDirect3DCubeTexture9_UnlockRect(texture, face, 0);
+            ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+        }
+
+        hr = D3DXSHProjectCubeMap(1, texture, red, green, blue);
+        ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
+
+        hr = D3DXSHProjectCubeMap(7, texture, red, green, blue);
+        ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
+
+        hr = D3DXSHProjectCubeMap(2, NULL, red, green, blue);
+        ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
+
+        memset(red, 0, sizeof(red));
+        memset(green, 0, sizeof(green));
+        memset(blue, 0, sizeof(blue));
+        hr = D3DXSHProjectCubeMap(2, texture, red, green, blue);
+        ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+        for (j = 0; j < 4; ++j)
+        {
+            ok(compare_float(red[j], tests[i].red[j], 1024),
+                    "Got unexpected value %.8e for red coefficient %u.\n", red[j], j);
+            ok(compare_float(green[j], tests[i].green[j], 1024),
+                    "Got unexpected value %.8e for green coefficient %u.\n", green[j], j);
+            ok(compare_float(blue[j], tests[i].blue[j], 1024),
+                    "Got unexpected value %.8e for blue coefficient %u.\n", blue[j], j);
+        }
+
+        hr = D3DXSHProjectCubeMap(2, texture, red, NULL, NULL);
+        ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+        hr = D3DXSHProjectCubeMap(2, texture, NULL, green, NULL);
+        ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
+
+        hr = D3DXSHProjectCubeMap(2, texture, NULL, NULL, blue);
+        ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
+
+        IDirect3DCubeTexture9_Release(texture);
+
+        winetest_pop_context();
+    }
+
+    refcount = IDirect3DDevice9_Release(device);
+    ok(!refcount, "Device has %u references left.\n", refcount);
+    IDirect3D9_Release(d3d);
+    DestroyWindow(window);
+}
+
 START_TEST(math)
 {
     D3DXColorTest();
@@ -4393,4 +4591,5 @@ START_TEST(math)
     test_D3DXSHRotate();
     test_D3DXSHRotateZ();
     test_D3DXSHScale();
+    test_D3DXSHProjectCubeMap();
 }
diff --git a/dlls/d3dx9_37/d3dx9_37.spec b/dlls/d3dx9_37/d3dx9_37.spec
index e1f44261610..5b7070145de 100644
--- a/dlls/d3dx9_37/d3dx9_37.spec
+++ b/dlls/d3dx9_37/d3dx9_37.spec
@@ -269,7 +269,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_38/d3dx9_38.spec b/dlls/d3dx9_38/d3dx9_38.spec
index e1f44261610..5b7070145de 100644
--- a/dlls/d3dx9_38/d3dx9_38.spec
+++ b/dlls/d3dx9_38/d3dx9_38.spec
@@ -269,7 +269,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_39/d3dx9_39.spec b/dlls/d3dx9_39/d3dx9_39.spec
index e1f44261610..5b7070145de 100644
--- a/dlls/d3dx9_39/d3dx9_39.spec
+++ b/dlls/d3dx9_39/d3dx9_39.spec
@@ -269,7 +269,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_40/d3dx9_40.spec b/dlls/d3dx9_40/d3dx9_40.spec
index e1f44261610..5b7070145de 100644
--- a/dlls/d3dx9_40/d3dx9_40.spec
+++ b/dlls/d3dx9_40/d3dx9_40.spec
@@ -269,7 +269,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_41/d3dx9_41.spec b/dlls/d3dx9_41/d3dx9_41.spec
index e1f44261610..5b7070145de 100644
--- a/dlls/d3dx9_41/d3dx9_41.spec
+++ b/dlls/d3dx9_41/d3dx9_41.spec
@@ -269,7 +269,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_42/d3dx9_42.spec b/dlls/d3dx9_42/d3dx9_42.spec
index 0851945d36b..4a418d1508a 100644
--- a/dlls/d3dx9_42/d3dx9_42.spec
+++ b/dlls/d3dx9_42/d3dx9_42.spec
@@ -262,7 +262,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/dlls/d3dx9_43/d3dx9_43.spec b/dlls/d3dx9_43/d3dx9_43.spec
index 0851945d36b..4a418d1508a 100644
--- a/dlls/d3dx9_43/d3dx9_43.spec
+++ b/dlls/d3dx9_43/d3dx9_43.spec
@@ -262,7 +262,7 @@
 @ stub D3DXSHMultiply6(ptr ptr ptr)
 @ stub D3DXSHPRTCompSplitMeshSC(ptr long long ptr long ptr long long ptr ptr long ptr ptr ptr ptr ptr)
 @ stub D3DXSHPRTCompSuperCluster(ptr ptr long long ptr ptr)
-@ stub D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
+@ stdcall D3DXSHProjectCubeMap(long ptr ptr ptr ptr)
 @ stdcall D3DXSHRotate(ptr long ptr ptr)
 @ stdcall D3DXSHRotateZ(ptr long float ptr)
 @ stdcall D3DXSHScale(ptr long ptr float)
diff --git a/include/d3dx9math.h b/include/d3dx9math.h
index bf03ca3abaa..32d894f9fed 100644
--- a/include/d3dx9math.h
+++ b/include/d3dx9math.h
@@ -396,6 +396,7 @@ HRESULT WINAPI D3DXSHEvalSphericalLight(UINT order, const D3DXVECTOR3 *dir, FLOA
 FLOAT* WINAPI D3DXSHMultiply2(FLOAT *out, const FLOAT *a, const FLOAT *b);
 FLOAT* WINAPI D3DXSHMultiply3(FLOAT *out, const FLOAT *a, const FLOAT *b);
 FLOAT* WINAPI D3DXSHMultiply4(FLOAT *out, const FLOAT *a, const FLOAT *b);
+HRESULT WINAPI D3DXSHProjectCubeMap(UINT order, IDirect3DCubeTexture9 *texture, FLOAT *red, FLOAT *green, FLOAT *blue);
 FLOAT* WINAPI D3DXSHRotate(FLOAT *out, UINT order, const D3DXMATRIX *matrix, const FLOAT *in);
 FLOAT* WINAPI D3DXSHRotateZ(FLOAT *out, UINT order, FLOAT angle, const FLOAT *in);
 FLOAT* WINAPI D3DXSHScale(FLOAT *out, UINT order, const FLOAT *a, const FLOAT scale);
-- 
2.34.1




More information about the wine-devel mailing list