Merge remote branch 'main/radeon-rewrite'
[mesa.git] / src / mesa / drivers / dri / r300 / r300_cmdbuf.c
index b8740e298badaab5a081a38d90195904d48f1de7..0261a5b1d8ace091057e26854649de7de488a37c 100644 (file)
@@ -44,288 +44,222 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "drm.h"
 #include "radeon_drm.h"
 
-#include "radeon_buffer.h"
-#include "radeon_ioctl.h"
 #include "r300_context.h"
 #include "r300_ioctl.h"
 #include "radeon_reg.h"
 #include "r300_reg.h"
 #include "r300_cmdbuf.h"
 #include "r300_emit.h"
-#include "r300_mipmap_tree.h"
+#include "radeon_bocs_wrapper.h"
+#include "radeon_mipmap_tree.h"
 #include "r300_state.h"
-#include "radeon_cs_legacy.h"
-#include "radeon_cs_gem.h"
 #include "radeon_reg.h"
 
-#define R300_VAP_PVS_UPLOAD_ADDRESS 0x2200
-#   define RADEON_ONE_REG_WR        (1 << 15)
-
-// Set this to 1 for extremely verbose debugging of command buffers
-#define DEBUG_CMDBUF           0
-
 /** # of dwords reserved for additional instructions that may need to be written
  * during flushing.
  */
 #define SPACE_FOR_FLUSHING     4
 
