opengl.c 66.8 KB
Newer Older
1 2 3
/*
 * Some tests for OpenGL functions
 *
4
 * Copyright (C) 2007-2008 Roderick Colenbrander
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <windows.h>
#include <wingdi.h>
#include "wine/test.h"
24
#include "wine/wgl.h"
25

26 27 28
#define MAX_FORMATS 256
typedef void* HPBUFFERARB;

29
/* WGL_ARB_create_context */
30
static HGLRC (WINAPI *pwglCreateContextAttribsARB)(HDC hDC, HGLRC hShareContext, const int *attribList);
31

32 33 34 35
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
#define WGL_CONTEXT_FLAGS_ARB 0x2094
36

37 38 39 40
/* Flags for WGL_CONTEXT_FLAGS_ARB */
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB	0x0002

41 42 43 44
/* WGL_ARB_extensions_string */
static const char* (WINAPI *pwglGetExtensionsStringARB)(HDC);
static int (WINAPI *pwglReleasePbufferDCARB)(HPBUFFERARB, HDC);

45 46
/* WGL_ARB_make_current_read */
static BOOL (WINAPI *pwglMakeContextCurrentARB)(HDC hdraw, HDC hread, HGLRC hglrc);
47
static HDC (WINAPI *pwglGetCurrentReadDCARB)(void);
48

49
/* WGL_ARB_pixel_format */
50
#define WGL_ACCELERATION_ARB 0x2003
51 52 53 54 55
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_RED_BITS_ARB   0x2015
#define WGL_GREEN_BITS_ARB 0x2017
#define WGL_BLUE_BITS_ARB  0x2019
#define WGL_ALPHA_BITS_ARB 0x201B
56 57
#define WGL_SUPPORT_GDI_ARB   0x200F
#define WGL_DOUBLE_BUFFER_ARB 0x2011
58 59 60
#define WGL_NO_ACCELERATION_ARB        0x2025
#define WGL_GENERIC_ACCELERATION_ARB   0x2026
#define WGL_FULL_ACCELERATION_ARB      0x2027
61

62
static BOOL (WINAPI *pwglChoosePixelFormatARB)(HDC, const int *, const FLOAT *, UINT, int *, UINT *);
63
static BOOL (WINAPI *pwglGetPixelFormatAttribivARB)(HDC, int, int, UINT, const int *, int *);
64 65 66 67 68 69

/* WGL_ARB_pbuffer */
#define WGL_DRAW_TO_PBUFFER_ARB 0x202D
static HPBUFFERARB* (WINAPI *pwglCreatePbufferARB)(HDC, int, int, int, const int *);
static HDC (WINAPI *pwglGetPbufferDCARB)(HPBUFFERARB);

70 71 72 73
/* WGL_EXT_swap_control */
static BOOL (WINAPI *pwglSwapIntervalEXT)(int interval);
static int (WINAPI *pwglGetSwapIntervalEXT)(void);

74 75 76 77
static const char* wgl_extensions = NULL;

