Stefan Dösinger : wined3d: Work around a bad crash in fglrx.

Alexandre Julliard julliard at winehq.org
Fri May 8 08:06:26 CDT 2009


Module: wine
Branch: master
Commit: 668328a697aaed3a7863c8c7e099e99471774bce
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=668328a697aaed3a7863c8c7e099e99471774bce

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Wed May  6 19:36:08 2009 +0200

wined3d: Work around a bad crash in fglrx.

---

 dlls/wined3d/context.c    |   10 ++++------
 dlls/wined3d/directx.c    |   38 +++++++++++++++++++++++++++++++++++++-
 dlls/wined3d/state.c      |   15 +++++++++++++--
 dlls/wined3d/wined3d_gl.h |    1 +
 4 files changed, 55 insertions(+), 9 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index a510d2e..2c6703f 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -895,12 +895,10 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
         }
     }
 
-    if(GL_SUPPORT(ARB_POINT_SPRITE)) {
-        for(s = 0; s < GL_LIMITS(textures); s++) {
-            GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + s));
-            glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
-            checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
-        }
+    for(s = 0; s < GL_LIMITS(point_sprite_units); s++) {
+        GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + s));
+        glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
+        checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
     }
     LEAVE_GL();
 
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 61927fc..d1f851a 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -1014,7 +1014,11 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
             /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float */
             gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
         }
-
+        if(gl_info->supported[ARB_POINT_SPRITE]) {
+            gl_info->max_point_sprite_units = gl_info->max_textures;
+        } else {
+            gl_info->max_point_sprite_units = 0;
+        }
     }
     checkGLcall("extension detection\n");
 
@@ -4031,6 +4035,13 @@ static BOOL match_apple_nonr500ati(const WineD3D_GL_Info *gl_info) {
     return TRUE;
 }
 
+static BOOL match_fglrx(const WineD3D_GL_Info *gl_info) {
+    if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
+    if(match_apple(gl_info)) return FALSE;
+    if(strstr(gl_info->gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers */
+    return TRUE;
+}
+
 static void quirk_arb_constants(WineD3D_GL_Info *gl_info) {
     TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL\n", gl_info->vs_arb_constantsF);
     gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
@@ -4048,6 +4059,26 @@ static void quirk_apple_glsl_constants(WineD3D_GL_Info *gl_info) {
     gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
 }
 
+/* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
+ * on more than one texture unit. This means that the d3d9 visual point size test will cause a
+ * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
+ * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
+ * most games, but avoids the crash
+ *
+ * A more sophisticated way would be to find all units that need texture coordinates and enable
+ * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
+ * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
+ *
+ * Note that disabling the extension entirely does not gain predictability because there is no point
+ * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension.
+ */
+static void quirk_one_point_sprite(WineD3D_GL_Info *gl_info) {
+    if(gl_info->supported[ARB_POINT_SPRITE]) {
+        TRACE("Limiting point sprites to one texture unit\n");
+        gl_info->max_point_sprite_units = 1;
+    }
+}
+
 static void quirk_ati_dx9(WineD3D_GL_Info *gl_info) {
     quirk_arb_constants(gl_info);
 
@@ -4146,6 +4177,11 @@ struct driver_quirk quirk_table[] = {
         match_apple_nonr500ati,
         quirk_texcoord_w,
         "Init texcoord .w for Apple ATI >= r600 GPU driver"
+    },
+    {
+        match_fglrx,
+        quirk_one_point_sprite,
+        "Fglrx point sprite crash workaround"
     }
 };
 
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index b1fbadf..ad1593c 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -1503,14 +1503,25 @@ static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, Win
 }
 
 static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
+    BOOL warned = FALSE;
     /* TODO: NV_POINT_SPRITE */
-    if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
-        TRACE("Point sprites not supported\n");
+    if (!warned && stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
+        /* A FIXME, not a WARN because point sprites should be software emulated if not supported by HW */
+        FIXME("Point sprites not supported\n");
+        warned = TRUE;
     }
 }
 
 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
     if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
+        BOOL warned = FALSE;
+        if(GL_LIMITS(point_sprite_units) < GL_LIMITS(textures) && !warned) {
+            if(use_ps(stateblock) || stateblock->lowest_disabled_stage > GL_LIMITS(point_sprite_units)) {
+                FIXME("The app uses point sprite texture coordinates on more units than supported by the driver\n");
+                warned = TRUE;
+            }
+        }
+
         glEnable(GL_POINT_SPRITE_ARB);
         checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
     } else {
diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h
index 2072391..1a9c925 100644
--- a/dlls/wined3d/wined3d_gl.h
+++ b/dlls/wined3d/wined3d_gl.h
@@ -3933,6 +3933,7 @@ typedef struct _WineD3D_GL_Info {
   UINT   max_texture_size;
   UINT   max_texture3d_size;
   float  max_pointsize, max_pointsizemin;
+  UINT   max_point_sprite_units;
   UINT   max_blends;
   UINT   max_anisotropy;
   UINT   max_glsl_varyings;




More information about the wine-cvs mailing list