opengl32: Correctly size and position opengl child windows

Ulrich Czekalla ulrich.czekalla at utoronto.ca
Thu Oct 5 14:52:33 CDT 2006


This patch override glViewport and glScissor to correctly position and size
opengl child windows.

I've only tested this patch with Google Earth and Google Sketchup so I'd
like to get some feedback to see if this solves the problem for your
application.

Roderick: I realize you're currently reworking opengl32 so let me know if
this conflicts with what you are doing.

Thanks,

/Ulrich

---

 dlls/opengl32/make_opengl         |   15 +++++++
 dlls/opengl32/opengl_ext.h        |    5 ++
 dlls/opengl32/opengl_norm.c       |   10 ++---
 dlls/opengl32/wgl.c               |   78 +++++++++++++++++++++++++++++++++++++
 dlls/winex11.drv/opengl.c         |   72 ++++++++++++++++++++++++++++++++--
 dlls/winex11.drv/winex11.drv.spec |    1 
 6 files changed, 172 insertions(+), 9 deletions(-)

6b6a26ef714827017c5ae438b2f843766d711cb2
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl
index 837b8d9..bfb0191 100755
--- a/dlls/opengl32/make_opengl
+++ b/dlls/opengl32/make_opengl
@@ -266,6 +266,21 @@ sub GenerateThunk($$$$$)
     if ( $func_ref->[0] eq "glGetIntegerv" ) {
 	$wine_func_ref_name = "internal_glGetIntegerv";
     }