-/**
- * Send the current command buffer via ioctl to the hardware.
- */
-int r300FlushCmdBufLocked(r300ContextPtr r300, const char *caller)
+static unsigned packet0_count(r300ContextPtr r300, uint32_t *pkt)
 {
-       int ret = 0;
-
-       if (r300->cmdbuf.flushing) {
-               fprintf(stderr, "Recursive call into r300FlushCmdBufLocked!\n");
-               exit(-1);
-       }
-       r300->cmdbuf.flushing = 1;
-    if (r300->cmdbuf.cs->cdw) {
-        ret = radeon_cs_emit(r300->cmdbuf.cs);
+    if (r300->radeon.radeonScreen->kernel_mm) {
+        return ((((*pkt) >> 16) & 0x3FFF) + 1);
+    } else {
+        drm_r300_cmd_header_t *t = (drm_r300_cmd_header_t*)pkt;
+        return t->packet0.count;
     }
-    radeon_cs_erase(r300->cmdbuf.cs);
-       r300->cmdbuf.flushing = 0;
-       return ret;
 }
 
-int r300FlushCmdBuf(r300ContextPtr r300, const char *caller)
-{
-       int ret;
-
-       LOCK_HARDWARE(&r300->radeon);
-       ret = r300FlushCmdBufLocked(r300, caller);
-       UNLOCK_HARDWARE(&r300->radeon);
-
-       if (ret) {
-               fprintf(stderr, "drmRadeonCmdBuffer: %d\n", ret);
-               _mesa_exit(ret);
-       }
-
-       return ret;
-}
-
-/**
- * Make sure that enough space is available in the command buffer
- * by flushing if necessary.
- *
- * \param dwords The number of dwords we need to be free on the command buffer
- */
-void r300EnsureCmdBufSpace(r300ContextPtr r300, int dwords, const char *caller)
-{
-       if ((r300->cmdbuf.cs->cdw + dwords + 128) > r300->cmdbuf.size ||
-        radeon_cs_need_flush(r300->cmdbuf.cs)) {
-               r300FlushCmdBuf(r300, caller);
-    }
-}
+#define vpu_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count)
+#define r500fp_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->r500fp.count)
 
-void r300BeginBatch(r300ContextPtr r300, int n,
-                   int dostate,
-                    const char *file,
-                    const char *function,
-                    int line)
+void emit_vpu(GLcontext *ctx, struct radeon_state_atom * atom)
 {
-       r300EnsureCmdBufSpace(r300, n, function);
-       if (!r300->cmdbuf.cs->cdw && dostate) {
-               if (RADEON_DEBUG & DEBUG_IOCTL)
-                       fprintf(stderr, "Reemit state after flush (from %s)\n", function);
-               r300EmitState(r300);
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       BATCH_LOCALS(&r300->radeon);
+       drm_r300_cmd_header_t cmd;
+       uint32_t addr, ndw, i;
+
+       if (!r300->radeon.radeonScreen->kernel_mm) {
+               uint32_t dwords;
+               dwords = (*atom->check) (ctx, atom);
+               BEGIN_BATCH_NO_AUTOSTATE(dwords);
+               OUT_BATCH_TABLE(atom->cmd, dwords);
+               END_BATCH();
+               return;
        }
-    radeon_cs_begin(r300->cmdbuf.cs, n, file, function, line);
-}
-
-static void r300PrintStateAtom(r300ContextPtr r300,
-                               struct r300_state_atom *state)
-{
-       int i;
-       int dwords = (*state->check) (r300, state);
-
-       fprintf(stderr, "  emit %s %d/%d\n", state->name, dwords, state->cmd_size);
 
-       if (RADEON_DEBUG & DEBUG_VERBOSE) {
-               for (i = 0; i < dwords; i++) {
-                       fprintf(stderr, "      %s[%d]: %08x\n",
-                               state->name, i, state->cmd[i]);
+       cmd.u = atom->cmd[0];
+       addr = (cmd.vpu.adrhi << 8) | cmd.vpu.adrlo;
+       ndw = cmd.vpu.count * 4;
+       if (ndw) {
+
+               if (r300->vap_flush_needed) {
+                       BEGIN_BATCH_NO_AUTOSTATE(15 + ndw);
+
+                       /* flush processing vertices */
+                       OUT_BATCH_REGVAL(R300_SC_SCREENDOOR, 0);
+                       OUT_BATCH_REGVAL(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
+                       OUT_BATCH_REGVAL(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+                       OUT_BATCH_REGVAL(R300_SC_SCREENDOOR, 0xffffff);
+                       OUT_BATCH_REGVAL(R300_VAP_PVS_STATE_FLUSH_REG, 0);
+                       r300->vap_flush_needed = GL_FALSE;
+               } else {
+                       BEGIN_BATCH_NO_AUTOSTATE(5 + ndw);
                }
-       }
-}
-
-/**
- * Emit all atoms with a dirty field equal to dirty.
- *
- * The caller must have ensured that there is enough space in the command
- * buffer.
- */
-static INLINE void r300EmitAtoms(r300ContextPtr r300, GLboolean dirty)
-{
-       BATCH_LOCALS(r300);
-       struct r300_state_atom *atom;
-       int dwords;
-
-    cp_wait(r300, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
-       BEGIN_BATCH_NO_AUTOSTATE(2);
-       OUT_BATCH(cmdpacket0(r300->radeon.radeonScreen, R300_TX_INVALTAGS, 1));
-       OUT_BATCH(R300_TX_FLUSH);
-       END_BATCH();
-    end_3d(r300);
-
-       /* Emit actual atoms */
-       foreach(atom, &r300->hw.atomlist) {
-               if ((atom->dirty || r300->hw.all_dirty) == dirty) {
-                       dwords = (*atom->check) (r300, atom);
-                       if (dwords) {
-                               if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) {
-                                       r300PrintStateAtom(r300, atom);
-                               }
-                               if (atom->emit) {
-                                       (*atom->emit)(r300, atom);
-                               } else {
-                                       BEGIN_BATCH_NO_AUTOSTATE(dwords);
-                                       OUT_BATCH_TABLE(atom->cmd, dwords);
-                                       END_BATCH();
-                               }
-                               atom->dirty = GL_FALSE;
-                       } else {
-                               if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) {
-                                       fprintf(stderr, "  skip state %s\n",
-                                               atom->name);
-                               }
-                       }
+               OUT_BATCH_REGVAL(R300_VAP_PVS_VECTOR_INDX_REG, addr);
+               OUT_BATCH(CP_PACKET0(R300_VAP_PVS_UPLOAD_DATA, ndw-1) | RADEON_ONE_REG_WR);
+               for (i = 0; i < ndw; i++) {
+                       OUT_BATCH(atom->cmd[i+1]);
                }
+               OUT_BATCH_REGVAL(R300_VAP_PVS_STATE_FLUSH_REG, 0);
+               END_BATCH();
        }
-
-       COMMIT_BATCH();
 }
 
-/**
- * Copy dirty hardware state atoms into the command buffer.
- *
- * We also copy out clean state if we're at the start of a buffer. That makes
- * it easy to recover from lost contexts.
- */
-void r300EmitState(r300ContextPtr r300)
+void emit_r500fp(GLcontext *ctx, struct radeon_state_atom * atom)
 {
-       if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_PRIMS))
-               fprintf(stderr, "%s\n", __FUNCTION__);
-
-       if (r300->cmdbuf.cs->cdw && !r300->hw.is_dirty
-           && !r300->hw.all_dirty)
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       BATCH_LOCALS(&r300->radeon);
+       drm_r300_cmd_header_t cmd;
+       uint32_t addr, ndw, i, sz;
+       int type, clamp, stride;
+
+       if (!r300->radeon.radeonScreen->kernel_mm) {
+               uint32_t dwords;
+               dwords = (*atom->check) (ctx, atom);
+               BEGIN_BATCH_NO_AUTOSTATE(dwords);
+               OUT_BATCH_TABLE(atom->cmd, dwords);
+               END_BATCH();
                return;
-
-       /* To avoid going across the entire set of states multiple times, just check
-        * for enough space for the case of emitting all state.
-        */
-       r300EnsureCmdBufSpace(r300, r300->hw.max_state_size, __FUNCTION__);
-
-       if (!r300->cmdbuf.cs->cdw) {
-               if (RADEON_DEBUG & DEBUG_STATE)
-                       fprintf(stderr, "Begin reemit state\n");
-
-               r300EmitAtoms(r300, GL_FALSE);
        }
 
-       if (RADEON_DEBUG & DEBUG_STATE)
-               fprintf(stderr, "Begin dirty state\n");
+       cmd.u = atom->cmd[0];
+       sz = cmd.r500fp.count;
+       addr = ((cmd.r500fp.adrhi_flags & 1) << 8) | cmd.r500fp.adrlo;
+       type = !!(cmd.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
+       clamp = !!(cmd.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
 
-       r300EmitAtoms(r300, GL_TRUE);
-       r300->hw.is_dirty = GL_FALSE;
-       r300->hw.all_dirty = GL_FALSE;
-}
+       addr |= (type << 16);
+       addr |= (clamp << 17);
 
-static unsigned packet0_count(r300ContextPtr r300, uint32_t *pkt)
-{
-    if (r300->radeon.radeonScreen->driScreen->dri2.enabled) {
-        return ((((*pkt) >> 16) & 0x3FFF) + 1);
-    } else {
-        drm_r300_cmd_header_t *t = (drm_r300_cmd_header_t*)pkt;
-        return t->packet0.count;
-    }
-    return 0;
-}
+       stride = type ? 4 : 6;
 
-#define vpu_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count)
-#define r500fp_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->r500fp.count)
-
-void emit_vpu(r300ContextPtr r300, struct r300_state_atom * atom)
-{
-       BATCH_LOCALS(r300);
-       drm_r300_cmd_header_t cmd;
-    uint32_t addr, ndw, i;
-
-    if (!r300->radeon.radeonScreen->driScreen->dri2.enabled) {
-        uint32_t dwords;
-       dwords = (*atom->check) (r300, atom);
-        BEGIN_BATCH_NO_AUTOSTATE(dwords);
-        OUT_BATCH_TABLE(atom->cmd, dwords);
-        END_BATCH();
-        return;
-    }
+       ndw = sz * stride;
+       if (ndw) {
 
-    cmd.u = atom->cmd[0];
-    addr = (cmd.vpu.adrhi << 8) | cmd.vpu.adrlo;
-       ndw = cmd.vpu.count * 4;
-    if (ndw) {
-        /* flush processing vertices */
-        OUT_BATCH(CP_PACKET0(R300_SC_SCREENDOOR, 0));
-        OUT_BATCH(0x0);
-        OUT_BATCH(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
-        OUT_BATCH((1 << 15) | (1 << 28));
-        OUT_BATCH(CP_PACKET0(R300_SC_SCREENDOOR, 0));
-        OUT_BATCH(0x00FFFFFF);
-        OUT_BATCH(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
-        OUT_BATCH(1);
-        /* write vpu */
-        OUT_BATCH(CP_PACKET0(R300_VAP_PVS_UPLOAD_ADDRESS, 0));
-        OUT_BATCH(addr);
-        OUT_BATCH(CP_PACKET0(R300_VAP_PVS_UPLOAD_DATA, ndw-1) | RADEON_ONE_REG_WR);
-        for (i = 0; i < ndw; i++) {
-            OUT_BATCH(atom->cmd[i+1]);
-        }
-    }
+               BEGIN_BATCH_NO_AUTOSTATE(3 + ndw);
+               OUT_BATCH(CP_PACKET0(R500_GA_US_VECTOR_INDEX, 0));
+               OUT_BATCH(addr);
+               OUT_BATCH(CP_PACKET0(R500_GA_US_VECTOR_DATA, ndw-1) | RADEON_ONE_REG_WR);
+               for (i = 0; i < ndw; i++) {
+                       OUT_BATCH(atom->cmd[i+1]);
+               }
+               END_BATCH();
+       }
 }
 
-static void emit_tex_offsets(r300ContextPtr r300, struct r300_state_atom * atom)
+static void emit_tex_offsets(GLcontext *ctx, struct radeon_state_atom * atom)
 {
-       BATCH_LOCALS(r300);
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       BATCH_LOCALS(&r300->radeon);
        int numtmus = packet0_count(r300, r300->hw.tex.offset.cmd);
+       int notexture = 0;
 
        if (numtmus) {
                int i;
 
                for(i = 0; i < numtmus; ++i) {
-                   BEGIN_BATCH(2);
-               OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
-                       r300TexObj *t = r300->hw.textures[i];
-                       if (t && !t->image_override) {
-                               OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
-                                RADEON_GEM_DOMAIN_VRAM, 0, 0);
-                       } else if (!t) {
-                               OUT_BATCH(r300->radeon.radeonScreen->texOffset[0]);
-                       } else {
-                if (t->bo) {
-                    OUT_BATCH_RELOC(t->tile_bits, t->bo, 0,
-                    RADEON_GEM_DOMAIN_VRAM, 0, 0);
-                } else {
-                               OUT_BATCH(t->override_offset);
+                   radeonTexObj *t = r300->hw.textures[i];
+
+                   if (!t)
+                       notexture = 1;
+               }
+
+               if (r300->radeon.radeonScreen->kernel_mm && notexture) {
+                       return;
+               }
+               for(i = 0; i < numtmus; ++i) {
+                   radeonTexObj *t = r300->hw.textures[i];
+                   if (t && !t->image_override) {
+                BEGIN_BATCH_NO_AUTOSTATE(4);
+                OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
+                           OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
+                                           RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+                END_BATCH();
+                   } else if (!t) {
+                /* Texture unit hasn't a texture bound nothings to do */
+                   } else { /* override cases */
+                           if (t->bo) {
+                    BEGIN_BATCH_NO_AUTOSTATE(4);
+                    OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
+                                   OUT_BATCH_RELOC(t->tile_bits, t->bo, 0,
+                                                   RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+                    END_BATCH();
+                           } else if (!r300->radeon.radeonScreen->kernel_mm) {
+                    BEGIN_BATCH_NO_AUTOSTATE(2);
+                    OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
+                                   OUT_BATCH(t->override_offset);
+                    END_BATCH();
+                           } else {
+                    /* Texture unit hasn't a texture bound nothings to do */
                 }
-                       }
-            END_BATCH();
+                   }
                }
        }
 }
 
-static void emit_cb_offset(r300ContextPtr r300, struct r300_state_atom * atom)
+void r300_emit_scissor(GLcontext *ctx)
 {
-       BATCH_LOCALS(r300);
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       BATCH_LOCALS(&r300->radeon);
+    unsigned x1, y1, x2, y2;
        struct radeon_renderbuffer *rrb;
-       uint32_t cbpitch;
-       GLframebuffer *fb = r300->radeon.dri.drawable->driverPrivate;
 
-       rrb = r300->radeon.state.color.rrb;
-    if (r300->radeon.radeonScreen->driScreen->dri2.enabled) {
-        rrb = fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+    if (!r300->radeon.radeonScreen->driScreen->dri2.enabled) {
+        return;
     }
-       if (!rrb) {
+       rrb = radeon_get_colorbuffer(&r300->radeon);
+       if (!rrb || !rrb->bo) {
+               fprintf(stderr, "no rrb\n");
+               return;
+       }
+    if (r300->radeon.state.scissor.enabled) {
+        x1 = r300->radeon.state.scissor.rect.x1;
+        y1 = r300->radeon.state.scissor.rect.y1;
+        x2 = r300->radeon.state.scissor.rect.x2 - 1;
+        y2 = r300->radeon.state.scissor.rect.y2 - 1;
+    } else {
+        x1 = 0;
+        y1 = 0;
+        x2 = rrb->width - 1;
+        y2 = rrb->height - 1;
+    }
+    if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) {
+        x1 += R300_SCISSORS_OFFSET;
+        y1 += R300_SCISSORS_OFFSET;
+        x2 += R300_SCISSORS_OFFSET;
+        y2 += R300_SCISSORS_OFFSET;
+    }
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    OUT_BATCH_REGSEQ(R300_SC_SCISSORS_TL, 2);
+    OUT_BATCH((x1 << R300_SCISSORS_X_SHIFT)|(y1 << R300_SCISSORS_Y_SHIFT));
+    OUT_BATCH((x2 << R300_SCISSORS_X_SHIFT)|(y2 << R300_SCISSORS_Y_SHIFT));
+    END_BATCH();
+}
+
+static void emit_cb_offset(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       BATCH_LOCALS(&r300->radeon);
+       struct radeon_renderbuffer *rrb;
+       uint32_t cbpitch;
+       uint32_t offset = r300->radeon.state.color.draw_offset;
+       uint32_t dw = 6;
+    int i;
+
+       rrb = radeon_get_colorbuffer(&r300->radeon);
+       if (!rrb || !rrb->bo) {
                fprintf(stderr, "no rrb\n");
                return;
        }
@@ -339,55 +273,169 @@ static void emit_cb_offset(r300ContextPtr r300, struct r300_state_atom * atom)
        if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
                cbpitch |= R300_COLOR_TILE_ENABLE;
 
-       BEGIN_BATCH(4);
+       if (r300->radeon.radeonScreen->kernel_mm)
+               dw += 2;
+       BEGIN_BATCH_NO_AUTOSTATE(dw);
        OUT_BATCH_REGSEQ(R300_RB3D_COLOROFFSET0, 1);
-       OUT_BATCH_RELOC(0, rrb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+       OUT_BATCH_RELOC(offset, rrb->bo, offset, 0, RADEON_GEM_DOMAIN_VRAM, 0);
        OUT_BATCH_REGSEQ(R300_RB3D_COLORPITCH0, 1);
-       OUT_BATCH(cbpitch);
+       if (!r300->radeon.radeonScreen->kernel_mm)
+               OUT_BATCH(cbpitch);
+       else
+               OUT_BATCH_RELOC(cbpitch, rrb->bo, cbpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0);
        END_BATCH();
+    if (r300->radeon.radeonScreen->driScreen->dri2.enabled) {
+        if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+            BEGIN_BATCH_NO_AUTOSTATE(3);
+            OUT_BATCH_REGSEQ(R300_SC_SCISSORS_TL, 2);
+            OUT_BATCH(0);
+            OUT_BATCH(((rrb->width - 1) << R300_SCISSORS_X_SHIFT) |
+                    ((rrb->height - 1) << R300_SCISSORS_Y_SHIFT));
+            END_BATCH();
+            BEGIN_BATCH_NO_AUTOSTATE(16);
+            for (i = 0; i < 4; i++) {
+                OUT_BATCH_REGSEQ(R300_SC_CLIPRECT_TL_0 + (i * 8), 2);
+                OUT_BATCH((0 << R300_CLIPRECT_X_SHIFT) | (0 << R300_CLIPRECT_Y_SHIFT));
+                OUT_BATCH(((rrb->width - 1) << R300_CLIPRECT_X_SHIFT) | ((rrb->height - 1) << R300_CLIPRECT_Y_SHIFT));
+            }
+            OUT_BATCH_REGSEQ(R300_SC_CLIP_RULE, 1);
+            OUT_BATCH(0xAAAA);
+            OUT_BATCH_REGSEQ(R300_SC_SCREENDOOR, 1);
+            OUT_BATCH(0xffffff);
+            END_BATCH();
+        } else {
+            BEGIN_BATCH_NO_AUTOSTATE(3);
+            OUT_BATCH_REGSEQ(R300_SC_SCISSORS_TL, 2);
+            OUT_BATCH((R300_SCISSORS_OFFSET << R300_SCISSORS_X_SHIFT) |
+                    (R300_SCISSORS_OFFSET << R300_SCISSORS_Y_SHIFT));
+            OUT_BATCH(((rrb->width + R300_SCISSORS_OFFSET - 1) << R300_SCISSORS_X_SHIFT) |
+                    ((rrb->height + R300_SCISSORS_OFFSET - 1) << R300_SCISSORS_Y_SHIFT));
+            END_BATCH();
+            BEGIN_BATCH_NO_AUTOSTATE(16);
+            for (i = 0; i < 4; i++) {
+                OUT_BATCH_REGSEQ(R300_SC_CLIPRECT_TL_0 + (i * 8), 2);
+                OUT_BATCH((R300_SCISSORS_OFFSET << R300_CLIPRECT_X_SHIFT) | (R300_SCISSORS_OFFSET << R300_CLIPRECT_Y_SHIFT));
+                OUT_BATCH(((R300_SCISSORS_OFFSET + rrb->width - 1) << R300_CLIPRECT_X_SHIFT) |
+                          ((R300_SCISSORS_OFFSET + rrb->height - 1) << R300_CLIPRECT_Y_SHIFT));
+            }
+            OUT_BATCH_REGSEQ(R300_SC_CLIP_RULE, 1);
+            OUT_BATCH(0xAAAA);
+            OUT_BATCH_REGSEQ(R300_SC_SCREENDOOR, 1);
+            OUT_BATCH(0xffffff);
+            END_BATCH();
+        }
+    }
 }
 
-static void emit_zb_offset(r300ContextPtr r300, struct r300_state_atom * atom)
+static void emit_zb_offset(GLcontext *ctx, struct radeon_state_atom * atom)
 {
-       BATCH_LOCALS(r300);
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       BATCH_LOCALS(&r300->radeon);
        struct radeon_renderbuffer *rrb;
        uint32_t zbpitch;
 
-       rrb = r300->radeon.state.depth_buffer;
+       rrb = radeon_get_depthbuffer(&r300->radeon);
        if (!rrb)
                return;
 
        zbpitch = (rrb->pitch / rrb->cpp);
-    if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE) {
-        zbpitch |= R300_DEPTHMACROTILE_ENABLE;
-    }
-    if (rrb->bo->flags & RADEON_BO_FLAGS_MICRO_TILE){
-        zbpitch |= R300_DEPTHMICROTILE_TILED;
-    }
+       if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE) {
+               zbpitch |= R300_DEPTHMACROTILE_ENABLE;
+       }
+       if (rrb->bo->flags & RADEON_BO_FLAGS_MICRO_TILE){
+               zbpitch |= R300_DEPTHMICROTILE_TILED;
+       }
 
-       BEGIN_BATCH(4);
+       BEGIN_BATCH_NO_AUTOSTATE(6);
        OUT_BATCH_REGSEQ(R300_ZB_DEPTHOFFSET, 1);
        OUT_BATCH_RELOC(0, rrb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
        OUT_BATCH_REGVAL(R300_ZB_DEPTHPITCH, zbpitch);
        END_BATCH();
 }
 
-static int check_always(r300ContextPtr r300, struct r300_state_atom *atom)
+static void emit_gb_misc(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       BATCH_LOCALS(&r300->radeon);
+    if (!r300->radeon.radeonScreen->driScreen->dri2.enabled) {
+        BEGIN_BATCH_NO_AUTOSTATE(4);
+        OUT_BATCH(atom->cmd[0]);
+        OUT_BATCH(atom->cmd[1]);
+        OUT_BATCH(atom->cmd[2]);
+        OUT_BATCH(atom->cmd[3]);
+        END_BATCH();
+    }
+}
+
+static void emit_threshold_misc(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       BATCH_LOCALS(&r300->radeon);
+    if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+        BEGIN_BATCH_NO_AUTOSTATE(3);
+        OUT_BATCH(atom->cmd[0]);
+        OUT_BATCH(atom->cmd[1]);
+        OUT_BATCH(atom->cmd[2]);
+        END_BATCH();
+    }
+}
+
+static void emit_shade_misc(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       BATCH_LOCALS(&r300->radeon);
+
+    if (!r300->radeon.radeonScreen->driScreen->dri2.enabled) {
+        BEGIN_BATCH_NO_AUTOSTATE(2);
+        OUT_BATCH(atom->cmd[0]);
+        OUT_BATCH(atom->cmd[1]);
+        END_BATCH();
+    }
+}
+
+static void emit_zstencil_format(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       BATCH_LOCALS(&r300->radeon);
+       struct radeon_renderbuffer *rrb;
+       uint32_t format = 0;
+
+       rrb = radeon_get_depthbuffer(&r300->radeon);
+       if (!rrb)
+         format = 0;
+       else {
+         if (rrb->cpp == 2)
+           format = R300_DEPTHFORMAT_16BIT_INT_Z;
+         else if (rrb->cpp == 4)
+           format = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
+       }
+
+       OUT_BATCH(atom->cmd[0]);
+       atom->cmd[1] &= ~0xf;
+       atom->cmd[1] |= format;
+       OUT_BATCH(atom->cmd[1]);
+       OUT_BATCH(atom->cmd[2]);
+       OUT_BATCH(atom->cmd[3]);
+       OUT_BATCH(atom->cmd[4]);
+}
+
+static int check_always(GLcontext *ctx, struct radeon_state_atom *atom)
 {
        return atom->cmd_size;
 }
 
-static int check_variable(r300ContextPtr r300, struct r300_state_atom *atom)
+static int check_variable(GLcontext *ctx, struct radeon_state_atom *atom)
 {
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
        int cnt;
-    if (atom->cmd[0] == CP_PACKET2) {
-        return 0;
-    }
+       if (atom->cmd[0] == CP_PACKET2) {
+               return 0;
+       }
        cnt = packet0_count(r300, atom->cmd);
        return cnt ? cnt + 1 : 0;
 }
 
-int check_vpu(r300ContextPtr r300, struct r300_state_atom *atom)
+int check_vpu(GLcontext *ctx, struct radeon_state_atom *atom)
 {
        int cnt;
 
@@ -395,7 +443,7 @@ int check_vpu(r300ContextPtr r300, struct r300_state_atom *atom)
        return cnt ? (cnt * 4) + 1 : 0;
 }
 
-static int check_r500fp(r300ContextPtr r300, struct r300_state_atom *atom)
+int check_r500fp(GLcontext *ctx, struct radeon_state_atom *atom)
 {
        int cnt;
 
@@ -403,11 +451,11 @@ static int check_r500fp(r300ContextPtr r300, struct r300_state_atom *atom)
        return cnt ? (cnt * 6) + 1 : 0;
 }
 
-static int check_r500fp_const(r300ContextPtr r300, struct r300_state_atom *atom)
+int check_r500fp_const(GLcontext *ctx, struct radeon_state_atom *atom)
 {
        int cnt;
 
-    cnt = r500fp_count(atom->cmd);
+       cnt = r500fp_count(atom->cmd);
        return cnt ? (cnt * 4) + 1 : 0;
 }
 
@@ -419,8 +467,8 @@ static int check_r500fp_const(r300ContextPtr r300, struct r300_state_atom *atom)
       r300->hw.ATOM.idx = (IDX);                                       \
       r300->hw.ATOM.check = check_##CHK;                               \
       r300->hw.ATOM.dirty = GL_FALSE;                                  \
-      r300->hw.max_state_size += (SZ);                                 \
-      insert_at_tail(&r300->hw.atomlist, &r300->hw.ATOM);              \
+      r300->radeon.hw.max_state_size += (SZ);                                  \
+      insert_at_tail(&r300->radeon.hw.atomlist, &r300->hw.ATOM);               \
    } while (0)
 /**
  * Allocate memory for the command buffer and initialize the state atom
@@ -428,18 +476,16 @@ static int check_r500fp_const(r300ContextPtr r300, struct r300_state_atom *atom)
  */
 void r300InitCmdBuf(r300ContextPtr r300)
 {
-       int size, mtu;
-       int has_tcl = 1;
+       int mtu;
+       int has_tcl;
        int is_r500 = 0;
-       int i;
 
-       if (!(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
-               has_tcl = 0;
+       has_tcl = r300->options.hw_tcl_enabled;
 
        if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
                is_r500 = 1;
 
-       r300->hw.max_state_size = 2 + 2;        /* reserve extra space for WAIT_IDLE and tex cache flush */
+       r300->radeon.hw.max_state_size = 2 + 2; /* reserve extra space for WAIT_IDLE and tex cache flush */
 
        mtu = r300->radeon.glCtx->Const.MaxTextureUnits;
        if (RADEON_DEBUG & DEBUG_TEXTURE) {
@@ -447,8 +493,8 @@ void r300InitCmdBuf(r300ContextPtr r300)
        }
 
        /* Setup the atom linked list */
-       make_empty_list(&r300->hw.atomlist);
-       r300->hw.atomlist.name = "atom-list";
+       make_empty_list(&r300->radeon.hw.atomlist);
+       r300->radeon.hw.atomlist.name = "atom-list";
 
        /* Initialize state atoms */
        ALLOC_STATE(vpt, always, R300_VPT_CMDSIZE, 0);
@@ -501,7 +547,10 @@ void r300InitCmdBuf(r300ContextPtr r300)
        ALLOC_STATE(gb_enable, always, 2, 0);
        r300->hw.gb_enable.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GB_ENABLE, 1);
        ALLOC_STATE(gb_misc, always, R300_GB_MISC_CMDSIZE, 0);
-       r300->hw.gb_misc.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GB_MSPOS0, 5);
+       r300->hw.gb_misc.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GB_MSPOS0, 3);
+       r300->hw.gb_misc.emit = emit_gb_misc;
+       ALLOC_STATE(gb_misc2, always, R300_GB_MISC2_CMDSIZE, 0);
+    r300->hw.gb_misc2.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, 0x401C, 2);
        ALLOC_STATE(txe, always, R300_TXE_CMDSIZE, 0);
        r300->hw.txe.cmd[R300_TXE_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_TX_ENABLE, 1);
        ALLOC_STATE(ga_point_s0, always, 5, 0);
@@ -516,8 +565,11 @@ void r300InitCmdBuf(r300ContextPtr r300)
        r300->hw.lcntl.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_LINE_CNTL, 1);
        ALLOC_STATE(ga_line_stipple, always, 4, 0);
        r300->hw.ga_line_stipple.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_LINE_STIPPLE_VALUE, 3);
-       ALLOC_STATE(shade, always, 5, 0);
-       r300->hw.shade.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_ENHANCE, 4);
+       ALLOC_STATE(shade, always, 2, 0);
+       r300->hw.shade.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_ENHANCE, 1);
+       r300->hw.shade.emit = emit_shade_misc;
+       ALLOC_STATE(shade2, always, 4, 0);
+       r300->hw.shade2.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, 0x4278, 3);
        ALLOC_STATE(polygon_mode, always, 4, 0);
        r300->hw.polygon_mode.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_POLY_MODE, 3);
        ALLOC_STATE(fogp, always, 3, 0);
@@ -536,19 +588,12 @@ void r300InitCmdBuf(r300ContextPtr r300)
        ALLOC_STATE(rc, always, R300_RC_CMDSIZE, 0);
        r300->hw.rc.cmd[R300_RC_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_RS_COUNT, 2);
        if (is_r500) {
-               ALLOC_STATE(ri, always, R500_RI_CMDSIZE, 0);
+               ALLOC_STATE(ri, variable, R500_RI_CMDSIZE, 0);
                r300->hw.ri.cmd[R300_RI_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R500_RS_IP_0, 16);
-               for (i = 0; i < 8; i++) {
-                       r300->hw.ri.cmd[R300_RI_CMD_0 + i +1] =
-                         (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_S_SHIFT) |
-                          (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_T_SHIFT) |
-                          (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_R_SHIFT) |
-                          (R500_RS_IP_PTR_K1 << R500_RS_IP_TEX_PTR_Q_SHIFT);
-               }
                ALLOC_STATE(rr, variable, R300_RR_CMDSIZE, 0);
                r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R500_RS_INST_0, 1);
        } else {
-               ALLOC_STATE(ri, always, R300_RI_CMDSIZE, 0);
+               ALLOC_STATE(ri, variable, R300_RI_CMDSIZE, 0);
                r300->hw.ri.cmd[R300_RI_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_RS_IP_0, 8);
                ALLOC_STATE(rr, variable, R300_RR_CMDSIZE, 0);
                r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_RS_INST_0, 1);
