Add GLXFBConfig on Wine_GLContext (we should remove XVisualInfo
[wine/testsucceed.git] / dlls / opengl32 / wgl.c
blobd3bff02ede80a9d273807c786d81e8803f4c0f50
1 /* Window-specific OpenGL functions implementation.
3 * Copyright (c) 1999 Lionel Ulmer
4 * Copyright (c) 2005 Raphael Junqueira
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winerror.h"
32 #include "winreg.h"
34 #include "wgl.h"
35 #include "wgl_ext.h"
36 #include "opengl_ext.h"
37 #include "wine/library.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(opengl);
42 /* x11drv GDI escapes */
43 #define X11DRV_ESCAPE 6789
44 enum x11drv_escape_codes
46 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
47 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
48 X11DRV_GET_FONT, /* get current X font for a DC */
51 void (*wine_tsx11_lock_ptr)(void) = NULL;
52 void (*wine_tsx11_unlock_ptr)(void) = NULL;
54 static GLXContext default_cx = NULL;
55 static Display *default_display; /* display to use for default context */
57 static HMODULE opengl32_handle;
59 static glXGetProcAddressARB_t p_glXGetProcAddressARB = NULL;
61 static char internal_gl_disabled_extensions[512];
62 static char* internal_gl_extensions = NULL;
64 typedef struct wine_glcontext {
65 HDC hdc;
66 Display *display;
67 XVisualInfo *vis;
68 GLXFBConfig fb_conf;
69 GLXContext ctx;
70 struct wine_glcontext *next;
71 struct wine_glcontext *prev;
72 } Wine_GLContext;
73 static Wine_GLContext *context_list;
75 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
77 Wine_GLContext *ret;
78 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
79 return ret;
82 static inline void free_context(Wine_GLContext *context)
84 if (context->next != NULL) context->next->prev = context->prev;
85 if (context->prev != NULL) context->prev->next = context->next;
86 else context_list = context->next;
88 HeapFree(GetProcessHeap(), 0, context);
91 static inline Wine_GLContext *alloc_context(void)
93 Wine_GLContext *ret;
95 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
97 ret->next = context_list;
98 if (context_list) context_list->prev = ret;
99 context_list = ret;
101 return ret;
104 inline static BOOL is_valid_context( Wine_GLContext *ctx )
106 Wine_GLContext *ptr;
107 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
108 return (ptr != NULL);
111 /* retrieve the X display to use on a given DC */
112 inline static Display *get_display( HDC hdc )
114 Display *display;
115 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
117 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
118 sizeof(display), (LPSTR)&display )) display = NULL;
119 return display;
123 /* retrieve the X drawable to use on a given DC */
124 inline static Drawable get_drawable( HDC hdc )
126 Drawable drawable;
127 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
129 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
130 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
131 return drawable;
134 /** for use of wglGetCurrentReadDCARB */
135 inline static HDC get_hdc_from_Drawable(GLXDrawable d)
137 Wine_GLContext *ret;
138 for (ret = context_list; ret; ret = ret->next) {
139 if (d == get_drawable( ret->hdc )) {
140 return ret->hdc;
143 return NULL;
146 /* retrieve the X drawable to use on a given DC */
147 inline static Font get_font( HDC hdc )
149 Font font;
150 enum x11drv_escape_codes escape = X11DRV_GET_FONT;
152 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
153 sizeof(font), (LPSTR)&font )) font = 0;
154 return font;
158 /***********************************************************************
159 * wglCreateContext (OPENGL32.@)
161 HGLRC WINAPI wglCreateContext(HDC hdc)
163 XVisualInfo *vis;
164 Wine_GLContext *ret;
165 int num;
166 XVisualInfo template;
167 Display *display = get_display( hdc );
169 TRACE("(%p)\n", hdc);
171 /* First, get the visual in use by the X11DRV */
172 if (!display) return 0;
173 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
174 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
176 if (vis == NULL) {
177 ERR("NULL visual !!!\n");
178 /* Need to set errors here */
179 return NULL;
182 /* The context will be allocated in the wglMakeCurrent call */
183 ENTER_GL();
184 ret = alloc_context();
185 LEAVE_GL();
186 ret->hdc = hdc;
187 ret->display = display;
188 ret->vis = vis;
191 int hdcPF = GetPixelFormat(hdc);
192 int nCfgs_fmt = 0;
193 GLXFBConfig* cfgs_fmt = NULL;
194 GLXFBConfig cur_cfg;
195 int value;
196 int gl_test = 0;
197 cfgs_fmt = glXGetFBConfigs(display, DefaultScreen(display), &nCfgs_fmt);
198 if (NULL == cfgs_fmt || 0 == nCfgs_fmt) {
199 ERR("Cannot get FB Configs, expect problems.\n");
200 return NULL;
202 cur_cfg = cfgs_fmt[hdcPF - 1];
203 gl_test = glXGetFBConfigAttrib(display, cur_cfg, GLX_FBCONFIG_ID, &value);
204 if (gl_test) {
205 ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
206 return NULL;
208 ret->fb_conf = cur_cfg;
209 XFree(cfgs_fmt);
212 TRACE(" creating context %p (GL context creation delayed)\n", ret);
213 return (HGLRC) ret;
216 /***********************************************************************
217 * wglCreateLayerContext (OPENGL32.@)
219 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
220 int iLayerPlane) {
221 TRACE("(%p,%d)\n", hdc, iLayerPlane);
223 if (iLayerPlane == 0) {
224 return wglCreateContext(hdc);
226 FIXME(" no handler for layer %d\n", iLayerPlane);
228 return NULL;
231 /***********************************************************************
232 * wglCopyContext (OPENGL32.@)
234 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
235 HGLRC hglrcDst,
236 UINT mask) {
237 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
239 return FALSE;
242 /***********************************************************************
243 * wglDeleteContext (OPENGL32.@)
245 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
247 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
248 BOOL ret = TRUE;
250 TRACE("(%p)\n", hglrc);
252 ENTER_GL();
253 /* A game (Half Life not to name it) deletes twice the same context,
254 * so make sure it is valid first */
255 if (is_valid_context( ctx ))
257 if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
258 free_context(ctx);
260 else
262 WARN("Error deleting context !\n");
263 SetLastError(ERROR_INVALID_HANDLE);
264 ret = FALSE;
266 LEAVE_GL();
268 return ret;
271 /***********************************************************************
272 * wglDescribeLayerPlane (OPENGL32.@)
274 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
275 int iPixelFormat,
276 int iLayerPlane,
277 UINT nBytes,
278 LPLAYERPLANEDESCRIPTOR plpd) {
279 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
281 return FALSE;
284 /***********************************************************************
285 * wglGetCurrentContext (OPENGL32.@)
287 HGLRC WINAPI wglGetCurrentContext(void) {
288 GLXContext gl_ctx;
289 Wine_GLContext *ret;
291 TRACE("()\n");
293 ENTER_GL();
294 gl_ctx = glXGetCurrentContext();
295 ret = get_context_from_GLXContext(gl_ctx);
296 LEAVE_GL();
298 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
300 return (HGLRC)ret;
303 /***********************************************************************
304 * wglGetCurrentDC (OPENGL32.@)
306 HDC WINAPI wglGetCurrentDC(void) {
307 GLXContext gl_ctx;
308 Wine_GLContext *ret;
310 TRACE("()\n");
312 ENTER_GL();
313 gl_ctx = glXGetCurrentContext();
314 ret = get_context_from_GLXContext(gl_ctx);
315 LEAVE_GL();
317 if (ret) {
318 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
319 return ret->hdc;
320 } else {
321 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
322 return 0;
326 /***********************************************************************
327 * wglGetLayerPaletteEntries (OPENGL32.@)
329 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
330 int iLayerPlane,
331 int iStart,
332 int cEntries,
333 const COLORREF *pcr) {
334 FIXME("(): stub !\n");
336 return 0;
339 /***********************************************************************
340 * wglGetProcAddress (OPENGL32.@)
342 static int compar(const void *elt_a, const void *elt_b) {
343 return strcmp(((const OpenGL_extension *) elt_a)->name,
344 ((const OpenGL_extension *) elt_b)->name);
347 static int wgl_compar(const void *elt_a, const void *elt_b) {
348 return strcmp(((const WGL_extension *) elt_a)->func_name,
349 ((const WGL_extension *) elt_b)->func_name);
352 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
353 void *local_func;
354 OpenGL_extension ext;
355 OpenGL_extension *ext_ret;
357 TRACE("(%s)\n", lpszProc);
359 /* First, look if it's not already defined in the 'standard' OpenGL functions */
360 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
361 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
362 return local_func;
365 if (p_glXGetProcAddressARB == NULL) {
366 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
367 return NULL;
370 /* After that, search in the thunks to find the real name of the extension */
371 ext.name = (char *) lpszProc;
372 ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
373 extension_registry_size, sizeof(OpenGL_extension), compar);
375 if (ext_ret == NULL) {
376 WGL_extension wgl_ext, *wgl_ext_ret;
378 /* Try to find the function in the WGL extensions ... */
379 wgl_ext.func_name = (char *) lpszProc;
380 wgl_ext_ret = (WGL_extension *) bsearch(&wgl_ext, wgl_extension_registry,
381 wgl_extension_registry_size, sizeof(WGL_extension), wgl_compar);
383 if (wgl_ext_ret == NULL) {
384 /* Some sanity checks :-) */
385 ENTER_GL();
386 local_func = p_glXGetProcAddressARB( (const GLubyte *) lpszProc);
387 LEAVE_GL();
388 if (local_func != NULL) {
389 WARN("Extension %s defined in the OpenGL library but NOT in opengl_ext.c...\n", lpszProc);
390 return NULL;
393 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
394 return NULL;
395 } else {
396 void *ret = NULL;
398 if (wgl_ext_ret->func_init != NULL) {
399 const char *err_msg;
400 if ((err_msg = wgl_ext_ret->func_init(p_glXGetProcAddressARB,
401 wgl_ext_ret->context)) == NULL) {
402 ret = wgl_ext_ret->func_address;
403 } else {
404 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc), err_msg);
405 return NULL;
407 } else {
408 ret = wgl_ext_ret->func_address;
411 if (ret)
412 TRACE(" returning WGL function (%p)\n", ret);
413 return ret;
415 } else {
416 ENTER_GL();
417 local_func = p_glXGetProcAddressARB( (const GLubyte*) ext_ret->glx_name);
418 LEAVE_GL();
420 /* After that, look at the extensions defined in the Linux OpenGL library */
421 if (local_func == NULL) {
422 char buf[256];
423 void *ret = NULL;
425 /* Remove the 3 last letters (EXT, ARB, ...).
427 I know that some extensions have more than 3 letters (MESA, NV,
428 INTEL, ...), but this is only a stop-gap measure to fix buggy
429 OpenGL drivers (moreover, it is only useful for old 1.0 apps
430 that query the glBindTextureEXT extension).
432 memcpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
433 buf[strlen(ext_ret->glx_name) - 3] = '\0';
434 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
436 ret = GetProcAddress(opengl32_handle, buf);
437 if (ret != NULL) {
438 TRACE(" found function in main OpenGL library (%p) !\n", ret);
439 } else {
440 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
443 return ret;
444 } else {
445 TRACE(" returning function (%p)\n", ext_ret->func);
446 *(ext_ret->func_ptr) = local_func;
448 return ext_ret->func;
453 /***********************************************************************
454 * wglMakeCurrent (OPENGL32.@)
456 BOOL WINAPI wglMakeCurrent(HDC hdc,
457 HGLRC hglrc) {
458 BOOL ret;
460 TRACE("(%p,%p)\n", hdc, hglrc);
462 ENTER_GL();
463 if (hglrc == NULL) {
464 ret = glXMakeCurrent(default_display, None, NULL);
465 } else {
466 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
467 Drawable drawable = get_drawable( hdc );
468 if (ctx->ctx == NULL) {
469 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
470 TRACE(" created a delayed OpenGL context (%p) for %p\n", ctx->ctx, ctx->vis);
472 TRACE(" make current for dis %p, drawable %p, ctx %p\n", ctx->display, (void*) drawable, ctx->ctx);
473 ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
475 LEAVE_GL();
476 TRACE(" returning %s\n", (ret ? "True" : "False"));
477 return ret;
480 /***********************************************************************
481 * wglMakeContextCurrentARB (OPENGL32.@)
483 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
485 BOOL ret;
486 TRACE("(%p,%p,%p)\n", hDrawDC, hReadDC, hglrc);
488 ENTER_GL();
489 if (hglrc == NULL) {
490 ret = glXMakeCurrent(default_display, None, NULL);
491 } else {
492 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
493 Drawable d_draw = get_drawable( hDrawDC );
494 Drawable d_read = get_drawable( hReadDC );
496 if (ctx->ctx == NULL) {
497 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
498 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
500 ret = glXMakeContextCurrent(ctx->display, d_draw, d_read, ctx->ctx);
502 LEAVE_GL();
504 TRACE(" returning %s\n", (ret ? "True" : "False"));
505 return ret;
508 /***********************************************************************
509 * wglGetCurrentReadDCARB (OPENGL32.@)
511 HDC WINAPI wglGetCurrentReadDCARB(void)
513 GLXDrawable gl_d;
514 HDC ret;
516 TRACE("()\n");
518 ENTER_GL();
519 gl_d = glXGetCurrentReadDrawable();
520 ret = get_hdc_from_Drawable(gl_d);
521 LEAVE_GL();
523 TRACE(" returning %p (GL drawable %lu)\n", ret, gl_d);
524 return ret;
529 /***********************************************************************
530 * wglRealizeLayerPalette (OPENGL32.@)
532 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
533 int iLayerPlane,
534 BOOL bRealize) {
535 FIXME("()\n");
537 return FALSE;
540 /***********************************************************************
541 * wglSetLayerPaletteEntries (OPENGL32.@)
543 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
544 int iLayerPlane,
545 int iStart,
546 int cEntries,
547 const COLORREF *pcr) {
548 FIXME("(): stub !\n");
550 return 0;
553 /***********************************************************************
554 * wglShareLists (OPENGL32.@)
556 BOOL WINAPI wglShareLists(HGLRC hglrc1,
557 HGLRC hglrc2) {
558 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
559 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
561 TRACE("(%p, %p)\n", org, dest);
563 if (dest->ctx != NULL) {
564 ERR("Could not share display lists, context already created !\n");
565 return FALSE;
566 } else {
567 if (org->ctx == NULL) {
568 ENTER_GL();
569 org->ctx = glXCreateContext(org->display, org->vis, NULL, True);
570 LEAVE_GL();
571 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
574 ENTER_GL();
575 /* Create the destination context with display lists shared */
576 dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, True);
577 LEAVE_GL();
578 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
581 return TRUE;
584 /***********************************************************************
585 * wglSwapLayerBuffers (OPENGL32.@)
587 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
588 UINT fuPlanes) {
589 TRACE("(%p, %08x)\n", hdc, fuPlanes);
591 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
592 if (!SwapBuffers(hdc)) return FALSE;
593 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
596 if (fuPlanes) {
597 WARN("Following layers unhandled : %08x\n", fuPlanes);
600 return TRUE;
603 static BOOL internal_wglUseFontBitmaps(HDC hdc,
604 DWORD first,
605 DWORD count,
606 DWORD listBase,
607 DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
609 /* We are running using client-side rendering fonts... */
610 GLYPHMETRICS gm;
611 unsigned int glyph;
612 int size = 0;
613 void *bitmap = NULL, *gl_bitmap = NULL;
614 int org_alignment;
616 ENTER_GL();
617 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
618 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
619 LEAVE_GL();
621 for (glyph = first; glyph < first + count; glyph++) {
622 unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
623 int height, width_int;
625 TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
626 if (needed_size == GDI_ERROR) {
627 TRACE(" - needed size : %d (GDI_ERROR)\n", needed_size);
628 goto error;
629 } else {
630 TRACE(" - needed size : %d\n", needed_size);
633 if (needed_size > size) {
634 size = needed_size;
635 HeapFree(GetProcessHeap(), 0, bitmap);
636 HeapFree(GetProcessHeap(), 0, gl_bitmap);
637 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
638 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
640 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
641 if (TRACE_ON(opengl)) {
642 unsigned int height, width, bitmask;
643 unsigned char *bitmap_ = (unsigned char *) bitmap;
645 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
646 TRACE(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
647 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
648 if (needed_size != 0) {
649 TRACE(" - bitmap :\n");
650 for (height = 0; height < gm.gmBlackBoxY; height++) {
651 TRACE(" ");
652 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
653 if (bitmask == 0) {
654 bitmap_ += 1;
655 bitmask = 0x80;
657 if (*bitmap_ & bitmask)
658 TRACE("*");
659 else
660 TRACE(" ");
662 bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
663 TRACE("\n");
668 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
669 * glyph for it to be drawn properly.
671 if (needed_size != 0) {
672 width_int = (gm.gmBlackBoxX + 31) / 32;
673 for (height = 0; height < gm.gmBlackBoxY; height++) {
674 int width;
675 for (width = 0; width < width_int; width++) {
676 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
677 ((int *) bitmap)[height * width_int + width];
682 ENTER_GL();
683 glNewList(listBase++, GL_COMPILE);
684 if (needed_size != 0) {
685 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
686 0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
687 gm.gmCellIncX, gm.gmCellIncY,
688 gl_bitmap);
689 } else {
690 /* This is the case of 'empty' glyphs like the space character */
691 glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
693 glEndList();
694 LEAVE_GL();
697 ENTER_GL();
698 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
699 LEAVE_GL();
701 HeapFree(GetProcessHeap(), 0, bitmap);
702 HeapFree(GetProcessHeap(), 0, gl_bitmap);
703 return TRUE;
705 error:
706 ENTER_GL();
707 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
708 LEAVE_GL();
710 HeapFree(GetProcessHeap(), 0, bitmap);
711 HeapFree(GetProcessHeap(), 0, gl_bitmap);
712 return FALSE;
715 /***********************************************************************
716 * wglUseFontBitmapsA (OPENGL32.@)
718 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
719 DWORD first,
720 DWORD count,
721 DWORD listBase)
723 Font fid = get_font( hdc );
725 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
727 if (fid == 0) {
728 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
731 ENTER_GL();
732 /* I assume that the glyphs are at the same position for X and for Windows */
733 glXUseXFont(fid, first, count, listBase);
734 LEAVE_GL();
735 return TRUE;
738 /***********************************************************************
739 * wglUseFontBitmapsW (OPENGL32.@)
741 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
742 DWORD first,
743 DWORD count,
744 DWORD listBase)
746 Font fid = get_font( hdc );
748 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
750 if (fid == 0) {
751 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
754 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
756 ENTER_GL();
757 /* I assume that the glyphs are at the same position for X and for Windows */
758 glXUseXFont(fid, first, count, listBase);
759 LEAVE_GL();
760 return TRUE;
763 /***********************************************************************
764 * wglUseFontOutlinesA (OPENGL32.@)
766 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
767 DWORD first,
768 DWORD count,
769 DWORD listBase,
770 FLOAT deviation,
771 FLOAT extrusion,
772 int format,
773 LPGLYPHMETRICSFLOAT lpgmf) {
774 FIXME("(): stub !\n");
776 return FALSE;
779 const GLubyte * internal_glGetString(GLenum name) {
780 const char* GL_Extensions = NULL;
782 if (GL_EXTENSIONS != name) {
783 return glGetString(name);
786 if (NULL == internal_gl_extensions) {
787 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
789 TRACE("GL_EXTENSIONS reported:\n");
790 if (NULL == GL_Extensions) {
791 ERR("GL_EXTENSIONS returns NULL\n");
792 return NULL;
793 } else {
794 size_t len = strlen(GL_Extensions);
795 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
797 while (*GL_Extensions != 0x00) {
798 const char* Start = GL_Extensions;
799 char ThisExtn[256];
801 memset(ThisExtn, 0x00, sizeof(ThisExtn));
802 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
803 GL_Extensions++;
805 memcpy(ThisExtn, Start, (GL_Extensions - Start));
806 TRACE("- %s:", ThisExtn);
808 /* test if supported API is disabled by config */
809 if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
810 strcat(internal_gl_extensions, " ");
811 strcat(internal_gl_extensions, ThisExtn);
812 TRACE(" active\n");
813 } else {
814 TRACE(" deactived (by config)\n");
817 if (*GL_Extensions == ' ') GL_Extensions++;
821 return (const GLubyte *) internal_gl_extensions;
824 void internal_glGetIntegerv(GLenum pname, GLint* params) {
825 glGetIntegerv(pname, params);
826 if (pname == GL_ALPHA_BITS) {
827 GLint tmp;
828 GLXContext gl_ctx = glXGetCurrentContext();
829 Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
830 glXGetFBConfigAttrib(ret->display, ret->fb_conf, GLX_ALPHA_SIZE, &tmp);
831 TRACE("returns GL_ALPHA_BITS as '%d'\n", tmp);
832 *params = tmp;
837 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
838 include all dependencies
840 #ifndef SONAME_LIBGL
841 #define SONAME_LIBGL "libGL.so"
842 #endif
844 /* This is for brain-dead applications that use OpenGL functions before even
845 creating a rendering context.... */
846 static BOOL process_attach(void)
848 XWindowAttributes win_attr;
849 Visual *rootVisual;
850 int num;
851 XVisualInfo template;
852 HDC hdc;
853 XVisualInfo *vis = NULL;
854 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
855 HMODULE mod = GetModuleHandleA( "winex11.drv" );
856 void *opengl_handle;
857 DWORD size = sizeof(internal_gl_disabled_extensions);
858 HKEY hkey = 0;
860 if (!root || !mod)
862 ERR("X11DRV not loaded. Cannot create default context.\n");
863 return FALSE;
866 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
867 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
869 hdc = GetDC(0);
870 default_display = get_display( hdc );
871 ReleaseDC( 0, hdc );
872 if (!default_display)
874 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
875 return FALSE;
878 ENTER_GL();
880 /* Try to get the visual from the Root Window. We can't use the standard (presumably
881 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
882 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
883 with mismatched visuals. Note that the Root Window visual may not be double
884 buffered, so apps actually attempting to render this way may flicker */
885 if (XGetWindowAttributes( default_display, root, &win_attr ))
887 rootVisual = win_attr.visual;
889 else
891 /* Get the default visual, since we can't seem to get the attributes from the
892 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
893 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
896 template.visualid = XVisualIDFromVisual(rootVisual);
897 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
898 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
899 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
900 XFree(vis);
901 LEAVE_GL();
903 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
904 if (opengl_handle != NULL) {
905 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
906 wine_dlclose(opengl_handle, NULL, 0);
907 if (p_glXGetProcAddressARB == NULL)
908 TRACE("could not find glXGetProcAddressARB in libGL.\n");
911 internal_gl_disabled_extensions[0] = 0;
912 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
913 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
914 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
916 RegCloseKey(hkey);
919 if (default_cx == NULL) {
920 ERR("Could not create default context.\n");
922 else
924 /* After context initialize also the list of supported WGL extensions. */
925 wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB, internal_gl_disabled_extensions);
927 return TRUE;
931 /**********************************************************************/
933 static void process_detach(void)
935 glXDestroyContext(default_display, default_cx);
937 /* Do not leak memory... */
938 wgl_ext_finalize_extensions();
939 if (NULL != internal_gl_extensions) {
940 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
944 /***********************************************************************
945 * OpenGL initialisation routine
947 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
949 switch(reason)
951 case DLL_PROCESS_ATTACH:
952 opengl32_handle = hinst;
953 DisableThreadLibraryCalls(hinst);
954 return process_attach();
955 case DLL_PROCESS_DETACH:
956 process_detach();
957 break;
959 return TRUE;