static void init_functions(void)
{
78 79 80 81 82
#define GET_PROC(func) \
    p ## func = (void*)wglGetProcAddress(#func); \
    if(!p ## func) \
      trace("wglGetProcAddress(%s) failed\n", #func);

83 84 85
    /* WGL_ARB_create_context */
    GET_PROC(wglCreateContextAttribsARB);

86
    /* WGL_ARB_extensions_string */
87
    GET_PROC(wglGetExtensionsStringARB)
88

89 90 91 92
    /* WGL_ARB_make_current_read */
    GET_PROC(wglMakeContextCurrentARB);
    GET_PROC(wglGetCurrentReadDCARB);

93
    /* WGL_ARB_pixel_format */
94 95
    GET_PROC(wglChoosePixelFormatARB)
    GET_PROC(wglGetPixelFormatAttribivARB)
96 97

    /* WGL_ARB_pbuffer */
98 99 100 101
    GET_PROC(wglCreatePbufferARB)
    GET_PROC(wglGetPbufferDCARB)
    GET_PROC(wglReleasePbufferDCARB)

102 103 104 105
    /* WGL_EXT_swap_control */
    GET_PROC(wglSwapIntervalEXT)
    GET_PROC(wglGetSwapIntervalEXT)

106
#undef GET_PROC
107 108
}

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
static BOOL gl_extension_supported(const char *extensions, const char *extension_string)
{
    size_t ext_str_len = strlen(extension_string);

    while (*extensions)
    {
        const char *start;
        size_t len;

        while (isspace(*extensions))
            ++extensions;
        start = extensions;
        while (!isspace(*extensions) && *extensions)
            ++extensions;

        len = extensions - start;
        if (!len)
            continue;

        if (len == ext_str_len && !memcmp(start, extension_string, ext_str_len))
        {
            return TRUE;
        }
    }
    return FALSE;
}

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
static void test_pbuffers(HDC hdc)
{
    const int iAttribList[] = { WGL_DRAW_TO_PBUFFER_ARB, 1, /* Request pbuffer support */
                                0 };
    int iFormats[MAX_FORMATS];
    unsigned int nOnscreenFormats;
    unsigned int nFormats;
    int i, res;
    int iPixelFormat = 0;

    nOnscreenFormats = DescribePixelFormat(hdc, 0, 0, NULL);

    /* When you want to render to a pbuffer you need to call wglGetPbufferDCARB which
     * returns a 'magic' HDC which you can then pass to wglMakeCurrent to switch rendering
     * to the pbuffer. Below some tests are performed on what happens if you use standard WGL calls
     * on this 'magic' HDC for both a pixelformat that support onscreen and offscreen rendering
     * and a pixelformat that's only available for offscreen rendering (this means that only
     * wglChoosePixelFormatARB and friends know about the format.
     *
Austin English's avatar
Austin English committed
155
     * The first thing we need are pixelformats with pbuffer capabilities.
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
     */
    res = pwglChoosePixelFormatARB(hdc, iAttribList, NULL, MAX_FORMATS, iFormats, &nFormats);
    if(res <= 0)
    {
        skip("No pbuffer compatible formats found while WGL_ARB_pbuffer is supported\n");
        return;
    }
    trace("nOnscreenFormats: %d\n", nOnscreenFormats);
    trace("Total number of pbuffer capable pixelformats: %d\n", nFormats);

    /* Try to select an onscreen pixelformat out of the list */
    for(i=0; i < nFormats; i++)
    {
        /* Check if the format is onscreen, if it is choose it */
        if(iFormats[i] <= nOnscreenFormats)
        {
            iPixelFormat = iFormats[i];
            trace("Selected iPixelFormat=%d\n", iPixelFormat);
            break;
        }
    }

    /* A video driver supports a large number of onscreen and offscreen pixelformats.
     * The traditional WGL calls only see a subset of the whole pixelformat list. First
     * of all they only see the onscreen formats (the offscreen formats are at the end of the
     * pixelformat list) and second extended pixelformat capabilities are hidden from the
     * standard WGL calls. Only functions that depend on WGL_ARB_pixel_format can see them.
     *
     * Below we check if the pixelformat is also supported onscreen.
     */
    if(iPixelFormat != 0)
    {
        HDC pbuffer_hdc;
189 190
        int attrib = 0;
        HPBUFFERARB pbuffer = pwglCreatePbufferARB(hdc, iPixelFormat, 640 /* width */, 480 /* height */, &attrib);
191 192 193 194 195 196 197 198 199 200
        if(!pbuffer)
            skip("Pbuffer creation failed!\n");

        /* Test the pixelformat returned by GetPixelFormat on a pbuffer as the behavior is not clear */
        pbuffer_hdc = pwglGetPbufferDCARB(pbuffer);
        res = GetPixelFormat(pbuffer_hdc);
        ok(res == iPixelFormat, "Unexpected iPixelFormat=%d returned by GetPixelFormat for format %d\n", res, iPixelFormat);
        trace("iPixelFormat returned by GetPixelFormat: %d\n", res);
        trace("PixelFormat from wglChoosePixelFormatARB: %d\n", iPixelFormat);

201
        pwglReleasePbufferDCARB(pbuffer, pbuffer_hdc);
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
    }
    else skip("Pbuffer test for onscreen pixelformat skipped as no onscreen format with pbuffer capabilities have been found\n");

    /* Search for a real offscreen format */
    for(i=0, iPixelFormat=0; i<nFormats; i++)
    {
        if(iFormats[i] > nOnscreenFormats)
        {
            iPixelFormat = iFormats[i];
            trace("Selected iPixelFormat: %d\n", iPixelFormat);
            break;
        }
    }

    if(iPixelFormat != 0)
    {
        HDC pbuffer_hdc;
        HPBUFFERARB pbuffer = pwglCreatePbufferARB(hdc, iPixelFormat, 640 /* width */, 480 /* height */, NULL);
        if(!pbuffer)
            skip("Pbuffer creation failed!\n");

        /* Test the pixelformat returned by GetPixelFormat on a pbuffer as the behavior is not clear */
        pbuffer_hdc = pwglGetPbufferDCARB(pbuffer);
        res = GetPixelFormat(pbuffer_hdc);

        ok(res == 1, "Unexpected iPixelFormat=%d (1 expected) returned by GetPixelFormat for offscreen format %d\n", res, iPixelFormat);
        trace("iPixelFormat returned by GetPixelFormat: %d\n", res);
        trace("PixelFormat from wglChoosePixelFormatARB: %d\n", iPixelFormat);
        pwglReleasePbufferDCARB(pbuffer, hdc);
    }
    else skip("Pbuffer test for offscreen pixelformat skipped as no offscreen-only format with pbuffer capabilities has been found\n");
}

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
static int test_pfd(const PIXELFORMATDESCRIPTOR *pfd)
{
    int pf;
    HDC hdc;
    HWND hwnd;

    hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW, 10, 10, 200, 200, NULL, NULL,
            NULL, NULL);
    if (!hwnd)
        return 0;

    hdc = GetDC( hwnd );
    pf = ChoosePixelFormat( hdc, pfd );
    ReleaseDC( hwnd, hdc );
    DestroyWindow( hwnd );

    return pf;
}

static void test_choosepixelformat(void)
{
    PIXELFORMATDESCRIPTOR pfd = {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,                     /* version */
        PFD_DRAW_TO_WINDOW |
        PFD_SUPPORT_OPENGL |
        PFD_TYPE_RGBA,
        0,                     /* color depth */
        0, 0, 0, 0, 0, 0,      /* color bits */
        0,                     /* alpha buffer */
        0,                     /* shift bit */
        0,                     /* accumulation buffer */
        0, 0, 0, 0,            /* accum bits */
        0,                     /* z-buffer */
        0,                     /* stencil buffer */
        0,                     /* auxiliary buffer */
        PFD_MAIN_PLANE,        /* main layer */
        0,                     /* reserved */
        0, 0, 0                /* layer masks */
    };

    ok( test_pfd(&pfd), "Simple pfd failed\n" );
    pfd.dwFlags |= PFD_DOUBLEBUFFER_DONTCARE;
    ok( test_pfd(&pfd), "PFD_DOUBLEBUFFER_DONTCARE failed\n" );
    pfd.dwFlags |= PFD_STEREO_DONTCARE;
280
    ok( test_pfd(&pfd), "PFD_DOUBLEBUFFER_DONTCARE|PFD_STEREO_DONTCARE failed\n" );
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
    pfd.dwFlags &= ~PFD_DOUBLEBUFFER_DONTCARE;
    ok( test_pfd(&pfd), "PFD_STEREO_DONTCARE failed\n" );
    pfd.dwFlags &= ~PFD_STEREO_DONTCARE;

    pfd.cColorBits = 32;
    ok( test_pfd(&pfd), "Simple pfd failed\n" );
    pfd.dwFlags |= PFD_DOUBLEBUFFER_DONTCARE;
    ok( test_pfd(&pfd), "PFD_DOUBLEBUFFER_DONTCARE failed\n" );
    pfd.dwFlags |= PFD_STEREO_DONTCARE;
    ok( test_pfd(&pfd), "PFD_DOUBLEBUFFER_DONTCARE|PFD_STEREO_DONTCARE failed\n" );
    pfd.dwFlags &= ~PFD_DOUBLEBUFFER_DONTCARE;
    ok( test_pfd(&pfd), "PFD_STEREO_DONTCARE failed\n" );
    pfd.dwFlags &= ~PFD_STEREO_DONTCARE;
    pfd.cColorBits = 0;

    pfd.cAlphaBits = 8;
    ok( test_pfd(&pfd), "Simple pfd failed\n" );
    pfd.dwFlags |= PFD_DOUBLEBUFFER_DONTCARE;
    ok( test_pfd(&pfd), "PFD_DOUBLEBUFFER_DONTCARE failed\n" );
    pfd.dwFlags |= PFD_STEREO_DONTCARE;
    ok( test_pfd(&pfd), "PFD_DOUBLEBUFFER_DONTCARE|PFD_STEREO_DONTCARE failed\n" );
    pfd.dwFlags &= ~PFD_DOUBLEBUFFER_DONTCARE;
    ok( test_pfd(&pfd), "PFD_STEREO_DONTCARE failed\n" );
    pfd.dwFlags &= ~PFD_STEREO_DONTCARE;
    pfd.cAlphaBits = 0;

    pfd.cStencilBits = 8;
    ok( test_pfd(&pfd), "Simple pfd failed\n" );
    pfd.dwFlags |= PFD_DOUBLEBUFFER_DONTCARE;
    ok( test_pfd(&pfd), "PFD_DOUBLEBUFFER_DONTCARE failed\n" );
    pfd.dwFlags |= PFD_STEREO_DONTCARE;
    ok( test_pfd(&pfd), "PFD_DOUBLEBUFFER_DONTCARE|PFD_STEREO_DONTCARE failed\n" );
    pfd.dwFlags &= ~PFD_DOUBLEBUFFER_DONTCARE;
    ok( test_pfd(&pfd), "PFD_STEREO_DONTCARE failed\n" );
    pfd.dwFlags &= ~PFD_STEREO_DONTCARE;
    pfd.cStencilBits = 0;

    pfd.cAuxBuffers = 1;
    ok( test_pfd(&pfd), "Simple pfd failed\n" );
    pfd.dwFlags |= PFD_DOUBLEBUFFER_DONTCARE;
    ok( test_pfd(&pfd), "PFD_DOUBLEBUFFER_DONTCARE failed\n" );
    pfd.dwFlags |= PFD_STEREO_DONTCARE;
    ok( test_pfd(&pfd), "PFD_DOUBLEBUFFER_DONTCARE|PFD_STEREO_DONTCARE failed\n" );
    pfd.dwFlags &= ~PFD_DOUBLEBUFFER_DONTCARE;
    ok( test_pfd(&pfd), "PFD_STEREO_DONTCARE failed\n" );
    pfd.dwFlags &= ~PFD_STEREO_DONTCARE;
    pfd.cAuxBuffers = 0;
}

330
static void test_setpixelformat(HDC winhdc)
331 332
{
    int res = 0;
333
    int nCfgs;
334
    int pf;
335
    int i;
336
    HWND hwnd;
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
    PIXELFORMATDESCRIPTOR pfd = {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,                     /* version */
        PFD_DRAW_TO_WINDOW |
        PFD_SUPPORT_OPENGL |
        PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        24,                    /* 24-bit color depth */
        0, 0, 0, 0, 0, 0,      /* color bits */
        0,                     /* alpha buffer */
        0,                     /* shift bit */
        0,                     /* accumulation buffer */
        0, 0, 0, 0,            /* accum bits */
        32,                    /* z-buffer */
        0,                     /* stencil buffer */
        0,                     /* auxiliary buffer */
        PFD_MAIN_PLANE,        /* main layer */
        0,                     /* reserved */
        0, 0, 0                /* layer masks */
    };

    HDC hdc = GetDC(0);
    ok(hdc != 0, "GetDC(0) failed!\n");

    /* This should pass even on the main device context */
    pf = ChoosePixelFormat(hdc, &pfd);
363
    ok(pf != 0, "ChoosePixelFormat failed on main device context\n");
364

365 366 367
    /* SetPixelFormat on the main device context 'X root window' should fail,
     * but some broken drivers allow it
     */
368
    res = SetPixelFormat(hdc, pf, &pfd);
369
    trace("SetPixelFormat on main device context %s\n", res ? "succeeded" : "failed");
370 371 372 373 374 375 376 377 378 379 380

    /* Setting the same format that was set on the HDC is allowed; other
       formats fail */
    nCfgs = DescribePixelFormat(winhdc, 0, 0, NULL);
    pf = GetPixelFormat(winhdc);
    for(i = 1;i <= nCfgs;i++)
    {
        int res = SetPixelFormat(winhdc, i, NULL);
        if(i == pf) ok(res, "Failed to set the same pixel format\n");
        else ok(!res, "Unexpectedly set an alternate pixel format\n");
    }
381

382 383
    hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW, 10, 10, 200, 200, NULL, NULL,
            NULL, NULL);
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
    ok(hwnd != NULL, "err: %d\n", GetLastError());
    if (hwnd)
    {
        HDC hdc = GetDC( hwnd );
        pf = ChoosePixelFormat( hdc, &pfd );
        ok( pf != 0, "ChoosePixelFormat failed\n" );
        res = SetPixelFormat( hdc, pf, &pfd );
        ok( res != 0, "SetPixelFormat failed\n" );
        i = GetPixelFormat( hdc );
        ok( i == pf, "GetPixelFormat returned wrong format %d/%d\n", i, pf );
        ReleaseDC( hwnd, hdc );
        hdc = GetWindowDC( hwnd );
        i = GetPixelFormat( hdc );
        ok( i == pf, "GetPixelFormat returned wrong format %d/%d\n", i, pf );
        ReleaseDC( hwnd, hdc );
        DestroyWindow( hwnd );
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
        /* check various calls with invalid hdc */
        SetLastError( 0xdeadbeef );
        i = GetPixelFormat( hdc );
        ok( i == 0, "GetPixelFormat succeeded\n" );
        ok( GetLastError() == ERROR_INVALID_PIXEL_FORMAT, "wrong error %u\n", GetLastError() );
        SetLastError( 0xdeadbeef );
        res = SetPixelFormat( hdc, pf, &pfd );
        ok( i == 0, "SetPixelFormat succeeded\n" );
        ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
        SetLastError( 0xdeadbeef );
        res = DescribePixelFormat( hdc, 0, 0, NULL );
        ok( !res, "DescribePixelFormat succeeded\n" );
        ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
        SetLastError( 0xdeadbeef );
        pf = ChoosePixelFormat( hdc, &pfd );
        ok( !pf, "ChoosePixelFormat succeeded\n" );
        ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
        SetLastError( 0xdeadbeef );
        res = SwapBuffers( hdc );
        ok( !res, "SwapBuffers succeeded\n" );
        ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
        SetLastError( 0xdeadbeef );
        ok( !wglCreateContext( hdc ), "CreateContext succeeded\n" );
        ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
424 425
    }

426 427
    hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW, 10, 10, 200, 200, NULL, NULL,
            NULL, NULL);
428 429 430 431 432 433 434 435 436 437 438 439 440
    ok(hwnd != NULL, "err: %d\n", GetLastError());
    if (hwnd)
    {
        HDC hdc = GetWindowDC( hwnd );
        pf = ChoosePixelFormat( hdc, &pfd );
        ok( pf != 0, "ChoosePixelFormat failed\n" );
        res = SetPixelFormat( hdc, pf, &pfd );
        ok( res != 0, "SetPixelFormat failed\n" );
        i = GetPixelFormat( hdc );
        ok( i == pf, "GetPixelFormat returned wrong format %d/%d\n", i, pf );
        ReleaseDC( hwnd, hdc );
        DestroyWindow( hwnd );
    }
