OK, one more time. Simplify the state-backup system by just storing the full
authorEric Anholt <anholt@FreeBSD.org>
Thu, 30 Sep 2004 00:08:05 +0000 (00:08 +0000)
committerEric Anholt <anholt@FreeBSD.org>
Thu, 30 Sep 2004 00:08:05 +0000 (00:08 +0000)
state in a ready-to-emit cmdbuf, which avoids the issue Nicolai Haehnle reported
where the check() could return differently during backup-and-emit than it should
have if it were called at the right time.  Move the lit emission before most of
the TCL state emission on r200, which fixes neverball issues.

Tested with: r100/r200 with neverball, tuxracer, chromium, quake3, ipers

13 files changed:
src/mesa/drivers/dri/r200/r200_cmdbuf.c
src/mesa/drivers/dri/r200/r200_context.c
src/mesa/drivers/dri/r200/r200_context.h
src/mesa/drivers/dri/r200/r200_ioctl.c
src/mesa/drivers/dri/r200/r200_ioctl.h
src/mesa/drivers/dri/r200/r200_lock.h
src/mesa/drivers/dri/r200/r200_state_init.c
src/mesa/drivers/dri/radeon/radeon_context.c
src/mesa/drivers/dri/radeon/radeon_context.h
src/mesa/drivers/dri/radeon/radeon_ioctl.c
src/mesa/drivers/dri/radeon/radeon_ioctl.h
src/mesa/drivers/dri/radeon/radeon_lock.h
src/mesa/drivers/dri/radeon/radeon_state_init.c

index 384c1634ea0fd7834d2242fb9fba7d70df7a4a3b..5cdb3657f98526479e51b5defcc8c9a322e8abea 100644 (file)
@@ -92,18 +92,38 @@ void r200SetUpAtomList( r200ContextPtr rmesa )
        insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tex[i] );
    for (i = 0; i < mtu; ++i)
        insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.cube[i] );
+   for (i = 0; i < 6; ++i)
+       insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.pix[i] );
+
+   for (i = 0; i < 8; ++i)
+       insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.lit[i] );
    for (i = 0; i < 3 + mtu; ++i)
        insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.mat[i] );
    insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.eye );
    insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.glt );
    for (i = 0; i < 2; ++i)
       insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.mtl[i] );
-   for (i = 0; i < 8; ++i)
-       insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.lit[i] );
    for (i = 0; i < 6; ++i)
        insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ucp[i] );
-   for (i = 0; i < 6; ++i)
-       insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.pix[i] );
+}
+
+static void r200SaveHwState( r200ContextPtr rmesa )
+{
+   struct r200_state_atom *atom;
+   char * dest = rmesa->backup_store.cmd_buf;
+
+   rmesa->backup_store.cmd_used = 0;
+
+   foreach( atom, &rmesa->hw.atomlist ) {
+      if ( atom->check( rmesa->glCtx, atom->idx ) ) {
+        int size = atom->cmd_size * 4;
+        memcpy( dest, atom->cmd, size);
+        dest += size;
+        rmesa->backup_store.cmd_used += size;
+      }
+   }
+
+   assert( rmesa->backup_store.cmd_used <= R200_CMD_BUF_SZ );
 }
 
 void r200EmitState( r200ContextPtr rmesa )
@@ -115,6 +135,11 @@ void r200EmitState( r200ContextPtr rmesa )
    if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
       fprintf(stderr, "%s\n", __FUNCTION__);
 
+   if (rmesa->save_on_next_emit) {
+      r200SaveHwState(rmesa);
+      rmesa->save_on_next_emit = GL_FALSE;
+   }
+
    if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty)
       return;
 
index 3b8394f794f3fc12d850c65019b2e6e495daf02b..d5ca2f9b3a64c721baa673957cd92fec30b32c41 100644 (file)
@@ -62,7 +62,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r200_vtxfmt.h"
 #include "r200_maos.h"
 
-#define DRIVER_DATE    "20040924"
+#define DRIVER_DATE    "20040929"
 
 #include "vblank.h"
 #include "utils.h"
