opengl.c 139 KB
Newer Older
1
/*
Lionel Ulmer's avatar
Lionel Ulmer committed
2 3 4
 * X11DRV OpenGL functions
 *
 * Copyright 2000 Lionel Ulmer
5 6
 * Copyright 2005 Alex Woods
 * Copyright 2005 Raphael Junqueira
7
 * Copyright 2006-2009 Roderick Colenbrander
8
 * Copyright 2006 Tomas Carnecky
Lionel Ulmer's avatar
Lionel Ulmer committed
9
 *
10 11 12 13 14 15 16 17 18 19 20 21
 * 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
22
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Lionel Ulmer's avatar
Lionel Ulmer committed
23 24 25
 */

#include "config.h"
26
#include "wine/port.h"
Lionel Ulmer's avatar
Lionel Ulmer committed
27

28
#include <assert.h>
Lionel Ulmer's avatar
Lionel Ulmer committed
29 30 31
#include <stdlib.h>
#include <string.h>

32 33 34 35 36 37 38
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif

Lionel Ulmer's avatar
Lionel Ulmer committed
39
#include "x11drv.h"
40
#include "winternl.h"
41
#include "wine/library.h"
42
#include "wine/debug.h"
Lionel Ulmer's avatar
Lionel Ulmer committed
43

44
WINE_DEFAULT_DEBUG_CHANNEL(wgl);
45
WINE_DECLARE_DEBUG_CHANNEL(winediag);
Lionel Ulmer's avatar
Lionel Ulmer committed
46

47
#ifdef SONAME_LIBGL
Lionel Ulmer's avatar
Lionel Ulmer committed
48

49 50 51 52
#undef APIENTRY
#undef CALLBACK
#undef WINAPI

53 54 55 56 57 58
#ifdef HAVE_GL_GL_H
# include <GL/gl.h>
#endif
#ifdef HAVE_GL_GLX_H
# include <GL/glx.h>
#endif
59

60 61
#include "wine/wgl.h"

62 63 64 65 66 67 68 69 70
#undef APIENTRY
#undef CALLBACK
#undef WINAPI

/* Redefines the constants */
#define CALLBACK    __stdcall
#define WINAPI      __stdcall
#define APIENTRY    WINAPI

71

72
WINE_DECLARE_DEBUG_CHANNEL(fps);
73

74 75 76 77 78
typedef struct wine_glextension {
    const char *extName;
    struct {
        const char *funcName;
        void *funcAddress;
79
    } extEntryPoints[9];
80 81 82 83
} WineGLExtension;

struct WineGLInfo {
    const char *glVersion;
84
    char *glExtensions;
85 86 87 88

    int glxVersion[2];

    const char *glxServerVersion;
89
    const char *glxServerVendor;
90 91 92
    const char *glxServerExtensions;

    const char *glxClientVersion;
93
    const char *glxClientVendor;
94 95 96 97 98 99 100 101
    const char *glxClientExtensions;

    const char *glxExtensions;

    BOOL glxDirect;
    char wglExtensions[4096];
};

102
typedef struct wine_glpixelformat {
103 104 105
    int         iPixelFormat;
    GLXFBConfig fbconfig;
    int         fmt_id;
106
    int         render_type;
107
    BOOL        offscreenOnly;
108
    DWORD       dwFlags; /* We store some PFD_* flags in here for emulated bitmap formats */
109 110
} WineGLPixelFormat;

111 112
typedef struct wine_glcontext {
    HDC hdc;
113
    BOOL do_escape;
114 115
    BOOL has_been_current;
    BOOL sharing;
116
    DWORD tid;
117
    BOOL gl3_context;
118 119
    XVisualInfo *vis;
    WineGLPixelFormat *fmt;
120 121
    int numAttribs; /* This is needed for delaying wglCreateContextAttribsARB */
    int attribList[16]; /* This is needed for delaying wglCreateContextAttribsARB */
122
    GLXContext ctx;
123
    HDC read_hdc;
124 125
    Drawable drawables[2];
    BOOL refresh_drawables;
126 127 128 129
    struct wine_glcontext *next;
    struct wine_glcontext *prev;
} Wine_GLContext;

130 131 132 133 134 135 136 137 138
typedef struct wine_glpbuffer {
    Drawable   drawable;
    Display*   display;
    WineGLPixelFormat* fmt;
    int        width;
    int        height;
    int*       attribList;
    HDC        hdc;

139 140 141 142
    int        use_render_texture; /* This is also the internal texture format */
    int        texture_bind_target;
    int        texture_bpp;
    GLint      texture_format;
143
    GLuint     texture_target;
144
    GLenum     texture_type;
145 146 147 148
    GLuint     texture;
    int        texture_level;
} Wine_GLPBuffer;

149
static Wine_GLContext *context_list;
150
static struct WineGLInfo WineGLInfo = { 0 };
151
static int use_render_texture_emulation = 1;
152
static int use_render_texture_ati = 0;
153 154
static int swap_interval = 1;

155 156 157 158 159
#define MAX_EXTENSIONS 16
static const WineGLExtension *WineGLExtensionList[MAX_EXTENSIONS];
static int WineGLExtensionListSize;

static void X11DRV_WineGL_LoadExtensions(void);
160
static WineGLPixelFormat* ConvertPixelFormatWGLtoGLX(Display *display, int iPixelFormat, BOOL AllowOffscreen, int *fmt_count);
161 162
static BOOL glxRequireVersion(int requiredVersion);
static BOOL glxRequireExtension(const char *requiredExtension);
163

Eric Pouech's avatar
Eric Pouech committed
164
static void dump_PIXELFORMATDESCRIPTOR(const PIXELFORMATDESCRIPTOR *ppfd) {
165 166 167
  TRACE("  - size / version : %d / %d\n", ppfd->nSize, ppfd->nVersion);
  TRACE("  - dwFlags : ");
#define TEST_AND_DUMP(t,tv) if ((t) & (tv)) TRACE(#tv " ")
Lionel Ulmer's avatar
Lionel Ulmer committed
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
  TEST_AND_DUMP(ppfd->dwFlags, PFD_DEPTH_DONTCARE);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_DOUBLEBUFFER);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_DOUBLEBUFFER_DONTCARE);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_DRAW_TO_WINDOW);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_DRAW_TO_BITMAP);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_GENERIC_ACCELERATED);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_GENERIC_FORMAT);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_NEED_PALETTE);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_NEED_SYSTEM_PALETTE);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_STEREO);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_STEREO_DONTCARE);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_GDI);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_OPENGL);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_COPY);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_EXCHANGE);
  TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_LAYER_BUFFERS);
184 185 186
  /* PFD_SUPPORT_COMPOSITION is new in Vista, it is similar to composition
   * under X e.g. COMPOSITE + GLX_EXT_TEXTURE_FROM_PIXMAP. */
  TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_COMPOSITION);
Lionel Ulmer's avatar
Lionel Ulmer committed
187
#undef TEST_AND_DUMP
188
  TRACE("\n");
189

190
  TRACE("  - iPixelType : ");
Lionel Ulmer's avatar
Lionel Ulmer committed
191
  switch (ppfd->iPixelType) {
192 193
  case PFD_TYPE_RGBA: TRACE("PFD_TYPE_RGBA"); break;
  case PFD_TYPE_COLORINDEX: TRACE("PFD_TYPE_COLORINDEX"); break;
Lionel Ulmer's avatar
Lionel Ulmer committed
194
  }
195
  TRACE("\n");
196

197 198 199 200 201 202 203 204 205
  TRACE("  - Color   : %d\n", ppfd->cColorBits);
  TRACE("  - Red     : %d\n", ppfd->cRedBits);
  TRACE("  - Green   : %d\n", ppfd->cGreenBits);
  TRACE("  - Blue    : %d\n", ppfd->cBlueBits);
  TRACE("  - Alpha   : %d\n", ppfd->cAlphaBits);
  TRACE("  - Accum   : %d\n", ppfd->cAccumBits);
  TRACE("  - Depth   : %d\n", ppfd->cDepthBits);
  TRACE("  - Stencil : %d\n", ppfd->cStencilBits);
  TRACE("  - Aux     : %d\n", ppfd->cAuxBuffers);
206

207
  TRACE("  - iLayerType : ");
Lionel Ulmer's avatar
Lionel Ulmer committed
208
  switch (ppfd->iLayerType) {
209 210 211
  case PFD_MAIN_PLANE: TRACE("PFD_MAIN_PLANE"); break;
  case PFD_OVERLAY_PLANE: TRACE("PFD_OVERLAY_PLANE"); break;
  case (BYTE)PFD_UNDERLAY_PLANE: TRACE("PFD_UNDERLAY_PLANE"); break;
Lionel Ulmer's avatar
Lionel Ulmer committed
212
  }
213
  TRACE("\n");
Lionel Ulmer's avatar
Lionel Ulmer committed
214
}
215

216 217 218
#define PUSH1(attribs,att)        do { attribs[nAttribs++] = (att); } while (0)
#define PUSH2(attribs,att,value)  do { attribs[nAttribs++] = (att); attribs[nAttribs++] = (value); } while(0)

219
#define MAKE_FUNCPTR(f) static typeof(f) * p##f;
220
/* GLX 1.0 */
221
MAKE_FUNCPTR(glXChooseVisual)
222
MAKE_FUNCPTR(glXCopyContext)
223 224 225
MAKE_FUNCPTR(glXCreateContext)
MAKE_FUNCPTR(glXCreateGLXPixmap)
MAKE_FUNCPTR(glXGetCurrentContext)
226
MAKE_FUNCPTR(glXGetCurrentDrawable)
227 228
MAKE_FUNCPTR(glXDestroyContext)
MAKE_FUNCPTR(glXDestroyGLXPixmap)
229
MAKE_FUNCPTR(glXGetConfig)
230 231
MAKE_FUNCPTR(glXIsDirect)
MAKE_FUNCPTR(glXMakeCurrent)
232 233
MAKE_FUNCPTR(glXSwapBuffers)
MAKE_FUNCPTR(glXQueryExtension)
234
MAKE_FUNCPTR(glXQueryVersion)
235
MAKE_FUNCPTR(glXUseXFont)
236 237 238 239

/* GLX 1.1 */
MAKE_FUNCPTR(glXGetClientString)
MAKE_FUNCPTR(glXQueryExtensionsString)
240
MAKE_FUNCPTR(glXQueryServerString)
241

242
/* GLX 1.3 */
243 244
MAKE_FUNCPTR(glXGetFBConfigs)
MAKE_FUNCPTR(glXChooseFBConfig)
245
MAKE_FUNCPTR(glXCreatePbuffer)
246
MAKE_FUNCPTR(glXCreateNewContext)
247
MAKE_FUNCPTR(glXDestroyPbuffer)
248
MAKE_FUNCPTR(glXGetFBConfigAttrib)
249
MAKE_FUNCPTR(glXGetVisualFromFBConfig)
250 251
MAKE_FUNCPTR(glXMakeContextCurrent)
MAKE_FUNCPTR(glXQueryDrawable)
252
MAKE_FUNCPTR(glXGetCurrentReadDrawable)
253

254
/* GLX Extensions */
255
static GLXContext (*pglXCreateContextAttribsARB)(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
256 257 258
static void* (*pglXGetProcAddressARB)(const GLubyte *);
static int   (*pglXSwapIntervalSGI)(int);

259 260 261 262 263
/* ATI GLX Extensions */
static BOOL  (*pglXBindTexImageATI)(Display *dpy, GLXPbuffer pbuffer, int buffer);
static BOOL  (*pglXReleaseTexImageATI)(Display *dpy, GLXPbuffer pbuffer, int buffer);
static BOOL  (*pglXDrawableAttribATI)(Display *dpy, GLXDrawable draw, const int *attribList);

264 265 266 267
/* NV GLX Extension */
static void* (*pglXAllocateMemoryNV)(GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
static void  (*pglXFreeMemoryNV)(GLvoid *pointer);

268 269 270
/* MESA GLX Extensions */
static void (*pglXCopySubBufferMESA)(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height);

271 272
/* Standard OpenGL */
MAKE_FUNCPTR(glBindTexture)
273
MAKE_FUNCPTR(glBitmap)
274
MAKE_FUNCPTR(glCopyTexSubImage1D)
275
MAKE_FUNCPTR(glCopyTexImage2D)
276
MAKE_FUNCPTR(glCopyTexSubImage2D)
277
MAKE_FUNCPTR(glDrawBuffer)
278
MAKE_FUNCPTR(glEndList)
279 280 281
MAKE_FUNCPTR(glGetError)
MAKE_FUNCPTR(glGetIntegerv)
MAKE_FUNCPTR(glGetString)
282 283
MAKE_FUNCPTR(glNewList)
MAKE_FUNCPTR(glPixelStorei)
284 285
MAKE_FUNCPTR(glReadPixels)
MAKE_FUNCPTR(glTexImage2D)
286 287
MAKE_FUNCPTR(glFinish)
MAKE_FUNCPTR(glFlush)
288 289
#undef MAKE_FUNCPTR

290 291 292 293 294 295
static int GLXErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
{
    /* In the future we might want to find the exact X or GLX error to report back to the app */
    return 1;
}

296
static BOOL infoInitialized = FALSE;
297
static BOOL X11DRV_WineGL_InitOpenglInfo(void)
298 299
{
    int screen = DefaultScreen(gdi_display);
300
    Window win = 0, root = 0;
301
    const char* str;
302 303
    XVisualInfo *vis;
    GLXContext ctx = NULL;
304 305
    XSetWindowAttributes attr;
    BOOL ret = FALSE;
306
    int attribList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, None};
307 308 309 310 311

    if (infoInitialized)
        return TRUE;
    infoInitialized = TRUE;

312 313
    attr.override_redirect = True;
    attr.colormap = None;
314
    attr.border_pixel = 0;
315

316 317
    wine_tsx11_lock();

318
    vis = pglXChooseVisual(gdi_display, screen, attribList);
319
    if (vis) {
320
#ifdef __i386__
321
        WORD old_fs = wine_get_fs();
322 323
        /* Create a GLX Context. Without one we can't query GL information */
        ctx = pglXCreateContext(gdi_display, vis, None, GL_TRUE);
324 325 326 327 328
        if (wine_get_fs() != old_fs)
        {
            wine_set_fs( old_fs );
            ERR( "%%fs register corrupted, probably broken ATI driver, disabling OpenGL.\n" );
            ERR( "You need to set the \"UseFastTls\" option to \"2\" in your X config file.\n" );
329
            goto done;
330
        }
331 332 333
#else
        ctx = pglXCreateContext(gdi_display, vis, None, GL_TRUE);
#endif
334
    }
335 336 337 338 339 340
    if (!ctx) goto done;

    root = RootWindow( gdi_display, vis->screen );
    if (vis->visual != DefaultVisual( gdi_display, vis->screen ))
        attr.colormap = XCreateColormap( gdi_display, root, vis->visual, AllocNone );
    if ((win = XCreateWindow( gdi_display, root, -1, -1, 1, 1, 0, vis->depth, InputOutput,
341
                              vis->visual, CWBorderPixel | CWOverrideRedirect | CWColormap, &attr )))
342 343 344
        XMapWindow( gdi_display, win );
    else
        win = root;
345

346
    pglXMakeCurrent(gdi_display, win, ctx);
347 348

    WineGLInfo.glVersion = (const char *) pglGetString(GL_VERSION);
349 350 351
    str = (const char *) pglGetString(GL_EXTENSIONS);
    WineGLInfo.glExtensions = HeapAlloc(GetProcessHeap(), 0, strlen(str)+1);
    strcpy(WineGLInfo.glExtensions, str);
352 353 354 355 356

    /* Get the common GLX version supported by GLX client and server ( major/minor) */
    pglXQueryVersion(gdi_display, &WineGLInfo.glxVersion[0], &WineGLInfo.glxVersion[1]);

    WineGLInfo.glxServerVersion = pglXQueryServerString(gdi_display, screen, GLX_VERSION);
357
    WineGLInfo.glxServerVendor = pglXQueryServerString(gdi_display, screen, GLX_VENDOR);
358 359 360
    WineGLInfo.glxServerExtensions = pglXQueryServerString(gdi_display, screen, GLX_EXTENSIONS);

    WineGLInfo.glxClientVersion = pglXGetClientString(gdi_display, GLX_VERSION);
361
    WineGLInfo.glxClientVendor = pglXGetClientString(gdi_display, GLX_VENDOR);
362 363 364 365 366 367
    WineGLInfo.glxClientExtensions = pglXGetClientString(gdi_display, GLX_EXTENSIONS);

    WineGLInfo.glxExtensions = pglXQueryExtensionsString(gdi_display, screen);
    WineGLInfo.glxDirect = pglXIsDirect(gdi_display, ctx);

    TRACE("GL version             : %s.\n", WineGLInfo.glVersion);
368
    TRACE("GL renderer            : %s.\n", pglGetString(GL_RENDERER));
369 370
    TRACE("GLX version            : %d.%d.\n", WineGLInfo.glxVersion[0], WineGLInfo.glxVersion[1]);
    TRACE("Server GLX version     : %s.\n", WineGLInfo.glxServerVersion);
371
    TRACE("Server GLX vendor:     : %s.\n", WineGLInfo.glxServerVendor);
372
    TRACE("Client GLX version     : %s.\n", WineGLInfo.glxClientVersion);
373
    TRACE("Client GLX vendor:     : %s.\n", WineGLInfo.glxClientVendor);
374 375
    TRACE("Direct rendering enabled: %s\n", WineGLInfo.glxDirect ? "True" : "False");

376 377 378 379 380 381 382 383 384
    if(!WineGLInfo.glxDirect)
    {
        int fd = ConnectionNumber(gdi_display);
        struct sockaddr_un uaddr;
        unsigned int uaddrlen = sizeof(struct sockaddr_un);

        /* In general indirect rendering on a local X11 server indicates a driver problem.
         * Detect a local X11 server by checking whether the X11 socket is a Unix socket.
         */
385
        if(!getsockname(fd, (struct sockaddr *)&uaddr, &uaddrlen) && uaddr.sun_family == AF_UNIX)
386 387
            ERR_(winediag)("Direct rendering is disabled, most likely your OpenGL drivers haven't been installed correctly\n");
    }
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
    else
    {
        /* In general you would expect that if direct rendering is returned, that you receive hardware
         * accelerated OpenGL rendering. The definition of direct rendering is that rendering is performed
         * client side without sending all GL commands to X using the GLX protocol. When Mesa falls back to
         * software rendering, it shows direct rendering.
         *
         * Depending on the cause of software rendering a different rendering string is shown. In case Mesa fails
         * to load a DRI module 'Software Rasterizer' is returned. When Mesa is compiled as a OpenGL reference driver
         * it shows 'Mesa X11'.
         */
        const char *gl_renderer = (const char *)pglGetString(GL_RENDERER);
        if(!strcmp(gl_renderer, "Software Rasterizer") || !strcmp(gl_renderer, "Mesa X11"))
            ERR_(winediag)("The Mesa OpenGL driver is using software rendering, most likely your OpenGL drivers haven't been installed correctly\n");
    }
403
    ret = TRUE;
404

405
done:
406
    if(vis) XFree(vis);
407 408 409 410
    if(ctx) {
        pglXMakeCurrent(gdi_display, None, NULL);    
        pglXDestroyContext(gdi_display, ctx);
    }
411 412
    if (win != root) XDestroyWindow( gdi_display, win );
    if (attr.colormap) XFreeColormap( gdi_display, attr.colormap );
413
    wine_tsx11_unlock();
414 415
    if (!ret) ERR(" couldn't initialize OpenGL, expect problems\n");
    return ret;
416 417
}

418 419 420 421 422 423
void X11DRV_OpenGL_Cleanup(void)
{
    HeapFree(GetProcessHeap(), 0, WineGLInfo.glExtensions);
    infoInitialized = FALSE;
}

424 425 426 427 428
static BOOL has_opengl(void)
{
    static int init_done;
    static void *opengl_handle;

429
    char buffer[200];
430 431
    int error_base, event_base;

432 433 434
    if (init_done) return (opengl_handle != NULL);
    init_done = 1;

435 436
    /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient
       and include all dependencies */
437 438 439 440 441
    opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, buffer, sizeof(buffer));
    if (opengl_handle == NULL)
    {
        ERR( "Failed to load libGL: %s\n", buffer );
        ERR( "OpenGL support is disabled.\n");
442 443 444
        return FALSE;
    }

445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
    pglXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
    if (pglXGetProcAddressARB == NULL) {
        ERR("Could not find glXGetProcAddressARB in libGL, disabling OpenGL.\n");
        goto failed;
    }

#define LOAD_FUNCPTR(f) do if((p##f = (void*)pglXGetProcAddressARB((const unsigned char*)#f)) == NULL) \
    { \
        ERR( "%s not found in libGL, disabling OpenGL.\n", #f ); \
        goto failed; \
    } while(0)

    /* GLX 1.0 */
    LOAD_FUNCPTR(glXChooseVisual);
    LOAD_FUNCPTR(glXCopyContext);
    LOAD_FUNCPTR(glXCreateContext);
    LOAD_FUNCPTR(glXCreateGLXPixmap);
    LOAD_FUNCPTR(glXGetCurrentContext);
    LOAD_FUNCPTR(glXGetCurrentDrawable);
    LOAD_FUNCPTR(glXDestroyContext);
    LOAD_FUNCPTR(glXDestroyGLXPixmap);
    LOAD_FUNCPTR(glXGetConfig);
    LOAD_FUNCPTR(glXIsDirect);
    LOAD_FUNCPTR(glXMakeCurrent);
    LOAD_FUNCPTR(glXSwapBuffers);
    LOAD_FUNCPTR(glXQueryExtension);
    LOAD_FUNCPTR(glXQueryVersion);
    LOAD_FUNCPTR(glXUseXFont);

    /* GLX 1.1 */
    LOAD_FUNCPTR(glXGetClientString);
    LOAD_FUNCPTR(glXQueryExtensionsString);
    LOAD_FUNCPTR(glXQueryServerString);

    /* GLX 1.3 */
    LOAD_FUNCPTR(glXCreatePbuffer);
    LOAD_FUNCPTR(glXCreateNewContext);
    LOAD_FUNCPTR(glXDestroyPbuffer);
    LOAD_FUNCPTR(glXMakeContextCurrent);
    LOAD_FUNCPTR(glXGetCurrentReadDrawable);
    LOAD_FUNCPTR(glXGetFBConfigs);

    /* Standard OpenGL calls */
    LOAD_FUNCPTR(glBindTexture);
    LOAD_FUNCPTR(glBitmap);
    LOAD_FUNCPTR(glCopyTexSubImage1D);
    LOAD_FUNCPTR(glCopyTexImage2D);
    LOAD_FUNCPTR(glCopyTexSubImage2D);
    LOAD_FUNCPTR(glDrawBuffer);
    LOAD_FUNCPTR(glEndList);
    LOAD_FUNCPTR(glGetError);
    LOAD_FUNCPTR(glGetIntegerv);
    LOAD_FUNCPTR(glGetString);
    LOAD_FUNCPTR(glNewList);
    LOAD_FUNCPTR(glPixelStorei);
    LOAD_FUNCPTR(glReadPixels);
    LOAD_FUNCPTR(glTexImage2D);
    LOAD_FUNCPTR(glFinish);
    LOAD_FUNCPTR(glFlush);
504 505 506 507 508
#undef LOAD_FUNCPTR

/* It doesn't matter if these fail. They'll only be used if the driver reports
   the associated extension is available (and if a driver reports the extension
   is available but fails to provide the functions, it's quite broken) */
509
#define LOAD_FUNCPTR(f) p##f = pglXGetProcAddressARB((const GLubyte *)#f)
510 511
    /* ARB GLX Extension */
    LOAD_FUNCPTR(glXCreateContextAttribsARB);
512 513
    /* SGI GLX Extension */
    LOAD_FUNCPTR(glXSwapIntervalSGI);
514 515 516
    /* NV GLX Extension */
    LOAD_FUNCPTR(glXAllocateMemoryNV);
    LOAD_FUNCPTR(glXFreeMemoryNV);
517 518
#undef LOAD_FUNCPTR

519
    if(!X11DRV_WineGL_InitOpenglInfo()) goto failed;
520

521
    wine_tsx11_lock();
522
    if (pglXQueryExtension(gdi_display, &error_base, &event_base)) {
523
        TRACE("GLX is up and running error_base = %d\n", error_base);
524
    } else {
525 526 527
        wine_tsx11_unlock();
        ERR( "GLX extension is missing, disabling OpenGL.\n" );
        goto failed;
528
    }
529

530 531 532 533 534 535 536 537
    /* In case of GLX you have direct and indirect rendering. Most of the time direct rendering is used
     * as in general only that is hardware accelerated. In some cases like in case of remote X indirect
     * rendering is used.
     *
     * The main problem for our OpenGL code is that we need certain GLX calls but their presence
     * depends on the reported GLX client / server version and on the client / server extension list.
     * Those don't have to be the same.
     *
538 539 540 541 542 543
     * In general the server GLX information lists the capabilities in case of indirect rendering.
     * When direct rendering is used, the OpenGL client library is responsible for which GLX calls are
     * available and in that case the client GLX informat can be used.
     * OpenGL programs should use the 'intersection' of both sets of information which is advertised
     * in the GLX version/extension list. When a program does this it works for certain for both
     * direct and indirect rendering.
544
     *
545 546 547 548 549 550 551 552
     * The problem we are having in this area is that ATI's Linux drivers are broken. For some reason
     * they haven't added some very important GLX extensions like GLX_SGIX_fbconfig to their client
     * extension list which causes this extension not to be listed. (Wine requires this extension).
     * ATI advertises a GLX client version of 1.3 which implies that this fbconfig extension among
     * pbuffers is around.
     *
     * In order to provide users of Ati's proprietary drivers with OpenGL support, we need to detect
     * the ATI drivers and from then on use GLX client information for them.
553 554
     */

555
    if(glxRequireVersion(3)) {
556 557 558 559
        pglXChooseFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfig");
        pglXGetFBConfigAttrib = pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttrib");
        pglXGetVisualFromFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfig");
        pglXQueryDrawable = pglXGetProcAddressARB((const GLubyte *) "glXQueryDrawable");
560
    } else if(glxRequireExtension("GLX_SGIX_fbconfig")) {
561 562 563
        pglXChooseFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfigSGIX");
        pglXGetFBConfigAttrib = pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttribSGIX");
        pglXGetVisualFromFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfigSGIX");
564 565 566 567

        /* The mesa libGL client library seems to forward glXQueryDrawable to the Xserver, so only
         * enable this function when the Xserver understand GLX 1.3 or newer
         */
568
        pglXQueryDrawable = NULL;
569 570
     } else if(strcmp("ATI", WineGLInfo.glxClientVendor) == 0) {
        TRACE("Overriding ATI GLX capabilities!\n");
571 572 573 574
        pglXChooseFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfig");
        pglXGetFBConfigAttrib = pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttrib");
        pglXGetVisualFromFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfig");
        pglXQueryDrawable = pglXGetProcAddressARB((const GLubyte *) "glXQueryDrawable");
575 576 577 578 579 580 581 582 583

        /* Use client GLX information in case of the ATI drivers. We override the
         * capabilities over here and not somewhere else as ATI might better their
         * life in the future. In case they release proper drivers this block of
         * code won't be called. */
        WineGLInfo.glxExtensions = WineGLInfo.glxClientExtensions;
    } else {
         ERR(" glx_version is %s and GLX_SGIX_fbconfig extension is unsupported. Expect problems.\n", WineGLInfo.glxServerVersion);
    }
584

585
    if(glxRequireExtension("GLX_ATI_render_texture")) {
586
        use_render_texture_ati = 1;
587 588 589
        pglXBindTexImageATI = pglXGetProcAddressARB((const GLubyte *) "glXBindTexImageATI");
        pglXReleaseTexImageATI = pglXGetProcAddressARB((const GLubyte *) "glXReleaseTexImageATI");
        pglXDrawableAttribATI = pglXGetProcAddressARB((const GLubyte *) "glXDrawableAttribATI");
590 591
    }

592
    if(glxRequireExtension("GLX_MESA_copy_sub_buffer")) {
593
        pglXCopySubBufferMESA = pglXGetProcAddressARB((const GLubyte *) "glXCopySubBufferMESA");
594 595
    }

596 597
    X11DRV_WineGL_LoadExtensions();

598
    wine_tsx11_unlock();
599
    return TRUE;
600

601
failed:
602 603
    wine_dlclose(opengl_handle, NULL, 0);
    opengl_handle = NULL;
604
    return FALSE;
605 606
}

607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
static inline Wine_GLContext *alloc_context(void)
{
    Wine_GLContext *ret;

    if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
    {
        ret->next = context_list;
        if (context_list) context_list->prev = ret;
        context_list = ret;
    }
    return ret;
}

static inline void free_context(Wine_GLContext *context)
{
    if (context->next != NULL) context->next->prev = context->prev;
    if (context->prev != NULL) context->prev->next = context->next;
    else context_list = context->next;

626
    if (context->vis) XFree(context->vis);
627 628 629
    HeapFree(GetProcessHeap(), 0, context);
}

630
static inline BOOL is_valid_context( Wine_GLContext *ctx )
631 632 633 634 635 636
{
    Wine_GLContext *ptr;
    for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
    return (ptr != NULL);
}

637 638 639 640
static int describeContext(Wine_GLContext* ctx) {
    int tmp;
    int ctx_vis_id;
    TRACE(" Context %p have (vis:%p):\n", ctx, ctx->vis);
641
    pglXGetFBConfigAttrib(gdi_display, ctx->fmt->fbconfig, GLX_FBCONFIG_ID, &tmp);
642
    TRACE(" - FBCONFIG_ID 0x%x\n", tmp);
643
    pglXGetFBConfigAttrib(gdi_display, ctx->fmt->fbconfig, GLX_VISUAL_ID, &tmp);
644 645 646 647 648
    TRACE(" - VISUAL_ID 0x%x\n", tmp);
    ctx_vis_id = tmp;
    return ctx_vis_id;
}

649
static BOOL describeDrawable(X11DRV_PDEVICE *physDev) {
650
    int tmp;
651 652
    WineGLPixelFormat *fmt;
    int fmt_count = 0;
653

654 655
    fmt = ConvertPixelFormatWGLtoGLX(gdi_display, physDev->current_pf, TRUE /* Offscreen */, &fmt_count);
    if(!fmt) return FALSE;
656

657 658 659 660
    TRACE(" HDC %p has:\n", physDev->hdc);
    TRACE(" - iPixelFormat %d\n", fmt->iPixelFormat);
    TRACE(" - Drawable %p\n", (void*) get_glxdrawable(physDev));
    TRACE(" - FBCONFIG_ID 0x%x\n", fmt->fmt_id);
661

662 663
    pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_VISUAL_ID, &tmp);
    TRACE(" - VISUAL_ID 0x%x\n", tmp);
664

665
    return TRUE;
666 667
}