441 442
}

443 444 445
static void test_sharelists(HDC winhdc)
{
    HGLRC hglrc1, hglrc2, hglrc3;
446
    BOOL res;
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467

    hglrc1 = wglCreateContext(winhdc);
    res = wglShareLists(0, 0);
    ok(res == FALSE, "Sharing display lists for no contexts passed!\n");

    /* Test 1: Create a context and just share lists without doing anything special */
    hglrc2 = wglCreateContext(winhdc);
    if(hglrc2)
    {
        res = wglShareLists(hglrc1, hglrc2);
        ok(res, "Sharing of display lists failed\n");
        wglDeleteContext(hglrc2);
    }

    /* Test 2: Share display lists with a 'destination' context which has been made current */
    hglrc2 = wglCreateContext(winhdc);
    if(hglrc2)
    {
        res = wglMakeCurrent(winhdc, hglrc2);
        ok(res, "Make current failed\n");
        res = wglShareLists(hglrc1, hglrc2);
468
        todo_wine ok(res, "Sharing display lists with a destination context which has been made current failed\n");
469 470 471 472 473
        wglMakeCurrent(0, 0);
        wglDeleteContext(hglrc2);
    }

    /* Test 3: Share display lists with a context which already shares display lists with another context.
474
     * According to MSDN the second parameter cannot share any display lists but some buggy drivers might allow it */
475 476 477 478
    hglrc3 = wglCreateContext(winhdc);
    if(hglrc3)
    {
        res = wglShareLists(hglrc3, hglrc1);
479
        ok(res == FALSE, "Sharing of display lists passed for a context which already shared lists before\n");
480 481 482 483 484 485 486 487 488 489
        wglDeleteContext(hglrc3);
    }

    /* Test 4: Share display lists with a 'source' context which has been made current */
    hglrc2 = wglCreateContext(winhdc);
    if(hglrc2)
    {
        res = wglMakeCurrent(winhdc, hglrc1);
        ok(res, "Make current failed\n");
        res = wglShareLists(hglrc1, hglrc2);
490
        ok(res, "Sharing display lists with a source context which has been made current failed\n");
491 492 493 494 495
        wglMakeCurrent(0, 0);
        wglDeleteContext(hglrc2);
    }
}

496 497 498 499 500 501 502 503 504 505 506 507
static void test_makecurrent(HDC winhdc)
{
    BOOL ret;
    HGLRC hglrc;

    hglrc = wglCreateContext(winhdc);
    ok( hglrc != 0, "wglCreateContext failed\n" );

    ret = wglMakeCurrent( winhdc, hglrc );
    ok( ret, "wglMakeCurrent failed\n" );

    ok( wglGetCurrentContext() == hglrc, "wrong context\n" );
508 509 510 511 512 513 514 515 516 517 518 519 520 521

    /* set the same context again */
    ret = wglMakeCurrent( winhdc, hglrc );
    ok( ret, "wglMakeCurrent failed\n" );

    /* check wglMakeCurrent(x, y) after another call to wglMakeCurrent(x, y) */
    ret = wglMakeCurrent( winhdc, NULL );
    ok( ret, "wglMakeCurrent failed\n" );

    ret = wglMakeCurrent( winhdc, NULL );
    ok( ret, "wglMakeCurrent failed\n" );

    SetLastError( 0xdeadbeef );
    ret = wglMakeCurrent( NULL, NULL );
522 523 524
    ok( !ret || broken(ret) /* nt4 */, "wglMakeCurrent succeeded\n" );
    if (!ret) ok( GetLastError() == ERROR_INVALID_HANDLE,
                  "Expected ERROR_INVALID_HANDLE, got error=%x\n", GetLastError() );
525 526 527 528 529 530 531 532 533 534

    ret = wglMakeCurrent( winhdc, NULL );
    ok( ret, "wglMakeCurrent failed\n" );

    ret = wglMakeCurrent( winhdc, hglrc );
    ok( ret, "wglMakeCurrent failed\n" );

    ret = wglMakeCurrent( NULL, NULL );
    ok( ret, "wglMakeCurrent failed\n" );

535 536
    ok( wglGetCurrentContext() == NULL, "wrong context\n" );

537 538
    SetLastError( 0xdeadbeef );
    ret = wglMakeCurrent( NULL, NULL );
539 540 541
    ok( !ret || broken(ret) /* nt4 */, "wglMakeCurrent succeeded\n" );
    if (!ret) ok( GetLastError() == ERROR_INVALID_HANDLE,
                  "Expected ERROR_INVALID_HANDLE, got error=%x\n", GetLastError() );
542 543 544

    ret = wglMakeCurrent( winhdc, hglrc );
    ok( ret, "wglMakeCurrent failed\n" );
545 546
}

547 548 549 550 551 552 553
static void test_colorbits(HDC hdc)
{
    const int iAttribList[] = { WGL_COLOR_BITS_ARB, WGL_RED_BITS_ARB, WGL_GREEN_BITS_ARB,
                                WGL_BLUE_BITS_ARB, WGL_ALPHA_BITS_ARB };
    int iAttribRet[sizeof(iAttribList)/sizeof(iAttribList[0])];
    const int iAttribs[] = { WGL_ALPHA_BITS_ARB, 1, 0 };
    unsigned int nFormats;
554
    BOOL res;
555 556
    int iPixelFormat = 0;

557 558
    if (!pwglChoosePixelFormatARB)
    {
559
        win_skip("wglChoosePixelFormatARB is not available\n");
560 561 562
        return;
    }

563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
    /* We need a pixel format with at least one bit of alpha */
    res = pwglChoosePixelFormatARB(hdc, iAttribs, NULL, 1, &iPixelFormat, &nFormats);
    if(res == FALSE || nFormats == 0)
    {
        skip("No suitable pixel formats found\n");
        return;
    }

    res = pwglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0,
              sizeof(iAttribList)/sizeof(iAttribList[0]), iAttribList, iAttribRet);
    if(res == FALSE)
    {
        skip("wglGetPixelFormatAttribivARB failed\n");
        return;
    }
    iAttribRet[1] += iAttribRet[2]+iAttribRet[3]+iAttribRet[4];
    ok(iAttribRet[0] == iAttribRet[1], "WGL_COLOR_BITS_ARB (%d) does not equal R+G+B+A (%d)!\n",
                                       iAttribRet[0], iAttribRet[1]);
}

583 584 585 586 587 588
static void test_gdi_dbuf(HDC hdc)
{
    const int iAttribList[] = { WGL_SUPPORT_GDI_ARB, WGL_DOUBLE_BUFFER_ARB };
    int iAttribRet[sizeof(iAttribList)/sizeof(iAttribList[0])];
    unsigned int nFormats;
    int iPixelFormat;
589
    BOOL res;
590

591 592
    if (!pwglGetPixelFormatAttribivARB)
    {
593
        win_skip("wglGetPixelFormatAttribivARB is not available\n");
594 595 596
        return;
    }

597 598 599 600 601 602 603 604 605 606 607 608 609 610
    nFormats = DescribePixelFormat(hdc, 0, 0, NULL);
    for(iPixelFormat = 1;iPixelFormat <= nFormats;iPixelFormat++)
    {
        res = pwglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0,
                  sizeof(iAttribList)/sizeof(iAttribList[0]), iAttribList,
                  iAttribRet);
        ok(res!=FALSE, "wglGetPixelFormatAttribivARB failed for pixel format %d\n", iPixelFormat);
        if(res == FALSE)
            continue;

        ok(!(iAttribRet[0] && iAttribRet[1]), "GDI support and double buffering on pixel format %d\n", iPixelFormat);
    }
}

611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653
static void test_acceleration(HDC hdc)
{
    const int iAttribList[] = { WGL_ACCELERATION_ARB };
    int iAttribRet[sizeof(iAttribList)/sizeof(iAttribList[0])];
    unsigned int nFormats;
    int iPixelFormat;
    int res;
    PIXELFORMATDESCRIPTOR pfd;

    if (!pwglGetPixelFormatAttribivARB)
    {
        win_skip("wglGetPixelFormatAttribivARB is not available\n");
        return;
    }

    nFormats = DescribePixelFormat(hdc, 0, 0, NULL);
    for(iPixelFormat = 1; iPixelFormat <= nFormats; iPixelFormat++)
    {
        res = pwglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0,
                  sizeof(iAttribList)/sizeof(iAttribList[0]), iAttribList,
                  iAttribRet);
        ok(res!=FALSE, "wglGetPixelFormatAttribivARB failed for pixel format %d\n", iPixelFormat);
        if(res == FALSE)
            continue;

        memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
        DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);

        switch(iAttribRet[0])
        {
            case WGL_NO_ACCELERATION_ARB:
                ok( (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED)) == PFD_GENERIC_FORMAT , "Expected only PFD_GENERIC_FORMAT to be set for WGL_NO_ACCELERATION_ARB!: iPixelFormat=%d, dwFlags=%x!\n", iPixelFormat, pfd.dwFlags);
                break;
            case WGL_GENERIC_ACCELERATION_ARB:
                ok( (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED)) == (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED), "Expected both PFD_GENERIC_FORMAT and PFD_GENERIC_ACCELERATION to be set for WGL_GENERIC_ACCELERATION_ARB: iPixelFormat=%d, dwFlags=%x!\n", iPixelFormat, pfd.dwFlags);
                break;
            case WGL_FULL_ACCELERATION_ARB:
                ok( (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED)) == 0, "Expected no PFD_GENERIC_FORMAT/_ACCELERATION to be set for WGL_FULL_ACCELERATION_ARB: iPixelFormat=%d, dwFlags=%x!\n", iPixelFormat, pfd.dwFlags);
                break;
        }
    }
}

