[PATCH] Add a WINE-specific WGL extension 'WGL_WINE_pixel_format_passthrough' to allow wined3d to change the pixel format of a HDC multiple times. This happens e.g. on a device reset. It was tested on DirectX8 SDK samples and appears to work fine.

Roderick Colenbrander thunderbird2k at gmx.net
Thu Mar 6 16:35:32 CST 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         |    2 -
 dlls/winex11.drv/winex11.drv.spec |    1 +
 include/wine/wined3d_gl.h         |    6 ++++-
 9 files changed, 94 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 52b1099..592bf72 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -288,7 +288,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 04af700..81783f1 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -1347,6 +1347,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 33b09d3..72d8e57 100644
--- a/dlls/winex11.drv/opengl.c
+++ b/dlls/winex11.drv/opengl.c
@@ -3103,6 +3103,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.
@@ -3240,6 +3262,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
  */
@@ -3309,6 +3339,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);
 }
 
 
@@ -3572,6 +3609,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 3f3ac99..0628f3a 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -375,8 +375,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();
diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec
index 751da52..edef7ba 100644
--- a/dlls/winex11.drv/winex11.drv.spec
+++ b/dlls/winex11.drv/winex11.drv.spec
@@ -141,6 +141,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 1e45b20..76dbb4b 100644
--- a/include/wine/wined3d_gl.h
+++ b/include/wine/wined3d_gl.h
@@ -3293,6 +3293,7 @@ typedef enum _GL_SupportedExt {
 
   /* WGL extensions */
   WGL_ARB_PBUFFER,
+  WGL_WINE_PIXEL_FORMAT_PASSTHROUGH,
 
   OPENGL_SUPPORTED_EXT_END
 } GL_SupportedExt;
@@ -3667,6 +3668,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); \
@@ -3679,7 +3682,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


--========GMX309511204843001623827--



More information about the wine-patches mailing list