dmloader: Declare some functions static.
[wine] / dlls / ddraw / tests / dsurface.c
1 /*
2  * Unit tests for (a few) ddraw surface functions
3  *
4  * Copyright (C) 2005 Antoine Chavasse (a.chavasse@gmail.com)
5  * Copyright (C) 2005 Christian Costa
6  * Copyright 2005 Ivan Leo Puoti
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include <assert.h>
24 #include "wine/test.h"
25 #include "ddraw.h"
26
27 static LPDIRECTDRAW lpDD = NULL;
28
29 static BOOL CreateDirectDraw(void)
30 {
31     HRESULT rc;
32
33     rc = DirectDrawCreate(NULL, &lpDD, NULL);
34     ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
35     if (!lpDD) {
36         trace("DirectDrawCreateEx() failed with an error %x\n", rc);
37         return FALSE;
38     }
39
40     rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
41     ok(rc==DD_OK,"SetCooperativeLevel returned: %x\n",rc);
42
43     return TRUE;
44 }
45
46
47 static void ReleaseDirectDraw(void)
48 {
49     if( lpDD != NULL )
50     {
51         IDirectDraw_Release(lpDD);
52         lpDD = NULL;
53     }
54 }
55
56 static void MipMapCreationTest(void)
57 {
58     LPDIRECTDRAWSURFACE lpDDSMipMapTest;
59     DDSURFACEDESC ddsd;
60     HRESULT rc;
61
62     /* First mipmap creation test: create a surface with DDSCAPS_COMPLEX,
63        DDSCAPS_MIPMAP, and DDSD_MIPMAPCOUNT. This create the number of
64         requested mipmap levels. */
65     ddsd.dwSize = sizeof(ddsd);
66     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
67     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
68     U2(ddsd).dwMipMapCount = 3;
69     ddsd.dwWidth = 128;
70     ddsd.dwHeight = 32;
71     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
72     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
73
74     /* Check the number of created mipmaps */
75     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
76     ddsd.dwSize = sizeof(ddsd);
77     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
78     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
79     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
80         "GetSurfaceDesc returned no mipmapcount.\n");
81     ok(U2(ddsd).dwMipMapCount == 3, "Incorrect mipmap count: %d.\n",
82         U2(ddsd).dwMipMapCount);
83
84     /* Destroy the surface. */
85     IDirectDrawSurface_Release(lpDDSMipMapTest);
86
87
88     /* Second mipmap creation test: create a surface without a mipmap
89        count, with DDSCAPS_MIPMAP and without DDSCAPS_COMPLEX.
90        This creates a single mipmap level. */
91     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
92     ddsd.dwSize = sizeof(ddsd);
93     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
94     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
95     ddsd.dwWidth = 128;
96     ddsd.dwHeight = 32;
97     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
98     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
99
100     /* Check the number of created mipmaps */
101     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
102     ddsd.dwSize = sizeof(ddsd);
103     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
104     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
105     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
106         "GetSurfaceDesc returned no mipmapcount.\n");
107     ok(U2(ddsd).dwMipMapCount == 1, "Incorrect mipmap count: %d.\n",
108         U2(ddsd).dwMipMapCount);
109
110
111     /* Third mipmap creation test: create a surface with DDSCAPS_MIPMAP,
112         DDSCAPS_COMPLEX and without DDSD_MIPMAPCOUNT.
113        It's an undocumented features where a chain of mipmaps, starting from
114        he specified size and down to the smallest size, is automatically
115        created.
116        Anarchy Online needs this feature to work. */
117     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
118     ddsd.dwSize = sizeof(ddsd);
119     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
120     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
121     ddsd.dwWidth = 128;
122     ddsd.dwHeight = 32;
123     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
124     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
125
126     /* Check the number of created mipmaps */
127     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
128     ddsd.dwSize = sizeof(ddsd);
129     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
130     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
131     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
132         "GetSurfaceDesc returned no mipmapcount.\n");
133     ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %d.\n",
134         U2(ddsd).dwMipMapCount);
135
136
137     /* Fourth mipmap creation test: same as above with a different texture
138        size.
139        The purpose is to verify that the number of generated mipmaps is
140        dependent on the smallest dimension. */
141     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
142     ddsd.dwSize = sizeof(ddsd);
143     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
144     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
145     ddsd.dwWidth = 32;
146     ddsd.dwHeight = 64;
147     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
148     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
149
150     /* Check the number of created mipmaps */
151     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
152     ddsd.dwSize = sizeof(ddsd);
153     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
154     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
155     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
156         "GetSurfaceDesc returned no mipmapcount.\n");
157     ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %d.\n",
158         U2(ddsd).dwMipMapCount);
159
160     /* Destroy the surface. */
161     IDirectDrawSurface_Release(lpDDSMipMapTest);
162 }
163
164 static void SrcColorKey32BlitTest(void)
165 {
166     LPDIRECTDRAWSURFACE lpSrc;
167     LPDIRECTDRAWSURFACE lpDst;
168     DDSURFACEDESC ddsd;
169     DDSURFACEDESC ddsd2;
170     DDCOLORKEY DDColorKey;
171     LPDWORD lpData;
172     HRESULT rc;
173
174     ddsd2.dwSize = sizeof(ddsd2);
175     ddsd2.ddpfPixelFormat.dwSize = sizeof(ddsd2.ddpfPixelFormat);
176
177     ddsd.dwSize = sizeof(ddsd);
178     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
179     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
180     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
181     ddsd.dwWidth = 800;
182     ddsd.dwHeight = 600;
183     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
184     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
185     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
186     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
187     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
188     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDst, NULL);
189     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
190
191     ddsd.dwFlags |= DDSD_CKSRCBLT;
192     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0xFF00FF;
193     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0xFF00FF;
194     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL);
195     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
196     
197     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
198     ok(rc==DD_OK,"Lock returned: %x\n",rc);
199     lpData = (LPDWORD)ddsd2.lpSurface;
200     lpData[0] = 0xCCCCCCCC;
201     lpData[1] = 0xCCCCCCCC;
202     lpData[2] = 0xCCCCCCCC;
203     lpData[3] = 0xCCCCCCCC;
204     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
205     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
206
207     rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
208     ok(rc==DD_OK,"Lock returned: %x\n",rc);
209     lpData = (LPDWORD)ddsd2.lpSurface;
210     lpData[0] = 0x77010203;
211     lpData[1] = 0x00010203;
212     lpData[2] = 0x77FF00FF;
213     lpData[3] = 0x00FF00FF;
214     rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
215     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
216
217     IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, NULL);
218
219     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
220     ok(rc==DD_OK,"Lock returned: %x\n",rc);
221     lpData = (LPDWORD)ddsd2.lpSurface;
222     ok((lpData[0]==0x77010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0xCCCCCCCC)&&(lpData[3]==0xCCCCCCCC),
223        "Destination data after blitting is not correct\n");
224     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
225     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
226
227     /* Also test SetColorKey */
228     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
229     ok(DDColorKey.dwColorSpaceLowValue == 0xFF00FF && DDColorKey.dwColorSpaceHighValue == 0xFF00FF,
230        "GetColorKey does not return the colorkey used at surface creation\n");
231
232     DDColorKey.dwColorSpaceLowValue = 0x00FF00;
233     DDColorKey.dwColorSpaceHighValue = 0x00FF00;
234     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
235
236     DDColorKey.dwColorSpaceLowValue = 0;
237     DDColorKey.dwColorSpaceHighValue = 0;
238     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
239     ok(DDColorKey.dwColorSpaceLowValue == 0x00FF00 && DDColorKey.dwColorSpaceHighValue == 0x00FF00,
240        "GetColorKey does not return the colorkey set with SetColorKey\n");
241
242     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
243     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
244     IDirectDrawSurface_GetSurfaceDesc(lpSrc, &ddsd);
245     ok(ddsd.ddckCKSrcBlt.dwColorSpaceLowValue == 0x00FF00 && ddsd.ddckCKSrcBlt.dwColorSpaceHighValue == 0x00FF00,
246        "GetSurfaceDesc does not return the colorkey set with SetColorKey\n");
247
248     IDirectDrawSurface_Release(lpSrc);
249     IDirectDrawSurface_Release(lpDst);
250 }
251
252 static void QueryInterface(void)
253 {
254     LPDIRECTDRAWSURFACE dsurface;
255     DDSURFACEDESC surface;
256     LPVOID object;
257     HRESULT ret;
258
259     /* Create a surface */
260     ZeroMemory(&surface, sizeof(surface));
261     surface.dwSize = sizeof(surface);
262     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
263     surface.dwHeight = 10;
264     surface.dwWidth = 10;
265     ret = IDirectDraw_CreateSurface(lpDD, &surface, &dsurface, NULL);
266     if(ret != DD_OK)
267     {
268         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
269         return;
270     }
271
272     /* Call IUnknown::QueryInterface */
273     ret = IDirectDrawSurface_QueryInterface(dsurface, 0, &object);
274     ok(ret == DDERR_INVALIDPARAMS, "IDirectDrawSurface::QueryInterface returned %x\n", ret);
275
276     IDirectDrawSurface_Release(dsurface);
277 }
278
279 START_TEST(dsurface)
280 {
281     if (!CreateDirectDraw())
282         return;
283     MipMapCreationTest();
284     SrcColorKey32BlitTest();
285     QueryInterface();
286     ReleaseDirectDraw();
287 }