654
static void test_bitmap_rendering( BOOL use_dib )
655 656
{
    PIXELFORMATDESCRIPTOR pfd;
657
    int i, ret, bpp, iPixelFormat=0;
658
    unsigned int nFormats;
659
    HGLRC hglrc, hglrc2;
660
    BITMAPINFO biDst;
661
    HBITMAP bmpDst, oldDst, bmp2;
662
    HDC hdcDst, hdcScreen;
663
    UINT *dstBuffer = NULL;
664 665

    hdcScreen = CreateCompatibleDC(0);
666 667 668
    hdcDst = CreateCompatibleDC(0);

    if (use_dib)
669
    {
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
        bpp = 32;
        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);

        biDst.bmiHeader.biWidth = 12;
        biDst.bmiHeader.biHeight = -12;
        biDst.bmiHeader.biBitCount = 16;
        bmp2 = CreateDIBSection(0, &biDst, DIB_RGB_COLORS, NULL, NULL, 0);
    }
    else
    {
        bpp = GetDeviceCaps( hdcScreen, BITSPIXEL );
        bmpDst = CreateBitmap( 4, 4, 1, bpp, NULL );
        bmp2 = CreateBitmap( 12, 12, 1, bpp, NULL );
691 692 693 694
    }

    oldDst = SelectObject(hdcDst, bmpDst);

695 696
    trace( "testing on %s\n", use_dib ? "DIB" : "DDB" );

697 698 699 700 701 702 703 704 705
    /* Pick a pixel format by hand because ChoosePixelFormat is unreliable */
    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) &&
706
           (pfd.cColorBits == bpp) &&
707 708 709 710 711 712 713 714 715
           (pfd.cAlphaBits == 8) )
        {
            iPixelFormat = i;
            break;
        }
    }

    if(!iPixelFormat)
    {
716
        skip("Unable to find a suitable pixel format\n");
717 718 719
    }
    else
    {
720 721 722 723 724 725
        ret = SetPixelFormat(hdcDst, iPixelFormat, &pfd);
        ok( ret, "SetPixelFormat failed\n" );
        ret = GetPixelFormat( hdcDst );
        ok( ret == iPixelFormat, "GetPixelFormat returned %d/%d\n", ret, iPixelFormat );
        ret = SetPixelFormat(hdcDst, iPixelFormat + 1, &pfd);
        ok( !ret, "SetPixelFormat succeeded\n" );
726
        hglrc = wglCreateContext(hdcDst);
727
        ok(hglrc != NULL, "Unable to create a context\n");
728 729 730

        if(hglrc)
        {
731
            GLint viewport[4];
732
            wglMakeCurrent(hdcDst, hglrc);
733 734
            hglrc2 = wglCreateContext(hdcDst);
            ok(hglrc2 != NULL, "Unable to create a context\n");
735 736 737 738

            /* Note this is RGBA but we read ARGB back */
            glClearColor((float)0x22/0xff, (float)0x33/0xff, (float)0x44/0xff, (float)0x11/0xff);
            glClear(GL_COLOR_BUFFER_BIT);
739
            glGetIntegerv( GL_VIEWPORT, viewport );
740 741
            glFinish();

742 743
            ok( viewport[0] == 0 && viewport[1] == 0 && viewport[2] == 4 && viewport[3] == 4,
                "wrong viewport %d,%d,%d,%d\n", viewport[0], viewport[1], viewport[2], viewport[3] );
744
            /* Note apparently the alpha channel is not supported by the software renderer (bitmap only works using software) */
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
            if (dstBuffer)
                for (i = 0; i < 16; i++)
                    ok(dstBuffer[i] == 0x223344 || dstBuffer[i] == 0x11223344, "Received color=%x at %u\n",
                       dstBuffer[i], i);

            SelectObject(hdcDst, bmp2);
            ret = GetPixelFormat( hdcDst );
            ok( ret == iPixelFormat, "GetPixelFormat returned %d/%d\n", ret, iPixelFormat );
            ret = SetPixelFormat(hdcDst, iPixelFormat + 1, &pfd);
            ok( !ret, "SetPixelFormat succeeded\n" );

            /* context still uses the old pixel format and viewport */
            glClearColor((float)0x44/0xff, (float)0x33/0xff, (float)0x22/0xff, (float)0x11/0xff);
            glClear(GL_COLOR_BUFFER_BIT);
            glFinish();
            glGetIntegerv( GL_VIEWPORT, viewport );
            ok( viewport[0] == 0 && viewport[1] == 0 && viewport[2] == 4 && viewport[3] == 4,
                "wrong viewport %d,%d,%d,%d\n", viewport[0], viewport[1], viewport[2], viewport[3] );
763 764

            wglMakeCurrent(NULL, NULL);
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
            wglMakeCurrent(hdcDst, hglrc);
            glClearColor((float)0x44/0xff, (float)0x55/0xff, (float)0x66/0xff, (float)0x11/0xff);
            glClear(GL_COLOR_BUFFER_BIT);
            glFinish();
            glGetIntegerv( GL_VIEWPORT, viewport );
            ok( viewport[0] == 0 && viewport[1] == 0 && viewport[2] == 4 && viewport[3] == 4,
                "wrong viewport %d,%d,%d,%d\n", viewport[0], viewport[1], viewport[2], viewport[3] );

            wglMakeCurrent(hdcDst, hglrc2);
            glGetIntegerv( GL_VIEWPORT, viewport );
            ok( viewport[0] == 0 && viewport[1] == 0 && viewport[2] == 12 && viewport[3] == 12,
                "wrong viewport %d,%d,%d,%d\n", viewport[0], viewport[1], viewport[2], viewport[3] );

            wglMakeCurrent(hdcDst, hglrc);
            glGetIntegerv( GL_VIEWPORT, viewport );
            ok( viewport[0] == 0 && viewport[1] == 0 && viewport[2] == 4 && viewport[3] == 4,
                "wrong viewport %d,%d,%d,%d\n", viewport[0], viewport[1], viewport[2], viewport[3] );

            SelectObject(hdcDst, bmpDst);
            ret = GetPixelFormat( hdcDst );
            ok( ret == iPixelFormat, "GetPixelFormat returned %d/%d\n", ret, iPixelFormat );
            ret = SetPixelFormat(hdcDst, iPixelFormat + 1, &pfd);
            ok( !ret, "SetPixelFormat succeeded\n" );
            wglMakeCurrent(hdcDst, hglrc2);
            glGetIntegerv( GL_VIEWPORT, viewport );
            ok( viewport[0] == 0 && viewport[1] == 0 && viewport[2] == 12 && viewport[3] == 12,
                "wrong viewport %d,%d,%d,%d\n", viewport[0], viewport[1], viewport[2], viewport[3] );
792 793 794

            wglDeleteContext(hglrc2);
            wglDeleteContext(hglrc);
795 796 797 798
        }
    }

    SelectObject(hdcDst, oldDst);
799
    DeleteObject(bmp2);
800 801 802 803 804
    DeleteObject(bmpDst);
    DeleteDC(hdcDst);
    DeleteDC(hdcScreen);
}

805 806 807
struct wgl_thread_param
{
    HANDLE test_finished;
808
    HWND hwnd;
809
    HGLRC hglrc;
810 811 812 813
    BOOL make_current;
    BOOL make_current_error;
    BOOL deleted;
    DWORD deleted_error;
814 815 816 817 818
};

static DWORD WINAPI wgl_thread(void *param)
{
    struct wgl_thread_param *p = param;
819
    HDC hdc = GetDC( p->hwnd );
820

821 822 823
    ok(!glGetString(GL_RENDERER) && !glGetString(GL_VERSION) && !glGetString(GL_VENDOR),
       "Expected NULL string when no active context is set\n");

824
    SetLastError(0xdeadbeef);
825 826 827 828 829
    p->make_current = wglMakeCurrent(hdc, p->hglrc);
    p->make_current_error = GetLastError();
    p->deleted = wglDeleteContext(p->hglrc);
    p->deleted_error = GetLastError();
    ReleaseDC( p->hwnd, hdc );
830 831 832 833
    SetEvent(p->test_finished);
    return 0;
}

834
static void test_deletecontext(HWND hwnd, HDC hdc)
835 836 837 838
{
    struct wgl_thread_param thread_params;
    HGLRC hglrc = wglCreateContext(hdc);
    HANDLE thread_handle;
839 840
    BOOL res;
    DWORD tid;
841

842 843 844 845 846
    SetLastError(0xdeadbeef);
    res = wglDeleteContext(NULL);
    ok(res == FALSE, "wglDeleteContext succeeded\n");
    ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected last error to be ERROR_INVALID_HANDLE, got %u\n", GetLastError());

847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
    if(!hglrc)
    {
        skip("wglCreateContext failed!\n");
        return;
    }

    res = wglMakeCurrent(hdc, hglrc);
    if(!res)
    {
        skip("wglMakeCurrent failed!\n");
        return;
    }

    /* WGL doesn't allow you to delete a context from a different thread than the one in which it is current.
     * This differs from GLX which does allow it but it delays actual deletion until the context becomes not current.
     */
    thread_params.hglrc = hglrc;
864
    thread_params.hwnd  = hwnd;
865
    thread_params.test_finished = CreateEventW(NULL, FALSE, FALSE, NULL);
866 867 868 869 870
    thread_handle = CreateThread(NULL, 0, wgl_thread, &thread_params, 0, &tid);
    ok(!!thread_handle, "Failed to create thread, last error %#x.\n", GetLastError());
    if(thread_handle)
    {
        WaitForSingleObject(thread_handle, INFINITE);
871 872 873 874
        ok(!thread_params.make_current, "Attempt to make WGL context from another thread passed\n");
        ok(thread_params.make_current_error == ERROR_BUSY, "Expected last error to be ERROR_BUSY, got %u\n", thread_params.make_current_error);
        ok(!thread_params.deleted, "Attempt to delete WGL context from another thread passed\n");
        ok(thread_params.deleted_error == ERROR_BUSY, "Expected last error to be ERROR_BUSY, got %u\n", thread_params.deleted_error);
875 876 877 878 879
    }
    CloseHandle(thread_params.test_finished);

    res = wglDeleteContext(hglrc);
    ok(res == TRUE, "wglDeleteContext failed\n");
880

881 882 883 884 885 886
    /* Attempting to delete the same context twice should fail. */
    SetLastError(0xdeadbeef);
    res = wglDeleteContext(hglrc);
    ok(res == FALSE, "wglDeleteContext succeeded\n");
    ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected last error to be ERROR_INVALID_HANDLE, got %u\n", GetLastError());

887 888 889 890
    /* WGL makes a context not current when deleting it. This differs from GLX behavior where
     * deletion takes place when the thread becomes not current. */
    hglrc = wglGetCurrentContext();
    ok(hglrc == NULL, "A WGL context is active while none was expected\n");
891 892
}