668 669 670 671
static int ConvertAttribWGLtoGLX(const int* iWGLAttr, int* oGLXAttr, Wine_GLPBuffer* pbuf) {
  int nAttribs = 0;
  unsigned cur = 0; 
  int pop;
672
  int drawattrib = 0;
673
  int nvfloatattrib = GLX_DONT_CARE;
674
  int pixelattrib = ~0;
675

676 677 678
  /* The list of WGL attributes is allowed to be NULL. We don't return here for NULL
   * because we need to do fixups for GLX_DRAWABLE_TYPE/GLX_RENDER_TYPE/GLX_FLOAT_COMPONENTS_NV. */
  while (iWGLAttr && 0 != iWGLAttr[cur]) {
679 680 681
    TRACE("pAttr[%d] = %x\n", cur, iWGLAttr[cur]);

    switch (iWGLAttr[cur]) {
682 683 684 685 686
    case WGL_AUX_BUFFERS_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_AUX_BUFFERS, pop);
      TRACE("pAttr[%d] = GLX_AUX_BUFFERS: %d\n", cur, pop);
      break;
687 688
    case WGL_COLOR_BITS_ARB:
      pop = iWGLAttr[++cur];
689 690
      PUSH2(oGLXAttr, GLX_BUFFER_SIZE, pop);
      TRACE("pAttr[%d] = GLX_BUFFER_SIZE: %d\n", cur, pop);
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
      break;
    case WGL_BLUE_BITS_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_BLUE_SIZE, pop);
      TRACE("pAttr[%d] = GLX_BLUE_SIZE: %d\n", cur, pop);
      break;
    case WGL_RED_BITS_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_RED_SIZE, pop);
      TRACE("pAttr[%d] = GLX_RED_SIZE: %d\n", cur, pop);
      break;
    case WGL_GREEN_BITS_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_GREEN_SIZE, pop);
      TRACE("pAttr[%d] = GLX_GREEN_SIZE: %d\n", cur, pop);
      break;
    case WGL_ALPHA_BITS_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_ALPHA_SIZE, pop);
      TRACE("pAttr[%d] = GLX_ALPHA_SIZE: %d\n", cur, pop);
      break;
    case WGL_DEPTH_BITS_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_DEPTH_SIZE, pop);
      TRACE("pAttr[%d] = GLX_DEPTH_SIZE: %d\n", cur, pop);
      break;
    case WGL_STENCIL_BITS_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_STENCIL_SIZE, pop);
      TRACE("pAttr[%d] = GLX_STENCIL_SIZE: %d\n", cur, pop);
      break;
    case WGL_DOUBLE_BUFFER_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_DOUBLEBUFFER, pop);
      TRACE("pAttr[%d] = GLX_DOUBLEBUFFER: %d\n", cur, pop);
      break;
727 728 729 730 731
    case WGL_STEREO_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_STEREO, pop);
      TRACE("pAttr[%d] = GLX_STEREO: %d\n", cur, pop);
      break;
732 733 734

    case WGL_PIXEL_TYPE_ARB:
      pop = iWGLAttr[++cur];
735
      TRACE("pAttr[%d] = WGL_PIXEL_TYPE_ARB: %d\n", cur, pop);
736
      switch (pop) {
737
      case WGL_TYPE_COLORINDEX_ARB: pixelattrib = GLX_COLOR_INDEX_BIT; break ;
738
      case WGL_TYPE_RGBA_ARB: pixelattrib = GLX_RGBA_BIT; break ;
739
      /* This is the same as WGL_TYPE_RGBA_FLOAT_ATI but the GLX constants differ, only the ARB GLX one is widely supported so use that */
740
      case WGL_TYPE_RGBA_FLOAT_ATI: pixelattrib = GLX_RGBA_FLOAT_BIT; break ;
741
      case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: pixelattrib = GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT; break ;
742 743 744 745 746 747 748
      default:
        ERR("unexpected PixelType(%x)\n", pop);	
        pop = 0;
      }
      break;

    case WGL_SUPPORT_GDI_ARB:
749
      /* This flag is set in a WineGLPixelFormat */
750
      pop = iWGLAttr[++cur];
751
      TRACE("pAttr[%d] = WGL_SUPPORT_GDI_ARB: %d\n", cur, pop);
752 753 754
      break;

    case WGL_DRAW_TO_BITMAP_ARB:
755
      /* This flag is set in a WineGLPixelFormat */
756
      pop = iWGLAttr[++cur];
757
      TRACE("pAttr[%d] = WGL_DRAW_TO_BITMAP_ARB: %d\n", cur, pop);
758 759 760 761
      break;

    case WGL_DRAW_TO_WINDOW_ARB:
      pop = iWGLAttr[++cur];
762 763
      TRACE("pAttr[%d] = WGL_DRAW_TO_WINDOW_ARB: %d\n", cur, pop);
      /* GLX_DRAWABLE_TYPE flags need to be OR'd together. See below. */
764
      if (pop) {
765
        drawattrib |= GLX_WINDOW_BIT;
766 767 768 769 770
      }
      break;

    case WGL_DRAW_TO_PBUFFER_ARB:
      pop = iWGLAttr[++cur];
771 772
      TRACE("pAttr[%d] = WGL_DRAW_TO_PBUFFER_ARB: %d\n", cur, pop);
      /* GLX_DRAWABLE_TYPE flags need to be OR'd together. See below. */
773
      if (pop) {
774
        drawattrib |= GLX_PBUFFER_BIT;
775 776 777 778
      }
      break;

    case WGL_ACCELERATION_ARB:
779 780 781 782 783
      /* This flag is set in a WineGLPixelFormat */
      pop = iWGLAttr[++cur];
      TRACE("pAttr[%d] = WGL_ACCELERATION_ARB: %d\n", cur, pop);
      break;

784 785 786 787 788 789
    case WGL_SUPPORT_OPENGL_ARB:
      pop = iWGLAttr[++cur];
      /** nothing to do, if we are here, supposing support Accelerated OpenGL */
      TRACE("pAttr[%d] = WGL_SUPPORT_OPENGL_ARB: %d\n", cur, pop);
      break;

790 791 792 793 794 795
    case WGL_SWAP_METHOD_ARB:
      pop = iWGLAttr[++cur];
      /* For now we ignore this and just return SWAP_EXCHANGE */
      TRACE("pAttr[%d] = WGL_SWAP_METHOD_ARB: %#x\n", cur, pop);
      break;

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
    case WGL_PBUFFER_LARGEST_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_LARGEST_PBUFFER, pop);
      TRACE("pAttr[%d] = GLX_LARGEST_PBUFFER: %x\n", cur, pop);
      break;

    case WGL_SAMPLE_BUFFERS_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_SAMPLE_BUFFERS_ARB, pop);
      TRACE("pAttr[%d] = GLX_SAMPLE_BUFFERS_ARB: %x\n", cur, pop);
      break;

    case WGL_SAMPLES_ARB:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_SAMPLES_ARB, pop);
      TRACE("pAttr[%d] = GLX_SAMPLES_ARB: %x\n", cur, pop);
      break;

    case WGL_TEXTURE_FORMAT_ARB:
    case WGL_TEXTURE_TARGET_ARB:
    case WGL_MIPMAP_TEXTURE_ARB:
      TRACE("WGL_render_texture Attributes: %x as %x\n", iWGLAttr[cur], iWGLAttr[cur + 1]);
      pop = iWGLAttr[++cur];
      if (NULL == pbuf) {
        ERR("trying to use GLX_Pbuffer Attributes without Pbuffer (was %x)\n", iWGLAttr[cur]);
      }
      if (use_render_texture_ati) {
        /** nothing to do here */
      }
      else if (!use_render_texture_emulation) {
        if (WGL_NO_TEXTURE_ARB != pop) {
          ERR("trying to use WGL_render_texture Attributes without support (was %x)\n", iWGLAttr[cur]);
          return -1; /** error: don't support it */
        } else {
830
          drawattrib |= GLX_PBUFFER_BIT;
831 832 833
        }
      }
      break ;
834
    case WGL_FLOAT_COMPONENTS_NV:
835 836
      nvfloatattrib = iWGLAttr[++cur];
      TRACE("pAttr[%d] = WGL_FLOAT_COMPONENTS_NV: %x\n", cur, nvfloatattrib);
837
      break ;
838
    case WGL_BIND_TO_TEXTURE_DEPTH_NV:
839 840
    case WGL_BIND_TO_TEXTURE_RGB_ARB:
    case WGL_BIND_TO_TEXTURE_RGBA_ARB:
841 842 843 844
    case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV:
    case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV:
    case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV:
    case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV:
845 846 847 848 849 850
      pop = iWGLAttr[++cur];
      /** cannot be converted, see direct handling on 
       *   - wglGetPixelFormatAttribivARB
       *  TODO: wglChoosePixelFormat
       */
      break ;
851 852 853 854 855
    case WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, pop);
      TRACE("pAttr[%d] = GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT: %x\n", cur, pop);
      break ;
856

857 858 859 860 861
    case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:
      pop = iWGLAttr[++cur];
      PUSH2(oGLXAttr, GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT, pop);
      TRACE("pAttr[%d] = GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT: %x\n", cur, pop);
      break ;
862 863 864 865 866 867 868
    default:
      FIXME("unsupported %x WGL Attribute\n", iWGLAttr[cur]);
      break;
    }
    ++cur;
  }

869 870 871 872
  /* By default glXChooseFBConfig defaults to GLX_WINDOW_BIT. wglChoosePixelFormatARB searches through
   * all formats. Unless drawattrib is set to a non-zero value override it with ~0, so that pixmap and pbuffer
   * formats appear as well. */
  if(!drawattrib) drawattrib = ~0;
873 874 875
  PUSH2(oGLXAttr, GLX_DRAWABLE_TYPE, drawattrib);
  TRACE("pAttr[?] = GLX_DRAWABLE_TYPE: %#x\n", drawattrib);

876 877 878
  /* By default glXChooseFBConfig uses GLX_RGBA_BIT as the default value. Since wglChoosePixelFormatARB
   * searches in all formats we have to do the same. For this reason we set GLX_RENDER_TYPE to ~0 unless
   * it is overridden. */
879 880 881 882 883 884 885
  PUSH2(oGLXAttr, GLX_RENDER_TYPE, pixelattrib);
  TRACE("pAttr[?] = GLX_RENDER_TYPE: %#x\n", pixelattrib);

  /* Set GLX_FLOAT_COMPONENTS_NV all the time */
  if(strstr(WineGLInfo.glxExtensions, "GLX_NV_float_buffer")) {
    PUSH2(oGLXAttr, GLX_FLOAT_COMPONENTS_NV, nvfloatattrib);
    TRACE("pAttr[?] = GLX_FLOAT_COMPONENTS_NV: %#x\n", nvfloatattrib);
886 887
  }

888 889 890
  return nAttribs;
}

891 892 893 894 895 896 897 898 899 900 901 902
static int get_render_type_from_fbconfig(Display *display, GLXFBConfig fbconfig)
{
    int render_type=0, render_type_bit;
    pglXGetFBConfigAttrib(display, fbconfig, GLX_RENDER_TYPE, &render_type_bit);
    switch(render_type_bit)
    {
        case GLX_RGBA_BIT:
            render_type = GLX_RGBA_TYPE;
            break;
        case GLX_COLOR_INDEX_BIT:
            render_type = GLX_COLOR_INDEX_TYPE;
            break;
903 904
        case GLX_RGBA_FLOAT_BIT:
            render_type = GLX_RGBA_FLOAT_TYPE;
905
            break;
906 907 908
        case GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT:
            render_type = GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT;
            break;
909
        default:
910
            ERR("Unknown render_type: %x\n", render_type_bit);
911 912 913 914
    }
    return render_type;
}

