janitorial: Remove remaining NULL checks before free() (found by Smatch).
[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: %lx\n", rc);
35     if (!lpDD) {
36         trace("DirectDrawCreateEx() failed with an error %lx\n", rc);
37         return FALSE;
38     }
39
40     rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
41     ok(rc==DD_OK,"SetCooperativeLevel returned: %lx\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: %lx\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: %lx\n",rc);
79     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
80         "GetSurfaceDesc returned no mipmapcount.\n");
81     ok(U2(ddsd).dwMipMapCount == 3, "Incorrect mipmap count: %ld.\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: %lx\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: %lx\n",rc);
105     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
106         "GetSurfaceDesc returned no mipmapcount.\n");
107     ok(U2(ddsd).dwMipMapCount == 1, "Incorrect mipmap count: %ld.\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: %lx\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: %lx\n",rc);
131     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
132         "GetSurfaceDesc returned no mipmapcount.\n");
133     ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %ld.\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: %lx\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: %lx\n",rc);
155     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
156         "GetSurfaceDesc returned no mipmapcount.\n");
157     ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %ld.\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     LPDWORD lpData;
171     HRESULT rc;
172
173     ddsd2.dwSize = sizeof(ddsd2);
174     ddsd2.ddpfPixelFormat.dwSize = sizeof(ddsd2.ddpfPixelFormat);
175
176     ddsd.dwSize = sizeof(ddsd);
177     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
178     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
179     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
180     ddsd.dwWidth = 800;
181     ddsd.dwHeight = 600;
182     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
183     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
184     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
185     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
186     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
187     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDst, NULL);
188     ok(rc==DD_OK,"CreateSurface returned: %lx\n",rc);
189
190     ddsd.dwFlags |= DDSD_CKSRCBLT;
191     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0xFF00FF;
192     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0xFF00FF;
193     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL);
194     ok(rc==DD_OK,"CreateSurface returned: %lx\n",rc);
195     
196     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
197     ok(rc==DD_OK,"Lock returned: %lx\n",rc);
198     lpData = (LPDWORD)ddsd2.lpSurface;
199     lpData[0] = 0xCCCCCCCC;
200     lpData[1] = 0xCCCCCCCC;
201     lpData[2] = 0xCCCCCCCC;
202     lpData[3] = 0xCCCCCCCC;
203     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
204     ok(rc==DD_OK,"Unlock returned: %lx\n",rc);
205
206     rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
207     ok(rc==DD_OK,"Lock returned: %lx\n",rc);
208     lpData = (LPDWORD)ddsd2.lpSurface;
209     lpData[0] = 0x77010203;
210     lpData[1] = 0x00010203;
211     lpData[2] = 0x77FF00FF;
212     lpData[3] = 0x00FF00FF;
213     rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
214     ok(rc==DD_OK,"Unlock returned: %lx\n",rc);
215
216     IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, NULL);
217
218     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
219     ok(rc==DD_OK,"Lock returned: %lx\n",rc);
220     lpData = (LPDWORD)ddsd2.lpSurface;
221     ok((lpData[0]==0x77010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0xCCCCCCCC)&&(lpData[3]==0xCCCCCCCC),
222        "Destination data after blitting is not correct\n");
223     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
224     ok(rc==DD_OK,"Unlock returned: %lx\n",rc);
225
226     IDirectDrawSurface_Release(lpSrc);
227     IDirectDrawSurface_Release(lpDst);
228 }
229
230 static void QueryInterface(void)
231 {
232     LPDIRECTDRAWSURFACE dsurface;
233     DDSURFACEDESC surface;
234     LPVOID object;
235     HRESULT ret;
236
237     /* Create a surface */
238     ZeroMemory(&surface, sizeof(surface));
239     surface.dwSize = sizeof(surface);
240     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
241     surface.dwHeight = 10;
242     surface.dwWidth = 10;
243     ret = IDirectDraw_CreateSurface(lpDD, &surface, &dsurface, NULL);
244     if(ret != DD_OK)
245     {
246         ok(FALSE, "IDirectDraw::CreateSurface failed with error %lx\n", ret);
247         return;
248     }
249
250     /* Call IUnknown::QueryInterface */
251     ret = IDirectDrawSurface_QueryInterface(dsurface, 0, &object);
252     ok(ret == DDERR_INVALIDPARAMS, "IDirectDrawSurface::QueryInterface returned %lx\n", ret);
253
254     IDirectDrawSurface_Release(dsurface);
255 }
256
257 START_TEST(dsurface)
258 {
259     if (!CreateDirectDraw())
260         return;
261     MipMapCreationTest();
262     SrcColorKey32BlitTest();
263     QueryInterface();
264     ReleaseDirectDraw();
265 }