893 894 895 896 897 898 899 900 901 902 903 904 905

static void test_getprocaddress(HDC hdc)
{
    const char *extensions = (const char*)glGetString(GL_EXTENSIONS);
    PROC func = NULL;
    HGLRC ctx = wglGetCurrentContext();

    if (!extensions)
    {
        skip("skipping wglGetProcAddress tests because no GL extensions supported\n");
        return;
    }

906 907 908 909 910 911 912 913 914 915
    /* Core GL 1.0/1.1 functions should not be loadable through wglGetProcAddress.
     * Try to load the function with and without a context.
     */
    func = wglGetProcAddress("glEnable");
    ok(func == NULL, "Lookup of function glEnable with a context passed, expected a failure\n");
    wglMakeCurrent(hdc, NULL);
    func = wglGetProcAddress("glEnable");
    ok(func == NULL, "Lookup of function glEnable without a context passed, expected a failure\n");
    wglMakeCurrent(hdc, ctx);

916 917 918 919 920 921 922 923 924 925
    /* The goal of the test will be to test behavior of wglGetProcAddress when
     * no WGL context is active. Before the test we pick an extension (GL_ARB_multitexture)
     * which any GL >=1.2.1 implementation supports. Unfortunately the GDI renderer doesn't
     * support it. There aren't any extensions we can use for this test which are supported by
     * both GDI and real drivers.
     * Note GDI only has GL_EXT_bgra, GL_EXT_paletted_texture and GL_WIN_swap_hint.
     */
    if (!gl_extension_supported(extensions, "GL_ARB_multitexture"))
    {
        skip("skipping test because lack of GL_ARB_multitexture support\n");
926
        return;
927 928 929 930 931 932 933 934
    }

    func = wglGetProcAddress("glActiveTextureARB");
    ok(func != NULL, "Unable to lookup glActiveTextureARB, last error %#x\n", GetLastError());

    /* Temporarily disable the context, so we can see that we can't retrieve functions now. */
    wglMakeCurrent(hdc, NULL);
    func = wglGetProcAddress("glActiveTextureARB");
935
    ok(func == NULL, "Function lookup without a context passed, expected a failure; last error %#x\n", GetLastError());
936 937 938
    wglMakeCurrent(hdc, ctx);
}

939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
static void test_make_current_read(HDC hdc)
{
    int res;
    HDC hread;
    HGLRC hglrc = wglCreateContext(hdc);

    if(!hglrc)
    {
        skip("wglCreateContext failed!\n");
        return;
    }

    res = wglMakeCurrent(hdc, hglrc);
    if(!res)
    {
        skip("wglMakeCurrent failed!\n");
        return;
    }

    /* Test what wglGetCurrentReadDCARB does for wglMakeCurrent as the spec doesn't mention it */
    hread = pwglGetCurrentReadDCARB();
    trace("hread %p, hdc %p\n", hread, hdc);
    ok(hread == hdc, "wglGetCurrentReadDCARB failed for standard wglMakeCurrent\n");

    pwglMakeContextCurrentARB(hdc, hdc, hglrc);
    hread = pwglGetCurrentReadDCARB();
    ok(hread == hdc, "wglGetCurrentReadDCARB failed for wglMakeContextCurrent\n");
}

968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990
static void test_dc(HWND hwnd, HDC hdc)
{
    int pf1, pf2;
    HDC hdc2;

    /* Get another DC and make sure it has the same pixel format */
    hdc2 = GetDC(hwnd);
    if(hdc != hdc2)
    {
        pf1 = GetPixelFormat(hdc);
        pf2 = GetPixelFormat(hdc2);
        ok(pf1 == pf2, "Second DC does not have the same format (%d != %d)\n", pf1, pf2);
    }
    else
        skip("Could not get a different DC for the window\n");

    if(hdc2)
    {
        ReleaseDC(hwnd, hdc2);
        hdc2 = NULL;
    }
}

991 992
/* Nvidia converts win32 error codes to (0xc007 << 16) | win32_error_code */
#define NVIDIA_HRESULT_FROM_WIN32(x) (HRESULT_FROM_WIN32(x) | 0x40000000)
993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
static void test_opengl3(HDC hdc)
{
    /* Try to create a context compatible with OpenGL 1.x; 1.0-2.1 is allowed */
    {
        HGLRC gl3Ctx;
        int attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 1, 0};

        gl3Ctx = pwglCreateContextAttribsARB(hdc, 0, attribs);
        ok(gl3Ctx != 0, "pwglCreateContextAttribsARB for a 1.x context failed!\n");
        wglDeleteContext(gl3Ctx);
    }

    /* Try to pass an invalid HDC */
    {
        HGLRC gl3Ctx;
        DWORD error;
1009
        SetLastError(0xdeadbeef);
1010 1011 1012
        gl3Ctx = pwglCreateContextAttribsARB((HDC)0xdeadbeef, 0, 0);
        ok(gl3Ctx == 0, "pwglCreateContextAttribsARB using an invalid HDC passed\n");
        error = GetLastError();
1013 1014
        ok(error == ERROR_DC_NOT_FOUND || error == ERROR_INVALID_HANDLE ||
           broken(error == ERROR_DS_GENERIC_ERROR) ||
1015 1016
           broken(error == NVIDIA_HRESULT_FROM_WIN32(ERROR_INVALID_DATA)), /* Nvidia Vista + Win7 */
           "Expected ERROR_DC_NOT_FOUND, got error=%x\n", error);
1017 1018 1019 1020 1021 1022 1023
        wglDeleteContext(gl3Ctx);
    }

    /* Try to pass an invalid shareList */
    {
        HGLRC gl3Ctx;
        DWORD error;
1024
        SetLastError(0xdeadbeef);
1025
        gl3Ctx = pwglCreateContextAttribsARB(hdc, (HGLRC)0xdeadbeef, 0);
1026
        ok(gl3Ctx == 0, "pwglCreateContextAttribsARB using an invalid shareList passed\n");
1027
        error = GetLastError();
1028
        /* The Nvidia implementation seems to return hresults instead of win32 error codes */
1029
        ok(error == ERROR_INVALID_OPERATION || error == ERROR_INVALID_DATA ||
1030
           error == NVIDIA_HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION), "Expected ERROR_INVALID_OPERATION, got error=%x\n", error);
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
        wglDeleteContext(gl3Ctx);
    }

    /* Try to create an OpenGL 3.0 context */
    {
        int attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 0};
        HGLRC gl3Ctx = pwglCreateContextAttribsARB(hdc, 0, attribs);

        if(gl3Ctx == NULL)
        {
            skip("Skipping the rest of the WGL_ARB_create_context test due to lack of OpenGL 3.0\n");
            return;
        }

        wglDeleteContext(gl3Ctx);
    }

    /* Test matching an OpenGL 3.0 context with an older one, OpenGL 3.0 should allow it until the new object model is introduced in a future revision */
    {
        HGLRC glCtx = wglCreateContext(hdc);

        int attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 0};
        int attribs_future[] = {WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 0};

        HGLRC gl3Ctx = pwglCreateContextAttribsARB(hdc, glCtx, attribs);
        ok(gl3Ctx != NULL, "Sharing of a display list between OpenGL 3.0 and OpenGL 1.x/2.x failed!\n");
        if(gl3Ctx)
            wglDeleteContext(gl3Ctx);

        gl3Ctx = pwglCreateContextAttribsARB(hdc, glCtx, attribs_future);
        ok(gl3Ctx != NULL, "Sharing of a display list between a forward compatible OpenGL 3.0 context and OpenGL 1.x/2.x failed!\n");
        if(gl3Ctx)
            wglDeleteContext(gl3Ctx);

        if(glCtx)
            wglDeleteContext(glCtx);
    }

    /* Try to create an OpenGL 3.0 context and test windowless rendering */
    {
        HGLRC gl3Ctx;
        int attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 0};
        BOOL res;

        gl3Ctx = pwglCreateContextAttribsARB(hdc, 0, attribs);
        ok(gl3Ctx != 0, "pwglCreateContextAttribsARB for a 3.0 context failed!\n");

1078 1079 1080 1081 1082
        /* OpenGL 3.0 allows offscreen rendering WITHOUT a drawable
         * Neither AMD or Nvidia support it at this point. The WGL_ARB_create_context specs also say that
         * it is hard because drivers use the HDC to enter the display driver and it sounds like they don't
         * expect drivers to ever offer it.
         */
1083
        res = wglMakeCurrent(0, gl3Ctx);
1084
        ok(res == FALSE, "Wow, OpenGL 3.0 windowless rendering passed while it was expected not to!\n");
