2 * Copyright (C) 2006 Vitaliy Margolen
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.
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.
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
22 #include "wine/test.h"
24 static IDirect3D8
*(WINAPI
*pDirect3DCreate8
)(UINT
);
26 static int get_refcount(IUnknown
*object
)
28 IUnknown_AddRef( object
);
29 return IUnknown_Release( object
);
32 #define CHECK_CALL(r,c,d,rc) \
34 int tmp1 = get_refcount( (IUnknown *)d ); \
35 ok(rc == tmp1, "Invalid refcount. Expected %d got %d\n", rc, tmp1); \
37 trace("%s failed: %s\n", c, DXGetErrorString8(r)); \
40 static void test_swapchain(void)
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
;
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
;
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;
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
;
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
);
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
);
80 d3dpp
.BackBufferCount
= 1;
81 hr
= IDirect3DDevice8_CreateAdditionalSwapChain(pDevice
, &d3dpp
, &swapchain2
);
82 ok(SUCCEEDED(hr
), "Failed to create a swapchain (%s)\n", DXGetErrorString8(hr
));
84 d3dpp
.BackBufferCount
= 2;
85 hr
= IDirect3DDevice8_CreateAdditionalSwapChain(pDevice
, &d3dpp
, &swapchain3
);
86 ok(SUCCEEDED(hr
), "Failed to create a swapchain (%s)\n", DXGetErrorString8(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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
155 static void test_refcount(void)
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
;
175 D3DPRESENT_PARAMETERS d3dpp
;
176 D3DDISPLAYMODE d3ddm
;
182 D3DVSD_REG(D3DVSDE_POSITION
, D3DVSDT_FLOAT3
), /* D3DVSDE_POSITION, Register v0 */
183 D3DVSD_REG(D3DVSDE_DIFFUSE
, D3DVSDT_D3DCOLOR
), /* D3DVSDE_DIFFUSE, Register v5 */
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 */
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
;
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
;
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
;
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 );
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
);
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 );
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 );
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 );
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 );}
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 );
271 if (pDevice
) IUnknown_Release( pDevice
);
274 if (pVertexBuffer
) IUnknown_Release( pVertexBuffer
);
275 if (pIndexBuffer
) IUnknown_Release( pIndexBuffer
);
277 if (dVertexShader
!= -1) IDirect3DDevice8_DeleteVertexShader( pDevice
, dVertexShader
);
278 if (dPixelShader
!= -1) IDirect3DDevice8_DeletePixelShader( pDevice
, dPixelShader
);
280 if (pTexture
) IUnknown_Release( pTexture
);
281 if (pTextureLevel
) IUnknown_Release( pTextureLevel
);
282 if (pCubeTexture
) IUnknown_Release( pCubeTexture
);
283 if (pVolumeTexture
) IUnknown_Release( pVolumeTexture
);
285 if (pStencilSurface
) IUnknown_Release( pStencilSurface
);
286 if (pImageSurface
) IUnknown_Release( pImageSurface
);
287 if (pRenderTarget
) IUnknown_Release( pRenderTarget
);
289 if (dStateBlock
!= -1) IDirect3DDevice8_DeleteStateBlock( pDevice
, dStateBlock
);
290 /* Avoid crash for now.
291 if (pSwapChain) IUnknown_Release( pSwapChain );
294 if (pD3d
) IUnknown_Release( pD3d
);
296 DestroyWindow( hwnd
);
301 HMODULE d3d8_handle
= LoadLibraryA( "d3d8.dll" );
303 pDirect3DCreate8
= (void *)GetProcAddress( d3d8_handle
, "Direct3DCreate8" );
304 if (pDirect3DCreate8
)