915 916 917 918 919 920 921 922 923 924 925 926
/* Check whether a fbconfig is suitable for Windows-style bitmap rendering */
static BOOL check_fbconfig_bitmap_capability(Display *display, GLXFBConfig fbconfig)
{
    int dbuf, value;
    pglXGetFBConfigAttrib(display, fbconfig, GLX_DOUBLEBUFFER, &dbuf);
    pglXGetFBConfigAttrib(gdi_display, fbconfig, GLX_DRAWABLE_TYPE, &value);

    /* Windows only supports bitmap rendering on single buffered formats, further the fbconfig needs to have
     * the GLX_PIXMAP_BIT set. */
    return !dbuf && (value & GLX_PIXMAP_BIT);
}

927
static WineGLPixelFormat *get_formats(Display *display, int *size_ret, int *onscreen_size_ret)
928
{
929 930 931
    static WineGLPixelFormat *list;
    static int size, onscreen_size;

932
    int fmt_id, nCfgs, i, run, bmp_formats;
933
    GLXFBConfig* cfgs;
934
    XVisualInfo *visinfo;
935

936 937 938
    wine_tsx11_lock();
    if (list) goto done;

939 940 941
    cfgs = pglXGetFBConfigs(display, DefaultScreen(display), &nCfgs);
    if (NULL == cfgs || 0 == nCfgs) {
        if(cfgs != NULL) XFree(cfgs);
942 943 944
        wine_tsx11_unlock();
        ERR("glXChooseFBConfig returns NULL\n");
        return NULL;
945 946
    }

947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
    /* Bitmap rendering on Windows implies the use of the Microsoft GDI software renderer.
     * Further most GLX drivers only offer pixmap rendering using indirect rendering (except for modern drivers which support 'AIGLX' / composite).
     * Indirect rendering can indicate software rendering (on Nvidia it is hw accelerated)
     * Since bitmap rendering implies the use of software rendering we can safely use indirect rendering for bitmaps.
     *
     * Below we count the number of formats which are suitable for bitmap rendering. Windows restricts bitmap rendering to single buffered formats.
     */
    for(i=0, bmp_formats=0; i<nCfgs; i++)
    {
        if(check_fbconfig_bitmap_capability(display, cfgs[i]))
            bmp_formats++;
    }
    TRACE("Found %d bitmap capable fbconfigs\n", bmp_formats);

    list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nCfgs + bmp_formats)*sizeof(WineGLPixelFormat));
962

963 964 965 966 967
    /* Fill the pixel format list. Put onscreen formats at the top and offscreen ones at the bottom.
     * Do this as GLX doesn't guarantee that the list is sorted */
    for(run=0; run < 2; run++)
    {
        for(i=0; i<nCfgs; i++) {
968
            pglXGetFBConfigAttrib(display, cfgs[i], GLX_FBCONFIG_ID, &fmt_id);
969 970 971 972 973 974 975 976 977 978 979 980 981 982
            visinfo = pglXGetVisualFromFBConfig(display, cfgs[i]);

            /* The first run we only add onscreen formats (ones which have an associated X Visual).
             * The second run we only set offscreen formats. */
            if(!run && visinfo)
            {
                /* We implement child window rendering using offscreen buffers (using composite or an XPixmap).
                 * The contents is copied to the destination using XCopyArea. For the copying to work
                 * the depth of the source and destination window should be the same. In general this should
                 * not be a problem for OpenGL as drivers only advertise formats with a similar depth (or no depth).
                 * As of the introduction of composition managers at least Nvidia now also offers ARGB visuals
                 * with a depth of 32 in addition to the default 24 bit. In order to prevent BadMatch errors we only
                 * list formats with the same depth. */
                if(visinfo->depth != screen_depth)
983 984
                {
                    XFree(visinfo);
985
                    continue;
986
                }
987

988 989 990 991 992 993
                TRACE("Found onscreen format FBCONFIG_ID 0x%x corresponding to iPixelFormat %d at GLX index %d\n", fmt_id, size+1, i);
                list[size].iPixelFormat = size+1; /* The index starts at 1 */
                list[size].fbconfig = cfgs[i];
                list[size].fmt_id = fmt_id;
                list[size].render_type = get_render_type_from_fbconfig(display, cfgs[i]);
                list[size].offscreenOnly = FALSE;
994
                list[size].dwFlags = 0;
995 996
                size++;
                onscreen_size++;
997 998 999 1000 1001 1002 1003 1004 1005 1006

                /* Clone a format if it is bitmap capable for indirect rendering to bitmaps */
                if(check_fbconfig_bitmap_capability(display, cfgs[i]))
                {
                    TRACE("Found bitmap capable format FBCONFIG_ID 0x%x corresponding to iPixelFormat %d at GLX index %d\n", fmt_id, size+1, i);
                    list[size].iPixelFormat = size+1; /* The index starts at 1 */
                    list[size].fbconfig = cfgs[i];
                    list[size].fmt_id = fmt_id;
                    list[size].render_type = get_render_type_from_fbconfig(display, cfgs[i]);
                    list[size].offscreenOnly = FALSE;
1007
                    list[size].dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI | PFD_GENERIC_FORMAT;
1008 1009 1010
                    size++;
                    onscreen_size++;
                }
1011
            } else if(run && !visinfo) {
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
                int window_drawable=0;
                pglXGetFBConfigAttrib(gdi_display, cfgs[i], GLX_DRAWABLE_TYPE, &window_drawable);

                /* Recent Nvidia drivers and DRI drivers offer window drawable formats without a visual.
                 * This are formats like 16-bit rgb on a 24-bit desktop. In order to support these formats
                 * onscreen we would have to use glXCreateWindow instead of XCreateWindow. Further it will
                 * likely make our child window opengl rendering more complicated since likely you can't use
                 * XCopyArea on a GLX Window.
                 * For now ignore fbconfigs which are window drawable but lack a visual. */
                if(window_drawable & GLX_WINDOW_BIT)
                {
                    TRACE("Skipping FBCONFIG_ID 0x%x as an offscreen format because it is window_drawable\n", fmt_id);
                    continue;
                }

1027 1028 1029 1030 1031 1032
                TRACE("Found offscreen format FBCONFIG_ID 0x%x corresponding to iPixelFormat %d at GLX index %d\n", fmt_id, size+1, i);
                list[size].iPixelFormat = size+1; /* The index starts at 1 */
                list[size].fbconfig = cfgs[i];
                list[size].fmt_id = fmt_id;
                list[size].render_type = get_render_type_from_fbconfig(display, cfgs[i]);
                list[size].offscreenOnly = TRUE;
1033
                list[size].dwFlags = 0;
1034
                size++;
1035
            }
1036 1037

            if (visinfo) XFree(visinfo);
1038 1039 1040
        }
    }

1041
    XFree(cfgs);
1042

1043 1044 1045 1046 1047
done:
    if (size_ret) *size_ret = size;
    if (onscreen_size_ret) *onscreen_size_ret = onscreen_size;
    wine_tsx11_unlock();
    return list;
1048 1049
}

1050 1051 1052
/* GLX can advertise dozens of different pixelformats including offscreen and onscreen ones.
 * In our WGL implementation we only support a subset of these formats namely the format of
 * Wine's main visual and offscreen formats (if they are available).
1053 1054
 * This function converts a WGL format to its corresponding GLX one. It returns a WineGLPixelFormat
 * and it returns the number of supported WGL formats in fmt_count.
1055
 */
1056
static WineGLPixelFormat* ConvertPixelFormatWGLtoGLX(Display *display, int iPixelFormat, BOOL AllowOffscreen, int *fmt_count)
1057
{
1058 1059
    WineGLPixelFormat *list, *res = NULL;
    int size, onscreen_size;
1060

1061
    if (!(list = get_formats(display, &size, &onscreen_size ))) return NULL;
1062

1063 1064 1065
    /* Check if the pixelformat is valid. Note that it is legal to pass an invalid
     * iPixelFormat in case of probing the number of pixelformats.
     */
1066 1067 1068
    if((iPixelFormat > 0) && (iPixelFormat <= size) &&
       (!list[iPixelFormat-1].offscreenOnly || AllowOffscreen)) {
        res = &list[iPixelFormat-1];
1069
        TRACE("Returning fmt_id=%#x for iPixelFormat=%d\n", res->fmt_id, iPixelFormat);
1070 1071
    }

1072
    if(AllowOffscreen)
1073
        *fmt_count = size;
1074
    else
1075
        *fmt_count = onscreen_size;
1076

1077
    TRACE("Number of returned pixelformats=%d\n", *fmt_count);
1078 1079

    return res;
1080 1081 1082
}

/* Search our internal pixelformat list for the WGL format corresponding to the given fbconfig */
1083
static WineGLPixelFormat* ConvertPixelFormatGLXtoWGL(Display *display, int fmt_id, DWORD dwFlags)
1084
{
1085 1086
    WineGLPixelFormat *list;
    int i, size;
1087

1088
    if (!(list = get_formats(display, &size, NULL ))) return NULL;
1089

1090
    for(i=0; i<size; i++) {
1091 1092 1093
        /* A GLX format can appear multiple times in the pixel format list due to fake formats for bitmap rendering.
         * Fake formats might get selected when the user passes the proper flags using the dwFlags parameter. */
        if( (list[i].fmt_id == fmt_id) && ((list[i].dwFlags & dwFlags) == dwFlags) ) {
1094 1095
            TRACE("Returning iPixelFormat %d for fmt_id 0x%x\n", list[i].iPixelFormat, fmt_id);
            return &list[i];
1096 1097
        }
    }
1098
    TRACE("No compatible format found for fmt_id 0x%x\n", fmt_id);
1099
    return NULL;
1100
}
Lionel Ulmer's avatar
Lionel Ulmer committed
1101

1102 1103 1104 1105 1106 1107
int pixelformat_from_fbconfig_id(XID fbconfig_id)
{
    WineGLPixelFormat *fmt;

    if (!fbconfig_id) return 0;

1108
    fmt = ConvertPixelFormatGLXtoWGL(gdi_display, fbconfig_id, 0 /* no flags */);
1109 1110 1111 1112 1113 1114 1115
    if(fmt)
        return fmt->iPixelFormat;
    /* This will happen on hwnds without a pixel format set; it's ok */
    return 0;
}


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
/* Mark any allocated context using the glx drawable 'old' to use 'new' */
void mark_drawable_dirty(Drawable old, Drawable new)
{
    Wine_GLContext *ctx;
    for (ctx = context_list; ctx; ctx = ctx->next) {
        if (old == ctx->drawables[0]) {
            ctx->drawables[0] = new;
            ctx->refresh_drawables = TRUE;
        }
        if (old == ctx->drawables[1]) {
            ctx->drawables[1] = new;
            ctx->refresh_drawables = TRUE;
        }
    }
}

/* Given the current context, make sure its drawable is sync'd */
static inline void sync_context(Wine_GLContext *context)
{
    if(context && context->refresh_drawables) {
        if (glxRequireVersion(3))
            pglXMakeContextCurrent(gdi_display, context->drawables[0],
                                   context->drawables[1], context->ctx);
        else
            pglXMakeCurrent(gdi_display, context->drawables[0], context->ctx);
        context->refresh_drawables = FALSE;
    }
}


1146
static GLXContext create_glxcontext(Display *display, Wine_GLContext *context, GLXContext shareList)
1147 1148
{
    GLXContext ctx;
1149 1150 1151 1152

    /* We use indirect rendering for rendering to bitmaps. See get_formats for a comment about this. */
    BOOL indirect = (context->fmt->dwFlags & PFD_DRAW_TO_BITMAP) ? FALSE : TRUE;

1153 1154 1155 1156 1157 1158 1159 1160
    if(context->gl3_context)
    {
        if(context->numAttribs)
            ctx = pglXCreateContextAttribsARB(gdi_display, context->fmt->fbconfig, shareList, indirect, context->attribList);
        else
            ctx = pglXCreateContextAttribsARB(gdi_display, context->fmt->fbconfig, shareList, indirect, NULL);
    }
    else if(context->vis)
1161
        ctx = pglXCreateContext(gdi_display, context->vis, shareList, indirect);
1162
    else /* Create a GLX Context for a pbuffer */
1163
        ctx = pglXCreateNewContext(gdi_display, context->fmt->fbconfig, context->fmt->render_type, shareList, TRUE);
1164 1165 1166 1167 1168

    return ctx;
}


1169 1170 1171 1172 1173 1174
Drawable create_glxpixmap(Display *display, XVisualInfo *vis, Pixmap parent)
{
    return pglXCreateGLXPixmap(display, vis, parent);
}


1175
static XID create_bitmap_glxpixmap(X11DRV_PDEVICE *physDev, WineGLPixelFormat *fmt)
1176
{
1177
    GLXPixmap ret = 0;
1178 1179 1180 1181
    XVisualInfo *vis;

    wine_tsx11_lock();

1182 1183 1184 1185 1186 1187
    vis = pglXGetVisualFromFBConfig(gdi_display, fmt->fbconfig);
    if(vis) {
        if(vis->depth == physDev->bitmap->pixmap_depth)
            ret = pglXCreateGLXPixmap(gdi_display, vis, physDev->bitmap->pixmap);
        XFree(vis);
    }
1188 1189 1190 1191 1192
    wine_tsx11_unlock();
    TRACE("return %lx\n", ret);
    return ret;
}

1193 1194 1195
/**
 * X11DRV_ChoosePixelFormat
 *
1196
 * Equivalent to glXChooseVisual.
1197
 */
1198
int CDECL X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev,
Lionel Ulmer's avatar
Lionel Ulmer committed
1199
			     const PIXELFORMATDESCRIPTOR *ppfd) {
1200 1201
    WineGLPixelFormat *list;
    int onscreen_size;
1202 1203 1204 1205
    int ret = 0;
    int value = 0;
    int i = 0;
    int bestFormat = -1;
1206 1207
    int bestDBuffer = -1;
    int bestStereo = -1;
1208 1209 1210 1211 1212 1213
    int bestColor = -1;
    int bestAlpha = -1;
    int bestDepth = -1;
    int bestStencil = -1;
    int bestAux = -1;

1214
    if (!has_opengl()) return 0;
1215

1216
    if (TRACE_ON(wgl)) {
1217
        TRACE("(%p,%p)\n", physDev, ppfd);
1218

1219
        dump_PIXELFORMATDESCRIPTOR(ppfd);
1220
    }
1221

1222 1223
    if (!(list = get_formats(gdi_display, NULL, &onscreen_size ))) return 0;

1224
    wine_tsx11_lock();
1225
    for(i=0; i<onscreen_size; i++)
1226 1227 1228 1229
    {
        int dwFlags = 0;
        int iPixelType = 0;
        int alpha=0, color=0, depth=0, stencil=0, aux=0;
1230
        WineGLPixelFormat *fmt = &list[i];
1231

1232 1233 1234 1235 1236 1237
        /* Pixel type */
        pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &value);
        if (value & GLX_RGBA_BIT)
            iPixelType = PFD_TYPE_RGBA;
        else
            iPixelType = PFD_TYPE_COLORINDEX;
1238

1239 1240 1241 1242 1243
        if (ppfd->iPixelType != iPixelType)
        {
            TRACE("pixel type mismatch for iPixelFormat=%d\n", i+1);
            continue;
        }
1244

1245 1246 1247 1248 1249 1250 1251 1252
        /* Only use bitmap capable for formats for bitmap rendering.
         * See get_formats for more info. */
        if( (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) != (fmt->dwFlags & PFD_DRAW_TO_BITMAP))
        {
            TRACE("PFD_DRAW_TO_BITMAP mismatch for iPixelFormat=%d\n", i+1);
            continue;
        }

1253 1254 1255 1256 1257 1258 1259 1260 1261
        pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value);
        if (value) dwFlags |= PFD_DOUBLEBUFFER;
        pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STEREO, &value);
        if (value) dwFlags |= PFD_STEREO;
        pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, &color); /* cColorBits */
        pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &alpha); /* cAlphaBits */
        pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &depth); /* cDepthBits */
        pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &stencil); /* cStencilBits */
        pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_AUX_BUFFERS, &aux); /* cAuxBuffers */
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
        /* The behavior of PDF_STEREO/PFD_STEREO_DONTCARE and PFD_DOUBLEBUFFER / PFD_DOUBLEBUFFER_DONTCARE
         * is not very clear on MSDN. They specify that ChoosePixelFormat tries to match pixel formats
         * with the flag (PFD_STEREO / PFD_DOUBLEBUFFERING) set. Otherwise it says that it tries to match
         * formats without the given flag set.
         * A test on Windows using a Radeon 9500pro on WinXP (the driver doesn't support Stereo)
         * has indicated that a format without stereo is returned when stereo is unavailable.
         * So in case PFD_STEREO is set, formats that support it should have priority above formats
         * without. In case PFD_STEREO_DONTCARE is set, stereo is ignored.
         *
         * To summarize the following is most likely the correct behavior:
         * stereo not set -> prefer no-stereo formats, else also accept stereo formats
         * stereo set -> prefer stereo formats, else also accept no-stereo formats
         * stereo don't care -> it doesn't matter whether we get stereo or not
         *
         * In Wine we will treat no-stereo the same way as don't care because it makes
         * format selection even more complicated and second drivers with Stereo advertise
         * each format twice anyway.
         */

        /* Doublebuffer, see the comments above */
        if( !(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) ) {
            if( ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer) &&
                ((dwFlags & PFD_DOUBLEBUFFER) == (ppfd->dwFlags & PFD_DOUBLEBUFFER)) )
            {
                bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
                bestStereo = dwFlags & PFD_STEREO;
                bestAlpha = alpha;
                bestColor = color;
                bestDepth = depth;
                bestStencil = stencil;
                bestAux = aux;
                bestFormat = i;
                continue;
            }
1297 1298
            if(bestDBuffer != -1 && (dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer)
                continue;
1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
        }

        /* Stereo, see the comments above. */
        if( !(ppfd->dwFlags & PFD_STEREO_DONTCARE) ) {
            if( ((ppfd->dwFlags & PFD_STEREO) != bestStereo) &&
                ((dwFlags & PFD_STEREO) == (ppfd->dwFlags & PFD_STEREO)) )
            {
                bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
                bestStereo = dwFlags & PFD_STEREO;
                bestAlpha = alpha;
                bestColor = color;
                bestDepth = depth;
                bestStencil = stencil;
                bestAux = aux;
                bestFormat = i;
                continue;
            }
1316 1317
            if(bestStereo != -1 && (dwFlags & PFD_STEREO) != bestStereo)
                continue;
1318 1319
        }

1320 1321 1322
        /* Below we will do a number of checks to select the 'best' pixelformat.
         * We assume the precedence cColorBits > cAlphaBits > cDepthBits > cStencilBits -> cAuxBuffers.
         * The code works by trying to match the most important options as close as possible.
1323 1324 1325 1326
         * When a reasonable format is found, we will try to match more options.
         * It appears (see the opengl32 test) that Windows opengl drivers ignore options
         * like cColorBits, cAlphaBits and friends if they are set to 0, so they are considered
         * as DONTCARE. At least Serious Sam TSE relies on this behavior. */
1327

1328
        /* Color bits */
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345
        if(ppfd->cColorBits) {
            if( ((ppfd->cColorBits > bestColor) && (color > bestColor)) ||
                ((color >= ppfd->cColorBits) && (color < bestColor)) )
            {
                bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
                bestStereo = dwFlags & PFD_STEREO;
                bestAlpha = alpha;
                bestColor = color;
                bestDepth = depth;
                bestStencil = stencil;
                bestAux = aux;
                bestFormat = i;
                continue;
            } else if(bestColor != color) {  /* Do further checks if the format is compatible */
                TRACE("color mismatch for iPixelFormat=%d\n", i+1);
                continue;
            }
1346
        }
1347

1348
        /* Alpha bits */
1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
        if(ppfd->cAlphaBits) {
            if( ((ppfd->cAlphaBits > bestAlpha) && (alpha > bestAlpha)) ||
                ((alpha >= ppfd->cAlphaBits) && (alpha < bestAlpha)) )
            {
                bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
                bestStereo = dwFlags & PFD_STEREO;
                bestAlpha = alpha;
                bestColor = color;
                bestDepth = depth;
                bestStencil = stencil;
                bestAux = aux;
                bestFormat = i;
                continue;
            } else if(bestAlpha != alpha) {
                TRACE("alpha mismatch for iPixelFormat=%d\n", i+1);
                continue;
            }
1366
        }
1367

1368
        /* Depth bits */
1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
        if(ppfd->cDepthBits) {
            if( ((ppfd->cDepthBits > bestDepth) && (depth > bestDepth)) ||
                ((depth >= ppfd->cDepthBits) && (depth < bestDepth)) )
            {
                bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
                bestStereo = dwFlags & PFD_STEREO;
                bestAlpha = alpha;
                bestColor = color;
                bestDepth = depth;
                bestStencil = stencil;
                bestAux = aux;
                bestFormat = i;
                continue;
            } else if(bestDepth != depth) {
                TRACE("depth mismatch for iPixelFormat=%d\n", i+1);
                continue;
            }
1386 1387 1388
        }

        /* Stencil bits */
1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
        if(ppfd->cStencilBits) {
            if( ((ppfd->cStencilBits > bestStencil) && (stencil > bestStencil)) ||
                ((stencil >= ppfd->cStencilBits) && (stencil < bestStencil)) )
            {
                bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
                bestStereo = dwFlags & PFD_STEREO;
                bestAlpha = alpha;
                bestColor = color;
                bestDepth = depth;
                bestStencil = stencil;
                bestAux = aux;
                bestFormat = i;
                continue;
            } else if(bestStencil != stencil) {
                TRACE("stencil mismatch for iPixelFormat=%d\n", i+1);
                continue;
            }
1406 1407 1408
        }

        /* Aux buffers */