@@ -570,10 +615,12 @@ void r300InitCmdBuf(r300ContextPtr r300)
 
                ALLOC_STATE(r500fp, r500fp, R500_FPI_CMDSIZE, 0);
                r300->hw.r500fp.cmd[R300_FPI_CMD_0] =
-            cmdr500fp(r300->radeon.radeonScreen, 0, 0, 0, 0);
+                       cmdr500fp(r300->radeon.radeonScreen, 0, 0, 0, 0);
+               r300->hw.r500fp.emit = emit_r500fp;
                ALLOC_STATE(r500fp_const, r500fp_const, R500_FPP_CMDSIZE, 0);
                r300->hw.r500fp_const.cmd[R300_FPI_CMD_0] =
-            cmdr500fp(r300->radeon.radeonScreen, 0, 0, 1, 0);
+                       cmdr500fp(r300->radeon.radeonScreen, 0, 0, 1, 0);
+               r300->hw.r500fp_const.emit = emit_r500fp;
        } else {
                ALLOC_STATE(fp, always, R300_FP_CMDSIZE, 0);
                r300->hw.fp.cmd[R300_FP_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_US_CONFIG, 3);
@@ -622,20 +669,24 @@ void r300InitCmdBuf(r300ContextPtr r300)
        r300->hw.rb3d_dither_ctl.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_RB3D_DITHER_CTL, 9);
        ALLOC_STATE(rb3d_aaresolve_ctl, always, 2, 0);
        r300->hw.rb3d_aaresolve_ctl.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_RB3D_AARESOLVE_CTL, 1);
