opengl32: Avoid generating a wrapper for internal functions when we can call the...
[wine] / dlls / d3d9 / tests / device.c
1 /*
2  * Copyright (C) 2006 Vitaliy Margolen
3  * Copyright (C) 2006 Stefan Dösinger(For CodeWeavers)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #define COBJMACROS
21 #include <d3d9.h>
22 #include <dxerr9.h>
23 #include "wine/test.h"
24
25 static IDirect3D9 *(WINAPI *pDirect3DCreate9)(UINT);
26
27 static int get_refcount(IUnknown *object)
28 {
29     IUnknown_AddRef( object );
30     return IUnknown_Release( object );
31 }
32
33 #define CHECK_CALL(r,c,d,rc) \
34     if (SUCCEEDED(r)) {\
35         int tmp1 = get_refcount( (IUnknown *)d ); \
36         int rc_new = rc; \
37         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
38     } else {\
39         trace("%s failed: %s\n", c, DXGetErrorString9(r)); \
40     }
41
42 #define CHECK_RELEASE(obj,d,rc) \
43     if (obj) { \
44         int tmp1, rc_new = rc; \
45         IUnknown_Release( obj ); \
46         tmp1 = get_refcount( (IUnknown *)d ); \
47         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
48     }
49
50 #define CHECK_REFCOUNT(obj,rc) \
51     { \
52         int rc_new = rc; \
53         int count = get_refcount( (IUnknown *)obj ); \
54         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
55     }
56
57 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
58     { \
59         int rc_new = rc; \
60         int count = IUnknown_Release( (IUnknown *)obj ); \
61         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
62     }
63
64 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
65     { \
66         int rc_new = rc; \
67         int count = IUnknown_AddRef( (IUnknown *)obj ); \
68         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
69     }
70
71 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
72     { \
73         void *container_ptr = (void *)0x1337c0d3; \
74         hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
75         ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
76             "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
77         if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
78     }
79
80 static void check_mipmap_levels(
81     IDirect3DDevice9* device, 
82     int width, int height, int count) 
83 {
84
85     IDirect3DBaseTexture9* texture = NULL;
86     HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0, 
87         D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
88        
89     if (SUCCEEDED(hr)) {
90         DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
91         ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
92     } else 
93         trace("CreateTexture failed: %s\n", DXGetErrorString9(hr));
94
95     if (texture) IUnknown_Release( texture );
96 }
97
98 static void test_mipmap_levels(void)
99 {
100
101     HRESULT               hr;
102     HWND                  hwnd = NULL;
103
104     IDirect3D9            *pD3d = NULL;
105     IDirect3DDevice9      *pDevice = NULL;
106     D3DPRESENT_PARAMETERS d3dpp;
107     D3DDISPLAYMODE        d3ddm;
108  
109     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
110     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
111     hwnd = CreateWindow( "static", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
112     ok(hwnd != NULL, "Failed to create window\n");
113     if (!pD3d || !hwnd) goto cleanup;
114
115     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
116     ZeroMemory( &d3dpp, sizeof(d3dpp) );
117     d3dpp.Windowed         = TRUE;
118     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
119     d3dpp.BackBufferFormat = d3ddm.Format;
120
121     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
122                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
123     ok(SUCCEEDED(hr), "Failed to create IDirect3D9Device (%s)\n", DXGetErrorString9(hr));
124     if (FAILED(hr)) goto cleanup;
125
126     check_mipmap_levels(pDevice, 32, 32, 6);
127     check_mipmap_levels(pDevice, 256, 1, 9);
128     check_mipmap_levels(pDevice, 1, 256, 9);
129     check_mipmap_levels(pDevice, 1, 1, 1);
130
131     cleanup:
132     if (pD3d)     IUnknown_Release( pD3d );
133     if (pDevice)  IUnknown_Release( pDevice );
134     DestroyWindow( hwnd );
135 }
136
137 static void test_swapchain(void)
138 {
139     HRESULT                      hr;
140     HWND                         hwnd               = NULL;
141     IDirect3D9                  *pD3d               = NULL;
142     IDirect3DDevice9            *pDevice            = NULL;
143     IDirect3DSwapChain9         *swapchain0         = NULL;
144     IDirect3DSwapChain9         *swapchain1         = NULL;
145     IDirect3DSwapChain9         *swapchain2         = NULL;
146     IDirect3DSwapChain9         *swapchain3         = NULL;
147     IDirect3DSwapChain9         *swapchainX         = NULL;
148     IDirect3DSurface9           *backbuffer         = NULL;
149     D3DPRESENT_PARAMETERS        d3dpp;
150     D3DDISPLAYMODE               d3ddm;
151
152     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
153     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
154     hwnd = CreateWindow( "static", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
155     ok(hwnd != NULL, "Failed to create window\n");
156     if (!pD3d || !hwnd) goto cleanup;
157
158     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
159     ZeroMemory( &d3dpp, sizeof(d3dpp) );
160     d3dpp.Windowed         = TRUE;
161     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
162     d3dpp.BackBufferFormat = d3ddm.Format;
163     d3dpp.BackBufferCount  = 0;
164
165     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
166                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
167     ok(SUCCEEDED(hr), "Failed to create IDirect3D9Device (%s)\n", DXGetErrorString9(hr));
168     if (FAILED(hr)) goto cleanup;
169
170     /* Check if the back buffer count was modified */
171     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
172
173     /* Get the implicit swapchain */
174     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &swapchain0);
175     ok(SUCCEEDED(hr), "Failed to get the impicit swapchain (%s)\n", DXGetErrorString9(hr));
176     if(swapchain0) IDirect3DSwapChain9_Release(swapchain0);
177
178     /* Check if there is a back buffer */
179     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
180     ok(SUCCEEDED(hr), "Failed to get the back buffer (%s)\n", DXGetErrorString9(hr));
181     ok(backbuffer != NULL, "The back buffer is NULL\n");
182     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
183
184     /* Try to get a nonexistant swapchain */
185     hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
186     ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%s)\n", DXGetErrorString9(hr));
187     ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
188     if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
189
190     /* Create a bunch of swapchains */
191     d3dpp.BackBufferCount = 0;
192     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain1);
193     ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString9(hr));
194     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
195
196     d3dpp.BackBufferCount  = 1;
197     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
198     ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString9(hr));
199
200     d3dpp.BackBufferCount  = 2;
201     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
202     ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString9(hr));
203     if(SUCCEEDED(hr)) {
204         /* Swapchain 3, created with backbuffercount 2 */
205         backbuffer = (void *) 0xdeadbeef;
206         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
207         ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%s)\n", DXGetErrorString9(hr));
208         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
209         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
210
211         backbuffer = (void *) 0xdeadbeef;
212         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
213         ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%s)\n", DXGetErrorString9(hr));
214         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
215         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
216
217         backbuffer = (void *) 0xdeadbeef;
218         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
219         ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %s\n", DXGetErrorString9(hr));
220         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
221         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
222
223         backbuffer = (void *) 0xdeadbeef;
224         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
225         ok(FAILED(hr), "Failed to get the back buffer (%s)\n", DXGetErrorString9(hr));
226         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
227         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
228     }
229
230     /* Check the back buffers of the swapchains */
231     /* Swapchain 1, created with backbuffercount 0 */
232     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
233     ok(SUCCEEDED(hr), "Failed to get the back buffer (%s)\n", DXGetErrorString9(hr));
234     ok(backbuffer != NULL, "The back buffer is NULL (%s)\n", DXGetErrorString9(hr));
235     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
236
237     backbuffer = (void *) 0xdeadbeef;
238     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
239     ok(FAILED(hr), "Failed to get the back buffer (%s)\n", DXGetErrorString9(hr));
240     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
241     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
242
243     /* Swapchain 2 - created with backbuffercount 1 */
244     backbuffer = (void *) 0xdeadbeef;
245     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
246     ok(SUCCEEDED(hr), "Failed to get the back buffer (%s)\n", DXGetErrorString9(hr));
247     ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
248     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
249
250     backbuffer = (void *) 0xdeadbeef;
251     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
252     ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %s\n", DXGetErrorString9(hr));
253     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
254     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
255
256     backbuffer = (void *) 0xdeadbeef;
257     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
258     ok(FAILED(hr), "Failed to get the back buffer (%s)\n", DXGetErrorString9(hr));
259     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
260     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
261
262     /* Try getSwapChain on a manually created swapchain
263      * it should fail, apparently GetSwapChain only returns implicit swapchains
264      */
265     swapchainX = (void *) 0xdeadbeef;
266     hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
267     ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%s)\n", DXGetErrorString9(hr));
268     ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
269     if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
270
271     cleanup:
272     if(swapchain1) IDirect3DSwapChain9_Release(swapchain1);
273     if(swapchain2) IDirect3DSwapChain9_Release(swapchain2);
274     if(swapchain3) IDirect3DSwapChain9_Release(swapchain3);
275     if(pDevice) IDirect3DDevice9_Release(pDevice);
276     if(pD3d) IDirect3DDevice9_Release(pD3d);
277     DestroyWindow( hwnd );
278 }
279
280 static void test_refcount(void)
281 {
282     HRESULT                      hr;
283     HWND                         hwnd               = NULL;
284     IDirect3D9                  *pD3d               = NULL;
285     IDirect3DDevice9            *pDevice            = NULL;
286     IDirect3DVertexBuffer9      *pVertexBuffer      = NULL;
287     IDirect3DIndexBuffer9       *pIndexBuffer       = NULL;
288     IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
289     IDirect3DVertexShader9      *pVertexShader      = NULL;
290     IDirect3DPixelShader9       *pPixelShader       = NULL;
291     IDirect3DCubeTexture9       *pCubeTexture       = NULL;
292     IDirect3DTexture9           *pTexture           = NULL;
293     IDirect3DVolumeTexture9     *pVolumeTexture     = NULL;
294     IDirect3DVolume9            *pVolumeLevel       = NULL;
295     IDirect3DSurface9           *pStencilSurface    = NULL;
296     IDirect3DSurface9           *pOffscreenSurface  = NULL;
297     IDirect3DSurface9           *pRenderTarget      = NULL;
298     IDirect3DSurface9           *pRenderTarget2     = NULL;
299     IDirect3DSurface9           *pRenderTarget3     = NULL;
300     IDirect3DSurface9           *pTextureLevel      = NULL;
301     IDirect3DSurface9           *pBackBuffer        = NULL;
302     IDirect3DStateBlock9        *pStateBlock        = NULL;
303     IDirect3DStateBlock9        *pStateBlock1       = NULL;
304     IDirect3DSwapChain9         *pSwapChain         = NULL;
305     IDirect3DQuery9             *pQuery             = NULL;
306     D3DPRESENT_PARAMETERS        d3dpp;
307     D3DDISPLAYMODE               d3ddm;
308     int                          refcount = 0, tmp;
309
310     D3DVERTEXELEMENT9 decl[] =
311     {
312         D3DDECL_END()
313     };
314     static DWORD simple_vs[] = {0xFFFE0101,             /* vs_1_1               */
315         0x0000001F, 0x80000000, 0x900F0000,             /* dcl_position0 v0     */
316         0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0   */
317         0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1   */
318         0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2   */
319         0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3   */
320         0x0000FFFF};                                    /* END                  */
321     static DWORD simple_ps[] = {0xFFFF0101,                                     /* ps_1_1                       */
322         0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0  */
323         0x00000042, 0xB00F0000,                                                 /* tex t0                       */
324         0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000,                         /* dp3 r0, c1, c0               */
325         0x00000005, 0x800F0000, 0x90E40000, 0x80E40000,                         /* mul r0, v0, r0               */
326         0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000,                         /* mul r0, t0, r0               */
327         0x0000FFFF};                                                            /* END                          */
328
329
330     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
331     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
332     hwnd = CreateWindow( "static", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
333     ok(hwnd != NULL, "Failed to create window\n");
334     if (!pD3d || !hwnd) goto cleanup;
335
336     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
337     ZeroMemory( &d3dpp, sizeof(d3dpp) );
338     d3dpp.Windowed         = TRUE;
339     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
340     d3dpp.BackBufferFormat = d3ddm.Format;
341     d3dpp.EnableAutoDepthStencil = TRUE;
342     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
343
344     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
345                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
346     ok(SUCCEEDED(hr), "Failed to create IDirect3D9Device (%s)\n", DXGetErrorString9(hr));
347     if (FAILED(hr)) goto cleanup;
348
349     refcount = get_refcount( (IUnknown *)pDevice );
350     ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
351
352     /**
353      * Check refcount of implicit surfaces and implicit swapchain. Findings:
354      *   - the container is the device OR swapchain
355      *   - they hold a refernce to the device
356      *   - they are created with a refcount of 0 (Get/Release returns orignial refcount)
357      *   - they are not freed if refcount reaches 0.
358      *   - the refcount is not forwarded to the container.
359      */
360     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapChain);
361     todo_wine CHECK_CALL( hr, "GetSwapChain", pDevice, ++refcount);
362     if (pSwapChain)
363     {
364         todo_wine CHECK_REFCOUNT( pSwapChain, 1);
365
366         hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
367         todo_wine CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
368         todo_wine CHECK_REFCOUNT( pSwapChain, 1);
369         if(pRenderTarget)
370         {
371             CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
372             todo_wine CHECK_REFCOUNT( pRenderTarget, 1);
373
374             todo_wine CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
375             todo_wine CHECK_REFCOUNT(pDevice, refcount);
376             todo_wine CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
377             todo_wine CHECK_REFCOUNT(pDevice, refcount);
378
379             hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
380             todo_wine CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
381             todo_wine CHECK_REFCOUNT( pRenderTarget, 2);
382             todo_wine CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
383             todo_wine CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
384             todo_wine CHECK_REFCOUNT( pDevice, --refcount);
385
386             /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
387             todo_wine CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
388             todo_wine CHECK_REFCOUNT(pDevice, ++refcount);
389             todo_wine CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
390             todo_wine CHECK_REFCOUNT(pDevice, --refcount);
391         }
392
393         /* Render target and back buffer are identical. */
394         hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, 0, &pBackBuffer);
395         todo_wine CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
396         if(pBackBuffer)
397         {
398             todo_wine CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
399             ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
400             pRenderTarget, pBackBuffer);
401             pBackBuffer = NULL;
402         }
403         todo_wine CHECK_REFCOUNT( pDevice, --refcount);
404
405         hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pStencilSurface);
406         todo_wine CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
407         todo_wine CHECK_REFCOUNT( pSwapChain, 1);
408         if(pStencilSurface)
409         {
410             CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice9, pDevice);
411             todo_wine CHECK_REFCOUNT( pStencilSurface, 1);
412
413             todo_wine CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
414             todo_wine CHECK_REFCOUNT(pDevice, refcount);
415             todo_wine CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
416             todo_wine CHECK_REFCOUNT(pDevice, refcount);
417
418             todo_wine CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
419             todo_wine CHECK_REFCOUNT( pDevice, --refcount);
420
421             /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
422             todo_wine CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
423             todo_wine CHECK_REFCOUNT(pDevice, ++refcount);
424             todo_wine CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
425             todo_wine CHECK_REFCOUNT(pDevice, --refcount);
426             pStencilSurface = NULL;
427         }
428
429         todo_wine CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
430         CHECK_REFCOUNT( pDevice, --refcount);
431
432         /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
433         todo_wine CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
434         todo_wine CHECK_REFCOUNT(pDevice, ++refcount);
435         todo_wine CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
436         CHECK_REFCOUNT(pDevice, --refcount);
437         pSwapChain = NULL;
438     }
439
440     /* Buffers */
441     hr = IDirect3DDevice9_CreateIndexBuffer( pDevice, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL );
442     CHECK_CALL( hr, "CreateIndexBuffer", pDevice, ++refcount );
443     if(pIndexBuffer)
444     {
445         tmp = get_refcount( (IUnknown *)pIndexBuffer );
446
447         hr = IDirect3DDevice9_SetIndices(pDevice, pIndexBuffer);
448         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
449         hr = IDirect3DDevice9_SetIndices(pDevice, NULL);
450         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
451     }
452
453     hr = IDirect3DDevice9_CreateVertexBuffer( pDevice, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
454     CHECK_CALL( hr, "CreateVertexBuffer", pDevice, ++refcount );
455     if(pVertexBuffer)
456     {
457         tmp = get_refcount( (IUnknown *)pVertexBuffer );
458
459         hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, pVertexBuffer, 0, 3 * sizeof(float));
460         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
461         hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, NULL, 0, 0);
462         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
463     }
464     /* Shaders */
465     hr = IDirect3DDevice9_CreateVertexDeclaration( pDevice, decl, &pVertexDeclaration );
466     CHECK_CALL( hr, "CreateVertexDeclaration", pDevice, ++refcount );
467     hr = IDirect3DDevice9_CreateVertexShader( pDevice, simple_vs, &pVertexShader );
468     CHECK_CALL( hr, "CreateVertexShader", pDevice, ++refcount );
469     hr = IDirect3DDevice9_CreatePixelShader( pDevice, simple_ps, &pPixelShader );
470     CHECK_CALL( hr, "CreatePixelShader", pDevice, ++refcount );
471     /* Textures */
472     hr = IDirect3DDevice9_CreateTexture( pDevice, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL );
473     CHECK_CALL( hr, "CreateTexture", pDevice, ++refcount );
474     if (pTexture)
475     {
476         tmp = get_refcount( (IUnknown *)pTexture );
477
478         /* SetTexture should not increase refcounts */
479         hr = IDirect3DDevice9_SetTexture(pDevice, 0, (IDirect3DBaseTexture9 *) pTexture);
480         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
481         hr = IDirect3DDevice9_SetTexture(pDevice, 0, NULL);
482         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
483
484         /* This should not increment device refcount */
485         hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
486         CHECK_CALL( hr, "GetSurfaceLevel", pDevice, refcount );
487         /* But should increment texture's refcount */
488         CHECK_REFCOUNT( pTexture, tmp+1 );
489         /* Because the texture and surface refcount are identical */
490         if (pTextureLevel)
491         {
492             CHECK_REFCOUNT        ( pTextureLevel, tmp+1 );
493             CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
494             CHECK_REFCOUNT        ( pTexture     , tmp+2 );
495             CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
496             CHECK_REFCOUNT        ( pTexture     , tmp+1 );
497             CHECK_RELEASE_REFCOUNT( pTexture     , tmp   );
498             CHECK_REFCOUNT        ( pTextureLevel, tmp   );
499         }
500     }
501     hr = IDirect3DDevice9_CreateCubeTexture( pDevice, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL );
502     CHECK_CALL( hr, "CreateCubeTexture", pDevice, ++refcount );
503     hr = IDirect3DDevice9_CreateVolumeTexture( pDevice, 32, 32, 2, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL );
504     CHECK_CALL( hr, "CreateVolumeTexture", pDevice, ++refcount );
505     if (pVolumeTexture)
506     {
507         tmp = get_refcount( (IUnknown *)pVolumeTexture );
508
509         /* This should not increment device refcount */
510         hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
511         CHECK_CALL( hr, "GetVolumeLevel", pDevice, refcount );
512         /* But should increment volume texture's refcount */
513         CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
514         /* Because the volume texture and volume refcount are identical */
515         if (pVolumeLevel)
516         {
517             CHECK_REFCOUNT        ( pVolumeLevel  , tmp+1 );
518             CHECK_ADDREF_REFCOUNT ( pVolumeLevel  , tmp+2 );
519             CHECK_REFCOUNT        ( pVolumeTexture, tmp+2 );
520             CHECK_RELEASE_REFCOUNT( pVolumeLevel  , tmp+1 );
521             CHECK_REFCOUNT        ( pVolumeTexture, tmp+1 );
522             CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp   );
523             CHECK_REFCOUNT        ( pVolumeLevel  , tmp   );
524         }
525     }
526     /* Surfaces */
527     hr = IDirect3DDevice9_CreateDepthStencilSurface( pDevice, 32, 32, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL );
528     CHECK_CALL( hr, "CreateDepthStencilSurface", pDevice, ++refcount );
529     hr = IDirect3DDevice9_CreateOffscreenPlainSurface( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL );
530     CHECK_CALL( hr, "CreateOffscreenPlainSurface", pDevice, ++refcount );
531     hr = IDirect3DDevice9_CreateRenderTarget( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL );
532     CHECK_CALL( hr, "CreateRenderTarget", pDevice, ++refcount );
533     /* Misc */
534     hr = IDirect3DDevice9_CreateStateBlock( pDevice, D3DSBT_ALL, &pStateBlock );
535     CHECK_CALL( hr, "CreateStateBlock", pDevice, ++refcount );
536     hr = IDirect3DDevice9_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain );
537     CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, ++refcount );
538     if(pSwapChain)
539     {
540         /* check implicit back buffer */
541         hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
542         todo_wine CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
543         todo_wine CHECK_REFCOUNT( pSwapChain, 1);
544         if(pBackBuffer)
545         {
546             CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
547             todo_wine CHECK_REFCOUNT( pBackBuffer, 1);
548             todo_wine CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
549             CHECK_REFCOUNT( pDevice, --refcount);
550
551             /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
552             todo_wine CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
553             todo_wine CHECK_REFCOUNT(pDevice, ++refcount);
554             todo_wine CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
555             CHECK_REFCOUNT(pDevice, --refcount);
556             pBackBuffer = NULL;
557         }
558         CHECK_REFCOUNT( pSwapChain, 1);
559     }
560     hr = IDirect3DDevice9_CreateQuery( pDevice, D3DQUERYTYPE_EVENT, &pQuery );
561     CHECK_CALL( hr, "CreateQuery", pDevice, ++refcount );
562
563     hr = IDirect3DDevice9_BeginStateBlock( pDevice );
564     CHECK_CALL( hr, "BeginStateBlock", pDevice, refcount );
565     hr = IDirect3DDevice9_EndStateBlock( pDevice, &pStateBlock1 );
566     CHECK_CALL( hr, "EndStateBlock", pDevice, ++refcount );
567
568     /* The implicit render target is not freed if refcount reaches 0.
569      * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
570     hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget2);
571     todo_wine CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
572     if(pRenderTarget2)
573     {
574         todo_wine CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
575         ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
576            pRenderTarget, pRenderTarget2);
577         CHECK_REFCOUNT( pDevice, --refcount);
578         pRenderTarget2 = NULL;
579     }
580     pRenderTarget = NULL;
581
582 cleanup:
583     CHECK_RELEASE(pDevice,              pDevice, --refcount);
584
585     /* Buffers */
586     CHECK_RELEASE(pVertexBuffer,        pDevice, --refcount);
587     CHECK_RELEASE(pIndexBuffer,         pDevice, --refcount);
588     /* Shaders */
589     CHECK_RELEASE(pVertexDeclaration,   pDevice, --refcount);
590     CHECK_RELEASE(pVertexShader,        pDevice, --refcount);
591     CHECK_RELEASE(pPixelShader,         pDevice, --refcount);
592     /* Textures */
593     CHECK_RELEASE(pTextureLevel,        pDevice, --refcount);
594     CHECK_RELEASE(pCubeTexture,         pDevice, --refcount);
595     CHECK_RELEASE(pVolumeTexture,       pDevice, --refcount);
596     /* Surfaces */
597     CHECK_RELEASE(pStencilSurface,      pDevice, --refcount);
598     CHECK_RELEASE(pOffscreenSurface,    pDevice, --refcount);
599     CHECK_RELEASE(pRenderTarget3,       pDevice, --refcount);
600     /* Misc */
601     CHECK_RELEASE(pStateBlock,          pDevice, --refcount);
602     CHECK_RELEASE(pSwapChain,           pDevice, --refcount);
603     CHECK_RELEASE(pQuery,               pDevice, --refcount);
604     /* This will destroy device - cannot check the refcount here */
605     if (pStateBlock1)         CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
606
607     if (pD3d)                 CHECK_RELEASE_REFCOUNT( pD3d, 0);
608
609     DestroyWindow( hwnd );
610 }
611
612 static void test_cursor(void)
613 {
614     HRESULT                      hr;
615     HWND                         hwnd               = NULL;
616     IDirect3D9                  *pD3d               = NULL;
617     IDirect3DDevice9            *pDevice            = NULL;
618     D3DPRESENT_PARAMETERS        d3dpp;
619     D3DDISPLAYMODE               d3ddm;
620     CURSORINFO                   info;
621     IDirect3DSurface9 *cursor = NULL;
622     HCURSOR cur;
623
624     memset(&info, 0, sizeof(info));
625     info.cbSize = sizeof(info);
626     hr = GetCursorInfo(&info);
627     cur = info.hCursor;
628
629     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
630     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
631     hwnd = CreateWindow( "static", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
632     ok(hwnd != NULL, "Failed to create window\n");
633     if (!pD3d || !hwnd) goto cleanup;
634
635     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
636     ZeroMemory( &d3dpp, sizeof(d3dpp) );
637     d3dpp.Windowed         = TRUE;
638     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
639     d3dpp.BackBufferFormat = d3ddm.Format;
640
641     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
642                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
643     ok(SUCCEEDED(hr), "Failed to create IDirect3D9Device (%s)\n", DXGetErrorString9(hr));
644     if (FAILED(hr)) goto cleanup;
645
646     IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, 0);
647     ok(cursor != NULL, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
648
649     /* Initially hidden */
650     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
651     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
652
653     /* Not enabled without a surface*/
654     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
655     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
656
657     /* Fails */
658     hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, NULL);
659     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
660
661     hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, cursor);
662     ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
663
664     IDirect3DSurface9_Release(cursor);
665
666     memset(&info, 0, sizeof(info));
667     info.cbSize = sizeof(info);
668     hr = GetCursorInfo(&info);
669     ok(hr != 0, "GetCursorInfo returned %08x\n", hr);
670     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
671     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
672
673     /* Still hidden */
674     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
675     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
676
677     /* Enabled now*/
678     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
679     ok(hr == TRUE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
680
681     /* GDI cursor unchanged */
682     memset(&info, 0, sizeof(info));
683     info.cbSize = sizeof(info);
684     hr = GetCursorInfo(&info);
685     ok(hr != 0, "GetCursorInfo returned %08x\n", hr);
686     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
687     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
688
689 cleanup:
690     if(pDevice) IDirect3D9_Release(pDevice);
691     if(pD3d) IDirect3D9_Release(pD3d);
692     DestroyWindow( hwnd );
693 }
694
695 static void test_reset(void)
696 {
697     HRESULT                      hr;
698     HWND                         hwnd               = NULL;
699     IDirect3D9                  *pD3d               = NULL;
700     IDirect3DDevice9            *pDevice            = NULL;
701     D3DPRESENT_PARAMETERS        d3dpp;
702     D3DDISPLAYMODE               d3ddm;
703     D3DVIEWPORT9                 vp;
704     DWORD                        width, orig_width = GetSystemMetrics(SM_CXSCREEN);
705     DWORD                        height, orig_height = GetSystemMetrics(SM_CYSCREEN);
706     IDirect3DSwapChain9          *pSwapchain;
707
708     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
709     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
710     hwnd = CreateWindow( "static", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
711     ok(hwnd != NULL, "Failed to create window\n");
712     if (!pD3d || !hwnd) goto cleanup;
713
714     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
715     ZeroMemory( &d3dpp, sizeof(d3dpp) );
716     d3dpp.Windowed         = FALSE;
717     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
718     d3dpp.BackBufferWidth  = 800;
719     d3dpp.BackBufferHeight  = 600;
720     d3dpp.BackBufferFormat = d3ddm.Format;
721
722     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
723                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
724     ok(SUCCEEDED(hr), "Failed to create IDirect3D9Device (%s)\n", DXGetErrorString9(hr));
725     if (FAILED(hr)) goto cleanup;
726
727     width = GetSystemMetrics(SM_CXSCREEN);
728     height = GetSystemMetrics(SM_CYSCREEN);
729     ok(width == 800, "Screen width is %d\n", width);
730     ok(height == 600, "Screen height is %d\n", height);
731
732     hr = IDirect3DDevice9_GetViewport(pDevice, &vp);
733     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %s\n", DXGetErrorString9(hr));
734     if(SUCCEEDED(hr))
735     {
736         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
737         ok(vp.Y == 0, "D3DVIEWPORT->X = %d\n", vp.Y);
738         ok(vp.Width == 800, "D3DVIEWPORT->X = %d\n", vp.Width);
739         ok(vp.Height == 600, "D3DVIEWPORT->X = %d\n", vp.Height);
740         ok(vp.MinZ == 0, "D3DVIEWPORT->X = %d\n", vp.Height);
741         ok(vp.MaxZ == 1, "D3DVIEWPORT->X = %d\n", vp.Height);
742     }
743     vp.X = 10;
744     vp.X = 20;
745     vp.MinZ = 2;
746     vp.MaxZ = 3;
747     hr = IDirect3DDevice9_SetViewport(pDevice, &vp);
748     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %s\n", DXGetErrorString9(hr));
749
750     ZeroMemory( &d3dpp, sizeof(d3dpp) );
751     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
752     d3dpp.Windowed         = FALSE;
753     d3dpp.BackBufferWidth  = 640;
754     d3dpp.BackBufferHeight  = 480;
755     d3dpp.BackBufferFormat = d3ddm.Format;
756     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
757     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr));
758
759     ZeroMemory(&vp, sizeof(vp));
760     hr = IDirect3DDevice9_GetViewport(pDevice, &vp);
761     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %s\n", DXGetErrorString9(hr));
762     if(SUCCEEDED(hr))
763     {
764         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
765         ok(vp.Y == 0, "D3DVIEWPORT->X = %d\n", vp.Y);
766         ok(vp.Width == 640, "D3DVIEWPORT->X = %d\n", vp.Width);
767         ok(vp.Height == 480, "D3DVIEWPORT->X = %d\n", vp.Height);
768         ok(vp.MinZ == 0, "D3DVIEWPORT->X = %d\n", vp.Height);
769         ok(vp.MaxZ == 1, "D3DVIEWPORT->X = %d\n", vp.Height);
770     }
771
772     width = GetSystemMetrics(SM_CXSCREEN);
773     height = GetSystemMetrics(SM_CYSCREEN);
774     ok(width == 640, "Screen width is %d\n", width);
775     ok(height == 480, "Screen height is %d\n", height);
776
777     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapchain);
778     ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %s\n", DXGetErrorString9(hr));
779     if(SUCCEEDED(hr))
780     {
781         ZeroMemory(&d3dpp, sizeof(d3dpp));
782         hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
783         ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %s\n", DXGetErrorString9(hr));
784         if(SUCCEEDED(hr))
785         {
786             ok(d3dpp.BackBufferWidth == 640, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
787             ok(d3dpp.BackBufferHeight == 480, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
788         }
789         IDirect3DSwapChain9_Release(pSwapchain);
790     }
791
792     ZeroMemory( &d3dpp, sizeof(d3dpp) );
793     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
794     d3dpp.Windowed         = TRUE;
795     d3dpp.BackBufferWidth  = 400;
796     d3dpp.BackBufferHeight  = 300;
797     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
798     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr));
799
800     width = GetSystemMetrics(SM_CXSCREEN);
801     height = GetSystemMetrics(SM_CYSCREEN);
802     ok(width == orig_width, "Screen width is %d\n", width);
803     ok(height == orig_height, "Screen height is %d\n", height);
804
805     ZeroMemory(&vp, sizeof(vp));
806     hr = IDirect3DDevice9_GetViewport(pDevice, &vp);
807     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %s\n", DXGetErrorString9(hr));
808     if(SUCCEEDED(hr))
809     {
810         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
811         ok(vp.Y == 0, "D3DVIEWPORT->X = %d\n", vp.Y);
812         ok(vp.Width == 400, "D3DVIEWPORT->X = %d\n", vp.Width);
813         ok(vp.Height == 300, "D3DVIEWPORT->X = %d\n", vp.Height);
814         ok(vp.MinZ == 0, "D3DVIEWPORT->X = %d\n", vp.Height);
815         ok(vp.MaxZ == 1, "D3DVIEWPORT->X = %d\n", vp.Height);
816     }
817
818     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapchain);
819     ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %s\n", DXGetErrorString9(hr));
820     if(SUCCEEDED(hr))
821     {
822         ZeroMemory(&d3dpp, sizeof(d3dpp));
823         hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
824         ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %s\n", DXGetErrorString9(hr));
825         if(SUCCEEDED(hr))
826         {
827             ok(d3dpp.BackBufferWidth == 400, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
828             ok(d3dpp.BackBufferHeight == 300, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
829         }
830         IDirect3DSwapChain9_Release(pSwapchain);
831     }
832
833 cleanup:
834     if(pD3d) IDirect3D9_Release(pD3d);
835     if(pDevice) IDirect3D9_Release(pDevice);
836 }
837
838 START_TEST(device)
839 {
840     HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
841
842     pDirect3DCreate9 = (void *)GetProcAddress( d3d9_handle, "Direct3DCreate9" );
843     if (pDirect3DCreate9)
844     {
845         test_swapchain();
846         test_refcount();
847         test_mipmap_levels();
848         test_cursor();
849         test_reset();
850     }
851 }