opengl32: Correctly size and position opengl child windows

Aaron Slunt tonglebeak at gmail.com
Thu Oct 5 23:16:57 CDT 2006


Ulrich Czekalla wrote:
> 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
>   
Unfortunately, this doesn't seem to fix Valve Hammer Editor. On top of 
that, hammer never spit out any errors to the console before, now the 
console is filled with:

err:syslevel:_EnterSysLevel (0x7ed4a220, level 2): Holding 0x7ec3d9e0, 
level 3. Expect deadlock!





More information about the wine-devel mailing list