index 25faec955c527605b30d673d890a7c030b241357..140902c356b7a77968db844c680330436e60b088 100644 (file)
@@ -191,7 +191,6 @@ struct r200_state_atom {
    GLuint idx;
    int *cmd;                            /* one or more cmd's */
    int *lastcmd;                        /* one or more cmd's */
-   int *savedcmd;                       /* one or more cmd's */
    GLboolean dirty;
    GLboolean (*check)( GLcontext *, int );    /* is this state active? */
 };
@@ -825,8 +824,6 @@ struct r200_vbinfo {
 };
 
 
-
-
 struct r200_context {
    GLcontext *glCtx;                   /* Mesa context */
 
@@ -854,6 +851,10 @@ struct r200_context {
    struct r200_ioctl ioctl;
    struct r200_dma dma;
    struct r200_store store;
+   /* A full state emit as of the first state emit in the main store, in case
+    * the context is lost.
+    */
+   struct r200_store backup_store;
 
    /* Page flipping
     */
@@ -876,7 +877,7 @@ struct r200_context {
    drm_clip_rect_t *pClipRects;
    unsigned int lastStamp;
    GLboolean lost_context;
-   GLboolean save_on_next_unlock;
+   GLboolean save_on_next_emit;
    r200ScreenPtr r200Screen;   /* Screen private DRI data */
    drm_radeon_sarea_t *sarea;          /* Private SAREA data */
 
index 74dd7d38eb9c81ed92cf7797b2a4f2400b8221bc..d2fde39a1cdc1f6d8fca980399306f28df7d2b07 100644 (file)
@@ -58,59 +58,34 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 static void r200WaitForIdle( r200ContextPtr rmesa );
 
-void r200SaveHwState( r200ContextPtr rmesa )
-{
-   struct r200_state_atom *atom;
-
-   foreach( atom, &rmesa->hw.atomlist )
-      memcpy(atom->savedcmd, atom->cmd, atom->cmd_size * 4);
-}
-
-static void r200SwapHwState( r200ContextPtr rmesa )
-{
-   int *temp;
-   struct r200_state_atom *atom;
-
-   foreach( atom, &rmesa->hw.atomlist ) {
-      temp = atom->cmd;
-      atom->cmd = atom->savedcmd;
-      atom->savedcmd = temp;
-   }
-}
 
 /* At this point we were in FlushCmdBufLocked but we had lost our context, so
- * we need to unwire our current cmdbuf and hook a new one in, emit that, then
- * wire the old cmdbuf back in so that FlushCmdBufLocked can continue and the
- * buffer can depend on the state not being lost across lock/unlock.
+ * we need to unwire our current cmdbuf, hook the one with the saved state in
+ * it, flush it, and then put the current one back.  This is so commands at the
+ * start of a cmdbuf can rely on the state being kept from the previous one.
  */
 static void r200BackUpAndEmitLostStateLocked( r200ContextPtr rmesa )
 {
-   GLuint nr_released_bufs;
-   struct r200_store store;
+   GLuint nr_released_bufs, saved_cmd_used;
+   struct r200_store saved_store;
+
+   if (rmesa->backup_store.cmd_used == 0)
+      return;
+
+   if (R200_DEBUG & DEBUG_STATE)
+      fprintf(stderr, "Emitting backup state on lost context\n");
 
    rmesa->lost_context = GL_FALSE;
 
    nr_released_bufs = rmesa->dma.nr_released_bufs;
-   store = rmesa->store;
-   rmesa->store.statenr = 0;
-   rmesa->store.primnr = 0;
-   rmesa->store.cmd_used = 0;
-   rmesa->store.elts_start = 0;
-   rmesa->hw.all_dirty = GL_TRUE;
-   r200SwapHwState( rmesa );
-   /* In this case it's okay to EmitState while locked because we won't exhaust
-    * our (empty) cmdbuf.
-    */
-   r200EmitState( rmesa );
+   saved_store = rmesa->store;
+   rmesa->dma.nr_released_bufs = 0;
+   rmesa->store = rmesa->backup_store;
+   saved_cmd_used = rmesa->backup_store.cmd_used;
    r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
-
-   r200SwapHwState( rmesa );
-   /* We've just cleared out the dirty flags, so we don't remember what 
-    * actually needed to be emitted for the next state emit.
-    */
-   rmesa->hw.all_dirty = GL_TRUE;
+   rmesa->backup_store.cmd_used = saved_cmd_used;
    rmesa->dma.nr_released_bufs = nr_released_bufs;
-   rmesa->store = store;
+   rmesa->store = saved_store;
 }
 
 int r200FlushCmdBufLocked( r200ContextPtr rmesa, const char * caller )
@@ -189,7 +164,7 @@ int r200FlushCmdBufLocked( r200ContextPtr rmesa, const char * caller )
    rmesa->store.statenr = 0;
    rmesa->store.cmd_used = 0;
    rmesa->dma.nr_released_bufs = 0;
-   rmesa->save_on_next_unlock = 1;
+   rmesa->save_on_next_emit = 1;
 
    return ret;
 }
index 57474d7a05215b869516732147ee2ec78732c577..939dab36853fd8c973f0b968cdfcc9bcf615052e 100644 (file)
@@ -117,7 +117,6 @@ extern GLboolean r200IsGartMemory( r200ContextPtr rmesa, const GLvoid *pointer,
 extern GLuint r200GartOffsetFromVirtual( r200ContextPtr rmesa, 
                                         const GLvoid *pointer );
 
-void r200SaveHwState( r200ContextPtr rmesa );
 void r200SetUpAtomList( r200ContextPtr rmesa );
 
 /* ================================================================
index 908052659c17bedad500700f995a1c12c8be1ef1..587e4fe5ccd47e5f31f97fe5674283850f434adf 100644 (file)
@@ -104,10 +104,6 @@ extern int prevLockLine;
                  rmesa->dri.hwLock,                                    \
                  rmesa->dri.hwContext );                               \
       DEBUG_RESET();                                                   \
-      if (rmesa->save_on_next_unlock) {                                        \
-        r200SaveHwState( rmesa );                                      \
-        rmesa->save_on_next_unlock = GL_FALSE;                         \
-      }                                                                        \
    } while (0)
 
 #endif
index e97a2f4d995d83e44049411ed319567fe9c7aef1..049820b3cb73049fc9d51905343f3832f5175e46 100644 (file)
@@ -208,7 +208,6 @@ void r200InitState( r200ContextPtr rmesa )
       rmesa->hw.ATOM.cmd_size = SZ;                            \
       rmesa->hw.ATOM.cmd = (int *)CALLOC(SZ * sizeof(int));    \
       rmesa->hw.ATOM.lastcmd = (int *)CALLOC(SZ * sizeof(int));        \
-      rmesa->hw.ATOM.savedcmd = (int *)CALLOC(SZ * sizeof(int)); \
       rmesa->hw.ATOM.name = NM;                                        \
       rmesa->hw.ATOM.idx = IDX;                                        \
       rmesa->hw.ATOM.check = check_##CHK;                      \
@@ -770,6 +769,5 @@ void r200InitState( r200ContextPtr rmesa )
 
    r200LightingSpaceChange( ctx );
    
-   r200SaveHwState( rmesa );
    rmesa->hw.all_dirty = GL_TRUE;
 }
index dcc704cfd2ad4a35a27ff64f968787a8ec9667a5..5f419347b45f351437d43216d8b611e5df586f13 100644 (file)
@@ -62,7 +62,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "radeon_vtxfmt.h"
 #include "radeon_maos.h"
 
-#define DRIVER_DATE    "20040924"
+#define DRIVER_DATE    "20040929"
 
 #include "vblank.h"
 #include "utils.h"
index f5bc0b0547b47ec5aef3765fb4a9d990fdf1e054..b44ea08dc836b219e9dce3fb4fa92502a732c438 100644 (file)
@@ -185,7 +185,6 @@ struct radeon_state_atom {
    GLuint is_tcl;
    int *cmd;                            /* one or more cmd's */
    int *lastcmd;                        /* one or more cmd's */
-   int *savedcmd;                       /* one or more cmd's */
    GLboolean dirty;                      /* dirty-mark in emit_state_list */
    GLboolean (*check)( GLcontext * );    /* is this state active? */
 };
@@ -714,6 +713,10 @@ struct radeon_context {
    struct radeon_ioctl ioctl;
    struct radeon_dma dma;
    struct radeon_store store;
+   /* A full state emit as of the first state emit in the main store, in case
+    * the context is lost.
+    */
+   struct radeon_store backup_store;
 
    /* Page flipping
     */
@@ -732,7 +735,7 @@ struct radeon_context {
    drm_clip_rect_t *pClipRects;
    unsigned int lastStamp;
    GLboolean lost_context;
-   GLboolean save_on_next_unlock;
+   GLboolean save_on_next_emit;
    radeonScreenPtr radeonScreen;       /* Screen private DRI data */
    drm_radeon_sarea_t *sarea;          /* Private SAREA data */
 
index 5ef14e34bba5253e24a063449cd175ba3cd20fbd..50d5154016ae5738ab5bec0429b1df965657daff 100644 (file)
@@ -62,59 +62,52 @@ static void radeonWaitForIdle( radeonContextPtr rmesa );
 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa, 
                                    const char * caller );
 
-void radeonSaveHwState( radeonContextPtr rmesa )
+static void radeonSaveHwState( radeonContextPtr rmesa )
 {
    struct radeon_state_atom *atom;
+   char * dest = rmesa->backup_store.cmd_buf;
 
-   foreach(atom, &rmesa->hw.atomlist)
-      memcpy(atom->savedcmd, atom->cmd, atom->cmd_size * 4);
-}
-
-static void radeonSwapHwState( radeonContextPtr rmesa )
-{
-   int *temp;
-   struct radeon_state_atom *atom;
+   rmesa->backup_store.cmd_used = 0;
 
-   foreach(atom, &rmesa->hw.atomlist) {
-      temp = atom->cmd;
-      atom->cmd = atom->savedcmd;
-      atom->savedcmd = temp;
+   foreach( atom, &rmesa->hw.atomlist ) {
+      if ( atom->check( rmesa->glCtx ) ) {
+        int size = atom->cmd_size * 4;
+        memcpy( dest, atom->cmd, size);
+        dest += size;
+        rmesa->backup_store.cmd_used += size;
+      }
    }
+
+   assert( rmesa->backup_store.cmd_used <= RADEON_CMD_BUF_SZ );
 }
 
 /* At this point we were in FlushCmdBufLocked but we had lost our context, so
- * we need to unwire our current cmdbuf and hook a new one in, emit that, then
- * wire the old cmdbuf back in so that FlushCmdBufLocked can continue and the
- * buffer can depend on the state not being lost across lock/unlock.
+ * we need to unwire our current cmdbuf, hook the one with the saved state in
+ * it, flush it, and then put the current one back.  This is so commands at the
+ * start of a cmdbuf can rely on the state being kept from the previous one.
  */
 static void radeonBackUpAndEmitLostStateLocked( radeonContextPtr rmesa )
 {
-   GLuint nr_released_bufs;
-   struct radeon_store store;
+   GLuint nr_released_bufs, saved_cmd_used;
+   struct radeon_store saved_store;
+
+   if (rmesa->backup_store.cmd_used == 0)
+      return;
+
+   if (RADEON_DEBUG & DEBUG_STATE)
+      fprintf(stderr, "Emitting backup state on lost context\n");
 
    rmesa->lost_context = GL_FALSE;
 
    nr_released_bufs = rmesa->dma.nr_released_bufs;
-   store = rmesa->store;
-   rmesa->store.statenr = 0;
-   rmesa->store.primnr = 0;
-   rmesa->store.cmd_used = 0;
-   rmesa->store.elts_start = 0;
-   rmesa->hw.all_dirty = GL_TRUE;
-   radeonSwapHwState( rmesa );
-   /* In this case it's okay to EmitState while locked because we won't exhaust
-    * our (empty) cmdbuf.
-    */
-   radeonEmitState(rmesa);
-   radeonFlushCmdBufLocked(rmesa, __FUNCTION__);
-
-   radeonSwapHwState(rmesa);
-   /* We've just cleared out the dirty flags, so we don't remember what 
-    * actually needed to be emitted for the next state emit.
-    */
-   rmesa->hw.all_dirty = GL_TRUE;
+   saved_store = rmesa->store;
+   rmesa->dma.nr_released_bufs = 0;
+   rmesa->store = rmesa->backup_store;
+   saved_cmd_used = rmesa->backup_store.cmd_used;
+   radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
+   rmesa->backup_store.cmd_used = saved_cmd_used;
    rmesa->dma.nr_released_bufs = nr_released_bufs;
-   rmesa->store = store;
+   rmesa->store = saved_store;
 }
 
 /* =============================================================
@@ -176,6 +169,11 @@ void radeonEmitState( radeonContextPtr rmesa )
    if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
       fprintf(stderr, "%s\n", __FUNCTION__);
 
+   if (rmesa->save_on_next_emit) {
+      radeonSaveHwState(rmesa);
+      rmesa->save_on_next_emit = GL_FALSE;
+   }
+
    if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty)
       return;
 
@@ -582,7 +580,7 @@ static int radeonFlushCmdBufLocked( radeonContextPtr rmesa,
    rmesa->store.statenr = 0;
    rmesa->store.cmd_used = 0;
    rmesa->dma.nr_released_bufs = 0;
-   rmesa->save_on_next_unlock = 1;
+   rmesa->save_on_next_emit = 1;
 
    return ret;
 }
index 7ad4f3a93250772e18d159a2577dccf6f769b830..79b3b72c60e8f282dca5871853305fdc829aa202 100644 (file)
@@ -103,8 +103,6 @@ extern void radeonWaitForIdleLocked( radeonContextPtr rmesa );
 extern void radeonWaitForVBlank( radeonContextPtr rmesa );
 extern void radeonInitIoctlFuncs( GLcontext *ctx );
 extern void radeonGetAllParams( radeonContextPtr rmesa );
-
-extern void radeonSaveHwState( radeonContextPtr rmesa );
 extern void radeonSetUpAtomList( radeonContextPtr rmesa );
 
 /* radeon_compat.c:
index c28cf23161ed8e2a155921c7ce2bff93ed21cf94..c2e0c3706b8478375bb972074310e673a059aabd 100644 (file)
@@ -105,10 +105,6 @@ extern int prevLockLine;
                  rmesa->dri.hwLock,                                    \
                  rmesa->dri.hwContext );                               \
       DEBUG_RESET();                                                   \
-      if ( rmesa->save_on_next_unlock ) {                                      \
-        radeonSaveHwState( rmesa );                                    \
-        rmesa->save_on_next_unlock = GL_FALSE;                         \
-      }                                                                        \
    } while (0)
 
 #endif
index 4df76603bba7214b4129bd9d61ec2d955337bf9f..0945fa803f384ffa4c972388d47f8dc08a2abcd8 100644 (file)
@@ -205,7 +205,6 @@ void radeonInitState( radeonContextPtr rmesa )
       rmesa->hw.ATOM.cmd_size = SZ;                            \
       rmesa->hw.ATOM.cmd = (int *)CALLOC(SZ * sizeof(int));    \
       rmesa->hw.ATOM.lastcmd = (int *)CALLOC(SZ * sizeof(int));        \
-      rmesa->hw.ATOM.savedcmd = (int *)CALLOC(SZ * sizeof(int));       \
       rmesa->hw.ATOM.name = NM;                                        \
       rmesa->hw.ATOM.is_tcl = FLAG;                                    \
       rmesa->hw.ATOM.check = check_##CHK;                              \
@@ -551,6 +550,5 @@ void radeonInitState( radeonContextPtr rmesa )
    rmesa->hw.eye.cmd[EYE_Z] = IEEE_ONE;
    rmesa->hw.eye.cmd[EYE_RESCALE_FACTOR] = IEEE_ONE;
    
-   radeonSaveHwState( rmesa );
    rmesa->hw.all_dirty = GL_TRUE;
 }