/* * PROJECT: ReactOS api tests * LICENSE: BSD - See COPYING.ARM in the top level directory * PURPOSE: Tests pixel formats exposed by the software implementation * PROGRAMMERS: Jérôme Gardou */ #include #include #include #include #include "wine/test.h" static char* str_dbg_pfd_flags(DWORD flags) { static char buffer[1000]; static char *p = buffer; char* ret; BOOL first = TRUE; if (p > &buffer[800]) p = buffer; *p = 0; #define FLAGS_TO_STR(__x__) \ do { \ if (flags & __x__) \ { \ if (!first) strcat(p, " | "); \ strcat(p, #__x__); \ first = FALSE; \ flags &= ~((DWORD)__x__); \ } \ } while(0) FLAGS_TO_STR(PFD_DOUBLEBUFFER); FLAGS_TO_STR(PFD_STEREO); FLAGS_TO_STR(PFD_DRAW_TO_WINDOW); FLAGS_TO_STR(PFD_DRAW_TO_BITMAP); FLAGS_TO_STR(PFD_SUPPORT_GDI); FLAGS_TO_STR(PFD_SUPPORT_OPENGL); FLAGS_TO_STR(PFD_GENERIC_FORMAT); FLAGS_TO_STR(PFD_NEED_PALETTE); FLAGS_TO_STR(PFD_NEED_SYSTEM_PALETTE); FLAGS_TO_STR(PFD_SWAP_EXCHANGE); FLAGS_TO_STR(PFD_SWAP_COPY); FLAGS_TO_STR(PFD_SWAP_LAYER_BUFFERS); FLAGS_TO_STR(PFD_GENERIC_ACCELERATED); FLAGS_TO_STR(PFD_SUPPORT_COMPOSITION); #undef FLAGS_TO_STR if (flags) { char tmp[16]; sprintf(tmp, " | 0x%08x", (UINT)flags); strcat(p, tmp); } ret = p; p += strlen(p) + 1; return ret; } struct test_color { BYTE iPixelType; BYTE cColorBits; BYTE cRedBits; BYTE cRedShift; BYTE cGreenBits; BYTE cGreenShift; BYTE cBlueBits; BYTE cBlueShift; BYTE cAlphaBits; BYTE cAlphaShift; BYTE cAccumBits; BYTE cAccumRedBits; BYTE cAccumGreenBits; BYTE cAccumBlueBits; BYTE cAccumAlphaBits; }; static const struct test_color test_colors_32[] = { {PFD_TYPE_RGBA, 32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0}, {PFD_TYPE_RGBA, 32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16}, {PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0}, }; static const struct test_color test_colors_24[] = { {PFD_TYPE_RGBA, 24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0}, {PFD_TYPE_RGBA, 24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16}, {PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0}, }; static const struct test_color test_colors_16[] = { {PFD_TYPE_RGBA, 16, 5, 10, 5, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0}, {PFD_TYPE_RGBA, 16, 5, 10, 5, 5, 5, 0, 8, 0, 32, 8, 8, 8, 8}, {PFD_TYPE_COLORINDEX, 16, 5, 10, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0}, }; static const struct test_color test_colors_16_565[] = { {PFD_TYPE_RGBA, 16, 5, 11, 6, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0}, {PFD_TYPE_RGBA, 16, 5, 11, 6, 5, 5, 0, 8, 0, 32, 8, 8, 8, 8}, {PFD_TYPE_COLORINDEX, 16, 5, 11, 6, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0}, }; static const struct test_color test_colors_8[] = { {PFD_TYPE_RGBA, 8, 3, 0, 3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0}, {PFD_TYPE_RGBA, 8, 3, 0, 3, 3, 2, 6, 8, 0, 32, 8, 8, 8, 8}, {PFD_TYPE_COLORINDEX, 8, 3, 0, 3, 3, 2, 6, 0, 0, 0, 0, 0, 0, 0}, }; static const struct test_color test_colors_4[] = { {PFD_TYPE_RGBA, 4, 1, 0, 1, 1, 1, 2, 0, 0, 16, 5, 6, 5, 0}, {PFD_TYPE_RGBA, 4, 1, 0, 1, 1, 1, 2, 8, 0, 16, 4, 4, 4, 4}, {PFD_TYPE_COLORINDEX, 4, 1, 0, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0}, }; static const struct test_color* test_colors_32bpp[] = {test_colors_32, test_colors_24, test_colors_16, test_colors_8, test_colors_4, NULL}; static const struct test_color* test_colors_24bpp[] = {test_colors_24, test_colors_32, test_colors_16, test_colors_8, test_colors_4, NULL}; 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}; static const struct test_color* test_colors_8bpp[] = {test_colors_8, test_colors_24, test_colors_32, test_colors_16, test_colors_4, NULL}; static const BYTE test_depths[] = { 32, 16 }; 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) { PIXELFORMATDESCRIPTOR pfd; int ret; ret = DescribePixelFormat(hdc, pf, sizeof(pfd), &pfd); ok(ret == num_pf, "Number of pixel formats changed!\n"); ok(pfd.nSize == sizeof(pfd), "Wrong nSize for format %i, expected %u, got %u\n", pf, (WORD)sizeof(pfd), pfd.nSize); ok(pfd.nVersion == 1, "Wrong nVersion for format %i, expected 1, got %u\n", pf, pfd.nVersion); if (is_window) { DWORD flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT; if ((pfd.cColorBits <= 8) && (pfd.iPixelType == PFD_TYPE_RGBA)) flags |= PFD_NEED_PALETTE; if (is_double_buffered) { flags |= PFD_DOUBLEBUFFER | PFD_SWAP_COPY; } else { flags |= PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI; } ok((pfd.dwFlags == flags) || (pfd.dwFlags == (flags | PFD_SUPPORT_COMPOSITION)), "Wrong dwFlags for format %i, expected %s (0x%08x), got %s(0x%08x)\n", pf, str_dbg_pfd_flags(flags), (UINT)flags, str_dbg_pfd_flags(pfd.dwFlags), (UINT)pfd.dwFlags); } else { ok(pfd.dwFlags == (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT), "Wrong dwFlags for format %i, expected PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT, got %s\n", pf, str_dbg_pfd_flags(pfd.dwFlags)); } #define TEST_FIELD(__x__) ok(pfd.__x__ == colors->__x__, "Wrong " #__x__ " for format %i, expected %u, got %u\n", pf, colors->__x__, pfd.__x__) TEST_FIELD(iPixelType); TEST_FIELD(cColorBits); TEST_FIELD(cRedBits); TEST_FIELD(cRedShift); TEST_FIELD(cGreenBits); TEST_FIELD(cGreenShift); TEST_FIELD(cBlueBits); TEST_FIELD(cBlueShift); TEST_FIELD(cAlphaBits); TEST_FIELD(cAlphaShift); TEST_FIELD(cAccumBits); TEST_FIELD(cAccumRedBits); TEST_FIELD(cAccumGreenBits); TEST_FIELD(cAccumBlueBits); TEST_FIELD(cAccumAlphaBits); #undef TEST_FIELD ok(pfd.cDepthBits == depth, "Wrong cDepthBit for format %i, expected %u, got %u\n", pf, depth, pfd.cDepthBits); /* the rest is constant */ #define TEST_FIELD(__x__, __y__) ok(pfd.__x__ == __y__, "Wrong " #__x__ " for format %i, expected " #__y__ ", got %u\n", pf, (UINT)pfd.__x__) TEST_FIELD(cStencilBits, 8); TEST_FIELD(cAuxBuffers, 0); TEST_FIELD(iLayerType, 0); TEST_FIELD(bReserved, 0); TEST_FIELD(dwLayerMask, 0); TEST_FIELD(dwVisibleMask, 0); TEST_FIELD(dwDamageMask, 0); #undef TEST_FIELD } static void test_screen_colors(const struct test_color **colors) { int pf, num_pf, ret; int i, j; HDC hdc; HWND hwnd; PIXELFORMATDESCRIPTOR pfd; hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW, 10, 10, 200, 200, NULL, NULL, NULL, NULL); if (!hwnd) { ok(hwnd != NULL, "Failed to create a window.\n"); return; } hdc = GetDC( hwnd ); num_pf = DescribePixelFormat(hdc, 0, 0, NULL); ok(num_pf > 0, "DescribePixelFormat failed.\n"); for (pf = 1; pf <= num_pf; pf++) { ret = DescribePixelFormat(hdc, pf, sizeof(pfd), &pfd); ok(ret == num_pf, "Number of pixel formats changed!\n"); if (pfd.dwFlags & PFD_GENERIC_FORMAT) break; } ok(pf < num_pf, "No generic pixel format!\n"); /* First the formats compatible with the DC */ for (i = 0; i < 3; i++) { /* Single buffered first */ for (j = 0; j < ARRAY_SIZE(test_depths); j++) { test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], TRUE, FALSE); } /* Then double buffered */ for (j = 0; j < ARRAY_SIZE(test_depths); j++) { test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], TRUE, TRUE); } } colors++; /* Then the rest */ while (*colors) { for (i = 0; i < 3; i++) { for (j = 0; j < ARRAY_SIZE(test_depths); j++) { test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], FALSE, FALSE); } } colors++; } /* We must have tested all generic formats. */ ok(pf - 1 == num_pf, "We didn't test all generic formats : tested %u, total %u.\n", pf, num_pf); ReleaseDC( hwnd, hdc ); DestroyWindow( hwnd ); } static HBITMAP create_dib_section(WORD bpp, void** dstBuffer) { BITMAPINFO bi; memset(&bi, 0, sizeof(BITMAPINFO)); bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biWidth = 4; bi.bmiHeader.biHeight = -4; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = bpp; bi.bmiHeader.biCompression = BI_RGB; return CreateDIBSection(0, &bi, DIB_RGB_COLORS, dstBuffer, NULL, 0); } static void test_bitmap_colors(HDC hdc, const struct test_color** colors) { INT num_pf, pf, ret; PIXELFORMATDESCRIPTOR pfd; INT i, j; num_pf = DescribePixelFormat(hdc, 0, 0, NULL); ok(num_pf > 0, "DescribePixelFormat failed.\n"); for (pf = 1; pf <= num_pf; pf++) { ret = DescribePixelFormat(hdc, pf, sizeof(pfd), &pfd); ok(ret == num_pf, "Number of pixel formats changed!\n"); if (pfd.dwFlags & PFD_GENERIC_FORMAT) break; } ok(pf < num_pf, "No generic pixel format!\n"); /* First the formats compatible with the DC */ for (i = 0; i < 3; i++) { /* Single buffered first */ for (j = 0; j < ARRAY_SIZE(test_depths); j++) { test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], TRUE, FALSE); } /* Then double buffered */ for (j = 0; j < ARRAY_SIZE(test_depths); j++) { test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], TRUE, TRUE); } } colors++; /* Then the rest */ while (*colors) { for (i = 0; i < 3; i++) { for (j = 0; j < ARRAY_SIZE(test_depths); j++) { test_format(hdc, num_pf, pf++, &colors[0][i], test_depths[j], FALSE, FALSE); } } colors++; } /* We must have tested all generic formats. */ ok(pf - 1 == num_pf, "We didn't test all generic formats : tested %u, total %u.\n", pf, num_pf); } static void test_bitmap_formats(const struct test_color ** colors) { HBITMAP oldBmp, dib; HDC hdc; static const INT bpps [] = {4, 8, 16, 24, 32}; INT i; void* dib_buffer; hdc = CreateCompatibleDC(NULL); ok (hdc != NULL, "Failed creating a memory DC.\n"); for (i = 0; i < ARRAY_SIZE(bpps); i++) { dib = create_dib_section(bpps[i], &dib_buffer); ok(dib != NULL, "Failed to create DIB for %u bpp\n", bpps[i]); oldBmp = SelectObject(hdc, dib); ok (oldBmp != NULL, "Failed to select the DIB\n"); trace("testing DIB %ubpp\n", bpps[i]); /* For mem DC, this is always the depth of the screen which is taken into account */ test_bitmap_colors(hdc, colors); SelectObject(hdc, oldBmp); DeleteObject(dib); } } START_TEST(sw_pixelformat) { DEVMODEW devMode; INT ret; DWORD orig_bpp; static const WORD bit_depths[] = {8, 16, 24, 32}; static const struct test_color** colors[] = {test_colors_8bpp, test_colors_16bpp, test_colors_24bpp, test_colors_32bpp}; INT i; ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devMode); ok (ret != 0, "EnumDisplaySettings failed.\n"); orig_bpp = devMode.dmBitsPerPel; for (i = 0; i < ARRAY_SIZE(bit_depths); i++) { devMode.dmBitsPerPel = bit_depths[i]; ret = ChangeDisplaySettingsExW(NULL, &devMode, NULL, 0, NULL); if (ret == DISP_CHANGE_SUCCESSFUL) { trace("Testing %ubpp\n", bit_depths[i]); test_screen_colors(colors[i]); test_bitmap_formats(colors[i]); } else { skip("Unable to switch to %ubpp\n", bit_depths[i]); } } devMode.dmBitsPerPel = orig_bpp; ret = ChangeDisplaySettingsExW(NULL, &devMode, NULL, 0, NULL); }