From e5d5dab8c03f72097ec3e5b465fe93b6e369bb2d Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 5 Nov 2008 14:31:46 +0100 Subject: r300: bo and cs abstraction. This abstract memory management and command stream building so we can use different backend either legacy one which use old pathway or a new one like with a new memory manager. This works was done by : Nicolai Haehnle Dave Airlie Jerome Glisse --- src/mesa/drivers/dri/r300/r300_cmdbuf.c | 306 +++++++++++++++++--------------- 1 file changed, 159 insertions(+), 147 deletions(-) (limited to 'src/mesa/drivers/dri/r300/r300_cmdbuf.c') diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c index c9e1dfe977..7d7fed4e5d 100644 --- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c +++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c @@ -44,6 +44,7 @@ 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" @@ -51,62 +52,33 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r300_reg.h" #include "r300_cmdbuf.h" #include "r300_emit.h" +#include "r300_mipmap_tree.h" #include "r300_state.h" +#include "radeon_cs_legacy.h" // 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) { int ret; - int i; - drm_radeon_cmd_buffer_t cmd; - int start; - - if (r300->radeon.lost_context) { - start = 0; - r300->radeon.lost_context = GL_FALSE; - } else - start = r300->cmdbuf.count_reemit; - - if (RADEON_DEBUG & DEBUG_IOCTL) { - fprintf(stderr, "%s from %s - %i cliprects\n", - __FUNCTION__, caller, r300->radeon.numClipRects); - - if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_VERBOSE) - for (i = start; i < r300->cmdbuf.count_used; ++i) - fprintf(stderr, "%d: %08x\n", i, - r300->cmdbuf.cmd_buf[i]); - } - - cmd.buf = (char *)(r300->cmdbuf.cmd_buf + start); - cmd.bufsz = (r300->cmdbuf.count_used - start) * 4; - - if (r300->radeon.state.scissor.enabled) { - cmd.nbox = r300->radeon.state.scissor.numClipRects; - cmd.boxes = - (drm_clip_rect_t *) r300->radeon.state.scissor.pClipRects; - } else { - cmd.nbox = r300->radeon.numClipRects; - cmd.boxes = (drm_clip_rect_t *) r300->radeon.pClipRects; - } - ret = drmCommandWrite(r300->radeon.dri.fd, - DRM_RADEON_CMDBUF, &cmd, sizeof(cmd)); - - if (RADEON_DEBUG & DEBUG_SYNC) { - fprintf(stderr, "Syncing in %s (from %s)\n\n", - __FUNCTION__, caller); - radeonWaitForIdleLocked(&r300->radeon); + if (r300->cmdbuf.flushing) { + fprintf(stderr, "Recursive call into r300FlushCmdBufLocked!\n"); + exit(-1); } - - r300->dma.nr_released_bufs = 0; - r300->cmdbuf.count_used = 0; - r300->cmdbuf.count_reemit = 0; - + r300->cmdbuf.flushing = 1; + ret = radeon_cs_emit(r300->cmdbuf.cs); + radeon_cs_erase(r300->cmdbuf.cs); + r300->cmdbuf.flushing = 0; return ret; } @@ -115,9 +87,7 @@ int r300FlushCmdBuf(r300ContextPtr r300, const char *caller) int ret; LOCK_HARDWARE(&r300->radeon); - ret = r300FlushCmdBufLocked(r300, caller); - UNLOCK_HARDWARE(&r300->radeon); if (ret) { @@ -128,13 +98,44 @@ int r300FlushCmdBuf(r300ContextPtr r300, const char *caller) return ret; } -static void r300PrintStateAtom(r300ContextPtr r300, struct r300_state_atom *state) +/** + * 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) +{ + assert(dwords < r300->cmdbuf.size); + + if ((r300->cmdbuf.cs->cdw + dwords + 128) > r300->cmdbuf.size || + radeon_cs_need_flush(r300->cmdbuf.cs)) { + r300FlushCmdBuf(r300, caller); + } +} + +void r300BeginBatch(r300ContextPtr r300, int n, + int dostate, + const char *file, + const char *function, + int line) +{ + 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); + } + 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); + fprintf(stderr, " emit %s %d/%d\n", state->name, dwords, state->cmd_size); if (RADEON_DEBUG & DEBUG_VERBOSE) { for (i = 0; i < dwords; i++) { @@ -152,33 +153,18 @@ static void r300PrintStateAtom(r300ContextPtr r300, struct r300_state_atom *stat */ static INLINE void r300EmitAtoms(r300ContextPtr r300, GLboolean dirty) { + BATCH_LOCALS(r300); struct r300_state_atom *atom; - uint32_t *dest; int dwords; - dest = r300->cmdbuf.cmd_buf + r300->cmdbuf.count_used; - - /* Emit WAIT */ - *dest = cmdwait(R300_WAIT_3D | R300_WAIT_3D_CLEAN); - dest++; - r300->cmdbuf.count_used++; - - /* Emit cache flush */ - *dest = cmdpacket0(R300_TX_INVALTAGS, 1); - dest++; - r300->cmdbuf.count_used++; - - *dest = R300_TX_FLUSH; - dest++; - r300->cmdbuf.count_used++; - - /* Emit END3D */ - *dest = cmdpacify(); - dest++; - r300->cmdbuf.count_used++; + BEGIN_BATCH_NO_AUTOSTATE(4); + OUT_BATCH(cmdwait(R300_WAIT_3D | R300_WAIT_3D_CLEAN)); + OUT_BATCH(cmdpacket0(R300_TX_INVALTAGS, 1)); + OUT_BATCH(R300_TX_FLUSH); + OUT_BATCH(cmdpacify()); + END_BATCH(); /* Emit actual atoms */ - foreach(atom, &r300->hw.atomlist) { if ((atom->dirty || r300->hw.all_dirty) == dirty) { dwords = (*atom->check) (r300, atom); @@ -186,9 +172,13 @@ static INLINE void r300EmitAtoms(r300ContextPtr r300, GLboolean dirty) if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) { r300PrintStateAtom(r300, atom); } - memcpy(dest, atom->cmd, dwords * 4); - dest += dwords; - r300->cmdbuf.count_used += dwords; + if (atom->emit) { + (*atom->emit)(r300); + } 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) { @@ -198,6 +188,8 @@ static INLINE void r300EmitAtoms(r300ContextPtr r300, GLboolean dirty) } } } + + COMMIT_BATCH(); } /** @@ -211,31 +203,26 @@ void r300EmitState(r300ContextPtr r300) if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_PRIMS)) fprintf(stderr, "%s\n", __FUNCTION__); - if (r300->cmdbuf.count_used && !r300->hw.is_dirty + if (r300->cmdbuf.cs->cdw && !r300->hw.is_dirty && !r300->hw.all_dirty) return; /* 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 - * r300AllocCmdBuf code here without all the checks. + * for enough space for the case of emitting all state. */ r300EnsureCmdBufSpace(r300, r300->hw.max_state_size, __FUNCTION__); - if (!r300->cmdbuf.count_used) { + if (!r300->cmdbuf.cs->cdw) { if (RADEON_DEBUG & DEBUG_STATE) fprintf(stderr, "Begin reemit state\n"); r300EmitAtoms(r300, GL_FALSE); - r300->cmdbuf.count_reemit = r300->cmdbuf.count_used; } if (RADEON_DEBUG & DEBUG_STATE) fprintf(stderr, "Begin dirty state\n"); r300EmitAtoms(r300, GL_TRUE); - - assert(r300->cmdbuf.count_used < r300->cmdbuf.size); - r300->hw.is_dirty = GL_FALSE; r300->hw.all_dirty = GL_FALSE; } @@ -244,6 +231,84 @@ void r300EmitState(r300ContextPtr r300) #define vpu_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count) #define r500fp_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->r500fp.count) +static void emit_tex_offsets(r300ContextPtr r300) +{ + BATCH_LOCALS(r300); + int numtmus = packet0_count(r300->hw.tex.offset.cmd); + + 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, 0); + } else if (!t) { + OUT_BATCH(r300->radeon.radeonScreen->texOffset[0]); + } else { + OUT_BATCH(t->override_offset); + } + END_BATCH(); + } + } +} + +static void emit_cb_offset(r300ContextPtr r300) +{ + BATCH_LOCALS(r300); + struct radeon_renderbuffer *rrb; + uint32_t cbpitch; + + rrb = r300->radeon.state.color.rrb; + if (!rrb) { + fprintf(stderr, "no rrb\n"); + return; + } + + cbpitch = rrb->pitch; + if (rrb->cpp == 4) + cbpitch |= R300_COLOR_FORMAT_ARGB8888; + else + cbpitch |= R300_COLOR_FORMAT_RGB565; + + if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE) + cbpitch |= R300_COLOR_TILE_ENABLE; + + BEGIN_BATCH(4); + OUT_BATCH_REGSEQ(R300_RB3D_COLOROFFSET0, 1); + OUT_BATCH_RELOC(0, rrb->bo, 0, 0); + OUT_BATCH_REGSEQ(R300_RB3D_COLORPITCH0, 1); + OUT_BATCH(cbpitch); + END_BATCH(); +} + +static void emit_zb_offset(r300ContextPtr r300) +{ + BATCH_LOCALS(r300); + struct radeon_renderbuffer *rrb; + uint32_t zbpitch; + + rrb = r300->radeon.state.depth_buffer; + if (!rrb) + return; + + zbpitch = rrb->pitch; + if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE) { + zbpitch |= R300_DEPTHMACROTILE_ENABLE; + } + if (r300->radeon.glCtx->Visual.depthBits == 24) { + zbpitch |= R300_DEPTHMICROTILE_TILED; + } + + BEGIN_BATCH(4); + OUT_BATCH_REGSEQ(R300_ZB_DEPTHOFFSET, 1); + OUT_BATCH_RELOC(0, rrb->bo, 0, 0); + OUT_BATCH_REGVAL(R300_ZB_DEPTHPITCH, zbpitch); + END_BATCH(); +} + static int check_always(r300ContextPtr r300, struct r300_state_atom *atom) { return atom->cmd_size; @@ -480,8 +545,7 @@ void r300InitCmdBuf(r300ContextPtr r300) ALLOC_STATE(rop, always, 2, 0); r300->hw.rop.cmd[0] = cmdpacket0(R300_RB3D_ROPCNTL, 1); ALLOC_STATE(cb, always, R300_CB_CMDSIZE, 0); - r300->hw.cb.cmd[R300_CB_CMD_0] = cmdpacket0(R300_RB3D_COLOROFFSET0, 1); - r300->hw.cb.cmd[R300_CB_CMD_1] = cmdpacket0(R300_RB3D_COLORPITCH0, 1); + r300->hw.cb.emit = &emit_cb_offset; ALLOC_STATE(rb3d_dither_ctl, always, 10, 0); r300->hw.rb3d_dither_ctl.cmd[0] = cmdpacket0(R300_RB3D_DITHER_CTL, 9); ALLOC_STATE(rb3d_aaresolve_ctl, always, 2, 0); @@ -495,7 +559,7 @@ void r300InitCmdBuf(r300ContextPtr r300) r300->hw.zstencil_format.cmd[0] = cmdpacket0(R300_ZB_FORMAT, 4); ALLOC_STATE(zb, always, R300_ZB_CMDSIZE, 0); - r300->hw.zb.cmd[R300_ZB_CMD_0] = cmdpacket0(R300_ZB_DEPTHOFFSET, 2); + r300->hw.zb.emit = emit_zb_offset; ALLOC_STATE(zb_depthclearvalue, always, 2, 0); r300->hw.zb_depthclearvalue.cmd[0] = cmdpacket0(R300_ZB_DEPTHCLEARVALUE, 1); ALLOC_STATE(unk4F30, always, 3, 0); @@ -562,9 +626,10 @@ void r300InitCmdBuf(r300ContextPtr r300) ALLOC_STATE(tex.pitch, variable, mtu + 1, 0); r300->hw.tex.pitch.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_FORMAT2_0, 0); - ALLOC_STATE(tex.offset, variable, mtu + 1, 0); + ALLOC_STATE(tex.offset, variable, 1, 0); r300->hw.tex.offset.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_OFFSET_0, 0); + r300->hw.tex.offset.emit = &emit_tex_offsets; ALLOC_STATE(tex.chroma_key, variable, mtu + 1, 0); r300->hw.tex.chroma_key.cmd[R300_TEX_CMD_0] = @@ -587,6 +652,7 @@ void r300InitCmdBuf(r300ContextPtr r300) 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)); @@ -597,10 +663,14 @@ void r300InitCmdBuf(r300ContextPtr r300) size * 4, r300->hw.max_state_size * 4); } + r300->cmdbuf.csm = radeon_cs_manager_legacy(&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; - r300->cmdbuf.cmd_buf = (uint32_t *) CALLOC(size * 4); - r300->cmdbuf.count_used = 0; - r300->cmdbuf.count_reemit = 0; } /** @@ -610,66 +680,8 @@ void r300DestroyCmdBuf(r300ContextPtr r300) { struct r300_state_atom *atom; - FREE(r300->cmdbuf.cmd_buf); - + radeon_cs_destroy(r300->cmdbuf.cs); foreach(atom, &r300->hw.atomlist) { FREE(atom->cmd); } } - -void r300EmitBlit(r300ContextPtr rmesa, - GLuint color_fmt, - GLuint src_pitch, - GLuint src_offset, - GLuint dst_pitch, - GLuint dst_offset, - GLint srcx, GLint srcy, - GLint dstx, GLint dsty, GLuint w, GLuint h) -{ - drm_r300_cmd_header_t *cmd; - - if (RADEON_DEBUG & DEBUG_IOCTL) - fprintf(stderr, - "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n", - __FUNCTION__, src_pitch, src_offset, srcx, srcy, - dst_pitch, dst_offset, dstx, dsty, w, h); - - assert((src_pitch & 63) == 0); - assert((dst_pitch & 63) == 0); - assert((src_offset & 1023) == 0); - assert((dst_offset & 1023) == 0); - assert(w < (1 << 16)); - assert(h < (1 << 16)); - - cmd = (drm_r300_cmd_header_t *) r300AllocCmdBuf(rmesa, 8, __FUNCTION__); - - cmd[0].header.cmd_type = R300_CMD_PACKET3; - cmd[0].header.pad0 = R300_CMD_PACKET3_RAW; - cmd[1].u = R300_CP_CMD_BITBLT_MULTI | (5 << 16); - cmd[2].u = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | - RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_NONE | - (color_fmt << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP3_S | - RADEON_DP_SRC_SOURCE_MEMORY | - RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); - - cmd[3].u = ((src_pitch / 64) << 22) | (src_offset >> 10); - cmd[4].u = ((dst_pitch / 64) << 22) | (dst_offset >> 10); - cmd[5].u = (srcx << 16) | srcy; - cmd[6].u = (dstx << 16) | dsty; /* dst */ - cmd[7].u = (w << 16) | h; -} - -void r300EmitWait(r300ContextPtr rmesa, GLuint flags) -{ - drm_r300_cmd_header_t *cmd; - - assert(!(flags & ~(R300_WAIT_2D | R300_WAIT_3D))); - - cmd = (drm_r300_cmd_header_t *) r300AllocCmdBuf(rmesa, 1, __FUNCTION__); - cmd[0].u = 0; - cmd[0].wait.cmd_type = R300_CMD_WAIT; - cmd[0].wait.flags = flags; -} -- cgit v1.2.3