Henri Verbeet : d3d8: Set the FPU control word on device creation.

Alexandre Julliard julliard at winehq.org
Wed May 26 11:49:08 CDT 2010


Module: wine
Branch: master
Commit: 7d5666e084da03fad7f97ab235039d1afd530377
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7d5666e084da03fad7f97ab235039d1afd530377

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Wed May 26 09:41:37 2010 +0200

d3d8: Set the FPU control word on device creation.

---

 dlls/d3d8/device.c       |   15 ++++++++
 dlls/d3d8/tests/device.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 101 insertions(+), 0 deletions(-)

diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 2312a6a..12ed0fb 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -2764,6 +2764,19 @@ static const IWineD3DDeviceParentVtbl d3d8_wined3d_device_parent_vtbl =
     device_parent_CreateSwapChain,
 };
 
+static void setup_fpu(void)
+{
+    WORD cw;
+
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+    __asm__ volatile ("fnstcw %0" : "=m" (cw));
+    cw = (cw & ~0xf3f) | 0x3f;
+    __asm__ volatile ("fldcw %0" : : "m" (cw));
+#else
+    FIXME("FPU setup not implemented for this platform.\n");
+#endif
+}
+
 HRESULT device_init(IDirect3DDevice8Impl *device, IWineD3D *wined3d, UINT adapter,
         D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters)
 {
@@ -2782,6 +2795,8 @@ HRESULT device_init(IDirect3DDevice8Impl *device, IWineD3D *wined3d, UINT adapte
     }
     device->handle_table.table_size = D3D8_INITIAL_HANDLE_TABLE_SIZE;
 
+    if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu();
+
     wined3d_mutex_lock();
     hr = IWineD3D_CreateDevice(wined3d, adapter, device_type, focus_window, flags, (IUnknown *)device,
             (IWineD3DDeviceParent *)&device->device_parent_vtbl, &device->WineD3DDevice);
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index cd2df9a..b46ec4e 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -1797,6 +1797,89 @@ done:
     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
 }
 
+static inline void set_fpu_cw(WORD cw)
+{
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+    __asm__ volatile ("fnclex");
+    __asm__ volatile ("fldcw %0" : : "m" (cw));
+#endif
+}
+
+static inline WORD get_fpu_cw(void)
+{
+    WORD cw = 0;
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+    __asm__ volatile ("fnstcw %0" : "=m" (cw));
+#endif
+    return cw;
+}
+
+static void test_fpu_setup(void)
+{
+    D3DPRESENT_PARAMETERS present_parameters;
+    IDirect3DDevice8 *device;
+    D3DDISPLAYMODE d3ddm;
+    HWND window = NULL;
+    IDirect3D8 *d3d8;
+    HRESULT hr;
+    WORD cw;
+
+    d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
+    ok(!!d3d8, "Failed to create a d3d8 object.\n");
+    if (!d3d8) return;
+
+    window = CreateWindowA("static", "d3d8_test", WS_CAPTION, 0, 0, 640, 480, 0, 0, 0, 0);
+    ok(!!window, "Failed to create a window.\n");
+    if (!window) goto done;
+
+    hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
+    ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
+
+    memset(&present_parameters, 0, sizeof(present_parameters));
+    present_parameters.Windowed = TRUE;
+    present_parameters.hDeviceWindow = window;
+    present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    present_parameters.BackBufferFormat = d3ddm.Format;
+
+    set_fpu_cw(0xf60);
+    cw = get_fpu_cw();
+    ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
+
+    hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
+            D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
+    if (FAILED(hr))
+    {
+        skip("Failed to create a device, hr %#x.\n", hr);
+        set_fpu_cw(0x37f);
+        goto done;
+    }
+
+    cw = get_fpu_cw();
+    ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
+
+    IDirect3DDevice8_Release(device);
+
+    cw = get_fpu_cw();
+    ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
+    set_fpu_cw(0xf60);
+    cw = get_fpu_cw();
+    ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
+
+    hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
+            D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
+    ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
+
+    cw = get_fpu_cw();
+    ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
+    set_fpu_cw(0x37f);
+
+    IDirect3DDevice8_Release(device);
+
+done:
+    if (window) DestroyWindow(window);
+    if (d3d8) IDirect3D8_Release(d3d8);
+}
+
 START_TEST(device)
 {
     HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
@@ -1819,6 +1902,9 @@ START_TEST(device)
         }
         IDirect3D8_Release(d3d8);
 
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+        test_fpu_setup();
+#endif
         test_display_modes();
         test_shader_versions();
         test_swapchain();




More information about the wine-cvs mailing list