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