#include "radeon_tcl.h"
#include "radeon_sanity.h"
+#define STANDALONE_MMIO
#include "radeon_macros.h" /* for INREG() */
#include "vblank.h"
static void radeonWaitForIdle( radeonContextPtr rmesa );
-
-/* =============================================================
- * Kernel command buffer handling
- */
+static int radeonFlushCmdBufLocked( radeonContextPtr rmesa,
+ const char * caller );
static void print_state_atom( struct radeon_state_atom *state )
{
}
-static void radeon_emit_state_list( radeonContextPtr rmesa,
- struct radeon_state_atom *list )
+static void radeonSaveHwState( radeonContextPtr rmesa )
{
- struct radeon_state_atom *state, *tmp;
- char *dest;
- int i, size, texunits;
-
- /* It appears that some permutations of state atoms lock up the
- * chip. Therefore we make sure that state atoms are emitted in a
- * fixed order. First mark all dirty state atoms and then go
- * through all state atoms in a well defined order and emit only
- * the marked ones.
- * FIXME: This requires knowledge of which state atoms exist.
- * FIXME: Is the zbs hack below still needed?
- */
- size = 0;
- foreach_s( state, tmp, list ) {
- if (state->check( rmesa->glCtx )) {
- size += state->cmd_size;
- state->dirty = GL_TRUE;
- move_to_head( &(rmesa->hw.clean), state );
- if (RADEON_DEBUG & DEBUG_STATE)
- print_state_atom( state );
+ struct radeon_state_atom *atom;
+ char * dest = rmesa->backup_store.cmd_buf;
+
+ if (RADEON_DEBUG & DEBUG_STATE)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ rmesa->backup_store.cmd_used = 0;
+
+ 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;
+ if (RADEON_DEBUG & DEBUG_STATE)
+ print_state_atom( atom );
}
- else if (RADEON_DEBUG & DEBUG_STATE)
- fprintf(stderr, "skip state %s\n", state->name);
}
- /* short cut */
- if (!size)
- return;
-
- dest = radeonAllocCmdBuf( rmesa, size * 4, __FUNCTION__);
- texunits = rmesa->glCtx->Const.MaxTextureUnits;
-
-#define EMIT_ATOM(ATOM) \
-do { \
- if (rmesa->hw.ATOM.dirty) { \
- rmesa->hw.ATOM.dirty = GL_FALSE; \
- memcpy( dest, rmesa->hw.ATOM.cmd, rmesa->hw.ATOM.cmd_size * 4); \
- dest += rmesa->hw.ATOM.cmd_size * 4; \
- } \
-} while (0)
-
- EMIT_ATOM (ctx);
- EMIT_ATOM (set);
- EMIT_ATOM (lin);
- EMIT_ATOM (msk);
- EMIT_ATOM (vpt);
- EMIT_ATOM (tcl);
- EMIT_ATOM (msc);
- for (i = 0; i < texunits; ++i) {
- EMIT_ATOM (tex[i]);
- EMIT_ATOM (txr[i]);
+
+ assert( rmesa->backup_store.cmd_used <= RADEON_CMD_BUF_SZ );
+ if (RADEON_DEBUG & DEBUG_STATE)
+ fprintf(stderr, "Returning to radeonEmitState\n");
+}
+
+/* At this point we were in FlushCmdBufLocked but we had lost our context, so
+ * 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 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;
+ saved_store = rmesa->store;
+ rmesa->dma.nr_released_bufs = 0;
+ rmesa->store = rmesa->backup_store;
+ radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
+ rmesa->dma.nr_released_bufs = nr_released_bufs;
+ rmesa->store = saved_store;
+}
+
+/* =============================================================
+ * Kernel command buffer handling
+ */
+
+/* The state atoms will be emitted in the order they appear in the atom list,
+ * so this step is important.
+ */
+void radeonSetUpAtomList( radeonContextPtr rmesa )
+{
+ int i, mtu = rmesa->glCtx->Const.MaxTextureUnits;
+
+ make_empty_list(&rmesa->hw.atomlist);
+ rmesa->hw.atomlist.name = "atom-list";
+
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.ctx);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.set);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.lin);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.msk);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.vpt);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.tcl);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.msc);
+ for (i = 0; i < mtu; ++i) {
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.tex[i]);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.txr[i]);
}
- EMIT_ATOM (zbs);
- EMIT_ATOM (mtl);
- for (i = 0; i < 3 + texunits; ++i)
- EMIT_ATOM (mat[i]);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.zbs);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.mtl);
+ for (i = 0; i < 3 + mtu; ++i)
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.mat[i]);
for (i = 0; i < 8; ++i)
- EMIT_ATOM (lit[i]);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.lit[i]);
for (i = 0; i < 6; ++i)
- EMIT_ATOM (ucp[i]);
- EMIT_ATOM (eye);
- EMIT_ATOM (grd);
- EMIT_ATOM (fog);
- EMIT_ATOM (glt);
-
-#undef EMIT_ATOM
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.ucp[i]);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.eye);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.grd);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.fog);
+ insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.glt);
}
-
void radeonEmitState( radeonContextPtr rmesa )
{
- struct radeon_state_atom *state, *tmp;
+ struct radeon_state_atom *atom;
+ char *dest;
if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
fprintf(stderr, "%s\n", __FUNCTION__);
- /* Somewhat overkill:
- */
- if (rmesa->lost_context) {
- if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL))
- fprintf(stderr, "%s - lost context\n", __FUNCTION__);
+ if (rmesa->save_on_next_emit) {
+ radeonSaveHwState(rmesa);
+ rmesa->save_on_next_emit = GL_FALSE;
+ }
- foreach_s( state, tmp, &(rmesa->hw.clean) )
- move_to_tail(&(rmesa->hw.dirty), state );
+ if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty)
+ return;
- rmesa->lost_context = 0;
- }
- else if (1) {
- /* This is a darstardly kludge to work around a lockup that I
- * haven't otherwise figured out.
- */
- move_to_tail(&(rmesa->hw.dirty), &(rmesa->hw.zbs) );
+ /* To avoid going across the entire set of states multiple times, just check
+ * for enough space for the case of emitting all state, and inline the
+ * radeonAllocCmdBuf code here without all the checks.
+ */
+ radeonEnsureCmdBufSpace(rmesa, rmesa->hw.max_state_size);
+ dest = rmesa->store.cmd_buf + rmesa->store.cmd_used;
+
+ if (RADEON_DEBUG & DEBUG_STATE) {
+ foreach(atom, &rmesa->hw.atomlist) {
+ if (atom->dirty || rmesa->hw.all_dirty) {
+ if (atom->check(rmesa->glCtx))
+ print_state_atom(atom);
+ else
+ fprintf(stderr, "skip state %s\n", atom->name);
+ }
+ }
}
- if (!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
- foreach_s( state, tmp, &(rmesa->hw.dirty) ) {
- if (state->is_tcl) {
- move_to_head( &(rmesa->hw.clean), state );
- }
- }
+ foreach(atom, &rmesa->hw.atomlist) {
+ if (rmesa->hw.all_dirty)
+ atom->dirty = GL_TRUE;
+ if (!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL) &&
+ atom->is_tcl)
+ atom->dirty = GL_FALSE;
+ if (atom->dirty) {
+ if (atom->check(rmesa->glCtx)) {
+ int size = atom->cmd_size * 4;
+ memcpy(dest, atom->cmd, size);
+ dest += size;
+ rmesa->store.cmd_used += size;
+ atom->dirty = GL_FALSE;
+ }
+ }
}
- radeon_emit_state_list( rmesa, &rmesa->hw.dirty );
+ assert(rmesa->store.cmd_used <= RADEON_CMD_BUF_SZ);
+
+ rmesa->hw.is_dirty = GL_FALSE;
+ rmesa->hw.all_dirty = GL_FALSE;
}
-
-
/* Fire a section of the retained (indexed_verts) buffer as a regular
* primtive.
*/
fprintf(stderr, "%s cmd_used/4: %d\n", __FUNCTION__,
rmesa->store.cmd_used/4);
+ cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, VBUF_BUFSZ,
+ __FUNCTION__ );
#if RADEON_OLD_PACKETS
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 6 * sizeof(*cmd),
- __FUNCTION__ );
+ cmd[0].i = 0;
cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM | (3 << 16);
cmd[2].i = rmesa->ioctl.vertex_offset;
__FUNCTION__,
cmd[1].i, cmd[2].i, cmd[4].i, cmd[5].i);
#else
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 4 * sizeof(*cmd),
- __FUNCTION__ );
cmd[0].i = 0;
cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_VBUF | (1 << 16);
radeonEmitState( rmesa );
+ cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa,
+ ELTS_BUFSZ(min_nr),
+ __FUNCTION__ );
#if RADEON_OLD_PACKETS
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa,
- 24 + min_nr*2,
- __FUNCTION__ );
cmd[0].i = 0;
cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM;
retval = (GLushort *)(cmd+6);
#else
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa,
- 16 + min_nr*2,
- __FUNCTION__ );
cmd[0].i = 0;
cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_INDX;
fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n",
__FUNCTION__, vertex_size, offset);
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 5 * sizeof(int),
+ cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, VERT_AOS_BUFSZ,
__FUNCTION__ );
cmd[0].i = 0;
(component[0]->aos_start + offset * component[0]->aos_stride * 4);
#else
drm_radeon_cmd_header_t *cmd;
- int sz = 3 + (nr/2 * 3) + (nr & 1) * 2;
+ int sz = AOS_BUFSZ(nr);
int i;
int *tmp;
fprintf(stderr, "%s\n", __FUNCTION__);
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, sz * sizeof(int),
+ cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, sz,
__FUNCTION__ );
cmd[0].i = 0;
cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
- cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | ((sz-3) << 16);
+ cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | (((sz / sizeof(int))-3) << 16);
cmd[2].i = nr;
tmp = &cmd[0].i;
cmd += 3;
int ret, i;
drm_radeon_cmd_buffer_t cmd;
+ if (rmesa->lost_context)
+ radeonBackUpAndEmitLostStateLocked(rmesa);
+
if (RADEON_DEBUG & DEBUG_IOCTL) {
fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
rmesa->store.statenr = 0;
rmesa->store.cmd_used = 0;
rmesa->dma.nr_released_bufs = 0;
- rmesa->lost_context = 1;
+ rmesa->save_on_next_emit = 1;
+
return ret;
}
else
ret = -EINVAL;
-#ifndef __alpha__
if ( ret == -EINVAL ) {
frame = INREG( RADEON_LAST_FRAME_REG );
ret = 0;
}
-#endif
if ( ret ) {
fprintf( stderr, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__, ret );
exit(1);
rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
if ( RADEON_DEBUG & DEBUG_IOCTL ) {
- fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, rmesa->glCtx );
+ fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, (void *) rmesa->glCtx );
}
RADEON_FIREVERTICES( rmesa );
}
rmesa->swap_ust = ust;
+ rmesa->hw.all_dirty = GL_TRUE;
}
void radeonPageFlip( const __DRIdrawablePrivate *dPriv )
__FUNCTION__, all, cx, cy, cw, ch );
}
- radeonEmitState( rmesa );
-
- /* Need to cope with lostcontext here as kernel relies on
- * some residual state:
- */
- RADEON_FIREVERTICES( rmesa );
+ {
+ LOCK_HARDWARE( rmesa );
+ UNLOCK_HARDWARE( rmesa );
+ if ( dPriv->numClipRects == 0 )
+ return;
+ }
+
+ radeonFlush( ctx );
if ( mask & DD_FRONT_LEFT_BIT ) {
flags |= RADEON_FRONT;
}
if ( mask & DD_DEPTH_BIT ) {
- if ( ctx->Depth.Mask ) flags |= RADEON_DEPTH; /* FIXME: ??? */
+ flags |= RADEON_DEPTH;
mask &= ~DD_DEPTH_BIT;
}
if ( !flags )
return;
+ if (rmesa->using_hyperz) {
+ flags |= RADEON_USE_COMP_ZBUF;
+/* if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)
+ flags |= RADEON_USE_HIERZ; */
+ if (!(rmesa->state.stencil.hwBuffer) ||
+ ((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) &&
+ ((rmesa->state.stencil.clear & RADEON_STENCIL_WRITE_MASK) == RADEON_STENCIL_WRITE_MASK))) {
+ flags |= RADEON_CLEAR_FASTZ;
+ }
+ }
/* Flip top to bottom */
cx += dPriv->x;
} else
ret = -EINVAL;
-#ifndef __alpha__
if ( ret == -EINVAL ) {
clear = INREG( RADEON_LAST_CLEAR_REG );
ret = 0;
}
-#endif
if ( ret ) {
fprintf( stderr, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__, ret );
exit(1);
}
}
+ /* Send current state to the hardware */
+ radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
+
for ( i = 0 ; i < dPriv->numClipRects ; ) {
GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
drm_clip_rect_t *box = dPriv->pClipRects;
}
UNLOCK_HARDWARE( rmesa );
+ rmesa->hw.all_dirty = GL_TRUE;
}
if (rmesa->dma.flush)
rmesa->dma.flush( rmesa );
- if (!is_empty_list(&rmesa->hw.dirty))
- radeonEmitState( rmesa );
+ radeonEmitState( rmesa );
if (rmesa->store.cmd_used)
radeonFlushCmdBuf( rmesa, __FUNCTION__ );