1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
        if(ppfd->cAuxBuffers) {
            if( ((ppfd->cAuxBuffers > bestAux) && (aux > bestAux)) ||
                ((aux >= ppfd->cAuxBuffers) && (aux < bestAux)) )
            {
                bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
                bestStereo = dwFlags & PFD_STEREO;
                bestAlpha = alpha;
                bestColor = color;
                bestDepth = depth;
                bestStencil = stencil;
                bestAux = aux;
                bestFormat = i;
                continue;
            } else if(bestAux != aux) {
                TRACE("aux mismatch for iPixelFormat=%d\n", i+1);
                continue;
            }
1426
        }
1427
    }
1428

1429 1430 1431 1432 1433 1434
    if(bestFormat == -1) {
        TRACE("No matching mode was found returning 0\n");
        ret = 0;
    }
    else {
        ret = bestFormat+1; /* the return value should be a 1-based index */
1435
        TRACE("Successfully found a matching mode, returning index: %d %x\n", ret, list[bestFormat].fmt_id);
1436
    }
1437

1438
    wine_tsx11_unlock();
1439

1440
    return ret;
Lionel Ulmer's avatar
Lionel Ulmer committed
1441
}
1442 1443 1444 1445 1446
/**
 * X11DRV_DescribePixelFormat
 *
 * Get the pixel-format descriptor associated to the given id
 */
1447
int CDECL X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev,
Lionel Ulmer's avatar
Lionel Ulmer committed
1448 1449 1450
			       int iPixelFormat,
			       UINT nBytes,
			       PIXELFORMATDESCRIPTOR *ppfd) {
1451
  /*XVisualInfo *vis;*/
Lionel Ulmer's avatar
Lionel Ulmer committed
1452 1453
  int value;
  int rb,gb,bb,ab;
1454
  WineGLPixelFormat *fmt;
1455
  int ret = 0;
1456
  int fmt_count = 0;
1457

1458 1459
  if (!has_opengl()) return 0;

1460
  TRACE("(%p,%d,%d,%p)\n", physDev, iPixelFormat, nBytes, ppfd);
1461

1462
  /* Look for the iPixelFormat in our list of supported formats. If it is supported we get the index in the FBConfig table and the number of supported formats back */
1463
  fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, FALSE /* Offscreen */, &fmt_count);
1464
  if (ppfd == NULL) {
1465
      /* The application is only querying the number of pixelformats */
1466
      return fmt_count;
1467
  } else if(fmt == NULL) {
1468 1469
      WARN("unexpected iPixelFormat(%d): not >=1 and <=nFormats(%d), returning NULL!\n", iPixelFormat, fmt_count);
      return 0;
1470
  }
1471

Lionel Ulmer's avatar
Lionel Ulmer committed
1472 1473 1474 1475 1476 1477
  if (nBytes < sizeof(PIXELFORMATDESCRIPTOR)) {
    ERR("Wrong structure size !\n");
    /* Should set error */
    return 0;
  }

1478
  ret = fmt_count;
Lionel Ulmer's avatar
Lionel Ulmer committed
1479 1480 1481 1482

  memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
  ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
  ppfd->nVersion = 1;
1483

Lionel Ulmer's avatar
Lionel Ulmer committed
1484
  /* These flags are always the same... */
1485
  ppfd->dwFlags = PFD_SUPPORT_OPENGL;
1486
  /* Now the flags extracted from the Visual */
1487

1488
  wine_tsx11_lock();
1489

1490 1491 1492
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &value);
  if(value & GLX_WINDOW_BIT)
      ppfd->dwFlags |= PFD_DRAW_TO_WINDOW;
1493 1494 1495 1496 1497 1498

  /* On Windows bitmap rendering is only offered using the GDI Software renderer. We reserve some formats (see get_formats for more info)
   * for bitmap rendering since we require indirect rendering for this. Further pixel format logs of a GeforceFX, Geforce8800GT, Radeon HD3400 and a
   * Radeon 9000 indicated that all bitmap formats have PFD_SUPPORT_GDI. Except for 2 formats on the Radeon 9000 none of the hw accelerated formats
   * offered the GDI bit either. */
  ppfd->dwFlags |= fmt->dwFlags & (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI);
1499

1500
  /* PFD_GENERIC_FORMAT - gdi software rendering
1501
   * PFD_GENERIC_ACCELERATED - some parts are accelerated by a display driver (MCD e.g. 3dfx minigl)
1502 1503
   * none set - full hardware accelerated by a ICD
   *
1504 1505
   * We only set PFD_GENERIC_FORMAT on bitmap formats (see get_formats) as that's what ATI and Nvidia Windows drivers do  */
  ppfd->dwFlags |= fmt->dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED);
1506

1507 1508 1509 1510 1511
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value);
  if (value) {
      ppfd->dwFlags |= PFD_DOUBLEBUFFER;
      ppfd->dwFlags &= ~PFD_SUPPORT_GDI;
  }
1512
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STEREO, &value); if (value) ppfd->dwFlags |= PFD_STEREO;
Lionel Ulmer's avatar
Lionel Ulmer committed
1513 1514

  /* Pixel type */
1515
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &value);
1516
  if (value & GLX_RGBA_BIT)
Lionel Ulmer's avatar
Lionel Ulmer committed
1517 1518 1519 1520 1521
    ppfd->iPixelType = PFD_TYPE_RGBA;
  else
    ppfd->iPixelType = PFD_TYPE_COLORINDEX;

  /* Color bits */
1522
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, &value);
Lionel Ulmer's avatar
Lionel Ulmer committed
1523 1524 1525 1526
  ppfd->cColorBits = value;

  /* Red, green, blue and alpha bits / shifts */
  if (ppfd->iPixelType == PFD_TYPE_RGBA) {
1527 1528 1529 1530
    pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RED_SIZE, &rb);
    pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_GREEN_SIZE, &gb);
    pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BLUE_SIZE, &bb);
    pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &ab);
1531

Lionel Ulmer's avatar
Lionel Ulmer committed
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549
    ppfd->cRedBits = rb;
    ppfd->cRedShift = gb + bb + ab;
    ppfd->cBlueBits = bb;
    ppfd->cBlueShift = ab;
    ppfd->cGreenBits = gb;
    ppfd->cGreenShift = bb + ab;
    ppfd->cAlphaBits = ab;
    ppfd->cAlphaShift = 0;
  } else {
    ppfd->cRedBits = 0;
    ppfd->cRedShift = 0;
    ppfd->cBlueBits = 0;
    ppfd->cBlueShift = 0;
    ppfd->cGreenBits = 0;
    ppfd->cGreenShift = 0;
    ppfd->cAlphaBits = 0;
    ppfd->cAlphaShift = 0;
  }
1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561

  /* Accum RGBA bits */
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_RED_SIZE, &rb);
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_GREEN_SIZE, &gb);
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &bb);
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &ab);

  ppfd->cAccumBits = rb+gb+bb+ab;
  ppfd->cAccumRedBits = rb;
  ppfd->cAccumGreenBits = gb;
  ppfd->cAccumBlueBits = bb;
  ppfd->cAccumAlphaBits = ab;
1562

1563 1564 1565 1566
  /* Aux bits */
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_AUX_BUFFERS, &value);
  ppfd->cAuxBuffers = value;

Lionel Ulmer's avatar
Lionel Ulmer committed
1567
  /* Depth bits */
1568
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &value);
Lionel Ulmer's avatar
Lionel Ulmer committed
1569
  ppfd->cDepthBits = value;
1570 1571

  /* stencil bits */
1572
  pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &value);
1573
  ppfd->cStencilBits = value;
1574

1575
  wine_tsx11_unlock();
Lionel Ulmer's avatar
Lionel Ulmer committed
1576 1577

  ppfd->iLayerType = PFD_MAIN_PLANE;
1578

1579
  if (TRACE_ON(wgl)) {
1580 1581
    dump_PIXELFORMATDESCRIPTOR(ppfd);
  }
1582

1583
  return ret;
Lionel Ulmer's avatar
Lionel Ulmer committed
1584 1585
}

1586 1587 1588 1589 1590
/**
 * X11DRV_GetPixelFormat
 *
 * Get the pixel-format id used by this DC
 */
1591
int CDECL X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) {
1592 1593 1594 1595
  WineGLPixelFormat *fmt;
  int tmp;
  TRACE("(%p)\n", physDev);

1596 1597
  if (!physDev->current_pf) return 0;  /* not set yet */

1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610
  fmt = ConvertPixelFormatWGLtoGLX(gdi_display, physDev->current_pf, TRUE, &tmp);
  if(!fmt)
  {
    ERR("Unable to find a WineGLPixelFormat for iPixelFormat=%d\n", physDev->current_pf);
    return 0;
  }
  else if(fmt->offscreenOnly)
  {
    /* Offscreen formats can't be used with traditional WGL calls.
     * As has been verified on Windows GetPixelFormat doesn't fail but returns iPixelFormat=1. */
     TRACE("Returning iPixelFormat=1 for offscreen format: %d\n", fmt->iPixelFormat);
    return 1;
  }
Lionel Ulmer's avatar
Lionel Ulmer committed
1611

1612
  TRACE("(%p): returns %d\n", physDev, physDev->current_pf);
1613
  return physDev->current_pf;
Lionel Ulmer's avatar
Lionel Ulmer committed
1614 1615
}

1616 1617 1618 1619
/* This function is the core of X11DRV_SetPixelFormat and X11DRV_SetPixelFormatWINE.
 * Both functions are the same except that X11DRV_SetPixelFormatWINE allows you to
 * set the pixel format multiple times. */
static BOOL internal_SetPixelFormat(X11DRV_PDEVICE *physDev,
Lionel Ulmer's avatar
Lionel Ulmer committed
1620 1621
			   int iPixelFormat,
			   const PIXELFORMATDESCRIPTOR *ppfd) {
1622 1623 1624
    WineGLPixelFormat *fmt;
    int value;
    HWND hwnd;
1625

1626 1627 1628 1629 1630 1631
    /* SetPixelFormat is not allowed on the X root_window e.g. GetDC(0) */
    if(get_glxdrawable(physDev) == root_window)
    {
        ERR("Invalid operation on root_window\n");
        return FALSE;
    }
1632

1633 1634 1635 1636 1637 1638
    /* Check if iPixelFormat is in our list of supported formats to see if it is supported. */
    fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, FALSE /* Offscreen */, &value);
    if(!fmt) {
        ERR("Invalid iPixelFormat: %d\n", iPixelFormat);
        return FALSE;
    }
1639

1640
    wine_tsx11_lock();
1641
    pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &value);
1642
    wine_tsx11_unlock();
1643 1644 1645 1646 1647

    hwnd = WindowFromDC(physDev->hdc);
    if(hwnd) {
        if(!(value&GLX_WINDOW_BIT)) {
            WARN("Pixel format %d is not compatible for window rendering\n", iPixelFormat);
1648
            return FALSE;
1649 1650
        }

1651
        if(!SendMessageW(hwnd, WM_X11DRV_SET_WIN_FORMAT, fmt->fmt_id, 0)) {
1652
            ERR("Couldn't set format of the window, returning failure\n");
1653
            return FALSE;
1654 1655
        }
    }
1656 1657 1658 1659 1660 1661
    else if(physDev->bitmap) {
        if(!(value&GLX_PIXMAP_BIT)) {
            WARN("Pixel format %d is not compatible for bitmap rendering\n", iPixelFormat);
            return FALSE;
        }

1662
        physDev->bitmap->glxpixmap = create_bitmap_glxpixmap(physDev, fmt);
1663 1664 1665 1666 1667 1668
        if(!physDev->bitmap->glxpixmap) {
            WARN("Couldn't create glxpixmap for pixel format %d\n", iPixelFormat);
            return FALSE;
        }
    }
    else {
1669
        FIXME("called on a non-window, non-bitmap object?\n");
1670
    }
1671

1672
    physDev->current_pf = iPixelFormat;
1673

1674 1675
    if (TRACE_ON(wgl)) {
        int gl_test = 0;
1676

1677
        wine_tsx11_lock();
1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688
        gl_test = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_FBCONFIG_ID, &value);
        if (gl_test) {
           ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
        } else {
            TRACE(" FBConfig have :\n");
            TRACE(" - FBCONFIG_ID   0x%x\n", value);
            pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_VISUAL_ID, &value);
            TRACE(" - VISUAL_ID     0x%x\n", value);
            pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &value);
            TRACE(" - DRAWABLE_TYPE 0x%x\n", value);
        }
1689
        wine_tsx11_unlock();
1690
    }
1691 1692 1693 1694 1695 1696 1697 1698 1699
    return TRUE;
}


/**
 * X11DRV_SetPixelFormat
 *
 * Set the pixel-format id used by this DC
 */
1700
BOOL CDECL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev,
1701 1702 1703 1704
			   int iPixelFormat,
			   const PIXELFORMATDESCRIPTOR *ppfd) {
    TRACE("(%p,%d,%p)\n", physDev, iPixelFormat, ppfd);

1705
    if (!has_opengl()) return FALSE;
1706 1707 1708 1709 1710

    if(physDev->current_pf)  /* cannot change it if already set */
        return (physDev->current_pf == iPixelFormat);

    return internal_SetPixelFormat(physDev, iPixelFormat, ppfd);
Lionel Ulmer's avatar
Lionel Ulmer committed
1711 1712
}

1713 1714 1715 1716 1717
/**
 * X11DRV_wglCopyContext
 *
 * For OpenGL32 wglCopyContext.
 */
1718
BOOL CDECL X11DRV_wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask) {
1719 1720 1721 1722 1723
    Wine_GLContext *src = (Wine_GLContext*)hglrcSrc;
    Wine_GLContext *dst = (Wine_GLContext*)hglrcDst;

    TRACE("hglrcSrc: (%p), hglrcDst: (%p), mask: %#x\n", hglrcSrc, hglrcDst, mask);

1724
    wine_tsx11_lock();
1725
    pglXCopyContext(gdi_display, src->ctx, dst->ctx, mask);
1726
    wine_tsx11_unlock();
1727 1728 1729 1730 1731

    /* As opposed to wglCopyContext, glXCopyContext doesn't return anything, so hopefully we passed */
    return TRUE;
}

1732 1733 1734 1735 1736
/**
 * X11DRV_wglCreateContext
 *
 * For OpenGL32 wglCreateContext.
 */
1737
HGLRC CDECL X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev)
1738 1739
{
    Wine_GLContext *ret;
1740
    WineGLPixelFormat *fmt;
1741 1742
    int hdcPF = physDev->current_pf;
    int fmt_count = 0;
1743
    HDC hdc = physDev->hdc;
1744 1745 1746

    TRACE("(%p)->(PF:%d)\n", hdc, hdcPF);

1747
    if (!has_opengl()) return 0;
1748

1749 1750 1751 1752 1753
    fmt = ConvertPixelFormatWGLtoGLX(gdi_display, hdcPF, TRUE /* Offscreen */, &fmt_count);
    /* We can render using the iPixelFormat (1) of Wine's Main visual AND using some offscreen formats.
     * Note that standard WGL-calls don't recognize offscreen-only formats. For that reason pbuffers
     * use a sort of 'proxy' HDC (wglGetPbufferDCARB).
     * If this fails something is very wrong on the system. */
1754
    if(!fmt) {
1755
        ERR("Cannot get FB Config for iPixelFormat %d, expect problems!\n", hdcPF);
1756 1757 1758 1759 1760 1761 1762
        SetLastError(ERROR_INVALID_PIXEL_FORMAT);
        return NULL;
    }

    wine_tsx11_lock();
    ret = alloc_context();
    ret->hdc = hdc;
1763
    ret->fmt = fmt;
1764 1765
    ret->has_been_current = FALSE;
    ret->sharing = FALSE;
1766

1767
    ret->vis = pglXGetVisualFromFBConfig(gdi_display, fmt->fbconfig);
1768 1769
    ret->ctx = create_glxcontext(gdi_display, ret, NULL);
    wine_tsx11_unlock();
1770 1771 1772 1773 1774

    TRACE(" creating context %p (GL context creation delayed)\n", ret);
    return (HGLRC) ret;
}

1775 1776 1777 1778 1779
/**
 * X11DRV_wglDeleteContext
 *
 * For OpenGL32 wglDeleteContext.
 */
1780
BOOL CDECL X11DRV_wglDeleteContext(HGLRC hglrc)
1781 1782 1783 1784 1785
{
    Wine_GLContext *ctx = (Wine_GLContext *) hglrc;

    TRACE("(%p)\n", hglrc);

1786
    if (!has_opengl()) return 0;
1787

1788
    if (!is_valid_context(ctx))
1789 1790 1791
    {
        WARN("Error deleting context !\n");
        SetLastError(ERROR_INVALID_HANDLE);
1792
        return FALSE;
1793 1794
    }

1795 1796 1797 1798
    /* WGL doesn't allow deletion of a context which is current in another thread */
    if (ctx->tid != 0 && ctx->tid != GetCurrentThreadId())
    {
        TRACE("Cannot delete context=%p because it is current in another thread.\n", ctx);
1799
        SetLastError(ERROR_BUSY);
1800 1801 1802
        return FALSE;
    }

1803 1804 1805 1806
    /* WGL makes a context not current if it is active before deletion. GLX waits until the context is not current. */
    if (ctx == NtCurrentTeb()->glContext)
        wglMakeCurrent(ctx->hdc, NULL);

1807 1808 1809 1810 1811 1812 1813
    if (ctx->ctx)
    {
        wine_tsx11_lock();
        pglXDestroyContext(gdi_display, ctx->ctx);
        wine_tsx11_unlock();
    }

1814
    free_context(ctx);
1815
    return TRUE;
1816 1817
}

1818 1819 1820 1821 1822
/**
 * X11DRV_wglGetCurrentReadDCARB
 *
 * For OpenGL32 wglGetCurrentReadDCARB.
 */
1823
static HDC WINAPI X11DRV_wglGetCurrentReadDCARB(void) 
1824
{
1825 1826
    HDC ret = 0;
    Wine_GLContext *ctx = NtCurrentTeb()->glContext;
1827

1828
    if (ctx) ret = ctx->read_hdc;
1829

1830
    TRACE(" returning %p (GL drawable %lu)\n", ret, ctx ? ctx->drawables[1] : 0);
1831 1832 1833
    return ret;
}

1834 1835 1836 1837 1838
/**
 * X11DRV_wglGetProcAddress
 *
 * For OpenGL32 wglGetProcAddress.
 */
1839
PROC CDECL X11DRV_wglGetProcAddress(LPCSTR lpszProc)
1840 1841
{
    int i, j;
1842
    const WineGLExtension *ext;
1843 1844 1845 1846 1847

    int padding = 32 - strlen(lpszProc);
    if (padding < 0)
        padding = 0;

1848
    if (!has_opengl()) return NULL;
1849

1850 1851 1852
    /* Check the table of WGL extensions to see if we need to return a WGL extension
     * or a function pointer to a native OpenGL function. */
    if(strncmp(lpszProc, "wgl", 3) != 0) {
1853
        return pglXGetProcAddressARB((const GLubyte*)lpszProc);
1854 1855 1856 1857 1858 1859 1860 1861 1862
    } else {
        TRACE("('%s'):%*s", lpszProc, padding, " ");
        for (i = 0; i < WineGLExtensionListSize; ++i) {
            ext = WineGLExtensionList[i];
            for (j = 0; ext->extEntryPoints[j].funcName; ++j) {
                if (strcmp(ext->extEntryPoints[j].funcName, lpszProc) == 0) {
                    TRACE("(%p) - WineGL\n", ext->extEntryPoints[j].funcAddress);
                    return ext->extEntryPoints[j].funcAddress;
                }
1863 1864 1865 1866
            }
        }
    }

1867
    WARN("(%s) - not found\n", lpszProc);
1868 1869 1870
    return NULL;
}

1871 1872 1873 1874 1875
/**
 * X11DRV_wglMakeCurrent
 *
 * For OpenGL32 wglMakeCurrent.
 */
1876
BOOL CDECL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) {
1877
    BOOL ret;
1878
    HDC hdc = physDev->hdc;
1879
    DWORD type = GetObjectType(hdc);
1880
    Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
1881 1882 1883

    TRACE("(%p,%p)\n", hdc, hglrc);

1884
    if (!has_opengl()) return FALSE;
1885

1886
    wine_tsx11_lock();
1887 1888 1889 1890 1891
    if (hglrc == NULL)
    {
        Wine_GLContext *prev_ctx = NtCurrentTeb()->glContext;
        if (prev_ctx) prev_ctx->tid = 0;

1892 1893
        ret = pglXMakeCurrent(gdi_display, None, NULL);
        NtCurrentTeb()->glContext = NULL;
1894 1895 1896
    }
    else if (ctx->fmt->iPixelFormat != physDev->current_pf)
    {
1897 1898 1899 1900
        WARN( "mismatched pixel format hdc %p %u ctx %p %u\n",
              hdc, physDev->current_pf, ctx, ctx->fmt->iPixelFormat );
        SetLastError( ERROR_INVALID_PIXEL_FORMAT );
        ret = FALSE;
1901 1902 1903
    }
    else
    {
1904
        Drawable drawable = get_glxdrawable(physDev);
1905 1906
        Wine_GLContext *prev_ctx = NtCurrentTeb()->glContext;
        if (prev_ctx) prev_ctx->tid = 0;
1907

1908 1909 1910 1911
        /* The describe lines below are for debugging purposes only */
        if (TRACE_ON(wgl)) {
            describeDrawable(physDev);
            describeContext(ctx);
1912
        }
1913

1914 1915
        TRACE(" make current for dis %p, drawable %p, ctx %p\n", gdi_display, (void*) drawable, ctx->ctx);
        ret = pglXMakeCurrent(gdi_display, drawable, ctx->ctx);
1916
        NtCurrentTeb()->glContext = ctx;
1917

1918
        if(ret)
1919
        {
1920
            ctx->has_been_current = TRUE;
1921
            ctx->tid = GetCurrentThreadId();
1922
            ctx->hdc = hdc;
1923
            ctx->read_hdc = hdc;
1924 1925 1926
            ctx->drawables[0] = drawable;
            ctx->drawables[1] = drawable;
            ctx->refresh_drawables = FALSE;
1927 1928 1929 1930 1931 1932

            if (type == OBJ_MEMDC)
            {
                ctx->do_escape = TRUE;
                pglDrawBuffer(GL_FRONT_LEFT);
            }
1933 1934 1935 1936 1937 1938 1939
        }
    }
    wine_tsx11_unlock();
    TRACE(" returning %s\n", (ret ? "True" : "False"));
    return ret;
}