+    if ( $func_ref->[0] eq "glEnable" ) {
+	$wine_func_ref_name = "internal_glEnable";
+    }
+    if ( $func_ref->[0] eq "glIsEnable" ) {
+	$wine_func_ref_name = "internal_glIsEnable";
+    }
+    if ( $func_ref->[0] eq "glDisable" ) {
+	$wine_func_ref_name = "internal_glDisable";
+    }
+    if ( $func_ref->[0] eq "glScissorr" ) {
+	$wine_func_ref_name = "internal_glScissorr";
+    }
+    if ( $func_ref->[0] eq "glViewport" ) {
+	$wine_func_ref_name = "internal_glViewport";
+    }
     $ret = "$ret$prefix$wine_func_ref_name( $call_arg);\n";
     if ($thread_safe) {
 	$ret = "$ret  LEAVE_GL();\n";
diff --git a/dlls/opengl32/opengl_ext.h b/dlls/opengl32/opengl_ext.h
index a7fe233..b7263df 100644
--- a/dlls/opengl32/opengl_ext.h
+++ b/dlls/opengl32/opengl_ext.h
@@ -75,5 +75,10 @@ extern const int extension_registry_size
 
 const GLubyte* internal_glGetString(GLenum name);
 void internal_glGetIntegerv(GLenum pname, GLint* params);
+void internal_glDisable(GLenum cap);
+void internal_glEnable(GLenum cap);
+GLboolean internal_glIsEnabled(GLenum cap);
+void internal_glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
+void internal_glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
 
 #endif /* __DLLS_OPENGL32_OPENGL_EXT_H */
diff --git a/dlls/opengl32/opengl_norm.c b/dlls/opengl32/opengl_norm.c
index 8374a86..047770f 100644
--- a/dlls/opengl32/opengl_norm.c
+++ b/dlls/opengl32/opengl_norm.c
@@ -815,7 +815,7 @@ void WINAPI wine_glDepthRange( GLclampd 
 void WINAPI wine_glDisable( GLenum cap ) {
   TRACE("(%d)\n", cap );
   ENTER_GL();
-  glDisable( cap );
+  internal_glDisable( cap );
   LEAVE_GL();
 }
 
@@ -915,7 +915,7 @@ void WINAPI wine_glEdgeFlagv( GLboolean*
 void WINAPI wine_glEnable( GLenum cap ) {
   TRACE("(%d)\n", cap );
   ENTER_GL();
-  glEnable( cap );
+  internal_glEnable( cap );
   LEAVE_GL();
 }
 
@@ -1772,7 +1772,7 @@ GLboolean WINAPI wine_glIsEnabled( GLenu
   GLboolean ret_value;
   TRACE("(%d)\n", cap );
   ENTER_GL();
-  ret_value = glIsEnabled( cap );
+  ret_value = internal_glIsEnabled( cap );
   LEAVE_GL();
   return ret_value;
 }
@@ -2889,7 +2889,7 @@ void WINAPI wine_glScalef( GLfloat x, GL
 void WINAPI wine_glScissor( GLint x, GLint y, GLsizei width, GLsizei height ) {
   TRACE("(%d, %d, %d, %d)\n", x, y, width, height );
   ENTER_GL();
-  glScissor( x, y, width, height );
+  internal_glScissor( x, y, width, height );
   LEAVE_GL();
 }
 
@@ -3759,6 +3759,6 @@ void WINAPI wine_glVertexPointer( GLint 
 void WINAPI wine_glViewport( GLint x, GLint y, GLsizei width, GLsizei height ) {
   TRACE("(%d, %d, %d, %d)\n", x, y, width, height );
   ENTER_GL();
-  glViewport( x, y, width, height );
+  internal_glViewport( x, y, width, height );
   LEAVE_GL();
 }
diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c
index 1c3973c..76785d7 100644
--- a/dlls/opengl32/wgl.c
+++ b/dlls/opengl32/wgl.c
@@ -84,6 +84,7 @@ static Display *default_display;  /* dis
 static HMODULE opengl32_handle;
 
 static void* (*p_glXGetProcAddressARB)(const GLubyte *);
+static void  (*p_SyncCurrentDrawable)();
 
 static char  internal_gl_disabled_extensions[512];
 static char* internal_gl_extensions = NULL;
@@ -95,6 +96,9 @@ typedef struct wine_glcontext {
   GLXFBConfig fb_conf;
   GLXContext ctx;
   BOOL do_escape;
+  RECT viewport;
+  RECT scissor;
+  BOOL scissor_enabled;
   struct wine_glcontext *next;
   struct wine_glcontext *prev;
 } Wine_GLContext;
@@ -124,6 +128,7 @@ inline static Display *get_display( HDC 
     return display;
 }
 
+
 /***********************************************************************
  *		wglCreateLayerContext (OPENGL32.@)
  */
@@ -563,6 +568,72 @@ BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
     return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
 }
 
+
+void internal_glEnable(GLenum cap)
+{
+    if (cap == GL_SCISSOR_TEST)
+    {
+       Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
+       ctx->scissor_enabled = TRUE;
+    }
+    else
+    {
+       glEnable(cap);
+    }
+}
+
+GLboolean internal_glIsEnabled(GLenum cap)
+{
+    GLboolean enabled;
+
+    if (cap == GL_SCISSOR_TEST)
+    {
+       Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
+       enabled = ctx->scissor_enabled;
+    }
+    else
+    {
+       enabled = glIsEnabled(cap);
+    }
+
+    return enabled;
+}
+
+void internal_glDisable(GLenum cap)
+{
+    if (cap == GL_SCISSOR_TEST)
+    {
+       Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
+       ctx->scissor_enabled = FALSE;
+    }
+    else
+    {
+       glDisable(cap);
+    }
+}
+
+void internal_glScissor( GLint x, GLint y, GLsizei width, GLsizei height ) 
+{
+    Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
+
+    ctx->scissor.left = x;
+    ctx->scissor.top = y;
+    ctx->scissor.right = x + width;
+    ctx->scissor.bottom = y + height;
+
+    p_SyncCurrentDrawable();
+}
+
+void internal_glViewport( GLint x, GLint y, GLsizei width, GLsizei height ) 
+{
+    Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
+    ctx->viewport.left = x;
+    ctx->viewport.top = y;
+    ctx->viewport.right = x + width;
+    ctx->viewport.bottom = y + height;
+    p_SyncCurrentDrawable();
+}
+
 const GLubyte * internal_glGetString(GLenum name) {
   const char* GL_Extensions = NULL;
   
@@ -658,6 +729,13 @@ static BOOL process_attach(void)
   /* Interal WGL function */
   wine_wgl.p_wglGetIntegerv = (void *)GetProcAddress(mod, "wglGetIntegerv");
 
+  p_SyncCurrentDrawable = (void *)GetProcAddress(mod, "SyncCurrentDrawable");
+  if (!p_SyncCurrentDrawable)
+  {
+      ERR("Using incompatible version of winex11drv\n");
+      return FALSE;
+  }
+
   hdc = GetDC(0);
   default_display = get_display( hdc );
   ReleaseDC( 0, hdc );
diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c
index 64b1166..c8650a1 100644
--- a/dlls/winex11.drv/opengl.c
+++ b/dlls/winex11.drv/opengl.c
@@ -74,6 +74,9 @@ typedef struct wine_glcontext {
     GLXFBConfig fb_conf;
     GLXContext ctx;
     BOOL do_escape;
+    RECT viewport;
+    RECT scissor;
+    BOOL scissor_enabled;
     struct wine_glcontext *next;
     struct wine_glcontext *prev;
 } Wine_GLContext;
@@ -240,12 +243,15 @@ MAKE_FUNCPTR(glBitmap)
 MAKE_FUNCPTR(glCopyTexSubImage1D)
 MAKE_FUNCPTR(glCopyTexSubImage2D)
 MAKE_FUNCPTR(glDrawBuffer)
+MAKE_FUNCPTR(glEnable)
 MAKE_FUNCPTR(glEndList)
 MAKE_FUNCPTR(glGetError)
 MAKE_FUNCPTR(glGetIntegerv)
 MAKE_FUNCPTR(glGetString)
 MAKE_FUNCPTR(glNewList)
 MAKE_FUNCPTR(glPixelStorei)
+MAKE_FUNCPTR(glScissor)
+MAKE_FUNCPTR(glViewport)
 #undef MAKE_FUNCPTR
 
 BOOL X11DRV_WineGL_InitOpenglInfo()
@@ -363,15 +369,18 @@ LOAD_FUNCPTR(glXGetFBConfigs)
 /* Standard OpenGL calls */
 LOAD_FUNCPTR(glBindTexture)
 LOAD_FUNCPTR(glBitmap)
-LOAD_FUNCPTR(glEndList)
 LOAD_FUNCPTR(glCopyTexSubImage1D)
 LOAD_FUNCPTR(glCopyTexSubImage2D)
 LOAD_FUNCPTR(glDrawBuffer)
+LOAD_FUNCPTR(glEnable)
+LOAD_FUNCPTR(glEndList)
 LOAD_FUNCPTR(glGetError)
 LOAD_FUNCPTR(glGetIntegerv)
 LOAD_FUNCPTR(glGetString)
 LOAD_FUNCPTR(glNewList)
 LOAD_FUNCPTR(glPixelStorei)
+LOAD_FUNCPTR(glScissor)
+LOAD_FUNCPTR(glViewport)
 #undef LOAD_FUNCPTR
 
     if(!X11DRV_WineGL_InitOpenglInfo()) {
@@ -1353,6 +1362,54 @@ PROC X11DRV_wglGetProcAddress(LPCSTR lps
     return NULL;
 }
 
+/***********************************************************************
+ *		X11DRV_SyncCurrentDrawable
+ *
+ * Adjust the current viewport and stencil in order to position
+ * and size the current drawable correctly on the parent window.
+ */
+void X11DRV_SyncCurrentDrawable()
+{
+    RECT rc;
+    RECT rootrc;
+    HWND hwnd;
+    HWND roothwnd;
+    int width, height;
+    int rheight;
+    Wine_GLContext *ctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
+
+    if (ctx && (hwnd = WindowFromDC(ctx->hdc)) != 0)
+    {
+        roothwnd = GetAncestor(hwnd, GA_ROOT);
+
+        if (roothwnd != hwnd)
+        {
+            GetClientRect(roothwnd, &rootrc);
+            rheight = rootrc.bottom - rootrc.top;
+
+            GetWindowRect(hwnd, &rc);
+            width = rc.right - rc.left;
+            height = rc.bottom - rc.top;
+
+            MapWindowPoints(0, roothwnd, (LPPOINT)&rc, 2);
+
+            pglViewport(rc.left + ctx->viewport.left, rheight - rc.bottom + ctx->viewport.top,
+                ctx->viewport.right ? (ctx->viewport.right - ctx->viewport.left) : width,
+                ctx->viewport.bottom ? (ctx->viewport.bottom - ctx->viewport.top) : height);
+
+            pglEnable(GL_SCISSOR_TEST);
+
+            if (ctx->scissor_enabled)
+                pglScissor(rc.left + min(width, max(0, ctx->scissor.left)),
+                    rheight  - rc.bottom + min(height, max(0, ctx->scissor.top)),
+                    min(width, max(0, ctx->scissor.right - ctx->scissor.left)),
+                    min(height, max(0, ctx->scissor.bottom - ctx->scissor.top)));
+            else
+                pglScissor(rc.left, rheight - rc.bottom, width, height);
+
+        }
+    }
+}
 
 /* OpenGL32 wglMakeCurrent */
 BOOL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) {
@@ -1397,10 +1454,17 @@ BOOL X11DRV_wglMakeCurrent(X11DRV_PDEVIC
         TRACE(" make current for dis %p, drawable %p, ctx %p\n", ctx->display, (void*) drawable, ctx->ctx);
         ret = pglXMakeCurrent(ctx->display, drawable, ctx->ctx);
         NtCurrentTeb()->glContext = ctx;
-        if(ret && type == OBJ_MEMDC)
+        if(ret)
         {
-            ctx->do_escape = TRUE;
-            pglDrawBuffer(GL_FRONT_LEFT);
+            if (type == OBJ_MEMDC)
+            {
+                ctx->do_escape = TRUE;
+                pglDrawBuffer(GL_FRONT_LEFT);
+            }
+            else
+            {
+                X11DRV_SyncCurrentDrawable();
+            }
         }
     }
     wine_tsx11_unlock();
diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec
index 4e4dcbf..62e3197 100644
--- a/dlls/winex11.drv/winex11.drv.spec
+++ b/dlls/winex11.drv/winex11.drv.spec
@@ -139,3 +139,4 @@
 @ cdecl wglShareLists(long long) X11DRV_wglShareLists
 @ cdecl wglUseFontBitmapsA(long long long long) X11DRV_wglUseFontBitmapsA
 @ cdecl wglUseFontBitmapsW(long long long long) X11DRV_wglUseFontBitmapsW
+@ cdecl SyncCurrentDrawable() X11DRV_SyncCurrentDrawable
-- 
1.2.4



More information about the wine-patches mailing list