1085 1086 1087 1088 1089 1090 1091 1092
        if(res)
            wglMakeCurrent(0, 0);

        if(gl3Ctx)
            wglDeleteContext(gl3Ctx);
    }
}

1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
static void test_minimized(void)
{
    PIXELFORMATDESCRIPTOR pf_desc =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,                     /* version */
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        24,                    /* 24-bit color depth */
        0, 0, 0, 0, 0, 0,      /* color bits */
        0,                     /* alpha buffer */
        0,                     /* shift bit */
        0,                     /* accumulation buffer */
        0, 0, 0, 0,            /* accum bits */
        32,                    /* z-buffer */
        0,                     /* stencil buffer */
        0,                     /* auxiliary buffer */
        PFD_MAIN_PLANE,        /* main layer */
        0,                     /* reserved */
        0, 0, 0                /* layer masks */
    };
    int pixel_format;
    HWND window;
    LONG style;
    HGLRC ctx;
    BOOL ret;
    HDC dc;

    window = CreateWindowA("static", "opengl32_test",
            WS_POPUP | WS_MINIMIZE, 0, 0, 640, 480, 0, 0, 0, 0);
    ok(!!window, "Failed to create window, last error %#x.\n", GetLastError());

    dc = GetDC(window);
    ok(!!dc, "Failed to get DC.\n");

    pixel_format = ChoosePixelFormat(dc, &pf_desc);
    if (!pixel_format)
    {
        win_skip("Failed to find pixel format.\n");
        ReleaseDC(window, dc);
        DestroyWindow(window);
        return;
    }

    ret = SetPixelFormat(dc, pixel_format, &pf_desc);
    ok(ret, "Failed to set pixel format, last error %#x.\n", GetLastError());

    style = GetWindowLongA(window, GWL_STYLE);
    ok(style & WS_MINIMIZE, "Window should be minimized, got style %#x.\n", style);

    ctx = wglCreateContext(dc);
    ok(!!ctx, "Failed to create GL context, last error %#x.\n", GetLastError());

    ret = wglMakeCurrent(dc, ctx);
    ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());

    style = GetWindowLongA(window, GWL_STYLE);
    ok(style & WS_MINIMIZE, "window should be minimized, got style %#x.\n", style);

    ret = wglMakeCurrent(NULL, NULL);
    ok(ret, "Failed to clear current context, last error %#x.\n", GetLastError());

    ret = wglDeleteContext(ctx);
    ok(ret, "Failed to delete GL context, last error %#x.\n", GetLastError());

    ReleaseDC(window, dc);
    DestroyWindow(window);
}

1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
static void test_window_dc(void)
{
    PIXELFORMATDESCRIPTOR pf_desc =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,                     /* version */
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        24,                    /* 24-bit color depth */
        0, 0, 0, 0, 0, 0,      /* color bits */
        0,                     /* alpha buffer */
        0,                     /* shift bit */
        0,                     /* accumulation buffer */
        0, 0, 0, 0,            /* accum bits */
        32,                    /* z-buffer */
        0,                     /* stencil buffer */
        0,                     /* auxiliary buffer */
        PFD_MAIN_PLANE,        /* main layer */
        0,                     /* reserved */
        0, 0, 0                /* layer masks */
    };
    int pixel_format;
    HWND window;
    RECT vp, r;
    HGLRC ctx;
    BOOL ret;
    HDC dc;

    window = CreateWindowA("static", "opengl32_test",
            WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
    ok(!!window, "Failed to create window, last error %#x.\n", GetLastError());

    ShowWindow(window, SW_SHOW);

    dc = GetWindowDC(window);
    ok(!!dc, "Failed to get DC.\n");

    pixel_format = ChoosePixelFormat(dc, &pf_desc);
    if (!pixel_format)
    {
        win_skip("Failed to find pixel format.\n");
        ReleaseDC(window, dc);
        DestroyWindow(window);
        return;
    }

    ret = SetPixelFormat(dc, pixel_format, &pf_desc);
    ok(ret, "Failed to set pixel format, last error %#x.\n", GetLastError());

    ctx = wglCreateContext(dc);
    ok(!!ctx, "Failed to create GL context, last error %#x.\n", GetLastError());

    ret = wglMakeCurrent(dc, ctx);
    ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());

    GetClientRect(window, &r);
    glGetIntegerv(GL_VIEWPORT, (GLint *)&vp);
    ok(EqualRect(&r, &vp), "Viewport not equal to client rect.\n");

    ret = wglMakeCurrent(NULL, NULL);
    ok(ret, "Failed to clear current context, last error %#x.\n", GetLastError());

    ret = wglDeleteContext(ctx);
    ok(ret, "Failed to delete GL context, last error %#x.\n", GetLastError());

    ReleaseDC(window, dc);
    DestroyWindow(window);
}

1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
static void test_message_window(void)
{
    PIXELFORMATDESCRIPTOR pf_desc =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,                     /* version */
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        24,                    /* 24-bit color depth */
        0, 0, 0, 0, 0, 0,      /* color bits */
        0,                     /* alpha buffer */
        0,                     /* shift bit */
        0,                     /* accumulation buffer */
        0, 0, 0, 0,            /* accum bits */
        32,                    /* z-buffer */
        0,                     /* stencil buffer */
        0,                     /* auxiliary buffer */
        PFD_MAIN_PLANE,        /* main layer */
        0,                     /* reserved */
        0, 0, 0                /* layer masks */
    };
    int pixel_format;
    HWND window;
    RECT vp, r;
    HGLRC ctx;
    BOOL ret;
    HDC dc;
    GLenum glerr;

    window = CreateWindowA("static", "opengl32_test",
                           WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, HWND_MESSAGE, 0, 0, 0);
    if (!window)
    {
        win_skip( "HWND_MESSAGE not supported\n" );
        return;
    }
    dc = GetDC(window);
    ok(!!dc, "Failed to get DC.\n");

    pixel_format = ChoosePixelFormat(dc, &pf_desc);
    if (!pixel_format)
    {
        win_skip("Failed to find pixel format.\n");
        ReleaseDC(window, dc);
        DestroyWindow(window);
        return;
    }

    ret = SetPixelFormat(dc, pixel_format, &pf_desc);
    ok(ret, "Failed to set pixel format, last error %#x.\n", GetLastError());

    ctx = wglCreateContext(dc);
    ok(!!ctx, "Failed to create GL context, last error %#x.\n", GetLastError());

    ret = wglMakeCurrent(dc, ctx);
    ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());

    GetClientRect(window, &r);
    glGetIntegerv(GL_VIEWPORT, (GLint *)&vp);
    ok(EqualRect(&r, &vp), "Viewport not equal to client rect.\n");

    glClear(GL_COLOR_BUFFER_BIT);
    glFinish();
    glerr = glGetError();
    ok(glerr == GL_NO_ERROR, "Failed glClear, error %#x.\n", glerr);
    ret = SwapBuffers(dc);
    ok(ret, "Failed SwapBuffers, error %#x.\n", GetLastError());

    ret = wglMakeCurrent(NULL, NULL);
    ok(ret, "Failed to clear current context, last error %#x.\n", GetLastError());

    ret = wglDeleteContext(ctx);
    ok(ret, "Failed to delete GL context, last error %#x.\n", GetLastError());

    ReleaseDC(window, dc);
    DestroyWindow(window);
}

1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369
static void test_destroy(HDC oldhdc)
{
    PIXELFORMATDESCRIPTOR pf_desc =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,                     /* version */
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        24,                    /* 24-bit color depth */
        0, 0, 0, 0, 0, 0,      /* color bits */
        0,                     /* alpha buffer */
        0,                     /* shift bit */
        0,                     /* accumulation buffer */
        0, 0, 0, 0,            /* accum bits */
        32,                    /* z-buffer */
        0,                     /* stencil buffer */
        0,                     /* auxiliary buffer */
        PFD_MAIN_PLANE,        /* main layer */
        0,                     /* reserved */
        0, 0, 0                /* layer masks */
    };
    int pixel_format;
    HWND window;
    HGLRC ctx;
    BOOL ret;
    HDC dc;
    GLenum glerr;
    DWORD err;
    HGLRC oldctx = wglGetCurrentContext();

    ok(!!oldctx, "Expected to find a valid current context.\n");

    window = CreateWindowA("static", "opengl32_test",
            WS_POPUP, 0, 0, 640, 480, 0, 0, 0, 0);
    ok(!!window, "Failed to create window, last error %#x.\n", GetLastError());

    dc = GetDC(window);
    ok(!!dc, "Failed to get DC.\n");

    pixel_format = ChoosePixelFormat(dc, &pf_desc);
    if (!pixel_format)
    {
        win_skip("Failed to find pixel format.\n");
        ReleaseDC(window, dc);
        DestroyWindow(window);
        return;
    }

    ret = SetPixelFormat(dc, pixel_format, &pf_desc);
    ok(ret, "Failed to set pixel format, last error %#x.\n", GetLastError());

    ctx = wglCreateContext(dc);
    ok(!!ctx, "Failed to create GL context, last error %#x.\n", GetLastError());

    ret = wglMakeCurrent(dc, ctx);
    ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());

    glClear(GL_COLOR_BUFFER_BIT);
    glFinish();
    glerr = glGetError();
    ok(glerr == GL_NO_ERROR, "Failed glClear, error %#x.\n", glerr);
1370 1371
    ret = SwapBuffers(dc);
    ok(ret, "Failed SwapBuffers, error %#x.\n", GetLastError());
1372 1373 1374 1375 1376 1377 1378 1379 1380

    ret = DestroyWindow(window);
    ok(ret, "Failed to destroy window, last error %#x.\n", GetLastError());

    ok(wglGetCurrentContext() == ctx, "Wrong current context.\n");

    SetLastError(0xdeadbeef);
    ret = wglMakeCurrent(dc, ctx);
    err = GetLastError();
