[APITESTS] Add tests for opengl32.dll
authorJérôme Gardou <jerome.gardou@reactos.org>
Thu, 22 Nov 2018 17:18:05 +0000 (18:18 +0100)
committerJérôme Gardou <zefklop@users.noreply.github.com>
Sat, 19 Jan 2019 13:23:54 +0000 (14:23 +0100)
Ensure that our SW implementation exposes the same extensions and the same pixel formats than windows.

modules/rostests/apitests/CMakeLists.txt
modules/rostests/apitests/opengl32/CMakeLists.txt [new file with mode: 0644]
modules/rostests/apitests/opengl32/sw_extensions.c [new file with mode: 0644]
modules/rostests/apitests/opengl32/sw_pixelformat.c [new file with mode: 0644]
modules/rostests/apitests/opengl32/testlist.c [new file with mode: 0644]

index 8d4ee48..5bff8ce 100644 (file)
@@ -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 (file)
index 0000000..6fddd12
--- /dev/null
@@ -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 (file)
index 0000000..3329645
--- /dev/null
@@ -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 <windows.h>
+#include <wingdi.h>
+#include <GL/gl.h>
+
+#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 (file)
index 0000000..ffb3d4d
--- /dev/null
@@ -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 <windows.h>
+#include <wingdi.h>
+#include <GL/gl.h>
+#include <stdio.h>
+
+#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 (file)
index 0000000..2110503
--- /dev/null
@@ -0,0 +1,15 @@
+#define __ROS_LONG64__
+
+#define STANDALONE
+#include <wine/test.h>
+
+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 }
+};