OpenGL 'hack' patch

Lionel Ulmer lionel.ulmer at free.fr
Mon Aug 5 08:55:55 CDT 2002


Hi all,

To make NWN's model viewer work in Wine, I did the attached patch...
Warning, it's not for the faint of heart so ugly it is :-)

Basically, the plan is to have two drawable per DC in the X11 driver, one
for 'normal' drawings, the other for OpenGL drawings, the latter being the
one associated with the window when goind a CLIPSIBLINGS GetDCEx.

Now to do this 'nicely', the 'use ExtEscape to store data' method is not the
right one (but it works :-) ).

So my current plan is to really separate all the X11 stuff into the X11DRV
and to have a 'portable' opengl32.dll library. Now my question is 'how to do
this properly' ? Is extending the 'dc' function pointer array with all the
needed OpenGL functions a way (even if these functions are NOT GDI functions
but pure OpenGL) ? The problem with this solution is that I would need to
use the 'DC_GetDCPtr' function outside of GDI (and that may break DLL
separation).

Another solution could be to add all the OpenGL functions as GDI functions,
do the DC function pointer thing and then put a forward from all the wgl
functions to the GDI32.* functions.

What do you all think of it ?

                        Lionel

-- 
		 Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
Index: graphics/x11drv/init.c
===================================================================
RCS file: /home/wine/wine/graphics/x11drv/init.c,v
retrieving revision 1.53
diff -u -r1.53 init.c
--- graphics/x11drv/init.c	3 Jul 2002 01:16:46 -0000	1.53
+++ graphics/x11drv/init.c	5 Aug 2002 13:44:18 -0000
@@ -294,6 +294,14 @@
                     *(Font *)out_data = pfo->fs->fid;
                     return TRUE;
                 }
+		break;
+	    case X11DRV_SET_GL_DRAWABLE:
+                if (out_count >= sizeof(Drawable))
+                {
+		    physDev->gl_drawable = *(Drawable *)out_data;
+                    return TRUE;
+                }
+		break;	
             }
         }
         break;
Index: graphics/x11drv/opengl.c
===================================================================
RCS file: /home/wine/wine/graphics/x11drv/opengl.c,v
retrieving revision 1.10
diff -u -r1.10 opengl.c
--- graphics/x11drv/opengl.c	31 May 2002 23:06:48 -0000	1.10
+++ graphics/x11drv/opengl.c	5 Aug 2002 13:44:18 -0000
@@ -317,7 +317,7 @@
   TRACE("(%p)\n", physDev);
 
   ENTER_GL();
-  glXSwapBuffers(gdi_display, physDev->drawable);
+  glXSwapBuffers(gdi_display, physDev->gl_drawable);
   LEAVE_GL();
 
   return TRUE;
Index: include/x11drv.h
===================================================================
RCS file: /home/wine/wine/include/x11drv.h,v
retrieving revision 1.111
diff -u -r1.111 x11drv.h
--- include/x11drv.h	14 Jun 2002 00:08:40 -0000	1.111
+++ include/x11drv.h	5 Aug 2002 13:44:25 -0000
@@ -82,6 +82,7 @@
     DC           *dc;          /* direct pointer to DC, should go away */
     GC            gc;          /* X Window GC */
     Drawable      drawable;
+    Drawable      gl_drawable;
     POINT         org;          /* DC origin relative to drawable */
     POINT         drawable_org; /* Origin of drawable relative to screen */
     X_PHYSFONT    font;
@@ -310,9 +311,10 @@
 #define X11DRV_ESCAPE 6789
 enum x11drv_escape_codes
 {
-    X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
-    X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
-    X11DRV_GET_FONT,      /* get current X font for a DC */
+    X11DRV_GET_DISPLAY,     /* get X11 display for a DC */
+    X11DRV_GET_DRAWABLE,    /* get current drawable for a DC */
+    X11DRV_GET_FONT,        /* get current X font for a DC */
+    X11DRV_SET_GL_DRAWABLE, /* sets the GL drawable for a DC */
 };
 
 /**************************************************************************
Index: dlls/opengl32/wgl.c
===================================================================
RCS file: /home/wine/wine/dlls/opengl32/wgl.c,v
retrieving revision 1.26
diff -u -r1.26 wgl.c
--- dlls/opengl32/wgl.c	8 Jul 2002 19:34:26 -0000	1.26
+++ dlls/opengl32/wgl.c	5 Aug 2002 13:44:32 -0000
@@ -108,7 +108,7 @@
 }
 
 
-/* retrieve the X drawable to use on a given DC */
+/* retrieve the X font to use on a given DC */
 inline static Font get_font( HDC hdc )
 {
     Font font;
@@ -119,6 +119,14 @@
     return font;
 }
 
+/* retrieve the X font to use on a given DC */
+inline static int set_gl_drawable( HDC hdc, Drawable gl_drawable )
+{
+    enum x11drv_escape_codes escape = X11DRV_SET_GL_DRAWABLE;
+
+    return ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
+		     sizeof(gl_drawable), (LPSTR)&gl_drawable );
+}
 
 /***********************************************************************
  *		wglCreateContext (OPENGL32.@)
@@ -362,8 +370,27 @@
       ret = glXMakeCurrent(default_display, None, NULL);
   } else {
       Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
-      Drawable drawable = get_drawable( hdc );
+      Drawable drawable;
+      HWND gl_hwnd;
 
+      /* This is an (ugly) hack due to incompatibilities between how the X11 driver handles
+	 DCs and how GLX is using them. */
+      gl_hwnd = WindowFromDC(hdc);
+      if (gl_hwnd != 0) {
+	  HDC gl_hdc = GetDCEx(gl_hwnd, 0, DCX_CACHE | DCX_CLIPSIBLINGS);
+	  drawable = get_drawable( gl_hdc );
+	  ReleaseDC(gl_hwnd, gl_hdc);
+      } else {
+	  drawable = get_drawable( hdc );
+      }
+
+      /* Whatever the case, set the GL drawable for this HDC */
+      if (!set_gl_drawable(hdc, drawable)) {
+	  ERR("Error setting the GL drawable - returning False !\n");
+	  LEAVE_GL();
+	  return FALSE;
+      }
+      
       if (ctx->ctx == NULL) {
 	ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
 	TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);


More information about the wine-devel mailing list