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