2 * X11DRV OpenGL functions
4 * Copyright 2000 Lionel Ulmer
5 * Copyright 2006 Roderick Colenbrander
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
29 #include "wine/library.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
33 WINE_DECLARE_DEBUG_CHANNEL(opengl);
35 #if defined(HAVE_GL_GL_H) && defined(HAVE_GL_GLX_H)
47 #ifdef HAVE_GL_GLEXT_H
48 # include <GL/glext.h>
55 /* Redefines the constants */
56 #define CALLBACK __stdcall
57 #define WINAPI __stdcall
58 #define APIENTRY WINAPI
60 WINE_DECLARE_DEBUG_CHANNEL(fps);
62 typedef struct wine_glcontext {
69 struct wine_glcontext *next;
70 struct wine_glcontext *prev;
72 static Wine_GLContext *context_list;
74 static void dump_PIXELFORMATDESCRIPTOR(const PIXELFORMATDESCRIPTOR *ppfd) {
75 TRACE(" - size / version : %d / %d\n", ppfd->nSize, ppfd->nVersion);
76 TRACE(" - dwFlags : ");
77 #define TEST_AND_DUMP(t,tv) if ((t) & (tv)) TRACE(#tv " ")
78 TEST_AND_DUMP(ppfd->dwFlags, PFD_DEPTH_DONTCARE);
79 TEST_AND_DUMP(ppfd->dwFlags, PFD_DOUBLEBUFFER);
80 TEST_AND_DUMP(ppfd->dwFlags, PFD_DOUBLEBUFFER_DONTCARE);
81 TEST_AND_DUMP(ppfd->dwFlags, PFD_DRAW_TO_WINDOW);
82 TEST_AND_DUMP(ppfd->dwFlags, PFD_DRAW_TO_BITMAP);
83 TEST_AND_DUMP(ppfd->dwFlags, PFD_GENERIC_ACCELERATED);
84 TEST_AND_DUMP(ppfd->dwFlags, PFD_GENERIC_FORMAT);
85 TEST_AND_DUMP(ppfd->dwFlags, PFD_NEED_PALETTE);
86 TEST_AND_DUMP(ppfd->dwFlags, PFD_NEED_SYSTEM_PALETTE);
87 TEST_AND_DUMP(ppfd->dwFlags, PFD_STEREO);
88 TEST_AND_DUMP(ppfd->dwFlags, PFD_STEREO_DONTCARE);
89 TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_GDI);
90 TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_OPENGL);
91 TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_COPY);
92 TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_EXCHANGE);
93 TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_LAYER_BUFFERS);
97 TRACE(" - iPixelType : ");
98 switch (ppfd->iPixelType) {
99 case PFD_TYPE_RGBA: TRACE("PFD_TYPE_RGBA"); break;
100 case PFD_TYPE_COLORINDEX: TRACE("PFD_TYPE_COLORINDEX"); break;
104 TRACE(" - Color : %d\n", ppfd->cColorBits);
105 TRACE(" - Red : %d\n", ppfd->cRedBits);
106 TRACE(" - Green : %d\n", ppfd->cGreenBits);
107 TRACE(" - Blue : %d\n", ppfd->cBlueBits);
108 TRACE(" - Alpha : %d\n", ppfd->cAlphaBits);
109 TRACE(" - Accum : %d\n", ppfd->cAccumBits);
110 TRACE(" - Depth : %d\n", ppfd->cDepthBits);
111 TRACE(" - Stencil : %d\n", ppfd->cStencilBits);
112 TRACE(" - Aux : %d\n", ppfd->cAuxBuffers);
114 TRACE(" - iLayerType : ");
115 switch (ppfd->iLayerType) {
116 case PFD_MAIN_PLANE: TRACE("PFD_MAIN_PLANE"); break;
117 case PFD_OVERLAY_PLANE: TRACE("PFD_OVERLAY_PLANE"); break;
118 case (BYTE)PFD_UNDERLAY_PLANE: TRACE("PFD_UNDERLAY_PLANE"); break;
123 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
124 include all dependencies
127 #define SONAME_LIBGL "libGL.so"
130 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
131 MAKE_FUNCPTR(glGetError)
132 MAKE_FUNCPTR(glXChooseVisual)
133 MAKE_FUNCPTR(glXGetConfig)
134 MAKE_FUNCPTR(glXSwapBuffers)
135 MAKE_FUNCPTR(glXQueryExtension)
137 MAKE_FUNCPTR(glXGetFBConfigs)
138 MAKE_FUNCPTR(glXChooseFBConfig)
139 MAKE_FUNCPTR(glXGetFBConfigAttrib)
140 MAKE_FUNCPTR(glXGetVisualFromFBConfig)
141 MAKE_FUNCPTR(glXCreateGLXPixmap)
142 MAKE_FUNCPTR(glXDestroyGLXPixmap)
143 MAKE_FUNCPTR(glXCreateContext)
144 MAKE_FUNCPTR(glXDestroyContext)
145 MAKE_FUNCPTR(glXGetCurrentContext)
146 MAKE_FUNCPTR(glXGetCurrentReadDrawable)
147 /* MAKE_FUNCPTR(glXQueryDrawable) */
150 static BOOL has_opengl(void)
152 static int init_done;
153 static void *opengl_handle;
155 int error_base, event_base;
157 if (init_done) return (opengl_handle != NULL);
160 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
161 if (opengl_handle == NULL) return FALSE;
163 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(RTLD_DEFAULT, #f, NULL, 0)) == NULL) goto sym_not_found;
164 LOAD_FUNCPTR(glGetError)
165 LOAD_FUNCPTR(glXChooseVisual)
166 LOAD_FUNCPTR(glXGetConfig)
167 LOAD_FUNCPTR(glXSwapBuffers)
168 LOAD_FUNCPTR(glXQueryExtension)
170 LOAD_FUNCPTR(glXGetFBConfigs)
171 LOAD_FUNCPTR(glXChooseFBConfig)
172 LOAD_FUNCPTR(glXGetFBConfigAttrib)
173 LOAD_FUNCPTR(glXGetVisualFromFBConfig)
174 LOAD_FUNCPTR(glXCreateGLXPixmap)
175 LOAD_FUNCPTR(glXDestroyGLXPixmap)
176 LOAD_FUNCPTR(glXCreateContext)
177 LOAD_FUNCPTR(glXDestroyContext)
178 LOAD_FUNCPTR(glXGetCurrentContext)
179 LOAD_FUNCPTR(glXGetCurrentReadDrawable)
183 if (pglXQueryExtension(gdi_display, &error_base, &event_base) == True) {
184 TRACE("GLX is up and running error_base = %d\n", error_base);
186 wine_dlclose(opengl_handle, NULL, 0);
187 opengl_handle = NULL;
190 return (opengl_handle != NULL);
193 wine_dlclose(opengl_handle, NULL, 0);
194 opengl_handle = NULL;
198 static inline Wine_GLContext *alloc_context(void)
202 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
204 ret->next = context_list;
205 if (context_list) context_list->prev = ret;
211 static inline void free_context(Wine_GLContext *context)
213 if (context->next != NULL) context->next->prev = context->prev;
214 if (context->prev != NULL) context->prev->next = context->next;
215 else context_list = context->next;
217 HeapFree(GetProcessHeap(), 0, context);
220 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
223 if (!ctx) return NULL;
224 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
228 /* retrieve the GLX drawable to use on a given DC */
229 inline static Drawable get_drawable( HDC hdc )
231 GLXDrawable drawable;
232 enum x11drv_escape_codes escape = X11DRV_GET_GLX_DRAWABLE;
234 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
235 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
239 /** for use of wglGetCurrentReadDCARB */
240 inline static HDC get_hdc_from_Drawable(GLXDrawable d)
243 for (ret = context_list; ret; ret = ret->next) {
244 if (d == get_drawable( ret->hdc )) {
251 inline static BOOL is_valid_context( Wine_GLContext *ctx )
254 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
255 return (ptr != NULL);
258 /* GLX can advertise dozens of different pixelformats including offscreen and onscreen ones.
259 * In our WGL implementation we only support a subset of these formats namely the format of
260 * Wine's main visual and offscreen formats (if they are available).
261 * This function converts a WGL format to its corresponding GLX one. It returns the index (zero-based)
262 * into the GLX FB config table and it returns the number of supported WGL formats in fmt_count.
264 static BOOL ConvertPixelFormatWGLtoGLX(Display *display, int iPixelFormat, int *fmt_index, int *fmt_count)
268 GLXFBConfig* cfgs = NULL;
272 int nFormats = 1; /* Start at 1 as we always have a main visual */
273 VisualID visualid = 0;
275 /* Request to look up the format of the main visual when iPixelFormat = 1 */
276 if(iPixelFormat == 1) visualid = XVisualIDFromVisual(visual);
278 /* As mentioned in various parts of the code only the format of the main visual can be used for onscreen rendering.
279 * Next to this format there are also so called offscreen rendering formats (used for pbuffers) which can be supported
280 * because they don't need a visual. Below we use glXGetFBConfigs instead of glXChooseFBConfig to enumerate the fb configurations
281 * bas this call lists both types of formats instead of only onscreen ones. */
282 cfgs = pglXGetFBConfigs(display, DefaultScreen(display), &nCfgs);
283 if (NULL == cfgs || 0 == nCfgs) {
284 ERR("glXChooseFBConfig returns NULL\n");
285 if(cfgs != NULL) XFree(cfgs);
289 /* Find the requested offscreen format and count the number of offscreen formats */
290 for(i=0; i<nCfgs; i++) {
291 pglXGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &tmp_vis_id);
292 pglXGetFBConfigAttrib(display, cfgs[i], GLX_FBCONFIG_ID, &tmp_fmt_id);
294 /* We are looking up the GLX index of our main visual and have found it :) */
295 if(iPixelFormat == 1 && visualid == tmp_vis_id) {
297 TRACE("Found FBCONFIG_ID 0x%x at index %d for VISUAL_ID 0x%x\n", tmp_fmt_id, *fmt_index, tmp_vis_id);
300 /* We found an offscreen rendering format :) */
301 else if(tmp_vis_id == 0) {
303 TRACE("Checking offscreen format FBCONFIG_ID 0x%x at index %d\n", tmp_fmt_id, i);
305 if(iPixelFormat == nFormats) {
307 TRACE("Found offscreen format FBCONFIG_ID 0x%x corresponding to iPixelFormat %d at GLX index %d\n", tmp_fmt_id, iPixelFormat, i);
312 *fmt_count = nFormats;
313 TRACE("Number of offscreen formats: %d; returning index: %d\n", *fmt_count, *fmt_index);
315 if(cfgs != NULL) XFree(cfgs);
317 if(res == FALSE && iPixelFormat == 1)
318 ERR("Can't find a matching FBCONFIG_ID for VISUAL_ID 0x%lx!\n", visualid);
324 * X11DRV_ChoosePixelFormat
326 * Equivalent of glXChooseVisual
328 int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev,
329 const PIXELFORMATDESCRIPTOR *ppfd) {
330 GLXFBConfig* cfgs = NULL;
337 ERR("No libGL on this box - disabling OpenGL support !\n");
341 if (TRACE_ON(opengl)) {
342 TRACE("(%p,%p)\n", physDev, ppfd);
344 dump_PIXELFORMATDESCRIPTOR((const PIXELFORMATDESCRIPTOR *) ppfd);
349 ERR("Can't get an opengl visual!\n");
353 /* Get a list containing all supported FB configurations */
354 cfgs = pglXChooseFBConfig(gdi_display, DefaultScreen(gdi_display), NULL, &nCfgs);
355 if (NULL == cfgs || 0 == nCfgs) {
356 ERR("glXChooseFBConfig returns NULL (glError: %d)\n", pglGetError());
360 /* In case an fbconfig was found, check if it matches to the requirements of the ppfd */
361 if(!ConvertPixelFormatWGLtoGLX(gdi_display, 1 /* main visual */, &fmt_index, &value)) {
362 ERR("Can't find a matching FBCONFIG_ID for VISUAL_ID 0x%lx!\n", visual->visualid);
369 pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_RENDER_TYPE, &value);
370 if (value & GLX_RGBA_BIT)
371 iPixelType = PFD_TYPE_RGBA;
373 iPixelType = PFD_TYPE_COLORINDEX;
375 if (ppfd->iPixelType != iPixelType) {
380 pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_DOUBLEBUFFER, &value); if (value) dwFlags |= PFD_DOUBLEBUFFER;
381 if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) {
382 if ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (dwFlags & PFD_DOUBLEBUFFER)) {
388 pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_STEREO, &value); if (value) dwFlags |= PFD_STEREO;
389 if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE)) {
390 if ((ppfd->dwFlags & PFD_STEREO) != (dwFlags & PFD_STEREO)) {
396 pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_ALPHA_SIZE, &value);
397 if (ppfd->iPixelType==PFD_TYPE_RGBA && ppfd->cAlphaBits && !value) {
402 pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_DEPTH_SIZE, &value);
403 if (ppfd->cDepthBits && !value) {
408 pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_STENCIL_SIZE, &value);
409 if (ppfd->cStencilBits && !value) {
414 pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_AUX_BUFFERS, &value);
415 if (ppfd->cAuxBuffers && !value) {
419 /* When we pass all the checks we have found a matching format :) */
421 TRACE("Successfully found a matching mode, returning index: %d\n", ret);
426 TRACE("No matching mode was found returning 0\n");
428 if (NULL != cfgs) XFree(cfgs);
434 * X11DRV_DescribePixelFormat
436 * Get the pixel-format descriptor associated to the given id
438 int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev,
441 PIXELFORMATDESCRIPTOR *ppfd) {
442 /*XVisualInfo *vis;*/
446 GLXFBConfig* cfgs = NULL;
453 ERR("No libGL on this box - disabling OpenGL support !\n");
457 TRACE("(%p,%d,%d,%p)\n", physDev, iPixelFormat, nBytes, ppfd);
460 cfgs = pglXGetFBConfigs(gdi_display, DefaultScreen(gdi_display), &nCfgs);
463 if (NULL == cfgs || 0 == nCfgs) {
464 ERR("unexpected iPixelFormat(%d), returns NULL\n", iPixelFormat);
465 return 0; /* unespected error */
468 /* This function always reports the total number of supported pixel formats.
469 * At the moment we only support the pixel format corresponding to the main
470 * visual which got created at x11drv initialization. More formats could be
471 * supported if there was a way to recreate x11 windows in x11drv.
472 * Because we only support one format nCfgs needs to be set to 1.
477 /* The application is only querying the number of visuals */
479 if (NULL != cfgs) XFree(cfgs);
484 if (nBytes < sizeof(PIXELFORMATDESCRIPTOR)) {
485 ERR("Wrong structure size !\n");
486 /* Should set error */
490 if (nCfgs < iPixelFormat || 1 > iPixelFormat) {
491 WARN("unexpected iPixelFormat(%d): not >=1 and <=nFormats(%d), returning NULL\n", iPixelFormat, nCfgs);
495 /* Retrieve the index in the FBConfig table corresponding to the visual ID from the main visual */
496 if(!ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, &fmt_index, &value)) {
497 ERR("Can't find a valid pixel format index from the main visual, expect problems!\n");
502 cur = cfgs[fmt_index];
504 memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
505 ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
508 /* These flags are always the same... */
509 ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
510 /* Now the flags extracted from the Visual */
514 pglXGetFBConfigAttrib(gdi_display, cur, GLX_CONFIG_CAVEAT, &value);
515 if(value == GLX_SLOW_CONFIG)
516 ppfd->dwFlags |= PFD_GENERIC_ACCELERATED;
518 pglXGetFBConfigAttrib(gdi_display, cur, GLX_DOUBLEBUFFER, &value); if (value) ppfd->dwFlags |= PFD_DOUBLEBUFFER;
519 pglXGetFBConfigAttrib(gdi_display, cur, GLX_STEREO, &value); if (value) ppfd->dwFlags |= PFD_STEREO;
522 pglXGetFBConfigAttrib(gdi_display, cur, GLX_RENDER_TYPE, &value);
523 if (value & GLX_RGBA_BIT)
524 ppfd->iPixelType = PFD_TYPE_RGBA;
526 ppfd->iPixelType = PFD_TYPE_COLORINDEX;
529 pglXGetFBConfigAttrib(gdi_display, cur, GLX_BUFFER_SIZE, &value);
530 ppfd->cColorBits = value;
532 /* Red, green, blue and alpha bits / shifts */
533 if (ppfd->iPixelType == PFD_TYPE_RGBA) {
534 pglXGetFBConfigAttrib(gdi_display, cur, GLX_RED_SIZE, &rb);
535 pglXGetFBConfigAttrib(gdi_display, cur, GLX_GREEN_SIZE, &gb);
536 pglXGetFBConfigAttrib(gdi_display, cur, GLX_BLUE_SIZE, &bb);
537 pglXGetFBConfigAttrib(gdi_display, cur, GLX_ALPHA_SIZE, &ab);
540 ppfd->cRedShift = gb + bb + ab;
541 ppfd->cBlueBits = bb;
542 ppfd->cBlueShift = ab;
543 ppfd->cGreenBits = gb;
544 ppfd->cGreenShift = bb + ab;
545 ppfd->cAlphaBits = ab;
546 ppfd->cAlphaShift = 0;
551 ppfd->cBlueShift = 0;
552 ppfd->cGreenBits = 0;
553 ppfd->cGreenShift = 0;
554 ppfd->cAlphaBits = 0;
555 ppfd->cAlphaShift = 0;
557 /* Accums : to do ... */
560 pglXGetFBConfigAttrib(gdi_display, cur, GLX_DEPTH_SIZE, &value);
561 ppfd->cDepthBits = value;
564 pglXGetFBConfigAttrib(gdi_display, cur, GLX_STENCIL_SIZE, &value);
565 ppfd->cStencilBits = value;
569 /* Aux : to do ... */
571 ppfd->iLayerType = PFD_MAIN_PLANE;
573 if (TRACE_ON(opengl)) {
574 dump_PIXELFORMATDESCRIPTOR(ppfd);
578 if (NULL != cfgs) XFree(cfgs);
585 * X11DRV_GetPixelFormat
587 * Get the pixel-format id used by this DC
589 int X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) {
590 TRACE("(%p): returns %d\n", physDev, physDev->current_pf);
592 return physDev->current_pf;
596 * X11DRV_SetPixelFormat
598 * Set the pixel-format id used by this DC
600 BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev,
602 const PIXELFORMATDESCRIPTOR *ppfd) {
603 TRACE("(%p,%d,%p)\n", physDev, iPixelFormat, ppfd);
605 /* At the moment we only support the pixelformat corresponding to the main
606 * x11drv visual which got created at x11drv initialization. More formats
607 * can be supported if there was a way to recreate x11 windows in x11drv
609 if(iPixelFormat != 1) {
610 TRACE("Invalid iPixelFormat: %d\n", iPixelFormat);
614 physDev->current_pf = iPixelFormat;
616 if (TRACE_ON(opengl)) {
618 GLXFBConfig* cfgs_fmt = NULL;
624 if(!ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, &fmt_index, &value)) {
625 ERR("Can't find a valid pixel format index from the main visual, expect problems!\n");
626 return TRUE; /* Return true because the SetPixelFormat stuff itself passed */
630 * How to test if hdc current drawable is compatible (visual/FBConfig) ?
632 * in case of root window created HDCs we crash here :(
634 Drawable drawable = get_drawable( physDev->hdc );
635 TRACE(" drawable (%p,%p) have :\n", drawable, root_window);
636 pglXQueryDrawable(gdi_display, drawable, GLX_FBCONFIG_ID, (unsigned int*) &value);
637 TRACE(" - FBCONFIG_ID as 0x%x\n", tmp);
638 pglXQueryDrawable(gdi_display, drawable, GLX_VISUAL_ID, (unsigned int*) &value);
639 TRACE(" - VISUAL_ID as 0x%x\n", tmp);
640 pglXQueryDrawable(gdi_display, drawable, GLX_WIDTH, (unsigned int*) &value);
641 TRACE(" - WIDTH as %d\n", tmp);
642 pglXQueryDrawable(gdi_display, drawable, GLX_HEIGHT, (unsigned int*) &value);
643 TRACE(" - HEIGHT as %d\n", tmp);
645 cfgs_fmt = pglXGetFBConfigs(gdi_display, DefaultScreen(gdi_display), &nCfgs_fmt);
646 cur_cfg = cfgs_fmt[fmt_index];
647 gl_test = pglXGetFBConfigAttrib(gdi_display, cur_cfg, GLX_FBCONFIG_ID, &value);
649 ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
651 TRACE(" FBConfig have :\n");
652 TRACE(" - FBCONFIG_ID 0x%x\n", value);
653 pglXGetFBConfigAttrib(gdi_display, cur_cfg, GLX_VISUAL_ID, &value);
654 TRACE(" - VISUAL_ID 0x%x\n", value);
655 pglXGetFBConfigAttrib(gdi_display, cur_cfg, GLX_DRAWABLE_TYPE, &value);
656 TRACE(" - DRAWABLE_TYPE 0x%x\n", value);
663 /* OpenGL32 wglCreateContext */
664 HGLRC WINAPI X11DRV_wglCreateContext(HDC hdc)
667 GLXFBConfig* cfgs_fmt = NULL;
669 int hdcPF = 1; /* We can only use the Wine's main visual which has an index of 1 */
676 TRACE("(%p)->(PF:%d)\n", hdc, hdcPF);
678 /* First, get the visual in use by the X11DRV */
679 if (!gdi_display) return 0;
681 /* We can only render using the iPixelFormat (1) of Wine's Main visual, we need to get the correspondig GLX format.
682 * If this fails something is very wrong on the system. */
683 if(!ConvertPixelFormatWGLtoGLX(gdi_display, hdcPF, &tmp, &fmt_index)) {
684 ERR("Cannot get FB Config for main iPixelFormat 1, expect problems!\n");
685 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
689 cfgs_fmt = pglXGetFBConfigs(gdi_display, DefaultScreen(gdi_display), &nCfgs_fmt);
690 if (NULL == cfgs_fmt || 0 == nCfgs_fmt) {
691 ERR("Cannot get FB Configs, expect problems.\n");
692 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
696 if (nCfgs_fmt < fmt_index) {
697 ERR("(%p): unexpected pixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, fmt_index, nCfgs_fmt);
698 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
702 cur_cfg = cfgs_fmt[fmt_index];
703 gl_test = pglXGetFBConfigAttrib(gdi_display, cur_cfg, GLX_FBCONFIG_ID, &value);
705 ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
706 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
711 /* The context will be allocated in the wglMakeCurrent call */
713 ret = alloc_context();
716 ret->display = gdi_display;
717 ret->fb_conf = cur_cfg;
719 ret->vis = pglXGetVisualFromFBConfig(gdi_display, cur_cfg);
721 TRACE(" creating context %p (GL context creation delayed)\n", ret);
725 /* OpenGL32 wglDeleteContext */
726 BOOL WINAPI X11DRV_wglDeleteContext(HGLRC hglrc)
728 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
731 TRACE("(%p)\n", hglrc);
734 /* A game (Half Life not to name it) deletes twice the same context,
735 * so make sure it is valid first */
736 if (is_valid_context( ctx ))
738 if (ctx->ctx) pglXDestroyContext(ctx->display, ctx->ctx);
743 WARN("Error deleting context !\n");
744 SetLastError(ERROR_INVALID_HANDLE);
752 /* OpenGL32 wglGetCurrentContext() */
753 HGLRC WINAPI X11DRV_wglGetCurrentContext(void) {
760 gl_ctx = pglXGetCurrentContext();
761 ret = get_context_from_GLXContext(gl_ctx);
764 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
769 /* OpenGL32 wglGetCurrentDC */
770 HDC WINAPI X11DRV_wglGetCurrentDC(void) {
777 gl_ctx = pglXGetCurrentContext();
778 ret = get_context_from_GLXContext(gl_ctx);
782 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
785 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
790 /* OpenGL32 wglGetCurrentReadDCARB */
791 HDC WINAPI X11DRV_wglGetCurrentReadDCARB(void)
799 gl_d = pglXGetCurrentReadDrawable();
800 ret = get_hdc_from_Drawable(gl_d);
803 TRACE(" returning %p (GL drawable %lu)\n", ret, gl_d);
807 /* WGL helper function which handles differences in glGetIntegerv from WGL and GLX */
808 void X11DRV_wglGetIntegerv(GLenum pname, GLint* params) {
809 TRACE("pname: 0x%x, params: %p\n", pname, params);
810 if (pname == GL_DEPTH_BITS) {
811 GLXContext gl_ctx = pglXGetCurrentContext();
812 Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
813 /*TRACE("returns Wine Ctx as %p\n", ret);*/
815 * if we cannot find a Wine Context
816 * we only have the default wine desktop context,
817 * so if we have only a 24 depth say we have 32
819 if (NULL == ret && 24 == *params) {
822 TRACE("returns GL_DEPTH_BITS as '%d'\n", *params);
824 if (pname == GL_ALPHA_BITS) {
826 GLXContext gl_ctx = pglXGetCurrentContext();
827 Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
828 pglXGetFBConfigAttrib(ret->display, ret->fb_conf, GLX_ALPHA_SIZE, &tmp);
829 TRACE("returns GL_ALPHA_BITS as '%d'\n", tmp);
834 static XID create_glxpixmap(X11DRV_PDEVICE *physDev)
838 XVisualInfo template;
843 /* Retrieve the visualid from our main visual which is the only visual we can use */
844 template.visualid = XVisualIDFromVisual(visual);
845 vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
847 ret = pglXCreateGLXPixmap(gdi_display, vis, physDev->bitmap->pixmap);
850 TRACE("return %lx\n", ret);
854 Drawable get_glxdrawable(X11DRV_PDEVICE *physDev)
860 if (physDev->bitmap->hbitmap == BITMAP_stock_phys_bitmap.hbitmap)
861 ret = physDev->drawable; /* PBuffer */
864 if(!physDev->bitmap->glxpixmap)
865 physDev->bitmap->glxpixmap = create_glxpixmap(physDev);
866 ret = physDev->bitmap->glxpixmap;
870 ret = physDev->drawable;
874 BOOL destroy_glxpixmap(XID glxpixmap)
877 pglXDestroyGLXPixmap(gdi_display, glxpixmap);
885 * Swap the buffers of this DC
887 BOOL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev)
889 GLXDrawable drawable;
891 ERR("No libGL on this box - disabling OpenGL support !\n");
895 TRACE_(opengl)("(%p)\n", physDev);
897 drawable = get_glxdrawable(physDev);
899 pglXSwapBuffers(gdi_display, drawable);
905 static long prev_time, frames;
907 DWORD time = GetTickCount();
909 /* every 1.5 seconds */
910 if (time - prev_time > 1500) {
911 TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
920 /***********************************************************************
921 * X11DRV_setup_opengl_visual
923 * Setup the default visual used for OpenGL and Direct3D, and the desktop
924 * window (if it exists). If OpenGL isn't available, the visual is simply
925 * set to the default visual for the display
927 XVisualInfo *X11DRV_setup_opengl_visual( Display *display )
929 XVisualInfo *visual = NULL;
930 /* In order to support OpenGL or D3D, we require a double-buffered visual and stencil buffer support, */
931 int dblBuf[] = {GLX_RGBA,GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DOUBLEBUFFER, None};
932 if (!has_opengl()) return NULL;
935 visual = pglXChooseVisual(display, DefaultScreen(display), dblBuf);
937 if (visual == NULL) {
938 /* fallback to 16 bits depth, no alpha */
939 int dblBuf2[] = {GLX_RGBA,GLX_DEPTH_SIZE, 16, GLX_STENCIL_SIZE, 8, GLX_DOUBLEBUFFER, None};
940 WARN("Failed to get a visual with at least 24 bits depth\n");
943 visual = pglXChooseVisual(display, DefaultScreen(display), dblBuf2);
945 if (visual == NULL) {
946 /* fallback to no stencil */
947 int dblBuf2[] = {GLX_RGBA,GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None};
948 WARN("Failed to get a visual with at least 8 bits of stencil\n");
951 visual = pglXChooseVisual(display, DefaultScreen(display), dblBuf2);
953 if (visual == NULL) {
954 /* This should only happen if we cannot find a match with a depth size 16 */
955 FIXME("Failed to find a suitable visual\n");
960 TRACE("Visual ID %lx Chosen\n",visual->visualid);
964 #else /* no OpenGL includes */
966 void X11DRV_OpenGL_Init(Display *display)
970 /***********************************************************************
971 * ChoosePixelFormat (X11DRV.@)
973 int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev,
974 const PIXELFORMATDESCRIPTOR *ppfd) {
975 ERR("No OpenGL support compiled in.\n");
980 /***********************************************************************
981 * DescribePixelFormat (X11DRV.@)
983 int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev,
986 PIXELFORMATDESCRIPTOR *ppfd) {
987 ERR("No OpenGL support compiled in.\n");
992 /***********************************************************************
993 * GetPixelFormat (X11DRV.@)
995 int X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) {
996 ERR("No OpenGL support compiled in.\n");
1001 /***********************************************************************
1002 * SetPixelFormat (X11DRV.@)
1004 BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev,
1006 const PIXELFORMATDESCRIPTOR *ppfd) {
1007 ERR("No OpenGL support compiled in.\n");
1012 /***********************************************************************
1013 * SwapBuffers (X11DRV.@)
1015 BOOL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev) {
1016 ERR_(opengl)("No OpenGL support compiled in.\n");
1021 /* OpenGL32 wglCreateContext */
1022 HGLRC WINAPI X11DRV_wglCreateContext(HDC hdc) {
1023 ERR_(opengl)("No OpenGL support compiled in.\n");
1027 /* OpenGL32 wglDeleteContext */
1028 BOOL WINAPI X11DRV_wglDeleteContext(HGLRC hglrc) {
1029 ERR_(opengl)("No OpenGL support compiled in.\n");
1033 /* OpenGL32 wglGetCurrentContext() */
1034 HGLRC WINAPI X11DRV_wglGetCurrentContext(void) {
1035 ERR_(opengl)("No OpenGL support compiled in.\n");
1039 /* OpenGL32 wglGetCurrentDC */
1040 HDC WINAPI X11DRV_wglGetCurrentDC(void) {
1041 ERR_(opengl)("No OpenGL support compiled in.\n");
1045 /* WGL helper function which handles differences in glGetIntegerv from WGL and GLX */
1046 void X11DRV_wglGetIntegerv(GLenum pname, GLint* params) {
1047 ERR_(opengl)("No OpenGL support compiled in.\n");
1050 XVisualInfo *X11DRV_setup_opengl_visual( Display *display )
1055 Drawable get_glxdrawable(X11DRV_PDEVICE *physDev)
1060 BOOL destroy_glxpixmap(XID glxpixmap)
1065 #endif /* defined(HAVE_OPENGL) */