mshtml: Added IHTMLWindow2::focus implementation.
[wine] / dlls / ddrawex / tests / surface.c
1 /*
2  * Unit tests for ddrawex surfaces
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 /* For IID_IDirectDraw3 - it is not in dxguid.dll */
20 #define INITGUID
21
22 #include <assert.h>
23 #include "wine/test.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "ddraw.h"
27 #include "ddrawex.h"
28 #include "unknwn.h"
29
30 static IDirectDrawFactory *factory;
31 static HRESULT (WINAPI *pDllGetClassObject)(REFCLSID rclsid, REFIID riid, LPVOID *ppv);
32
33 static IDirectDraw *createDD(void)
34 {
35     HRESULT hr;
36     IDirectDraw *dd;
37
38     hr = IDirectDrawFactory_CreateDirectDraw(factory, NULL, NULL, DDSCL_NORMAL, 0,
39                                              0, &dd);
40     ok(hr == DD_OK, "Failed to create an IDirectDraw interface, hr = 0x%08x\n", hr);
41     return SUCCEEDED(hr) ? dd : NULL;
42 }
43
44 static void dctest_surf(IDirectDrawSurface *surf, int ddsdver) {
45     HRESULT hr;
46     HDC dc, dc2 = (HDC) 0x1234;
47     DDSURFACEDESC ddsd;
48     DDSURFACEDESC2 ddsd2;
49
50     memset(&ddsd, 0, sizeof(ddsd));
51     ddsd.dwSize = sizeof(ddsd);
52     memset(&ddsd2, 0, sizeof(ddsd2));
53     ddsd2.dwSize = sizeof(ddsd2);
54
55     hr = IDirectDrawSurface_GetDC(surf, &dc);
56     ok(hr == DD_OK, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
57
58     hr = IDirectDrawSurface_GetDC(surf, &dc);
59     ok(hr == DDERR_DCALREADYCREATED, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
60     ok(dc2 == (HDC) 0x1234, "The failed GetDC call changed the dc: %p\n", dc2);
61
62     hr = IDirectDrawSurface_Lock(surf, NULL, ddsdver == 1 ? &ddsd : ((DDSURFACEDESC *) &ddsd2), 0, NULL);
63     ok(hr == DDERR_SURFACEBUSY, "IDirectDrawSurface_Lock returned 0x%08x, expected DDERR_SURFACEBUSY\n", hr);
64
65     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
66     ok(hr == DD_OK, "IDirectDrawSurface_ReleaseDC failed: 0x%08x\n", hr);
67     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
68     ok(hr == DDERR_NODC, "IDirectDrawSurface_ReleaseDC returned 0x%08x, expected DDERR_NODC\n", hr);
69 }
70
71 static void GetDCTest_main(DDSURFACEDESC *ddsd, DDSURFACEDESC2 *ddsd2, void (*testfunc)(IDirectDrawSurface *surf, int ddsdver))
72 {
73     IDirectDrawSurface *surf;
74     IDirectDrawSurface2 *surf2;
75     IDirectDrawSurface2 *surf3;
76     IDirectDrawSurface4 *surf4;
77     HRESULT hr;
78     IDirectDraw  *dd1 = createDD();
79     IDirectDraw2 *dd2;
80     IDirectDraw3 *dd3;
81     IDirectDraw4 *dd4;
82
83     hr = IDirectDraw_CreateSurface(dd1, ddsd, &surf, NULL);
84     if (hr == DDERR_UNSUPPORTEDMODE) {
85         win_skip("Unsupported mode\n");
86         return;
87     }
88     ok(hr == DD_OK, "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
89     testfunc(surf, 1);
90     IDirectDrawSurface_Release(surf);
91
92     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirectDraw2, (void **) &dd2);
93     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
94
95     hr = IDirectDraw2_CreateSurface(dd2, ddsd, &surf, NULL);
96     ok(hr == DD_OK, "IDirectDraw2_CreateSurface failed: 0x%08x\n", hr);
97     testfunc(surf, 1);
98
99     hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface2, (void **) &surf2);
100     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed: 0x%08x\n", hr);
101     testfunc((IDirectDrawSurface *) surf2, 1);
102
103     IDirectDrawSurface2_Release(surf2);
104     IDirectDrawSurface_Release(surf);
105     IDirectDraw2_Release(dd2);
106
107     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirectDraw3, (void **) &dd3);
108     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
109
110     hr = IDirectDraw3_CreateSurface(dd3, ddsd, &surf, NULL);
111     ok(hr == DD_OK, "IDirectDraw3_CreateSurface failed: 0x%08x\n", hr);
112     testfunc(surf, 1);
113
114     hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface3, (void **) &surf3);
115     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed: 0x%08x\n", hr);
116     testfunc((IDirectDrawSurface *) surf3, 1);
117
118     IDirectDrawSurface3_Release(surf3);
119     IDirectDrawSurface_Release(surf);
120     IDirectDraw3_Release(dd3);
121
122     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirectDraw4, (void **) &dd4);
123     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
124
125     surf = NULL;
126     hr = IDirectDraw4_CreateSurface(dd4, ddsd2, &surf4, NULL);
127     ok(hr == DD_OK, "IDirectDraw4_CreateSurface failed: 0x%08x\n", hr);
128     testfunc((IDirectDrawSurface *) surf4, 2);
129
130     IDirectDrawSurface4_Release(surf4);
131     IDirectDraw4_Release(dd4);
132
133     IDirectDraw_Release(dd1);
134 }
135
136 static void GetDCTest(void)
137 {
138     DDSURFACEDESC ddsd;
139     DDSURFACEDESC2 ddsd2;
140
141     memset(&ddsd, 0, sizeof(ddsd));
142     ddsd.dwSize = sizeof(ddsd);
143     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
144     ddsd.dwWidth = 64;
145     ddsd.dwHeight = 64;
146     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
147     memset(&ddsd2, 0, sizeof(ddsd2));
148     ddsd2.dwSize = sizeof(ddsd2);
149     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
150     ddsd2.dwWidth = 64;
151     ddsd2.dwHeight = 64;
152     ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
153
154     GetDCTest_main(&ddsd, &ddsd2, dctest_surf);
155 }
156
157 static void CapsTest(void)
158 {
159     DDSURFACEDESC ddsd;
160     IDirectDraw  *dd1 = createDD();
161     IDirectDrawSurface *surf;
162     HRESULT hr;
163
164     memset(&ddsd, 0, sizeof(ddsd));
165     ddsd.dwSize = sizeof(ddsd);
166     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
167     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY;
168     ddsd.dwWidth = 64;
169     ddsd.dwHeight = 64;
170     hr = IDirectDraw_CreateSurface(dd1, &ddsd, &surf, NULL);
171     if (hr == DDERR_UNSUPPORTEDMODE) {
172         win_skip("Unsupported mode\n");
173         return;
174     }
175     ok(hr == DD_OK, "Creating a SYSMEM | VIDMEM surface returned 0x%08x, expected DD_OK\n", hr);
176     if(surf) IDirectDrawSurface_Release(surf);
177
178     IDirectDraw_Release(dd1);
179 }
180
181 static void dctest_sysvidmem(IDirectDrawSurface *surf, int ddsdver) {
182     HRESULT hr;
183     HDC dc, dc2 = (HDC) 0x1234;
184     DDSURFACEDESC ddsd;
185     DDSURFACEDESC2 ddsd2;
186
187     memset(&ddsd, 0, sizeof(ddsd));
188     ddsd.dwSize = sizeof(ddsd);
189     memset(&ddsd2, 0, sizeof(ddsd2));
190     ddsd2.dwSize = sizeof(ddsd2);
191
192     hr = IDirectDrawSurface_GetDC(surf, &dc);
193     ok(hr == DD_OK, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
194
195     hr = IDirectDrawSurface_GetDC(surf, &dc2);
196     ok(hr == DD_OK, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
197     ok(dc == dc2, "Got two different DCs\n");
198
199     hr = IDirectDrawSurface_Lock(surf, NULL, ddsdver == 1 ? &ddsd : ((DDSURFACEDESC *) &ddsd2), 0, NULL);
200     ok(hr == DD_OK, "IDirectDrawSurface_Lock returned 0x%08x, expected DD_OK\n", hr);
201
202     hr = IDirectDrawSurface_Lock(surf, NULL, ddsdver == 1 ? &ddsd : ((DDSURFACEDESC *) &ddsd2), 0, NULL);
203     ok(hr == DDERR_SURFACEBUSY, "IDirectDrawSurface_Lock returned 0x%08x, expected DDERR_SURFACEBUSY\n", hr);
204
205     hr = IDirectDrawSurface_Unlock(surf, NULL);
206     ok(hr == DD_OK, "IDirectDrawSurface_Unlock returned 0x%08x, expected DD_OK\n", hr);
207     hr = IDirectDrawSurface_Unlock(surf, NULL);
208     ok(hr == DDERR_NOTLOCKED, "IDirectDrawSurface_Unlock returned 0x%08x, expected DDERR_NOTLOCKED\n", hr);
209
210     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
211     ok(hr == DD_OK, "IDirectDrawSurface_ReleaseDC failed: 0x%08x\n", hr);
212     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
213     ok(hr == DD_OK, "IDirectDrawSurface_ReleaseDC failed: 0x%08x\n", hr);
214     /* That works any number of times... */
215     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
216     ok(hr == DD_OK, "IDirectDrawSurface_ReleaseDC failed: 0x%08x\n", hr);
217 }
218
219 static void SysVidMemTest(void)
220 {
221     DDSURFACEDESC ddsd;
222     DDSURFACEDESC2 ddsd2;
223
224     memset(&ddsd, 0, sizeof(ddsd));
225     ddsd.dwSize = sizeof(ddsd);
226     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
227     ddsd.dwWidth = 64;
228     ddsd.dwHeight = 64;
229     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY;
230     memset(&ddsd2, 0, sizeof(ddsd2));
231     ddsd2.dwSize = sizeof(ddsd2);
232     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
233     ddsd2.dwWidth = 64;
234     ddsd2.dwHeight = 64;
235     ddsd2.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY;
236
237     GetDCTest_main(&ddsd, &ddsd2, dctest_sysvidmem);
238 }
239
240 static void test_surface_from_dc3(void)
241 {
242     IDirectDrawSurface3 *surf3;
243     IDirectDrawSurface *surf1;
244     IDirectDrawSurface *tmp;
245     DDSURFACEDESC ddsd;
246     IDirectDraw3 *dd3;
247     IDirectDraw *dd1;
248     HRESULT hr;
249     HDC dc;
250
251     dd1 = createDD();
252     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirectDraw3, (void **)&dd3);
253     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed, hr %#x.\n", hr);
254     IDirectDraw_Release(dd1);
255
256     memset(&ddsd, 0, sizeof(ddsd));
257     ddsd.dwSize = sizeof(ddsd);
258     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
259     ddsd.dwWidth = 64;
260     ddsd.dwHeight = 64;
261     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
262
263     hr = IDirectDraw3_CreateSurface(dd3, &ddsd, &surf1, NULL);
264     if (hr == DDERR_UNSUPPORTEDMODE) {
265         win_skip("Unsupported mode\n");
266         IDirectDraw3_Release(dd3);
267         return;
268     }
269     ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
270
271     hr = IDirectDrawSurface3_QueryInterface(surf1, &IID_IDirectDrawSurface, (void **)&surf3);
272     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
273     IDirectDrawSurface_Release(surf1);
274
275     hr = IDirectDrawSurface3_GetDC(surf3, &dc);
276     ok(SUCCEEDED(hr), "GetDC failed, hr %#x.\n", hr);
277
278     hr = IDirectDraw3_GetSurfaceFromDC(dd3, dc, NULL);
279     ok(hr == E_POINTER, "Expected E_POINTER, got %#x.\n", hr);
280
281     hr = IDirectDraw3_GetSurfaceFromDC(dd3, dc, &tmp);
282     ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
283     ok((IDirectDrawSurface3 *)tmp == surf3, "Expected surface != %p.\n", surf3);
284
285     IUnknown_Release(tmp);
286
287     hr = IDirectDrawSurface3_ReleaseDC(surf3, dc);
288     ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
289
290     dc = CreateCompatibleDC(NULL);
291     ok(!!dc, "CreateCompatibleDC failed.\n");
292
293     tmp = (IDirectDrawSurface *)0xdeadbeef;
294     hr = IDirectDraw3_GetSurfaceFromDC(dd3, dc, &tmp);
295     ok(hr == DDERR_NOTFOUND, "Expected DDERR_NOTFOUND, got %#x.\n", hr);
296     ok(!tmp, "Expected surface NULL, got %p.\n", tmp);
297
298     ok(DeleteDC(dc), "DeleteDC failed.\n");
299
300     IDirectDrawSurface3_Release(surf3);
301     IDirectDraw3_Release(dd3);
302 }
303
304 DEFINE_GUID(guid, 0x38594b23, 0x2311, 0x4332, 0x95, 0xde, 0x2b, 0x0c, 0x61, 0xbf, 0x7b, 0x84);
305
306 static void test_surface_from_dc4(void)
307 {
308     IDirectDrawSurface4 *surf4;
309     IDirectDrawSurface *surf1;
310     DDSURFACEDESC2 ddsd2;
311     IUnknown *tmp, *tmp2;
312     IDirectDraw4 *dd4;
313     IDirectDraw *dd1;
314     DWORD priv, size;
315     HRESULT hr;
316     HDC dc;
317
318     dd1 = createDD();
319     hr = IDirectDraw_QueryInterface(dd1, &IID_IDirectDraw4, (void **)&dd4);
320     if (hr == E_NOINTERFACE) {
321         win_skip("DirectDraw4 is not supported\n");
322         IDirectDraw_Release(dd1);
323         return;
324     }
325     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed, hr %#x.\n", hr);
326     IDirectDraw_Release(dd1);
327
328     memset(&ddsd2, 0, sizeof(ddsd2));
329     ddsd2.dwSize = sizeof(ddsd2);
330     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
331     ddsd2.dwWidth = 64;
332     ddsd2.dwHeight = 64;
333     ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
334
335     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
336     if (hr == DDERR_UNSUPPORTEDMODE) {
337         win_skip("Unsupported mode\n");
338         IDirectDraw3_Release(dd4);
339         return;
340     }
341     ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
342
343     hr = IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface, (void **)&surf1);
344     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
345
346     priv = 0xdeadbeef;
347     size = sizeof(priv);
348     hr = IDirectDrawSurface4_SetPrivateData(surf4, &guid, &priv, size, 0);
349     ok(SUCCEEDED(hr), "SetPrivateData failed, hr %#x.\n", hr);
350
351     priv = 0;
352     hr = IDirectDrawSurface4_GetPrivateData(surf4, &guid, &priv, &size);
353     ok(SUCCEEDED(hr), "GetPrivateData failed, hr %#x.\n", hr);
354     ok(priv == 0xdeadbeef, "Expected private data 0xdeadbeef, got %#x.\n", priv);
355
356     hr = IDirectDrawSurface4_GetDC(surf4, &dc);
357     ok(SUCCEEDED(hr), "GetDC failed, hr %#x.\n", hr);
358
359     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, NULL);
360     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %#x.\n", hr);
361
362     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, (IDirectDrawSurface4 **)&tmp);
363     ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
364     ok((IDirectDrawSurface4 *)tmp != surf4, "Expected surface != %p.\n", surf4);
365
366     hr = IUnknown_QueryInterface(tmp, &IID_IDirectDrawSurface, (void **)&tmp2);
367     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
368     ok(tmp2 == tmp, "Expected %p, got %p.\n", tmp, tmp2);
369     ok((IDirectDrawSurface *)tmp2 != surf1, "Expected surface != %p.\n", surf1);
370     IUnknown_Release(tmp2);
371
372     hr = IUnknown_QueryInterface(tmp, &IID_IDirectDrawSurface4, (void **)&tmp2);
373     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
374     ok((IDirectDrawSurface4 *)tmp2 != surf4, "Expected surface != %p.\n", surf4);
375
376     priv = 0;
377     hr = IDirectDrawSurface4_GetPrivateData((IDirectDrawSurface4 *)tmp2, &guid, &priv, &size);
378     ok(SUCCEEDED(hr), "GetPrivateData failed, hr %#x.\n", hr);
379     ok(priv == 0xdeadbeef, "Expected private data 0xdeadbeef, got %#x.\n", priv);
380     IUnknown_Release(tmp2);
381
382     IUnknown_Release(tmp);
383
384     hr = IDirectDrawSurface4_ReleaseDC(surf4, dc);
385     ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
386
387     dc = CreateCompatibleDC(NULL);
388     ok(!!dc, "CreateCompatibleDC failed.\n");
389
390     tmp = (IUnknown *)0xdeadbeef;
391     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, (IDirectDrawSurface4 **)&tmp);
392     ok(hr == DDERR_NOTFOUND, "Expected DDERR_NOTFOUND, got %#x.\n", hr);
393     ok(!tmp, "Expected surface NULL, got %p.\n", tmp);
394
395     ok(DeleteDC(dc), "DeleteDC failed.\n");
396
397     tmp = (IUnknown *)0xdeadbeef;
398     hr = IDirectDraw4_GetSurfaceFromDC(dd4, NULL, (IDirectDrawSurface4 **)&tmp);
399     ok(hr == DDERR_NOTFOUND, "Expected DDERR_NOTFOUND, got %#x.\n", hr);
400     ok(!tmp, "Expected surface NULL, got %p.\n", tmp);
401
402     IDirectDrawSurface_Release(surf1);
403     IDirectDrawSurface4_Release(surf4);
404     IDirectDraw4_Release(dd4);
405 }
406
407 START_TEST(surface)
408 {
409     IClassFactory *classfactory = NULL;
410     ULONG ref;
411     HRESULT hr;
412     HMODULE hmod = LoadLibrary("ddrawex.dll");
413     if(hmod == NULL) {
414         skip("Failed to load ddrawex.dll\n");
415         return;
416     }
417     pDllGetClassObject = (void*)GetProcAddress(hmod, "DllGetClassObject");
418     if(pDllGetClassObject == NULL) {
419         skip("Failed to get DllGetClassObject\n");
420         return;
421     }
422
423     hr = pDllGetClassObject(&CLSID_DirectDrawFactory, &IID_IClassFactory, (void **) &classfactory);
424     ok(hr == S_OK, "Failed to create a IClassFactory\n");
425     hr = IClassFactory_CreateInstance(classfactory, NULL, &IID_IDirectDrawFactory, (void **) &factory);
426     ok(hr == S_OK, "Failed to create a IDirectDrawFactory\n");
427
428     GetDCTest();
429     CapsTest();
430     SysVidMemTest();
431     test_surface_from_dc3();
432     test_surface_from_dc4();
433
434     if(factory) {
435         ref = IDirectDrawFactory_Release(factory);
436         ok(ref == 0, "IDirectDrawFactory not cleanly released\n");
437     }
438     if(classfactory) {
439         ref = IClassFactory_Release(classfactory);
440         todo_wine ok(ref == 1, "IClassFactory refcount wrong, ref = %u\n", ref);
441     }
442 }