-       ALLOC_STATE(rb3d_discard_src_pixel_lte_threshold, always, 3, 0);
-       r300->hw.rb3d_discard_src_pixel_lte_threshold.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 2);
+    ALLOC_STATE(rb3d_discard_src_pixel_lte_threshold, always, 3, 0);
+    r300->hw.rb3d_discard_src_pixel_lte_threshold.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 2);
+       r300->hw.rb3d_discard_src_pixel_lte_threshold.emit = emit_threshold_misc;
        ALLOC_STATE(zs, always, R300_ZS_CMDSIZE, 0);
        r300->hw.zs.cmd[R300_ZS_CMD_0] =
            cmdpacket0(r300->radeon.radeonScreen, R300_ZB_CNTL, 3);
+
        ALLOC_STATE(zstencil_format, always, 5, 0);
        r300->hw.zstencil_format.cmd[0] =
            cmdpacket0(r300->radeon.radeonScreen, R300_ZB_FORMAT, 4);
+       r300->hw.zstencil_format.emit = emit_zstencil_format;
+
        ALLOC_STATE(zb, always, R300_ZB_CMDSIZE, 0);
        r300->hw.zb.emit = emit_zb_offset;
        ALLOC_STATE(zb_depthclearvalue, always, 2, 0);
        r300->hw.zb_depthclearvalue.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_ZB_DEPTHCLEARVALUE, 1);
