svga: add work-around for Sauerbraten Z fighting issue
authorBrian Paul <brianp@vmware.com>
Mon, 24 Mar 2014 23:24:01 +0000 (17:24 -0600)
committerBrian Paul <brianp@vmware.com>
Wed, 26 Mar 2014 16:31:13 +0000 (10:31 -0600)
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
src/gallium/drivers/svga/svga_context.c
src/gallium/drivers/svga/svga_context.h
src/gallium/drivers/svga/svga_state_need_swtnl.c

index 4da9a6551f6bdf02891a17eb087502b2b9f81426..0ba09ce2ebc03c2e6b11e040072dd651a2ee81b6 100644 (file)
 
 #include "svga_cmd.h"
 
+#include "os/os_process.h"
 #include "pipe/p_defines.h"
 #include "util/u_inlines.h"
 #include "pipe/p_screen.h"
 #include "util/u_memory.h"
 #include "util/u_bitmask.h"
+#include "util/u_string.h"
 
 #include "svga_context.h"
 #include "svga_screen.h"
@@ -80,6 +82,35 @@ static void svga_destroy( struct pipe_context *pipe )
 }
 
 
+/**
+ * Check the process name to see if we're running with an app that
+ * needs any particular work-arounds.
+ */
+static void
+check_for_workarounds(struct svga_context *svga)
+{
+   char name[1000];
+
+   if (!os_get_process_name(name, sizeof(name)))
+      return;
+
+   if (util_strcmp(name, "sauer_client") == 0) {
+      /*
+       * Sauerbraten uses a two-pass rendering algorithm.  The first pass
+       * draws a depth map.  The second pass draws the colors.  On the second
+       * pass we wind up using the swtnl path because the game tries to use
+       * a GLbyte[3] normal vector array (which the SVGA3D protocol does not
+       * support.)  The vertices of the first and second passes don't quite
+       * match so we see some depth/Z-fighting issues.  This work-around
+       * causes us to map GLbyte[3] to SVGA3D_DECLTYPE_UBYTE4N and avoid the
+       * swtnl path.  Despite not correctly converting normal vectors from
+       * GLbyte[3] to float[4], the rendering looks OK.
+       */
+      debug_printf("Enabling sauerbraten GLbyte[3] work-around\n");
+      svga->workaround.use_decltype_ubyte4n = TRUE;
+   }
+}
+
 
 struct pipe_context *svga_context_create( struct pipe_screen *screen,
                                          void *priv )
@@ -156,6 +187,8 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen,
 
    LIST_INITHEAD(&svga->dirty_buffers);
 
+   check_for_workarounds(svga);
+
    return &svga->pipe;
 
 no_state:
index 0daab0b322954010963d7fcb8ddbcf0f307d2350..1e93b024f9fa3bef6c5c10e706a4c4494f20a6a8 100644 (file)
@@ -389,6 +389,11 @@ struct svga_context
    /** performance / info queries */
    uint64_t num_draw_calls;  /**< SVGA_QUERY_DRAW_CALLS */
    uint64_t num_fallbacks;   /**< SVGA_QUERY_FALLBACKS */
+
+   /** quirks / work-around flags for particular apps */
+   struct {
+      boolean use_decltype_ubyte4n;
+   } workaround;
 };
 
 /* A flag for each state_tracker state object:
index c0bfd2c14d06f14a480e97201ba1ee5c290e498f..6f1d802bceddd3b457c0cf5e1c60ba989598754c 100644 (file)
@@ -36,7 +36,8 @@
  * format.  Return SVGA3D_DECLTYPE_MAX for unsupported gallium formats.
  */
 static INLINE SVGA3dDeclType
-svga_translate_vertex_format(enum pipe_format format)
+svga_translate_vertex_format(const struct svga_context *svga,
+                             enum pipe_format format)
 {
    switch (format) {
    case PIPE_FORMAT_R32_FLOAT:            return SVGA3D_DECLTYPE_FLOAT1;
@@ -57,6 +58,12 @@ svga_translate_vertex_format(enum pipe_format format)
    case PIPE_FORMAT_R16G16_FLOAT:         return SVGA3D_DECLTYPE_FLOAT16_2;
    case PIPE_FORMAT_R16G16B16A16_FLOAT:   return SVGA3D_DECLTYPE_FLOAT16_4;
 
+   case PIPE_FORMAT_R8G8B8_SNORM:
+      if (svga->workaround.use_decltype_ubyte4n) {
+         return SVGA3D_DECLTYPE_UBYTE4N;
+      }
+      /* fall-through */
+
    default:
       /* There are many formats without hardware support.  This case
        * will be hit regularly, meaning we'll need swvfetch.
@@ -78,7 +85,9 @@ update_need_swvfetch(struct svga_context *svga, unsigned dirty)
    }
 
    for (i = 0; i < svga->curr.velems->count; i++) {
-      svga->state.sw.ve_format[i] = svga_translate_vertex_format(svga->curr.velems->velem[i].src_format);
+      svga->state.sw.ve_format[i] =
+         svga_translate_vertex_format(svga,
+                                      svga->curr.velems->velem[i].src_format);
       if (svga->state.sw.ve_format[i] == SVGA3D_DECLTYPE_MAX) {
          /* Unsupported format - use software fetch */
          need_swvfetch = TRUE;