1381
    ok(!ret && err == ERROR_INVALID_HANDLE,
1382
            "Unexpected behavior when making context current, ret %d, last error %#x.\n", ret, err);
1383 1384 1385 1386
    SetLastError(0xdeadbeef);
    ret = SwapBuffers(dc);
    err = GetLastError();
    ok(!ret && err == ERROR_INVALID_HANDLE, "Unexpected behavior with SwapBuffer, last error %#x.\n", err);
1387 1388 1389 1390 1391 1392 1393

    ok(wglGetCurrentContext() == ctx, "Wrong current context.\n");

    glClear(GL_COLOR_BUFFER_BIT);
    glFinish();
    glerr = glGetError();
    ok(glerr == GL_NO_ERROR, "Failed glClear, error %#x.\n", glerr);
1394 1395 1396 1397
    SetLastError(0xdeadbeef);
    ret = SwapBuffers(dc);
    err = GetLastError();
    ok(!ret && err == ERROR_INVALID_HANDLE, "Unexpected behavior with SwapBuffer, last error %#x.\n", err);
1398 1399 1400 1401 1402 1403 1404

    ret = wglMakeCurrent(NULL, NULL);
    ok(ret, "Failed to clear current context, last error %#x.\n", GetLastError());

    glClear(GL_COLOR_BUFFER_BIT);
    glFinish();
    glerr = glGetError();
1405
    ok(glerr == GL_INVALID_OPERATION, "Failed glClear, error %#x.\n", glerr);
1406 1407 1408 1409
    SetLastError(0xdeadbeef);
    ret = SwapBuffers(dc);
    err = GetLastError();
    ok(!ret && err == ERROR_INVALID_HANDLE, "Unexpected behavior with SwapBuffer, last error %#x.\n", err);
1410 1411 1412 1413

    SetLastError(0xdeadbeef);
    ret = wglMakeCurrent(dc, ctx);
    err = GetLastError();
1414
    ok(!ret && err == ERROR_INVALID_HANDLE,
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
            "Unexpected behavior when making context current, ret %d, last error %#x.\n", ret, err);

    ok(wglGetCurrentContext() == NULL, "Wrong current context.\n");

    ret = wglMakeCurrent(oldhdc, oldctx);
    ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());
    ok(wglGetCurrentContext() == oldctx, "Wrong current context.\n");

    SetLastError(0xdeadbeef);
    ret = wglMakeCurrent(dc, ctx);
    err = GetLastError();
1426
    ok(!ret && err == ERROR_INVALID_HANDLE,
1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439
            "Unexpected behavior when making context current, ret %d, last error %#x.\n", ret, err);

    ok(wglGetCurrentContext() == oldctx, "Wrong current context.\n");

    ret = wglDeleteContext(ctx);
    ok(ret, "Failed to delete GL context, last error %#x.\n", GetLastError());

    ReleaseDC(window, dc);

    ret = wglMakeCurrent(oldhdc, oldctx);
    ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());
}

1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521
static void test_destroy_read(HDC oldhdc)
{
    PIXELFORMATDESCRIPTOR pf_desc =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,                     /* version */
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        24,                    /* 24-bit color depth */
        0, 0, 0, 0, 0, 0,      /* color bits */
        0,                     /* alpha buffer */
        0,                     /* shift bit */
        0,                     /* accumulation buffer */
        0, 0, 0, 0,            /* accum bits */
        32,                    /* z-buffer */
        0,                     /* stencil buffer */
        0,                     /* auxiliary buffer */
        PFD_MAIN_PLANE,        /* main layer */
        0,                     /* reserved */
        0, 0, 0                /* layer masks */
    };
    int pixel_format;
    HWND draw_window, read_window;
    HGLRC ctx;
    BOOL ret;
    HDC read_dc, draw_dc;
    GLenum glerr;
    DWORD err;
    HGLRC oldctx = wglGetCurrentContext();

    ok(!!oldctx, "Expected to find a valid current context\n");

    draw_window = CreateWindowA("static", "opengl32_test",
            WS_POPUP, 0, 0, 640, 480, 0, 0, 0, 0);
    ok(!!draw_window, "Failed to create window, last error %#x.\n", GetLastError());

    draw_dc = GetDC(draw_window);
    ok(!!draw_dc, "Failed to get DC.\n");

    pixel_format = ChoosePixelFormat(draw_dc, &pf_desc);
    if (!pixel_format)
    {
        win_skip("Failed to find pixel format.\n");
        ReleaseDC(draw_window, draw_dc);
        DestroyWindow(draw_window);
        return;
    }

    ret = SetPixelFormat(draw_dc, pixel_format, &pf_desc);
    ok(ret, "Failed to set pixel format, last error %#x.\n", GetLastError());

    read_window = CreateWindowA("static", "opengl32_test",
            WS_POPUP, 0, 0, 640, 480, 0, 0, 0, 0);
    ok(!!read_window, "Failed to create window, last error %#x.\n", GetLastError());

    read_dc = GetDC(read_window);
    ok(!!draw_dc, "Failed to get DC.\n");

    pixel_format = ChoosePixelFormat(read_dc, &pf_desc);
    if (!pixel_format)
    {
        win_skip("Failed to find pixel format.\n");
        ReleaseDC(read_window, read_dc);
        DestroyWindow(read_window);
        ReleaseDC(draw_window, draw_dc);
        DestroyWindow(draw_window);
        return;
    }

    ret = SetPixelFormat(read_dc, pixel_format, &pf_desc);
    ok(ret, "Failed to set pixel format, last error %#x.\n", GetLastError());

    ctx = wglCreateContext(draw_dc);
    ok(!!ctx, "Failed to create GL context, last error %#x.\n", GetLastError());

    ret = pwglMakeContextCurrentARB(draw_dc, read_dc, ctx);
    ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());

    glCopyPixels(0, 0, 640, 480, GL_COLOR);
    glFinish();
    glerr = glGetError();
    ok(glerr == GL_NO_ERROR, "Failed glCopyPixel, error %#x.\n", glerr);
1522 1523
    ret = SwapBuffers(draw_dc);
    ok(ret, "Failed SwapBuffers, error %#x.\n", GetLastError());
1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541

    ret = DestroyWindow(read_window);
    ok(ret, "Failed to destroy window, last error %#x.\n", GetLastError());

    ok(wglGetCurrentContext() == ctx, "Wrong current context.\n");

    if (0) /* Crashes on AMD on Windows */
    {
        glCopyPixels(0, 0, 640, 480, GL_COLOR);
        glFinish();
        glerr = glGetError();
        ok(glerr == GL_NO_ERROR, "Failed glCopyPixel, error %#x.\n", glerr);
    }

    glClear(GL_COLOR_BUFFER_BIT);
    glFinish();
    glerr = glGetError();
    ok(glerr == GL_NO_ERROR, "Failed glClear, error %#x.\n", glerr);
1542 1543
    ret = SwapBuffers(draw_dc);
    ok(ret, "Failed SwapBuffers, error %#x.\n", GetLastError());
1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562

    ret = wglMakeCurrent(NULL, NULL);
    ok(ret, "Failed to clear current context, last error %#x.\n", GetLastError());

    if (0) /* This crashes with Nvidia drivers on Windows. */
    {
        SetLastError(0xdeadbeef);
        ret = pwglMakeContextCurrentARB(draw_dc, read_dc, ctx);
        err = GetLastError();
        ok(!ret && err == ERROR_INVALID_HANDLE,
                "Unexpected behavior when making context current, ret %d, last error %#x.\n", ret, err);
    }

    ret = DestroyWindow(draw_window);
    ok(ret, "Failed to destroy window, last error %#x.\n", GetLastError());

    glClear(GL_COLOR_BUFFER_BIT);
    glFinish();
    glerr = glGetError();
1563
    ok(glerr == GL_INVALID_OPERATION, "Failed glClear, error %#x.\n", glerr);
1564 1565 1566 1567
    SetLastError(0xdeadbeef);
    ret = SwapBuffers(draw_dc);
    err = GetLastError();
    ok(!ret && err == ERROR_INVALID_HANDLE, "Unexpected behavior with SwapBuffer, last error %#x.\n", err);
1568 1569 1570 1571

    SetLastError(0xdeadbeef);
    ret = pwglMakeContextCurrentARB(draw_dc, read_dc, ctx);
    err = GetLastError();
1572
    ok(!ret && (err == ERROR_INVALID_HANDLE || err == 0xc0070006),
1573 1574
            "Unexpected behavior when making context current, ret %d, last error %#x.\n", ret, err);

1575
    ok(wglGetCurrentContext() == NULL, "Wrong current context.\n");
1576 1577 1578 1579 1580 1581 1582 1583 1584

    wglMakeCurrent(NULL, NULL);

    wglMakeCurrent(oldhdc, oldctx);
    ok(wglGetCurrentContext() == oldctx, "Wrong current context.\n");

    SetLastError(0xdeadbeef);
    ret = pwglMakeContextCurrentARB(draw_dc, read_dc, ctx);
    err = GetLastError();
1585
    ok(!ret && (err == ERROR_INVALID_HANDLE || err == 0xc0070006),
1586 1587
            "Unexpected behavior when making context current, last error %#x.\n", err);

1588
    ok(wglGetCurrentContext() == oldctx, "Wrong current context.\n");
1589 1590 1591 1592 1593 1594 1595 1596 1597 1598

    ret = wglDeleteContext(ctx);
    ok(ret, "Failed to delete GL context, last error %#x.\n", GetLastError());

    ReleaseDC(read_window, read_dc);
    ReleaseDC(draw_window, draw_dc);

    wglMakeCurrent(oldhdc, oldctx);
}

