push 4d5485f9b89f417d46b39b93e8d940437007f325
[wine/hacks.git] / dlls / winex11.drv / opengl.c
blob516de5fa1b98122a5c35fc28dca2143d98c96fc7
1 /*
2 * X11DRV OpenGL functions
4 * Copyright 2000 Lionel Ulmer
5 * Copyright 2005 Alex Woods
6 * Copyright 2005 Raphael Junqueira
7 * Copyright 2006 Roderick Colenbrander
8 * Copyright 2006 Tomas Carnecky
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * 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
25 #include "config.h"
26 #include "wine/port.h"
28 #include <assert.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #include "x11drv.h"
33 #include "winternl.h"
34 #include "wine/library.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
38 WINE_DECLARE_DEBUG_CHANNEL(opengl);
40 #ifdef SONAME_LIBGL
42 #undef APIENTRY
43 #undef CALLBACK
44 #undef WINAPI
46 #ifdef HAVE_GL_GL_H
47 # include <GL/gl.h>
48 #endif
49 #ifdef HAVE_GL_GLX_H
50 # include <GL/glx.h>
51 #endif
52 #ifdef HAVE_GL_GLEXT_H
53 # include <GL/glext.h>
54 #endif
56 #include "wine/wgl.h"
58 #undef APIENTRY
59 #undef CALLBACK
60 #undef WINAPI
62 /* Redefines the constants */
63 #define CALLBACK __stdcall
64 #define WINAPI __stdcall
65 #define APIENTRY WINAPI
68 WINE_DECLARE_DEBUG_CHANNEL(fps);
70 typedef struct wine_glextension {
71 const char *extName;
72 struct {
73 const char *funcName;
74 void *funcAddress;
75 } extEntryPoints[8];
76 } WineGLExtension;
78 struct WineGLInfo {
79 const char *glVersion;
80 const char *glExtensions;
82 int glxVersion[2];
84 const char *glxServerVersion;
85 const char *glxServerVendor;
86 const char *glxServerExtensions;
88 const char *glxClientVersion;
89 const char *glxClientVendor;
90 const char *glxClientExtensions;
92 const char *glxExtensions;
94 BOOL glxDirect;
95 char wglExtensions[4096];
98 typedef struct wine_glpixelformat {
99 int iPixelFormat;
100 GLXFBConfig fbconfig;
101 int fmt_id;
102 int render_type;
103 BOOL offscreenOnly;
104 } WineGLPixelFormat;
106 typedef struct wine_glcontext {
107 HDC hdc;
108 XVisualInfo *vis;
109 WineGLPixelFormat *fmt;
110 GLXContext ctx;
111 BOOL do_escape;
112 X11DRV_PDEVICE *physDev;
113 RECT viewport;
114 RECT scissor;
115 BOOL scissor_enabled;
116 struct wine_glcontext *next;
117 struct wine_glcontext *prev;
118 } Wine_GLContext;
120 typedef struct wine_glpbuffer {
121 Drawable drawable;
122 Display* display;
123 WineGLPixelFormat* fmt;
124 int width;
125 int height;
126 int* attribList;
127 HDC hdc;
129 int use_render_texture; /* This is also the internal texture format */
130 int texture_bind_target;
131 int texture_bpp;
132 GLint texture_format;
133 GLuint texture_target;
134 GLenum texture_type;
135 GLuint texture;
136 int texture_level;
137 } Wine_GLPBuffer;
139 static Wine_GLContext *context_list;
140 static struct WineGLInfo WineGLInfo = { 0 };
141 static int use_render_texture_emulation = 1;
142 static int use_render_texture_ati = 1;
143 static int swap_interval = 1;
145 #define MAX_EXTENSIONS 16
146 static const WineGLExtension *WineGLExtensionList[MAX_EXTENSIONS];
147 static int WineGLExtensionListSize;
149 static WineGLPixelFormat *WineGLPixelFormatList;
150 static int WineGLPixelFormatListSize = 0;
152 static void X11DRV_WineGL_LoadExtensions(void);
153 static BOOL glxRequireVersion(int requiredVersion);
154 static BOOL glxRequireExtension(const char *requiredExtension);
156 static void dump_PIXELFORMATDESCRIPTOR(const PIXELFORMATDESCRIPTOR *ppfd) {
157 TRACE(" - size / version : %d / %d\n", ppfd->nSize, ppfd->nVersion);
158 TRACE(" - dwFlags : ");
159 #define TEST_AND_DUMP(t,tv) if ((t) & (tv)) TRACE(#tv " ")
160 TEST_AND_DUMP(ppfd->dwFlags, PFD_DEPTH_DONTCARE);
161 TEST_AND_DUMP(ppfd->dwFlags, PFD_DOUBLEBUFFER);
162 TEST_AND_DUMP(ppfd->dwFlags, PFD_DOUBLEBUFFER_DONTCARE);
163 TEST_AND_DUMP(ppfd->dwFlags, PFD_DRAW_TO_WINDOW);
164 TEST_AND_DUMP(ppfd->dwFlags, PFD_DRAW_TO_BITMAP);
165 TEST_AND_DUMP(ppfd->dwFlags, PFD_GENERIC_ACCELERATED);
166 TEST_AND_DUMP(ppfd->dwFlags, PFD_GENERIC_FORMAT);
167 TEST_AND_DUMP(ppfd->dwFlags, PFD_NEED_PALETTE);
168 TEST_AND_DUMP(ppfd->dwFlags, PFD_NEED_SYSTEM_PALETTE);
169 TEST_AND_DUMP(ppfd->dwFlags, PFD_STEREO);
170 TEST_AND_DUMP(ppfd->dwFlags, PFD_STEREO_DONTCARE);
171 TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_GDI);
172 TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_OPENGL);
173 TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_COPY);
174 TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_EXCHANGE);
175 TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_LAYER_BUFFERS);
176 /* PFD_SUPPORT_COMPOSITION is new in Vista, it is similar to composition
177 * under X e.g. COMPOSITE + GLX_EXT_TEXTURE_FROM_PIXMAP. */
178 TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_COMPOSITION);
179 #undef TEST_AND_DUMP
180 TRACE("\n");
182 TRACE(" - iPixelType : ");
183 switch (ppfd->iPixelType) {
184 case PFD_TYPE_RGBA: TRACE("PFD_TYPE_RGBA"); break;
185 case PFD_TYPE_COLORINDEX: TRACE("PFD_TYPE_COLORINDEX"); break;
187 TRACE("\n");
189 TRACE(" - Color : %d\n", ppfd->cColorBits);
190 TRACE(" - Red : %d\n", ppfd->cRedBits);
191 TRACE(" - Green : %d\n", ppfd->cGreenBits);
192 TRACE(" - Blue : %d\n", ppfd->cBlueBits);
193 TRACE(" - Alpha : %d\n", ppfd->cAlphaBits);
194 TRACE(" - Accum : %d\n", ppfd->cAccumBits);
195 TRACE(" - Depth : %d\n", ppfd->cDepthBits);
196 TRACE(" - Stencil : %d\n", ppfd->cStencilBits);
197 TRACE(" - Aux : %d\n", ppfd->cAuxBuffers);
199 TRACE(" - iLayerType : ");
200 switch (ppfd->iLayerType) {
201 case PFD_MAIN_PLANE: TRACE("PFD_MAIN_PLANE"); break;
202 case PFD_OVERLAY_PLANE: TRACE("PFD_OVERLAY_PLANE"); break;
203 case (BYTE)PFD_UNDERLAY_PLANE: TRACE("PFD_UNDERLAY_PLANE"); break;
205 TRACE("\n");
208 #define PUSH1(attribs,att) do { attribs[nAttribs++] = (att); } while (0)
209 #define PUSH2(attribs,att,value) do { attribs[nAttribs++] = (att); attribs[nAttribs++] = (value); } while(0)
211 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
212 /* GLX 1.0 */
213 MAKE_FUNCPTR(glXChooseVisual)
214 MAKE_FUNCPTR(glXCreateContext)
215 MAKE_FUNCPTR(glXCreateGLXPixmap)
216 MAKE_FUNCPTR(glXGetCurrentContext)
217 MAKE_FUNCPTR(glXGetCurrentDrawable)
218 MAKE_FUNCPTR(glXDestroyContext)
219 MAKE_FUNCPTR(glXDestroyGLXPixmap)
220 MAKE_FUNCPTR(glXGetConfig)
221 MAKE_FUNCPTR(glXIsDirect)
222 MAKE_FUNCPTR(glXMakeCurrent)
223 MAKE_FUNCPTR(glXSwapBuffers)
224 MAKE_FUNCPTR(glXQueryExtension)
225 MAKE_FUNCPTR(glXQueryVersion)
226 MAKE_FUNCPTR(glXUseXFont)
228 /* GLX 1.1 */
229 MAKE_FUNCPTR(glXGetClientString)
230 MAKE_FUNCPTR(glXQueryExtensionsString)
231 MAKE_FUNCPTR(glXQueryServerString)
233 /* GLX 1.3 */
234 MAKE_FUNCPTR(glXGetFBConfigs)
235 MAKE_FUNCPTR(glXChooseFBConfig)
236 MAKE_FUNCPTR(glXCreatePbuffer)
237 MAKE_FUNCPTR(glXCreateNewContext)
238 MAKE_FUNCPTR(glXDestroyPbuffer)
239 MAKE_FUNCPTR(glXGetFBConfigAttrib)
240 MAKE_FUNCPTR(glXGetVisualFromFBConfig)
241 MAKE_FUNCPTR(glXMakeContextCurrent)
242 MAKE_FUNCPTR(glXQueryDrawable)
243 MAKE_FUNCPTR(glXGetCurrentReadDrawable)
245 /* GLX Extensions */
246 static void* (*pglXGetProcAddressARB)(const GLubyte *);
247 static int (*pglXSwapIntervalSGI)(int);
249 /* ATI GLX Extensions */
250 static BOOL (*pglXBindTexImageATI)(Display *dpy, GLXPbuffer pbuffer, int buffer);
251 static BOOL (*pglXReleaseTexImageATI)(Display *dpy, GLXPbuffer pbuffer, int buffer);
252 static BOOL (*pglXDrawableAttribATI)(Display *dpy, GLXDrawable draw, const int *attribList);
254 /* NV GLX Extension */
255 static void* (*pglXAllocateMemoryNV)(GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
256 static void (*pglXFreeMemoryNV)(GLvoid *pointer);
258 /* Standard OpenGL */
259 MAKE_FUNCPTR(glBindTexture)
260 MAKE_FUNCPTR(glBitmap)
261 MAKE_FUNCPTR(glCopyTexSubImage1D)
262 MAKE_FUNCPTR(glCopyTexImage2D)
263 MAKE_FUNCPTR(glCopyTexSubImage2D)
264 MAKE_FUNCPTR(glDisable)
265 MAKE_FUNCPTR(glDrawBuffer)
266 MAKE_FUNCPTR(glEnable)
267 MAKE_FUNCPTR(glEndList)
268 MAKE_FUNCPTR(glGetError)
269 MAKE_FUNCPTR(glGetIntegerv)
270 MAKE_FUNCPTR(glGetString)
271 MAKE_FUNCPTR(glIsEnabled)
272 MAKE_FUNCPTR(glNewList)
273 MAKE_FUNCPTR(glPixelStorei)
274 MAKE_FUNCPTR(glReadPixels)
275 MAKE_FUNCPTR(glScissor)
276 MAKE_FUNCPTR(glTexImage2D)
277 MAKE_FUNCPTR(glViewport)
278 #undef MAKE_FUNCPTR
280 static BOOL X11DRV_WineGL_InitOpenglInfo(void)
282 static BOOL infoInitialized = FALSE;
284 int screen = DefaultScreen(gdi_display);
285 Window win = RootWindow(gdi_display, screen);
286 Visual *visual;
287 XVisualInfo template;
288 XVisualInfo *vis;
289 int num;
290 GLXContext ctx = NULL;
292 if (infoInitialized)
293 return TRUE;
294 infoInitialized = TRUE;
296 wine_tsx11_lock();
298 visual = DefaultVisual(gdi_display, screen);
299 template.visualid = XVisualIDFromVisual(visual);
300 vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
301 if (vis) {
302 WORD old_fs = wine_get_fs();
303 /* Create a GLX Context. Without one we can't query GL information */
304 ctx = pglXCreateContext(gdi_display, vis, None, GL_TRUE);
305 if (wine_get_fs() != old_fs)
307 wine_set_fs( old_fs );
308 wine_tsx11_unlock();
309 ERR( "%%fs register corrupted, probably broken ATI driver, disabling OpenGL.\n" );
310 ERR( "You need to set the \"UseFastTls\" option to \"2\" in your X config file.\n" );
311 return FALSE;
315 if (ctx) {
316 pglXMakeCurrent(gdi_display, win, ctx);
317 } else {
318 ERR(" couldn't initialize OpenGL, expect problems\n");
319 wine_tsx11_unlock();
320 return FALSE;
323 WineGLInfo.glVersion = (const char *) pglGetString(GL_VERSION);
324 WineGLInfo.glExtensions = strdup((const char *) pglGetString(GL_EXTENSIONS));
326 /* Get the common GLX version supported by GLX client and server ( major/minor) */
327 pglXQueryVersion(gdi_display, &WineGLInfo.glxVersion[0], &WineGLInfo.glxVersion[1]);
329 WineGLInfo.glxServerVersion = pglXQueryServerString(gdi_display, screen, GLX_VERSION);
330 WineGLInfo.glxServerVendor = pglXQueryServerString(gdi_display, screen, GLX_VENDOR);
331 WineGLInfo.glxServerExtensions = pglXQueryServerString(gdi_display, screen, GLX_EXTENSIONS);
333 WineGLInfo.glxClientVersion = pglXGetClientString(gdi_display, GLX_VERSION);
334 WineGLInfo.glxClientVendor = pglXGetClientString(gdi_display, GLX_VENDOR);
335 WineGLInfo.glxClientExtensions = pglXGetClientString(gdi_display, GLX_EXTENSIONS);
337 WineGLInfo.glxExtensions = pglXQueryExtensionsString(gdi_display, screen);
338 WineGLInfo.glxDirect = pglXIsDirect(gdi_display, ctx);
340 TRACE("GL version : %s.\n", WineGLInfo.glVersion);
341 TRACE("GL renderer : %s.\n", pglGetString(GL_RENDERER));
342 TRACE("GLX version : %d.%d.\n", WineGLInfo.glxVersion[0], WineGLInfo.glxVersion[1]);
343 TRACE("Server GLX version : %s.\n", WineGLInfo.glxServerVersion);
344 TRACE("Server GLX vendor: : %s.\n", WineGLInfo.glxServerVendor);
345 TRACE("Client GLX version : %s.\n", WineGLInfo.glxClientVersion);
346 TRACE("Client GLX vendor: : %s.\n", WineGLInfo.glxClientVendor);
347 TRACE("Direct rendering enabled: %s\n", WineGLInfo.glxDirect ? "True" : "False");
349 if(vis) XFree(vis);
350 if(ctx) {
351 pglXMakeCurrent(gdi_display, None, NULL);
352 pglXDestroyContext(gdi_display, ctx);
354 wine_tsx11_unlock();
355 return TRUE;
358 static BOOL has_opengl(void)
360 static int init_done;
361 static void *opengl_handle;
363 int error_base, event_base;
365 if (init_done) return (opengl_handle != NULL);
366 init_done = 1;
368 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient
369 and include all dependencies */
370 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
371 if (opengl_handle == NULL) return FALSE;
373 pglXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
374 if (pglXGetProcAddressARB == NULL) {
375 ERR("could not find glXGetProcAddressARB in libGL.\n");
376 return FALSE;
379 #define LOAD_FUNCPTR(f) if((p##f = (void*)pglXGetProcAddressARB((const unsigned char*)#f)) == NULL) goto sym_not_found;
380 /* GLX 1.0 */
381 LOAD_FUNCPTR(glXChooseVisual)
382 LOAD_FUNCPTR(glXCreateContext)
383 LOAD_FUNCPTR(glXCreateGLXPixmap)
384 LOAD_FUNCPTR(glXGetCurrentContext)
385 LOAD_FUNCPTR(glXGetCurrentDrawable)
386 LOAD_FUNCPTR(glXDestroyContext)
387 LOAD_FUNCPTR(glXDestroyGLXPixmap)
388 LOAD_FUNCPTR(glXGetConfig)
389 LOAD_FUNCPTR(glXIsDirect)
390 LOAD_FUNCPTR(glXMakeCurrent)
391 LOAD_FUNCPTR(glXSwapBuffers)
392 LOAD_FUNCPTR(glXQueryExtension)
393 LOAD_FUNCPTR(glXQueryVersion)
394 LOAD_FUNCPTR(glXUseXFont)
396 /* GLX 1.1 */
397 LOAD_FUNCPTR(glXGetClientString)
398 LOAD_FUNCPTR(glXQueryExtensionsString)
399 LOAD_FUNCPTR(glXQueryServerString)
401 /* GLX 1.3 */
402 LOAD_FUNCPTR(glXCreatePbuffer)
403 LOAD_FUNCPTR(glXCreateNewContext)
404 LOAD_FUNCPTR(glXDestroyPbuffer)
405 LOAD_FUNCPTR(glXMakeContextCurrent)
406 LOAD_FUNCPTR(glXGetCurrentReadDrawable)
407 LOAD_FUNCPTR(glXGetFBConfigs)
409 /* Standard OpenGL calls */
410 LOAD_FUNCPTR(glBindTexture)
411 LOAD_FUNCPTR(glBitmap)
412 LOAD_FUNCPTR(glCopyTexSubImage1D)
413 LOAD_FUNCPTR(glCopyTexImage2D)
414 LOAD_FUNCPTR(glCopyTexSubImage2D)
415 LOAD_FUNCPTR(glDisable)
416 LOAD_FUNCPTR(glDrawBuffer)
417 LOAD_FUNCPTR(glEnable)
418 LOAD_FUNCPTR(glEndList)
419 LOAD_FUNCPTR(glGetError)
420 LOAD_FUNCPTR(glGetIntegerv)
421 LOAD_FUNCPTR(glGetString)
422 LOAD_FUNCPTR(glIsEnabled)
423 LOAD_FUNCPTR(glNewList)
424 LOAD_FUNCPTR(glPixelStorei)
425 LOAD_FUNCPTR(glReadPixels)
426 LOAD_FUNCPTR(glScissor)
427 LOAD_FUNCPTR(glTexImage2D)
428 LOAD_FUNCPTR(glViewport)
429 #undef LOAD_FUNCPTR
431 /* It doesn't matter if these fail. They'll only be used if the driver reports
432 the associated extension is available (and if a driver reports the extension
433 is available but fails to provide the functions, it's quite broken) */
434 #define LOAD_FUNCPTR(f) p##f = (void*)pglXGetProcAddressARB((const unsigned char*)#f);
435 /* NV GLX Extension */
436 LOAD_FUNCPTR(glXAllocateMemoryNV)
437 LOAD_FUNCPTR(glXFreeMemoryNV)
438 #undef LOAD_FUNCPTR
440 if(!X11DRV_WineGL_InitOpenglInfo()) {
441 wine_dlclose(opengl_handle, NULL, 0);
442 opengl_handle = NULL;
443 return FALSE;
446 wine_tsx11_lock();
447 if (pglXQueryExtension(gdi_display, &error_base, &event_base) == True) {
448 TRACE("GLX is up and running error_base = %d\n", error_base);
449 } else {
450 wine_dlclose(opengl_handle, NULL, 0);
451 opengl_handle = NULL;
454 /* In case of GLX you have direct and indirect rendering. Most of the time direct rendering is used
455 * as in general only that is hardware accelerated. In some cases like in case of remote X indirect
456 * rendering is used.
458 * The main problem for our OpenGL code is that we need certain GLX calls but their presence
459 * depends on the reported GLX client / server version and on the client / server extension list.
460 * Those don't have to be the same.
462 * In general the server GLX information lists the capabilities in case of indirect rendering.
463 * When direct rendering is used, the OpenGL client library is responsible for which GLX calls are
464 * available and in that case the client GLX informat can be used.
465 * OpenGL programs should use the 'intersection' of both sets of information which is advertised
466 * in the GLX version/extension list. When a program does this it works for certain for both
467 * direct and indirect rendering.
469 * The problem we are having in this area is that ATI's Linux drivers are broken. For some reason
470 * they haven't added some very important GLX extensions like GLX_SGIX_fbconfig to their client
471 * extension list which causes this extension not to be listed. (Wine requires this extension).
472 * ATI advertises a GLX client version of 1.3 which implies that this fbconfig extension among
473 * pbuffers is around.
475 * In order to provide users of Ati's proprietary drivers with OpenGL support, we need to detect
476 * the ATI drivers and from then on use GLX client information for them.
479 if(glxRequireVersion(3)) {
480 pglXChooseFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfig");
481 pglXGetFBConfigAttrib = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttrib");
482 pglXGetVisualFromFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfig");
483 pglXQueryDrawable = (void*)pglXGetProcAddressARB((const GLubyte *) "glXQueryDrawable");
484 } else if(glxRequireExtension("GLX_SGIX_fbconfig")) {
485 pglXChooseFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfigSGIX");
486 pglXGetFBConfigAttrib = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttribSGIX");
487 pglXGetVisualFromFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfigSGIX");
489 /* The mesa libGL client library seems to forward glXQueryDrawable to the Xserver, so only
490 * enable this function when the Xserver understand GLX 1.3 or newer
492 pglXQueryDrawable = NULL;
493 } else if(strcmp("ATI", WineGLInfo.glxClientVendor) == 0) {
494 TRACE("Overriding ATI GLX capabilities!\n");
495 pglXChooseFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfig");
496 pglXGetFBConfigAttrib = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttrib");
497 pglXGetVisualFromFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfig");
498 pglXQueryDrawable = (void*)pglXGetProcAddressARB((const GLubyte *) "glXQueryDrawable");
500 /* Use client GLX information in case of the ATI drivers. We override the
501 * capabilities over here and not somewhere else as ATI might better their
502 * life in the future. In case they release proper drivers this block of
503 * code won't be called. */
504 WineGLInfo.glxExtensions = WineGLInfo.glxClientExtensions;
505 } else {
506 ERR(" glx_version is %s and GLX_SGIX_fbconfig extension is unsupported. Expect problems.\n", WineGLInfo.glxServerVersion);
509 if(glxRequireExtension("GLX_ATI_render_texture")) {
510 pglXBindTexImageATI = (void*)pglXGetProcAddressARB((const GLubyte *) "glXBindTexImageATI");
511 pglXReleaseTexImageATI = (void*)pglXGetProcAddressARB((const GLubyte *) "glXReleaseTexImageATI");
512 pglXDrawableAttribATI = (void*)pglXGetProcAddressARB((const GLubyte *) "glXDrawableAttribATI");
515 X11DRV_WineGL_LoadExtensions();
517 wine_tsx11_unlock();
518 return (opengl_handle != NULL);
520 sym_not_found:
521 wine_dlclose(opengl_handle, NULL, 0);
522 opengl_handle = NULL;
523 return FALSE;
526 static inline Wine_GLContext *alloc_context(void)
528 Wine_GLContext *ret;
530 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
532 ret->next = context_list;
533 if (context_list) context_list->prev = ret;
534 context_list = ret;
536 return ret;
539 static inline void free_context(Wine_GLContext *context)
541 if (context->next != NULL) context->next->prev = context->prev;
542 if (context->prev != NULL) context->prev->next = context->next;
543 else context_list = context->next;
545 HeapFree(GetProcessHeap(), 0, context);
548 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
550 Wine_GLContext *ret;
551 if (!ctx) return NULL;
552 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
553 return ret;
557 * get_hdc_from_Drawable (internal)
559 * For use by wglGetCurrentReadDCARB.
561 static inline HDC get_hdc_from_Drawable(GLXDrawable d)
563 Wine_GLContext *ret;
564 for (ret = context_list; ret; ret = ret->next) {
565 if (d == ret->physDev->drawable) {
566 return ret->hdc;
569 return NULL;
572 static inline BOOL is_valid_context( Wine_GLContext *ctx )
574 Wine_GLContext *ptr;
575 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
576 return (ptr != NULL);
579 static int describeContext(Wine_GLContext* ctx) {
580 int tmp;
581 int ctx_vis_id;
582 TRACE(" Context %p have (vis:%p):\n", ctx, ctx->vis);
583 pglXGetFBConfigAttrib(gdi_display, ctx->fmt->fbconfig, GLX_FBCONFIG_ID, &tmp);
584 TRACE(" - FBCONFIG_ID 0x%x\n", tmp);
585 pglXGetFBConfigAttrib(gdi_display, ctx->fmt->fbconfig, GLX_VISUAL_ID, &tmp);
586 TRACE(" - VISUAL_ID 0x%x\n", tmp);
587 ctx_vis_id = tmp;
588 return ctx_vis_id;
591 static int describeDrawable(Wine_GLContext* ctx, Drawable drawable) {
592 int tmp;
593 int nElements;
594 int attribList[3] = { GLX_FBCONFIG_ID, 0, None };
595 GLXFBConfig *fbCfgs;
597 if (pglXQueryDrawable == NULL) {
598 /** glXQueryDrawable not available so returns not supported */
599 return -1;
602 TRACE(" Drawable %p have :\n", (void*) drawable);
603 pglXQueryDrawable(gdi_display, drawable, GLX_WIDTH, (unsigned int*) &tmp);
604 TRACE(" - WIDTH as %d\n", tmp);
605 pglXQueryDrawable(gdi_display, drawable, GLX_HEIGHT, (unsigned int*) &tmp);
606 TRACE(" - HEIGHT as %d\n", tmp);
607 pglXQueryDrawable(gdi_display, drawable, GLX_FBCONFIG_ID, (unsigned int*) &tmp);
608 TRACE(" - FBCONFIG_ID as 0x%x\n", tmp);
610 attribList[1] = tmp;
611 fbCfgs = pglXChooseFBConfig(gdi_display, DefaultScreen(gdi_display), attribList, &nElements);
612 if (fbCfgs == NULL) {
613 return -1;
616 pglXGetFBConfigAttrib(gdi_display, fbCfgs[0], GLX_VISUAL_ID, &tmp);
617 TRACE(" - VISUAL_ID as 0x%x\n", tmp);
619 XFree(fbCfgs);
621 return tmp;
624 static int ConvertAttribWGLtoGLX(const int* iWGLAttr, int* oGLXAttr, Wine_GLPBuffer* pbuf) {
625 int nAttribs = 0;
626 unsigned cur = 0;
627 int pop;
628 int drawattrib = 0;
629 int nvfloatattrib = GLX_DONT_CARE;
630 int pixelattrib = 0;
632 /* The list of WGL attributes is allowed to be NULL. We don't return here for NULL
633 * because we need to do fixups for GLX_DRAWABLE_TYPE/GLX_RENDER_TYPE/GLX_FLOAT_COMPONENTS_NV. */
634 while (iWGLAttr && 0 != iWGLAttr[cur]) {
635 TRACE("pAttr[%d] = %x\n", cur, iWGLAttr[cur]);
637 switch (iWGLAttr[cur]) {
638 case WGL_COLOR_BITS_ARB:
639 pop = iWGLAttr[++cur];
640 PUSH2(oGLXAttr, GLX_BUFFER_SIZE, pop);
641 TRACE("pAttr[%d] = GLX_BUFFER_SIZE: %d\n", cur, pop);
642 break;
643 case WGL_BLUE_BITS_ARB:
644 pop = iWGLAttr[++cur];
645 PUSH2(oGLXAttr, GLX_BLUE_SIZE, pop);
646 TRACE("pAttr[%d] = GLX_BLUE_SIZE: %d\n", cur, pop);
647 break;
648 case WGL_RED_BITS_ARB:
649 pop = iWGLAttr[++cur];
650 PUSH2(oGLXAttr, GLX_RED_SIZE, pop);
651 TRACE("pAttr[%d] = GLX_RED_SIZE: %d\n", cur, pop);
652 break;
653 case WGL_GREEN_BITS_ARB:
654 pop = iWGLAttr[++cur];
655 PUSH2(oGLXAttr, GLX_GREEN_SIZE, pop);
656 TRACE("pAttr[%d] = GLX_GREEN_SIZE: %d\n", cur, pop);
657 break;
658 case WGL_ALPHA_BITS_ARB:
659 pop = iWGLAttr[++cur];
660 PUSH2(oGLXAttr, GLX_ALPHA_SIZE, pop);
661 TRACE("pAttr[%d] = GLX_ALPHA_SIZE: %d\n", cur, pop);
662 break;
663 case WGL_DEPTH_BITS_ARB:
664 pop = iWGLAttr[++cur];
665 PUSH2(oGLXAttr, GLX_DEPTH_SIZE, pop);
666 TRACE("pAttr[%d] = GLX_DEPTH_SIZE: %d\n", cur, pop);
667 break;
668 case WGL_STENCIL_BITS_ARB:
669 pop = iWGLAttr[++cur];
670 PUSH2(oGLXAttr, GLX_STENCIL_SIZE, pop);
671 TRACE("pAttr[%d] = GLX_STENCIL_SIZE: %d\n", cur, pop);
672 break;
673 case WGL_DOUBLE_BUFFER_ARB:
674 pop = iWGLAttr[++cur];
675 PUSH2(oGLXAttr, GLX_DOUBLEBUFFER, pop);
676 TRACE("pAttr[%d] = GLX_DOUBLEBUFFER: %d\n", cur, pop);
677 break;
679 case WGL_PIXEL_TYPE_ARB:
680 pop = iWGLAttr[++cur];
681 TRACE("pAttr[%d] = WGL_PIXEL_TYPE_ARB: %d\n", cur, pop);
682 switch (pop) {
683 case WGL_TYPE_COLORINDEX_ARB: pixelattrib = GLX_COLOR_INDEX_BIT; break ;
684 case WGL_TYPE_RGBA_ARB: pixelattrib = GLX_RGBA_BIT; break ;
685 /* 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 */
686 case WGL_TYPE_RGBA_FLOAT_ATI: pixelattrib = GLX_RGBA_FLOAT_BIT; break ;
687 default:
688 ERR("unexpected PixelType(%x)\n", pop);
689 pop = 0;
691 break;
693 case WGL_SUPPORT_GDI_ARB:
694 pop = iWGLAttr[++cur];
695 PUSH2(oGLXAttr, GLX_X_RENDERABLE, pop);
696 TRACE("pAttr[%d] = WGL_SUPPORT_GDI_ARB: %d\n", cur, pop);
697 break;
699 case WGL_DRAW_TO_BITMAP_ARB:
700 pop = iWGLAttr[++cur];
701 TRACE("pAttr[%d] = WGL_DRAW_TO_BITMAP_ARB: %d\n", cur, pop);
702 /* GLX_DRAWABLE_TYPE flags need to be OR'd together. See below. */
703 if (pop) {
704 drawattrib |= GLX_PIXMAP_BIT;
706 break;
708 case WGL_DRAW_TO_WINDOW_ARB:
709 pop = iWGLAttr[++cur];
710 TRACE("pAttr[%d] = WGL_DRAW_TO_WINDOW_ARB: %d\n", cur, pop);
711 /* GLX_DRAWABLE_TYPE flags need to be OR'd together. See below. */
712 if (pop) {
713 drawattrib |= GLX_WINDOW_BIT;
715 break;
717 case WGL_DRAW_TO_PBUFFER_ARB:
718 pop = iWGLAttr[++cur];
719 TRACE("pAttr[%d] = WGL_DRAW_TO_PBUFFER_ARB: %d\n", cur, pop);
720 /* GLX_DRAWABLE_TYPE flags need to be OR'd together. See below. */
721 if (pop) {
722 drawattrib |= GLX_PBUFFER_BIT;
724 break;
726 case WGL_ACCELERATION_ARB:
727 case WGL_SUPPORT_OPENGL_ARB:
728 pop = iWGLAttr[++cur];
729 /** nothing to do, if we are here, supposing support Accelerated OpenGL */
730 TRACE("pAttr[%d] = WGL_SUPPORT_OPENGL_ARB: %d\n", cur, pop);
731 break;
733 case WGL_PBUFFER_LARGEST_ARB:
734 pop = iWGLAttr[++cur];
735 PUSH2(oGLXAttr, GLX_LARGEST_PBUFFER, pop);
736 TRACE("pAttr[%d] = GLX_LARGEST_PBUFFER: %x\n", cur, pop);
737 break;
739 case WGL_SAMPLE_BUFFERS_ARB:
740 pop = iWGLAttr[++cur];
741 PUSH2(oGLXAttr, GLX_SAMPLE_BUFFERS_ARB, pop);
742 TRACE("pAttr[%d] = GLX_SAMPLE_BUFFERS_ARB: %x\n", cur, pop);
743 break;
745 case WGL_SAMPLES_ARB:
746 pop = iWGLAttr[++cur];
747 PUSH2(oGLXAttr, GLX_SAMPLES_ARB, pop);
748 TRACE("pAttr[%d] = GLX_SAMPLES_ARB: %x\n", cur, pop);
749 break;
751 case WGL_TEXTURE_FORMAT_ARB:
752 case WGL_TEXTURE_TARGET_ARB:
753 case WGL_MIPMAP_TEXTURE_ARB:
754 TRACE("WGL_render_texture Attributes: %x as %x\n", iWGLAttr[cur], iWGLAttr[cur + 1]);
755 pop = iWGLAttr[++cur];
756 if (NULL == pbuf) {
757 ERR("trying to use GLX_Pbuffer Attributes without Pbuffer (was %x)\n", iWGLAttr[cur]);
759 if (use_render_texture_ati) {
760 /** nothing to do here */
762 else if (!use_render_texture_emulation) {
763 if (WGL_NO_TEXTURE_ARB != pop) {
764 ERR("trying to use WGL_render_texture Attributes without support (was %x)\n", iWGLAttr[cur]);
765 return -1; /** error: don't support it */
766 } else {
767 PUSH2(oGLXAttr, GLX_X_RENDERABLE, pop);
768 drawattrib |= GLX_PBUFFER_BIT;
771 break ;
772 case WGL_FLOAT_COMPONENTS_NV:
773 nvfloatattrib = iWGLAttr[++cur];
774 TRACE("pAttr[%d] = WGL_FLOAT_COMPONENTS_NV: %x\n", cur, nvfloatattrib);
775 break ;
776 case WGL_BIND_TO_TEXTURE_RGB_ARB:
777 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
778 case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV:
779 case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV:
780 case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV:
781 case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV:
782 pop = iWGLAttr[++cur];
783 /** cannot be converted, see direct handling on
784 * - wglGetPixelFormatAttribivARB
785 * TODO: wglChoosePixelFormat
787 break ;
789 default:
790 FIXME("unsupported %x WGL Attribute\n", iWGLAttr[cur]);
791 break;
793 ++cur;
796 /* Apply the OR'd drawable type bitmask now EVEN when WGL_DRAW_TO* is unset.
797 * It is needed in all cases because GLX_DRAWABLE_TYPE default to GLX_WINDOW_BIT. */
798 PUSH2(oGLXAttr, GLX_DRAWABLE_TYPE, drawattrib);
799 TRACE("pAttr[?] = GLX_DRAWABLE_TYPE: %#x\n", drawattrib);
801 /* Set GLX_RENDER_TYPE all the time */
802 PUSH2(oGLXAttr, GLX_RENDER_TYPE, pixelattrib);
803 TRACE("pAttr[?] = GLX_RENDER_TYPE: %#x\n", pixelattrib);
805 /* Set GLX_FLOAT_COMPONENTS_NV all the time */
806 if(strstr(WineGLInfo.glxExtensions, "GLX_NV_float_buffer")) {
807 PUSH2(oGLXAttr, GLX_FLOAT_COMPONENTS_NV, nvfloatattrib);
808 TRACE("pAttr[?] = GLX_FLOAT_COMPONENTS_NV: %#x\n", nvfloatattrib);
811 return nAttribs;
814 static int get_render_type_from_fbconfig(Display *display, GLXFBConfig fbconfig)
816 int render_type=0, render_type_bit;
817 pglXGetFBConfigAttrib(display, fbconfig, GLX_RENDER_TYPE, &render_type_bit);
818 switch(render_type_bit)
820 case GLX_RGBA_BIT:
821 render_type = GLX_RGBA_TYPE;
822 break;
823 case GLX_COLOR_INDEX_BIT:
824 render_type = GLX_COLOR_INDEX_TYPE;
825 break;
826 case GLX_RGBA_FLOAT_BIT:
827 render_type = GLX_RGBA_FLOAT_TYPE;
828 break;
829 default:
830 ERR("Unknown render_type: %x\n", render_type);
832 return render_type;
835 static BOOL get_fbconfig_from_visualid(Display *display, Visual *visual, GLXFBConfig *fbconfig, int *fmt_id)
837 GLXFBConfig* cfgs = NULL;
838 int i;
839 int nCfgs;
840 int tmp_fmt_id;
841 int tmp_vis_id;
842 VisualID visualid;
844 if(!display || !visual) {
845 ERR("Invalid display or visual\n");
846 return FALSE;
848 visualid = XVisualIDFromVisual(visual);
850 /* Get a list of all available framebuffer configurations */
851 cfgs = pglXGetFBConfigs(display, DefaultScreen(display), &nCfgs);
852 if (NULL == cfgs || 0 == nCfgs) {
853 ERR("glXChooseFBConfig returns NULL\n");
854 if(cfgs != NULL) XFree(cfgs);
855 return FALSE;
858 /* Find the requested offscreen format and count the number of offscreen formats */
859 for(i=0; i<nCfgs; i++) {
860 pglXGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &tmp_vis_id);
861 pglXGetFBConfigAttrib(display, cfgs[i], GLX_FBCONFIG_ID, &tmp_fmt_id);
863 /* We are looking up the GLX index of our main visual and have found it :) */
864 if(visualid == tmp_vis_id) {
865 TRACE("Found FBCONFIG_ID 0x%x at index %d for VISUAL_ID 0x%x\n", tmp_fmt_id, i, tmp_vis_id);
866 *fbconfig = cfgs[i];
867 *fmt_id = tmp_fmt_id;
868 XFree(cfgs);
869 return TRUE;
873 ERR("No fbconfig found for Wine's main visual (0x%lx), expect problems!\n", visualid);
874 XFree(cfgs);
875 return FALSE;
878 static BOOL init_formats(Display *display, int screen, Visual *visual)
880 int fmt_id, tmp_vis_id, tmp_fmt_id, nCfgs, i;
881 GLXFBConfig* cfgs;
882 GLXFBConfig fbconfig;
883 int nOffscreenFormats = 0;
885 /* Locate the fbconfig correspondig to our main visual */
886 if(!get_fbconfig_from_visualid(display, visual, &fbconfig, &fmt_id)) {
887 ERR("Can't get the FBCONFIG_ID for the main visual, expect problems!\n");
888 return FALSE;
891 /* As mentioned in various parts of the code only the format of the main visual can be used for onscreen rendering.
892 * Next to this format there are also so called offscreen rendering formats (used for pbuffers) which can be supported
893 * because they don't need a visual. Below we use glXGetFBConfigs instead of glXChooseFBConfig to enumerate the fb configurations
894 * because this call lists both types of formats instead of only onscreen ones. */
895 cfgs = pglXGetFBConfigs(display, DefaultScreen(display), &nCfgs);
896 if (NULL == cfgs || 0 == nCfgs) {
897 WARN("glXChooseFBConfig returns NULL\n");
898 if(cfgs != NULL) XFree(cfgs);
900 /* We only have the single format of Wine's main visual */
901 WineGLPixelFormatList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineGLPixelFormat));
902 WineGLPixelFormatList[0].iPixelFormat = 1;
903 WineGLPixelFormatList[0].fbconfig = fbconfig;
904 WineGLPixelFormatList[0].fmt_id = fmt_id;
905 WineGLPixelFormatList[0].render_type = get_render_type_from_fbconfig(display, fbconfig);
906 WineGLPixelFormatList[0].offscreenOnly = FALSE;
907 WineGLPixelFormatListSize = 1;
909 else {
910 /* Count the number of offscreen formats to determine the size for our pixelformat list */
911 for(i=0; i<nCfgs; i++) {
912 pglXGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &tmp_vis_id);
914 /* We have found an offscreen rendering format :) */
915 if(tmp_vis_id == 0) {
916 nOffscreenFormats++;
919 TRACE("Number of offscreen formats: %d\n", nOffscreenFormats);
921 /* Allocate memory for all the offscreen pixelformats and the format of Wine's main visual */
922 WineGLPixelFormatList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (1+nOffscreenFormats)*sizeof(WineGLPixelFormat));
923 WineGLPixelFormatList[0].iPixelFormat = 1;
924 WineGLPixelFormatList[0].fbconfig = fbconfig;
925 WineGLPixelFormatList[0].fmt_id = fmt_id;
926 WineGLPixelFormatList[0].render_type = get_render_type_from_fbconfig(display, fbconfig);
927 WineGLPixelFormatList[0].offscreenOnly = FALSE;
928 WineGLPixelFormatListSize = 1;
930 /* Fill the list with offscreen formats */
931 for(i=0; i<nCfgs; i++) {
932 pglXGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &tmp_vis_id);
933 pglXGetFBConfigAttrib(display, cfgs[i], GLX_FBCONFIG_ID, &tmp_fmt_id);
935 /* We have found an offscreen rendering format :) */
936 if(tmp_vis_id == 0) {
937 TRACE("Found offscreen format FBCONFIG_ID 0x%x corresponding to iPixelFormat %d at GLX index %d\n", tmp_fmt_id, WineGLPixelFormatListSize+1, i);
938 WineGLPixelFormatList[WineGLPixelFormatListSize].iPixelFormat = WineGLPixelFormatListSize+1; /* The index starts at 1 */
939 WineGLPixelFormatList[WineGLPixelFormatListSize].fbconfig = cfgs[i];
940 WineGLPixelFormatList[WineGLPixelFormatListSize].fmt_id = tmp_fmt_id;
941 WineGLPixelFormatList[WineGLPixelFormatListSize].render_type = get_render_type_from_fbconfig(display, cfgs[i]);
942 WineGLPixelFormatList[WineGLPixelFormatListSize].offscreenOnly = TRUE;
943 WineGLPixelFormatListSize++;
948 if(cfgs != NULL) XFree(cfgs);
950 return TRUE;
953 /* GLX can advertise dozens of different pixelformats including offscreen and onscreen ones.
954 * In our WGL implementation we only support a subset of these formats namely the format of
955 * Wine's main visual and offscreen formats (if they are available).
956 * This function converts a WGL format to its corresponding GLX one. It returns a WineGLPixelFormat
957 * and it returns the number of supported WGL formats in fmt_count.
959 static WineGLPixelFormat* ConvertPixelFormatWGLtoGLX(Display *display, int iPixelFormat, BOOL AllowOffscreen, int *fmt_count)
961 WineGLPixelFormat *res = NULL;
963 /* Init the list of pixel formats when we need it */
964 if(!WineGLPixelFormatListSize)
965 init_formats(display, DefaultScreen(display), visual);
967 /* Check if the pixelformat is valid. Note that it is legal to pass an invalid
968 * iPixelFormat in case of probing the number of pixelformats.
970 if((iPixelFormat <= 0) || (iPixelFormat > WineGLPixelFormatListSize)) {
971 if(AllowOffscreen)
972 *fmt_count = WineGLPixelFormatListSize;
973 else
974 *fmt_count = 1; /* Only show the format of our main visual */
976 else if(iPixelFormat == 1) {
977 res = &WineGLPixelFormatList[0];
978 *fmt_count = 1; /* Only show the format of our main visual */
980 else if((WineGLPixelFormatList[iPixelFormat-1].offscreenOnly == TRUE) && AllowOffscreen) {
981 res = &WineGLPixelFormatList[iPixelFormat-1];
982 *fmt_count = WineGLPixelFormatListSize;
983 TRACE("Returning FBConfig=%p for iPixelFormat=%d\n", res->fbconfig, iPixelFormat);
986 TRACE("Number of returned pixelformats=%d\n", *fmt_count);
988 return res;
991 /* Search our internal pixelformat list for the WGL format corresponding to the given fbconfig */
992 static WineGLPixelFormat* ConvertPixelFormatGLXtoWGL(Display *display, int fmt_id)
994 int i;
996 /* Init the list of pixel formats when we need it */
997 if(!WineGLPixelFormatListSize)
998 init_formats(display, DefaultScreen(display), visual);
1000 for(i=0; i<WineGLPixelFormatListSize; i++) {
1001 if(WineGLPixelFormatList[i].fmt_id == fmt_id) {
1002 TRACE("Returning iPixelFormat %d for fmt_id 0x%x\n", WineGLPixelFormatList[i].iPixelFormat, fmt_id);
1003 return &WineGLPixelFormatList[i];
1006 TRACE("No compatible format found for fmt_id 0x%x\n", fmt_id);
1007 return NULL;
1011 * X11DRV_ChoosePixelFormat
1013 * Equivalent to glXChooseVisual.
1015 int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev,
1016 const PIXELFORMATDESCRIPTOR *ppfd) {
1017 WineGLPixelFormat *fmt = NULL;
1018 int ret = 0;
1019 int nPixelFormats;
1020 int value = 0;
1021 int i = 0;
1022 int bestFormat = -1;
1023 int bestDBuffer = -1;
1024 int bestStereo = -1;
1025 int bestColor = -1;
1026 int bestAlpha = -1;
1027 int bestDepth = -1;
1028 int bestStencil = -1;
1029 int bestAux = -1;
1030 int score;
1032 if (!has_opengl()) {
1033 ERR("No libGL on this box - disabling OpenGL support !\n");
1034 return 0;
1037 if (TRACE_ON(opengl)) {
1038 TRACE("(%p,%p)\n", physDev, ppfd);
1040 dump_PIXELFORMATDESCRIPTOR((const PIXELFORMATDESCRIPTOR *) ppfd);
1043 wine_tsx11_lock();
1044 ConvertPixelFormatWGLtoGLX(gdi_display, 0, FALSE /* offscreen */, &nPixelFormats);
1045 for(i=0; i<nPixelFormats; i++)
1047 int dwFlags = 0;
1048 int iPixelType = 0;
1049 int alpha=0, color=0, depth=0, stencil=0, aux=0;
1051 fmt = ConvertPixelFormatWGLtoGLX(gdi_display, i+1 /* 1-based index */, FALSE /* offscreen */, &value);
1052 score = 0;
1054 /* Pixel type */
1055 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &value);
1056 if (value & GLX_RGBA_BIT)
1057 iPixelType = PFD_TYPE_RGBA;
1058 else
1059 iPixelType = PFD_TYPE_COLORINDEX;
1061 if (ppfd->iPixelType != iPixelType)
1063 TRACE("pixel type mismatch for iPixelFormat=%d\n", i+1);
1064 continue;
1067 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value);
1068 if (value) dwFlags |= PFD_DOUBLEBUFFER;
1069 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STEREO, &value);
1070 if (value) dwFlags |= PFD_STEREO;
1071 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, &color); /* cColorBits */
1072 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &alpha); /* cAlphaBits */
1073 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &depth); /* cDepthBits */
1074 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &stencil); /* cStencilBits */
1075 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_AUX_BUFFERS, &aux); /* cAuxBuffers */
1077 /* The behavior of PDF_STEREO/PFD_STEREO_DONTCARE and PFD_DOUBLEBUFFER / PFD_DOUBLEBUFFER_DONTCARE
1078 * is not very clear on MSDN. They specify that ChoosePixelFormat tries to match pixel formats
1079 * with the flag (PFD_STEREO / PFD_DOUBLEBUFFERING) set. Otherwise it says that it tries to match
1080 * formats without the given flag set.
1081 * A test on Windows using a Radeon 9500pro on WinXP (the driver doesn't support Stereo)
1082 * has indicated that a format without stereo is returned when stereo is unavailable.
1083 * So in case PFD_STEREO is set, formats that support it should have priority above formats
1084 * without. In case PFD_STEREO_DONTCARE is set, stereo is ignored.
1086 * To summarize the following is most likely the correct behavior:
1087 * stereo not set -> prefer no-stereo formats, else also accept stereo formats
1088 * stereo set -> prefer stereo formats, else also accept no-stereo formats
1089 * stereo don't care -> it doesn't matter whether we get stereo or not
1091 * In Wine we will treat no-stereo the same way as don't care because it makes
1092 * format selection even more complicated and second drivers with Stereo advertise
1093 * each format twice anyway.
1096 /* Doublebuffer, see the comments above */
1097 if( !(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) ) {
1098 if( ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer) &&
1099 ((dwFlags & PFD_DOUBLEBUFFER) == (ppfd->dwFlags & PFD_DOUBLEBUFFER)) )
1101 bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
1102 bestStereo = dwFlags & PFD_STEREO;
1103 bestAlpha = alpha;
1104 bestColor = color;
1105 bestDepth = depth;
1106 bestStencil = stencil;
1107 bestAux = aux;
1108 bestFormat = i;
1109 continue;
1113 /* Stereo, see the comments above. */
1114 if( !(ppfd->dwFlags & PFD_STEREO_DONTCARE) ) {
1115 if( ((ppfd->dwFlags & PFD_STEREO) != bestStereo) &&
1116 ((dwFlags & PFD_STEREO) == (ppfd->dwFlags & PFD_STEREO)) )
1118 bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
1119 bestStereo = dwFlags & PFD_STEREO;
1120 bestAlpha = alpha;
1121 bestColor = color;
1122 bestDepth = depth;
1123 bestStencil = stencil;
1124 bestAux = aux;
1125 bestFormat = i;
1126 continue;
1130 /* Below we will do a number of checks to select the 'best' pixelformat.
1131 * We assume the precedence cColorBits > cAlphaBits > cDepthBits > cStencilBits -> cAuxBuffers.
1132 * The code works by trying to match the most important options as close as possible.
1133 * When a reasonable format is found, we will try to match more options. */
1135 /* Color bits */
1136 if( ((ppfd->cColorBits > bestColor) && (color > bestColor)) ||
1137 ((color >= ppfd->cColorBits) && (color < bestColor)) )
1139 bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
1140 bestStereo = dwFlags & PFD_STEREO;
1141 bestAlpha = alpha;
1142 bestColor = color;
1143 bestDepth = depth;
1144 bestStencil = stencil;
1145 bestAux = aux;
1146 bestFormat = i;
1147 continue;
1148 } else if(bestColor != color) { /* Do further checks if the format is compatible */
1149 TRACE("color mismatch for iPixelFormat=%d\n", i+1);
1150 continue;
1153 /* Alpha bits */
1154 if( ((ppfd->cAlphaBits > bestAlpha) && (alpha > bestAlpha)) ||
1155 ((alpha >= ppfd->cAlphaBits) && (alpha < bestAlpha)) )
1157 bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
1158 bestStereo = dwFlags & PFD_STEREO;
1159 bestAlpha = alpha;
1160 bestColor = color;
1161 bestDepth = depth;
1162 bestStencil = stencil;
1163 bestAux = aux;
1164 bestFormat = i;
1165 continue;
1166 } else if(bestAlpha != alpha) {
1167 TRACE("alpha mismatch for iPixelFormat=%d\n", i+1);
1168 continue;
1171 /* Depth bits */
1172 if( ((ppfd->cDepthBits > bestDepth) && (depth > bestDepth)) ||
1173 ((depth >= ppfd->cDepthBits) && (depth < bestDepth)) )
1175 bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
1176 bestStereo = dwFlags & PFD_STEREO;
1177 bestAlpha = alpha;
1178 bestColor = color;
1179 bestDepth = depth;
1180 bestStencil = stencil;
1181 bestAux = aux;
1182 bestFormat = i;
1183 continue;
1184 } else if(bestDepth != depth) {
1185 TRACE("depth mismatch for iPixelFormat=%d\n", i+1);
1186 continue;
1189 /* Stencil bits */
1190 if( ((ppfd->cStencilBits > bestStencil) && (stencil > bestStencil)) ||
1191 ((stencil >= ppfd->cStencilBits) && (stencil < bestStencil)) )
1193 bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
1194 bestStereo = dwFlags & PFD_STEREO;
1195 bestAlpha = alpha;
1196 bestColor = color;
1197 bestDepth = depth;
1198 bestStencil = stencil;
1199 bestAux = aux;
1200 bestFormat = i;
1201 continue;
1202 } else if(bestStencil != stencil) {
1203 TRACE("stencil mismatch for iPixelFormat=%d\n", i+1);
1204 continue;
1207 /* Aux buffers */
1208 if( ((ppfd->cAuxBuffers > bestAux) && (aux > bestAux)) ||
1209 ((aux >= ppfd->cAuxBuffers) && (aux < bestAux)) )
1211 bestDBuffer = dwFlags & PFD_DOUBLEBUFFER;
1212 bestStereo = dwFlags & PFD_STEREO;
1213 bestAlpha = alpha;
1214 bestColor = color;
1215 bestDepth = depth;
1216 bestStencil = stencil;
1217 bestAux = aux;
1218 bestFormat = i;
1219 continue;
1220 } else if(bestAux != aux) {
1221 TRACE("aux mismatch for iPixelFormat=%d\n", i+1);
1222 continue;
1226 if(bestFormat == -1) {
1227 TRACE("No matching mode was found returning 0\n");
1228 ret = 0;
1230 else {
1231 ret = bestFormat+1; /* the return value should be a 1-based index */
1232 TRACE("Successfully found a matching mode, returning index: %d %x\n", ret, WineGLPixelFormatList[bestFormat-1].fmt_id);
1235 wine_tsx11_unlock();
1237 return ret;
1240 * X11DRV_DescribePixelFormat
1242 * Get the pixel-format descriptor associated to the given id
1244 int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev,
1245 int iPixelFormat,
1246 UINT nBytes,
1247 PIXELFORMATDESCRIPTOR *ppfd) {
1248 /*XVisualInfo *vis;*/
1249 int value;
1250 int rb,gb,bb,ab;
1251 WineGLPixelFormat *fmt;
1252 int ret = 0;
1253 int fmt_count = 0;
1255 if (!has_opengl()) {
1256 ERR("No libGL on this box - disabling OpenGL support !\n");
1257 return 0;
1260 TRACE("(%p,%d,%d,%p)\n", physDev, iPixelFormat, nBytes, ppfd);
1262 /* 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 */
1263 fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, FALSE /* Offscreen */, &fmt_count);
1264 if (ppfd == NULL) {
1265 /* The application is only querying the number of pixelformats */
1266 return fmt_count;
1267 } else if(fmt == NULL) {
1268 WARN("unexpected iPixelFormat(%d): not >=1 and <=nFormats(%d), returning NULL!\n", iPixelFormat, fmt_count);
1269 return 0;
1272 if (nBytes < sizeof(PIXELFORMATDESCRIPTOR)) {
1273 ERR("Wrong structure size !\n");
1274 /* Should set error */
1275 return 0;
1278 ret = fmt_count;
1280 memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
1281 ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
1282 ppfd->nVersion = 1;
1284 /* These flags are always the same... */
1285 ppfd->dwFlags = PFD_SUPPORT_OPENGL;
1286 /* Now the flags extracted from the Visual */
1288 wine_tsx11_lock();
1290 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_X_RENDERABLE, &value);
1291 if(value)
1292 ppfd->dwFlags |= PFD_SUPPORT_GDI;
1294 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &value);
1295 if(value & GLX_WINDOW_BIT)
1296 ppfd->dwFlags |= PFD_DRAW_TO_WINDOW;
1297 if(value & GLX_PIXMAP_BIT)
1298 ppfd->dwFlags |= PFD_DRAW_TO_BITMAP;
1300 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_CONFIG_CAVEAT, &value);
1301 if(value == GLX_SLOW_CONFIG)
1302 ppfd->dwFlags |= PFD_GENERIC_ACCELERATED;
1304 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value);
1305 if (value) {
1306 ppfd->dwFlags |= PFD_DOUBLEBUFFER;
1307 ppfd->dwFlags &= ~PFD_SUPPORT_GDI;
1309 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STEREO, &value); if (value) ppfd->dwFlags |= PFD_STEREO;
1311 /* Pixel type */
1312 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &value);
1313 if (value & GLX_RGBA_BIT)
1314 ppfd->iPixelType = PFD_TYPE_RGBA;
1315 else
1316 ppfd->iPixelType = PFD_TYPE_COLORINDEX;
1318 /* Color bits */
1319 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, &value);
1320 ppfd->cColorBits = value;
1322 /* Red, green, blue and alpha bits / shifts */
1323 if (ppfd->iPixelType == PFD_TYPE_RGBA) {
1324 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RED_SIZE, &rb);
1325 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_GREEN_SIZE, &gb);
1326 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BLUE_SIZE, &bb);
1327 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &ab);
1329 ppfd->cRedBits = rb;
1330 ppfd->cRedShift = gb + bb + ab;
1331 ppfd->cBlueBits = bb;
1332 ppfd->cBlueShift = ab;
1333 ppfd->cGreenBits = gb;
1334 ppfd->cGreenShift = bb + ab;
1335 ppfd->cAlphaBits = ab;
1336 ppfd->cAlphaShift = 0;
1337 } else {
1338 ppfd->cRedBits = 0;
1339 ppfd->cRedShift = 0;
1340 ppfd->cBlueBits = 0;
1341 ppfd->cBlueShift = 0;
1342 ppfd->cGreenBits = 0;
1343 ppfd->cGreenShift = 0;
1344 ppfd->cAlphaBits = 0;
1345 ppfd->cAlphaShift = 0;
1348 /* Accum RGBA bits */
1349 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_RED_SIZE, &rb);
1350 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_GREEN_SIZE, &gb);
1351 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &bb);
1352 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &ab);
1354 ppfd->cAccumBits = rb+gb+bb+ab;
1355 ppfd->cAccumRedBits = rb;
1356 ppfd->cAccumGreenBits = gb;
1357 ppfd->cAccumBlueBits = bb;
1358 ppfd->cAccumAlphaBits = ab;
1360 /* Depth bits */
1361 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &value);
1362 ppfd->cDepthBits = value;
1364 /* stencil bits */
1365 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &value);
1366 ppfd->cStencilBits = value;
1368 wine_tsx11_unlock();
1370 /* Aux : to do ... */
1372 ppfd->iLayerType = PFD_MAIN_PLANE;
1374 if (TRACE_ON(opengl)) {
1375 dump_PIXELFORMATDESCRIPTOR(ppfd);
1378 return ret;
1382 * X11DRV_GetPixelFormat
1384 * Get the pixel-format id used by this DC
1386 int X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) {
1387 WineGLPixelFormat *fmt;
1388 int tmp;
1389 TRACE("(%p)\n", physDev);
1391 fmt = ConvertPixelFormatWGLtoGLX(gdi_display, physDev->current_pf, TRUE, &tmp);
1392 if(!fmt)
1394 /* This happens on HDCs on which SetPixelFormat wasn't called yet */
1395 ERR("Unable to find a WineGLPixelFormat for iPixelFormat=%d\n", physDev->current_pf);
1396 return 0;
1398 else if(fmt->offscreenOnly)
1400 /* Offscreen formats can't be used with traditional WGL calls.
1401 * As has been verified on Windows GetPixelFormat doesn't fail but returns iPixelFormat=1. */
1402 TRACE("Returning iPixelFormat=1 for offscreen format: %d\n", fmt->iPixelFormat);
1403 return 1;
1406 TRACE("(%p): returns %d\n", physDev, physDev->current_pf);
1407 return physDev->current_pf;
1411 * X11DRV_SetPixelFormat
1413 * Set the pixel-format id used by this DC
1415 BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev,
1416 int iPixelFormat,
1417 const PIXELFORMATDESCRIPTOR *ppfd) {
1418 WineGLPixelFormat *fmt;
1419 int value;
1421 TRACE("(%p,%d,%p)\n", physDev, iPixelFormat, ppfd);
1423 if (!has_opengl()) {
1424 ERR("No libGL on this box - disabling OpenGL support !\n");
1425 return 0;
1428 /* SetPixelFormat is not allowed on the X root_window e.g. GetDC(0) */
1429 if(get_glxdrawable(physDev) == root_window)
1431 ERR("Invalid operation on root_window\n");
1432 return 0;
1435 /* Check if iPixelFormat is in our list of supported formats to see if it is supported. */
1436 fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, FALSE /* Offscreen */, &value);
1437 if(!fmt) {
1438 ERR("Invalid iPixelFormat: %d\n", iPixelFormat);
1439 return 0;
1442 physDev->current_pf = iPixelFormat;
1444 if (TRACE_ON(opengl)) {
1445 int gl_test = 0;
1448 * How to test if hdc current drawable is compatible (visual/FBConfig) ?
1450 * in case of root window created HDCs we crash here :(
1452 Drawable drawable = get_drawable( physDev->hdc );
1453 TRACE(" drawable (%p,%p) have :\n", drawable, root_window);
1454 pglXQueryDrawable(gdi_display, drawable, GLX_FBCONFIG_ID, (unsigned int*) &value);
1455 TRACE(" - FBCONFIG_ID as 0x%x\n", tmp);
1456 pglXQueryDrawable(gdi_display, drawable, GLX_VISUAL_ID, (unsigned int*) &value);
1457 TRACE(" - VISUAL_ID as 0x%x\n", tmp);
1458 pglXQueryDrawable(gdi_display, drawable, GLX_WIDTH, (unsigned int*) &value);
1459 TRACE(" - WIDTH as %d\n", tmp);
1460 pglXQueryDrawable(gdi_display, drawable, GLX_HEIGHT, (unsigned int*) &value);
1461 TRACE(" - HEIGHT as %d\n", tmp);
1463 gl_test = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_FBCONFIG_ID, &value);
1464 if (gl_test) {
1465 ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
1466 } else {
1467 TRACE(" FBConfig have :\n");
1468 TRACE(" - FBCONFIG_ID 0x%x\n", value);
1469 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_VISUAL_ID, &value);
1470 TRACE(" - VISUAL_ID 0x%x\n", value);
1471 pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &value);
1472 TRACE(" - DRAWABLE_TYPE 0x%x\n", value);
1475 return TRUE;
1479 * X11DRV_wglCreateContext
1481 * For OpenGL32 wglCreateContext.
1483 HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev)
1485 Wine_GLContext *ret;
1486 WineGLPixelFormat *fmt;
1487 int hdcPF = physDev->current_pf;
1488 int fmt_count = 0;
1489 int value = 0;
1490 int gl_test = 0;
1491 HDC hdc = physDev->hdc;
1493 TRACE("(%p)->(PF:%d)\n", hdc, hdcPF);
1495 if (!has_opengl()) {
1496 ERR("No libGL on this box - disabling OpenGL support !\n");
1497 return 0;
1500 /* First, get the visual in use by the X11DRV */
1501 if (!gdi_display) return 0;
1503 fmt = ConvertPixelFormatWGLtoGLX(gdi_display, hdcPF, TRUE /* Offscreen */, &fmt_count);
1504 /* We can render using the iPixelFormat (1) of Wine's Main visual AND using some offscreen formats.
1505 * Note that standard WGL-calls don't recognize offscreen-only formats. For that reason pbuffers
1506 * use a sort of 'proxy' HDC (wglGetPbufferDCARB).
1507 * If this fails something is very wrong on the system. */
1508 if(!fmt) {
1509 ERR("Cannot get FB Config for iPixelFormat %d, expect problems!\n", hdcPF);
1510 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1511 return NULL;
1514 if (fmt_count < hdcPF) {
1515 ERR("(%p): unexpected pixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, hdcPF, fmt_count);
1516 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1517 return NULL;
1520 gl_test = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_FBCONFIG_ID, &value);
1521 if (gl_test) {
1522 ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
1523 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
1524 return NULL;
1527 /* The context will be allocated in the wglMakeCurrent call */
1528 wine_tsx11_lock();
1529 ret = alloc_context();
1530 wine_tsx11_unlock();
1531 ret->hdc = hdc;
1532 ret->physDev = physDev;
1533 ret->fmt = fmt;
1535 /*ret->vis = vis;*/
1536 ret->vis = pglXGetVisualFromFBConfig(gdi_display, fmt->fbconfig);
1538 TRACE(" creating context %p (GL context creation delayed)\n", ret);
1539 return (HGLRC) ret;
1543 * X11DRV_wglDeleteContext
1545 * For OpenGL32 wglDeleteContext.
1547 BOOL X11DRV_wglDeleteContext(HGLRC hglrc)
1549 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
1550 BOOL ret = TRUE;
1552 TRACE("(%p)\n", hglrc);
1554 if (!has_opengl()) {
1555 ERR("No libGL on this box - disabling OpenGL support !\n");
1556 return 0;
1559 wine_tsx11_lock();
1560 /* A game (Half Life not to name it) deletes twice the same context,
1561 * so make sure it is valid first */
1562 if (is_valid_context( ctx ))
1564 if (ctx->ctx) pglXDestroyContext(gdi_display, ctx->ctx);
1565 free_context(ctx);
1567 else
1569 WARN("Error deleting context !\n");
1570 SetLastError(ERROR_INVALID_HANDLE);
1571 ret = FALSE;
1573 wine_tsx11_unlock();
1575 return ret;
1579 * X11DRV_wglGetCurrentReadDCARB
1581 * For OpenGL32 wglGetCurrentReadDCARB.
1583 static HDC WINAPI X11DRV_wglGetCurrentReadDCARB(void)
1585 GLXDrawable gl_d;
1586 HDC ret;
1588 TRACE("()\n");
1590 wine_tsx11_lock();
1591 gl_d = pglXGetCurrentReadDrawable();
1592 ret = get_hdc_from_Drawable(gl_d);
1593 wine_tsx11_unlock();
1595 TRACE(" returning %p (GL drawable %lu)\n", ret, gl_d);
1596 return ret;
1600 * X11DRV_wglGetProcAddress
1602 * For OpenGL32 wglGetProcAddress.
1604 PROC X11DRV_wglGetProcAddress(LPCSTR lpszProc)
1606 int i, j;
1607 const WineGLExtension *ext;
1609 int padding = 32 - strlen(lpszProc);
1610 if (padding < 0)
1611 padding = 0;
1613 if (!has_opengl()) {
1614 ERR("No libGL on this box - disabling OpenGL support !\n");
1615 return 0;
1618 /* Check the table of WGL extensions to see if we need to return a WGL extension
1619 * or a function pointer to a native OpenGL function. */
1620 if(strncmp(lpszProc, "wgl", 3) != 0) {
1621 return pglXGetProcAddressARB((const GLubyte*)lpszProc);
1622 } else {
1623 TRACE("('%s'):%*s", lpszProc, padding, " ");
1624 for (i = 0; i < WineGLExtensionListSize; ++i) {
1625 ext = WineGLExtensionList[i];
1626 for (j = 0; ext->extEntryPoints[j].funcName; ++j) {
1627 if (strcmp(ext->extEntryPoints[j].funcName, lpszProc) == 0) {
1628 TRACE("(%p) - WineGL\n", ext->extEntryPoints[j].funcAddress);
1629 return ext->extEntryPoints[j].funcAddress;
1635 ERR("(%s) - not found\n", lpszProc);
1636 return NULL;
1639 /***********************************************************************
1640 * sync_current_drawable
1642 * Adjust the current viewport and scissor in order to position
1643 * and size the current drawable correctly on the parent window.
1645 static void sync_current_drawable(BOOL updatedc)
1647 int dy;
1648 int width;
1649 int height;
1650 RECT rc;
1651 Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
1653 TRACE("\n");
1655 if (ctx && ctx->physDev)
1657 if (updatedc)
1658 GetClipBox(ctx->physDev->hdc, &rc); /* Make sure physDev is up to date */
1660 dy = ctx->physDev->drawable_rect.bottom - ctx->physDev->drawable_rect.top -
1661 ctx->physDev->dc_rect.bottom;
1662 width = ctx->physDev->dc_rect.right - ctx->physDev->dc_rect.left;
1663 height = ctx->physDev->dc_rect.bottom - ctx->physDev->dc_rect.top;
1665 wine_tsx11_lock();
1667 pglViewport(ctx->physDev->dc_rect.left + ctx->viewport.left,
1668 dy + ctx->viewport.top,
1669 ctx->viewport.right ? (ctx->viewport.right - ctx->viewport.left) : width,
1670 ctx->viewport.bottom ? (ctx->viewport.bottom - ctx->viewport.top) : height);
1672 pglEnable(GL_SCISSOR_TEST);
1674 if (ctx->scissor_enabled)
1675 pglScissor(ctx->physDev->dc_rect.left + min(width, max(0, ctx->scissor.left)),
1676 dy + min(height, max(0, ctx->scissor.top)),
1677 min(width, max(0, ctx->scissor.right - ctx->scissor.left)),
1678 min(height, max(0, ctx->scissor.bottom - ctx->scissor.top)));
1679 else
1680 pglScissor(ctx->physDev->dc_rect.left, dy, width, height);
1682 wine_tsx11_unlock();
1687 * X11DRV_wglMakeCurrent
1689 * For OpenGL32 wglMakeCurrent.
1691 BOOL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) {
1692 BOOL ret;
1693 HDC hdc = physDev->hdc;
1694 DWORD type = GetObjectType(hdc);
1696 TRACE("(%p,%p)\n", hdc, hglrc);
1698 if (!has_opengl()) {
1699 ERR("No libGL on this box - disabling OpenGL support !\n");
1700 return 0;
1703 wine_tsx11_lock();
1704 if (hglrc == NULL) {
1705 ret = pglXMakeCurrent(gdi_display, None, NULL);
1706 NtCurrentTeb()->glContext = NULL;
1707 } else {
1708 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
1709 Drawable drawable = get_glxdrawable(physDev);
1710 if (ctx->ctx == NULL) {
1711 /* The describe lines below are for debugging purposes only */
1712 if (TRACE_ON(wgl)) {
1713 describeDrawable(ctx, drawable);
1714 describeContext(ctx);
1717 /* Create a GLX context using the same visual as chosen earlier in wglCreateContext.
1718 * We are certain that the drawable and context are compatible as we only allow compatible formats.
1720 TRACE(" Creating GLX Context\n");
1721 if(ctx->vis)
1722 ctx->ctx = pglXCreateContext(gdi_display, ctx->vis, NULL, type == OBJ_MEMDC ? False : True);
1723 else /* Create a GLX Context for a pbuffer */
1724 ctx->ctx = pglXCreateNewContext(gdi_display, ctx->fmt->fbconfig, ctx->fmt->render_type, NULL, True);
1726 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
1728 TRACE(" make current for dis %p, drawable %p, ctx %p\n", gdi_display, (void*) drawable, ctx->ctx);
1729 ret = pglXMakeCurrent(gdi_display, drawable, ctx->ctx);
1730 NtCurrentTeb()->glContext = ctx;
1731 if(ret)
1733 ctx->physDev = physDev;
1735 if (type == OBJ_MEMDC)
1737 ctx->do_escape = TRUE;
1738 pglDrawBuffer(GL_FRONT_LEFT);
1740 else
1742 sync_current_drawable(FALSE);
1746 wine_tsx11_unlock();
1747 TRACE(" returning %s\n", (ret ? "True" : "False"));
1748 return ret;
1752 * X11DRV_wglMakeContextCurrentARB
1754 * For OpenGL32 wglMakeContextCurrentARB
1756 BOOL X11DRV_wglMakeContextCurrentARB(X11DRV_PDEVICE* hDrawDev, X11DRV_PDEVICE* hReadDev, HGLRC hglrc)
1758 BOOL ret;
1759 TRACE("(%p,%p,%p)\n", hDrawDev, hReadDev, hglrc);
1761 if (!has_opengl()) {
1762 ERR("No libGL on this box - disabling OpenGL support !\n");
1763 return 0;
1766 wine_tsx11_lock();
1767 if (hglrc == NULL) {
1768 ret = pglXMakeCurrent(gdi_display, None, NULL);
1769 NtCurrentTeb()->glContext = NULL;
1770 } else {
1771 if (NULL == pglXMakeContextCurrent) {
1772 ret = FALSE;
1773 } else {
1774 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
1775 Drawable d_draw = get_glxdrawable(hDrawDev);
1776 Drawable d_read = get_glxdrawable(hReadDev);
1778 if (ctx->ctx == NULL) {
1779 ctx->ctx = pglXCreateContext(gdi_display, ctx->vis, NULL, GetObjectType(hDrawDev->hdc) == OBJ_MEMDC ? False : True);
1780 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
1782 ret = pglXMakeContextCurrent(gdi_display, d_draw, d_read, ctx->ctx);
1783 NtCurrentTeb()->glContext = ctx;
1786 wine_tsx11_unlock();
1788 TRACE(" returning %s\n", (ret ? "True" : "False"));
1789 return ret;
1793 * X11DRV_wglShareLists
1795 * For OpenGL32 wglShaderLists.
1797 BOOL X11DRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) {
1798 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
1799 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
1801 TRACE("(%p, %p)\n", org, dest);
1803 if (!has_opengl()) {
1804 ERR("No libGL on this box - disabling OpenGL support !\n");
1805 return 0;
1808 if (NULL != dest && dest->ctx != NULL) {
1809 ERR("Could not share display lists, context already created !\n");
1810 return FALSE;
1811 } else {
1812 if (org->ctx == NULL) {
1813 wine_tsx11_lock();
1814 describeContext(org);
1816 if(org->vis)
1817 org->ctx = pglXCreateContext(gdi_display, org->vis, NULL, GetObjectType(org->physDev->hdc) == OBJ_MEMDC ? False : True);
1818 else /* Create a GLX Context for a pbuffer */
1819 org->ctx = pglXCreateNewContext(gdi_display, org->fmt->fbconfig, org->fmt->render_type, NULL, True);
1820 wine_tsx11_unlock();
1821 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
1823 if (NULL != dest) {
1824 wine_tsx11_lock();
1825 describeContext(dest);
1826 /* Create the destination context with display lists shared */
1827 if(dest->vis)
1828 dest->ctx = pglXCreateContext(gdi_display, dest->vis, org->ctx, GetObjectType(org->physDev->hdc) == OBJ_MEMDC ? False : True);
1829 else /* Create a GLX Context for a pbuffer */
1830 dest->ctx = pglXCreateNewContext(gdi_display, dest->fmt->fbconfig, dest->fmt->render_type, org->ctx, True);
1831 wine_tsx11_unlock();
1832 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
1833 return TRUE;
1836 return FALSE;
1839 static BOOL internal_wglUseFontBitmaps(HDC hdc, DWORD first, DWORD count, DWORD listBase, DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
1841 /* We are running using client-side rendering fonts... */
1842 GLYPHMETRICS gm;
1843 unsigned int glyph;
1844 int size = 0;
1845 void *bitmap = NULL, *gl_bitmap = NULL;
1846 int org_alignment;
1848 wine_tsx11_lock();
1849 pglGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
1850 pglPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1851 wine_tsx11_unlock();
1853 for (glyph = first; glyph < first + count; glyph++) {
1854 unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
1855 int height, width_int;
1857 TRACE("Glyph : %3d / List : %d\n", glyph, listBase);
1858 if (needed_size == GDI_ERROR) {
1859 TRACE(" - needed size : %d (GDI_ERROR)\n", needed_size);
1860 goto error;
1861 } else {
1862 TRACE(" - needed size : %d\n", needed_size);
1865 if (needed_size > size) {
1866 size = needed_size;
1867 HeapFree(GetProcessHeap(), 0, bitmap);
1868 HeapFree(GetProcessHeap(), 0, gl_bitmap);
1869 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1870 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1872 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
1873 if (TRACE_ON(opengl)) {
1874 unsigned int height, width, bitmask;
1875 unsigned char *bitmap_ = (unsigned char *) bitmap;
1877 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
1878 TRACE(" - origin : (%d , %d)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
1879 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
1880 if (needed_size != 0) {
1881 TRACE(" - bitmap :\n");
1882 for (height = 0; height < gm.gmBlackBoxY; height++) {
1883 TRACE(" ");
1884 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
1885 if (bitmask == 0) {
1886 bitmap_ += 1;
1887 bitmask = 0x80;
1889 if (*bitmap_ & bitmask)
1890 TRACE("*");
1891 else
1892 TRACE(" ");
1894 bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
1895 TRACE("\n");
1900 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
1901 * glyph for it to be drawn properly.
1903 if (needed_size != 0) {
1904 width_int = (gm.gmBlackBoxX + 31) / 32;
1905 for (height = 0; height < gm.gmBlackBoxY; height++) {
1906 int width;
1907 for (width = 0; width < width_int; width++) {
1908 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
1909 ((int *) bitmap)[height * width_int + width];
1914 wine_tsx11_lock();
1915 pglNewList(listBase++, GL_COMPILE);
1916 if (needed_size != 0) {
1917 pglBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
1918 0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
1919 gm.gmCellIncX, gm.gmCellIncY,
1920 gl_bitmap);
1921 } else {
1922 /* This is the case of 'empty' glyphs like the space character */
1923 pglBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
1925 pglEndList();
1926 wine_tsx11_unlock();
1929 wine_tsx11_lock();
1930 pglPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
1931 wine_tsx11_unlock();
1933 HeapFree(GetProcessHeap(), 0, bitmap);
1934 HeapFree(GetProcessHeap(), 0, gl_bitmap);
1935 return TRUE;
1937 error:
1938 wine_tsx11_lock();
1939 pglPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
1940 wine_tsx11_unlock();
1942 HeapFree(GetProcessHeap(), 0, bitmap);
1943 HeapFree(GetProcessHeap(), 0, gl_bitmap);
1944 return FALSE;
1948 * X11DRV_wglUseFontBitmapsA
1950 * For OpenGL32 wglUseFontBitmapsA.
1952 BOOL X11DRV_wglUseFontBitmapsA(X11DRV_PDEVICE *physDev, DWORD first, DWORD count, DWORD listBase)
1954 Font fid = physDev->font;
1956 TRACE("(%p, %d, %d, %d) using font %ld\n", physDev->hdc, first, count, listBase, fid);
1958 if (!has_opengl()) {
1959 ERR("No libGL on this box - disabling OpenGL support !\n");
1960 return 0;
1963 if (fid == 0) {
1964 return internal_wglUseFontBitmaps(physDev->hdc, first, count, listBase, GetGlyphOutlineA);
1967 wine_tsx11_lock();
1968 /* I assume that the glyphs are at the same position for X and for Windows */
1969 pglXUseXFont(fid, first, count, listBase);
1970 wine_tsx11_unlock();
1971 return TRUE;
1975 * X11DRV_wglUseFontBitmapsW
1977 * For OpenGL32 wglUseFontBitmapsW.
1979 BOOL X11DRV_wglUseFontBitmapsW(X11DRV_PDEVICE *physDev, DWORD first, DWORD count, DWORD listBase)
1981 Font fid = physDev->font;
1983 TRACE("(%p, %d, %d, %d) using font %ld\n", physDev->hdc, first, count, listBase, fid);
1985 if (!has_opengl()) {
1986 ERR("No libGL on this box - disabling OpenGL support !\n");
1987 return 0;
1990 if (fid == 0) {
1991 return internal_wglUseFontBitmaps(physDev->hdc, first, count, listBase, GetGlyphOutlineW);
1994 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
1996 wine_tsx11_lock();
1997 /* I assume that the glyphs are at the same position for X and for Windows */
1998 pglXUseXFont(fid, first, count, listBase);
1999 wine_tsx11_unlock();
2000 return TRUE;
2003 static void WINAPI X11DRV_wglDisable(GLenum cap)
2005 if (cap == GL_SCISSOR_TEST)
2007 Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
2009 if (ctx)
2010 ctx->scissor_enabled = FALSE;
2012 else
2014 wine_tsx11_lock();
2015 pglDisable(cap);
2016 wine_tsx11_unlock();
2020 static void WINAPI X11DRV_wglEnable(GLenum cap)
2022 if (cap == GL_SCISSOR_TEST)
2024 Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
2026 if (ctx)
2027 ctx->scissor_enabled = TRUE;
2029 else
2031 wine_tsx11_lock();
2032 pglEnable(cap);
2033 wine_tsx11_unlock();
2037 /* WGL helper function which handles differences in glGetIntegerv from WGL and GLX */
2038 static void WINAPI X11DRV_wglGetIntegerv(GLenum pname, GLint* params)
2040 wine_tsx11_lock();
2041 switch(pname)
2043 case GL_DEPTH_BITS:
2045 GLXContext gl_ctx = pglXGetCurrentContext();
2046 Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
2048 pglGetIntegerv(pname, params);
2050 * if we cannot find a Wine Context
2051 * we only have the default wine desktop context,
2052 * so if we have only a 24 depth say we have 32
2054 if (NULL == ret && 24 == *params) {
2055 *params = 32;
2057 TRACE("returns GL_DEPTH_BITS as '%d'\n", *params);
2058 break;
2060 case GL_ALPHA_BITS:
2062 GLXContext gl_ctx = pglXGetCurrentContext();
2063 Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
2065 pglXGetFBConfigAttrib(gdi_display, ret->fmt->fbconfig, GLX_ALPHA_SIZE, params);
2066 TRACE("returns GL_ALPHA_BITS as '%d'\n", *params);
2067 break;
2069 default:
2070 pglGetIntegerv(pname, params);
2071 break;
2073 wine_tsx11_unlock();
2076 static GLboolean WINAPI X11DRV_wglIsEnabled(GLenum cap)
2078 GLboolean enabled = False;
2080 if (cap == GL_SCISSOR_TEST)
2082 Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
2084 if (ctx)
2085 enabled = ctx->scissor_enabled;
2087 else
2089 wine_tsx11_lock();
2090 enabled = pglIsEnabled(cap);
2091 wine_tsx11_unlock();
2093 return enabled;
2096 static void WINAPI X11DRV_wglScissor(GLint x, GLint y, GLsizei width, GLsizei height)
2098 Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
2100 if (ctx)
2102 ctx->scissor.left = x;
2103 ctx->scissor.top = y;
2104 ctx->scissor.right = x + width;
2105 ctx->scissor.bottom = y + height;
2107 sync_current_drawable(TRUE);
2111 static void WINAPI X11DRV_wglViewport(GLint x, GLint y, GLsizei width, GLsizei height)
2113 Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
2115 if (ctx)
2117 ctx->viewport.left = x;
2118 ctx->viewport.top = y;
2119 ctx->viewport.right = x + width;
2120 ctx->viewport.bottom = y + height;
2122 sync_current_drawable(TRUE);
2127 * X11DRV_wglGetExtensionsStringARB
2129 * WGL_ARB_extensions_string: wglGetExtensionsStringARB
2131 static const char * WINAPI X11DRV_wglGetExtensionsStringARB(HDC hdc) {
2132 TRACE("() returning \"%s\"\n", WineGLInfo.wglExtensions);
2133 return WineGLInfo.wglExtensions;
2137 * X11DRV_wglCreatePbufferARB
2139 * WGL_ARB_pbuffer: wglCreatePbufferARB
2141 static HPBUFFERARB WINAPI X11DRV_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList)
2143 Wine_GLPBuffer* object = NULL;
2144 WineGLPixelFormat *fmt = NULL;
2145 int nCfgs = 0;
2146 int attribs[256];
2147 int nAttribs = 0;
2149 TRACE("(%p, %d, %d, %d, %p)\n", hdc, iPixelFormat, iWidth, iHeight, piAttribList);
2151 if (0 >= iPixelFormat) {
2152 ERR("(%p): unexpected iPixelFormat(%d) <= 0, returns NULL\n", hdc, iPixelFormat);
2153 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2154 return NULL; /* unexpected error */
2157 /* Convert the WGL pixelformat to a GLX format, if it fails then the format is invalid */
2158 fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, TRUE /* Offscreen */, &nCfgs);
2159 if(!fmt) {
2160 ERR("(%p): unexpected iPixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, iPixelFormat, nCfgs);
2161 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
2162 goto create_failed; /* unexpected error */
2165 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLPBuffer));
2166 if (NULL == object) {
2167 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2168 goto create_failed; /* unexpected error */
2170 object->hdc = hdc;
2171 object->display = gdi_display;
2172 object->width = iWidth;
2173 object->height = iHeight;
2174 object->fmt = fmt;
2176 PUSH2(attribs, GLX_PBUFFER_WIDTH, iWidth);
2177 PUSH2(attribs, GLX_PBUFFER_HEIGHT, iHeight);
2178 while (piAttribList && 0 != *piAttribList) {
2179 int attr_v;
2180 switch (*piAttribList) {
2181 case WGL_PBUFFER_LARGEST_ARB: {
2182 ++piAttribList;
2183 attr_v = *piAttribList;
2184 TRACE("WGL_LARGEST_PBUFFER_ARB = %d\n", attr_v);
2185 PUSH2(attribs, GLX_LARGEST_PBUFFER, attr_v);
2186 break;
2189 case WGL_TEXTURE_FORMAT_ARB: {
2190 ++piAttribList;
2191 attr_v = *piAttribList;
2192 TRACE("WGL_render_texture Attribute: WGL_TEXTURE_FORMAT_ARB as %x\n", attr_v);
2193 if (use_render_texture_ati) {
2194 int type = 0;
2195 switch (attr_v) {
2196 case WGL_NO_TEXTURE_ARB: type = GLX_NO_TEXTURE_ATI; break ;
2197 case WGL_TEXTURE_RGB_ARB: type = GLX_TEXTURE_RGB_ATI; break ;
2198 case WGL_TEXTURE_RGBA_ARB: type = GLX_TEXTURE_RGBA_ATI; break ;
2199 default:
2200 SetLastError(ERROR_INVALID_DATA);
2201 goto create_failed;
2203 object->use_render_texture = 1;
2204 PUSH2(attribs, GLX_TEXTURE_FORMAT_ATI, type);
2205 } else {
2206 if (WGL_NO_TEXTURE_ARB == attr_v) {
2207 object->use_render_texture = 0;
2208 } else {
2209 if (!use_render_texture_emulation) {
2210 SetLastError(ERROR_INVALID_DATA);
2211 goto create_failed;
2213 switch (attr_v) {
2214 case WGL_TEXTURE_RGB_ARB:
2215 object->use_render_texture = GL_RGB;
2216 object->texture_bpp = 3;
2217 object->texture_format = GL_RGB;
2218 object->texture_type = GL_UNSIGNED_BYTE;
2219 break;
2220 case WGL_TEXTURE_RGBA_ARB:
2221 object->use_render_texture = GL_RGBA;
2222 object->texture_bpp = 4;
2223 object->texture_format = GL_RGBA;
2224 object->texture_type = GL_UNSIGNED_BYTE;
2225 break;
2227 /* WGL_FLOAT_COMPONENTS_NV */
2228 case WGL_TEXTURE_FLOAT_R_NV:
2229 object->use_render_texture = GL_FLOAT_R_NV;
2230 object->texture_bpp = 4;
2231 object->texture_format = GL_RED;
2232 object->texture_type = GL_FLOAT;
2233 break;
2234 case WGL_TEXTURE_FLOAT_RG_NV:
2235 object->use_render_texture = GL_FLOAT_RG_NV;
2236 object->texture_bpp = 8;
2237 object->texture_format = GL_LUMINANCE_ALPHA;
2238 object->texture_type = GL_FLOAT;
2239 break;
2240 case WGL_TEXTURE_FLOAT_RGB_NV:
2241 object->use_render_texture = GL_FLOAT_RGB_NV;
2242 object->texture_bpp = 12;
2243 object->texture_format = GL_RGB;
2244 object->texture_type = GL_FLOAT;
2245 break;
2246 case WGL_TEXTURE_FLOAT_RGBA_NV:
2247 object->use_render_texture = GL_FLOAT_RGBA_NV;
2248 object->texture_bpp = 16;
2249 object->texture_format = GL_RGBA;
2250 object->texture_type = GL_FLOAT;
2251 break;
2252 default:
2253 ERR("Unknown texture format: %x\n", attr_v);
2254 SetLastError(ERROR_INVALID_DATA);
2255 goto create_failed;
2259 break;
2262 case WGL_TEXTURE_TARGET_ARB: {
2263 ++piAttribList;
2264 attr_v = *piAttribList;
2265 TRACE("WGL_render_texture Attribute: WGL_TEXTURE_TARGET_ARB as %x\n", attr_v);
2266 if (use_render_texture_ati) {
2267 int type = 0;
2268 switch (attr_v) {
2269 case WGL_NO_TEXTURE_ARB: type = GLX_NO_TEXTURE_ATI; break ;
2270 case WGL_TEXTURE_CUBE_MAP_ARB: type = GLX_TEXTURE_CUBE_MAP_ATI; break ;
2271 case WGL_TEXTURE_1D_ARB: type = GLX_TEXTURE_1D_ATI; break ;
2272 case WGL_TEXTURE_2D_ARB: type = GLX_TEXTURE_2D_ATI; break ;
2273 default:
2274 SetLastError(ERROR_INVALID_DATA);
2275 goto create_failed;
2277 PUSH2(attribs, GLX_TEXTURE_TARGET_ATI, type);
2278 } else {
2279 if (WGL_NO_TEXTURE_ARB == attr_v) {
2280 object->texture_target = 0;
2281 } else {
2282 if (!use_render_texture_emulation) {
2283 SetLastError(ERROR_INVALID_DATA);
2284 goto create_failed;
2286 switch (attr_v) {
2287 case WGL_TEXTURE_CUBE_MAP_ARB: {
2288 if (iWidth != iHeight) {
2289 SetLastError(ERROR_INVALID_DATA);
2290 goto create_failed;
2292 object->texture_target = GL_TEXTURE_CUBE_MAP;
2293 object->texture_bind_target = GL_TEXTURE_BINDING_CUBE_MAP;
2294 break;
2296 case WGL_TEXTURE_1D_ARB: {
2297 if (1 != iHeight) {
2298 SetLastError(ERROR_INVALID_DATA);
2299 goto create_failed;
2301 object->texture_target = GL_TEXTURE_1D;
2302 object->texture_bind_target = GL_TEXTURE_BINDING_1D;
2303 break;
2305 case WGL_TEXTURE_2D_ARB: {
2306 object->texture_target = GL_TEXTURE_2D;
2307 object->texture_bind_target = GL_TEXTURE_BINDING_2D;
2308 break;
2310 case WGL_TEXTURE_RECTANGLE_NV: {
2311 object->texture_target = GL_TEXTURE_RECTANGLE_NV;
2312 object->texture_bind_target = GL_TEXTURE_BINDING_RECTANGLE_NV;
2313 break;
2315 default:
2316 ERR("Unknown texture target: %x\n", attr_v);
2317 SetLastError(ERROR_INVALID_DATA);
2318 goto create_failed;
2322 break;
2325 case WGL_MIPMAP_TEXTURE_ARB: {
2326 ++piAttribList;
2327 attr_v = *piAttribList;
2328 TRACE("WGL_render_texture Attribute: WGL_MIPMAP_TEXTURE_ARB as %x\n", attr_v);
2329 if (use_render_texture_ati) {
2330 PUSH2(attribs, GLX_MIPMAP_TEXTURE_ATI, attr_v);
2331 } else {
2332 if (!use_render_texture_emulation) {
2333 SetLastError(ERROR_INVALID_DATA);
2334 goto create_failed;
2337 break;
2340 ++piAttribList;
2343 PUSH1(attribs, None);
2344 object->drawable = pglXCreatePbuffer(gdi_display, fmt->fbconfig, attribs);
2345 TRACE("new Pbuffer drawable as %p\n", (void*) object->drawable);
2346 if (!object->drawable) {
2347 SetLastError(ERROR_NO_SYSTEM_RESOURCES);
2348 goto create_failed; /* unexpected error */
2350 TRACE("->(%p)\n", object);
2351 return (HPBUFFERARB) object;
2353 create_failed:
2354 HeapFree(GetProcessHeap(), 0, object);
2355 TRACE("->(FAILED)\n");
2356 return (HPBUFFERARB) NULL;
2360 * X11DRV_wglDestroyPbufferARB
2362 * WGL_ARB_pbuffer: wglDestroyPbufferARB
2364 static GLboolean WINAPI X11DRV_wglDestroyPbufferARB(HPBUFFERARB hPbuffer)
2366 Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer;
2367 TRACE("(%p)\n", hPbuffer);
2368 if (NULL == object) {
2369 SetLastError(ERROR_INVALID_HANDLE);
2370 return GL_FALSE;
2372 pglXDestroyPbuffer(object->display, object->drawable);
2373 HeapFree(GetProcessHeap(), 0, object);
2374 return GL_TRUE;
2378 * X11DRV_wglGetPbufferDCARB
2380 * WGL_ARB_pbuffer: wglGetPbufferDCARB
2381 * The function wglGetPbufferDCARB returns a device context for a pbuffer.
2382 * Gdi32 implements the part of this function which creates a device context.
2383 * This part associates the physDev with the X drawable of the pbuffer.
2385 HDC X11DRV_wglGetPbufferDCARB(X11DRV_PDEVICE *physDev, HPBUFFERARB hPbuffer)
2387 Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer;
2388 if (NULL == object) {
2389 SetLastError(ERROR_INVALID_HANDLE);
2390 return NULL;
2393 /* The function wglGetPbufferDCARB returns a DC to which the pbuffer can be connected.
2394 * All formats in our pixelformat list are compatible with each other and the main drawable. */
2395 physDev->current_pf = object->fmt->iPixelFormat;
2396 physDev->drawable = object->drawable;
2397 SetRect( &physDev->drawable_rect, 0, 0, object->width, object->height );
2398 physDev->dc_rect = physDev->drawable_rect;
2400 TRACE("(%p)->(%p)\n", hPbuffer, physDev->hdc);
2401 return physDev->hdc;
2405 * X11DRV_wglQueryPbufferARB
2407 * WGL_ARB_pbuffer: wglQueryPbufferARB
2409 static GLboolean WINAPI X11DRV_wglQueryPbufferARB(HPBUFFERARB hPbuffer, int iAttribute, int *piValue)
2411 Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer;
2412 TRACE("(%p, 0x%x, %p)\n", hPbuffer, iAttribute, piValue);
2413 if (NULL == object) {
2414 SetLastError(ERROR_INVALID_HANDLE);
2415 return GL_FALSE;
2417 switch (iAttribute) {
2418 case WGL_PBUFFER_WIDTH_ARB:
2419 pglXQueryDrawable(object->display, object->drawable, GLX_WIDTH, (unsigned int*) piValue);
2420 break;
2421 case WGL_PBUFFER_HEIGHT_ARB:
2422 pglXQueryDrawable(object->display, object->drawable, GLX_HEIGHT, (unsigned int*) piValue);
2423 break;
2425 case WGL_PBUFFER_LOST_ARB:
2426 /* GLX Pbuffers cannot be lost by default. We can support this by
2427 * setting GLX_PRESERVED_CONTENTS to False and using glXSelectEvent
2428 * to receive pixel buffer clobber events, however that may or may
2429 * not give any benefit */
2430 *piValue = GL_FALSE;
2431 break;
2433 case WGL_TEXTURE_FORMAT_ARB:
2434 if (use_render_texture_ati) {
2435 unsigned int tmp;
2436 int type = WGL_NO_TEXTURE_ARB;
2437 pglXQueryDrawable(object->display, object->drawable, GLX_TEXTURE_FORMAT_ATI, &tmp);
2438 switch (tmp) {
2439 case GLX_NO_TEXTURE_ATI: type = WGL_NO_TEXTURE_ARB; break ;
2440 case GLX_TEXTURE_RGB_ATI: type = WGL_TEXTURE_RGB_ARB; break ;
2441 case GLX_TEXTURE_RGBA_ATI: type = WGL_TEXTURE_RGBA_ARB; break ;
2443 *piValue = type;
2444 } else {
2445 if (!object->use_render_texture) {
2446 *piValue = WGL_NO_TEXTURE_ARB;
2447 } else {
2448 if (!use_render_texture_emulation) {
2449 SetLastError(ERROR_INVALID_HANDLE);
2450 return GL_FALSE;
2452 switch(object->use_render_texture) {
2453 case GL_RGB:
2454 *piValue = WGL_TEXTURE_RGB_ARB;
2455 break;
2456 case GL_RGBA:
2457 *piValue = WGL_TEXTURE_RGBA_ARB;
2458 break;
2459 /* WGL_FLOAT_COMPONENTS_NV */
2460 case GL_FLOAT_R_NV:
2461 *piValue = WGL_TEXTURE_FLOAT_R_NV;
2462 break;
2463 case GL_FLOAT_RG_NV:
2464 *piValue = WGL_TEXTURE_FLOAT_RG_NV;
2465 break;
2466 case GL_FLOAT_RGB_NV:
2467 *piValue = WGL_TEXTURE_FLOAT_RGB_NV;
2468 break;
2469 case GL_FLOAT_RGBA_NV:
2470 *piValue = WGL_TEXTURE_FLOAT_RGBA_NV;
2471 break;
2472 default:
2473 ERR("Unknown texture format: %x\n", object->use_render_texture);
2477 break;
2479 case WGL_TEXTURE_TARGET_ARB:
2480 if (use_render_texture_ati) {
2481 unsigned int tmp;
2482 int type = WGL_NO_TEXTURE_ARB;
2483 pglXQueryDrawable(object->display, object->drawable, GLX_TEXTURE_TARGET_ATI, &tmp);
2484 switch (tmp) {
2485 case GLX_NO_TEXTURE_ATI: type = WGL_NO_TEXTURE_ARB; break ;
2486 case GLX_TEXTURE_CUBE_MAP_ATI: type = WGL_TEXTURE_CUBE_MAP_ARB; break ;
2487 case GLX_TEXTURE_1D_ATI: type = WGL_TEXTURE_1D_ARB; break ;
2488 case GLX_TEXTURE_2D_ATI: type = WGL_TEXTURE_2D_ARB; break ;
2490 *piValue = type;
2491 } else {
2492 if (!object->texture_target) {
2493 *piValue = WGL_NO_TEXTURE_ARB;
2494 } else {
2495 if (!use_render_texture_emulation) {
2496 SetLastError(ERROR_INVALID_DATA);
2497 return GL_FALSE;
2499 switch (object->texture_target) {
2500 case GL_TEXTURE_1D: *piValue = WGL_TEXTURE_1D_ARB; break;
2501 case GL_TEXTURE_2D: *piValue = WGL_TEXTURE_2D_ARB; break;
2502 case GL_TEXTURE_CUBE_MAP: *piValue = WGL_TEXTURE_CUBE_MAP_ARB; break;
2503 case GL_TEXTURE_RECTANGLE_NV: *piValue = WGL_TEXTURE_RECTANGLE_NV; break;
2507 break;
2509 case WGL_MIPMAP_TEXTURE_ARB:
2510 if (use_render_texture_ati) {
2511 pglXQueryDrawable(object->display, object->drawable, GLX_MIPMAP_TEXTURE_ATI, (unsigned int*) piValue);
2512 } else {
2513 *piValue = GL_FALSE; /** don't support that */
2514 FIXME("unsupported WGL_ARB_render_texture attribute query for 0x%x\n", iAttribute);
2516 break;
2518 default:
2519 FIXME("unexpected attribute %x\n", iAttribute);
2520 break;
2523 return GL_TRUE;
2527 * X11DRV_wglReleasePbufferDCARB
2529 * WGL_ARB_pbuffer: wglReleasePbufferDCARB
2531 static int WINAPI X11DRV_wglReleasePbufferDCARB(HPBUFFERARB hPbuffer, HDC hdc)
2533 TRACE("(%p, %p)\n", hPbuffer, hdc);
2534 DeleteDC(hdc);
2535 return 0;
2539 * X11DRV_wglSetPbufferAttribARB
2541 * WGL_ARB_pbuffer: wglSetPbufferAttribARB
2543 static GLboolean WINAPI X11DRV_wglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int *piAttribList)
2545 Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer;
2546 WARN("(%p, %p): alpha-testing, report any problem\n", hPbuffer, piAttribList);
2547 if (NULL == object) {
2548 SetLastError(ERROR_INVALID_HANDLE);
2549 return GL_FALSE;
2551 if (!object->use_render_texture) {
2552 SetLastError(ERROR_INVALID_HANDLE);
2553 return GL_FALSE;
2555 if (!use_render_texture_ati && 1 == use_render_texture_emulation) {
2556 return GL_TRUE;
2558 if (NULL != pglXDrawableAttribATI) {
2559 if (use_render_texture_ati) {
2560 FIXME("Need conversion for GLX_ATI_render_texture\n");
2562 return pglXDrawableAttribATI(object->display, object->drawable, piAttribList);
2564 return GL_FALSE;
2568 * X11DRV_wglChoosePixelFormatARB
2570 * WGL_ARB_pixel_format: wglChoosePixelFormatARB
2572 static GLboolean WINAPI X11DRV_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats)
2574 int gl_test = 0;
2575 int attribs[256];
2576 int nAttribs = 0;
2577 GLXFBConfig* cfgs = NULL;
2578 int nCfgs = 0;
2579 UINT it;
2580 int fmt_id;
2581 WineGLPixelFormat *fmt;
2582 int pfmt_it = 0;
2583 int run;
2585 TRACE("(%p, %p, %p, %d, %p, %p): hackish\n", hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
2586 if (NULL != pfAttribFList) {
2587 FIXME("unused pfAttribFList\n");
2590 nAttribs = ConvertAttribWGLtoGLX(piAttribIList, attribs, NULL);
2591 if (-1 == nAttribs) {
2592 WARN("Cannot convert WGL to GLX attributes\n");
2593 return GL_FALSE;
2595 PUSH1(attribs, None);
2597 /* Search for FB configurations matching the requirements in attribs */
2598 cfgs = pglXChooseFBConfig(gdi_display, DefaultScreen(gdi_display), attribs, &nCfgs);
2599 if (NULL == cfgs) {
2600 WARN("Compatible Pixel Format not found\n");
2601 return GL_FALSE;
2604 /* Loop through all matching formats and check if they are suitable.
2605 * Note that this function should at max return nMaxFormats different formats */
2606 for(run=0; run < 2; run++)
2608 for (it = 0; it < nCfgs; ++it) {
2609 gl_test = pglXGetFBConfigAttrib(gdi_display, cfgs[it], GLX_FBCONFIG_ID, &fmt_id);
2610 if (gl_test) {
2611 ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
2612 continue;
2615 /* Search for the format in our list of compatible formats */
2616 fmt = ConvertPixelFormatGLXtoWGL(gdi_display, fmt_id);
2617 if(!fmt)
2618 continue;
2620 /* During the first run we only want onscreen formats and during the second only offscreen 'XOR' */
2621 if( ((run == 0) && fmt->offscreenOnly) || ((run == 1) && !fmt->offscreenOnly) )
2622 continue;
2624 if(pfmt_it < nMaxFormats) {
2625 piFormats[pfmt_it] = fmt->iPixelFormat;
2626 TRACE("at %d/%d found FBCONFIG_ID 0x%x (%d)\n", it + 1, nCfgs, fmt_id, piFormats[pfmt_it]);
2628 pfmt_it++;
2632 *nNumFormats = pfmt_it;
2633 /** free list */
2634 XFree(cfgs);
2635 return GL_TRUE;
2639 * X11DRV_wglGetPixelFormatAttribivARB
2641 * WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
2643 static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues)
2645 UINT i;
2646 WineGLPixelFormat *fmt = NULL;
2647 int hTest;
2648 int tmp;
2649 int curGLXAttr = 0;
2650 int nWGLFormats = 0;
2652 TRACE("(%p, %d, %d, %d, %p, %p)\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
2654 if (0 < iLayerPlane) {
2655 FIXME("unsupported iLayerPlane(%d) > 0, returns FALSE\n", iLayerPlane);
2656 return GL_FALSE;
2659 /* Convert the WGL pixelformat to a GLX one, if this fails then most likely the iPixelFormat isn't supoprted.
2660 * We don't have to fail yet as a program can specify an invaled iPixelFormat (lets say 0) if it wants to query
2661 * the number of supported WGL formats. Whether the iPixelFormat is valid is handled in the for-loop below. */
2662 fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, TRUE /* Offscreen */, &nWGLFormats);
2663 if(!fmt) {
2664 WARN("Unable to convert iPixelFormat %d to a GLX one!\n", iPixelFormat);
2667 for (i = 0; i < nAttributes; ++i) {
2668 const int curWGLAttr = piAttributes[i];
2669 TRACE("pAttr[%d] = %x\n", i, curWGLAttr);
2671 switch (curWGLAttr) {
2672 case WGL_NUMBER_PIXEL_FORMATS_ARB:
2673 piValues[i] = nWGLFormats;
2674 continue;
2676 case WGL_SUPPORT_OPENGL_ARB:
2677 piValues[i] = GL_TRUE;
2678 continue;
2680 case WGL_ACCELERATION_ARB:
2681 curGLXAttr = GLX_CONFIG_CAVEAT;
2682 if (!fmt) goto pix_error;
2683 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
2684 if (hTest) goto get_error;
2685 switch (tmp) {
2686 case GLX_NONE: piValues[i] = WGL_FULL_ACCELERATION_ARB; break;
2687 case GLX_SLOW_CONFIG: piValues[i] = WGL_GENERIC_ACCELERATION_ARB; break;
2688 case GLX_NON_CONFORMANT_CONFIG: piValues[i] = WGL_FULL_ACCELERATION_ARB; break;
2689 default:
2690 ERR("unexpected Config Caveat(%x)\n", tmp);
2691 piValues[i] = WGL_NO_ACCELERATION_ARB;
2693 continue;
2695 case WGL_TRANSPARENT_ARB:
2696 curGLXAttr = GLX_TRANSPARENT_TYPE;
2697 if (!fmt) goto pix_error;
2698 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
2699 if (hTest) goto get_error;
2700 piValues[i] = GL_FALSE;
2701 if (GLX_NONE != tmp) piValues[i] = GL_TRUE;
2702 continue;
2704 case WGL_PIXEL_TYPE_ARB:
2705 curGLXAttr = GLX_RENDER_TYPE;
2706 if (!fmt) goto pix_error;
2707 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
2708 if (hTest) goto get_error;
2709 TRACE("WGL_PIXEL_TYPE_ARB: GLX_RENDER_TYPE = 0x%x\n", tmp);
2710 if (tmp & GLX_RGBA_BIT) { piValues[i] = WGL_TYPE_RGBA_ARB; }
2711 else if (tmp & GLX_COLOR_INDEX_BIT) { piValues[i] = WGL_TYPE_COLORINDEX_ARB; }
2712 else if (tmp & GLX_RGBA_FLOAT_BIT) { piValues[i] = WGL_TYPE_RGBA_FLOAT_ATI; }
2713 else if (tmp & GLX_RGBA_FLOAT_ATI_BIT) { piValues[i] = WGL_TYPE_RGBA_FLOAT_ATI; }
2714 else {
2715 ERR("unexpected RenderType(%x)\n", tmp);
2716 piValues[i] = WGL_TYPE_RGBA_ARB;
2718 continue;
2720 case WGL_COLOR_BITS_ARB:
2721 curGLXAttr = GLX_BUFFER_SIZE;
2722 break;
2724 case WGL_BIND_TO_TEXTURE_RGB_ARB:
2725 if (use_render_texture_ati) {
2726 curGLXAttr = GLX_BIND_TO_TEXTURE_RGB_ATI;
2727 break;
2729 case WGL_BIND_TO_TEXTURE_RGBA_ARB:
2730 if (use_render_texture_ati) {
2731 curGLXAttr = GLX_BIND_TO_TEXTURE_RGBA_ATI;
2732 break;
2734 if (!use_render_texture_emulation) {
2735 piValues[i] = GL_FALSE;
2736 continue;
2738 curGLXAttr = GLX_RENDER_TYPE;
2739 if (!fmt) goto pix_error;
2740 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
2741 if (hTest) goto get_error;
2742 if (GLX_COLOR_INDEX_BIT == tmp) {
2743 piValues[i] = GL_FALSE;
2744 continue;
2746 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &tmp);
2747 if (hTest) goto get_error;
2748 piValues[i] = (tmp & GLX_PBUFFER_BIT) ? GL_TRUE : GL_FALSE;
2749 continue;
2751 case WGL_BLUE_BITS_ARB:
2752 curGLXAttr = GLX_BLUE_SIZE;
2753 break;
2754 case WGL_RED_BITS_ARB:
2755 curGLXAttr = GLX_RED_SIZE;
2756 break;
2757 case WGL_GREEN_BITS_ARB:
2758 curGLXAttr = GLX_GREEN_SIZE;
2759 break;
2760 case WGL_ALPHA_BITS_ARB:
2761 curGLXAttr = GLX_ALPHA_SIZE;
2762 break;
2763 case WGL_DEPTH_BITS_ARB:
2764 curGLXAttr = GLX_DEPTH_SIZE;
2765 break;
2766 case WGL_STENCIL_BITS_ARB:
2767 curGLXAttr = GLX_STENCIL_SIZE;
2768 break;
2769 case WGL_DOUBLE_BUFFER_ARB:
2770 curGLXAttr = GLX_DOUBLEBUFFER;
2771 break;
2772 case WGL_STEREO_ARB:
2773 curGLXAttr = GLX_STEREO;
2774 break;
2775 case WGL_AUX_BUFFERS_ARB:
2776 curGLXAttr = GLX_AUX_BUFFERS;
2777 break;
2779 case WGL_SUPPORT_GDI_ARB:
2780 if (!fmt) goto pix_error;
2781 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &tmp);
2782 if (hTest) goto get_error;
2783 if(tmp) {
2784 piValues[i] = GL_FALSE;
2785 continue;
2787 curGLXAttr = GLX_X_RENDERABLE;
2788 break;
2790 case WGL_DRAW_TO_WINDOW_ARB:
2791 case WGL_DRAW_TO_BITMAP_ARB:
2792 case WGL_DRAW_TO_PBUFFER_ARB:
2793 if (!fmt) goto pix_error;
2794 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &tmp);
2795 if (hTest) goto get_error;
2796 if((curWGLAttr == WGL_DRAW_TO_WINDOW_ARB && (tmp&GLX_WINDOW_BIT)) ||
2797 (curWGLAttr == WGL_DRAW_TO_BITMAP_ARB && (tmp&GLX_PIXMAP_BIT)) ||
2798 (curWGLAttr == WGL_DRAW_TO_PBUFFER_ARB && (tmp&GLX_PBUFFER_BIT)))
2799 piValues[i] = GL_TRUE;
2800 else
2801 piValues[i] = GL_FALSE;
2802 continue;
2804 case WGL_PBUFFER_LARGEST_ARB:
2805 curGLXAttr = GLX_LARGEST_PBUFFER;
2806 break;
2808 case WGL_SAMPLE_BUFFERS_ARB:
2809 curGLXAttr = GLX_SAMPLE_BUFFERS_ARB;
2810 break;
2812 case WGL_SAMPLES_ARB:
2813 curGLXAttr = GLX_SAMPLES_ARB;
2814 break;
2816 case WGL_FLOAT_COMPONENTS_NV:
2817 curGLXAttr = GLX_FLOAT_COMPONENTS_NV;
2818 break;
2820 case WGL_ACCUM_RED_BITS_ARB:
2821 curGLXAttr = GLX_ACCUM_RED_SIZE;
2822 break;
2823 case WGL_ACCUM_GREEN_BITS_ARB:
2824 curGLXAttr = GLX_ACCUM_GREEN_SIZE;
2825 break;
2826 case WGL_ACCUM_BLUE_BITS_ARB:
2827 curGLXAttr = GLX_ACCUM_BLUE_SIZE;
2828 break;
2829 case WGL_ACCUM_ALPHA_BITS_ARB:
2830 curGLXAttr = GLX_ACCUM_ALPHA_SIZE;
2831 break;
2832 case WGL_ACCUM_BITS_ARB:
2833 if (!fmt) goto pix_error;
2834 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_RED_SIZE, &tmp);
2835 if (hTest) goto get_error;
2836 piValues[i] = tmp;
2837 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_GREEN_SIZE, &tmp);
2838 if (hTest) goto get_error;
2839 piValues[i] += tmp;
2840 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &tmp);
2841 if (hTest) goto get_error;
2842 piValues[i] += tmp;
2843 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &tmp);
2844 if (hTest) goto get_error;
2845 piValues[i] += tmp;
2846 continue;
2848 default:
2849 FIXME("unsupported %x WGL Attribute\n", curWGLAttr);
2852 /* Retrieve a GLX FBConfigAttrib when the attribute to query is valid and
2853 * iPixelFormat != 0. When iPixelFormat is 0 the only value which makes
2854 * sense to query is WGL_NUMBER_PIXEL_FORMATS_ARB.
2856 * TODO: properly test the behavior of wglGetPixelFormatAttrib*v on Windows
2857 * and check which options can work using iPixelFormat=0 and which not.
2858 * A problem would be that this function is an extension. This would
2859 * mean that the behavior could differ between different vendors (ATI, Nvidia, ..).
2861 if (0 != curGLXAttr && iPixelFormat != 0) {
2862 if (!fmt) goto pix_error;
2863 hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, piValues + i);
2864 if (hTest) goto get_error;
2865 curGLXAttr = 0;
2866 } else {
2867 piValues[i] = GL_FALSE;
2870 return GL_TRUE;
2872 get_error:
2873 ERR("(%p): unexpected failure on GetFBConfigAttrib(%x) returns FALSE\n", hdc, curGLXAttr);
2874 return GL_FALSE;
2876 pix_error:
2877 ERR("(%p): unexpected iPixelFormat(%d) vs nFormats(%d), returns FALSE\n", hdc, iPixelFormat, nWGLFormats);
2878 return GL_FALSE;
2882 * X11DRV_wglGetPixelFormatAttribfvARB
2884 * WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
2886 static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
2888 int *attr;
2889 int ret;
2890 int i;
2892 TRACE("(%p, %d, %d, %d, %p, %p)\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
2894 /* Allocate a temporary array to store integer values */
2895 attr = HeapAlloc(GetProcessHeap(), 0, nAttributes * sizeof(int));
2896 if (!attr) {
2897 ERR("couldn't allocate %d array\n", nAttributes);
2898 return GL_FALSE;
2901 /* Piggy-back on wglGetPixelFormatAttribivARB */
2902 ret = X11DRV_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
2903 if (ret) {
2904 /* Convert integer values to float. Should also check for attributes
2905 that can give decimal values here */
2906 for (i=0; i<nAttributes;i++) {
2907 pfValues[i] = attr[i];
2911 HeapFree(GetProcessHeap(), 0, attr);
2912 return ret;
2916 * X11DRV_wglBindTexImageARB
2918 * WGL_ARB_render_texture: wglBindTexImageARB
2920 static GLboolean WINAPI X11DRV_wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)
2922 Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer;
2923 TRACE("(%p, %d)\n", hPbuffer, iBuffer);
2924 if (NULL == object) {
2925 SetLastError(ERROR_INVALID_HANDLE);
2926 return GL_FALSE;
2928 if (!object->use_render_texture) {
2929 SetLastError(ERROR_INVALID_HANDLE);
2930 return GL_FALSE;
2933 if (!use_render_texture_ati && 1 == use_render_texture_emulation) {
2934 static int init = 0;
2935 int prev_binded_texture = 0;
2936 GLXContext prev_context = pglXGetCurrentContext();
2937 Drawable prev_drawable = pglXGetCurrentDrawable();
2938 GLXContext tmp_context;
2940 /* Our render_texture emulation is basic and lacks some features (1D/Cube support).
2941 This is mostly due to lack of demos/games using them. Further the use of glReadPixels
2942 isn't ideal performance wise but I wasn't able to get other ways working.
2944 if(!init) {
2945 init = 1; /* Only show the FIXME once for performance reasons */
2946 FIXME("partial stub!\n");
2949 TRACE("drawable=%p, context=%p\n", (void*)object->drawable, prev_context);
2950 tmp_context = pglXCreateNewContext(gdi_display, object->fmt->fbconfig, object->fmt->render_type, prev_context, True);
2952 pglGetIntegerv(object->texture_bind_target, &prev_binded_texture);
2954 /* Switch to our pbuffer */
2955 pglXMakeCurrent(gdi_display, object->drawable, tmp_context);
2957 /* Make sure that the prev_binded_texture is set as the current texture state isn't shared between contexts.
2958 * After that upload the pbuffer texture data. */
2959 pglBindTexture(object->texture_target, prev_binded_texture);
2960 pglCopyTexImage2D(object->texture_target, 0, object->use_render_texture, 0, 0, object->width, object->height, 0);
2962 /* Switch back to the original drawable and upload the pbuffer-texture */
2963 pglXMakeCurrent(object->display, prev_drawable, prev_context);
2964 pglXDestroyContext(gdi_display, tmp_context);
2965 return GL_TRUE;
2968 if (NULL != pglXBindTexImageATI) {
2969 int buffer;
2971 switch(iBuffer)
2973 case WGL_FRONT_LEFT_ARB:
2974 buffer = GLX_FRONT_LEFT_ATI;
2975 break;
2976 case WGL_FRONT_RIGHT_ARB:
2977 buffer = GLX_FRONT_RIGHT_ATI;
2978 break;
2979 case WGL_BACK_LEFT_ARB:
2980 buffer = GLX_BACK_LEFT_ATI;
2981 break;
2982 case WGL_BACK_RIGHT_ARB:
2983 buffer = GLX_BACK_RIGHT_ATI;
2984 break;
2985 default:
2986 ERR("Unknown iBuffer=%#x\n", iBuffer);
2987 return FALSE;
2990 /* In the sample 'ogl_offscreen_rendering_3' from codesampler.net I get garbage on the screen.
2991 * I'm not sure if that's a bug in the ATI extension or in the program. I think that the program
2992 * expected a single buffering format since it didn't ask for double buffering. A buffer swap
2993 * fixed the program. I don't know what the correct behavior is. On the other hand that demo
2994 * works fine using our pbuffer emulation path.
2996 return pglXBindTexImageATI(object->display, object->drawable, buffer);
2998 return GL_FALSE;
3002 * X11DRV_wglReleaseTexImageARB
3004 * WGL_ARB_render_texture: wglReleaseTexImageARB
3006 static GLboolean WINAPI X11DRV_wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)
3008 Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer;
3009 TRACE("(%p, %d)\n", hPbuffer, iBuffer);
3010 if (NULL == object) {
3011 SetLastError(ERROR_INVALID_HANDLE);
3012 return GL_FALSE;
3014 if (!object->use_render_texture) {
3015 SetLastError(ERROR_INVALID_HANDLE);
3016 return GL_FALSE;
3018 if (!use_render_texture_ati && 1 == use_render_texture_emulation) {
3019 return GL_TRUE;
3021 if (NULL != pglXReleaseTexImageATI) {
3022 int buffer;
3024 switch(iBuffer)
3026 case WGL_FRONT_LEFT_ARB:
3027 buffer = GLX_FRONT_LEFT_ATI;
3028 break;
3029 case WGL_FRONT_RIGHT_ARB:
3030 buffer = GLX_FRONT_RIGHT_ATI;
3031 break;
3032 case WGL_BACK_LEFT_ARB:
3033 buffer = GLX_BACK_LEFT_ATI;
3034 break;
3035 case WGL_BACK_RIGHT_ARB:
3036 buffer = GLX_BACK_RIGHT_ATI;
3037 break;
3038 default:
3039 ERR("Unknown iBuffer=%#x\n", iBuffer);
3040 return FALSE;
3042 return pglXReleaseTexImageATI(object->display, object->drawable, buffer);
3044 return GL_FALSE;
3048 * X11DRV_wglGetExtensionsStringEXT
3050 * WGL_EXT_extensions_string: wglGetExtensionsStringEXT
3052 static const char * WINAPI X11DRV_wglGetExtensionsStringEXT(void) {
3053 TRACE("() returning \"%s\"\n", WineGLInfo.wglExtensions);
3054 return WineGLInfo.wglExtensions;
3058 * X11DRV_wglGetSwapIntervalEXT
3060 * WGL_EXT_swap_control: wglGetSwapIntervalEXT
3062 static int WINAPI X11DRV_wglGetSwapIntervalEXT(VOID) {
3063 FIXME("(),stub!\n");
3064 return swap_interval;
3068 * X11DRV_wglSwapIntervalEXT
3070 * WGL_EXT_swap_control: wglSwapIntervalEXT
3072 static BOOL WINAPI X11DRV_wglSwapIntervalEXT(int interval) {
3073 TRACE("(%d)\n", interval);
3074 swap_interval = interval;
3075 if (NULL != pglXSwapIntervalSGI) {
3076 return 0 == pglXSwapIntervalSGI(interval);
3078 WARN("(): GLX_SGI_swap_control extension seems not supported\n");
3079 return TRUE;
3083 * X11DRV_wglAllocateMemoryNV
3085 * WGL_NV_vertex_array_range: wglAllocateMemoryNV
3087 static void* WINAPI X11DRV_wglAllocateMemoryNV(GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority) {
3088 TRACE("(%d, %f, %f, %f)\n", size, readfreq, writefreq, priority );
3089 if (pglXAllocateMemoryNV == NULL)
3090 return NULL;
3092 return pglXAllocateMemoryNV(size, readfreq, writefreq, priority);
3096 * X11DRV_wglFreeMemoryNV
3098 * WGL_NV_vertex_array_range: wglFreeMemoryNV
3100 static void WINAPI X11DRV_wglFreeMemoryNV(GLvoid* pointer) {
3101 TRACE("(%p)\n", pointer);
3102 if (pglXFreeMemoryNV == NULL)
3103 return;
3105 pglXFreeMemoryNV(pointer);
3109 * glxRequireVersion (internal)
3111 * Check if the supported GLX version matches requiredVersion.
3113 static BOOL glxRequireVersion(int requiredVersion)
3115 /* Both requiredVersion and glXVersion[1] contains the minor GLX version */
3116 if(requiredVersion <= WineGLInfo.glxVersion[1])
3117 return TRUE;
3119 return FALSE;
3122 static BOOL glxRequireExtension(const char *requiredExtension)
3124 if (strstr(WineGLInfo.glxExtensions, requiredExtension) == NULL) {
3125 return FALSE;
3128 return TRUE;
3131 static void register_extension_string(const char *ext)
3133 if (WineGLInfo.wglExtensions[0])
3134 strcat(WineGLInfo.wglExtensions, " ");
3135 strcat(WineGLInfo.wglExtensions, ext);
3137 TRACE("'%s'\n", ext);
3140 static BOOL register_extension(const WineGLExtension * ext)
3142 int i;
3144 assert( WineGLExtensionListSize < MAX_EXTENSIONS );
3145 WineGLExtensionList[WineGLExtensionListSize++] = ext;
3147 register_extension_string(ext->extName);
3149 for (i = 0; ext->extEntryPoints[i].funcName; ++i)
3150 TRACE(" - '%s'\n", ext->extEntryPoints[i].funcName);
3152 return TRUE;
3155 static const WineGLExtension WGL_internal_functions =
3159 { "wglDisable", X11DRV_wglDisable },
3160 { "wglEnable", X11DRV_wglEnable },
3161 { "wglGetIntegerv", X11DRV_wglGetIntegerv },
3162 { "wglIsEnabled", X11DRV_wglIsEnabled },
3163 { "wglScissor", X11DRV_wglScissor },
3164 { "wglViewport", X11DRV_wglViewport },
3169 static const WineGLExtension WGL_ARB_extensions_string =
3171 "WGL_ARB_extensions_string",
3173 { "wglGetExtensionsStringARB", X11DRV_wglGetExtensionsStringARB },
3177 static const WineGLExtension WGL_ARB_make_current_read =
3179 "WGL_ARB_make_current_read",
3181 { "wglGetCurrentReadDCARB", X11DRV_wglGetCurrentReadDCARB },
3182 { "wglMakeContextCurrentARB", X11DRV_wglMakeContextCurrentARB },
3186 static const WineGLExtension WGL_ARB_multisample =
3188 "WGL_ARB_multisample",
3191 static const WineGLExtension WGL_ARB_pbuffer =
3193 "WGL_ARB_pbuffer",
3195 { "wglCreatePbufferARB", X11DRV_wglCreatePbufferARB },
3196 { "wglDestroyPbufferARB", X11DRV_wglDestroyPbufferARB },
3197 { "wglGetPbufferDCARB", X11DRV_wglGetPbufferDCARB },
3198 { "wglQueryPbufferARB", X11DRV_wglQueryPbufferARB },
3199 { "wglReleasePbufferDCARB", X11DRV_wglReleasePbufferDCARB },
3200 { "wglSetPbufferAttribARB", X11DRV_wglSetPbufferAttribARB },
3204 static const WineGLExtension WGL_ARB_pixel_format =
3206 "WGL_ARB_pixel_format",
3208 { "wglChoosePixelFormatARB", X11DRV_wglChoosePixelFormatARB },
3209 { "wglGetPixelFormatAttribfvARB", X11DRV_wglGetPixelFormatAttribfvARB },
3210 { "wglGetPixelFormatAttribivARB", X11DRV_wglGetPixelFormatAttribivARB },
3214 static const WineGLExtension WGL_ARB_render_texture =
3216 "WGL_ARB_render_texture",
3218 { "wglBindTexImageARB", X11DRV_wglBindTexImageARB },
3219 { "wglReleaseTexImageARB", X11DRV_wglReleaseTexImageARB },
3223 static const WineGLExtension WGL_EXT_extensions_string =
3225 "WGL_EXT_extensions_string",
3227 { "wglGetExtensionsStringEXT", X11DRV_wglGetExtensionsStringEXT },
3231 static const WineGLExtension WGL_EXT_swap_control =
3233 "WGL_EXT_swap_control",
3235 { "wglSwapIntervalEXT", X11DRV_wglSwapIntervalEXT },
3236 { "wglGetSwapIntervalEXT", X11DRV_wglGetSwapIntervalEXT },
3240 static const WineGLExtension WGL_NV_vertex_array_range =
3242 "WGL_NV_vertex_array_range",
3244 { "wglAllocateMemoryNV", X11DRV_wglAllocateMemoryNV },
3245 { "wglFreeMemoryNV", X11DRV_wglFreeMemoryNV },
3250 * X11DRV_WineGL_LoadExtensions
3252 static void X11DRV_WineGL_LoadExtensions(void)
3254 WineGLInfo.wglExtensions[0] = 0;
3256 /* Load Wine internal functions */
3257 register_extension(&WGL_internal_functions);
3259 /* ARB Extensions */
3261 if(glxRequireExtension("GLX_ARB_fbconfig_float"))
3263 register_extension_string("WGL_ARB_pixel_format_float");
3264 register_extension_string("WGL_ATI_pixel_format_float");
3267 register_extension(&WGL_ARB_extensions_string);
3269 if (glxRequireVersion(3))
3270 register_extension(&WGL_ARB_make_current_read);
3272 if (glxRequireExtension("GLX_ARB_multisample"))
3273 register_extension(&WGL_ARB_multisample);
3275 /* In general pbuffer functionality requires support in the X-server. The functionality is
3276 * available either when the GLX_SGIX_pbuffer is present or when the GLX server version is 1.3.
3277 * All display drivers except for Nvidia's use the GLX module from Xfree86/Xorg which only
3278 * supports GLX 1.2. The endresult is that only Nvidia's drivers support pbuffers.
3280 * The only other drive which has pbuffer support is Ati's FGLRX driver. They provide clientside GLX 1.3 support
3281 * without support in the X-server (which other Mesa based drivers require).
3283 * Support pbuffers when the GLX version is 1.3 and GLX_SGIX_pbuffer is available. Further pbuffers can
3284 * also be supported when GLX_ATI_render_texture is available. This extension depends on pbuffers, so when it
3285 * is available pbuffers must be available too. */
3286 if ( (glxRequireVersion(3) && glxRequireExtension("GLX_SGIX_pbuffer")) || glxRequireExtension("GLX_ATI_render_texture"))
3287 register_extension(&WGL_ARB_pbuffer);
3289 register_extension(&WGL_ARB_pixel_format);
3291 /* Support WGL_ARB_render_texture when there's support or pbuffer based emulation */
3292 if (glxRequireExtension("GLX_ATI_render_texture") ||
3293 glxRequireExtension("GLX_ARB_render_texture") ||
3294 (glxRequireVersion(3) && glxRequireExtension("GLX_SGIX_pbuffer") && use_render_texture_emulation))
3296 register_extension(&WGL_ARB_render_texture);
3298 /* The WGL version of GLX_NV_float_buffer requires render_texture */
3299 if(glxRequireExtension("GLX_NV_float_buffer"))
3300 register_extension_string("WGL_NV_float_buffer");
3302 /* Again there's no GLX equivalent for this extension, so depend on the required GL extension */
3303 if(strstr(WineGLInfo.glExtensions, "GL_NV_texture_rectangle") != NULL)
3304 register_extension_string("WGL_NV_texture_rectangle");
3307 /* EXT Extensions */
3309 register_extension(&WGL_EXT_extensions_string);
3311 /* Load this extension even when it isn't backed by a GLX extension because it is has been around for ages.
3312 * Games like Call of Duty and K.O.T.O.R. rely on it. Further our emulation is good enough. */
3313 register_extension(&WGL_EXT_swap_control);
3315 /* The OpenGL extension GL_NV_vertex_array_range adds wgl/glX functions which aren't exported as 'real' wgl/glX extensions. */
3316 if(strstr(WineGLInfo.glExtensions, "GL_NV_vertex_array_range") != NULL)
3317 register_extension(&WGL_NV_vertex_array_range);
3321 static XID create_glxpixmap(X11DRV_PDEVICE *physDev)
3323 GLXPixmap ret;
3324 XVisualInfo *vis;
3325 XVisualInfo template;
3326 int num;
3328 wine_tsx11_lock();
3330 /* Retrieve the visualid from our main visual which is the only visual we can use */
3331 template.visualid = XVisualIDFromVisual(visual);
3332 vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
3334 ret = pglXCreateGLXPixmap(gdi_display, vis, physDev->bitmap->pixmap);
3335 XFree(vis);
3336 wine_tsx11_unlock();
3337 TRACE("return %lx\n", ret);
3338 return ret;
3341 Drawable get_glxdrawable(X11DRV_PDEVICE *physDev)
3343 Drawable ret;
3345 if(physDev->bitmap)
3347 if (physDev->bitmap->hbitmap == BITMAP_stock_phys_bitmap.hbitmap)
3348 ret = physDev->drawable; /* PBuffer */
3349 else
3351 if(!physDev->bitmap->glxpixmap)
3352 physDev->bitmap->glxpixmap = create_glxpixmap(physDev);
3353 ret = physDev->bitmap->glxpixmap;
3356 else
3357 ret = physDev->drawable;
3358 return ret;
3361 BOOL destroy_glxpixmap(XID glxpixmap)
3363 wine_tsx11_lock();
3364 pglXDestroyGLXPixmap(gdi_display, glxpixmap);
3365 wine_tsx11_unlock();
3366 return TRUE;
3370 * X11DRV_SwapBuffers
3372 * Swap the buffers of this DC
3374 BOOL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev)
3376 GLXDrawable drawable;
3377 if (!has_opengl()) {
3378 ERR("No libGL on this box - disabling OpenGL support !\n");
3379 return 0;
3382 TRACE_(opengl)("(%p)\n", physDev);
3384 drawable = get_glxdrawable(physDev);
3385 wine_tsx11_lock();
3386 pglXSwapBuffers(gdi_display, drawable);
3387 wine_tsx11_unlock();
3389 /* FPS support */
3390 if (TRACE_ON(fps))
3392 static long prev_time, frames;
3394 DWORD time = GetTickCount();
3395 frames++;
3396 /* every 1.5 seconds */
3397 if (time - prev_time > 1500) {
3398 TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
3399 prev_time = time;
3400 frames = 0;
3404 return TRUE;
3407 /***********************************************************************
3408 * X11DRV_setup_opengl_visual
3410 * Setup the default visual used for OpenGL and Direct3D, and the desktop
3411 * window (if it exists). If OpenGL isn't available, the visual is simply
3412 * set to the default visual for the display
3414 XVisualInfo *X11DRV_setup_opengl_visual( Display *display )
3416 XVisualInfo *visual = NULL;
3417 int i;
3419 /* In order to support OpenGL or D3D, we require a double-buffered visual and stencil buffer support,
3420 * D3D and some applications can make use of aux buffers.
3422 int visualProperties[][11] = {
3423 { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_AUX_BUFFERS, 1, None },
3424 { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8, GLX_ALPHA_SIZE, 8, None },
3425 { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, GLX_STENCIL_SIZE, 8, None },
3426 { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, None },
3429 if (!has_opengl())
3430 return NULL;
3432 wine_tsx11_lock();
3433 for (i = 0; i < sizeof(visualProperties)/sizeof(visualProperties[0]); ++i) {
3434 visual = pglXChooseVisual(display, DefaultScreen(display), visualProperties[i]);
3435 if (visual)
3436 break;
3438 wine_tsx11_unlock();
3440 if (visual)
3441 TRACE("Visual ID %lx Chosen\n", visual->visualid);
3442 else
3443 WARN("No suitable visual found\n");
3445 return visual;
3448 #else /* no OpenGL includes */
3450 /***********************************************************************
3451 * ChoosePixelFormat (X11DRV.@)
3453 int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev,
3454 const PIXELFORMATDESCRIPTOR *ppfd) {
3455 ERR("No OpenGL support compiled in.\n");
3457 return 0;
3460 /***********************************************************************
3461 * DescribePixelFormat (X11DRV.@)
3463 int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev,
3464 int iPixelFormat,
3465 UINT nBytes,
3466 PIXELFORMATDESCRIPTOR *ppfd) {
3467 ERR("No OpenGL support compiled in.\n");
3469 return 0;
3472 /***********************************************************************
3473 * GetPixelFormat (X11DRV.@)
3475 int X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) {
3476 ERR("No OpenGL support compiled in.\n");
3478 return 0;
3481 /***********************************************************************
3482 * SetPixelFormat (X11DRV.@)
3484 BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev,
3485 int iPixelFormat,
3486 const PIXELFORMATDESCRIPTOR *ppfd) {
3487 ERR("No OpenGL support compiled in.\n");
3489 return FALSE;
3492 /***********************************************************************
3493 * SwapBuffers (X11DRV.@)
3495 BOOL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev) {
3496 ERR_(opengl)("No OpenGL support compiled in.\n");
3498 return FALSE;
3502 * X11DRV_wglCreateContext
3504 * For OpenGL32 wglCreateContext.
3506 HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) {
3507 ERR_(opengl)("No OpenGL support compiled in.\n");
3508 return NULL;
3512 * X11DRV_wglDeleteContext
3514 * For OpenGL32 wglDeleteContext.
3516 BOOL X11DRV_wglDeleteContext(HGLRC hglrc) {
3517 ERR_(opengl)("No OpenGL support compiled in.\n");
3518 return FALSE;
3522 * X11DRV_wglGetProcAddress
3524 * For OpenGL32 wglGetProcAddress.
3526 PROC X11DRV_wglGetProcAddress(LPCSTR lpszProc) {
3527 ERR_(opengl)("No OpenGL support compiled in.\n");
3528 return NULL;
3531 HDC X11DRV_wglGetPbufferDCARB(X11DRV_PDEVICE *hDevice, void *hPbuffer)
3533 ERR_(opengl)("No OpenGL support compiled in.\n");
3534 return NULL;
3537 BOOL X11DRV_wglMakeContextCurrentARB(X11DRV_PDEVICE* hDrawDev, X11DRV_PDEVICE* hReadDev, HGLRC hglrc) {
3538 ERR_(opengl)("No OpenGL support compiled in.\n");
3539 return FALSE;
3543 * X11DRV_wglMakeCurrent
3545 * For OpenGL32 wglMakeCurrent.
3547 BOOL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) {
3548 ERR_(opengl)("No OpenGL support compiled in.\n");
3549 return FALSE;
3553 * X11DRV_wglShareLists
3555 * For OpenGL32 wglShaderLists.
3557 BOOL X11DRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) {
3558 ERR_(opengl)("No OpenGL support compiled in.\n");
3559 return FALSE;
3563 * X11DRV_wglUseFontBitmapsA
3565 * For OpenGL32 wglUseFontBitmapsA.
3567 BOOL X11DRV_wglUseFontBitmapsA(X11DRV_PDEVICE *physDev, DWORD first, DWORD count, DWORD listBase)
3569 ERR_(opengl)("No OpenGL support compiled in.\n");
3570 return FALSE;
3574 * X11DRV_wglUseFontBitmapsW
3576 * For OpenGL32 wglUseFontBitmapsW.
3578 BOOL X11DRV_wglUseFontBitmapsW(X11DRV_PDEVICE *physDev, DWORD first, DWORD count, DWORD listBase)
3580 ERR_(opengl)("No OpenGL support compiled in.\n");
3581 return FALSE;
3584 XVisualInfo *X11DRV_setup_opengl_visual( Display *display )
3586 return NULL;
3589 Drawable get_glxdrawable(X11DRV_PDEVICE *physDev)
3591 return 0;
3594 BOOL destroy_glxpixmap(XID glxpixmap)
3596 return FALSE;
3599 #endif /* defined(HAVE_OPENGL) */