mshtml: Added IHTMLWindow2::focus implementation.
[wine] / dlls / d3d8 / tests / surface.c
1 /*
2  * Copyright 2006-2007 Henri Verbeet
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 #define COBJMACROS
19 #include <d3d8.h>
20 #include "wine/test.h"
21
22 static HWND create_window(void)
23 {
24     WNDCLASS wc = {0};
25     wc.lpfnWndProc = DefWindowProc;
26     wc.lpszClassName = "d3d8_test_wc";
27     RegisterClass(&wc);
28
29     return CreateWindow("d3d8_test_wc", "d3d8_test",
30             0, 0, 0, 0, 0, 0, 0, 0, 0);
31 }
32
33 static IDirect3DDevice8 *init_d3d8(HMODULE d3d8_handle)
34 {
35     IDirect3D8 * (__stdcall * d3d8_create)(UINT SDKVersion) = 0;
36     IDirect3D8 *d3d8_ptr = 0;
37     IDirect3DDevice8 *device_ptr = 0;
38     D3DPRESENT_PARAMETERS present_parameters;
39     D3DDISPLAYMODE               d3ddm;
40     HRESULT hr;
41
42     d3d8_create = (void *)GetProcAddress(d3d8_handle, "Direct3DCreate8");
43     ok(d3d8_create != NULL, "Failed to get address of Direct3DCreate8\n");
44     if (!d3d8_create) return NULL;
45
46     d3d8_ptr = d3d8_create(D3D_SDK_VERSION);
47     if (!d3d8_ptr)
48     {
49         skip("could not create D3D8\n");
50         return NULL;
51     }
52
53     IDirect3D8_GetAdapterDisplayMode(d3d8_ptr, D3DADAPTER_DEFAULT, &d3ddm );
54     ZeroMemory(&present_parameters, sizeof(present_parameters));
55     present_parameters.Windowed = TRUE;
56     present_parameters.hDeviceWindow = create_window();
57     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
58     present_parameters.BackBufferFormat = d3ddm.Format;
59     present_parameters.EnableAutoDepthStencil = TRUE;
60     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
61
62     hr = IDirect3D8_CreateDevice(d3d8_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
63             NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
64
65     if(FAILED(hr))
66     {
67         skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
68         return NULL;
69     }
70
71     return device_ptr;
72 }
73
74 /* Test the behaviour of the IDirect3DDevice8::CreateImageSurface method.
75
76 Expected behaviour (and also documented in the original DX8 docs) is that the
77 call returns a surface with the SYSTEMMEM pool type. Games like Max Payne 1
78 and 2 which use Direct3D8 calls depend on this behaviour.
79
80 A short remark in the DX9 docs however states that the pool of the
81 returned surface object is of type SCRATCH. This is misinformation and results
82 in screenshots not appearing in the savegame loading menu of both games
83 mentioned above (engine tries to display a texture from the scratch pool).
84
85 This test verifies that the behaviour described in the original D3D8 docs is
86 the correct one. For more information about this issue, see the MSDN:
87
88 D3D9 docs: "Converting to Direct3D 9"
89 D3D9 reference: "IDirect3DDevice9::CreateOffscreenPlainSurface"
90 D3D8 reference: "IDirect3DDevice8::CreateImageSurface"
91 */
92
93 static void test_image_surface_pool(IDirect3DDevice8 *device) {
94     IDirect3DSurface8 *surface = 0;
95     D3DSURFACE_DESC surf_desc;
96     HRESULT hr;
97
98     hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
99     ok(SUCCEEDED(hr), "CreateImageSurface failed (0x%08x)\n", hr);
100
101     hr = IDirect3DSurface8_GetDesc(surface, &surf_desc);
102     ok(SUCCEEDED(hr), "GetDesc failed (0x%08x)\n", hr);
103
104     ok((surf_desc.Pool == D3DPOOL_SYSTEMMEM),
105         "CreateImageSurface returns surface with unexpected pool type %u (should be SYSTEMMEM = 2)\n", surf_desc.Pool);
106
107     IDirect3DSurface8_Release(surface);
108 }
109
110 static void test_surface_get_container(IDirect3DDevice8 *device_ptr)
111 {
112     IDirect3DTexture8 *texture_ptr = 0;
113     IDirect3DSurface8 *surface_ptr = 0;
114     void *container_ptr;
115     HRESULT hr;
116
117     hr = IDirect3DDevice8_CreateTexture(device_ptr, 128, 128, 1, 0,
118             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture_ptr);
119     ok(SUCCEEDED(hr) && texture_ptr != NULL, "CreateTexture returned: hr %#x, texture_ptr %p. "
120         "Expected hr %#x, texture_ptr != %p\n", hr, texture_ptr, D3D_OK, NULL);
121     if (!texture_ptr || FAILED(hr)) goto cleanup;
122
123     hr = IDirect3DTexture8_GetSurfaceLevel(texture_ptr, 0, &surface_ptr);
124     ok(SUCCEEDED(hr) && surface_ptr != NULL, "GetSurfaceLevel returned: hr %#x, surface_ptr %p. "
125         "Expected hr %#x, surface_ptr != %p\n", hr, surface_ptr, D3D_OK, NULL);
126     if (!surface_ptr || FAILED(hr)) goto cleanup;
127
128     /* These should work... */
129     container_ptr = (void *)0x1337c0d3;
130     hr = IDirect3DSurface8_GetContainer(surface_ptr, &IID_IUnknown, &container_ptr);
131     ok(SUCCEEDED(hr) && container_ptr == texture_ptr, "GetContainer returned: hr %#x, container_ptr %p. "
132         "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, texture_ptr);
133     if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr);
134
135     container_ptr = (void *)0x1337c0d3;
136     hr = IDirect3DSurface8_GetContainer(surface_ptr, &IID_IDirect3DResource8, &container_ptr);
137     ok(SUCCEEDED(hr) && container_ptr == texture_ptr, "GetContainer returned: hr %#x, container_ptr %p. "
138         "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, texture_ptr);
139     if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr);
140
141     container_ptr = (void *)0x1337c0d3;
142     hr = IDirect3DSurface8_GetContainer(surface_ptr, &IID_IDirect3DBaseTexture8, &container_ptr);
143     ok(SUCCEEDED(hr) && container_ptr == texture_ptr, "GetContainer returned: hr %#x, container_ptr %p. "
144         "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, texture_ptr);
145     if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr);
146
147     container_ptr = (void *)0x1337c0d3;
148     hr = IDirect3DSurface8_GetContainer(surface_ptr, &IID_IDirect3DTexture8, &container_ptr);
149     ok(SUCCEEDED(hr) && container_ptr == texture_ptr, "GetContainer returned: hr %#x, container_ptr %p. "
150         "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, texture_ptr);
151     if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr);
152
153     /* ...and this one shouldn't. This should return E_NOINTERFACE and set container_ptr to NULL */
154     container_ptr = (void *)0x1337c0d3;
155     hr = IDirect3DSurface8_GetContainer(surface_ptr, &IID_IDirect3DSurface8, &container_ptr);
156     ok(hr == E_NOINTERFACE && container_ptr == NULL, "GetContainer returned: hr %#x, container_ptr %p. "
157         "Expected hr %#x, container_ptr %p\n", hr, container_ptr, E_NOINTERFACE, NULL);
158     if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr);
159
160 cleanup:
161     if (texture_ptr) IDirect3DTexture8_Release(texture_ptr);
162     if (surface_ptr) IDirect3DSurface8_Release(surface_ptr);
163 }
164
165 static void test_lockrect_invalid(IDirect3DDevice8 *device)
166 {
167     IDirect3DSurface8 *surface = 0;
168     D3DLOCKED_RECT locked_rect;
169     unsigned int i;
170     BYTE *base;
171     HRESULT hr;
172
173     const RECT valid[] = {
174         {60, 60, 68, 68},
175         {120, 60, 128, 68},
176         {60, 120, 68, 128},
177     };
178
179     const RECT invalid[] = {
180         {60, 60, 60, 68},       /* 0 height */
181         {60, 60, 68, 60},       /* 0 width */
182         {68, 60, 60, 68},       /* left > right */
183         {60, 68, 68, 60},       /* top > bottom */
184         {-8, 60,  0, 68},       /* left < surface */
185         {60, -8, 68,  0},       /* top < surface */
186         {-16, 60, -8, 68},      /* right < surface */
187         {60, -16, 68, -8},      /* bottom < surface */
188         {60, 60, 136, 68},      /* right > surface */
189         {60, 60, 68, 136},      /* bottom > surface */
190         {136, 60, 144, 68},     /* left > surface */
191         {60, 136, 68, 144},     /* top > surface */
192     };
193
194     hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
195     ok(SUCCEEDED(hr), "CreateImageSurface failed (0x%08x)\n", hr);
196
197     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
198     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
199
200     base = locked_rect.pBits;
201
202     hr = IDirect3DSurface8_UnlockRect(surface);
203     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
204
205     for (i = 0; i < (sizeof(valid) / sizeof(*valid)); ++i)
206     {
207         unsigned int offset, expected_offset;
208         const RECT *rect = &valid[i];
209
210         locked_rect.pBits = (BYTE *)0xdeadbeef;
211         locked_rect.Pitch = 0xdeadbeef;
212
213         hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
214         ok(SUCCEEDED(hr), "LockRect failed (0x%08x) for rect [%d, %d]->[%d, %d]\n",
215                 hr, rect->left, rect->top, rect->right, rect->bottom);
216
217         offset = (BYTE *)locked_rect.pBits - base;
218         expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
219         ok(offset == expected_offset, "Got offset %u, expected offset %u for rect [%d, %d]->[%d, %d]\n",
220                 offset, expected_offset, rect->left, rect->top, rect->right, rect->bottom);
221
222         hr = IDirect3DSurface8_UnlockRect(surface);
223         ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
224     }
225
226     for (i = 0; i < (sizeof(invalid) / sizeof(*invalid)); ++i)
227     {
228         const RECT *rect = &invalid[i];
229
230         hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
231         ok(hr == D3DERR_INVALIDCALL, "LockRect returned 0x%08x for rect [%d, %d]->[%d, %d]"
232                 ", expected D3DERR_INVALIDCALL (0x%08x)\n", hr, rect->left, rect->top,
233                 rect->right, rect->bottom, D3DERR_INVALIDCALL);
234     }
235
236     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
237     ok(SUCCEEDED(hr), "LockRect failed (0x%08x) for rect NULL\n", hr);
238     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
239     ok(hr == D3DERR_INVALIDCALL, "Double LockRect returned 0x%08x for rect NULL\n", hr);
240     hr = IDirect3DSurface8_UnlockRect(surface);
241     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
242
243     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
244     ok(hr == D3D_OK, "LockRect failed (0x%08x) for rect [%d, %d]->[%d, %d]"
245             ", expected D3D_OK (0x%08x)\n", hr, valid[0].left, valid[0].top,
246             valid[0].right, valid[0].bottom, D3D_OK);
247     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
248     ok(hr == D3DERR_INVALIDCALL, "Double LockRect failed (0x%08x) for rect [%d, %d]->[%d, %d]"
249             ", expected D3DERR_INVALIDCALL (0x%08x)\n", hr, valid[0].left, valid[0].top,
250             valid[0].right, valid[0].bottom,D3DERR_INVALIDCALL);
251     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[1], 0);
252     ok(hr == D3DERR_INVALIDCALL, "Double LockRect failed (0x%08x) for rect [%d, %d]->[%d, %d]"
253             ", expected D3DERR_INVALIDCALL (0x%08x)\n", hr, valid[1].left, valid[1].top,
254             valid[1].right, valid[1].bottom, D3DERR_INVALIDCALL);
255     hr = IDirect3DSurface8_UnlockRect(surface);
256     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
257
258     IDirect3DSurface8_Release(surface);
259 }
260
261 static ULONG getref(IUnknown *iface)
262 {
263     IUnknown_AddRef(iface);
264     return IUnknown_Release(iface);
265 }
266
267 static void test_private_data(IDirect3DDevice8 *device)
268 {
269     HRESULT hr;
270     IDirect3DSurface8 *surface;
271     ULONG ref, ref2;
272     IUnknown *ptr;
273     DWORD size = sizeof(IUnknown *);
274
275     hr = IDirect3DDevice8_CreateImageSurface(device, 4, 4, D3DFMT_A8R8G8B8, &surface);
276     ok(SUCCEEDED(hr), "CreateImageSurface failed (0x%08x)\n", hr);
277     if(!surface)
278     {
279         return;
280     }
281
282     /* This fails */
283     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */, device, 0, D3DSPD_IUNKNOWN);
284     ok(hr == D3DERR_INVALIDCALL, "IDirect3DSurface8_SetPrivateData failed with %08x\n", hr);
285     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */, device, 5, D3DSPD_IUNKNOWN);
286     ok(hr == D3DERR_INVALIDCALL, "IDirect3DSurface8_SetPrivateData failed with %08x\n", hr);
287     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */, device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
288     ok(hr == D3DERR_INVALIDCALL, "IDirect3DSurface8_SetPrivateData failed with %08x\n", hr);
289
290     ref = getref((IUnknown *) device);
291     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */, device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
292     ok(hr == D3D_OK, "IDirect3DSurface8_SetPrivateData failed with %08x\n", hr);
293     ref2 = getref((IUnknown *) device);
294     ok(ref2 == ref + 1, "Object reference is %d, expected %d\n", ref2, ref + 1);
295     hr = IDirect3DSurface8_FreePrivateData(surface, &IID_IDirect3DSurface8);
296     ok(hr == D3D_OK, "IDirect3DSurface8_FreePrivateData returned %08x\n", hr);
297     ref2 = getref((IUnknown *) device);
298     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
299
300     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8, device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
301     ok(hr == D3D_OK, "IDirect3DSurface8_SetPrivateData failed with %08x\n", hr);
302     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8, surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
303     ok(hr == D3D_OK, "IDirect3DSurface8_SetPrivateData failed with %08x\n", hr);
304     ref2 = getref((IUnknown *) device);
305     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
306
307     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8, device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
308     ok(hr == D3D_OK, "IDirect3DSurface8_SetPrivateData failed with %08x\n", hr);
309     hr = IDirect3DSurface8_GetPrivateData(surface, &IID_IDirect3DSurface8, &ptr, &size);
310     ok(hr == D3D_OK, "IDirect3DSurface8_GetPrivateData failed with %08x\n", hr);
311     ref2 = getref((IUnknown *) device);
312     /* Object is NOT being addrefed */
313     ok(ptr == (IUnknown *) device, "Returned interface pointer is %p, expected %p\n", ptr, device);
314     ok(ref2 == ref + 2, "Object reference is %d, expected %d. ptr at %p, orig at %p\n", ref2, ref + 2, ptr, device);
315     IUnknown_Release(ptr);
316
317     IDirect3DSurface8_Release(surface);
318
319     /* Destroying the surface frees the held reference */
320     ref2 = getref((IUnknown *) device);
321     /* -1 because the surface was released and held a reference before */
322     ok(ref2 == (ref - 1), "Object reference is %d, expected %d\n", ref2, ref - 1);
323 }
324
325 static void test_surface_dimensions(IDirect3DDevice8 *device)
326 {
327     IDirect3DSurface8 *surface;
328     HRESULT hr;
329
330     hr = IDirect3DDevice8_CreateImageSurface(device, 0, 1, D3DFMT_A8R8G8B8, &surface);
331     ok(hr == D3DERR_INVALIDCALL, "CreateOffscreenPlainSurface returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
332     if (SUCCEEDED(hr)) IDirect3DSurface8_Release(surface);
333
334     hr = IDirect3DDevice8_CreateImageSurface(device, 1, 0, D3DFMT_A8R8G8B8, &surface);
335     ok(hr == D3DERR_INVALIDCALL, "CreateOffscreenPlainSurface returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
336     if (SUCCEEDED(hr)) IDirect3DSurface8_Release(surface);
337 }
338
339 static void test_surface_format_null(IDirect3DDevice8 *device)
340 {
341     static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
342     IDirect3DTexture8 *texture;
343     IDirect3DSurface8 *surface;
344     IDirect3DSurface8 *rt, *ds;
345     D3DLOCKED_RECT locked_rect;
346     D3DSURFACE_DESC desc;
347     IDirect3D8 *d3d;
348     HRESULT hr;
349
350     IDirect3DDevice8_GetDirect3D(device, &d3d);
351
352     hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
353             D3DUSAGE_RENDERTARGET,  D3DRTYPE_SURFACE, D3DFMT_NULL);
354     if (hr != D3D_OK)
355     {
356         skip("No D3DFMT_NULL support, skipping test.\n");
357         IDirect3D8_Release(d3d);
358         return;
359     }
360
361     hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
362             D3DUSAGE_RENDERTARGET,  D3DRTYPE_TEXTURE, D3DFMT_NULL);
363     ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
364
365     hr = IDirect3D8_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
366             D3DFMT_NULL, D3DFMT_D24S8);
367     ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
368
369     IDirect3D8_Release(d3d);
370
371     hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
372             D3DMULTISAMPLE_NONE, TRUE, &surface);
373     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
374
375     hr = IDirect3DDevice8_GetRenderTarget(device, &rt);
376     ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
377
378     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds);
379     ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
380
381     hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
382     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
383
384     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
385     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
386
387     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
388     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
389
390     IDirect3DSurface8_Release(rt);
391     IDirect3DSurface8_Release(ds);
392
393     hr = IDirect3DSurface8_GetDesc(surface, &desc);
394     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
395     ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
396     ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
397
398     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
399     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
400     ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
401     ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
402
403     hr = IDirect3DSurface8_UnlockRect(surface);
404     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
405
406     IDirect3DSurface8_Release(surface);
407
408     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
409             D3DFMT_NULL, D3DPOOL_DEFAULT, &texture);
410     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
411     IDirect3DTexture8_Release(texture);
412 }
413
414 START_TEST(surface)
415 {
416     HMODULE d3d8_handle;
417     IDirect3DDevice8 *device_ptr;
418     ULONG refcount;
419
420     d3d8_handle = LoadLibraryA("d3d8.dll");
421     if (!d3d8_handle)
422     {
423         skip("Could not load d3d8.dll\n");
424         return;
425     }
426
427     device_ptr = init_d3d8(d3d8_handle);
428     if (!device_ptr) return;
429
430     test_image_surface_pool(device_ptr);
431     test_surface_get_container(device_ptr);
432     test_lockrect_invalid(device_ptr);
433     test_private_data(device_ptr);
434     test_surface_dimensions(device_ptr);
435     test_surface_format_null(device_ptr);
436
437     refcount = IDirect3DDevice8_Release(device_ptr);
438     ok(!refcount, "Device has %u references left\n", refcount);
439 }