1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620
static void test_swap_control(HDC oldhdc)
{
    PIXELFORMATDESCRIPTOR pf_desc =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,                     /* version */
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        24,                    /* 24-bit color depth */
        0, 0, 0, 0, 0, 0,      /* color bits */
        0,                     /* alpha buffer */
        0,                     /* shift bit */
        0,                     /* accumulation buffer */
        0, 0, 0, 0,            /* accum bits */
        32,                    /* z-buffer */
        0,                     /* stencil buffer */
        0,                     /* auxiliary buffer */
        PFD_MAIN_PLANE,        /* main layer */
        0,                     /* reserved */
        0, 0, 0                /* layer masks */
    };
    int pixel_format;
1621
    HWND window1, window2, old_parent;
1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661
    HGLRC ctx1, ctx2, oldctx;
    BOOL ret;
    HDC dc1, dc2;
    int interval;

    oldctx = wglGetCurrentContext();
    ok(!!oldctx, "Expected to find a valid current context.\n");

    window1 = CreateWindowA("static", "opengl32_test",
            WS_POPUP, 0, 0, 640, 480, 0, 0, 0, 0);
    ok(!!window1, "Failed to create window1, last error %#x.\n", GetLastError());

    dc1 = GetDC(window1);
    ok(!!dc1, "Failed to get DC.\n");

    pixel_format = ChoosePixelFormat(dc1, &pf_desc);
    if (!pixel_format)
    {
        win_skip("Failed to find pixel format.\n");
        ReleaseDC(window1, dc1);
        DestroyWindow(window1);
        return;
    }

    ret = SetPixelFormat(dc1, pixel_format, &pf_desc);
    ok(ret, "Failed to set pixel format, last error %#x.\n", GetLastError());

    ctx1 = wglCreateContext(dc1);
    ok(!!ctx1, "Failed to create GL context, last error %#x.\n", GetLastError());

    ret = wglMakeCurrent(dc1, ctx1);
    ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());

    interval = pwglGetSwapIntervalEXT();
    ok(interval == 1, "Expected default swap interval 1, got %d\n", interval);

    ret = pwglSwapIntervalEXT(0);
    ok(ret, "Failed to set swap interval to 0, last error %#x.\n", GetLastError());

    interval = pwglGetSwapIntervalEXT();
1662
    ok(interval == 0, "Expected swap interval 0, got %d\n", interval);
1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693

    /* Check what interval we get on a second context on the same drawable.*/
    ctx2 = wglCreateContext(dc1);
    ok(!!ctx2, "Failed to create GL context, last error %#x.\n", GetLastError());

    ret = wglMakeCurrent(dc1, ctx2);
    ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());

    interval = pwglGetSwapIntervalEXT();
    ok(interval == 0, "Expected swap interval 0, got %d\n", interval);

    /* A second window is created to see whether its swap interval was affected
     * by previous calls.
     */
    window2 = CreateWindowA("static", "opengl32_test",
            WS_POPUP, 0, 0, 640, 480, 0, 0, 0, 0);
    ok(!!window2, "Failed to create window2, last error %#x.\n", GetLastError());

    dc2 = GetDC(window2);
    ok(!!dc2, "Failed to get DC.\n");

    ret = SetPixelFormat(dc2, pixel_format, &pf_desc);
    ok(ret, "Failed to set pixel format, last error %#x.\n", GetLastError());

    ret = wglMakeCurrent(dc2, ctx1);
    ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());

    /* Since the second window lacks the swap interval, this proves that the interval
     * is not global or shared among contexts.
     */
    interval = pwglGetSwapIntervalEXT();
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
    ok(interval == 1, "Expected default swap interval 1, got %d\n", interval);

    /* Test if setting the parent of a window resets the swap interval. */
    ret = wglMakeCurrent(dc1, ctx1);
    ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());

    old_parent = SetParent(window1, window2);
    ok(!!old_parent, "Failed to make window1 a child of window2, last error %#x.\n", GetLastError());

    interval = pwglGetSwapIntervalEXT();
    ok(interval == 0, "Expected swap interval 0, got %d\n", interval);
1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718

    ret = wglDeleteContext(ctx1);
    ok(ret, "Failed to delete GL context, last error %#x.\n", GetLastError());
    ret = wglDeleteContext(ctx2);
    ok(ret, "Failed to delete GL context, last error %#x.\n", GetLastError());

    ReleaseDC(window1, dc1);
    DestroyWindow(window1);
    ReleaseDC(window2, dc2);
    DestroyWindow(window2);

    wglMakeCurrent(oldhdc, oldctx);
}

1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742
START_TEST(opengl)
{
    HWND hwnd;
    PIXELFORMATDESCRIPTOR pfd = {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,                     /* version */
        PFD_DRAW_TO_WINDOW |
        PFD_SUPPORT_OPENGL |
        PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        24,                    /* 24-bit color depth */
        0, 0, 0, 0, 0, 0,      /* color bits */
        0,                     /* alpha buffer */
        0,                     /* shift bit */
        0,                     /* accumulation buffer */
        0, 0, 0, 0,            /* accum bits */
        32,                    /* z-buffer */
        0,                     /* stencil buffer */
        0,                     /* auxiliary buffer */
        PFD_MAIN_PLANE,        /* main layer */
        0,                     /* reserved */
        0, 0, 0                /* layer masks */
    };

1743 1744
    hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW, 10, 10, 200, 200, NULL, NULL,
            NULL, NULL);
1745 1746 1747 1748 1749 1750
    ok(hwnd != NULL, "err: %d\n", GetLastError());
    if (hwnd)
    {
        HDC hdc;
        int iPixelFormat, res;
        HGLRC hglrc;
1751
        DWORD error;
1752 1753 1754 1755 1756
        ShowWindow(hwnd, SW_SHOW);

        hdc = GetDC(hwnd);

        iPixelFormat = ChoosePixelFormat(hdc, &pfd);
1757 1758 1759 1760 1761 1762
        if(iPixelFormat == 0)
        {
            /* This should never happen as ChoosePixelFormat always returns a closest match, but currently this fails in Wine if we don't have glX */
            win_skip("Unable to find pixel format.\n");
            goto cleanup;
        }
1763

1764 1765
        /* We shouldn't be able to create a context from a hdc which doesn't have a pixel format set */
        hglrc = wglCreateContext(hdc);
1766
        ok(hglrc == NULL, "wglCreateContext should fail when no pixel format has been set, but it passed\n");
1767
        error = GetLastError();
1768
        ok(error == ERROR_INVALID_PIXEL_FORMAT, "expected ERROR_INVALID_PIXEL_FORMAT for wglCreateContext without a pixelformat set, but received %#x\n", error);
1769

1770 1771 1772
        res = SetPixelFormat(hdc, iPixelFormat, &pfd);
        ok(res, "SetPixelformat failed: %x\n", GetLastError());

1773 1774
        test_bitmap_rendering( TRUE );
        test_bitmap_rendering( FALSE );
1775
        test_minimized();
1776
        test_window_dc();
1777
        test_message_window();
1778 1779
        test_dc(hwnd, hdc);

1780 1781
        ok(!glGetString(GL_RENDERER) && !glGetString(GL_VERSION) && !glGetString(GL_VENDOR),
           "Expected NULL string when no active context is set\n");
1782 1783 1784
        hglrc = wglCreateContext(hdc);
        res = wglMakeCurrent(hdc, hglrc);
        ok(res, "wglMakeCurrent failed!\n");
1785 1786 1787 1788 1789 1790
        if(res)
        {
            trace("OpenGL renderer: %s\n", glGetString(GL_RENDERER));
            trace("OpenGL driver version: %s\n", glGetString(GL_VERSION));
            trace("OpenGL vendor: %s\n", glGetString(GL_VENDOR));
        }
1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
        else
        {
            skip("Skipping OpenGL tests without a current context\n");
            return;
        }

        /* Initialisation of WGL functions depends on an implicit WGL context. For this reason we can't load them before making
         * any WGL call :( On Wine this would work but not on real Windows because there can be different implementations (software, ICD, MCD).
         */
        init_functions();
1801
        test_getprocaddress(hdc);
1802
        test_deletecontext(hwnd, hdc);
1803 1804
        test_makecurrent(hdc);

1805 1806 1807
        /* The lack of wglGetExtensionsStringARB in general means broken software rendering or the lack of decent OpenGL support, skip tests in such cases */
        if (!pwglGetExtensionsStringARB)
        {
1808
            win_skip("wglGetExtensionsStringARB is not available\n");
1809 1810
            return;
        }
1811

1812
        test_choosepixelformat();
1813
        test_setpixelformat(hdc);
1814
        test_destroy(hdc);
1815
        test_sharelists(hdc);
1816
        test_colorbits(hdc);
1817
        test_gdi_dbuf(hdc);
1818
        test_acceleration(hdc);
1819

1820 1821 1822
        wgl_extensions = pwglGetExtensionsStringARB(hdc);
        if(wgl_extensions == NULL) skip("Skipping opengl32 tests because this OpenGL implementation doesn't support WGL extensions!\n");

1823 1824 1825
        if(strstr(wgl_extensions, "WGL_ARB_create_context"))
            test_opengl3(hdc);

1826
        if(strstr(wgl_extensions, "WGL_ARB_make_current_read"))
1827
        {
1828
            test_make_current_read(hdc);
1829 1830
            test_destroy_read(hdc);
        }
1831
        else
1832
            skip("WGL_ARB_make_current_read not supported, skipping test\n");
1833

1834 1835 1836
        if(strstr(wgl_extensions, "WGL_ARB_pbuffer"))
            test_pbuffers(hdc);
        else
1837
            skip("WGL_ARB_pbuffer not supported, skipping pbuffer test\n");
1838

1839 1840 1841 1842 1843
        if(strstr(wgl_extensions, "WGL_EXT_swap_control"))
            test_swap_control(hdc);
        else
            skip("WGL_EXT_swap_control not supported, skipping test\n");

1844 1845
cleanup:
        ReleaseDC(hwnd, hdc);
1846 1847 1848
        DestroyWindow(hwnd);
    }
}