1940 1941 1942 1943 1944
/**
 * X11DRV_wglMakeContextCurrentARB
 *
 * For OpenGL32 wglMakeContextCurrentARB
 */
1945
BOOL CDECL X11DRV_wglMakeContextCurrentARB(X11DRV_PDEVICE* pDrawDev, X11DRV_PDEVICE* pReadDev, HGLRC hglrc)
1946 1947
{
    BOOL ret;
1948

1949
    TRACE("(%p,%p,%p)\n", pDrawDev, pReadDev, hglrc);
1950

1951
    if (!has_opengl()) return 0;
1952

1953
    wine_tsx11_lock();
1954 1955 1956 1957 1958
    if (hglrc == NULL)
    {
        Wine_GLContext *prev_ctx = NtCurrentTeb()->glContext;
        if (prev_ctx) prev_ctx->tid = 0;

1959
        ret = pglXMakeCurrent(gdi_display, None, NULL);
1960
        NtCurrentTeb()->glContext = NULL;
1961 1962 1963
    }
    else
    {
1964 1965 1966
        if (NULL == pglXMakeContextCurrent) {
            ret = FALSE;
        } else {
1967
            Wine_GLContext *prev_ctx = NtCurrentTeb()->glContext;
1968
            Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
1969 1970
            Drawable d_draw = get_glxdrawable(pDrawDev);
            Drawable d_read = get_glxdrawable(pReadDev);
1971

1972 1973
            if (prev_ctx) prev_ctx->tid = 0;

1974
            ctx->has_been_current = TRUE;
1975
            ctx->tid = GetCurrentThreadId();
1976
            ctx->hdc = pDrawDev->hdc;
1977
            ctx->read_hdc = pReadDev->hdc;
1978 1979 1980
            ctx->drawables[0] = d_draw;
            ctx->drawables[1] = d_read;
            ctx->refresh_drawables = FALSE;
1981
            ret = pglXMakeContextCurrent(gdi_display, d_draw, d_read, ctx->ctx);
1982
            NtCurrentTeb()->glContext = ctx;
1983 1984 1985 1986 1987 1988 1989 1990
        }
    }
    wine_tsx11_unlock();

    TRACE(" returning %s\n", (ret ? "True" : "False"));
    return ret;
}

1991 1992 1993
/**
 * X11DRV_wglShareLists
 *
1994
 * For OpenGL32 wglShareLists.
1995
 */
1996
BOOL CDECL X11DRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) {
1997 1998 1999 2000 2001
    Wine_GLContext *org  = (Wine_GLContext *) hglrc1;
    Wine_GLContext *dest = (Wine_GLContext *) hglrc2;

    TRACE("(%p, %p)\n", org, dest);

2002
    if (!has_opengl()) return FALSE;
2003

2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
    /* Sharing of display lists works differently in GLX and WGL. In case of GLX it is done
     * at context creation time but in case of WGL it is done using wglShareLists.
     * In the past we tried to emulate wglShareLists by delaying GLX context creation until
     * either a wglMakeCurrent or wglShareLists. This worked fine for most apps but it causes
     * issues for OpenGL 3 because there wglCreateContextAttribsARB can fail in a lot of cases,
     * so there delaying context creation doesn't work.
     *
     * The new approach is to create a GLX context in wglCreateContext / wglCreateContextAttribsARB
     * and when a program requests sharing we recreate the destination context if it hasn't been made
     * current or when it hasn't shared display lists before.
     */

    if((org->has_been_current && dest->has_been_current) || dest->has_been_current)
    {
        ERR("Could not share display lists, one of the contexts has been current already !\n");
2019
        return FALSE;
2020 2021 2022 2023 2024 2025 2026 2027 2028 2029
    }
    else if(dest->sharing)
    {
        ERR("Could not share display lists because hglrc2 has already shared lists before\n");
        return FALSE;
    }
    else
    {
        if((GetObjectType(org->hdc) == OBJ_MEMDC) ^ (GetObjectType(dest->hdc) == OBJ_MEMDC))
        {
2030 2031 2032
            WARN("Attempting to share a context between a direct and indirect rendering context, expect issues!\n");
        }

2033 2034 2035
        wine_tsx11_lock();
        describeContext(org);
        describeContext(dest);
2036

2037 2038 2039 2040 2041 2042 2043 2044 2045
        /* Re-create the GLX context and share display lists */
        pglXDestroyContext(gdi_display, dest->ctx);
        dest->ctx = create_glxcontext(gdi_display, dest, org->ctx);
        wine_tsx11_unlock();
        TRACE(" re-created an OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);

        org->sharing = TRUE;
        dest->sharing = TRUE;
        return TRUE;
2046 2047 2048 2049
    }
    return FALSE;
}

2050
static BOOL internal_wglUseFontBitmaps(HDC hdc, DWORD first, DWORD count, DWORD listBase, DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
2051 2052 2053
{
     /* We are running using client-side rendering fonts... */
     GLYPHMETRICS gm;
2054
     unsigned int glyph, size = 0;
2055 2056 2057 2058 2059 2060 2061 2062 2063
     void *bitmap = NULL, *gl_bitmap = NULL;
     int org_alignment;

     wine_tsx11_lock();
     pglGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
     pglPixelStorei(GL_UNPACK_ALIGNMENT, 4);
     wine_tsx11_unlock();

     for (glyph = first; glyph < first + count; glyph++) {
2064 2065
         static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
         unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &identity);
2066
         unsigned int height, width_int;
2067

2068
         TRACE("Glyph : %3d / List : %d\n", glyph, listBase);
2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082
         if (needed_size == GDI_ERROR) {
             TRACE("  - needed size : %d (GDI_ERROR)\n", needed_size);
             goto error;
         } else {
             TRACE("  - needed size : %d\n", needed_size);
         }

         if (needed_size > size) {
             size = needed_size;
             HeapFree(GetProcessHeap(), 0, bitmap);
             HeapFree(GetProcessHeap(), 0, gl_bitmap);
             bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
             gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
         }
2083 2084
         if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, &identity) == GDI_ERROR)
             goto error;
2085
         if (TRACE_ON(wgl)) {
2086
             unsigned int height, width, bitmask;
2087
             unsigned char *bitmap_ = bitmap;
2088 2089

             TRACE("  - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
2090
             TRACE("  - origin : (%d , %d)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117
             TRACE("  - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
             if (needed_size != 0) {
                 TRACE("  - bitmap :\n");
                 for (height = 0; height < gm.gmBlackBoxY; height++) {
                     TRACE("      ");
                     for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
                         if (bitmask == 0) {
                             bitmap_ += 1;
                             bitmask = 0x80;
                         }
                         if (*bitmap_ & bitmask)
                             TRACE("*");
                         else
                             TRACE(" ");
                     }
                     bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
                     TRACE("\n");
                 }
             }
         }

         /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
         * glyph for it to be drawn properly.
         */
         if (needed_size != 0) {
             width_int = (gm.gmBlackBoxX + 31) / 32;
             for (height = 0; height < gm.gmBlackBoxY; height++) {
2118
                 unsigned int width;
2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129
                 for (width = 0; width < width_int; width++) {
                     ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
                     ((int *) bitmap)[height * width_int + width];
                 }
             }
         }

         wine_tsx11_lock();
         pglNewList(listBase++, GL_COMPILE);
         if (needed_size != 0) {
             pglBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
2130
                     0 - gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - gm.gmptGlyphOrigin.y,
2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158
                     gm.gmCellIncX, gm.gmCellIncY,
                     gl_bitmap);
         } else {
             /* This is the case of 'empty' glyphs like the space character */
             pglBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
         }
         pglEndList();
         wine_tsx11_unlock();
     }

     wine_tsx11_lock();
     pglPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
     wine_tsx11_unlock();

     HeapFree(GetProcessHeap(), 0, bitmap);
     HeapFree(GetProcessHeap(), 0, gl_bitmap);
     return TRUE;

  error:
     wine_tsx11_lock();
     pglPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
     wine_tsx11_unlock();

     HeapFree(GetProcessHeap(), 0, bitmap);
     HeapFree(GetProcessHeap(), 0, gl_bitmap);
     return FALSE;
}

2159 2160 2161 2162 2163
/**
 * X11DRV_wglUseFontBitmapsA
 *
 * For OpenGL32 wglUseFontBitmapsA.
 */
2164
BOOL CDECL X11DRV_wglUseFontBitmapsA(X11DRV_PDEVICE *physDev, DWORD first, DWORD count, DWORD listBase)
2165
{
2166
     Font fid = physDev->font;
2167

2168
     TRACE("(%p, %d, %d, %d) using font %ld\n", physDev->hdc, first, count, listBase, fid);
2169

2170
     if (!has_opengl()) return FALSE;
2171

2172
     if (fid == 0) {
2173
         return internal_wglUseFontBitmaps(physDev->hdc, first, count, listBase, GetGlyphOutlineA);
2174 2175 2176 2177 2178 2179 2180 2181 2182
     }

     wine_tsx11_lock();
     /* I assume that the glyphs are at the same position for X and for Windows */
     pglXUseXFont(fid, first, count, listBase);
     wine_tsx11_unlock();
     return TRUE;
}

2183 2184 2185 2186 2187
/**
 * X11DRV_wglUseFontBitmapsW
 *
 * For OpenGL32 wglUseFontBitmapsW.
 */
2188
BOOL CDECL X11DRV_wglUseFontBitmapsW(X11DRV_PDEVICE *physDev, DWORD first, DWORD count, DWORD listBase)
2189
{
2190
     Font fid = physDev->font;
2191

2192
     TRACE("(%p, %d, %d, %d) using font %ld\n", physDev->hdc, first, count, listBase, fid);
2193

2194
     if (!has_opengl()) return FALSE;
2195

2196
     if (fid == 0) {
2197
         return internal_wglUseFontBitmaps(physDev->hdc, first, count, listBase, GetGlyphOutlineW);
2198 2199 2200 2201 2202 2203 2204 2205 2206 2207
     }

     WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");

     wine_tsx11_lock();
     /* I assume that the glyphs are at the same position for X and for Windows */
     pglXUseXFont(fid, first, count, listBase);
     wine_tsx11_unlock();
     return TRUE;
}
2208

2209
/* WGL helper function which handles differences in glGetIntegerv from WGL and GLX */
2210 2211 2212 2213 2214 2215 2216
static void WINAPI X11DRV_wglGetIntegerv(GLenum pname, GLint* params)
{
    wine_tsx11_lock();
    switch(pname)
    {
    case GL_DEPTH_BITS:
        {
2217
            Wine_GLContext *ctx = NtCurrentTeb()->glContext;
2218 2219 2220 2221 2222 2223 2224

            pglGetIntegerv(pname, params);
            /**
             * if we cannot find a Wine Context
             * we only have the default wine desktop context,
             * so if we have only a 24 depth say we have 32
             */
2225
            if (!ctx && *params == 24) {
2226 2227 2228 2229
                *params = 32;
            }
            TRACE("returns GL_DEPTH_BITS as '%d'\n", *params);
            break;
2230
        }
2231 2232
    case GL_ALPHA_BITS:
        {
2233
            Wine_GLContext *ctx = NtCurrentTeb()->glContext;
2234

2235
            pglXGetFBConfigAttrib(gdi_display, ctx->fmt->fbconfig, GLX_ALPHA_SIZE, params);
2236 2237 2238 2239 2240 2241
            TRACE("returns GL_ALPHA_BITS as '%d'\n", *params);
            break;
        }
    default:
        pglGetIntegerv(pname, params);
        break;
2242
    }
2243
    wine_tsx11_unlock();
2244 2245
}

2246
void flush_gl_drawable(X11DRV_PDEVICE *physDev)
2247 2248 2249
{
    int w, h;

2250
    if (!physDev->gl_copy)
2251 2252 2253 2254 2255 2256
        return;

    w = physDev->dc_rect.right - physDev->dc_rect.left;
    h = physDev->dc_rect.bottom - physDev->dc_rect.top;

    if(w > 0 && h > 0) {
2257 2258 2259
        Drawable src = physDev->pixmap;
        if(!src) src = physDev->gl_drawable;

2260 2261
        /* The GL drawable may be lagged behind if we don't flush first, so
         * flush the display make sure we copy up-to-date data */
2262
        wine_tsx11_lock();
2263
        XFlush(gdi_display);
2264
        XSetFunction(gdi_display, physDev->gc, GXcopy);
2265 2266
        XCopyArea(gdi_display, src, physDev->drawable, physDev->gc, 0, 0, w, h,
                  physDev->dc_rect.left, physDev->dc_rect.top);
2267
        wine_tsx11_unlock();
2268 2269 2270 2271
    }
}


2272 2273
static void WINAPI X11DRV_wglFinish(void)
{
2274
    Wine_GLContext *ctx = NtCurrentTeb()->glContext;
2275
    enum x11drv_escape_codes code = X11DRV_FLUSH_GL_DRAWABLE;
2276

2277
    wine_tsx11_lock();
2278
    sync_context(ctx);
2279 2280
    pglFinish();
    wine_tsx11_unlock();
2281
    if (ctx) ExtEscape(ctx->hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, 0, NULL );
2282 2283 2284 2285
}

static void WINAPI X11DRV_wglFlush(void)
{
2286
    Wine_GLContext *ctx = NtCurrentTeb()->glContext;
2287
    enum x11drv_escape_codes code = X11DRV_FLUSH_GL_DRAWABLE;
2288

2289
    wine_tsx11_lock();
2290
    sync_context(ctx);
2291 2292
    pglFlush();
    wine_tsx11_unlock();
2293
    if (ctx) ExtEscape(ctx->hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, 0, NULL );
2294 2295
}

2296 2297 2298 2299 2300
/**
 * X11DRV_wglCreateContextAttribsARB
 *
 * WGL_ARB_create_context: wglCreateContextAttribsARB
 */
2301
HGLRC CDECL X11DRV_wglCreateContextAttribsARB(X11DRV_PDEVICE *physDev, HGLRC hShareContext, const int* attribList)
2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354
{
    Wine_GLContext *ret;
    WineGLPixelFormat *fmt;
    int hdcPF = physDev->current_pf;
    int fmt_count = 0;

    TRACE("(%p %p %p)\n", physDev, hShareContext, attribList);

    if (!has_opengl()) return 0;

    fmt = ConvertPixelFormatWGLtoGLX(gdi_display, hdcPF, TRUE /* Offscreen */, &fmt_count);
    /* wglCreateContextAttribsARB supports ALL pixel formats, so also offscreen ones.
     * If this fails something is very wrong on the system. */
    if(!fmt)
    {
        ERR("Cannot get FB Config for iPixelFormat %d, expect problems!\n", hdcPF);
        SetLastError(ERROR_INVALID_PIXEL_FORMAT);
        return NULL;
    }

    wine_tsx11_lock();
    ret = alloc_context();
    wine_tsx11_unlock();
    ret->hdc = physDev->hdc;
    ret->fmt = fmt;
    ret->vis = NULL; /* glXCreateContextAttribsARB requires a fbconfig instead of a visual */
    ret->gl3_context = TRUE;

    ret->numAttribs = 0;
    if(attribList)
    {
        int *pAttribList = (int*)attribList;
        int *pContextAttribList = &ret->attribList[0];
        /* attribList consists of pairs {token, value] terminated with 0 */
        while(pAttribList[0] != 0)
        {
            TRACE("%#x %#x\n", pAttribList[0], pAttribList[1]);
            switch(pAttribList[0])
            {
                case WGL_CONTEXT_MAJOR_VERSION_ARB:
                    pContextAttribList[0] = GLX_CONTEXT_MAJOR_VERSION_ARB;
                    pContextAttribList[1] = pAttribList[1];
                    break;
                case WGL_CONTEXT_MINOR_VERSION_ARB:
                    pContextAttribList[0] = GLX_CONTEXT_MINOR_VERSION_ARB;
                    pContextAttribList[1] = pAttribList[1];
                    break;
                case WGL_CONTEXT_LAYER_PLANE_ARB:
                    break;
                case WGL_CONTEXT_FLAGS_ARB:
                    pContextAttribList[0] = GLX_CONTEXT_FLAGS_ARB;
                    pContextAttribList[1] = pAttribList[1];
                    break;
2355 2356 2357 2358
                case WGL_CONTEXT_PROFILE_MASK_ARB:
                    pContextAttribList[0] = GLX_CONTEXT_PROFILE_MASK_ARB;
                    pContextAttribList[1] = pAttribList[1];
                    break;
2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387
                default:
                    ERR("Unhandled attribList pair: %#x %#x\n", pAttribList[0], pAttribList[1]);
            }

            ret->numAttribs++;
            pAttribList += 2;
            pContextAttribList += 2;
        }
    }

    wine_tsx11_lock();
    X11DRV_expect_error(gdi_display, GLXErrorHandler, NULL);
    ret->ctx = create_glxcontext(gdi_display, ret, NULL);

    XSync(gdi_display, False);
    if(X11DRV_check_error() || !ret->ctx)
    {
        /* In the future we should convert the GLX error to a win32 one here if needed */
        ERR("Context creation failed\n");
        free_context(ret);
        wine_tsx11_unlock();
        return NULL;
    }

    wine_tsx11_unlock();
    TRACE(" creating context %p\n", ret);
    return (HGLRC) ret;
}

2388 2389 2390 2391 2392
/**
 * X11DRV_wglGetExtensionsStringARB
 *
 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
 */
2393 2394 2395 2396 2397
static const char * WINAPI X11DRV_wglGetExtensionsStringARB(HDC hdc) {
    TRACE("() returning \"%s\"\n", WineGLInfo.wglExtensions);
    return WineGLInfo.wglExtensions;
}

2398 2399 2400 2401 2402
/**
 * X11DRV_wglCreatePbufferARB
 *
 * WGL_ARB_pbuffer: wglCreatePbufferARB
 */
2403 2404 2405
static HPBUFFERARB WINAPI X11DRV_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList)
{
    Wine_GLPBuffer* object = NULL;
2406
    WineGLPixelFormat *fmt = NULL;
2407 2408
    int nCfgs = 0;
    int attribs[256];
2409
    int nAttribs = 0;
2410 2411 2412 2413 2414 2415 2416 2417 2418 2419

    TRACE("(%p, %d, %d, %d, %p)\n", hdc, iPixelFormat, iWidth, iHeight, piAttribList);

    if (0 >= iPixelFormat) {
        ERR("(%p): unexpected iPixelFormat(%d) <= 0, returns NULL\n", hdc, iPixelFormat);
        SetLastError(ERROR_INVALID_PIXEL_FORMAT);
        return NULL; /* unexpected error */
    }

    /* Convert the WGL pixelformat to a GLX format, if it fails then the format is invalid */
2420
    fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, TRUE /* Offscreen */, &nCfgs);
2421
    if(!fmt) {
2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435
        ERR("(%p): unexpected iPixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, iPixelFormat, nCfgs);
        SetLastError(ERROR_INVALID_PIXEL_FORMAT);
        goto create_failed; /* unexpected error */
    }

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLPBuffer));
    if (NULL == object) {
        SetLastError(ERROR_NO_SYSTEM_RESOURCES);
        goto create_failed; /* unexpected error */
    }
    object->hdc = hdc;
    object->display = gdi_display;
    object->width = iWidth;
    object->height = iHeight;
2436
    object->fmt = fmt;
2437 2438 2439

    PUSH2(attribs, GLX_PBUFFER_WIDTH,  iWidth);
    PUSH2(attribs, GLX_PBUFFER_HEIGHT, iHeight); 
