1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * PURPOSE: Tests pixel formats exposed by the software implementation
5 * PROGRAMMERS: J�r�me Gardou
6 */
7
8 #include <windows.h>
9 #include <wingdi.h>
10 #include <GL/gl.h>
11 #include <stdio.h>
12
13 #include "wine/test.h"
14
str_dbg_pfd_flags(DWORD flags)15 static char* str_dbg_pfd_flags(DWORD flags)
16 {
17 static char buffer[1000];
18 static char *p = buffer;
19 char* ret;
20
21 BOOL first = TRUE;
22
23 if (p > &buffer[800])
24 p = buffer;
25
26 *p = 0;
27
28 #define FLAGS_TO_STR(__x__) \
29 do { \
30 if (flags & __x__) \
31 { \
32 if (!first) strcat(p, " | "); \
33 strcat(p, #__x__); \
34 first = FALSE; \
35 flags &= ~((DWORD)__x__); \
36 } \
37 } while(0)
38
39 FLAGS_TO_STR(PFD_DOUBLEBUFFER);
40 FLAGS_TO_STR(PFD_STEREO);
41 FLAGS_TO_STR(PFD_DRAW_TO_WINDOW);
42 FLAGS_TO_STR(PFD_DRAW_TO_BITMAP);
43 FLAGS_TO_STR(PFD_SUPPORT_GDI);
44 FLAGS_TO_STR(PFD_SUPPORT_OPENGL);
45 FLAGS_TO_STR(PFD_GENERIC_FORMAT);
46 FLAGS_TO_STR(PFD_NEED_PALETTE);
47 FLAGS_TO_STR(PFD_NEED_SYSTEM_PALETTE);
48 FLAGS_TO_STR(PFD_SWAP_EXCHANGE);
49 FLAGS_TO_STR(PFD_SWAP_COPY);
50 FLAGS_TO_STR(PFD_SWAP_LAYER_BUFFERS);
51 FLAGS_TO_STR(PFD_GENERIC_ACCELERATED);
52 FLAGS_TO_STR(PFD_SUPPORT_COMPOSITION);
53 #undef FLAGS_TO_STR
54
55 if (flags)
56 {
57 char tmp[16];
58 sprintf(tmp, " | 0x%08x", (UINT)flags);
59 strcat(p, tmp);
60 }
61
62 ret = p;
63
64 p += strlen(p) + 1;
65
66 return ret;
67 }
68
69 struct test_color
70 {
71 BYTE iPixelType;
72 BYTE cColorBits;
73 BYTE cRedBits; BYTE cRedShift;
74 BYTE cGreenBits; BYTE cGreenShift;
75 BYTE cBlueBits; BYTE cBlueShift;
76 BYTE cAlphaBits; BYTE cAlphaShift;
77 BYTE cAccumBits;
78 BYTE cAccumRedBits; BYTE cAccumGreenBits; BYTE cAccumBlueBits; BYTE cAccumAlphaBits;
79 };
80
81 static const struct test_color test_colors_32[] =
82 {
83 {PFD_TYPE_RGBA, 32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0},
84 {PFD_TYPE_RGBA, 32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16},
85 {PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0},
86 };
87
88 static const struct test_color test_colors_24[] =
89 {
90 {PFD_TYPE_RGBA, 24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0},
91 {PFD_TYPE_RGBA, 24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16},
92 {PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0},
93 };
94
95 static const struct test_color test_colors_16[] =
96 {
97 {PFD_TYPE_RGBA, 16, 5, 10, 5, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0},
98 {PFD_TYPE_RGBA, 16, 5, 10, 5, 5, 5, 0, 8, 0, 32, 8, 8, 8, 8},
99 {PFD_TYPE_COLORINDEX, 16, 5, 10, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0},
100 };
101
102 static const struct test_color test_colors_16_565[] =
103 {
104 {PFD_TYPE_RGBA, 16, 5, 11, 6, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0},
105 {PFD_TYPE_RGBA, 16, 5, 11, 6, 5, 5, 0, 8, 0, 32, 8, 8, 8, 8},
106 {PFD_TYPE_COLORINDEX, 16, 5, 11, 6, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0},
107 };
108
109 static const struct test_color test_colors_8[] =
110 {
111 {PFD_TYPE_RGBA, 8, 3, 0, 3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0},
112 {PFD_TYPE_RGBA, 8, 3, 0, 3, 3, 2, 6, 8, 0, 32, 8, 8, 8, 8},
113 {PFD_TYPE_COLORINDEX, 8, 3, 0, 3, 3, 2, 6, 0, 0, 0, 0, 0, 0, 0},
114 };
115
116 static const struct test_color test_colors_4[] =
117 {
118 {PFD_TYPE_RGBA, 4, 1, 0, 1, 1, 1, 2, 0, 0, 16, 5, 6, 5, 0},
119 {PFD_TYPE_RGBA, 4, 1, 0, 1, 1, 1, 2, 8, 0, 16, 4, 4, 4, 4},
120 {PFD_TYPE_COLORINDEX, 4, 1, 0, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0},
121 };
122
123 static const struct test_color* test_colors_32bpp[] = {test_colors_32, test_colors_24, test_colors_16, test_colors_8, test_colors_4, NULL};
124 static const struct test_color* test_colors_24bpp[] = {test_colors_24, test_colors_32, test_colors_16, test_colors_8, test_colors_4, NULL};
125 static const struct test_color* test_colors_16bpp[] = {test_colors_16_565, test_colors_24, test_colors_32, test_colors_8, test_colors_4, NULL};
126 static const struct test_color* test_colors_8bpp[] = {test_colors_8, test_colors_24, test_colors_32, test_colors_16, test_colors_4, NULL};
127
128 static const BYTE test_depths[] = { 32, 16 };
129
test_format(HDC hdc,int num_pf,int pf,const struct test_color * colors,BYTE depth,BOOL is_window,BOOL is_double_buffered)130 static void test_format(HDC hdc, int num_pf, int pf, const struct test_color *colors, BYTE depth, BOOL is_window, BOOL is_double_buffered)
131 {
132 PIXELFORMATDESCRIPTOR pfd;
133 int ret;
134
135 ret = DescribePixelFormat(hdc, pf, sizeof(pfd), &pfd);
136 ok(ret == num_pf, "Number of pixel formats changed!\n");
137
138 ok(pfd.nSize == sizeof(pfd), "Wrong nSize for format %i, expected %u, got %u\n", pf, (WORD)sizeof(pfd), pfd.nSize);
139 ok(pfd.nVersion == 1, "Wrong nVersion for format %i, expected 1, got %u\n", pf, pfd.nVersion);
140 if (is_window)
141 {
142 DWORD flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT;
143
144 if ((pfd.cColorBits <= 8) && (pfd.iPixelType == PFD_TYPE_RGBA))
145 flags |= PFD_NEED_PALETTE;
146
147 if (is_double_buffered)
148 {
149 flags |= PFD_DOUBLEBUFFER | PFD_SWAP_COPY;
150 }
151 else
152 {
153 flags |= PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI;
154 }
155 ok((pfd.dwFlags == flags) || (pfd.dwFlags == (flags | PFD_SUPPORT_COMPOSITION)),
156 "Wrong dwFlags for format %i, expected %s (0x%08x), got %s(0x%08x)\n",
157 pf, str_dbg_pfd_flags(flags), (UINT)flags, str_dbg_pfd_flags(pfd.dwFlags), (UINT)pfd.dwFlags);
158 }
159 else
160 {
161 ok(pfd.dwFlags == (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT),
162 "Wrong dwFlags for format %i, expected PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT, got %s\n",
163 pf, str_dbg_pfd_flags(pfd.dwFlags));
164 }
165
166 #define TEST_FIELD(__x__) ok(pfd.__x__ == colors->__x__, "Wrong " #__x__ " for format %i, expected %u, got %u\n", pf, colors->__x__, pfd.__x__)
167 TEST_FIELD(iPixelType);
168 TEST_FIELD(cColorBits);
169 TEST_FIELD(cRedBits);
170 TEST_FIELD(cRedShift);
171 TEST_FIELD(cGreenBits);
172 TEST_FIELD(cGreenShift);
173 TEST_FIELD(cBlueBits);
174 TEST_FIELD(cBlueShift);
175 TEST_FIELD(cAlphaBits);
176 TEST_FIELD(cAlphaShift);
177 TEST_FIELD(cAccumBits);
178 TEST_FIELD(cAccumRedBits);
179 TEST_FIELD(cAccumGreenBits);
180 TEST_FIELD(cAccumBlueBits);
181 TEST_FIELD(cAccumAlphaBits);
182 #undef TEST_FIELD
183 ok(pfd.cDepthBits == depth, "Wrong cDepthBit for format %i, expected %u, got %u\n", pf, depth, pfd.cDepthBits);
184
185 /* the rest is constant */
186 #define TEST_FIELD(__x__, __y__) ok(pfd.__x__ == __y__, "Wrong " #__x__ " for format %i, expected " #__y__ ", got %u\n", pf, (UINT)pfd.__x__)
187 TEST_FIELD(cStencilBits, 8);
188 TEST_FIELD(cAuxBuffers, 0);
189 TEST_FIELD(iLayerType, 0);
190 TEST_FIELD(bReserved, 0);
191 TEST_FIELD(dwLayerMask, 0);
192 TEST_FIELD(dwVisibleMask, 0);
193 TEST_FIELD(dwDamageMask, 0);
194 #undef TEST_FIELD
195 }
196
test_screen_colors(const struct test_color ** colors)197 static void test_screen_colors(const struct test_color **colors)
198 {
199 int pf, num_pf, ret;
200 int i, j;
201 HDC hdc;
202 HWND hwnd;
203 PIXELFORMATDESCRIPTOR pfd;
204
205 hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW, 10, 10, 200, 200, NULL, NULL,
206 NULL, NULL);
207 if (!hwnd)
208 {
209 ok(hwnd != NULL, "Failed to create a window.\n");
210 return;
211 }
212
213 hdc = GetDC( hwnd );
214 num_pf = DescribePixelFormat(hdc, 0, 0, NULL);
215 ok(num_pf > 0, "DescribePixelFormat failed.\n");
216
217 for (pf = 1; pf <= num_pf; pf++)
218 {
219 ret = DescribePixelFormat(hdc, pf, sizeof(pfd), &pfd);
220 ok(ret == num_pf, "Number of pixel formats changed!\n");
221
222 if (pfd.dwFlags & PFD_GENERIC_FORMAT)
223 break;
224 }
225
226 ok(pf < num_pf, "No generic pixel format!\n");
227
228 /* First the formats compatible with the DC */
229 for (i = 0; i < 3; i++)
230 {
231 /* Single buffered first */
232 for (j = 0; j < ARRAY_SIZE(test_depths); j++)
233 {
234 test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], TRUE, FALSE);
235 }
236
237 /* Then double buffered */
238 for (j = 0; j < ARRAY_SIZE(test_depths); j++)
239 {
240 test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], TRUE, TRUE);
241 }
242 }
243
244 colors++;
245
246 /* Then the rest */
247 while (*colors)
248 {
249 for (i = 0; i < 3; i++)
250 {
251 for (j = 0; j < ARRAY_SIZE(test_depths); j++)
252 {
253 test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], FALSE, FALSE);
254 }
255 }
256 colors++;
257 }
258
259 /* We must have tested all generic formats. */
260 ok(pf - 1 == num_pf, "We didn't test all generic formats : tested %u, total %u.\n", pf, num_pf);
261
262 ReleaseDC( hwnd, hdc );
263 DestroyWindow( hwnd );
264 }
265
create_dib_section(WORD bpp,void ** dstBuffer)266 static HBITMAP create_dib_section(WORD bpp, void** dstBuffer)
267 {
268 BITMAPINFO bi;
269
270 memset(&bi, 0, sizeof(BITMAPINFO));
271 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
272 bi.bmiHeader.biWidth = 4;
273 bi.bmiHeader.biHeight = -4;
274 bi.bmiHeader.biPlanes = 1;
275 bi.bmiHeader.biBitCount = bpp;
276 bi.bmiHeader.biCompression = BI_RGB;
277
278 return CreateDIBSection(0, &bi, DIB_RGB_COLORS, dstBuffer, NULL, 0);
279 }
280
test_bitmap_colors(HDC hdc,const struct test_color ** colors)281 static void test_bitmap_colors(HDC hdc, const struct test_color** colors)
282 {
283 INT num_pf, pf, ret;
284 PIXELFORMATDESCRIPTOR pfd;
285 INT i, j;
286
287 num_pf = DescribePixelFormat(hdc, 0, 0, NULL);
288 ok(num_pf > 0, "DescribePixelFormat failed.\n");
289
290 for (pf = 1; pf <= num_pf; pf++)
291 {
292 ret = DescribePixelFormat(hdc, pf, sizeof(pfd), &pfd);
293 ok(ret == num_pf, "Number of pixel formats changed!\n");
294
295 if (pfd.dwFlags & PFD_GENERIC_FORMAT)
296 break;
297 }
298
299 ok(pf < num_pf, "No generic pixel format!\n");
300
301 /* First the formats compatible with the DC */
302 for (i = 0; i < 3; i++)
303 {
304 /* Single buffered first */
305 for (j = 0; j < ARRAY_SIZE(test_depths); j++)
306 {
307 test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], TRUE, FALSE);
308 }
309
310 /* Then double buffered */
311 for (j = 0; j < ARRAY_SIZE(test_depths); j++)
312 {
313 test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], TRUE, TRUE);
314 }
315 }
316
317 colors++;
318
319 /* Then the rest */
320 while (*colors)
321 {
322 for (i = 0; i < 3; i++)
323 {
324 for (j = 0; j < ARRAY_SIZE(test_depths); j++)
325 {
326 test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], FALSE, FALSE);
327 }
328 }
329 colors++;
330 }
331
332 /* We must have tested all generic formats. */
333 ok(pf - 1 == num_pf, "We didn't test all generic formats : tested %u, total %u.\n", pf, num_pf);
334 }
335
test_bitmap_formats(const struct test_color ** colors)336 static void test_bitmap_formats(const struct test_color ** colors)
337 {
338 HBITMAP oldBmp, dib;
339 HDC hdc;
340 static const INT bpps [] = {4, 8, 16, 24, 32};
341 INT i;
342 void* dib_buffer;
343
344 hdc = CreateCompatibleDC(NULL);
345 ok (hdc != NULL, "Failed creating a memory DC.\n");
346
347 for (i = 0; i < ARRAY_SIZE(bpps); i++)
348 {
349 dib = create_dib_section(bpps[i], &dib_buffer);
350 ok(dib != NULL, "Failed to create DIB for %u bpp\n", bpps[i]);
351
352 oldBmp = SelectObject(hdc, dib);
353 ok (oldBmp != NULL, "Failed to select the DIB\n");
354
355 trace("testing DIB %ubpp\n", bpps[i]);
356 /* For mem DC, this is always the depth of the screen which is taken into account */
357 test_bitmap_colors(hdc, colors);
358
359 SelectObject(hdc, oldBmp);
360 DeleteObject(dib);
361 }
362 }
363
START_TEST(sw_pixelformat)364 START_TEST(sw_pixelformat)
365 {
366 DEVMODEW devMode;
367 INT ret;
368 DWORD orig_bpp;
369 static const WORD bit_depths[] = {8, 16, 24, 32};
370 static const struct test_color** colors[] = {test_colors_8bpp, test_colors_16bpp, test_colors_24bpp, test_colors_32bpp};
371 INT i;
372
373 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devMode);
374 ok (ret != 0, "EnumDisplaySettings failed.\n");
375 orig_bpp = devMode.dmBitsPerPel;
376
377 for (i = 0; i < ARRAY_SIZE(bit_depths); i++)
378 {
379 devMode.dmBitsPerPel = bit_depths[i];
380 ret = ChangeDisplaySettingsExW(NULL, &devMode, NULL, 0, NULL);
381 if (ret == DISP_CHANGE_SUCCESSFUL)
382 {
383 trace("Testing %ubpp\n", bit_depths[i]);
384 test_screen_colors(colors[i]);
385 test_bitmap_formats(colors[i]);
386 }
387 else
388 {
389 skip("Unable to switch to %ubpp\n", bit_depths[i]);
390 }
391 }
392
393 devMode.dmBitsPerPel = orig_bpp;
394 ret = ChangeDisplaySettingsExW(NULL, &devMode, NULL, 0, NULL);
395 }
396