From bb8a3f4e097bd08169f0d2027259d7bc6bd1b926 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Thu, 22 Nov 2018 18:18:05 +0100 Subject: [PATCH] [APITESTS] Add tests for opengl32.dll Ensure that our SW implementation exposes the same extensions and the same pixel formats than windows. --- modules/rostests/apitests/CMakeLists.txt | 1 + .../rostests/apitests/opengl32/CMakeLists.txt | 6 + .../apitests/opengl32/sw_extensions.c | 78 ++++ .../apitests/opengl32/sw_pixelformat.c | 395 ++++++++++++++++++ modules/rostests/apitests/opengl32/testlist.c | 15 + 5 files changed, 495 insertions(+) create mode 100644 modules/rostests/apitests/opengl32/CMakeLists.txt create mode 100644 modules/rostests/apitests/opengl32/sw_extensions.c create mode 100644 modules/rostests/apitests/opengl32/sw_pixelformat.c create mode 100644 modules/rostests/apitests/opengl32/testlist.c diff --git a/modules/rostests/apitests/CMakeLists.txt b/modules/rostests/apitests/CMakeLists.txt index 8d4ee4834b8..5bff8ce7604 100644 --- a/modules/rostests/apitests/CMakeLists.txt +++ b/modules/rostests/apitests/CMakeLists.txt @@ -26,6 +26,7 @@ add_subdirectory(netapi32) add_subdirectory(netshell) add_subdirectory(ntdll) add_subdirectory(ole32) +add_subdirectory(opengl32) add_subdirectory(pefile) add_subdirectory(powrprof) add_subdirectory(sdk) diff --git a/modules/rostests/apitests/opengl32/CMakeLists.txt b/modules/rostests/apitests/opengl32/CMakeLists.txt new file mode 100644 index 00000000000..6fddd120e1e --- /dev/null +++ b/modules/rostests/apitests/opengl32/CMakeLists.txt @@ -0,0 +1,6 @@ + +add_executable(opengl32_apitest sw_extensions.c sw_pixelformat.c testlist.c) +target_link_libraries(opengl32_apitest wine) +set_module_type(opengl32_apitest win32cui) +add_importlibs(opengl32_apitest opengl32 gdi32 user32 msvcrt kernel32) +add_rostests_file(TARGET opengl32_apitest) diff --git a/modules/rostests/apitests/opengl32/sw_extensions.c b/modules/rostests/apitests/opengl32/sw_extensions.c new file mode 100644 index 00000000000..3329645ae43 --- /dev/null +++ b/modules/rostests/apitests/opengl32/sw_extensions.c @@ -0,0 +1,78 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: BSD - See COPYING.ARM in the top level directory + * PURPOSE: Tests extensions exposed by the software implementation + * PROGRAMMERS: Jérôme Gardou + */ + +#include +#include +#include + +#include "wine/test.h" + +START_TEST(sw_extensions) +{ + BITMAPINFO biDst; + HDC hdcDst = CreateCompatibleDC(0); + HBITMAP bmpDst, bmpOld; + INT nFormats, iPixelFormat, res, i; + PIXELFORMATDESCRIPTOR pfd; + const char* output; + HGLRC Context; + UINT *dstBuffer = NULL; + + memset(&biDst, 0, sizeof(BITMAPINFO)); + biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + biDst.bmiHeader.biWidth = 4; + biDst.bmiHeader.biHeight = -4; + biDst.bmiHeader.biPlanes = 1; + biDst.bmiHeader.biBitCount = 32; + biDst.bmiHeader.biCompression = BI_RGB; + + bmpDst = CreateDIBSection(0, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0); + + bmpOld = SelectObject(hdcDst, bmpDst); + + /* Choose a pixel format */ + nFormats = DescribePixelFormat(hdcDst, 0, 0, NULL); + for(i=1; i<=nFormats; i++) + { + memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); + DescribePixelFormat(hdcDst, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + if((pfd.dwFlags & PFD_DRAW_TO_BITMAP) && + (pfd.dwFlags & PFD_SUPPORT_OPENGL) && + (pfd.cColorBits == 32) && + (pfd.cAlphaBits == 8) ) + { + iPixelFormat = i; + break; + } + } + + ok(pfd.dwFlags & PFD_GENERIC_FORMAT, "We found a pixel format for drawing to bitmap which is not generic !\n"); + ok (iPixelFormat >= 1 && iPixelFormat <= nFormats, "Could not find a suitable pixel format.\n"); + res = SetPixelFormat(hdcDst, iPixelFormat, &pfd); + ok (res != 0, "SetPixelFormat failed.\n"); + Context = wglCreateContext(hdcDst); + ok(Context != NULL, "We failed to create a GL context.\n"); + wglMakeCurrent(hdcDst, Context); + + /* Get the version */ + output = (const char*)glGetString(GL_VERSION); + ok(strcmp(output, "1.1.0") == 0, "Expected version 1.1.0, got \"%s\".\n", output); + + /* Get the extensions list */ + output = (const char*)glGetString(GL_EXTENSIONS); + trace("GL extensions are %s.\n", output); + ok (strlen(output) == strlen("GL_WIN_swap_hint GL_EXT_bgra GL_EXT_paletted_texture"), "Wrong extension list : \"%s\".\n", output); + ok(strstr(output, "GL_WIN_swap_hint") != NULL, "GL_WIN_swap_hint extension is not present.\n"); + ok(strstr(output, "GL_EXT_bgra") != NULL, "GL_EXT_bgra extension is not present.\n"); + ok(strstr(output, "GL_EXT_paletted_texture") != NULL, "GL_EXT_paletted_texture extension is not present.\n"); + + /* cleanup */ + wglDeleteContext(Context); + SelectObject(hdcDst, bmpOld); + DeleteDC(hdcDst); +} diff --git a/modules/rostests/apitests/opengl32/sw_pixelformat.c b/modules/rostests/apitests/opengl32/sw_pixelformat.c new file mode 100644 index 00000000000..ffb3d4d1a23 --- /dev/null +++ b/modules/rostests/apitests/opengl32/sw_pixelformat.c @@ -0,0 +1,395 @@ +/* + * 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); +} diff --git a/modules/rostests/apitests/opengl32/testlist.c b/modules/rostests/apitests/opengl32/testlist.c new file mode 100644 index 00000000000..21105035fea --- /dev/null +++ b/modules/rostests/apitests/opengl32/testlist.c @@ -0,0 +1,15 @@ +#define __ROS_LONG64__ + +#define STANDALONE +#include + +extern void func_sw_extensions(void); +extern void func_sw_pixelformat(void); + +const struct test winetest_testlist[] = +{ + { "sw_extensions", func_sw_extensions }, + { "sw_pixelformat", func_sw_pixelformat }, + + { 0, 0 } +}; -- 2.17.1