[PATCH] Add a wine specific WGL extension which allows you to change the pixel format multiple times this is needed for WineD3D as D3D allows this and WGL not. The patch has been tested using a number of DirectX8/9 SDK samples which all work fine.

Roderick Colenbrander thunderbird2k at gmx.net
Tue Apr 22 17:15:15 CDT 2008


---
 dlls/gdi32/driver.c               |    1 +
 dlls/gdi32/gdi_private.h          |    1 +
 dlls/gdi32/opengl.c               |   22 ++++++++++++++++
 dlls/wined3d/context.c            |   12 ++++++++-
 dlls/wined3d/directx.c            |    4 +++
 dlls/winex11.drv/opengl.c         |   49 +++++++++++++++++++++++++++++++++++++
 dlls/winex11.drv/window.c         |   18 ++++++++++++-
 dlls/winex11.drv/winex11.drv.spec |    1 +
 include/wine/wined3d_gl.h         |    6 ++++-
 9 files changed, 110 insertions(+), 4 deletions(-)

diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index 8d75803..3a2776c 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -203,6 +203,7 @@ static struct graphics_driver *create_driver( HMODULE module )
         GET_FUNC(wglGetPbufferDCARB);
         GET_FUNC(wglMakeContextCurrentARB);
         GET_FUNC(wglMakeCurrent);
+        GET_FUNC(wglSetPixelFormatWINE);
         GET_FUNC(wglShareLists);
         GET_FUNC(wglUseFontBitmapsA);
         GET_FUNC(wglUseFontBitmapsW);
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index e3a320a..cbca896 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -230,6 +230,7 @@ typedef struct tagDC_FUNCS
     HDC      (*pwglGetPbufferDCARB)(PHYSDEV, void*);
     BOOL     (*pwglMakeCurrent)(PHYSDEV, HGLRC);
     BOOL     (*pwglMakeContextCurrentARB)(PHYSDEV, PHYSDEV, HGLRC);
+    BOOL     (*pwglSetPixelFormatWINE)(PHYSDEV,INT,const PIXELFORMATDESCRIPTOR *);
     BOOL     (*pwglShareLists)(HGLRC hglrc1, HGLRC hglrc2);
     BOOL     (*pwglUseFontBitmapsA)(PHYSDEV, DWORD, DWORD, DWORD);
     BOOL     (*pwglUseFontBitmapsW)(PHYSDEV, DWORD, DWORD, DWORD);
diff --git a/dlls/gdi32/opengl.c b/dlls/gdi32/opengl.c
index f948cda..f0810a8 100644
--- a/dlls/gdi32/opengl.c
+++ b/dlls/gdi32/opengl.c
@@ -240,6 +240,26 @@ static BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglr
     return ret;
 }
 
+/**************************************************************************************
+ *      WINE-specific wglSetPixelFormat which can set the iPixelFormat multiple times
+ *
+ */
+static BOOL WINAPI wglSetPixelFormatWINE(HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd)
+{
+    INT bRet = FALSE;
+    DC * dc = get_dc_ptr( hdc );
+
+    TRACE("(%p,%d,%p)\n", hdc, iPixelFormat, ppfd);
+
+    if (!dc) return 0;
+
+    if (!dc->funcs->pwglSetPixelFormatWINE) FIXME(" :stub\n");
+    else bRet = dc->funcs->pwglSetPixelFormatWINE(dc->physDev, iPixelFormat, ppfd);
+
+    release_dc_ptr( dc );
+    return bRet;
+}
+
 /***********************************************************************
  *		wglShareLists (OPENGL32.@)
  */
@@ -333,6 +353,8 @@ PROC WINAPI wglGetProcAddress(LPCSTR func)
         return (PROC)wglMakeContextCurrentARB;
     else if(ret && strcmp(func, "wglGetPbufferDCARB") == 0)
         return (PROC)wglGetPbufferDCARB;
+    else if(ret && strcmp(func, "wglSetPixelFormatWINE") == 0)
+        return (PROC)wglSetPixelFormatWINE;
 
     return ret;
 }
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 67baee5..bbcdde6 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -296,7 +296,17 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
         if(!res) {
             int oldPixelFormat = GetPixelFormat(hdc);
 
-            if(oldPixelFormat) {
+            /* By default WGL doesn't allow pixel format adjustments but we need it here.
+             * For this reason there is a WINE-specific wglSetPixelFormat which allows you to
+             * set the pixel format multiple times. Only use it when it is really needed. */
+            if(oldPixelFormat && GL_SUPPORT(WGL_WINE_PIXEL_FORMAT_PASSTHROUGH)) {
+                res = GL_EXTCALL(wglSetPixelFormatWINE(hdc, iPixelFormat, NULL));
+
+                if(!res) {
+                    ERR("wglSetPixelFormatWINE failed on HDC=%p for iPixelFormat=%d\n", hdc, iPixelFormat);
+                    return FALSE;
+                }
+            } else if(oldPixelFormat) {
                 /* OpenGL doesn't allow pixel format adjustments. Print an error and continue using the old format.
                  * There's a big chance that the old format works although with a performance hit and perhaps rendering errors. */
                 ERR("HDC=%p is already set to iPixelFormat=%d and OpenGL doesn't allow changes!\n", hdc, oldPixelFormat);
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 6c16bc3..ae649e2 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -1377,6 +1377,10 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
                     gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
                     TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
                 }
+                if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
+                    gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
+                    TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
+                }
             }
         }
     }
diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c
index 0338d06..6a5b3d0 100644
--- a/dlls/winex11.drv/opengl.c
+++ b/dlls/winex11.drv/opengl.c
@@ -3119,6 +3119,28 @@ static void WINAPI X11DRV_wglFreeMemoryNV(GLvoid* pointer) {
 }
 
 /**
+ * X11DRV_wglSetPixelFormatWINE
+ *
+ * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
+ * This is a WINE-specific wglSetPixelFormat which can set the pixel format multiple times.
+ */
+BOOL X11DRV_wglSetPixelFormatWINE(X11DRV_PDEVICE *physDev, int iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd)
+{
+    TRACE("(%p,%d,%p)\n", physDev, iPixelFormat, ppfd);
+
+    /* When the requested pixel format differs from the physDev its pixel format AND
+     * the physDev has a pixel format set, clear current_pf, so that SetPixelFormat
+     * will set the pixel format again. */
+    if((physDev->current_pf != 0) && (physDev->current_pf != iPixelFormat)) {
+        TRACE("Changing iPixelFormat from %d to %d\n", physDev->current_pf, iPixelFormat);
+        physDev->current_pf = 0;
+    }
+
+    /* Relay to the normal SetPixelFormat */
+    return X11DRV_SetPixelFormat(physDev, iPixelFormat, ppfd);
+}
+
+/**
  * glxRequireVersion (internal)
  *
  * Check if the supported GLX version matches requiredVersion.
@@ -3256,6 +3278,14 @@ static const WineGLExtension WGL_NV_vertex_array_range =
   }
 };
 
+static const WineGLExtension WGL_WINE_pixel_format_passthrough =
+{
+  "WGL_WINE_pixel_format_passthrough",
+  {
+    { "wglSetPixelFormatWINE", X11DRV_wglSetPixelFormatWINE },
+  }
+};
+
 /**
  * X11DRV_WineGL_LoadExtensions
  */
@@ -3325,6 +3355,13 @@ static void X11DRV_WineGL_LoadExtensions(void)
     /* The OpenGL extension GL_NV_vertex_array_range adds wgl/glX functions which aren't exported as 'real' wgl/glX extensions. */
     if(strstr(WineGLInfo.glExtensions, "GL_NV_vertex_array_range") != NULL)
         register_extension(&WGL_NV_vertex_array_range);
+
+    /* WINE-specific WGL Extensions */
+
+    /* In WineD3D we need the ability to set the pixel format more than once (e.g. after a device reset).
+     * The default wglSetPixelFormat doesn't allow this, so add our own which allows it.
+     */
+    register_extension(&WGL_WINE_pixel_format_passthrough);
 }
 
 
@@ -3588,6 +3625,18 @@ BOOL X11DRV_wglUseFontBitmapsW(X11DRV_PDEVICE *physDev, DWORD first, DWORD count
     return FALSE;
 }
 