2440
    while (piAttribList && 0 != *piAttribList) {
2441 2442
        int attr_v;
        switch (*piAttribList) {
2443 2444 2445 2446 2447 2448 2449 2450
            case WGL_PBUFFER_LARGEST_ARB: {
                ++piAttribList;
                attr_v = *piAttribList;
                TRACE("WGL_LARGEST_PBUFFER_ARB = %d\n", attr_v);
                PUSH2(attribs, GLX_LARGEST_PBUFFER, attr_v);
                break;
            }

2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477
            case WGL_TEXTURE_FORMAT_ARB: {
                ++piAttribList;
                attr_v = *piAttribList;
                TRACE("WGL_render_texture Attribute: WGL_TEXTURE_FORMAT_ARB as %x\n", attr_v);
                if (use_render_texture_ati) {
                    int type = 0;
                    switch (attr_v) {
                        case WGL_NO_TEXTURE_ARB: type = GLX_NO_TEXTURE_ATI; break ;
                        case WGL_TEXTURE_RGB_ARB: type = GLX_TEXTURE_RGB_ATI; break ;
                        case WGL_TEXTURE_RGBA_ARB: type = GLX_TEXTURE_RGBA_ATI; break ;
                        default:
                            SetLastError(ERROR_INVALID_DATA);
                            goto create_failed;
                    }
                    object->use_render_texture = 1;
                    PUSH2(attribs, GLX_TEXTURE_FORMAT_ATI, type);
                } else {
                    if (WGL_NO_TEXTURE_ARB == attr_v) {
                        object->use_render_texture = 0;
                    } else {
                        if (!use_render_texture_emulation) {
                            SetLastError(ERROR_INVALID_DATA);
                            goto create_failed;
                        }
                        switch (attr_v) {
                            case WGL_TEXTURE_RGB_ARB:
                                object->use_render_texture = GL_RGB;
2478 2479 2480
                                object->texture_bpp = 3;
                                object->texture_format = GL_RGB;
                                object->texture_type = GL_UNSIGNED_BYTE;
2481 2482 2483
                                break;
                            case WGL_TEXTURE_RGBA_ARB:
                                object->use_render_texture = GL_RGBA;
2484 2485 2486
                                object->texture_bpp = 4;
                                object->texture_format = GL_RGBA;
                                object->texture_type = GL_UNSIGNED_BYTE;
2487
                                break;
2488 2489 2490 2491

                            /* WGL_FLOAT_COMPONENTS_NV */
                            case WGL_TEXTURE_FLOAT_R_NV:
                                object->use_render_texture = GL_FLOAT_R_NV;
2492 2493 2494
                                object->texture_bpp = 4;
                                object->texture_format = GL_RED;
                                object->texture_type = GL_FLOAT;
2495 2496 2497
                                break;
                            case WGL_TEXTURE_FLOAT_RG_NV:
                                object->use_render_texture = GL_FLOAT_RG_NV;
2498 2499 2500
                                object->texture_bpp = 8;
                                object->texture_format = GL_LUMINANCE_ALPHA;
                                object->texture_type = GL_FLOAT;
2501 2502 2503
                                break;
                            case WGL_TEXTURE_FLOAT_RGB_NV:
                                object->use_render_texture = GL_FLOAT_RGB_NV;
2504 2505 2506
                                object->texture_bpp = 12;
                                object->texture_format = GL_RGB;
                                object->texture_type = GL_FLOAT;
2507 2508 2509
                                break;
                            case WGL_TEXTURE_FLOAT_RGBA_NV:
                                object->use_render_texture = GL_FLOAT_RGBA_NV;
2510 2511 2512
                                object->texture_bpp = 16;
                                object->texture_format = GL_RGBA;
                                object->texture_type = GL_FLOAT;
2513
                                break;
2514
                            default:
2515
                                ERR("Unknown texture format: %x\n", attr_v);
2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554
                                SetLastError(ERROR_INVALID_DATA);
                                goto create_failed;
                        }
                    }
                }
                break;
            }

            case WGL_TEXTURE_TARGET_ARB: {
                ++piAttribList;
                attr_v = *piAttribList;
                TRACE("WGL_render_texture Attribute: WGL_TEXTURE_TARGET_ARB as %x\n", attr_v);
                if (use_render_texture_ati) {
                    int type = 0;
                    switch (attr_v) {
                        case WGL_NO_TEXTURE_ARB: type = GLX_NO_TEXTURE_ATI; break ;
                        case WGL_TEXTURE_CUBE_MAP_ARB: type = GLX_TEXTURE_CUBE_MAP_ATI; break ;
                        case WGL_TEXTURE_1D_ARB: type = GLX_TEXTURE_1D_ATI; break ;
                        case WGL_TEXTURE_2D_ARB: type = GLX_TEXTURE_2D_ATI; break ;
                        default:
                            SetLastError(ERROR_INVALID_DATA);
                            goto create_failed;
                    }
                    PUSH2(attribs, GLX_TEXTURE_TARGET_ATI, type);
                } else {
                    if (WGL_NO_TEXTURE_ARB == attr_v) {
                        object->texture_target = 0;
                    } else {
                        if (!use_render_texture_emulation) {
                            SetLastError(ERROR_INVALID_DATA);
                            goto create_failed;
                        }
                        switch (attr_v) {
                            case WGL_TEXTURE_CUBE_MAP_ARB: {
                                if (iWidth != iHeight) {
                                    SetLastError(ERROR_INVALID_DATA);
                                    goto create_failed;
                                }
                                object->texture_target = GL_TEXTURE_CUBE_MAP;
2555
                                object->texture_bind_target = GL_TEXTURE_BINDING_CUBE_MAP;
2556 2557 2558 2559 2560 2561 2562 2563
                               break;
                            }
                            case WGL_TEXTURE_1D_ARB: {
                                if (1 != iHeight) {
                                    SetLastError(ERROR_INVALID_DATA);
                                    goto create_failed;
                                }
                                object->texture_target = GL_TEXTURE_1D;
2564
                                object->texture_bind_target = GL_TEXTURE_BINDING_1D;
2565 2566 2567 2568
                                break;
                            }
                            case WGL_TEXTURE_2D_ARB: {
                                object->texture_target = GL_TEXTURE_2D;
2569
                                object->texture_bind_target = GL_TEXTURE_BINDING_2D;
2570 2571
                                break;
                            }
2572 2573 2574 2575 2576
                            case WGL_TEXTURE_RECTANGLE_NV: {
                                object->texture_target = GL_TEXTURE_RECTANGLE_NV;
                                object->texture_bind_target = GL_TEXTURE_BINDING_RECTANGLE_NV;
                                break;
                            }
2577
                            default:
2578
                                ERR("Unknown texture target: %x\n", attr_v);
2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605
                                SetLastError(ERROR_INVALID_DATA);
                                goto create_failed;
                        }
                    }
                }
                break;
            }

            case WGL_MIPMAP_TEXTURE_ARB: {
                ++piAttribList;
                attr_v = *piAttribList;
                TRACE("WGL_render_texture Attribute: WGL_MIPMAP_TEXTURE_ARB as %x\n", attr_v);
                if (use_render_texture_ati) {
                    PUSH2(attribs, GLX_MIPMAP_TEXTURE_ATI, attr_v);
                } else {
                    if (!use_render_texture_emulation) {
                        SetLastError(ERROR_INVALID_DATA);
                        goto create_failed;
                    }
                }
                break;
            }
        }
        ++piAttribList;
    }

    PUSH1(attribs, None);
2606
    wine_tsx11_lock();
2607
    object->drawable = pglXCreatePbuffer(gdi_display, fmt->fbconfig, attribs);
2608
    wine_tsx11_unlock();
2609 2610 2611 2612 2613 2614
    TRACE("new Pbuffer drawable as %p\n", (void*) object->drawable);
    if (!object->drawable) {
        SetLastError(ERROR_NO_SYSTEM_RESOURCES);
        goto create_failed; /* unexpected error */
    }
    TRACE("->(%p)\n", object);
2615
    return object;
2616 2617 2618 2619

create_failed:
    HeapFree(GetProcessHeap(), 0, object);
    TRACE("->(FAILED)\n");
2620
    return NULL;
2621 2622
}

2623 2624 2625 2626 2627
/**
 * X11DRV_wglDestroyPbufferARB
 *
 * WGL_ARB_pbuffer: wglDestroyPbufferARB
 */
2628 2629
static GLboolean WINAPI X11DRV_wglDestroyPbufferARB(HPBUFFERARB hPbuffer)
{
2630
    Wine_GLPBuffer* object = hPbuffer;
2631 2632 2633 2634 2635
    TRACE("(%p)\n", hPbuffer);
    if (NULL == object) {
        SetLastError(ERROR_INVALID_HANDLE);
        return GL_FALSE;
    }
2636
    wine_tsx11_lock();
2637
    pglXDestroyPbuffer(object->display, object->drawable);
2638
    wine_tsx11_unlock();
2639 2640 2641 2642
    HeapFree(GetProcessHeap(), 0, object);
    return GL_TRUE;
}

2643 2644 2645 2646
/**
 * X11DRV_wglGetPbufferDCARB
 *
 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2647 2648 2649 2650
 * The function wglGetPbufferDCARB returns a device context for a pbuffer.
 * Gdi32 implements the part of this function which creates a device context.
 * This part associates the physDev with the X drawable of the pbuffer.
 */
2651
HDC CDECL X11DRV_wglGetPbufferDCARB(X11DRV_PDEVICE *physDev, HPBUFFERARB hPbuffer)
2652
{
2653
    Wine_GLPBuffer* object = hPbuffer;
2654 2655 2656 2657 2658 2659
    if (NULL == object) {
        SetLastError(ERROR_INVALID_HANDLE);
        return NULL;
    }

    /* The function wglGetPbufferDCARB returns a DC to which the pbuffer can be connected.
2660
     * All formats in our pixelformat list are compatible with each other and the main drawable. */
2661
    physDev->current_pf = object->fmt->iPixelFormat;
2662
    physDev->drawable = object->drawable;
2663 2664
    SetRect( &physDev->drawable_rect, 0, 0, object->width, object->height );
    physDev->dc_rect = physDev->drawable_rect;
2665 2666 2667

    TRACE("(%p)->(%p)\n", hPbuffer, physDev->hdc);
    return physDev->hdc;
2668 2669
}

2670 2671 2672 2673 2674
/**
 * X11DRV_wglQueryPbufferARB
 *
 * WGL_ARB_pbuffer: wglQueryPbufferARB
 */
2675 2676
static GLboolean WINAPI X11DRV_wglQueryPbufferARB(HPBUFFERARB hPbuffer, int iAttribute, int *piValue)
{
2677
    Wine_GLPBuffer* object = hPbuffer;
2678 2679 2680 2681 2682 2683 2684
    TRACE("(%p, 0x%x, %p)\n", hPbuffer, iAttribute, piValue);
    if (NULL == object) {
        SetLastError(ERROR_INVALID_HANDLE);
        return GL_FALSE;
    }
    switch (iAttribute) {
        case WGL_PBUFFER_WIDTH_ARB:
2685
            wine_tsx11_lock();
2686
            pglXQueryDrawable(object->display, object->drawable, GLX_WIDTH, (unsigned int*) piValue);
2687
            wine_tsx11_unlock();
2688 2689
            break;
        case WGL_PBUFFER_HEIGHT_ARB:
2690
            wine_tsx11_lock();
2691
            pglXQueryDrawable(object->display, object->drawable, GLX_HEIGHT, (unsigned int*) piValue);
2692
            wine_tsx11_unlock();
2693 2694 2695
            break;

        case WGL_PBUFFER_LOST_ARB:
2696 2697 2698 2699 2700
            /* GLX Pbuffers cannot be lost by default. We can support this by
             * setting GLX_PRESERVED_CONTENTS to False and using glXSelectEvent
             * to receive pixel buffer clobber events, however that may or may
             * not give any benefit */
            *piValue = GL_FALSE;
2701 2702 2703 2704 2705 2706
            break;

        case WGL_TEXTURE_FORMAT_ARB:
            if (use_render_texture_ati) {
                unsigned int tmp;
                int type = WGL_NO_TEXTURE_ARB;
2707
                wine_tsx11_lock();
2708
                pglXQueryDrawable(object->display, object->drawable, GLX_TEXTURE_FORMAT_ATI, &tmp);
2709
                wine_tsx11_unlock();
2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723
                switch (tmp) {
                    case GLX_NO_TEXTURE_ATI: type = WGL_NO_TEXTURE_ARB; break ;
                    case GLX_TEXTURE_RGB_ATI: type = WGL_TEXTURE_RGB_ARB; break ;
                    case GLX_TEXTURE_RGBA_ATI: type = WGL_TEXTURE_RGBA_ARB; break ;
                }
                *piValue = type;
            } else {
                if (!object->use_render_texture) {
                    *piValue = WGL_NO_TEXTURE_ARB;
                } else {
                    if (!use_render_texture_emulation) {
                        SetLastError(ERROR_INVALID_HANDLE);
                        return GL_FALSE;
                    }
2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745
                    switch(object->use_render_texture) {
                        case GL_RGB:
                            *piValue = WGL_TEXTURE_RGB_ARB;
                            break;
                        case GL_RGBA:
                            *piValue = WGL_TEXTURE_RGBA_ARB;
                            break;
                        /* WGL_FLOAT_COMPONENTS_NV */
                        case GL_FLOAT_R_NV:
                            *piValue = WGL_TEXTURE_FLOAT_R_NV;
                            break;
                        case GL_FLOAT_RG_NV:
                            *piValue = WGL_TEXTURE_FLOAT_RG_NV;
                            break;
                        case GL_FLOAT_RGB_NV:
                            *piValue = WGL_TEXTURE_FLOAT_RGB_NV;
                            break;
                        case GL_FLOAT_RGBA_NV:
                            *piValue = WGL_TEXTURE_FLOAT_RGBA_NV;
                            break;
                        default:
                            ERR("Unknown texture format: %x\n", object->use_render_texture);
2746 2747 2748 2749 2750 2751 2752 2753 2754
                    }
                }
            }
            break;

        case WGL_TEXTURE_TARGET_ARB:
            if (use_render_texture_ati) {
                unsigned int tmp;
                int type = WGL_NO_TEXTURE_ARB;
2755
                wine_tsx11_lock();
2756
                pglXQueryDrawable(object->display, object->drawable, GLX_TEXTURE_TARGET_ATI, &tmp);
2757
                wine_tsx11_unlock();
2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773
                switch (tmp) {
                    case GLX_NO_TEXTURE_ATI: type = WGL_NO_TEXTURE_ARB; break ;
                    case GLX_TEXTURE_CUBE_MAP_ATI: type = WGL_TEXTURE_CUBE_MAP_ARB; break ;
                    case GLX_TEXTURE_1D_ATI: type = WGL_TEXTURE_1D_ARB; break ;
                    case GLX_TEXTURE_2D_ATI: type = WGL_TEXTURE_2D_ARB; break ;
                }
                *piValue = type;
            } else {
            if (!object->texture_target) {
                *piValue = WGL_NO_TEXTURE_ARB;
            } else {
                if (!use_render_texture_emulation) {
                    SetLastError(ERROR_INVALID_DATA);      
                    return GL_FALSE;
                }
                switch (object->texture_target) {
2774 2775 2776
                    case GL_TEXTURE_1D:       *piValue = WGL_TEXTURE_1D_ARB; break;
                    case GL_TEXTURE_2D:       *piValue = WGL_TEXTURE_2D_ARB; break;
                    case GL_TEXTURE_CUBE_MAP: *piValue = WGL_TEXTURE_CUBE_MAP_ARB; break;
2777
                    case GL_TEXTURE_RECTANGLE_NV: *piValue = WGL_TEXTURE_RECTANGLE_NV; break;
2778 2779 2780 2781 2782 2783 2784
                }
            }
        }
        break;

    case WGL_MIPMAP_TEXTURE_ARB:
        if (use_render_texture_ati) {
2785
            wine_tsx11_lock();
2786
            pglXQueryDrawable(object->display, object->drawable, GLX_MIPMAP_TEXTURE_ATI, (unsigned int*) piValue);
2787
            wine_tsx11_unlock();
2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801
        } else {
            *piValue = GL_FALSE; /** don't support that */
            FIXME("unsupported WGL_ARB_render_texture attribute query for 0x%x\n", iAttribute);
        }
        break;

    default:
        FIXME("unexpected attribute %x\n", iAttribute);
        break;
    }

    return GL_TRUE;
}

2802 2803 2804 2805 2806
/**
 * X11DRV_wglReleasePbufferDCARB
 *
 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
 */
2807 2808 2809
static int WINAPI X11DRV_wglReleasePbufferDCARB(HPBUFFERARB hPbuffer, HDC hdc)
{
    TRACE("(%p, %p)\n", hPbuffer, hdc);
2810
    return DeleteDC(hdc);
2811 2812
}

2813 2814 2815 2816 2817
/**
 * X11DRV_wglSetPbufferAttribARB
 *
 * WGL_ARB_pbuffer: wglSetPbufferAttribARB
 */
2818 2819
static GLboolean WINAPI X11DRV_wglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int *piAttribList)
{
2820
    Wine_GLPBuffer* object = hPbuffer;
2821 2822
    GLboolean ret = GL_FALSE;

2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834
    WARN("(%p, %p): alpha-testing, report any problem\n", hPbuffer, piAttribList);
    if (NULL == object) {
        SetLastError(ERROR_INVALID_HANDLE);
        return GL_FALSE;
    }
    if (!object->use_render_texture) {
        SetLastError(ERROR_INVALID_HANDLE);
        return GL_FALSE;
    }
    if (!use_render_texture_ati && 1 == use_render_texture_emulation) {
        return GL_TRUE;
    }
2835
    if (NULL != pglXDrawableAttribATI) {
2836 2837 2838
        if (use_render_texture_ati) {
            FIXME("Need conversion for GLX_ATI_render_texture\n");
        }
2839 2840 2841
        wine_tsx11_lock();
        ret = pglXDrawableAttribATI(object->display, object->drawable, piAttribList);
        wine_tsx11_unlock();
2842
    }
2843
    return ret;
2844 2845
}

2846 2847 2848 2849 2850
/**
 * X11DRV_wglChoosePixelFormatARB
 *
 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
 */
