wined3d: Implement more GLSL instructions and a little cleanup.
[wine] / dlls / d3d8 / tests / device.c
1 /*
2  * Copyright (C) 2006 Vitaliy Margolen
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #define COBJMACROS
20 #include <d3d8.h>
21 #include <dxerr8.h>
22 #include "wine/test.h"
23
24 static IDirect3D8 *(WINAPI *pDirect3DCreate8)(UINT);
25
26 static int get_refcount(IUnknown *object)
27 {
28     IUnknown_AddRef( object );
29     return IUnknown_Release( object );
30 }
31
32 #define CHECK_CALL(r,c,d,rc) \
33     if (SUCCEEDED(r)) {\
34         int tmp1 = get_refcount( (IUnknown *)d ); \
35         ok(rc == tmp1, "Invalid refcount. Expected %d got %d\n", rc, tmp1); \
36     } else {\
37         trace("%s failed: %s\n", c, DXGetErrorString8(r)); \
38     }
39
40 static void test_swapchain(void)
41 {
42     HRESULT                      hr;
43     HWND                         hwnd               = NULL;
44     IDirect3D8                  *pD3d               = NULL;
45     IDirect3DDevice8            *pDevice            = NULL;
46     IDirect3DSwapChain8         *swapchain1         = NULL;
47     IDirect3DSwapChain8         *swapchain2         = NULL;
48     IDirect3DSwapChain8         *swapchain3         = NULL;
49     IDirect3DSurface8           *backbuffer         = NULL;
50     D3DPRESENT_PARAMETERS        d3dpp;
51     D3DDISPLAYMODE               d3ddm;
52
53     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
54     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
55     hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
56     ok(hwnd != NULL, "Failed to create window\n");
57     if (!pD3d || !hwnd) goto cleanup;
58
59     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
60     ZeroMemory( &d3dpp, sizeof(d3dpp) );
61     d3dpp.Windowed         = TRUE;
62     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
63     d3dpp.BackBufferFormat = d3ddm.Format;
64     d3dpp.BackBufferCount  = 0;
65
66     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
67                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
68     ok(SUCCEEDED(hr), "Failed to create IDirect3D8Device (%s)\n", DXGetErrorString8(hr));
69     if (FAILED(hr)) goto cleanup;
70
71     /* Check if the back buffer count was modified */
72     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
73
74     /* Create a bunch of swapchains */
75     d3dpp.BackBufferCount = 0;
76     hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain1);
77     ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString8(hr));
78     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
79
80     d3dpp.BackBufferCount  = 1;
81     hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
82     ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString8(hr));
83
84     d3dpp.BackBufferCount  = 2;
85     hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
86     ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString8(hr));
87     if(SUCCEEDED(hr)) {
88         /* Swapchain 3, created with backbuffercount 2 */
89         backbuffer = (void *) 0xdeadbeef;
90         hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
91         ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%s)\n", DXGetErrorString8(hr));
92         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
93         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
94
95         backbuffer = (void *) 0xdeadbeef;
96         hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
97         ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%s)\n", DXGetErrorString8(hr));
98         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
99         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
100
101         backbuffer = (void *) 0xdeadbeef;
102         hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
103         ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %s\n", DXGetErrorString8(hr));
104         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
105         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
106
107         backbuffer = (void *) 0xdeadbeef;
108         hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
109         ok(FAILED(hr), "Failed to get the back buffer (%s)\n", DXGetErrorString8(hr));
110         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
111         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
112     }
113
114     /* Check the back buffers of the swapchains */
115     /* Swapchain 1, created with backbuffercount 0 */
116     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
117     ok(SUCCEEDED(hr), "Failed to get the back buffer (%s)\n", DXGetErrorString8(hr));
118     ok(backbuffer != NULL, "The back buffer is NULL (%s)\n", DXGetErrorString8(hr));
119     if(backbuffer) IDirect3DSurface8_Release(backbuffer);
120
121     backbuffer = (void *) 0xdeadbeef;
122     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
123     ok(FAILED(hr), "Failed to get the back buffer (%s)\n", DXGetErrorString8(hr));
124     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
125     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
126
127     /* Swapchain 2 - created with backbuffercount 1 */
128     backbuffer = (void *) 0xdeadbeef;
129     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
130     ok(SUCCEEDED(hr), "Failed to get the back buffer (%s)\n", DXGetErrorString8(hr));
131     ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
132     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
133
134     backbuffer = (void *) 0xdeadbeef;
135     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
136     ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %s\n", DXGetErrorString8(hr));
137     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
138     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
139
140     backbuffer = (void *) 0xdeadbeef;
141     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
142     ok(FAILED(hr), "Failed to get the back buffer (%s)\n", DXGetErrorString8(hr));
143     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
144     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
145
146     cleanup:
147     if(swapchain1) IDirect3DSwapChain8_Release(swapchain1);
148     if(swapchain2) IDirect3DSwapChain8_Release(swapchain2);
149     if(swapchain3) IDirect3DSwapChain8_Release(swapchain3);
150     if(pDevice) IDirect3DDevice8_Release(pDevice);
151     if(pD3d) IDirect3DDevice8_Release(pD3d);
152     DestroyWindow( hwnd );
153 }
154
155 static void test_refcount(void)
156 {
157     HRESULT                      hr;
158     HWND                         hwnd               = NULL;
159     IDirect3D8                  *pD3d               = NULL;
160     IDirect3DDevice8            *pDevice            = NULL;
161     IDirect3DVertexBuffer8      *pVertexBuffer      = NULL;
162     IDirect3DIndexBuffer8       *pIndexBuffer       = NULL;
163     DWORD dVertexShader         = -1;
164     DWORD dPixelShader          = -1;
165     IDirect3DCubeTexture8       *pCubeTexture       = NULL;
166     IDirect3DTexture8           *pTexture           = NULL;
167     IDirect3DVolumeTexture8     *pVolumeTexture     = NULL;
168     IDirect3DSurface8           *pStencilSurface    = NULL;
169     IDirect3DSurface8           *pImageSurface = NULL;
170     IDirect3DSurface8           *pRenderTarget      = NULL;
171     IDirect3DSurface8           *pTextureLevel      = NULL;
172     DWORD dStateBlock           = -1;
173     IDirect3DSwapChain8         *pSwapChain         = NULL;
174
175     D3DPRESENT_PARAMETERS        d3dpp;
176     D3DDISPLAYMODE               d3ddm;
177     int                          refcount, tmp;
178
179     DWORD decl[] =
180     {
181         D3DVSD_STREAM(0),
182         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
183         D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR), /* D3DVSDE_DIFFUSE, Register v5 */
184         D3DVSD_END()
185     };
186     static DWORD simple_vs[] = {0xFFFE0101,             /* vs_1_1               */
187         0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0   */
188         0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1   */
189         0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2   */
190         0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3   */
191         0x0000FFFF};                                    /* END                  */
192     static DWORD simple_ps[] = {0xFFFF0101,                                     /* ps_1_1                       */
193         0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0  */
194         0x00000042, 0xB00F0000,                                                 /* tex t0                       */
195         0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000,                         /* dp3 r0, c1, c0               */
196         0x00000005, 0x800F0000, 0x90E40000, 0x80E40000,                         /* mul r0, v0, r0               */
197         0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000,                         /* mul r0, t0, r0               */
198         0x0000FFFF};                                                            /* END                          */
199
200
201     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
202     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
203     hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
204     ok(hwnd != NULL, "Failed to create window\n");
205     if (!pD3d || !hwnd) goto cleanup;
206
207     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
208     ZeroMemory( &d3dpp, sizeof(d3dpp) );
209     d3dpp.Windowed         = TRUE;
210     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
211     d3dpp.BackBufferFormat = d3ddm.Format;
212
213     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
214                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
215     ok(SUCCEEDED(hr), "Failed to create IDirect3D8Device (%s)\n", DXGetErrorString8(hr));
216     if (FAILED(hr)) goto cleanup;
217
218
219     /* Buffers */
220     refcount = get_refcount( (IUnknown *)pDevice );
221     hr = IDirect3DDevice8_CreateIndexBuffer( pDevice, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer );
222     CHECK_CALL( hr, "CreateIndexBuffer", pDevice, refcount+1 );
223     refcount = get_refcount( (IUnknown *)pDevice );
224     hr = IDirect3DDevice8_CreateVertexBuffer( pDevice, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer );
225     CHECK_CALL( hr, "CreateVertexBuffer", pDevice, refcount+1 );
226     /* Shaders */
227     refcount = get_refcount( (IUnknown *)pDevice );
228     hr = IDirect3DDevice8_CreateVertexShader( pDevice, decl, simple_vs, &dVertexShader, 0 );
229     CHECK_CALL( hr, "CreateVertexShader", pDevice, refcount );
230     refcount = get_refcount( (IUnknown *)pDevice );
231     hr = IDirect3DDevice8_CreatePixelShader( pDevice, simple_ps, &dPixelShader );
232     CHECK_CALL( hr, "CreatePixelShader", pDevice, refcount );
233     /* Textures */
234     refcount = get_refcount( (IUnknown *)pDevice );
235     hr = IDirect3DDevice8_CreateTexture( pDevice, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture );
236     CHECK_CALL( hr, "CreateTexture", pDevice, refcount+1 );
237     if (pTexture)
238     {
239         tmp = get_refcount( (IUnknown *)pTexture );
240         /* This should not increment device refcount */
241         hr = IDirect3DTexture8_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
242         CHECK_CALL( hr, "GetSurfaceLevel", pDevice, refcount+1 );
243         /* But should increment texture's refcount */
244         CHECK_CALL( hr, "GetSurfaceLevel", pTexture, tmp+1 );
245     }
246     refcount = get_refcount( (IUnknown *)pDevice );
247     hr = IDirect3DDevice8_CreateCubeTexture( pDevice, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture );
248     CHECK_CALL( hr, "CreateCubeTexture", pDevice, refcount+1 );
249     refcount = get_refcount( (IUnknown *)pDevice );
250     hr = IDirect3DDevice8_CreateVolumeTexture( pDevice, 32, 32, 2, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture );
251     CHECK_CALL( hr, "CreateVolumeTexture", pDevice, refcount+1 );
252     /* Surfaces */
253     refcount = get_refcount( (IUnknown *)pDevice );
254     hr = IDirect3DDevice8_CreateDepthStencilSurface( pDevice, 32, 32, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &pStencilSurface );
255     todo_wine {CHECK_CALL( hr, "CreateDepthStencilSurface", pDevice, refcount+1 );}
256     refcount = get_refcount( (IUnknown *)pDevice );
257     hr = IDirect3DDevice8_CreateImageSurface( pDevice, 32, 32, D3DFMT_X8R8G8B8, &pImageSurface );
258     todo_wine {CHECK_CALL( hr, "CreateImageSurface", pDevice, refcount+1 );}
259     refcount = get_refcount( (IUnknown *)pDevice );
260     hr = IDirect3DDevice8_CreateRenderTarget( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, TRUE, &pRenderTarget );
261     todo_wine {CHECK_CALL( hr, "CreateRenderTarget", pDevice, refcount+1 );}
262     /* Misc */
263     refcount = get_refcount( (IUnknown *)pDevice );
264     hr = IDirect3DDevice8_CreateStateBlock( pDevice, D3DSBT_ALL, &dStateBlock );
265     CHECK_CALL( hr, "CreateStateBlock", pDevice, refcount );
266     refcount = get_refcount( (IUnknown *)pDevice );
267     hr = IDirect3DDevice8_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain );
268     CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, refcount+1 );
269
270 cleanup:
271     if (pDevice)              IUnknown_Release( pDevice );
272
273     /* Buffers */
274     if (pVertexBuffer)        IUnknown_Release( pVertexBuffer );
275     if (pIndexBuffer)         IUnknown_Release( pIndexBuffer );
276     /* Shaders */
277     if (dVertexShader != -1)  IDirect3DDevice8_DeleteVertexShader( pDevice, dVertexShader );
278     if (dPixelShader != -1)   IDirect3DDevice8_DeletePixelShader( pDevice, dPixelShader );
279     /* Textures */
280     if (pTexture)             IUnknown_Release( pTexture );
281     if (pTextureLevel)        IUnknown_Release( pTextureLevel );
282     if (pCubeTexture)         IUnknown_Release( pCubeTexture );
283     if (pVolumeTexture)       IUnknown_Release( pVolumeTexture );
284     /* Surfaces */
285     if (pStencilSurface)      IUnknown_Release( pStencilSurface );
286     if (pImageSurface)        IUnknown_Release( pImageSurface );
287     if (pRenderTarget)        IUnknown_Release( pRenderTarget );
288     /* Misc */
289     if (dStateBlock != -1)    IDirect3DDevice8_DeleteStateBlock( pDevice, dStateBlock );
290     /* Avoid crash for now.
291     if (pSwapChain)           IUnknown_Release( pSwapChain );
292     */
293
294     if (pD3d)                 IUnknown_Release( pD3d );
295
296     DestroyWindow( hwnd );
297 }
298
299 START_TEST(device)
300 {
301     HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
302
303     pDirect3DCreate8 = (void *)GetProcAddress( d3d8_handle, "Direct3DCreate8" );
304     if (pDirect3DCreate8)
305     {
306         test_refcount();
307         test_swapchain();
308     }
309 }