+/**
+ * X11DRV_wglSetPixelFormatWINE
+ *
+ * WGL_WINE_pixel_format_passthrough: wglSetPixelFormatWINE
+ * This is a WINE-specific wglSetPixelFormat which can set the pixel format multiple times.
+ */
+BOOL X11DRV_wglSetPixelFormatWINE(X11DRV_PDEVICE *physDev, int iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd)
+{
+    ERR_(opengl)("No OpenGL support compiled in.\n");
+    return FALSE;
+}
+
 Drawable get_glxdrawable(X11DRV_PDEVICE *physDev)
 {
     return 0;
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 996bb8e..89b5086 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -400,8 +400,6 @@ BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
     if (!(data = X11DRV_get_win_data(hwnd)) &&
         !(data = X11DRV_create_win_data(hwnd))) return FALSE;
 
-    if (data->fbconfig_id) return FALSE;  /* can't change it twice */
-
     wine_tsx11_lock();
     vis = visual_from_fbconfig_id(fbconfig_id);
     wine_tsx11_unlock();
@@ -446,6 +444,11 @@ BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
         attrib.colormap = data->colormap;
         XInstallColormap(gdi_display, attrib.colormap);
 
+        /* Destroy the gl_drawable if we already have one. This code is only entered when
+         * a pixel format change was requested by WineD3D. */
+        if(data->gl_drawable)
+            XDestroyWindow(gdi_display, data->gl_drawable);
+
         data->gl_drawable = XCreateWindow(display, parent, -w, 0, w, h, 0,
                                           vis->depth, InputOutput, vis->visual,
                                           CWColormap | CWOverrideRedirect,
@@ -465,6 +468,12 @@ BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
         WARN("XComposite is not available, using GLXPixmap hack\n");
 
         wine_tsx11_lock();
+
+        /* Destroy the pixmap if we already have one. This code is only entered when
+         * a pixel format change was requested by WineD3D. */
+        if(data->pixmap)
+            XFreePixmap(display, data->pixmap);
+
         data->pixmap = XCreatePixmap(display, root_window, w, h, vis->depth);
         if(!data->pixmap)
         {
@@ -473,6 +482,11 @@ BOOL X11DRV_set_win_format( HWND hwnd, XID fbconfig_id )
             return FALSE;
         }
 
+        /* Destroy the gl_drawable if we already have one. This code is only entered when
+         * a pixel format change was requested by WineD3D. */
+        if(data->gl_drawable)
+            destroy_glxpixmap(display, data->gl_drawable);
+
         data->gl_drawable = create_glxpixmap(display, vis, data->pixmap);
         if(!data->gl_drawable)
         {
diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec
index 959721d..6d469f8 100644
--- a/dlls/winex11.drv/winex11.drv.spec
+++ b/dlls/winex11.drv/winex11.drv.spec
@@ -142,6 +142,7 @@
 @ cdecl wglGetPbufferDCARB(ptr ptr) X11DRV_wglGetPbufferDCARB
 @ cdecl wglMakeContextCurrentARB(ptr ptr long) X11DRV_wglMakeContextCurrentARB
 @ cdecl wglMakeCurrent(ptr long) X11DRV_wglMakeCurrent
+@ cdecl wglSetPixelFormatWINE(ptr long ptr) X11DRV_wglSetPixelFormatWINE
 @ cdecl wglShareLists(long long) X11DRV_wglShareLists
 @ cdecl wglUseFontBitmapsA(ptr long long long) X11DRV_wglUseFontBitmapsA
 @ cdecl wglUseFontBitmapsW(ptr long long long) X11DRV_wglUseFontBitmapsW
diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h
index 02432db..2467a73 100644
--- a/include/wine/wined3d_gl.h
+++ b/include/wine/wined3d_gl.h
@@ -3373,6 +3373,7 @@ typedef enum _GL_SupportedExt {
 
   /* WGL extensions */
   WGL_ARB_PBUFFER,
+  WGL_WINE_PIXEL_FORMAT_PASSTHROUGH,
 
   OPENGL_SUPPORTED_EXT_END
 } GL_SupportedExt;
@@ -3762,6 +3763,8 @@ typedef BOOL (WINAPI * WINED3D_PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer,
 #define WGL_ARB_pixel_format_float 1
 #define WGL_TYPE_RGBA_FLOAT_ARB        0x21A0
 #endif
+/* WGL_WINE_pixel_format_passthrough */
+typedef BOOL (WINAPI * WINED3D_PFNWGLSETPIXELFORMATWINE) (HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR* ppfd);
 
 #define WGL_EXT_FUNCS_GEN \
     USE_GL_FUNC(WINED3D_PFNWGLGETEXTENSIONSSTRINGARBPROC, wglGetExtensionsStringARB, 0, NULL); \
@@ -3774,7 +3777,8 @@ typedef BOOL (WINAPI * WINED3D_PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer,
     USE_GL_FUNC(WINED3D_PFNWGLGETPBUFFERDCARBPROC, wglGetPbufferDCARB, 0, NULL); \
     USE_GL_FUNC(WINED3D_PFNWGLRELEASEPBUFFERDCARBPROC, wglReleasePbufferDCARB, 0, NULL); \
     USE_GL_FUNC(WINED3D_PFNWGLDESTROYPBUFFERARBPROC, wglDestroyPbufferARB, 0, NULL); \
-    USE_GL_FUNC(WINED3D_PFNWGLQUERYPBUFFERARBPROC, wglQueryPbufferARB, 0, NULL);
+    USE_GL_FUNC(WINED3D_PFNWGLQUERYPBUFFERARBPROC, wglQueryPbufferARB, 0, NULL) \
+    USE_GL_FUNC(WINED3D_PFNWGLSETPIXELFORMATWINE, wglSetPixelFormatWINE, 0, NULL);
 
 
 /****************************************************
-- 
1.5.3.4


--========GMX195951208895482616239--



More information about the wine-patches mailing list