2851
static GLboolean WINAPI X11DRV_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats)
2852 2853 2854 2855 2856 2857
{
    int gl_test = 0;
    int attribs[256];
    int nAttribs = 0;
    GLXFBConfig* cfgs = NULL;
    int nCfgs = 0;
2858
    int it;
2859
    int fmt_id;
2860
    WineGLPixelFormat *fmt;
2861
    UINT pfmt_it = 0;
2862
    int run;
2863 2864
    int i;
    DWORD dwFlags = 0;
2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877

    TRACE("(%p, %p, %p, %d, %p, %p): hackish\n", hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
    if (NULL != pfAttribFList) {
        FIXME("unused pfAttribFList\n");
    }

    nAttribs = ConvertAttribWGLtoGLX(piAttribIList, attribs, NULL);
    if (-1 == nAttribs) {
        WARN("Cannot convert WGL to GLX attributes\n");
        return GL_FALSE;
    }
    PUSH1(attribs, None);

2878 2879 2880 2881 2882
    /* There is no 1:1 mapping between GLX and WGL formats because we duplicate some GLX formats for bitmap rendering (see get_formats).
     * Flags like PFD_SUPPORT_GDI, PFD_DRAW_TO_BITMAP and others are a property of the WineGLPixelFormat. We don't query these attributes
     * using glXChooseFBConfig but we filter the result of glXChooseFBConfig later on by passing a dwFlags to 'ConvertPixelFormatGLXtoWGL'. */
    for(i=0; piAttribIList[i] != 0; i+=2)
    {
2883
        switch(piAttribIList[i])
2884
        {
2885 2886 2887 2888
            case WGL_DRAW_TO_BITMAP_ARB:
                if(piAttribIList[i+1])
                    dwFlags |= PFD_DRAW_TO_BITMAP;
                break;
2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902
            case WGL_ACCELERATION_ARB:
                switch(piAttribIList[i+1])
                {
                    case WGL_NO_ACCELERATION_ARB:
                        dwFlags |= PFD_GENERIC_FORMAT;
                        break;
                    case WGL_GENERIC_ACCELERATION_ARB:
                        dwFlags |= PFD_GENERIC_ACCELERATED;
                        break;
                    case WGL_FULL_ACCELERATION_ARB:
                        /* Nothing to do */
                        break;
                }
                break;
2903 2904 2905 2906
            case WGL_SUPPORT_GDI_ARB:
                if(piAttribIList[i+1])
                    dwFlags |= PFD_SUPPORT_GDI;
                break;
2907 2908 2909
        }
    }

2910
    /* Search for FB configurations matching the requirements in attribs */
2911
    wine_tsx11_lock();
2912 2913
    cfgs = pglXChooseFBConfig(gdi_display, DefaultScreen(gdi_display), attribs, &nCfgs);
    if (NULL == cfgs) {
2914
        wine_tsx11_unlock();
2915 2916 2917 2918 2919 2920
        WARN("Compatible Pixel Format not found\n");
        return GL_FALSE;
    }

    /* Loop through all matching formats and check if they are suitable.
    * Note that this function should at max return nMaxFormats different formats */
2921 2922 2923 2924 2925 2926 2927 2928
    for(run=0; run < 2; run++)
    {
        for (it = 0; it < nCfgs; ++it) {
            gl_test = pglXGetFBConfigAttrib(gdi_display, cfgs[it], GLX_FBCONFIG_ID, &fmt_id);
            if (gl_test) {
                ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
                continue;
            }
2929

2930
            /* Search for the format in our list of compatible formats */
2931
            fmt = ConvertPixelFormatGLXtoWGL(gdi_display, fmt_id, dwFlags);
2932 2933
            if(!fmt)
                continue;
2934

2935 2936 2937 2938 2939 2940 2941 2942 2943
            /* During the first run we only want onscreen formats and during the second only offscreen 'XOR' */
            if( ((run == 0) && fmt->offscreenOnly) || ((run == 1) && !fmt->offscreenOnly) )
                continue;

            if(pfmt_it < nMaxFormats) {
                piFormats[pfmt_it] = fmt->iPixelFormat;
                TRACE("at %d/%d found FBCONFIG_ID 0x%x (%d)\n", it + 1, nCfgs, fmt_id, piFormats[pfmt_it]);
            }
            pfmt_it++;
2944
        }
2945 2946 2947 2948 2949
    }

    *nNumFormats = pfmt_it;
    /** free list */
    XFree(cfgs);
2950
    wine_tsx11_unlock();
2951 2952 2953
    return GL_TRUE;
}

2954 2955 2956 2957 2958
/**
 * X11DRV_wglGetPixelFormatAttribivARB
 *
 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
 */
2959
static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues)
2960 2961
{
    UINT i;
2962
    WineGLPixelFormat *fmt = NULL;
2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974
    int hTest;
    int tmp;
    int curGLXAttr = 0;
    int nWGLFormats = 0;

    TRACE("(%p, %d, %d, %d, %p, %p)\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);

    if (0 < iLayerPlane) {
        FIXME("unsupported iLayerPlane(%d) > 0, returns FALSE\n", iLayerPlane);
        return GL_FALSE;
    }

Austin English's avatar
Austin English committed
2975 2976
    /* Convert the WGL pixelformat to a GLX one, if this fails then most likely the iPixelFormat isn't supported.
    * We don't have to fail yet as a program can specify an invalid iPixelFormat (lets say 0) if it wants to query
2977
    * the number of supported WGL formats. Whether the iPixelFormat is valid is handled in the for-loop below. */
2978
    fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, TRUE /* Offscreen */, &nWGLFormats);
2979
    if(!fmt) {
2980
        WARN("Unable to convert iPixelFormat %d to a GLX one!\n", iPixelFormat);
2981 2982
    }

2983
    wine_tsx11_lock();
2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998
    for (i = 0; i < nAttributes; ++i) {
        const int curWGLAttr = piAttributes[i];
        TRACE("pAttr[%d] = %x\n", i, curWGLAttr);

        switch (curWGLAttr) {
            case WGL_NUMBER_PIXEL_FORMATS_ARB:
                piValues[i] = nWGLFormats; 
                continue;

            case WGL_SUPPORT_OPENGL_ARB:
                piValues[i] = GL_TRUE; 
                continue;

            case WGL_ACCELERATION_ARB:
                curGLXAttr = GLX_CONFIG_CAVEAT;
2999
                if (!fmt) goto pix_error;
3000 3001 3002 3003 3004 3005
                if(fmt->dwFlags & PFD_GENERIC_FORMAT)
                    piValues[i] = WGL_NO_ACCELERATION_ARB;
                else if(fmt->dwFlags & PFD_GENERIC_ACCELERATED)
                    piValues[i] = WGL_GENERIC_ACCELERATION_ARB;
                else
                    piValues[i] = WGL_FULL_ACCELERATION_ARB;
3006 3007 3008 3009
                continue;

            case WGL_TRANSPARENT_ARB:
                curGLXAttr = GLX_TRANSPARENT_TYPE;
3010 3011
                if (!fmt) goto pix_error;
                hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
3012 3013 3014 3015 3016 3017 3018
                if (hTest) goto get_error;
                    piValues[i] = GL_FALSE;
                if (GLX_NONE != tmp) piValues[i] = GL_TRUE;
                    continue;

            case WGL_PIXEL_TYPE_ARB:
                curGLXAttr = GLX_RENDER_TYPE;
3019 3020
                if (!fmt) goto pix_error;
                hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
3021 3022 3023 3024 3025 3026
                if (hTest) goto get_error;
                TRACE("WGL_PIXEL_TYPE_ARB: GLX_RENDER_TYPE = 0x%x\n", tmp);
                if      (tmp & GLX_RGBA_BIT)           { piValues[i] = WGL_TYPE_RGBA_ARB; }
                else if (tmp & GLX_COLOR_INDEX_BIT)    { piValues[i] = WGL_TYPE_COLORINDEX_ARB; }
                else if (tmp & GLX_RGBA_FLOAT_BIT)     { piValues[i] = WGL_TYPE_RGBA_FLOAT_ATI; }
                else if (tmp & GLX_RGBA_FLOAT_ATI_BIT) { piValues[i] = WGL_TYPE_RGBA_FLOAT_ATI; }
3027
                else if (tmp & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) { piValues[i] = WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT; }
3028 3029 3030 3031 3032 3033 3034
                else {
                    ERR("unexpected RenderType(%x)\n", tmp);
                    piValues[i] = WGL_TYPE_RGBA_ARB;
                }
                continue;

            case WGL_COLOR_BITS_ARB:
3035 3036
                curGLXAttr = GLX_BUFFER_SIZE;
                break;
3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052

            case WGL_BIND_TO_TEXTURE_RGB_ARB:
                if (use_render_texture_ati) {
                    curGLXAttr = GLX_BIND_TO_TEXTURE_RGB_ATI;
                    break;
                }
            case WGL_BIND_TO_TEXTURE_RGBA_ARB:
                if (use_render_texture_ati) {
                    curGLXAttr = GLX_BIND_TO_TEXTURE_RGBA_ATI;
                    break;
                }
                if (!use_render_texture_emulation) {
                    piValues[i] = GL_FALSE;
                    continue;	
                }
                curGLXAttr = GLX_RENDER_TYPE;
3053 3054
                if (!fmt) goto pix_error;
                hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
3055 3056 3057 3058 3059
                if (hTest) goto get_error;
                if (GLX_COLOR_INDEX_BIT == tmp) {
                    piValues[i] = GL_FALSE;  
                    continue;
                }
3060
                hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &tmp);
3061
                if (hTest) goto get_error;
3062
                piValues[i] = (tmp & GLX_PBUFFER_BIT) ? GL_TRUE : GL_FALSE;
3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091
                continue;

            case WGL_BLUE_BITS_ARB:
                curGLXAttr = GLX_BLUE_SIZE;
                break;
            case WGL_RED_BITS_ARB:
                curGLXAttr = GLX_RED_SIZE;
                break;
            case WGL_GREEN_BITS_ARB:
                curGLXAttr = GLX_GREEN_SIZE;
                break;
            case WGL_ALPHA_BITS_ARB:
                curGLXAttr = GLX_ALPHA_SIZE;
                break;
            case WGL_DEPTH_BITS_ARB:
                curGLXAttr = GLX_DEPTH_SIZE;
                break;
            case WGL_STENCIL_BITS_ARB:
                curGLXAttr = GLX_STENCIL_SIZE;
                break;
            case WGL_DOUBLE_BUFFER_ARB:
                curGLXAttr = GLX_DOUBLEBUFFER;
                break;
            case WGL_STEREO_ARB:
                curGLXAttr = GLX_STEREO;
                break;
            case WGL_AUX_BUFFERS_ARB:
                curGLXAttr = GLX_AUX_BUFFERS;
                break;
3092

3093
            case WGL_SUPPORT_GDI_ARB:
3094
                if (!fmt) goto pix_error;
3095 3096
                piValues[i] = (fmt->dwFlags & PFD_SUPPORT_GDI) ? TRUE : FALSE;
                continue;
3097

3098
            case WGL_DRAW_TO_BITMAP_ARB:
3099 3100 3101 3102 3103
                if (!fmt) goto pix_error;
                piValues[i] = (fmt->dwFlags & PFD_DRAW_TO_BITMAP) ? TRUE : FALSE;
                continue;

            case WGL_DRAW_TO_WINDOW_ARB:
3104
            case WGL_DRAW_TO_PBUFFER_ARB:
3105
                if (!fmt) goto pix_error;
3106
                hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &tmp);
3107
                if (hTest) goto get_error;
3108 3109 3110 3111 3112
                if((curWGLAttr == WGL_DRAW_TO_WINDOW_ARB && (tmp&GLX_WINDOW_BIT)) ||
                   (curWGLAttr == WGL_DRAW_TO_PBUFFER_ARB && (tmp&GLX_PBUFFER_BIT)))
                    piValues[i] = GL_TRUE;
                else
                    piValues[i] = GL_FALSE;
3113
                continue;
3114

3115 3116 3117 3118 3119 3120 3121 3122
            case WGL_SWAP_METHOD_ARB:
                /* For now return SWAP_EXCHANGE_ARB which is the best type of buffer switch available.
                 * Later on we can also use GLX_OML_swap_method on drivers which support this. At this
                 * point only ATI offers this.
                 */
                piValues[i] = WGL_SWAP_EXCHANGE_ARB;
                break;

3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134
            case WGL_PBUFFER_LARGEST_ARB:
                curGLXAttr = GLX_LARGEST_PBUFFER;
                break;

            case WGL_SAMPLE_BUFFERS_ARB:
                curGLXAttr = GLX_SAMPLE_BUFFERS_ARB;
                break;

            case WGL_SAMPLES_ARB:
                curGLXAttr = GLX_SAMPLES_ARB;
                break;

3135 3136 3137 3138
            case WGL_FLOAT_COMPONENTS_NV:
                curGLXAttr = GLX_FLOAT_COMPONENTS_NV;
                break;

3139 3140 3141 3142
            case WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT:
                curGLXAttr = GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT;
                break;

3143 3144 3145 3146
            case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:
                curGLXAttr = GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT;
                break;

3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174
            case WGL_ACCUM_RED_BITS_ARB:
                curGLXAttr = GLX_ACCUM_RED_SIZE;
                break;
            case WGL_ACCUM_GREEN_BITS_ARB:
                curGLXAttr = GLX_ACCUM_GREEN_SIZE;
                break;
            case WGL_ACCUM_BLUE_BITS_ARB:
                curGLXAttr = GLX_ACCUM_BLUE_SIZE;
                break;
            case WGL_ACCUM_ALPHA_BITS_ARB:
                curGLXAttr = GLX_ACCUM_ALPHA_SIZE;
                break;
            case WGL_ACCUM_BITS_ARB:
                if (!fmt) goto pix_error;
                hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_RED_SIZE, &tmp);
                if (hTest) goto get_error;
                piValues[i] = tmp;
                hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_GREEN_SIZE, &tmp);
                if (hTest) goto get_error;
                piValues[i] += tmp;
                hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &tmp);
                if (hTest) goto get_error;
                piValues[i] += tmp;
                hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &tmp);
                if (hTest) goto get_error;
                piValues[i] += tmp;
                continue;

3175 3176 3177 3178
            default:
                FIXME("unsupported %x WGL Attribute\n", curWGLAttr);
        }

3179 3180 3181 3182 3183 3184 3185 3186 3187 3188
        /* Retrieve a GLX FBConfigAttrib when the attribute to query is valid and
         * iPixelFormat != 0. When iPixelFormat is 0 the only value which makes
         * sense to query is WGL_NUMBER_PIXEL_FORMATS_ARB.
         *
         * TODO: properly test the behavior of wglGetPixelFormatAttrib*v on Windows
         *       and check which options can work using iPixelFormat=0 and which not.
         *       A problem would be that this function is an extension. This would
         *       mean that the behavior could differ between different vendors (ATI, Nvidia, ..).
         */
        if (0 != curGLXAttr && iPixelFormat != 0) {
3189 3190
            if (!fmt) goto pix_error;
            hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, piValues + i);
3191
            if (hTest) goto get_error;
3192
            curGLXAttr = 0;
3193 3194 3195 3196
        } else { 
            piValues[i] = GL_FALSE; 
        }
    }
3197
    wine_tsx11_unlock();
3198 3199 3200
    return GL_TRUE;

get_error:
3201
    wine_tsx11_unlock();
3202 3203 3204 3205
    ERR("(%p): unexpected failure on GetFBConfigAttrib(%x) returns FALSE\n", hdc, curGLXAttr);
    return GL_FALSE;

pix_error:
3206
    wine_tsx11_unlock();
3207
    ERR("(%p): unexpected iPixelFormat(%d) vs nFormats(%d), returns FALSE\n", hdc, iPixelFormat, nWGLFormats);
3208 3209 3210
    return GL_FALSE;
}

3211 3212 3213 3214 3215 3216 3217 3218 3219
/**
 * X11DRV_wglGetPixelFormatAttribfvARB
 *
 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
 */
static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
{
    int *attr;
    int ret;
3220
    UINT i;
3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244

    TRACE("(%p, %d, %d, %d, %p, %p)\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);

    /* Allocate a temporary array to store integer values */
    attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
    if (!attr) {
        ERR("couldn't allocate %d array\n", nAttributes);
        return GL_FALSE;
    }

    /* Piggy-back on wglGetPixelFormatAttribivARB */
    ret = X11DRV_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
    if (ret) {
        /* Convert integer values to float. Should also check for attributes
           that can give decimal values here */
        for (i=0; i<nAttributes;i++) {
            pfValues[i] = attr[i];
        }
    }

    HeapFree(GetProcessHeap(), 0, attr);
    return ret;
}

3245 3246 3247 3248 3249
/**
 * X11DRV_wglBindTexImageARB
 *
 * WGL_ARB_render_texture: wglBindTexImageARB
 */
3250 3251
static GLboolean WINAPI X11DRV_wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)
{
3252
    Wine_GLPBuffer* object = hPbuffer;
3253 3254
    GLboolean ret = GL_FALSE;

3255 3256 3257 3258 3259 3260 3261 3262 3263
    TRACE("(%p, %d)\n", hPbuffer, iBuffer);
    if (NULL == object) {
        SetLastError(ERROR_INVALID_HANDLE);
        return GL_FALSE;
    }
    if (!object->use_render_texture) {
        SetLastError(ERROR_INVALID_HANDLE);
        return GL_FALSE;
    }
3264

3265
    if (!use_render_texture_ati && 1 == use_render_texture_emulation) {
3266
        static int init = 0;
3267
        int prev_binded_texture = 0;
3268 3269
        GLXContext prev_context;
        Drawable prev_drawable;
3270
        GLXContext tmp_context;
3271

3272 3273 3274 3275
        wine_tsx11_lock();
        prev_context = pglXGetCurrentContext();
        prev_drawable = pglXGetCurrentDrawable();

3276 3277 3278 3279 3280 3281 3282
        /* Our render_texture emulation is basic and lacks some features (1D/Cube support).
           This is mostly due to lack of demos/games using them. Further the use of glReadPixels
           isn't ideal performance wise but I wasn't able to get other ways working.
        */
        if(!init) {
            init = 1; /* Only show the FIXME once for performance reasons */
            FIXME("partial stub!\n");
3283
        }
3284

3285
        TRACE("drawable=%p, context=%p\n", (void*)object->drawable, prev_context);
3286 3287 3288
        tmp_context = pglXCreateNewContext(gdi_display, object->fmt->fbconfig, object->fmt->render_type, prev_context, True);

        pglGetIntegerv(object->texture_bind_target, &prev_binded_texture);
3289

3290
        /* Switch to our pbuffer */
3291
        pglXMakeCurrent(gdi_display, object->drawable, tmp_context);
3292 3293 3294 3295 3296

        /* Make sure that the prev_binded_texture is set as the current texture state isn't shared between contexts.
         * After that upload the pbuffer texture data. */
        pglBindTexture(object->texture_target, prev_binded_texture);
        pglCopyTexImage2D(object->texture_target, 0, object->use_render_texture, 0, 0, object->width, object->height, 0);
3297 3298 3299

        /* Switch back to the original drawable and upload the pbuffer-texture */
        pglXMakeCurrent(object->display, prev_drawable, prev_context);
3300
        pglXDestroyContext(gdi_display, tmp_context);
3301
        wine_tsx11_unlock();
3302
        return GL_TRUE;
3303
    }
3304

3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332
    if (NULL != pglXBindTexImageATI) {
        int buffer;

        switch(iBuffer)
        {
            case WGL_FRONT_LEFT_ARB:
                buffer = GLX_FRONT_LEFT_ATI;
                break;
            case WGL_FRONT_RIGHT_ARB:
                buffer = GLX_FRONT_RIGHT_ATI;
                break;
            case WGL_BACK_LEFT_ARB:
                buffer = GLX_BACK_LEFT_ATI;
                break;
            case WGL_BACK_RIGHT_ARB:
                buffer = GLX_BACK_RIGHT_ATI;
                break;
            default:
                ERR("Unknown iBuffer=%#x\n", iBuffer);
                return FALSE;
        }

        /* In the sample 'ogl_offscreen_rendering_3' from codesampler.net I get garbage on the screen.
         * I'm not sure if that's a bug in the ATI extension or in the program. I think that the program
         * expected a single buffering format since it didn't ask for double buffering. A buffer swap
         * fixed the program. I don't know what the correct behavior is. On the other hand that demo
         * works fine using our pbuffer emulation path.
         */
3333 3334 3335
        wine_tsx11_lock();
        ret = pglXBindTexImageATI(object->display, object->drawable, buffer);
        wine_tsx11_unlock();
3336
    }
3337
    return ret;
3338 3339
}

3340 3341 3342 3343 3344
/**
 * X11DRV_wglReleaseTexImageARB
 *
 * WGL_ARB_render_texture: wglReleaseTexImageARB
 */
3345 3346
static GLboolean WINAPI X11DRV_wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)
{
3347
    Wine_GLPBuffer* object = hPbuffer;
3348 3349
    GLboolean ret = GL_FALSE;

3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361
    TRACE("(%p, %d)\n", hPbuffer, iBuffer);
    if (NULL == object) {
        SetLastError(ERROR_INVALID_HANDLE);
        return GL_FALSE;
    }
    if (!object->use_render_texture) {
        SetLastError(ERROR_INVALID_HANDLE);
        return GL_FALSE;
    }
    if (!use_render_texture_ati && 1 == use_render_texture_emulation) {
        return GL_TRUE;
    }
3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382
    if (NULL != pglXReleaseTexImageATI) {
        int buffer;

        switch(iBuffer)
        {
            case WGL_FRONT_LEFT_ARB:
                buffer = GLX_FRONT_LEFT_ATI;
                break;
            case WGL_FRONT_RIGHT_ARB:
                buffer = GLX_FRONT_RIGHT_ATI;
                break;
            case WGL_BACK_LEFT_ARB:
                buffer = GLX_BACK_LEFT_ATI;
                break;
            case WGL_BACK_RIGHT_ARB:
                buffer = GLX_BACK_RIGHT_ATI;
                break;
            default:
                ERR("Unknown iBuffer=%#x\n", iBuffer);
                return FALSE;
        }
3383 3384 3385
        wine_tsx11_lock();
        ret = pglXReleaseTexImageATI(object->display, object->drawable, buffer);
        wine_tsx11_unlock();
3386
    }
3387
    return ret;
3388 3389
}

3390 3391 3392 3393 3394
/**
 * X11DRV_wglGetExtensionsStringEXT
 *
 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
 */
3395
static const char * WINAPI X11DRV_wglGetExtensionsStringEXT(void) {
3396 3397 3398 3399
    TRACE("() returning \"%s\"\n", WineGLInfo.wglExtensions);
    return WineGLInfo.wglExtensions;
}

3400 3401 3402 3403 3404
/**
 * X11DRV_wglGetSwapIntervalEXT
 *
 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
 */
3405
static int WINAPI X11DRV_wglGetSwapIntervalEXT(VOID) {
3406 3407 3408
    /* GLX_SGI_swap_control doesn't have any provisions for getting the swap
     * interval, so the swap interval has to be tracked. */
    TRACE("()\n");
3409 3410 3411
    return swap_interval;
}

3412 3413 3414 3415 3416
/**
 * X11DRV_wglSwapIntervalEXT
 *
 * WGL_EXT_swap_control: wglSwapIntervalEXT
 */
3417
static BOOL WINAPI X11DRV_wglSwapIntervalEXT(int interval) {
3418 3419
    BOOL ret = TRUE;

3420
    TRACE("(%d)\n", interval);
3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449

    if (interval < 0)
    {
        SetLastError(ERROR_INVALID_DATA);
        return FALSE;
    }
    else if (interval == 0)
    {
        /* wglSwapIntervalEXT considers an interval value of zero to mean that
         * vsync should be disabled, but glXSwapIntervalSGI considers such a
         * value to be an error. Just silently ignore the request for now. */
        WARN("Request to disable vertical sync is not handled\n");
        swap_interval = 0;
    }
    else
    {
        if (pglXSwapIntervalSGI)
        {
            wine_tsx11_lock();
            ret = !pglXSwapIntervalSGI(interval);
            wine_tsx11_unlock();
        }
        else
            WARN("GLX_SGI_swap_control extension is not available\n");

        if (ret)
            swap_interval = interval;
        else
            SetLastError(ERROR_DC_NOT_FOUND);
3450
    }
3451

3452
    return ret;
3453 3454
}

3455 3456 3457 3458 3459 3460
/**
 * X11DRV_wglAllocateMemoryNV
 *
 * WGL_NV_vertex_array_range: wglAllocateMemoryNV
 */
static void* WINAPI X11DRV_wglAllocateMemoryNV(GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority) {
3461
    void *ret = NULL;
3462 3463
    TRACE("(%d, %f, %f, %f)\n", size, readfreq, writefreq, priority );

3464 3465 3466 3467 3468 3469 3470
    if (pglXAllocateMemoryNV)
    {
        wine_tsx11_lock();
        ret = pglXAllocateMemoryNV(size, readfreq, writefreq, priority);
        wine_tsx11_unlock();
    }
    return ret;
3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482
}

/**
 * X11DRV_wglFreeMemoryNV
 *
 * WGL_NV_vertex_array_range: wglFreeMemoryNV
 */
static void WINAPI X11DRV_wglFreeMemoryNV(GLvoid* pointer) {
    TRACE("(%p)\n", pointer);
    if (pglXFreeMemoryNV == NULL)
        return;

3483
    wine_tsx11_lock();
3484
    pglXFreeMemoryNV(pointer);
3485
    wine_tsx11_unlock();
3486 3487
}