-       ALLOC_STATE(unk4F30, always, 3, 0);
-       r300->hw.unk4F30.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, 0x4F30, 2);
+       ALLOC_STATE(zb_zmask, always, 3, 0);
+       r300->hw.zb_zmask.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_ZB_ZMASK_OFFSET, 2);
        ALLOC_STATE(zb_hiz_offset, always, 2, 0);
        r300->hw.zb_hiz_offset.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_ZB_HIZ_OFFSET, 1);
        ALLOC_STATE(zb_hiz_pitch, always, 2, 0);
@@ -647,43 +698,43 @@ void r300InitCmdBuf(r300ContextPtr r300)
                ALLOC_STATE(vpi, vpu, R300_VPI_CMDSIZE, 0);
                r300->hw.vpi.cmd[0] =
                    cmdvpu(r300->radeon.radeonScreen, R300_PVS_CODE_START, 0);
-       r300->hw.vpi.emit = emit_vpu;
+               r300->hw.vpi.emit = emit_vpu;
 
                if (is_r500) {
                    ALLOC_STATE(vpp, vpu, R300_VPP_CMDSIZE, 0);
                    r300->hw.vpp.cmd[0] =
                        cmdvpu(r300->radeon.radeonScreen, R500_PVS_CONST_START, 0);
-               r300->hw.vpp.emit = emit_vpu;
+                   r300->hw.vpp.emit = emit_vpu;
 
                    ALLOC_STATE(vps, vpu, R300_VPS_CMDSIZE, 0);
                    r300->hw.vps.cmd[0] =
                        cmdvpu(r300->radeon.radeonScreen, R500_POINT_VPORT_SCALE_OFFSET, 1);
-               r300->hw.vps.emit = emit_vpu;
+                   r300->hw.vps.emit = emit_vpu;
 
                        for (i = 0; i < 6; i++) {
-                               ALLOC_STATE(vpucp[i], vpu, R300_VPUCP_CMDSIZE, 0);
-                               r300->hw.vpucp[i].cmd[0] =
-                                       cmdvpu(r300->radeon.radeonScreen,
+                         ALLOC_STATE(vpucp[i], vpu, R300_VPUCP_CMDSIZE, 0);
+                         r300->hw.vpucp[i].cmd[0] =
+                                 cmdvpu(r300->radeon.radeonScreen,
                            R500_PVS_UCP_START + i, 1);
-               r300->hw.vpucp[i].emit = emit_vpu;
+                               r300->hw.vpucp[i].emit = emit_vpu;
                        }
                } else {
                    ALLOC_STATE(vpp, vpu, R300_VPP_CMDSIZE, 0);
                    r300->hw.vpp.cmd[0] =
                        cmdvpu(r300->radeon.radeonScreen, R300_PVS_CONST_START, 0);
-            r300->hw.vpp.emit = emit_vpu;
+                   r300->hw.vpp.emit = emit_vpu;
 
                    ALLOC_STATE(vps, vpu, R300_VPS_CMDSIZE, 0);
                    r300->hw.vps.cmd[0] =
                        cmdvpu(r300->radeon.radeonScreen, R300_POINT_VPORT_SCALE_OFFSET, 1);
-            r300->hw.vps.emit = emit_vpu;
+                   r300->hw.vps.emit = emit_vpu;
 
                        for (i = 0; i < 6; i++) {
                                ALLOC_STATE(vpucp[i], vpu, R300_VPUCP_CMDSIZE, 0);
                                r300->hw.vpucp[i].cmd[0] =
                                        cmdvpu(r300->radeon.radeonScreen,
-                           R300_PVS_UCP_START + i, 1);
-                r300->hw.vpucp[i].emit = emit_vpu;
+                                              R300_PVS_UCP_START + i, 1);
+                               r300->hw.vpucp[i].emit = emit_vpu;
                        }
                }
        }
