Release 20050930.
[wine/gsoc-2012-control.git] / dlls / opengl32 / wgl.c
blob14015cb23a40d0b621f3615a4f63e544841de235
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 GLXContext ctx;
68 XVisualInfo *vis;
69 struct wine_glcontext *next;
70 struct wine_glcontext *prev;
71 } Wine_GLContext;
72 static Wine_GLContext *context_list;
74 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
76 Wine_GLContext *ret;
77 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
78 return ret;
81 static inline void free_context(Wine_GLContext *context)
83 if (context->next != NULL) context->next->prev = context->prev;
84 if (context->prev != NULL) context->prev->next = context->next;
85 else context_list = context->next;
87 HeapFree(GetProcessHeap(), 0, context);
90 static inline Wine_GLContext *alloc_context(void)
92 Wine_GLContext *ret;
94 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
96 ret->next = context_list;
97 if (context_list) context_list->prev = ret;
98 context_list = ret;
100 return ret;
103 inline static BOOL is_valid_context( Wine_GLContext *ctx )
105 Wine_GLContext *ptr;
106 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
107 return (ptr != NULL);
110 /* retrieve the X display to use on a given DC */
111 inline static Display *get_display( HDC hdc )
113 Display *display;
114 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
116 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
117 sizeof(display), (LPSTR)&display )) display = NULL;
118 return display;
122 /* retrieve the X drawable to use on a given DC */
123 inline static Drawable get_drawable( HDC hdc )
125 Drawable drawable;
126 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
128 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
129 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
130 return drawable;
133 /** for use of wglGetCurrentReadDCARB */
134 inline static HDC get_hdc_from_Drawable(GLXDrawable d)
136 Wine_GLContext *ret;
137 for (ret = context_list; ret; ret = ret->next) {
138 if (d == get_drawable( ret->hdc )) {
139 return ret->hdc;
142 return NULL;
145 /* retrieve the X drawable to use on a given DC */
146 inline static Font get_font( HDC hdc )
148 Font font;
149 enum x11drv_escape_codes escape = X11DRV_GET_FONT;
151 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
152 sizeof(font), (LPSTR)&font )) font = 0;
153 return font;
157 /***********************************************************************
158 * wglCreateContext (OPENGL32.@)
160 HGLRC WINAPI wglCreateContext(HDC hdc)
162 XVisualInfo *vis;
163 Wine_GLContext *ret;
164 int num;
165 XVisualInfo template;
166 Display *display = get_display( hdc );
168 TRACE("(%p)\n", hdc);
170 /* First, get the visual in use by the X11DRV */
171 if (!display) return 0;
172 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
173 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
175 if (vis == NULL) {
176 ERR("NULL visual !!!\n");
177 /* Need to set errors here */
178 return NULL;
181 /* The context will be allocated in the wglMakeCurrent call */
182 ENTER_GL();
183 ret = alloc_context();
184 LEAVE_GL();
185 ret->hdc = hdc;
186 ret->display = display;
187 ret->vis = vis;
189 TRACE(" creating context %p (GL context creation delayed)\n", ret);
190 return (HGLRC) ret;
193 /***********************************************************************
194 * wglCreateLayerContext (OPENGL32.@)
196 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
197 int iLayerPlane) {
198 TRACE("(%p,%d)\n", hdc, iLayerPlane);
200 if (iLayerPlane == 0) {
201 return wglCreateContext(hdc);
203 FIXME(" no handler for layer %d\n", iLayerPlane);
205 return NULL;
208 /***********************************************************************
209 * wglCopyContext (OPENGL32.@)
211 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
212 HGLRC hglrcDst,
213 UINT mask) {
214 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
216 return FALSE;
219 /***********************************************************************
220 * wglDeleteContext (OPENGL32.@)
222 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
224 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
225 BOOL ret = TRUE;
227 TRACE("(%p)\n", hglrc);
229 ENTER_GL();
230 /* A game (Half Life not to name it) deletes twice the same context,
231 * so make sure it is valid first */
232 if (is_valid_context( ctx ))
234 if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
235 free_context(ctx);
237 else
239 WARN("Error deleting context !\n");
240 SetLastError(ERROR_INVALID_HANDLE);
241 ret = FALSE;
243 LEAVE_GL();
245 return ret;
248 /***********************************************************************
249 * wglDescribeLayerPlane (OPENGL32.@)
251 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
252 int iPixelFormat,
253 int iLayerPlane,
254 UINT nBytes,
255 LPLAYERPLANEDESCRIPTOR plpd) {
256 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
258 return FALSE;
261 /***********************************************************************
262 * wglGetCurrentContext (OPENGL32.@)
264 HGLRC WINAPI wglGetCurrentContext(void) {
265 GLXContext gl_ctx;
266 Wine_GLContext *ret;
268 TRACE("()\n");
270 ENTER_GL();
271 gl_ctx = glXGetCurrentContext();
272 ret = get_context_from_GLXContext(gl_ctx);
273 LEAVE_GL();
275 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
277 return (HGLRC)ret;
280 /***********************************************************************
281 * wglGetCurrentDC (OPENGL32.@)
283 HDC WINAPI wglGetCurrentDC(void) {
284 GLXContext gl_ctx;
285 Wine_GLContext *ret;
287 TRACE("()\n");
289 ENTER_GL();
290 gl_ctx = glXGetCurrentContext();
291 ret = get_context_from_GLXContext(gl_ctx);
292 LEAVE_GL();
294 if (ret) {
295 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
296 return ret->hdc;
297 } else {
298 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
299 return 0;
303 /***********************************************************************
304 * wglGetLayerPaletteEntries (OPENGL32.@)
306 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
307 int iLayerPlane,
308 int iStart,
309 int cEntries,
310 const COLORREF *pcr) {
311 FIXME("(): stub !\n");
313 return 0;
316 /***********************************************************************
317 * wglGetProcAddress (OPENGL32.@)
319 static int compar(const void *elt_a, const void *elt_b) {
320 return strcmp(((const OpenGL_extension *) elt_a)->name,
321 ((const OpenGL_extension *) elt_b)->name);
324 static int wgl_compar(const void *elt_a, const void *elt_b) {
325 return strcmp(((const WGL_extension *) elt_a)->func_name,
326 ((const WGL_extension *) elt_b)->func_name);
329 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
330 void *local_func;
331 OpenGL_extension ext;
332 OpenGL_extension *ext_ret;
334 TRACE("(%s)\n", lpszProc);
336 /* First, look if it's not already defined in the 'standard' OpenGL functions */
337 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
338 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
339 return local_func;
342 if (p_glXGetProcAddressARB == NULL) {
343 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
344 return NULL;
347 /* After that, search in the thunks to find the real name of the extension */
348 ext.name = (char *) lpszProc;
349 ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
350 extension_registry_size, sizeof(OpenGL_extension), compar);
352 if (ext_ret == NULL) {
353 WGL_extension wgl_ext, *wgl_ext_ret;
355 /* Try to find the function in the WGL extensions ... */
356 wgl_ext.func_name = (char *) lpszProc;
357 wgl_ext_ret = (WGL_extension *) bsearch(&wgl_ext, wgl_extension_registry,
358 wgl_extension_registry_size, sizeof(WGL_extension), wgl_compar);
360 if (wgl_ext_ret == NULL) {
361 /* Some sanity checks :-) */
362 ENTER_GL();
363 local_func = p_glXGetProcAddressARB( (const GLubyte *) lpszProc);
364 LEAVE_GL();
365 if (local_func != NULL) {
366 WARN("Extension %s defined in the OpenGL library but NOT in opengl_ext.c...\n", lpszProc);
367 return NULL;
370 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
371 return NULL;
372 } else {
373 void *ret = NULL;
375 if (wgl_ext_ret->func_init != NULL) {
376 const char *err_msg;
377 if ((err_msg = wgl_ext_ret->func_init(p_glXGetProcAddressARB,
378 wgl_ext_ret->context)) == NULL) {
379 ret = wgl_ext_ret->func_address;
380 } else {
381 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc), err_msg);
382 return NULL;
384 } else {
385 ret = wgl_ext_ret->func_address;
388 if (ret)
389 TRACE(" returning WGL function (%p)\n", ret);
390 return ret;
392 } else {
393 ENTER_GL();
394 local_func = p_glXGetProcAddressARB( (const GLubyte*) ext_ret->glx_name);
395 LEAVE_GL();
397 /* After that, look at the extensions defined in the Linux OpenGL library */
398 if (local_func == NULL) {
399 char buf[256];
400 void *ret = NULL;
402 /* Remove the 3 last letters (EXT, ARB, ...).
404 I know that some extensions have more than 3 letters (MESA, NV,
405 INTEL, ...), but this is only a stop-gap measure to fix buggy
406 OpenGL drivers (moreover, it is only useful for old 1.0 apps
407 that query the glBindTextureEXT extension).
409 memcpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
410 buf[strlen(ext_ret->glx_name) - 3] = '\0';
411 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
413 ret = GetProcAddress(opengl32_handle, buf);
414 if (ret != NULL) {
415 TRACE(" found function in main OpenGL library (%p) !\n", ret);
416 } else {
417 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
420 return ret;
421 } else {
422 TRACE(" returning function (%p)\n", ext_ret->func);
423 *(ext_ret->func_ptr) = local_func;
425 return ext_ret->func;
430 /***********************************************************************
431 * wglMakeCurrent (OPENGL32.@)
433 BOOL WINAPI wglMakeCurrent(HDC hdc,
434 HGLRC hglrc) {
435 BOOL ret;
437 TRACE("(%p,%p)\n", hdc, hglrc);
439 ENTER_GL();
440 if (hglrc == NULL) {
441 ret = glXMakeCurrent(default_display, None, NULL);
442 } else {
443 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
444 Drawable drawable = get_drawable( hdc );
446 if (ctx->ctx == NULL) {
447 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
448 TRACE(" created a delayed OpenGL context (%p) for %p\n", ctx->ctx, ctx->vis);
450 TRACE(" make current for dis %p, drawable %p, ctx %p\n", ctx->display, (void*) drawable, ctx->ctx);
451 ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
453 LEAVE_GL();
454 TRACE(" returning %s\n", (ret ? "True" : "False"));
455 return ret;
458 /***********************************************************************
459 * wglMakeContextCurrentARB (OPENGL32.@)
461 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
463 BOOL ret;
464 TRACE("(%p,%p,%p)\n", hDrawDC, hReadDC, hglrc);
466 ENTER_GL();
467 if (hglrc == NULL) {
468 ret = glXMakeCurrent(default_display, None, NULL);
469 } else {
470 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
471 Drawable d_draw = get_drawable( hDrawDC );
472 Drawable d_read = get_drawable( hReadDC );
474 if (ctx->ctx == NULL) {
475 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
476 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
478 ret = glXMakeContextCurrent(ctx->display, d_draw, d_read, ctx->ctx);
480 LEAVE_GL();
482 TRACE(" returning %s\n", (ret ? "True" : "False"));
483 return ret;
486 /***********************************************************************
487 * wglGetCurrentReadDCARB (OPENGL32.@)
489 HDC WINAPI wglGetCurrentReadDCARB(void)
491 GLXDrawable gl_d;
492 HDC ret;
494 TRACE("()\n");
496 ENTER_GL();
497 gl_d = glXGetCurrentReadDrawable();
498 ret = get_hdc_from_Drawable(gl_d);
499 LEAVE_GL();
501 TRACE(" returning %p (GL drawable %lu)\n", ret, gl_d);
502 return ret;
507 /***********************************************************************
508 * wglRealizeLayerPalette (OPENGL32.@)
510 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
511 int iLayerPlane,
512 BOOL bRealize) {
513 FIXME("()\n");
515 return FALSE;
518 /***********************************************************************
519 * wglSetLayerPaletteEntries (OPENGL32.@)
521 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
522 int iLayerPlane,
523 int iStart,
524 int cEntries,
525 const COLORREF *pcr) {
526 FIXME("(): stub !\n");
528 return 0;
531 /***********************************************************************
532 * wglShareLists (OPENGL32.@)
534 BOOL WINAPI wglShareLists(HGLRC hglrc1,
535 HGLRC hglrc2) {
536 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
537 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
539 TRACE("(%p, %p)\n", org, dest);
541 if (dest->ctx != NULL) {
542 ERR("Could not share display lists, context already created !\n");
543 return FALSE;
544 } else {
545 if (org->ctx == NULL) {
546 ENTER_GL();
547 org->ctx = glXCreateContext(org->display, org->vis, NULL, True);
548 LEAVE_GL();
549 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
552 ENTER_GL();
553 /* Create the destination context with display lists shared */
554 dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, True);
555 LEAVE_GL();
556 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
559 return TRUE;
562 /***********************************************************************
563 * wglSwapLayerBuffers (OPENGL32.@)
565 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
566 UINT fuPlanes) {
567 TRACE("(%p, %08x)\n", hdc, fuPlanes);
569 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
570 if (!SwapBuffers(hdc)) return FALSE;
571 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
574 if (fuPlanes) {
575 WARN("Following layers unhandled : %08x\n", fuPlanes);
578 return TRUE;
581 static BOOL internal_wglUseFontBitmaps(HDC hdc,
582 DWORD first,
583 DWORD count,
584 DWORD listBase,
585 DWORD WINAPI (*GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
587 /* We are running using client-side rendering fonts... */
588 GLYPHMETRICS gm;
589 unsigned int glyph;
590 int size = 0;
591 void *bitmap = NULL, *gl_bitmap = NULL;
592 int org_alignment;
594 ENTER_GL();
595 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
596 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
597 LEAVE_GL();
599 for (glyph = first; glyph < first + count; glyph++) {
600 unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
601 int height, width_int;
603 TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
604 if (needed_size == GDI_ERROR) {
605 TRACE(" - needed size : %d (GDI_ERROR)\n", needed_size);
606 goto error;
607 } else {
608 TRACE(" - needed size : %d\n", needed_size);
611 if (needed_size > size) {
612 size = needed_size;
613 HeapFree(GetProcessHeap(), 0, bitmap);
614 HeapFree(GetProcessHeap(), 0, gl_bitmap);
615 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
616 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
618 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
619 if (TRACE_ON(opengl)) {
620 unsigned int height, width, bitmask;
621 unsigned char *bitmap_ = (unsigned char *) bitmap;
623 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
624 TRACE(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
625 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
626 if (needed_size != 0) {
627 TRACE(" - bitmap : \n");
628 for (height = 0; height < gm.gmBlackBoxY; height++) {
629 TRACE(" ");
630 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
631 if (bitmask == 0) {
632 bitmap_ += 1;
633 bitmask = 0x80;
635 if (*bitmap_ & bitmask)
636 TRACE("*");
637 else
638 TRACE(" ");
640 bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
641 TRACE("\n");
646 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
647 * glyph for it to be drawn properly.
649 if (needed_size != 0) {
650 width_int = (gm.gmBlackBoxX + 31) / 32;
651 for (height = 0; height < gm.gmBlackBoxY; height++) {
652 int width;
653 for (width = 0; width < width_int; width++) {
654 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
655 ((int *) bitmap)[height * width_int + width];
660 ENTER_GL();
661 glNewList(listBase++, GL_COMPILE);
662 if (needed_size != 0) {
663 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
664 0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
665 gm.gmCellIncX, gm.gmCellIncY,
666 gl_bitmap);
667 } else {
668 /* This is the case of 'empty' glyphs like the space character */
669 glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
671 glEndList();
672 LEAVE_GL();
675 ENTER_GL();
676 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
677 LEAVE_GL();
679 HeapFree(GetProcessHeap(), 0, bitmap);
680 HeapFree(GetProcessHeap(), 0, gl_bitmap);
681 return TRUE;
683 error:
684 ENTER_GL();
685 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
686 LEAVE_GL();
688 HeapFree(GetProcessHeap(), 0, bitmap);
689 HeapFree(GetProcessHeap(), 0, gl_bitmap);
690 return FALSE;
693 /***********************************************************************
694 * wglUseFontBitmapsA (OPENGL32.@)
696 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
697 DWORD first,
698 DWORD count,
699 DWORD listBase)
701 Font fid = get_font( hdc );
703 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
705 if (fid == 0) {
706 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
709 ENTER_GL();
710 /* I assume that the glyphs are at the same position for X and for Windows */
711 glXUseXFont(fid, first, count, listBase);
712 LEAVE_GL();
713 return TRUE;
716 /***********************************************************************
717 * wglUseFontBitmapsW (OPENGL32.@)
719 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
720 DWORD first,
721 DWORD count,
722 DWORD listBase)
724 Font fid = get_font( hdc );
726 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
728 if (fid == 0) {
729 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
732 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
734 ENTER_GL();
735 /* I assume that the glyphs are at the same position for X and for Windows */
736 glXUseXFont(fid, first, count, listBase);
737 LEAVE_GL();
738 return TRUE;
741 /***********************************************************************
742 * wglUseFontOutlinesA (OPENGL32.@)
744 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
745 DWORD first,
746 DWORD count,
747 DWORD listBase,
748 FLOAT deviation,
749 FLOAT extrusion,
750 int format,
751 LPGLYPHMETRICSFLOAT lpgmf) {
752 FIXME("(): stub !\n");
754 return FALSE;
757 const GLubyte * internal_glGetString(GLenum name) {
758 const char* GL_Extensions = NULL;
760 if (GL_EXTENSIONS != name) {
761 return glGetString(name);
764 if (NULL == internal_gl_extensions) {
765 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
767 TRACE("GL_EXTENSIONS reported:\n");
768 if (NULL == GL_Extensions) {
769 ERR("GL_EXTENSIONS returns NULL\n");
770 return NULL;
771 } else {
772 size_t len = strlen(GL_Extensions);
773 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
775 while (*GL_Extensions != 0x00) {
776 const char* Start = GL_Extensions;
777 char ThisExtn[256];
779 memset(ThisExtn, 0x00, sizeof(ThisExtn));
780 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
781 GL_Extensions++;
783 memcpy(ThisExtn, Start, (GL_Extensions - Start));
784 TRACE("- %s:", ThisExtn);
786 /* test if supported API is disabled by config */
787 if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
788 strcat(internal_gl_extensions, " ");
789 strcat(internal_gl_extensions, ThisExtn);
790 TRACE(" active\n");
791 } else {
792 TRACE(" deactived (by config)\n");
795 if (*GL_Extensions == ' ') GL_Extensions++;
799 return (const GLubyte *) internal_gl_extensions;
803 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
804 include all dependencies
806 #ifndef SONAME_LIBGL
807 #define SONAME_LIBGL "libGL.so"
808 #endif
810 /* This is for brain-dead applications that use OpenGL functions before even
811 creating a rendering context.... */
812 static BOOL process_attach(void)
814 XWindowAttributes win_attr;
815 Visual *rootVisual;
816 int num;
817 XVisualInfo template;
818 HDC hdc;
819 XVisualInfo *vis = NULL;
820 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
821 HMODULE mod = GetModuleHandleA( "winex11.drv" );
822 void *opengl_handle;
823 DWORD size = sizeof(internal_gl_disabled_extensions);
824 HKEY hkey = 0;
826 if (!root || !mod)
828 ERR("X11DRV not loaded. Cannot create default context.\n");
829 return FALSE;
832 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
833 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
835 hdc = GetDC(0);
836 default_display = get_display( hdc );
837 ReleaseDC( 0, hdc );
838 if (!default_display)
840 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
841 return FALSE;
844 ENTER_GL();
846 /* Try to get the visual from the Root Window. We can't use the standard (presumably
847 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
848 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
849 with mismatched visuals. Note that the Root Window visual may not be double
850 buffered, so apps actually attempting to render this way may flicker */
851 if (XGetWindowAttributes( default_display, root, &win_attr ))
853 rootVisual = win_attr.visual;
855 else
857 /* Get the default visual, since we can't seem to get the attributes from the
858 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
859 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
862 template.visualid = XVisualIDFromVisual(rootVisual);
863 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
864 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
865 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
866 XFree(vis);
867 LEAVE_GL();
869 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
870 if (opengl_handle != NULL) {
871 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
872 wine_dlclose(opengl_handle, NULL, 0);
873 if (p_glXGetProcAddressARB == NULL)
874 TRACE("could not find glXGetProcAddressARB in libGL.\n");
877 internal_gl_disabled_extensions[0] = 0;
878 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
879 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
880 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
882 RegCloseKey(hkey);
885 if (default_cx == NULL) {
886 ERR("Could not create default context.\n");
888 else
890 /* After context initialize also the list of supported WGL extensions. */
891 wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB, internal_gl_disabled_extensions);
893 return TRUE;
897 /**********************************************************************/
899 static void process_detach(void)
901 glXDestroyContext(default_display, default_cx);
903 /* Do not leak memory... */
904 wgl_ext_finalize_extensions();
905 if (NULL != internal_gl_extensions) {
906 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
910 /***********************************************************************
911 * OpenGL initialisation routine
913 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
915 switch(reason)
917 case DLL_PROCESS_ATTACH:
918 opengl32_handle = hinst;
919 DisableThreadLibraryCalls(hinst);
920 return process_attach();
921 case DLL_PROCESS_DETACH:
922 process_detach();
923 break;
925 return TRUE;