3488 3489 3490 3491 3492 3493
/**
 * X11DRV_wglSetPixelFormatWINE
 *
 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
 * This is a WINE-specific wglSetPixelFormat which can set the pixel format multiple times.
 */
3494
BOOL CDECL X11DRV_wglSetPixelFormatWINE(X11DRV_PDEVICE *physDev, int iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd)
3495 3496 3497
{
    TRACE("(%p,%d,%p)\n", physDev, iPixelFormat, ppfd);

3498
    if (!has_opengl()) return FALSE;
3499 3500 3501 3502 3503 3504 3505 3506

    if (physDev->current_pf == iPixelFormat) return TRUE;

    /* Relay to the core SetPixelFormat */
    TRACE("Changing iPixelFormat from %d to %d\n", physDev->current_pf, iPixelFormat);
    return internal_SetPixelFormat(physDev, iPixelFormat, ppfd);
}

3507 3508 3509 3510 3511
/**
 * glxRequireVersion (internal)
 *
 * Check if the supported GLX version matches requiredVersion.
 */
3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522
static BOOL glxRequireVersion(int requiredVersion)
{
    /* Both requiredVersion and glXVersion[1] contains the minor GLX version */
    if(requiredVersion <= WineGLInfo.glxVersion[1])
        return TRUE;

    return FALSE;
}

static BOOL glxRequireExtension(const char *requiredExtension)
{
3523
    if (strstr(WineGLInfo.glxExtensions, requiredExtension) == NULL) {
3524 3525 3526 3527 3528 3529
        return FALSE;
    }

    return TRUE;
}

3530 3531
static void register_extension_string(const char *ext)
{
3532 3533
    if (WineGLInfo.wglExtensions[0])
        strcat(WineGLInfo.wglExtensions, " ");
3534 3535 3536 3537 3538
    strcat(WineGLInfo.wglExtensions, ext);

    TRACE("'%s'\n", ext);
}

3539
static BOOL register_extension(const WineGLExtension * ext)
3540 3541 3542
{
    int i;

3543 3544
    assert( WineGLExtensionListSize < MAX_EXTENSIONS );
    WineGLExtensionList[WineGLExtensionListSize++] = ext;
3545

3546
    register_extension_string(ext->extName);
3547

3548
    for (i = 0; ext->extEntryPoints[i].funcName; ++i)
3549 3550 3551 3552 3553
        TRACE("    - '%s'\n", ext->extEntryPoints[i].funcName);

    return TRUE;
}

3554 3555 3556 3557 3558
static const WineGLExtension WGL_internal_functions =
{
  "",
  {
    { "wglGetIntegerv", X11DRV_wglGetIntegerv },
3559 3560
    { "wglFinish", X11DRV_wglFinish },
    { "wglFlush", X11DRV_wglFlush },
3561 3562 3563 3564
  }
};


3565 3566 3567 3568 3569 3570 3571 3572
static const WineGLExtension WGL_ARB_create_context =
{
  "WGL_ARB_create_context",
  {
    { "wglCreateContextAttribsARB", X11DRV_wglCreateContextAttribsARB },
  }
};

3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643
static const WineGLExtension WGL_ARB_extensions_string =
{
  "WGL_ARB_extensions_string",
  {
    { "wglGetExtensionsStringARB", X11DRV_wglGetExtensionsStringARB },
  }
};

static const WineGLExtension WGL_ARB_make_current_read =
{
  "WGL_ARB_make_current_read",
  {
    { "wglGetCurrentReadDCARB", X11DRV_wglGetCurrentReadDCARB },
    { "wglMakeContextCurrentARB", X11DRV_wglMakeContextCurrentARB },
  }
};

static const WineGLExtension WGL_ARB_multisample =
{
  "WGL_ARB_multisample",
};

static const WineGLExtension WGL_ARB_pbuffer =
{
  "WGL_ARB_pbuffer",
  {
    { "wglCreatePbufferARB", X11DRV_wglCreatePbufferARB },
    { "wglDestroyPbufferARB", X11DRV_wglDestroyPbufferARB },
    { "wglGetPbufferDCARB", X11DRV_wglGetPbufferDCARB },
    { "wglQueryPbufferARB", X11DRV_wglQueryPbufferARB },
    { "wglReleasePbufferDCARB", X11DRV_wglReleasePbufferDCARB },
    { "wglSetPbufferAttribARB", X11DRV_wglSetPbufferAttribARB },
  }
};

static const WineGLExtension WGL_ARB_pixel_format =
{
  "WGL_ARB_pixel_format",
  {
    { "wglChoosePixelFormatARB", X11DRV_wglChoosePixelFormatARB },
    { "wglGetPixelFormatAttribfvARB", X11DRV_wglGetPixelFormatAttribfvARB },
    { "wglGetPixelFormatAttribivARB", X11DRV_wglGetPixelFormatAttribivARB },
  }
};

static const WineGLExtension WGL_ARB_render_texture =
{
  "WGL_ARB_render_texture",
  {
    { "wglBindTexImageARB", X11DRV_wglBindTexImageARB },
    { "wglReleaseTexImageARB", X11DRV_wglReleaseTexImageARB },
  }
};

static const WineGLExtension WGL_EXT_extensions_string =
{
  "WGL_EXT_extensions_string",
  {
    { "wglGetExtensionsStringEXT", X11DRV_wglGetExtensionsStringEXT },
  }
};

static const WineGLExtension WGL_EXT_swap_control =
{
  "WGL_EXT_swap_control",
  {
    { "wglSwapIntervalEXT", X11DRV_wglSwapIntervalEXT },
    { "wglGetSwapIntervalEXT", X11DRV_wglGetSwapIntervalEXT },
  }
};

3644 3645 3646 3647 3648 3649 3650 3651
static const WineGLExtension WGL_NV_vertex_array_range =
{
  "WGL_NV_vertex_array_range",
  {
    { "wglAllocateMemoryNV", X11DRV_wglAllocateMemoryNV },
    { "wglFreeMemoryNV", X11DRV_wglFreeMemoryNV },
  }
};
3652

3653 3654 3655 3656 3657 3658 3659 3660
static const WineGLExtension WGL_WINE_pixel_format_passthrough =
{
  "WGL_WINE_pixel_format_passthrough",
  {
    { "wglSetPixelFormatWINE", X11DRV_wglSetPixelFormatWINE },
  }
};

3661 3662 3663
/**
 * X11DRV_WineGL_LoadExtensions
 */
3664
static void X11DRV_WineGL_LoadExtensions(void)
3665 3666
{
    WineGLInfo.wglExtensions[0] = 0;
3667

3668 3669 3670
    /* Load Wine internal functions */
    register_extension(&WGL_internal_functions);

3671
    /* ARB Extensions */
3672

3673 3674 3675
    if(glxRequireExtension("GLX_ARB_create_context"))
    {
        register_extension(&WGL_ARB_create_context);
3676 3677 3678

        if(glxRequireExtension("GLX_ARB_create_context_profile"))
            register_extension_string("WGL_ARB_create_context_profile");
3679 3680
    }

3681 3682 3683 3684 3685 3686
    if(glxRequireExtension("GLX_ARB_fbconfig_float"))
    {
        register_extension_string("WGL_ARB_pixel_format_float");
        register_extension_string("WGL_ATI_pixel_format_float");
    }

3687 3688 3689 3690 3691 3692 3693 3694
    register_extension(&WGL_ARB_extensions_string);

    if (glxRequireVersion(3))
        register_extension(&WGL_ARB_make_current_read);

    if (glxRequireExtension("GLX_ARB_multisample"))
        register_extension(&WGL_ARB_multisample);

3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706
    /* In general pbuffer functionality requires support in the X-server. The functionality is
     * available either when the GLX_SGIX_pbuffer is present or when the GLX server version is 1.3.
     * All display drivers except for Nvidia's use the GLX module from Xfree86/Xorg which only
     * supports GLX 1.2. The endresult is that only Nvidia's drivers support pbuffers.
     *
     * The only other drive which has pbuffer support is Ati's FGLRX driver. They provide clientside GLX 1.3 support
     * without support in the X-server (which other Mesa based drivers require).
     *
     * Support pbuffers when the GLX version is 1.3 and GLX_SGIX_pbuffer is available. Further pbuffers can
     * also be supported when GLX_ATI_render_texture is available. This extension depends on pbuffers, so when it
     * is available pbuffers must be available too. */
    if ( (glxRequireVersion(3) && glxRequireExtension("GLX_SGIX_pbuffer")) || glxRequireExtension("GLX_ATI_render_texture"))
3707 3708 3709 3710
        register_extension(&WGL_ARB_pbuffer);

    register_extension(&WGL_ARB_pixel_format);

3711
    /* Support WGL_ARB_render_texture when there's support or pbuffer based emulation */
3712
    if (glxRequireExtension("GLX_ATI_render_texture") ||
3713 3714
        glxRequireExtension("GLX_ARB_render_texture") ||
        (glxRequireVersion(3) && glxRequireExtension("GLX_SGIX_pbuffer") && use_render_texture_emulation))
3715
    {
3716
        register_extension(&WGL_ARB_render_texture);
3717

3718 3719 3720 3721 3722 3723 3724 3725 3726
        /* The WGL version of GLX_NV_float_buffer requires render_texture */
        if(glxRequireExtension("GLX_NV_float_buffer"))
            register_extension_string("WGL_NV_float_buffer");

        /* Again there's no GLX equivalent for this extension, so depend on the required GL extension */
        if(strstr(WineGLInfo.glExtensions, "GL_NV_texture_rectangle") != NULL)
            register_extension_string("WGL_NV_texture_rectangle");
    }

3727
    /* EXT Extensions */
3728 3729 3730

    register_extension(&WGL_EXT_extensions_string);

3731 3732 3733
    /* Load this extension even when it isn't backed by a GLX extension because it is has been around for ages.
     * Games like Call of Duty and K.O.T.O.R. rely on it. Further our emulation is good enough. */
    register_extension(&WGL_EXT_swap_control);
3734

3735 3736 3737
    if(glxRequireExtension("GLX_EXT_framebuffer_sRGB"))
        register_extension_string("WGL_EXT_framebuffer_sRGB");

3738 3739 3740
    if(glxRequireExtension("GLX_EXT_fbconfig_packed_float"))
        register_extension_string("WGL_EXT_pixel_format_packed_float");

3741 3742 3743
    /* The OpenGL extension GL_NV_vertex_array_range adds wgl/glX functions which aren't exported as 'real' wgl/glX extensions. */
    if(strstr(WineGLInfo.glExtensions, "GL_NV_vertex_array_range") != NULL)
        register_extension(&WGL_NV_vertex_array_range);
3744 3745 3746 3747 3748 3749 3750

    /* WINE-specific WGL Extensions */

    /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
     * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
     */
    register_extension(&WGL_WINE_pixel_format_passthrough);
3751 3752 3753
}


3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764
Drawable get_glxdrawable(X11DRV_PDEVICE *physDev)
{
    Drawable ret;

    if(physDev->bitmap)
    {
        if (physDev->bitmap->hbitmap == BITMAP_stock_phys_bitmap.hbitmap)
            ret = physDev->drawable; /* PBuffer */
        else
            ret = physDev->bitmap->glxpixmap;
    }
3765 3766
    else if(physDev->gl_drawable)
        ret = physDev->gl_drawable;
3767 3768 3769 3770 3771
    else
        ret = physDev->drawable;
    return ret;
}

3772
BOOL destroy_glxpixmap(Display *display, XID glxpixmap)
3773 3774
{
    wine_tsx11_lock(); 
3775
    pglXDestroyGLXPixmap(display, glxpixmap);
3776 3777 3778 3779
    wine_tsx11_unlock(); 
    return TRUE;
}

3780 3781 3782 3783 3784
/**
 * X11DRV_SwapBuffers
 *
 * Swap the buffers of this DC
 */
3785
BOOL CDECL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev)
3786 3787
{
  GLXDrawable drawable;
3788 3789
  Wine_GLContext *ctx = NtCurrentTeb()->glContext;

3790 3791
  if (!has_opengl()) return FALSE;

3792
  TRACE("(%p)\n", physDev);
Lionel Ulmer's avatar
Lionel Ulmer committed
3793

3794
  drawable = get_glxdrawable(physDev);
3795

3796
  wine_tsx11_lock();
3797
  sync_context(ctx);
3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814
  if(physDev->pixmap) {
      if(pglXCopySubBufferMESA) {
          int w = physDev->dc_rect.right - physDev->dc_rect.left;
          int h = physDev->dc_rect.bottom - physDev->dc_rect.top;

          /* (glX)SwapBuffers has an implicit glFlush effect, however
           * GLX_MESA_copy_sub_buffer doesn't. Make sure GL is flushed before
           * copying */
          pglFlush();
          if(w > 0 && h > 0)
              pglXCopySubBufferMESA(gdi_display, drawable, 0, 0, w, h);
      }
      else
          pglXSwapBuffers(gdi_display, drawable);
  }
  else
      pglXSwapBuffers(gdi_display, drawable);
3815 3816

  flush_gl_drawable(physDev);
3817
  wine_tsx11_unlock();
3818

3819 3820 3821
  /* FPS support */
  if (TRACE_ON(fps))
  {
3822 3823
      static long prev_time, start_time;
      static unsigned long frames, frames_total;
3824 3825 3826

      DWORD time = GetTickCount();
      frames++;
3827
      frames_total++;
3828 3829
      /* every 1.5 seconds */
      if (time - prev_time > 1500) {
3830 3831
          TRACE_(fps)("@ approx %.2ffps, total %.2ffps\n",
                      1000.0*frames/(time - prev_time), 1000.0*frames_total/(time - start_time));
3832 3833
          prev_time = time;
          frames = 0;
3834
          if(start_time == 0) start_time = time;
3835 3836 3837
      }
  }

Lionel Ulmer's avatar
Lionel Ulmer committed
3838 3839 3840
  return TRUE;
}

3841 3842 3843
XVisualInfo *visual_from_fbconfig_id( XID fbconfig_id )
{
    WineGLPixelFormat *fmt;
3844
    XVisualInfo *ret;
3845

3846
    fmt = ConvertPixelFormatGLXtoWGL(gdi_display, fbconfig_id, 0 /* no flags */);
3847 3848
    if(fmt == NULL)
        return NULL;
3849 3850 3851 3852 3853

    wine_tsx11_lock();
    ret = pglXGetVisualFromFBConfig(gdi_display, fmt->fbconfig);
    wine_tsx11_unlock();
    return ret;
3854 3855
}

3856
#else  /* no OpenGL includes */
Lionel Ulmer's avatar
Lionel Ulmer committed
3857

3858 3859 3860 3861
void X11DRV_OpenGL_Cleanup(void)
{
}

3862 3863 3864 3865 3866 3867
static inline void opengl_error(void)
{
    static int warned;
    if (!warned++) ERR("No OpenGL support compiled in.\n");
}

3868 3869 3870 3871 3872
int pixelformat_from_fbconfig_id(XID fbconfig_id)
{
    return 0;
}

3873 3874 3875 3876
void mark_drawable_dirty(Drawable old, Drawable new)
{
}

3877 3878 3879 3880
void flush_gl_drawable(X11DRV_PDEVICE *physDev)
{
}

3881 3882 3883 3884 3885
Drawable create_glxpixmap(Display *display, XVisualInfo *vis, Pixmap parent)
{
    return 0;
}

3886 3887 3888
/***********************************************************************
 *		ChoosePixelFormat (X11DRV.@)
 */
3889 3890
int CDECL X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev,
                                     const PIXELFORMATDESCRIPTOR *ppfd) {
3891
  opengl_error();
Lionel Ulmer's avatar
Lionel Ulmer committed
3892 3893 3894
  return 0;
}

3895 3896 3897
/***********************************************************************
 *		DescribePixelFormat (X11DRV.@)
 */
3898 3899 3900 3901
int CDECL X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev,
                                     int iPixelFormat,
                                     UINT nBytes,
                                     PIXELFORMATDESCRIPTOR *ppfd) {
3902
  opengl_error();
Lionel Ulmer's avatar
Lionel Ulmer committed
3903 3904 3905
  return 0;
}

3906 3907 3908
/***********************************************************************
 *		GetPixelFormat (X11DRV.@)
 */
3909
int CDECL X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) {
3910
  opengl_error();
Lionel Ulmer's avatar
Lionel Ulmer committed
3911 3912 3913
  return 0;
}

3914 3915 3916
/***********************************************************************
 *		SetPixelFormat (X11DRV.@)
 */
3917 3918 3919
BOOL CDECL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev,
                                   int iPixelFormat,
                                   const PIXELFORMATDESCRIPTOR *ppfd) {
3920
  opengl_error();
Lionel Ulmer's avatar
Lionel Ulmer committed
3921 3922 3923
  return FALSE;
}

3924 3925 3926
/***********************************************************************
 *		SwapBuffers (X11DRV.@)
 */
3927
BOOL CDECL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev) {
3928
  opengl_error();
Lionel Ulmer's avatar
Lionel Ulmer committed
3929 3930 3931
  return FALSE;
}

3932 3933 3934 3935 3936
/**
 * X11DRV_wglCopyContext
 *
 * For OpenGL32 wglCopyContext.
 */
3937
BOOL CDECL X11DRV_wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask) {
3938
    opengl_error();
3939 3940 3941
    return FALSE;
}

3942 3943 3944 3945 3946
/**
 * X11DRV_wglCreateContext
 *
 * For OpenGL32 wglCreateContext.
 */
3947
HGLRC CDECL X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) {
3948
    opengl_error();
3949 3950 3951 3952 3953 3954 3955 3956
    return NULL;
}

/**
 * X11DRV_wglCreateContextAttribsARB
 *
 * WGL_ARB_create_context: wglCreateContextAttribsARB
 */
3957
HGLRC CDECL X11DRV_wglCreateContextAttribsARB(X11DRV_PDEVICE *physDev, HGLRC hShareContext, const int* attribList)
3958 3959
{
    opengl_error();
3960 3961 3962
    return NULL;
}

3963 3964 3965 3966 3967
/**
 * X11DRV_wglDeleteContext
 *
 * For OpenGL32 wglDeleteContext.
 */
3968
BOOL CDECL X11DRV_wglDeleteContext(HGLRC hglrc) {
3969
    opengl_error();
3970 3971 3972
    return FALSE;
}

3973 3974 3975 3976 3977
/**
 * X11DRV_wglGetProcAddress
 *
 * For OpenGL32 wglGetProcAddress.
 */
3978
PROC CDECL X11DRV_wglGetProcAddress(LPCSTR lpszProc) {
3979
    opengl_error();
3980 3981 3982
    return NULL;
}

3983
HDC CDECL X11DRV_wglGetPbufferDCARB(X11DRV_PDEVICE *hDevice, void *hPbuffer)
3984
{
3985
    opengl_error();
3986 3987 3988
    return NULL;
}

3989
BOOL CDECL X11DRV_wglMakeContextCurrentARB(X11DRV_PDEVICE* hDrawDev, X11DRV_PDEVICE* hReadDev, HGLRC hglrc) {
3990
    opengl_error();
3991 3992 3993
    return FALSE;
}

3994 3995 3996 3997 3998
/**
 * X11DRV_wglMakeCurrent
 *
 * For OpenGL32 wglMakeCurrent.
 */
3999
BOOL CDECL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) {
4000
    opengl_error();
4001 4002 4003
    return FALSE;
}

4004 4005 4006
/**
 * X11DRV_wglShareLists
 *
4007
 * For OpenGL32 wglShareLists.
4008
 */
4009
BOOL CDECL X11DRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) {
4010
    opengl_error();
4011 4012 4013
    return FALSE;
}

4014 4015 4016 4017 4018
/**
 * X11DRV_wglUseFontBitmapsA
 *
 * For OpenGL32 wglUseFontBitmapsA.
 */
4019
BOOL CDECL X11DRV_wglUseFontBitmapsA(X11DRV_PDEVICE *physDev, DWORD first, DWORD count, DWORD listBase)
4020
{
4021
    opengl_error();
4022 4023 4024
    return FALSE;
}

4025 4026 4027 4028 4029
/**
 * X11DRV_wglUseFontBitmapsW
 *
 * For OpenGL32 wglUseFontBitmapsW.
 */
4030
BOOL CDECL X11DRV_wglUseFontBitmapsW(X11DRV_PDEVICE *physDev, DWORD first, DWORD count, DWORD listBase)
4031
{
4032
    opengl_error();
4033 4034 4035
    return FALSE;
}

4036 4037 4038 4039 4040 4041
/**
 * X11DRV_wglSetPixelFormatWINE
 *
 * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
 * This is a WINE-specific wglSetPixelFormat which can set the pixel format multiple times.
 */
4042
BOOL CDECL X11DRV_wglSetPixelFormatWINE(X11DRV_PDEVICE *physDev, int iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd)
4043
{
4044
    opengl_error();
4045 4046 4047
    return FALSE;
}

4048
Drawable get_glxdrawable(X11DRV_PDEVICE *physDev)
4049
{
4050
    return 0;
4051 4052
}

4053
BOOL destroy_glxpixmap(Display *display, XID glxpixmap)
4054 4055 4056 4057
{
    return FALSE;
}

4058 4059 4060 4061 4062
XVisualInfo *visual_from_fbconfig_id( XID fbconfig_id )
{
    return NULL;
}

4063
#endif /* defined(SONAME_LIBGL) */