@@ -720,59 +771,8 @@ void r300InitCmdBuf(r300ContextPtr r300)
        r300->hw.tex.border_color.cmd[R300_TEX_CMD_0] =
            cmdpacket0(r300->radeon.radeonScreen, R300_TX_BORDER_COLOR_0, 0);
 
-       r300->hw.is_dirty = GL_TRUE;
-       r300->hw.all_dirty = GL_TRUE;
-
-       /* Initialize command buffer */
-       size =
-           256 * driQueryOptioni(&r300->radeon.optionCache,
-                                 "command_buffer_size");
-       if (size < 2 * r300->hw.max_state_size) {
-               size = 2 * r300->hw.max_state_size + 65535;
-       }
-       if (size > 64 * 256)
-               size = 64 * 256;
-
-    size = 64 * 1024 / 4;
-       if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA)) {
-               fprintf(stderr, "sizeof(drm_r300_cmd_header_t)=%zd\n",
-                       sizeof(drm_r300_cmd_header_t));
-               fprintf(stderr, "sizeof(drm_radeon_cmd_buffer_t)=%zd\n",
-                       sizeof(drm_radeon_cmd_buffer_t));
-               fprintf(stderr,
-                       "Allocating %d bytes command buffer (max state is %d bytes)\n",
-                       size * 4, r300->hw.max_state_size * 4);
-       }
-
-    if (r300->radeon.radeonScreen->driScreen->dri2.enabled) {
-        int fd = r300->radeon.radeonScreen->driScreen->fd;
-        r300->cmdbuf.csm = radeon_cs_manager_gem_ctor(fd);
-    } else {
-        r300->cmdbuf.csm = radeon_cs_manager_legacy_ctor(&r300->radeon);
-    }
-    if (r300->cmdbuf.csm == NULL) {
-        /* FIXME: fatal error */
-        return;
-    }
-    r300->cmdbuf.cs = radeon_cs_create(r300->cmdbuf.csm, size);
-    assert(r300->cmdbuf.cs != NULL);
-       r300->cmdbuf.size = size;
-}
-
-/**
- * Destroy the command buffer and state atoms.
- */
-void r300DestroyCmdBuf(r300ContextPtr r300)
-{
-       struct r300_state_atom *atom;
+       r300->radeon.hw.is_dirty = GL_TRUE;
+       r300->radeon.hw.all_dirty = GL_TRUE;
 
-    radeon_cs_destroy(r300->cmdbuf.cs);
-       foreach(atom, &r300->hw.atomlist) {
-               FREE(atom->cmd);
-       }
-    if (r300->radeon.radeonScreen->driScreen->dri2.enabled) {
-        radeon_cs_manager_gem_dtor(r300->cmdbuf.csm);
-    } else {
-        radeon_cs_manager_legacy_dtor(r300->cmdbuf.csm);
-    }
+       rcommonInitCmdBuf(&r300->radeon);
 }