mesa/r300-cmdbuf.patch

7670 lines
238 KiB
Diff

diff --git a/src/mesa/drivers/dri/r200/Makefile b/src/mesa/drivers/dri/r200/Makefile
index e9144ac..b6ed58b 100644
--- a/src/mesa/drivers/dri/r200/Makefile
+++ b/src/mesa/drivers/dri/r200/Makefile
@@ -48,7 +48,8 @@ SYMLINKS = \
COMMON_SYMLINKS = \
radeon_chipset.h \
radeon_screen.c \
- radeon_screen.h
+ radeon_screen.h \
+ radeon_buffer.h
##### TARGETS #####
diff --git a/src/mesa/drivers/dri/r300/Makefile b/src/mesa/drivers/dri/r300/Makefile
index 6ca9342..3bb1ff4 100644
--- a/src/mesa/drivers/dri/r300/Makefile
+++ b/src/mesa/drivers/dri/r300/Makefile
@@ -11,15 +11,6 @@ ifeq ($(USING_EGL), 1)
EGL_SOURCES = server/radeon_egl.c
endif
-COMMON_SOURCES = \
- ../../common/driverfuncs.c \
- ../common/mm.c \
- ../common/utils.c \
- ../common/texmem.c \
- ../common/vblank.c \
- ../common/xmlconfig.c \
- ../common/dri_util.c
-
DRIVER_SOURCES = \
radeon_screen.c \
radeon_context.c \
@@ -36,6 +27,7 @@ DRIVER_SOURCES = \
r300_texmem.c \
r300_tex.c \
r300_texstate.c \
+ r300_mipmap_tree.c \
radeon_program.c \
radeon_program_alu.c \
radeon_program_pair.c \
@@ -51,7 +43,7 @@ DRIVER_SOURCES = \
r300_swtcl.c \
$(EGL_SOURCES)
-C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES)
+C_SOURCES = $(COMMON_SOURCES) $(COMMON_BM_SOURCES) $(DRIVER_SOURCES)
DRIVER_DEFINES = -DCOMPILE_R300 -DR200_MERGED=0 \
-DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R300
@@ -68,7 +60,8 @@ COMMON_SYMLINKS = \
radeon_chipset.h \
radeon_screen.c \
radeon_screen.h \
- radeon_span.h
+ radeon_span.h \
+ radeon_buffer.h
##### TARGETS #####
diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c
index c069660..493b0ac 100644
--- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c
+++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c
@@ -51,11 +51,18 @@ 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_mem.h"
+#include "r300_mipmap_tree.h"
#include "r300_state.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.
*/
@@ -66,24 +73,42 @@ int r300FlushCmdBufLocked(r300ContextPtr r300, const char *caller)
drm_radeon_cmd_buffer_t cmd;
int start;
+ if (r300->cmdbuf.flushing) {
+ fprintf(stderr, "Recursive call into r300FlushCmdBufLocked!\n");
+ exit(-1);
+ }
+ r300->cmdbuf.flushing = 1;
+
if (r300->radeon.lost_context) {
start = 0;
r300->radeon.lost_context = GL_FALSE;
} else
- start = r300->cmdbuf.count_reemit;
+ start = r300->cmdbuf.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)
+ if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_VERBOSE) {
+ fprintf(stderr, "written: %d committed: %d\n", r300->cmdbuf.written, r300->cmdbuf.committed);
+ for (i = start; i < r300->cmdbuf.written; ++i)
fprintf(stderr, "%d: %08x\n", i,
- r300->cmdbuf.cmd_buf[i]);
+ ((uint32_t*)r300->cmdbuf.buf->virtual)[i]);
+ }
}
- cmd.buf = (char *)(r300->cmdbuf.cmd_buf + start);
- cmd.bufsz = (r300->cmdbuf.count_used - start) * 4;
+ if (r300->cmdbuf.written != r300->cmdbuf.committed) {
+ _mesa_problem(r300->radeon.glCtx,
+ "Command buffer contains %d uncommitted dwords\n"
+ "in r300FlushCmdBufLocked called from %s.\n",
+ r300->cmdbuf.written - r300->cmdbuf.committed, caller);
+ }
+
+ dri_bo_unmap(r300->cmdbuf.buf);
+ dri_process_relocs(r300->cmdbuf.buf, 0);
+
+ cmd.buf = (char *)r300->cmdbuf.buf->virtual + 4*start;
+ cmd.bufsz = (r300->cmdbuf.committed - start) * 4;
if (r300->radeon.state.scissor.enabled) {
cmd.nbox = r300->radeon.state.scissor.numClipRects;
@@ -103,9 +128,19 @@ int r300FlushCmdBufLocked(r300ContextPtr r300, const char *caller)
radeonWaitForIdleLocked(&r300->radeon);
}
+ dri_post_submit(r300->cmdbuf.buf, 0);
+ dri_bo_unreference(r300->cmdbuf.buf);
+
r300->dma.nr_released_bufs = 0;
- r300->cmdbuf.count_used = 0;
- r300->cmdbuf.count_reemit = 0;
+ r300->cmdbuf.buf = dri_bo_alloc(&r300->radeon.bufmgr->base, "cmdbuf",
+ r300->cmdbuf.size*4, 16, DRM_BO_MEM_CMDBUF);
+ r300->cmdbuf.written = 0;
+ r300->cmdbuf.reserved = 0;
+ r300->cmdbuf.committed = 0;
+ r300->cmdbuf.reemit = 0;
+ dri_bo_map(r300->cmdbuf.buf, GL_TRUE);
+
+ r300->cmdbuf.flushing = 0;
return ret;
}
@@ -115,9 +150,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,6 +161,44 @@ int r300FlushCmdBuf(r300ContextPtr r300, const char *caller)
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)
+{
+ assert(dwords < r300->cmdbuf.size);
+
+ if (!r300->cmdbuf.flushing)
+ dwords += SPACE_FOR_FLUSHING;
+
+ if (r300->cmdbuf.written + dwords > r300->cmdbuf.size)
+ r300FlushCmdBuf(r300, caller);
+}
+
+void r300BeginBatch(r300ContextPtr r300, int n, GLboolean autostate, const char* function, int line)
+{
+ assert(r300->cmdbuf.written == r300->cmdbuf.reserved);
+
+ r300EnsureCmdBufSpace(r300, n, function);
+
+ if (autostate && !r300->cmdbuf.written) {
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr,
+ "Reemit state after flush (from %s)\n", function);
+ r300EmitState(r300);
+ }
+
+ r300->cmdbuf.reserved += n;
+ assert(r300->cmdbuf.reserved < r300->cmdbuf.size);
+
+ if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
+ n, r300->cmdbuf.written, function, line);
+}
+
static void r300PrintStateAtom(r300ContextPtr r300, struct r300_state_atom *state)
{
int i;
@@ -152,33 +223,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 +242,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 +258,8 @@ static INLINE void r300EmitAtoms(r300ContextPtr r300, GLboolean dirty)
}
}
}
+
+ COMMIT_BATCH();
}
/**
@@ -211,22 +273,21 @@ 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.written && !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.written) {
if (RADEON_DEBUG & DEBUG_STATE)
fprintf(stderr, "Begin reemit state\n");
r300EmitAtoms(r300, GL_FALSE);
- r300->cmdbuf.count_reemit = r300->cmdbuf.count_used;
+ r300->cmdbuf.reemit = r300->cmdbuf.committed;
}
if (RADEON_DEBUG & DEBUG_STATE)
@@ -234,7 +295,7 @@ void r300EmitState(r300ContextPtr r300)
r300EmitAtoms(r300, GL_TRUE);
- assert(r300->cmdbuf.count_used < r300->cmdbuf.size);
+ assert(r300->cmdbuf.written < r300->cmdbuf.size);
r300->hw.is_dirty = GL_FALSE;
r300->hw.all_dirty = GL_FALSE;
@@ -244,6 +305,79 @@ 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;
+
+ BEGIN_BATCH(numtmus + 1);
+ OUT_BATCH_REGSEQ(R300_TX_OFFSET_0, numtmus);
+ for(i = 0; i < numtmus; ++i) {
+ r300TexObj *t = r300->hw.textures[i];
+ if (t && !t->image_override) {
+ OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0, DRM_RELOC_TXOFFSET);
+ } 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 (r300->radeon.sarea->tiling_enabled)
+ cbpitch |= R300_COLOR_TILE_ENABLE;
+
+ BEGIN_BATCH(4);
+ OUT_BATCH_REGSEQ(R300_RB3D_COLOROFFSET0, 1);
+ OUT_BATCH_RELOC(0, rrb->bo, 0, DRM_RELOC_TXOFFSET);
+ 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;
+
+ BEGIN_BATCH(3);
+ OUT_BATCH_REGSEQ(R300_ZB_DEPTHOFFSET, 2);
+ OUT_BATCH_RELOC(0, rrb->bo, 0, DRM_RELOC_TXOFFSET);
+ OUT_BATCH(zbpitch);
+ END_BATCH();
+
+}
+
static int check_always(r300ContextPtr r300, struct r300_state_atom *atom)
{
return atom->cmd_size;
@@ -480,8 +614,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 +628,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 +695,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] =
@@ -597,10 +731,14 @@ void r300InitCmdBuf(r300ContextPtr r300)
size * 4, r300->hw.max_state_size * 4);
}
+ r300->cmdbuf.buf = dri_bo_alloc(&r300->radeon.bufmgr->base, "cmdbuf",
+ size*4, 16, DRM_BO_MEM_CMDBUF);
r300->cmdbuf.size = size;
- r300->cmdbuf.cmd_buf = (uint32_t *) CALLOC(size * 4);
- r300->cmdbuf.count_used = 0;
- r300->cmdbuf.count_reemit = 0;
+ r300->cmdbuf.written = 0;
+ r300->cmdbuf.reserved = 0;
+ r300->cmdbuf.committed = 0;
+ r300->cmdbuf.reemit = 0;
+ dri_bo_map(r300->cmdbuf.buf, GL_TRUE);
}
/**
@@ -610,66 +748,10 @@ void r300DestroyCmdBuf(r300ContextPtr r300)
{
struct r300_state_atom *atom;
- FREE(r300->cmdbuf.cmd_buf);
+ dri_bo_unmap(r300->cmdbuf.buf);
+ dri_bo_unreference(r300->cmdbuf.buf);
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;
-}
diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.h b/src/mesa/drivers/dri/r300/r300_cmdbuf.h
index a8eaa58..4708a4c 100644
--- a/src/mesa/drivers/dri/r300/r300_cmdbuf.h
+++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.h
@@ -45,29 +45,88 @@ extern void r300EmitState(r300ContextPtr r300);
extern void r300InitCmdBuf(r300ContextPtr r300);
extern void r300DestroyCmdBuf(r300ContextPtr r300);
+extern void r300EnsureCmdBufSpace(r300ContextPtr r300, int dwords, const char *caller);
+
+extern void r300BeginBatch(r300ContextPtr r300, int n, GLboolean autostate, const char* function, int line);
/**
- * 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
+ * Every function writing to the command buffer needs to declare this
+ * to get the necessary local variables.
*/
-static INLINE void r300EnsureCmdBufSpace(r300ContextPtr r300,
- int dwords, const char *caller)
-{
- assert(dwords < r300->cmdbuf.size);
+#define BATCH_LOCALS(r300) \
+ const r300ContextPtr b_l_r300 = r300
- if (r300->cmdbuf.count_used + dwords > r300->cmdbuf.size)
- r300FlushCmdBuf(r300, caller);
-}
+/**
+ * Prepare writing n dwords to the command buffer,
+ * including producing any necessary state emits on buffer wraparound.
+ */
+#define BEGIN_BATCH(n) r300BeginBatch(b_l_r300, n, GL_TRUE, __FUNCTION__, __LINE__)
+
+/**
+ * Same as BEGIN_BATCH, but do not cause automatic state emits.
+ */
+#define BEGIN_BATCH_NO_AUTOSTATE(n) r300BeginBatch(b_l_r300, n, GL_FALSE, __FUNCTION__, __LINE__)
+
+/**
+ * Write one dword to the command buffer.
+ */
+#define OUT_BATCH(data) \
+ do { \
+ if (b_l_r300->cmdbuf.written < b_l_r300->cmdbuf.reserved) { \
+ ((uint32_t*)b_l_r300->cmdbuf.buf->virtual)[b_l_r300->cmdbuf.written++] = data; \
+ } else { \
+ _mesa_problem(b_l_r300->radeon.glCtx, "%s:%i: OUT_BATCH mismatch", __FUNCTION__, __LINE__); \
+ } \
+ } while(0)
/**
- * Allocate the given number of dwords in the command buffer and return
- * a pointer to the allocated area.
- * When necessary, these functions cause a flush. r300AllocCmdBuf() also
- * causes state reemission after a flush. This is necessary to ensure
- * correct hardware state after an unlock.
+ * Write a relocated dword to the command buffer.
*/
+#define OUT_BATCH_RELOC(data, bo, offset, flags) \
+ do { \
+ if (b_l_r300->cmdbuf.written < b_l_r300->cmdbuf.reserved) { \
+ dri_emit_reloc(b_l_r300->cmdbuf.buf, flags, offset, 4*b_l_r300->cmdbuf.written, bo); \
+ ((uint32_t*)b_l_r300->cmdbuf.buf->virtual)[b_l_r300->cmdbuf.written++] = data; \
+ } else { \
+ _mesa_problem(b_l_r300->radeon.glCtx, "%s:%i: OUT_BATCH mismatch", __FUNCTION__, __LINE__); \
+ } \
+ } while(0)
+
+/**
+ * Write n dwords from ptr to the command buffer.
+ */
+#define OUT_BATCH_TABLE(ptr,n) \
+ do { \
+ int _n = n; \
+ if (b_l_r300->cmdbuf.written+_n <= b_l_r300->cmdbuf.reserved) { \
+ memcpy((uint32_t*)b_l_r300->cmdbuf.buf->virtual + b_l_r300->cmdbuf.written, (ptr), 4*_n); \
+ b_l_r300->cmdbuf.written += _n; \
+ } else { \
+ _mesa_problem(b_l_r300->radeon.glCtx, "%s:%i: OUT_BATCH_TABLE mismatch", __FUNCTION__, __LINE__); \
+ } \
+ } while(0)
+
+/**
+ * Finish writing dwords to the command buffer.
+ * The number of (direct or indirect) OUT_BATCH calls between the previous
+ * BEGIN_BATCH and END_BATCH must match the number specified at BEGIN_BATCH time.
+ */
+#define END_BATCH() \
+ do { \
+ if (b_l_r300->cmdbuf.written != b_l_r300->cmdbuf.reserved) \
+ _mesa_problem(b_l_r300->radeon.glCtx, "%s:%i: END_BATCH mismatch", __FUNCTION__, __LINE__); \
+ } while(0)
+
+/**
+ * After the last END_BATCH() of rendering, this indicates that flushing
+ * the command buffer now is okay.
+ */
+#define COMMIT_BATCH() \
+ do { \
+ assert(b_l_r300->cmdbuf.written == b_l_r300->cmdbuf.reserved); \
+ b_l_r300->cmdbuf.committed = b_l_r300->cmdbuf.written; \
+ } while(0)
+
static INLINE uint32_t *r300RawAllocCmdBuf(r300ContextPtr r300,
int dwords, const char *caller)
{
@@ -75,8 +134,9 @@ static INLINE uint32_t *r300RawAllocCmdBuf(r300ContextPtr r300,
r300EnsureCmdBufSpace(r300, dwords, caller);
- ptr = &r300->cmdbuf.cmd_buf[r300->cmdbuf.count_used];
- r300->cmdbuf.count_used += dwords;
+ ptr = (uint32_t*)r300->cmdbuf.buf->virtual + r300->cmdbuf.written;
+ r300->cmdbuf.written += dwords;
+ r300->cmdbuf.reserved = r300->cmdbuf.committed = r300->cmdbuf.written;
return ptr;
}
@@ -87,30 +147,17 @@ static INLINE uint32_t *r300AllocCmdBuf(r300ContextPtr r300,
r300EnsureCmdBufSpace(r300, dwords, caller);
- if (!r300->cmdbuf.count_used) {
+ if (!r300->cmdbuf.written) {
if (RADEON_DEBUG & DEBUG_IOCTL)
fprintf(stderr,
"Reemit state after flush (from %s)\n", caller);
r300EmitState(r300);
}
- ptr = &r300->cmdbuf.cmd_buf[r300->cmdbuf.count_used];
- r300->cmdbuf.count_used += dwords;
+ ptr = (uint32_t*)r300->cmdbuf.buf->virtual + r300->cmdbuf.written;
+ r300->cmdbuf.written += dwords;
+ r300->cmdbuf.reserved = r300->cmdbuf.committed = r300->cmdbuf.written;
return ptr;
}
-extern 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);
-
-extern void r300EmitWait(r300ContextPtr rmesa, GLuint flags);
-extern void r300EmitLOAD_VBPNTR(r300ContextPtr rmesa, int start);
-extern void r300EmitVertexShader(r300ContextPtr rmesa);
-extern void r300EmitPixelShader(r300ContextPtr rmesa);
-
#endif /* __R300_CMDBUF_H__ */
diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c
index fcf571d..cc9c11a 100644
--- a/src/mesa/drivers/dri/r300/r300_context.c
+++ b/src/mesa/drivers/dri/r300/r300_context.c
@@ -59,15 +59,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_span.h"
#include "r300_context.h"
#include "r300_cmdbuf.h"
+#include "r300_mipmap_tree.h"
#include "r300_state.h"
#include "r300_ioctl.h"
#include "r300_tex.h"
#include "r300_emit.h"
#include "r300_swtcl.h"
-#ifdef USER_BUFFERS
#include "r300_mem.h"
-#endif
#include "vblank.h"
#include "utils.h"
@@ -190,7 +189,7 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
struct dd_function_table functions;
r300ContextPtr r300;
GLcontext *ctx;
- int tcl_mode, i;
+ int tcl_mode;
assert(glVisual);
assert(driContextPriv);
@@ -222,10 +221,6 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
r300InitTextureFuncs(&functions);
r300InitShaderFuncs(&functions);
-#ifdef USER_BUFFERS
- r300_mem_init(r300);
-#endif
-
if (!radeonInitContext(&r300->radeon, &functions,
glVisual, driContextPriv,
sharedContextPrivate)) {
@@ -233,34 +228,9 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
return GL_FALSE;
}
+ r300->radeon.bufmgr = radeonBufmgrClassicInit(r300);
+
/* Init r300 context data */
- r300->dma.buf0_address =
- r300->radeon.radeonScreen->buffers->list[0].address;
-
- (void)memset(r300->texture_heaps, 0, sizeof(r300->texture_heaps));
- make_empty_list(&r300->swapped);
-
- r300->nr_heaps = 1 /* screen->numTexHeaps */ ;
- assert(r300->nr_heaps < RADEON_NR_TEX_HEAPS);
- for (i = 0; i < r300->nr_heaps; i++) {
- /* *INDENT-OFF* */
- r300->texture_heaps[i] = driCreateTextureHeap(i, r300,
- screen->
- texSize[i], 12,
- RADEON_NR_TEX_REGIONS,
- (drmTextureRegionPtr)
- r300->radeon.sarea->
- tex_list[i],
- &r300->radeon.sarea->
- tex_age[i],
- &r300->swapped,
- sizeof
- (r300TexObj),
- (destroy_texture_object_t
- *)
- r300DestroyTexObj);
- /* *INDENT-ON* */
- }
r300->texture_depth = driQueryOptioni(&r300->radeon.optionCache,
"texture_depth");
if (r300->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
@@ -299,13 +269,11 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
ctx->Const.MaxLineWidth = R300_LINESIZE_MAX;
ctx->Const.MaxLineWidthAA = R300_LINESIZE_MAX;
-#ifdef USER_BUFFERS
/* Needs further modifications */
#if 0
ctx->Const.MaxArrayLockSize =
( /*512 */ RADEON_BUFFER_SIZE * 16 * 1024) / (4 * 4);
#endif
-#endif
/* Initialize the software rasterizer and helper modules.
*/
@@ -407,72 +375,6 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
return GL_TRUE;
}
-static void r300FreeGartAllocations(r300ContextPtr r300)
-{
- int i, ret, tries = 0, done_age, in_use = 0;
- drm_radeon_mem_free_t memfree;
-
- memfree.region = RADEON_MEM_REGION_GART;
-
-#ifdef USER_BUFFERS
- for (i = r300->rmm->u_last; i > 0; i--) {
- if (r300->rmm->u_list[i].ptr == NULL) {
- continue;
- }
-
- /* check whether this buffer is still in use */
- if (r300->rmm->u_list[i].pending) {
- in_use++;
- }
- }
- /* Cannot flush/lock if no context exists. */
- if (in_use)
- r300FlushCmdBuf(r300, __FUNCTION__);
-
- done_age = radeonGetAge((radeonContextPtr) r300);
-
- for (i = r300->rmm->u_last; i > 0; i--) {
- if (r300->rmm->u_list[i].ptr == NULL) {
- continue;
- }
-
- /* check whether this buffer is still in use */
- if (!r300->rmm->u_list[i].pending) {
- continue;
- }
-
- assert(r300->rmm->u_list[i].h_pending == 0);
-
- tries = 0;
- while (r300->rmm->u_list[i].age > done_age && tries++ < 1000) {
- usleep(10);
- done_age = radeonGetAge((radeonContextPtr) r300);
- }
- if (tries >= 1000) {
- WARN_ONCE("Failed to idle region!");
- }
-
- memfree.region_offset = (char *)r300->rmm->u_list[i].ptr -
- (char *)r300->radeon.radeonScreen->gartTextures.map;
-
- ret = drmCommandWrite(r300->radeon.radeonScreen->driScreen->fd,
- DRM_RADEON_FREE, &memfree,
- sizeof(memfree));
- if (ret) {
- fprintf(stderr, "Failed to free at %p\nret = %s\n",
- r300->rmm->u_list[i].ptr, strerror(-ret));
- } else {
- if (i == r300->rmm->u_last)
- r300->rmm->u_last--;
-
- r300->rmm->u_list[i].pending = 0;
- r300->rmm->u_list[i].ptr = NULL;
- }
- }
- r300->rmm->u_head = i;
-#endif /* USER_BUFFERS */
-}
-
/* Destroy the device specific context.
*/
void r300DestroyContext(__DRIcontextPrivate * driContextPriv)
@@ -496,24 +398,17 @@ void r300DestroyContext(__DRIcontextPrivate * driContextPriv)
assert(r300); /* should never be null */
if (r300) {
- GLboolean release_texture_heaps;
-
- release_texture_heaps =
- (r300->radeon.glCtx->Shared->RefCount == 1);
_swsetup_DestroyContext(r300->radeon.glCtx);
_tnl_ProgramCacheDestroy(r300->radeon.glCtx);
_tnl_DestroyContext(r300->radeon.glCtx);
_vbo_DestroyContext(r300->radeon.glCtx);
_swrast_DestroyContext(r300->radeon.glCtx);
- if (r300->dma.current.buf) {
- r300ReleaseDmaRegion(r300, &r300->dma.current,
- __FUNCTION__);
-#ifndef USER_BUFFERS
- r300FlushCmdBuf(r300, __FUNCTION__);
-#endif
+ if (r300->dma.current) {
+ dri_bo_unreference(r300->dma.current);
+ r300->dma.current = 0;
}
- r300FreeGartAllocations(r300);
+ r300FlushCmdBuf(r300, __FUNCTION__);
r300DestroyCmdBuf(r300);
if (radeon->state.scissor.pClipRects) {
@@ -521,28 +416,13 @@ void r300DestroyContext(__DRIcontextPrivate * driContextPriv)
radeon->state.scissor.pClipRects = NULL;
}
- if (release_texture_heaps) {
- /* This share group is about to go away, free our private
- * texture object data.
- */
- int i;
-
- for (i = 0; i < r300->nr_heaps; i++) {
- driDestroyTextureHeap(r300->texture_heaps[i]);
- r300->texture_heaps[i] = NULL;
- }
-
- assert(is_empty_list(&r300->swapped));
- }
-
radeonCleanupContext(&r300->radeon);
-#ifdef USER_BUFFERS
/* the memory manager might be accessed when Mesa frees the shared
* state, so don't destroy it earlier
*/
- r300_mem_destroy(r300);
-#endif
+ dri_bufmgr_destroy(&r300->radeon.bufmgr->base);
+ r300->radeon.bufmgr = 0;
/* free the option cache */
driDestroyOptionCache(&r300->radeon.optionCache);
diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h
index d2017f8..5c99740 100644
--- a/src/mesa/drivers/dri/r300/r300_context.h
+++ b/src/mesa/drivers/dri/r300/r300_context.h
@@ -40,6 +40,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "tnl/t_vertex.h"
#include "drm.h"
#include "radeon_drm.h"
+#include "dri_bufmgr.h"
#include "dri_util.h"
#include "texmem.h"
@@ -47,11 +48,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "mtypes.h"
#include "colormac.h"
-#define USER_BUFFERS
-
struct r300_context;
typedef struct r300_context r300ContextRec;
typedef struct r300_context *r300ContextPtr;
+typedef struct radeon_bufmgr radeon_bufmgr;
#include "radeon_lock.h"
#include "mm.h"
@@ -122,44 +122,22 @@ static INLINE uint32_t r300PackFloat24(float f)
/************ DMA BUFFERS **************/
-/* Need refcounting on dma buffers:
- */
-struct r300_dma_buffer {
- int refcount; /**< the number of retained regions in buf */
- drmBufPtr buf;
- int id;
-};
-#undef GET_START
-#ifdef USER_BUFFERS
-#define GET_START(rvb) (r300GartOffsetFromVirtual(rmesa, (rvb)->address+(rvb)->start))
-#else
-#define GET_START(rvb) (rmesa->radeon.radeonScreen->gart_buffer_offset + \
- (rvb)->address - rmesa->dma.buf0_address + \
- (rvb)->start)
-#endif
-/* A retained region, eg vertices for indexed vertices.
- */
-struct r300_dma_region {
- struct r300_dma_buffer *buf;
- char *address; /* == buf->address */
- int start, end, ptr; /* offsets from start of buf */
-
- int aos_offset; /* address in GART memory */
- int aos_stride; /* distance between elements, in dwords */
- int aos_size; /* number of components (1-4) */
-};
-
struct r300_dma {
/* Active dma region. Allocations for vertices and retained
* regions come from here. Also used for emitting random vertices,
* these may be flushed by calling flush_current();
*/
- struct r300_dma_region current;
+ dri_bo *current; /** Buffer that DMA memory is allocated from */
+ int current_used; /** Number of bytes allocated and forgotten about */
+ int current_vertexptr; /** End of active vertex region */
+ /**
+ * If current_vertexptr != current_used then flush must be non-zero.
+ * flush must be called before non-active vertex allocations can be
+ * performed.
+ */
void (*flush) (r300ContextPtr);
- char *buf0_address; /* start of buf[0], for index calcs */
-
/* Number of "in-flight" DMA buffers, i.e. the number of buffers
* for which a DISCARD command is currently queued in the command buffer.
*/
@@ -173,15 +151,12 @@ typedef struct r300_tex_obj r300TexObj, *r300TexObjPtr;
/* Texture object in locally shared texture space.
*/
struct r300_tex_obj {
- driTextureObject base;
-
- GLuint bufAddr; /* Offset to start of locally
- shared texture block */
-
- drm_radeon_tex_image_t image[6][RADEON_MAX_TEXTURE_LEVELS];
- /* Six, for the cube faces */
+ struct gl_texture_object base;
+ struct _r300_mipmap_tree *mt;
+ GLuint dirty_images[6];
GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
+ GLuint override_offset;
GLuint pitch; /* this isn't sent to hardware just used in calculations */
/* hardware register values */
@@ -191,30 +166,16 @@ struct r300_tex_obj {
GLuint pitch_reg;
GLuint size; /* npot only */
GLuint format;
- GLuint offset; /* Image location in the card's address space.
- All cube faces follow. */
- GLuint unknown4;
- GLuint unknown5;
- /* end hardware registers */
-
- /* registers computed by r200 code - keep them here to
- compare against what is actually written.
-
- to be removed later.. */
GLuint pp_border_color;
- GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */
- GLuint format_x;
-
- GLboolean border_fallback;
+ /* end hardware registers */
GLuint tile_bits; /* hw texture tile bits used on this texture */
};
-struct r300_texture_env_state {
- r300TexObjPtr texobj;
- GLenum format;
- GLenum envMode;
-};
+static INLINE r300TexObj* r300_tex_obj(struct gl_texture_object *texObj)
+{
+ return (r300TexObj*)texObj;
+}
/* The blit width for texture uploads
*/
@@ -222,7 +183,6 @@ struct r300_texture_env_state {
#define R300_MAX_TEXTURE_UNITS 8
struct r300_texture_state {
- struct r300_texture_env_state unit[R300_MAX_TEXTURE_UNITS];
int tc_count; /* number of incoming texture coordinates from VAP */
};
@@ -242,6 +202,7 @@ struct r300_state_atom {
GLboolean dirty;
int (*check) (r300ContextPtr, struct r300_state_atom * atom);
+ void (*emit) (r300ContextPtr);
};
#define R300_VPT_CMD_0 0
@@ -549,6 +510,8 @@ struct r300_hw_state {
struct r300_state_atom border_color;
} tex;
struct r300_state_atom txe; /* tex enable (4104) */
+
+ r300TexObj *textures[R300_MAX_TEXTURE_UNITS];
};
/**
@@ -559,10 +522,14 @@ struct r300_hw_state {
* otherwise.
*/
struct r300_cmdbuf {
- int size; /* DWORDs allocated for buffer */
- uint32_t *cmd_buf;
- int count_used; /* DWORDs filled so far */
- int count_reemit; /* size of re-emission batch */
+ dri_bo *buf;
+ int reemit; /** # of dwords in reemit sequence (is always <= committed) */
+ int size; /** # of dwords total */
+
+ int committed; /** # of dwords that we have committed to */
+ int written; /** # of dwords written (is always >= committed) */
+ int reserved; /** # of dwords reserved up to previous BEGIN_BATCH */
+ unsigned int flushing:1; /** whether we're currently in FlushCmdBufLocked */
};
/**
@@ -811,18 +778,25 @@ struct r500_fragment_program {
#define REG_COLOR0 1
#define REG_TEX0 2
+struct r300_aos {
+ dri_bo *bo; /** Buffer object where vertex data is stored */
+ int offset; /** Offset into buffer object, in bytes */
+ int components; /** Number of components per vertex */
+ int stride; /** Stride in dwords (may be 0 for repeating) */
+ int count; /** Number of vertices */
+};
+
struct r300_state {
struct r300_depthbuffer_state depth;
struct r300_texture_state texture;
int sw_tcl_inputs[VERT_ATTRIB_MAX];
struct r300_vertex_shader_state vertex_shader;
- struct r300_dma_region aos[R300_MAX_AOS_ARRAYS];
+ struct r300_aos aos[R300_MAX_AOS_ARRAYS];
int aos_count;
- GLuint *Elts;
- struct r300_dma_region elt_dma;
+ dri_bo *elt_dma_bo; /** Buffer object that contains element indices */
+ int elt_dma_offset; /** Offset into this buffer object, in bytes */
- struct r300_dma_region swtcl_dma;
DECLARE_RENDERINPUTS(render_inputs_bitset); /* actual render inputs that R300 was configured for.
They are the same as tnl->render_inputs for fixed pipeline */
@@ -880,13 +854,6 @@ struct r300_swtcl_info {
* Offset of the 3UB specular color data within a hardware (swtcl) vertex.
*/
GLuint specoffset;
-
- /**
- * Should Mesa project vertex data or will the hardware do it?
- */
- GLboolean needproj;
-
- struct r300_dma_region indexed_verts;
};
@@ -905,25 +872,11 @@ struct r300_context {
/* Vertex buffers
*/
struct r300_dma dma;
- GLboolean save_on_next_unlock;
GLuint NewGLState;
- /* Texture object bookkeeping
- */
- unsigned nr_heaps;
- driTexHeap *texture_heaps[RADEON_NR_TEX_HEAPS];
- driTextureObject swapped;
int texture_depth;
float initialMaxAnisotropy;
- /* Clientdata textures;
- */
- GLuint prefer_gart_client_texturing;
-
-#ifdef USER_BUFFERS
- struct r300_memory_manager *rmm;
-#endif
-
GLvector4f dummy_attrib[_TNL_ATTRIB_MAX];
GLvector4f *temp_attrib[_TNL_ATTRIB_MAX];
diff --git a/src/mesa/drivers/dri/r300/r300_emit.c b/src/mesa/drivers/dri/r300/r300_emit.c
index 2ea17ad..5e2afd5 100644
--- a/src/mesa/drivers/dri/r300/r300_emit.c
+++ b/src/mesa/drivers/dri/r300/r300_emit.c
@@ -51,9 +51,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r300_emit.h"
#include "r300_ioctl.h"
-#ifdef USER_BUFFERS
#include "r300_mem.h"
-#endif
#if SWIZZLE_X != R300_INPUT_ROUTE_SELECT_X || \
SWIZZLE_Y != R300_INPUT_ROUTE_SELECT_Y || \
@@ -86,11 +84,9 @@ do { \
} while (0)
#endif
-static void r300EmitVec4(GLcontext * ctx, struct r300_dma_region *rvb,
- GLvoid * data, int stride, int count)
+static void r300EmitVec4(uint32_t *out, GLvoid * data, int stride, int count)
{
int i;
- int *out = (int *)(rvb->address + rvb->start);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d out %p data %p\n",
@@ -106,11 +102,9 @@ static void r300EmitVec4(GLcontext * ctx, struct r300_dma_region *rvb,
}
}
-static void r300EmitVec8(GLcontext * ctx, struct r300_dma_region *rvb,
- GLvoid * data, int stride, int count)
+static void r300EmitVec8(uint32_t *out, GLvoid * data, int stride, int count)
{
int i;
- int *out = (int *)(rvb->address + rvb->start);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d out %p data %p\n",
@@ -127,11 +121,9 @@ static void r300EmitVec8(GLcontext * ctx, struct r300_dma_region *rvb,
}
}
-static void r300EmitVec12(GLcontext * ctx, struct r300_dma_region *rvb,
- GLvoid * data, int stride, int count)
+static void r300EmitVec12(uint32_t *out, GLvoid * data, int stride, int count)
{
int i;
- int *out = (int *)(rvb->address + rvb->start);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d out %p data %p\n",
@@ -149,11 +141,9 @@ static void r300EmitVec12(GLcontext * ctx, struct r300_dma_region *rvb,
}
}
-static void r300EmitVec16(GLcontext * ctx, struct r300_dma_region *rvb,
- GLvoid * data, int stride, int count)
+static void r300EmitVec16(uint32_t *out, GLvoid * data, int stride, int count)
{
int i;
- int *out = (int *)(rvb->address + rvb->start);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d out %p data %p\n",
@@ -172,35 +162,31 @@ static void r300EmitVec16(GLcontext * ctx, struct r300_dma_region *rvb,
}
}
-static void r300EmitVec(GLcontext * ctx, struct r300_dma_region *rvb,
+
+static void r300EmitVec(GLcontext * ctx, struct r300_aos *aos,
GLvoid * data, int size, int stride, int count)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ uint32_t *out;
if (stride == 0) {
- r300AllocDmaRegion(rmesa, rvb, size * 4, 4);
+ r300AllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * 4, 32);
count = 1;
- rvb->aos_offset = GET_START(rvb);
- rvb->aos_stride = 0;
+ aos->stride = 0;
} else {
- r300AllocDmaRegion(rmesa, rvb, size * count * 4, 4);
- rvb->aos_offset = GET_START(rvb);
- rvb->aos_stride = size;
+ r300AllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * count * 4, 32);
+ aos->stride = size;
}
+ aos->components = size;
+ aos->count = count;
+
+ out = (uint32_t*)((char*)aos->bo->virtual + aos->offset);
switch (size) {
- case 1:
- r300EmitVec4(ctx, rvb, data, stride, count);
- break;
- case 2:
- r300EmitVec8(ctx, rvb, data, stride, count);
- break;
- case 3:
- r300EmitVec12(ctx, rvb, data, stride, count);
- break;
- case 4:
- r300EmitVec16(ctx, rvb, data, stride, count);
- break;
+ case 1: r300EmitVec4(out, data, stride, count); break;
+ case 2: r300EmitVec8(out, data, stride, count); break;
+ case 3: r300EmitVec12(out, data, stride, count); break;
+ case 4: r300EmitVec16(out, data, stride, count); break;
default:
assert(0);
break;
@@ -433,7 +419,7 @@ int r300EmitArrays(GLcontext * ctx)
}
for (i = 0; i < nr; i++) {
- int ci, fix, found = 0;
+ int ci;
swizzle[i][0] = SWIZZLE_ZERO;
swizzle[i][1] = SWIZZLE_ZERO;
@@ -444,48 +430,10 @@ int r300EmitArrays(GLcontext * ctx)
swizzle[i][ci] = ci;
}
- if (r300IsGartMemory(rmesa, vb->AttribPtr[tab[i]]->data, 4)) {
- if (vb->AttribPtr[tab[i]]->stride % 4) {
- return R300_FALLBACK_TCL;
- }
- rmesa->state.aos[i].address = (void *)(vb->AttribPtr[tab[i]]->data);
- rmesa->state.aos[i].start = 0;
- rmesa->state.aos[i].aos_offset = r300GartOffsetFromVirtual(rmesa, vb->AttribPtr[tab[i]]->data);
- rmesa->state.aos[i].aos_stride = vb->AttribPtr[tab[i]]->stride / 4;
- rmesa->state.aos[i].aos_size = vb->AttribPtr[tab[i]]->size;
- } else {
- r300EmitVec(ctx, &rmesa->state.aos[i],
- vb->AttribPtr[tab[i]]->data,
- vb->AttribPtr[tab[i]]->size,
- vb->AttribPtr[tab[i]]->stride, count);
- }
-
- rmesa->state.aos[i].aos_size = vb->AttribPtr[tab[i]]->size;
-
- for (fix = 0; fix <= 4 - vb->AttribPtr[tab[i]]->size; fix++) {
- if ((rmesa->state.aos[i].aos_offset - _mesa_sizeof_type(GL_FLOAT) * fix) % 4) {
- continue;
- }
- found = 1;
- break;
- }
-
- if (found) {
- if (fix > 0) {
- WARN_ONCE("Feeling lucky?\n");
- }
- rmesa->state.aos[i].aos_offset -= _mesa_sizeof_type(GL_FLOAT) * fix;
- for (ci = 0; ci < vb->AttribPtr[tab[i]]->size; ci++) {
- swizzle[i][ci] += fix;
- }
- } else {
- WARN_ONCE
- ("Cannot handle offset %x with stride %d, comp %d\n",
- rmesa->state.aos[i].aos_offset,
- rmesa->state.aos[i].aos_stride,
- vb->AttribPtr[tab[i]]->size);
- return R300_FALLBACK_TCL;
- }
+ r300EmitVec(ctx, &rmesa->state.aos[i],
+ vb->AttribPtr[tab[i]]->data,
+ vb->AttribPtr[tab[i]]->size,
+ vb->AttribPtr[tab[i]]->stride, count);
}
/* Setup INPUT_ROUTE. */
@@ -515,45 +463,76 @@ int r300EmitArrays(GLcontext * ctx)
return R300_FALLBACK_NONE;
}
-#ifdef USER_BUFFERS
-void r300UseArrays(GLcontext * ctx)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- int i;
-
- if (rmesa->state.elt_dma.buf)
- r300_mem_use(rmesa, rmesa->state.elt_dma.buf->id);
-
- for (i = 0; i < rmesa->state.aos_count; i++) {
- if (rmesa->state.aos[i].buf)
- r300_mem_use(rmesa, rmesa->state.aos[i].buf->id);
- }
-}
-#endif
-
void r300ReleaseArrays(GLcontext * ctx)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
int i;
- r300ReleaseDmaRegion(rmesa, &rmesa->state.elt_dma, __FUNCTION__);
+ if (rmesa->state.elt_dma_bo) {
+ dri_bo_unreference(rmesa->state.elt_dma_bo);
+ rmesa->state.elt_dma_bo = 0;
+ }
for (i = 0; i < rmesa->state.aos_count; i++) {
- r300ReleaseDmaRegion(rmesa, &rmesa->state.aos[i], __FUNCTION__);
+ if (rmesa->state.aos[i].bo) {
+ dri_bo_unreference(rmesa->state.aos[i].bo);
+ rmesa->state.aos[i].bo = 0;
+ }
}
}
void r300EmitCacheFlush(r300ContextPtr rmesa)
{
- int cmd_reserved = 0;
- int cmd_written = 0;
-
- drm_radeon_cmd_header_t *cmd = NULL;
-
- reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
- e32(R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS |
- R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
+ BATCH_LOCALS(rmesa);
+
+ BEGIN_BATCH(4);
+ OUT_BATCH_REGVAL(R300_RB3D_DSTCACHE_CTLSTAT,
+ R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS |
+ R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
+ OUT_BATCH_REGVAL(R300_ZB_ZCACHE_CTLSTAT,
+ R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE |
+ R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
+ END_BATCH();
+ COMMIT_BATCH();
+}
- reg_start(R300_ZB_ZCACHE_CTLSTAT, 0);
- e32(R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE |
- R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
+void r300EmitBlit(r300ContextPtr rmesa,
+ GLuint color_fmt,
+ GLuint src_pitch,
+ dri_bo *src_bo, int src_offset,
+ GLuint dst_pitch,
+ GLuint dst_offset,
+ GLint srcx, GLint srcy,
+ GLint dstx, GLint dsty, GLuint w, GLuint h)
+{
+ BATCH_LOCALS(rmesa);
+
+ 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));
+
+ BEGIN_BATCH(8);
+ OUT_BATCH_PACKET3(R300_CP_CMD_BITBLT_MULTI, 5);
+ OUT_BATCH(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);
+ OUT_BATCH_RELOC((src_pitch / 64) << 22, src_bo, src_offset, DRM_RELOC_BLITTER);
+ OUT_BATCH(((dst_pitch / 64) << 22) | (dst_offset >> 10));
+ OUT_BATCH((srcx << 16) | srcy);
+ OUT_BATCH((dstx << 16) | dsty);
+ OUT_BATCH((w << 16) | h);
+ END_BATCH();
}
diff --git a/src/mesa/drivers/dri/r300/r300_emit.h b/src/mesa/drivers/dri/r300/r300_emit.h
index 5950539..179983d 100644
--- a/src/mesa/drivers/dri/r300/r300_emit.h
+++ b/src/mesa/drivers/dri/r300/r300_emit.h
@@ -127,130 +127,62 @@ static INLINE uint32_t cmdpacify(void)
return cmd.u;
}
-/**
- * Prepare to write a register value to register at address reg.
- * If num_extra > 0 then the following extra values are written
- * to registers with address +4, +8 and so on..
- */
-#define reg_start(reg, num_extra) \
- do { \
- int _n; \
- _n=(num_extra); \
- cmd = (drm_radeon_cmd_header_t*) \
- r300AllocCmdBuf(rmesa, \
- (_n+2), \
- __FUNCTION__); \
- cmd_reserved=_n+2; \
- cmd_written=1; \
- cmd[0].i=cmdpacket0((reg), _n+1); \
- } while (0);
+
+/** Single register write to command buffer; requires 2 dwords. */
+#define OUT_BATCH_REGVAL(reg, val) \
+ OUT_BATCH(cmdpacket0((reg), 1)); \
+ OUT_BATCH((val))
+
+/** Continuous register range write to command buffer; requires 1 dword,
+ * expects count dwords afterwards for register contents. */
+#define OUT_BATCH_REGSEQ(reg, count) \
+ OUT_BATCH(cmdpacket0((reg), (count)));
+
+/** Write a 32 bit float to the ring; requires 1 dword. */
+#define OUT_BATCH_FLOAT32(f) \
+ OUT_BATCH(r300PackFloat32((f)));
/**
- * Emit GLuint freestyle
+ * Write the header of a packet3 to the command buffer.
+ * Outputs 2 dwords and expects (num_extra+1) additional dwords afterwards.
*/
-#define e32(dword) \
- do { \
- if(cmd_written<cmd_reserved) { \
- cmd[cmd_written].i=(dword); \
- cmd_written++; \
- } else { \
- fprintf(stderr, \
- "e32 but no previous packet " \
- "declaration.\n" \
- "Aborting! in %s::%s at line %d, " \
- "cmd_written=%d cmd_reserved=%d\n", \
- __FILE__, __FUNCTION__, __LINE__, \
- cmd_written, cmd_reserved); \
- _mesa_exit(-1); \
- } \
+#define OUT_BATCH_PACKET3(packet, num_extra) do {\
+ OUT_BATCH(cmdpacket3(R300_CMD_PACKET3_RAW)); \
+ OUT_BATCH(CP_PACKET3((packet), (num_extra))); \
} while(0)
-#define efloat(f) e32(r300PackFloat32(f))
-
-#define vsf_start_fragment(dest, length) \
- do { \
- int _n; \
- _n = (length); \
- cmd = (drm_radeon_cmd_header_t*) \
- r300AllocCmdBuf(rmesa, \
- (_n+1), \
- __FUNCTION__); \
- cmd_reserved = _n+2; \
- cmd_written =1; \
- cmd[0].i = cmdvpu((dest), _n/4); \
- } while (0);
-
-#define r500fp_start_fragment(dest, length) \
- do { \
- int _n; \
- _n = (length); \
- cmd = (drm_radeon_cmd_header_t*) \
- r300AllocCmdBuf(rmesa, \
- (_n+1), \
- __FUNCTION__); \
- cmd_reserved = _n+1; \
- cmd_written =1; \
- cmd[0].i = cmdr500fp((dest), _n/6, 0, 0); \
- } while (0);
-
-#define start_packet3(packet, count) \
- { \
- int _n; \
- GLuint _p; \
- _n = (count); \
- _p = (packet); \
- cmd = (drm_radeon_cmd_header_t*) \
- r300AllocCmdBuf(rmesa, \
- (_n+3), \
- __FUNCTION__); \
- cmd_reserved = _n+3; \
- cmd_written = 2; \
- if(_n > 0x3fff) { \
- fprintf(stderr,"Too big packet3 %08x: cannot " \
- "store %d dwords\n", \
- _p, _n); \
- _mesa_exit(-1); \
- } \
- cmd[0].i = cmdpacket3(R300_CMD_PACKET3_RAW); \
- cmd[1].i = _p | ((_n & 0x3fff)<<16); \
- }
-
/**
* Must be sent to switch to 2d commands
*/
void static INLINE end_3d(r300ContextPtr rmesa)
{
- drm_radeon_cmd_header_t *cmd = NULL;
+ BATCH_LOCALS(rmesa);
- cmd =
- (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, 1, __FUNCTION__);
- cmd[0].header.cmd_type = R300_CMD_END3D;
+ BEGIN_BATCH(1);
+ OUT_BATCH(cmdpacify());
+ END_BATCH();
}
void static INLINE cp_delay(r300ContextPtr rmesa, unsigned short count)
{
- drm_radeon_cmd_header_t *cmd = NULL;
+ BATCH_LOCALS(rmesa);
- cmd =
- (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, 1, __FUNCTION__);
- cmd[0].i = cmdcpdelay(count);
+ BEGIN_BATCH(1);
+ OUT_BATCH(cmdcpdelay(count));
+ END_BATCH();
}
void static INLINE cp_wait(r300ContextPtr rmesa, unsigned char flags)
{
- drm_radeon_cmd_header_t *cmd = NULL;
+ BATCH_LOCALS(rmesa);
- cmd =
- (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, 1, __FUNCTION__);
- cmd[0].i = cmdwait(flags);
+ BEGIN_BATCH(1);
+ OUT_BATCH(cmdwait(flags));
+ END_BATCH();
}
extern int r300EmitArrays(GLcontext * ctx);
-#ifdef USER_BUFFERS
-void r300UseArrays(GLcontext * ctx);
-#endif
-
extern void r300ReleaseArrays(GLcontext * ctx);
extern int r300PrimitiveType(r300ContextPtr rmesa, int prim);
extern int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim);
@@ -265,4 +197,13 @@ extern GLuint r300VAPInputCntl1(GLcontext * ctx, GLuint InputsRead);
extern GLuint r300VAPOutputCntl0(GLcontext * ctx, GLuint OutputsWritten);
extern GLuint r300VAPOutputCntl1(GLcontext * ctx, GLuint OutputsWritten);
+extern void r300EmitBlit(r300ContextPtr rmesa,
+ GLuint color_fmt,
+ GLuint src_pitch,
+ dri_bo *src_bo, int src_offset,
+ GLuint dst_pitch,
+ GLuint dst_offset,
+ GLint srcx, GLint srcy,
+ GLint dstx, GLint dsty, GLuint w, GLuint h);
+
#endif
diff --git a/src/mesa/drivers/dri/r300/r300_ioctl.c b/src/mesa/drivers/dri/r300/r300_ioctl.c
index bd7f060..046f9a2 100644
--- a/src/mesa/drivers/dri/r300/r300_ioctl.c
+++ b/src/mesa/drivers/dri/r300/r300_ioctl.c
@@ -55,6 +55,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_reg.h"
#include "r300_emit.h"
#include "r300_fragprog.h"
+#include "r300_mem.h"
#include "vblank.h"
@@ -62,64 +63,51 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define CLEARBUFFER_DEPTH 0x2
#define CLEARBUFFER_STENCIL 0x4
-static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
+static void r300ClearBuffer(r300ContextPtr r300, int flags,
+ struct radeon_renderbuffer *rrb)
{
+ BATCH_LOCALS(r300);
GLcontext *ctx = r300->radeon.glCtx;
__DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
- GLuint cboffset, cbpitch;
- drm_r300_cmd_header_t *cmd2;
- int cmd_reserved = 0;
- int cmd_written = 0;
- drm_radeon_cmd_header_t *cmd = NULL;
+ GLuint cbpitch = 0;
r300ContextPtr rmesa = r300;
if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s: %s buffer (%i,%i %ix%i)\n",
- __FUNCTION__, buffer ? "back" : "front",
- dPriv->x, dPriv->y, dPriv->w, dPriv->h);
-
- if (buffer) {
- cboffset = r300->radeon.radeonScreen->backOffset;
- cbpitch = r300->radeon.radeonScreen->backPitch;
- } else {
- cboffset = r300->radeon.radeonScreen->frontOffset;
- cbpitch = r300->radeon.radeonScreen->frontPitch;
+ fprintf(stderr, "%s: buffer %p (%i,%i %ix%i)\n",
+ __FUNCTION__, rrb, dPriv->x, dPriv->y,
+ dPriv->w, dPriv->h);
+
+ if (rrb) {
+ cbpitch = rrb->pitch;
+ if (rrb->cpp == 4)
+ cbpitch |= R300_COLOR_FORMAT_ARGB8888;
+ else
+ cbpitch |= R300_COLOR_FORMAT_RGB565;
+
+ if (r300->radeon.sarea->tiling_enabled)
+ cbpitch |= R300_COLOR_TILE_ENABLE;
}
- cboffset += r300->radeon.radeonScreen->fbLocation;
-
+ /* TODO in bufmgr */
cp_wait(r300, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
end_3d(rmesa);
- R300_STATECHANGE(r300, cb);
- reg_start(R300_RB3D_COLOROFFSET0, 0);
- e32(cboffset);
-
- if (r300->radeon.radeonScreen->cpp == 4)
- cbpitch |= R300_COLOR_FORMAT_ARGB8888;
- else
- cbpitch |= R300_COLOR_FORMAT_RGB565;
-
- if (r300->radeon.sarea->tiling_enabled)
- cbpitch |= R300_COLOR_TILE_ENABLE;
-
- reg_start(R300_RB3D_COLORPITCH0, 0);
- e32(cbpitch);
-
- R300_STATECHANGE(r300, cmk);
- reg_start(RB3D_COLOR_CHANNEL_MASK, 0);
+ BEGIN_BATCH(19);
+ OUT_BATCH_REGSEQ(R300_RB3D_COLOROFFSET0, 1);
+ OUT_BATCH_RELOC(0, rrb->bo, 0, DRM_RELOC_TXOFFSET);
+ OUT_BATCH_REGVAL(R300_RB3D_COLORPITCH0, cbpitch);
+ OUT_BATCH_REGSEQ(RB3D_COLOR_CHANNEL_MASK, 1);
if (flags & CLEARBUFFER_COLOR) {
- e32((ctx->Color.ColorMask[BCOMP] ? RB3D_COLOR_CHANNEL_MASK_BLUE_MASK0 : 0) |
- (ctx->Color.ColorMask[GCOMP] ? RB3D_COLOR_CHANNEL_MASK_GREEN_MASK0 : 0) |
- (ctx->Color.ColorMask[RCOMP] ? RB3D_COLOR_CHANNEL_MASK_RED_MASK0 : 0) |
- (ctx->Color.ColorMask[ACOMP] ? RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK0 : 0));
+ OUT_BATCH((ctx->Color.ColorMask[BCOMP] ? RB3D_COLOR_CHANNEL_MASK_BLUE_MASK0 : 0) |
+ (ctx->Color.ColorMask[GCOMP] ? RB3D_COLOR_CHANNEL_MASK_GREEN_MASK0 : 0) |
+ (ctx->Color.ColorMask[RCOMP] ? RB3D_COLOR_CHANNEL_MASK_RED_MASK0 : 0) |
+ (ctx->Color.ColorMask[ACOMP] ? RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK0 : 0));
} else {
- e32(0x0);
+ OUT_BATCH(0);
}
- R300_STATECHANGE(r300, zs);
- reg_start(R300_ZB_CNTL, 2);
+ OUT_BATCH_REGSEQ(R300_ZB_CNTL, 3);
{
uint32_t t1, t2;
@@ -146,37 +134,37 @@ static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
R300_S_FRONT_ZFAIL_OP_SHIFT);
}
- e32(t1);
- e32(t2);
- e32(((ctx->Stencil.WriteMask[0] & R300_STENCILREF_MASK) << R300_STENCILWRITEMASK_SHIFT) |
- (ctx->Stencil.Clear & R300_STENCILREF_MASK));
+ OUT_BATCH(t1);
+ OUT_BATCH(t2);
+ OUT_BATCH(((ctx->Stencil.WriteMask[0] & R300_STENCILREF_MASK) << R300_STENCILWRITEMASK_SHIFT) |
+ (ctx->Stencil.Clear & R300_STENCILREF_MASK));
}
- cmd2 = (drm_r300_cmd_header_t *) r300AllocCmdBuf(r300, 9, __FUNCTION__);
- cmd2[0].packet3.cmd_type = R300_CMD_PACKET3;
- cmd2[0].packet3.packet = R300_CMD_PACKET3_CLEAR;
- cmd2[1].u = r300PackFloat32(dPriv->w / 2.0);
- cmd2[2].u = r300PackFloat32(dPriv->h / 2.0);
- cmd2[3].u = r300PackFloat32(ctx->Depth.Clear);
- cmd2[4].u = r300PackFloat32(1.0);
- cmd2[5].u = r300PackFloat32(ctx->Color.ClearColor[0]);
- cmd2[6].u = r300PackFloat32(ctx->Color.ClearColor[1]);
- cmd2[7].u = r300PackFloat32(ctx->Color.ClearColor[2]);
- cmd2[8].u = r300PackFloat32(ctx->Color.ClearColor[3]);
+ OUT_BATCH(cmdpacket3(R300_CMD_PACKET3_CLEAR));
+ OUT_BATCH_FLOAT32(dPriv->w / 2.0);
+ OUT_BATCH_FLOAT32(dPriv->h / 2.0);
+ OUT_BATCH_FLOAT32(ctx->Depth.Clear);
+ OUT_BATCH_FLOAT32(1.0);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[0]);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[1]);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[2]);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[3]);
+ END_BATCH();
r300EmitCacheFlush(rmesa);
cp_wait(rmesa, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
+
+ R300_STATECHANGE(r300, cb);
+ R300_STATECHANGE(r300, cmk);
+ R300_STATECHANGE(r300, zs);
}
static void r300EmitClearState(GLcontext * ctx)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
- r300ContextPtr rmesa = r300;
+ BATCH_LOCALS(r300);
__DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
int i;
- int cmd_reserved = 0;
- int cmd_written = 0;
- drm_radeon_cmd_header_t *cmd = NULL;
int has_tcl = 1;
int is_r500 = 0;
GLuint vap_cntl;
@@ -184,35 +172,37 @@ static void r300EmitClearState(GLcontext * ctx)
if (!(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
has_tcl = 0;
- if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
- is_r500 = 1;
-
+ if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
+ is_r500 = 1;
- /* FIXME: the values written to R300_VAP_INPUT_ROUTE_0_0 and
- * R300_VAP_INPUT_ROUTE_0_1 are in fact known, however, the values are
- * quite complex; see the functions in r300_emit.c.
+ /* State atom dirty tracking is a little subtle here.
+ *
+ * On the one hand, we need to make sure base state is emitted
+ * here if we start with an empty batch buffer, otherwise clear
+ * works incorrectly with multiple processes. Therefore, the first
+ * BEGIN_BATCH cannot be a BEGIN_BATCH_NO_AUTOSTATE.
*
- * I believe it would be a good idea to extend the functions in
- * r300_emit.c so that they can be used to setup the default values for
- * these registers, as well as the actual values used for rendering.
+ * On the other hand, implicit state emission clears the state atom
+ * dirty bits, so we have to call R300_STATECHANGE later than the
+ * first BEGIN_BATCH.
+ *
+ * The final trickiness is that, because we change state, we need
+ * to ensure that any stored swtcl primitives are flushed properly
+ * before we start changing state. See the R300_NEWPRIM in r300Clear
+ * for this.
*/
- R300_STATECHANGE(r300, vir[0]);
- reg_start(R300_VAP_PROG_STREAM_CNTL_0, 0);
+ BEGIN_BATCH(31);
+ OUT_BATCH_REGSEQ(R300_VAP_PROG_STREAM_CNTL_0, 1);
if (!has_tcl)
- e32(((((0 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_0_SHIFT) |
+ OUT_BATCH(((((0 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_0_SHIFT) |
((R300_LAST_VEC | (2 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT)));
else
- e32(((((0 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_0_SHIFT) |
+ OUT_BATCH(((((0 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_0_SHIFT) |
((R300_LAST_VEC | (1 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT)));
- /* disable fog */
- R300_STATECHANGE(r300, fogs);
- reg_start(R300_FG_FOG_BLEND, 0);
- e32(0x0);
-
- R300_STATECHANGE(r300, vir[1]);
- reg_start(R300_VAP_PROG_STREAM_CNTL_EXT_0, 0);
- e32(((((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) |
+ OUT_BATCH_REGVAL(R300_FG_FOG_BLEND, 0);
+ OUT_BATCH_REGVAL(R300_VAP_PROG_STREAM_CNTL_EXT_0,
+ ((((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) |
(R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) |
(R300_SWIZZLE_SELECT_Z << R300_SWIZZLE_SELECT_Z_SHIFT) |
(R300_SWIZZLE_SELECT_W << R300_SWIZZLE_SELECT_W_SHIFT) |
@@ -226,238 +216,246 @@ static void r300EmitClearState(GLcontext * ctx)
<< R300_SWIZZLE1_SHIFT)));
/* R300_VAP_INPUT_CNTL_0, R300_VAP_INPUT_CNTL_1 */
- R300_STATECHANGE(r300, vic);
- reg_start(R300_VAP_VTX_STATE_CNTL, 1);
- e32((R300_SEL_USER_COLOR_0 << R300_COLOR_0_ASSEMBLY_SHIFT));
- e32(R300_INPUT_CNTL_POS | R300_INPUT_CNTL_COLOR | R300_INPUT_CNTL_TC0);
+ OUT_BATCH_REGSEQ(R300_VAP_VTX_STATE_CNTL, 2);
+ OUT_BATCH((R300_SEL_USER_COLOR_0 << R300_COLOR_0_ASSEMBLY_SHIFT));
+ OUT_BATCH(R300_INPUT_CNTL_POS | R300_INPUT_CNTL_COLOR | R300_INPUT_CNTL_TC0);
- R300_STATECHANGE(r300, vte);
/* comes from fglrx startup of clear */
- reg_start(R300_SE_VTE_CNTL, 1);
- e32(R300_VTX_W0_FMT | R300_VPORT_X_SCALE_ENA |
- R300_VPORT_X_OFFSET_ENA | R300_VPORT_Y_SCALE_ENA |
- R300_VPORT_Y_OFFSET_ENA | R300_VPORT_Z_SCALE_ENA |
- R300_VPORT_Z_OFFSET_ENA);
- e32(0x8);
+ OUT_BATCH_REGSEQ(R300_SE_VTE_CNTL, 2);
+ OUT_BATCH(R300_VTX_W0_FMT | R300_VPORT_X_SCALE_ENA |
+ R300_VPORT_X_OFFSET_ENA | R300_VPORT_Y_SCALE_ENA |
+ R300_VPORT_Y_OFFSET_ENA | R300_VPORT_Z_SCALE_ENA |
+ R300_VPORT_Z_OFFSET_ENA);
+ OUT_BATCH(0x8);
- reg_start(R300_VAP_PSC_SGN_NORM_CNTL, 0);
- e32(0xaaaaaaaa);
+ OUT_BATCH_REGVAL(R300_VAP_PSC_SGN_NORM_CNTL, 0xaaaaaaaa);
- R300_STATECHANGE(r300, vof);
- reg_start(R300_VAP_OUTPUT_VTX_FMT_0, 1);
- e32(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT |
- R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT);
- e32(0x0); /* no textures */
+ OUT_BATCH_REGSEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2);
+ OUT_BATCH(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT |
+ R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT);
+ OUT_BATCH(0); /* no textures */
- R300_STATECHANGE(r300, txe);
- reg_start(R300_TX_ENABLE, 0);
- e32(0x0);
+ OUT_BATCH_REGVAL(R300_TX_ENABLE, 0);
- R300_STATECHANGE(r300, vpt);
- reg_start(R300_SE_VPORT_XSCALE, 5);
- efloat(1.0);
- efloat(dPriv->x);
- efloat(1.0);
- efloat(dPriv->y);
- efloat(1.0);
- efloat(0.0);
+ OUT_BATCH_REGSEQ(R300_SE_VPORT_XSCALE, 6);
+ OUT_BATCH_FLOAT32(1.0);
+ OUT_BATCH_FLOAT32(dPriv->x);
+ OUT_BATCH_FLOAT32(1.0);
+ OUT_BATCH_FLOAT32(dPriv->y);
+ OUT_BATCH_FLOAT32(1.0);
+ OUT_BATCH_FLOAT32(0.0);
- R300_STATECHANGE(r300, at);
- reg_start(R300_FG_ALPHA_FUNC, 0);
- e32(0x0);
+ OUT_BATCH_REGVAL(R300_FG_ALPHA_FUNC, 0);
+
+ OUT_BATCH_REGSEQ(R300_RB3D_CBLEND, 2);
+ OUT_BATCH(0x0);
+ OUT_BATCH(0x0);
+ END_BATCH();
+ R300_STATECHANGE(r300, vir[0]);
+ R300_STATECHANGE(r300, fogs);
+ R300_STATECHANGE(r300, vir[1]);
+ R300_STATECHANGE(r300, vic);
+ R300_STATECHANGE(r300, vte);
+ R300_STATECHANGE(r300, vof);
+ R300_STATECHANGE(r300, txe);
+ R300_STATECHANGE(r300, vpt);
+ R300_STATECHANGE(r300, at);
R300_STATECHANGE(r300, bld);
- reg_start(R300_RB3D_CBLEND, 1);
- e32(0x0);
- e32(0x0);
+ R300_STATECHANGE(r300, ps);
if (has_tcl) {
- R300_STATECHANGE(r300, vap_clip_cntl);
- reg_start(R300_VAP_CLIP_CNTL, 0);
- e32(R300_PS_UCP_MODE_CLIP_AS_TRIFAN | R300_CLIP_DISABLE);
+ R300_STATECHANGE(r300, vap_clip_cntl);
+
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ OUT_BATCH_REGVAL(R300_VAP_CLIP_CNTL, R300_PS_UCP_MODE_CLIP_AS_TRIFAN | R300_CLIP_DISABLE);
+ END_BATCH();
}
- R300_STATECHANGE(r300, ps);
- reg_start(R300_GA_POINT_SIZE, 0);
- e32(((dPriv->w * 6) << R300_POINTSIZE_X_SHIFT) |
- ((dPriv->h * 6) << R300_POINTSIZE_Y_SHIFT));
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ OUT_BATCH_REGVAL(R300_GA_POINT_SIZE,
+ ((dPriv->w * 6) << R300_POINTSIZE_X_SHIFT) |
+ ((dPriv->h * 6) << R300_POINTSIZE_Y_SHIFT));
+ END_BATCH();
if (!is_r500) {
R300_STATECHANGE(r300, ri);
- reg_start(R300_RS_IP_0, 7);
- for (i = 0; i < 8; ++i) {
- e32(R300_RS_SEL_T(1) | R300_RS_SEL_R(2) | R300_RS_SEL_Q(3));
- }
-
R300_STATECHANGE(r300, rc);
- /* The second constant is needed to get glxgears display anything .. */
- reg_start(R300_RS_COUNT, 1);
- e32((1 << R300_IC_COUNT_SHIFT) | R300_HIRES_EN);
- e32(0x0);
-
R300_STATECHANGE(r300, rr);
- reg_start(R300_RS_INST_0, 0);
- e32(R300_RS_INST_COL_CN_WRITE);
+
+ BEGIN_BATCH(14);
+ OUT_BATCH_REGSEQ(R300_RS_IP_0, 8);
+ for (i = 0; i < 8; ++i)
+ OUT_BATCH(R300_RS_SEL_T(1) | R300_RS_SEL_R(2) | R300_RS_SEL_Q(3));
+
+ OUT_BATCH_REGSEQ(R300_RS_COUNT, 2);
+ OUT_BATCH((1 << R300_IC_COUNT_SHIFT) | R300_HIRES_EN);
+ OUT_BATCH(0x0);
+
+ OUT_BATCH_REGVAL(R300_RS_INST_0, R300_RS_INST_COL_CN_WRITE);
+ END_BATCH();
} else {
R300_STATECHANGE(r300, ri);
- reg_start(R500_RS_IP_0, 7);
+ R300_STATECHANGE(r300, rc);
+ R300_STATECHANGE(r300, rr);
+
+ BEGIN_BATCH(14);
+ OUT_BATCH_REGSEQ(R500_RS_IP_0, 8);
for (i = 0; i < 8; ++i) {
- e32((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));
+ OUT_BATCH((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));
}
- R300_STATECHANGE(r300, rc);
- /* The second constant is needed to get glxgears display anything .. */
- reg_start(R300_RS_COUNT, 1);
- e32((1 << R300_IC_COUNT_SHIFT) | R300_HIRES_EN);
- e32(0x0);
-
- R300_STATECHANGE(r300, rr);
- reg_start(R500_RS_INST_0, 0);
- e32(R500_RS_INST_COL_CN_WRITE);
+ OUT_BATCH_REGSEQ(R300_RS_COUNT, 2);
+ OUT_BATCH((1 << R300_IC_COUNT_SHIFT) | R300_HIRES_EN);
+ OUT_BATCH(0x0);
+ OUT_BATCH_REGVAL(R500_RS_INST_0, R500_RS_INST_COL_CN_WRITE);
+ END_BATCH();
}
if (!is_r500) {
R300_STATECHANGE(r300, fp);
- reg_start(R300_US_CONFIG, 2);
- e32(0x0);
- e32(0x0);
- e32(0x0);
- reg_start(R300_US_CODE_ADDR_0, 3);
- e32(0x0);
- e32(0x0);
- e32(0x0);
- e32(R300_RGBA_OUT);
-
R300_STATECHANGE(r300, fpi[0]);
R300_STATECHANGE(r300, fpi[1]);
R300_STATECHANGE(r300, fpi[2]);
R300_STATECHANGE(r300, fpi[3]);
- reg_start(R300_US_ALU_RGB_INST_0, 0);
- e32(FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO)));
-
- reg_start(R300_US_ALU_RGB_ADDR_0, 0);
- e32(FP_SELC(0, NO, XYZ, FP_TMP(0), 0, 0));
-
- reg_start(R300_US_ALU_ALPHA_INST_0, 0);
- e32(FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO)));
-
- reg_start(R300_US_ALU_ALPHA_ADDR_0, 0);
- e32(FP_SELA(0, NO, W, FP_TMP(0), 0, 0));
+ BEGIN_BATCH(17);
+ OUT_BATCH_REGSEQ(R300_US_CONFIG, 3);
+ OUT_BATCH(0x0);
+ OUT_BATCH(0x0);
+ OUT_BATCH(0x0);
+ OUT_BATCH_REGSEQ(R300_US_CODE_ADDR_0, 4);
+ OUT_BATCH(0x0);
+ OUT_BATCH(0x0);
+ OUT_BATCH(0x0);
+ OUT_BATCH(R300_RGBA_OUT);
+
+ OUT_BATCH_REGVAL(R300_US_ALU_RGB_INST_0,
+ FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO)));
+ OUT_BATCH_REGVAL(R300_US_ALU_RGB_ADDR_0,
+ FP_SELC(0, NO, XYZ, FP_TMP(0), 0, 0));
+ OUT_BATCH_REGVAL(R300_US_ALU_ALPHA_INST_0,
+ FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO)));
+ OUT_BATCH_REGVAL(R300_US_ALU_ALPHA_ADDR_0,
+ FP_SELA(0, NO, W, FP_TMP(0), 0, 0));
+ END_BATCH();
} else {
- R300_STATECHANGE(r300, fp);
- reg_start(R500_US_CONFIG, 1);
- e32(R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
- e32(0x0);
- reg_start(R500_US_CODE_ADDR, 2);
- e32(R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(1));
- e32(R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(1));
- e32(R500_US_CODE_OFFSET_ADDR(0));
-
+ R300_STATECHANGE(r300, fp);
R300_STATECHANGE(r300, r500fp);
- r500fp_start_fragment(0, 6);
-
- e32(R500_INST_TYPE_OUT |
- R500_INST_TEX_SEM_WAIT |
- R500_INST_LAST |
- R500_INST_RGB_OMASK_R |
- R500_INST_RGB_OMASK_G |
- R500_INST_RGB_OMASK_B |
- R500_INST_ALPHA_OMASK |
- R500_INST_RGB_CLAMP |
- R500_INST_ALPHA_CLAMP);
-
- e32(R500_RGB_ADDR0(0) |
- R500_RGB_ADDR1(0) |
- R500_RGB_ADDR1_CONST |
- R500_RGB_ADDR2(0) |
- R500_RGB_ADDR2_CONST);
-
- e32(R500_ALPHA_ADDR0(0) |
- R500_ALPHA_ADDR1(0) |
- R500_ALPHA_ADDR1_CONST |
- R500_ALPHA_ADDR2(0) |
- R500_ALPHA_ADDR2_CONST);
-
- e32(R500_ALU_RGB_SEL_A_SRC0 |
- R500_ALU_RGB_R_SWIZ_A_R |
- R500_ALU_RGB_G_SWIZ_A_G |
- R500_ALU_RGB_B_SWIZ_A_B |
- R500_ALU_RGB_SEL_B_SRC0 |
- R500_ALU_RGB_R_SWIZ_B_R |
- R500_ALU_RGB_B_SWIZ_B_G |
- R500_ALU_RGB_G_SWIZ_B_B);
-
- e32(R500_ALPHA_OP_CMP |
- R500_ALPHA_SWIZ_A_A |
- R500_ALPHA_SWIZ_B_A);
-
- e32(R500_ALU_RGBA_OP_CMP |
- R500_ALU_RGBA_R_SWIZ_0 |
- R500_ALU_RGBA_G_SWIZ_0 |
- R500_ALU_RGBA_B_SWIZ_0 |
- R500_ALU_RGBA_A_SWIZ_0);
+
+ BEGIN_BATCH(14);
+ OUT_BATCH_REGSEQ(R500_US_CONFIG, 2);
+ OUT_BATCH(R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
+ OUT_BATCH(0x0);
+ OUT_BATCH_REGSEQ(R500_US_CODE_ADDR, 3);
+ OUT_BATCH(R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(1));
+ OUT_BATCH(R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(1));
+ OUT_BATCH(R500_US_CODE_OFFSET_ADDR(0));
+
+ OUT_BATCH(cmdr500fp(0, 1, 0, 0));
+ OUT_BATCH(R500_INST_TYPE_OUT |
+ R500_INST_TEX_SEM_WAIT |
+ R500_INST_LAST |
+ R500_INST_RGB_OMASK_R |
+ R500_INST_RGB_OMASK_G |
+ R500_INST_RGB_OMASK_B |
+ R500_INST_ALPHA_OMASK |
+ R500_INST_RGB_CLAMP |
+ R500_INST_ALPHA_CLAMP);
+ OUT_BATCH(R500_RGB_ADDR0(0) |
+ R500_RGB_ADDR1(0) |
+ R500_RGB_ADDR1_CONST |
+ R500_RGB_ADDR2(0) |
+ R500_RGB_ADDR2_CONST);
+ OUT_BATCH(R500_ALPHA_ADDR0(0) |
+ R500_ALPHA_ADDR1(0) |
+ R500_ALPHA_ADDR1_CONST |
+ R500_ALPHA_ADDR2(0) |
+ R500_ALPHA_ADDR2_CONST);
+ OUT_BATCH(R500_ALU_RGB_SEL_A_SRC0 |
+ R500_ALU_RGB_R_SWIZ_A_R |
+ R500_ALU_RGB_G_SWIZ_A_G |
+ R500_ALU_RGB_B_SWIZ_A_B |
+ R500_ALU_RGB_SEL_B_SRC0 |
+ R500_ALU_RGB_R_SWIZ_B_R |
+ R500_ALU_RGB_B_SWIZ_B_G |
+ R500_ALU_RGB_G_SWIZ_B_B);
+ OUT_BATCH(R500_ALPHA_OP_CMP |
+ R500_ALPHA_SWIZ_A_A |
+ R500_ALPHA_SWIZ_B_A);
+ OUT_BATCH(R500_ALU_RGBA_OP_CMP |
+ R500_ALU_RGBA_R_SWIZ_0 |
+ R500_ALU_RGBA_G_SWIZ_0 |
+ R500_ALU_RGBA_B_SWIZ_0 |
+ R500_ALU_RGBA_A_SWIZ_0);
+ END_BATCH();
}
- reg_start(R300_VAP_PVS_STATE_FLUSH_REG, 0);
- e32(0x00000000);
+ BEGIN_BATCH(2);
+ OUT_BATCH_REGVAL(R300_VAP_PVS_STATE_FLUSH_REG, 0);
+ END_BATCH();
+
if (has_tcl) {
- vap_cntl = ((10 << R300_PVS_NUM_SLOTS_SHIFT) |
+ vap_cntl = ((10 << R300_PVS_NUM_SLOTS_SHIFT) |
(5 << R300_PVS_NUM_CNTLRS_SHIFT) |
(12 << R300_VF_MAX_VTX_NUM_SHIFT));
- if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
- vap_cntl |= R500_TCL_STATE_OPTIMIZATION;
- } else
- vap_cntl = ((10 << R300_PVS_NUM_SLOTS_SHIFT) |
+ if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
+ vap_cntl |= R500_TCL_STATE_OPTIMIZATION;
+ } else {
+ vap_cntl = ((10 << R300_PVS_NUM_SLOTS_SHIFT) |
(5 << R300_PVS_NUM_CNTLRS_SHIFT) |
(5 << R300_VF_MAX_VTX_NUM_SHIFT));
+ }
if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV515)
- vap_cntl |= (2 << R300_PVS_NUM_FPUS_SHIFT);
+ vap_cntl |= (2 << R300_PVS_NUM_FPUS_SHIFT);
else if ((r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) ||
(r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV560) ||
(r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV570))
- vap_cntl |= (5 << R300_PVS_NUM_FPUS_SHIFT);
+ vap_cntl |= (5 << R300_PVS_NUM_FPUS_SHIFT);
else if ((r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV410) ||
(r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R420))
- vap_cntl |= (6 << R300_PVS_NUM_FPUS_SHIFT);
+ vap_cntl |= (6 << R300_PVS_NUM_FPUS_SHIFT);
else if ((r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R520) ||
(r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R580))
- vap_cntl |= (8 << R300_PVS_NUM_FPUS_SHIFT);
+ vap_cntl |= (8 << R300_PVS_NUM_FPUS_SHIFT);
else
- vap_cntl |= (4 << R300_PVS_NUM_FPUS_SHIFT);
+ vap_cntl |= (4 << R300_PVS_NUM_FPUS_SHIFT);
+
+ R300_STATECHANGE(r300, vap_cntl);
- R300_STATECHANGE(rmesa, vap_cntl);
- reg_start(R300_VAP_CNTL, 0);
- e32(vap_cntl);
+ BEGIN_BATCH(2);
+ OUT_BATCH_REGVAL(R300_VAP_CNTL, vap_cntl);
+ END_BATCH();
if (has_tcl) {
R300_STATECHANGE(r300, pvs);
- reg_start(R300_VAP_PVS_CODE_CNTL_0, 2);
-
- e32((0 << R300_PVS_FIRST_INST_SHIFT) |
- (0 << R300_PVS_XYZW_VALID_INST_SHIFT) |
- (1 << R300_PVS_LAST_INST_SHIFT));
- e32((0 << R300_PVS_CONST_BASE_OFFSET_SHIFT) |
- (0 << R300_PVS_MAX_CONST_ADDR_SHIFT));
- e32(1 << R300_PVS_LAST_VTX_SRC_INST_SHIFT);
-
R300_STATECHANGE(r300, vpi);
- vsf_start_fragment(0x0, 8);
-
- e32(PVS_OP_DST_OPERAND(VE_ADD, GL_FALSE, GL_FALSE, 0, 0xf, PVS_DST_REG_OUT));
- e32(PVS_SRC_OPERAND(0, PVS_SRC_SELECT_X, PVS_SRC_SELECT_Y, PVS_SRC_SELECT_Z, PVS_SRC_SELECT_W, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
- e32(PVS_SRC_OPERAND(0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
- e32(0x0);
- e32(PVS_OP_DST_OPERAND(VE_ADD, GL_FALSE, GL_FALSE, 1, 0xf, PVS_DST_REG_OUT));
- e32(PVS_SRC_OPERAND(1, PVS_SRC_SELECT_X, PVS_SRC_SELECT_Y, PVS_SRC_SELECT_Z, PVS_SRC_SELECT_W, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
- e32(PVS_SRC_OPERAND(1, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
- e32(0x0);
+ BEGIN_BATCH(13);
+ OUT_BATCH_REGSEQ(R300_VAP_PVS_CODE_CNTL_0, 3);
+ OUT_BATCH((0 << R300_PVS_FIRST_INST_SHIFT) |
+ (0 << R300_PVS_XYZW_VALID_INST_SHIFT) |
+ (1 << R300_PVS_LAST_INST_SHIFT));
+ OUT_BATCH((0 << R300_PVS_CONST_BASE_OFFSET_SHIFT) |
+ (0 << R300_PVS_MAX_CONST_ADDR_SHIFT));
+ OUT_BATCH(1 << R300_PVS_LAST_VTX_SRC_INST_SHIFT);
+
+ OUT_BATCH(cmdvpu(0, 2));
+ OUT_BATCH(PVS_OP_DST_OPERAND(VE_ADD, GL_FALSE, GL_FALSE, 0, 0xf, PVS_DST_REG_OUT));
+ OUT_BATCH(PVS_SRC_OPERAND(0, PVS_SRC_SELECT_X, PVS_SRC_SELECT_Y, PVS_SRC_SELECT_Z, PVS_SRC_SELECT_W, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
+ OUT_BATCH(PVS_SRC_OPERAND(0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
+ OUT_BATCH(0x0);
+
+ OUT_BATCH(PVS_OP_DST_OPERAND(VE_ADD, GL_FALSE, GL_FALSE, 1, 0xf, PVS_DST_REG_OUT));
+ OUT_BATCH(PVS_SRC_OPERAND(1, PVS_SRC_SELECT_X, PVS_SRC_SELECT_Y, PVS_SRC_SELECT_Z, PVS_SRC_SELECT_W, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
+ OUT_BATCH(PVS_SRC_OPERAND(1, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
+ OUT_BATCH(0x0);
+ END_BATCH();
}
}
@@ -467,7 +465,10 @@ static void r300EmitClearState(GLcontext * ctx)
static void r300Clear(GLcontext * ctx, GLbitfield mask)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
+ BATCH_LOCALS(r300);
__DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
+ GLframebuffer *fb = dPriv->driverPrivate;
+ struct radeon_renderbuffer *rrb;
int flags = 0;
int bits = 0;
int swapped;
@@ -482,6 +483,12 @@ static void r300Clear(GLcontext * ctx, GLbitfield mask)
return;
}
+ /* Flush swtcl vertices if necessary, because we will change hardware
+ * state during clear. See also the state-related comment in
+ * r300EmitClearState.
+ */
+ R300_NEWPRIM(r300);
+
if (mask & BUFFER_BIT_FRONT_LEFT) {
flags |= BUFFER_BIT_FRONT_LEFT;
mask &= ~BUFFER_BIT_FRONT_LEFT;
@@ -509,26 +516,27 @@ static void r300Clear(GLcontext * ctx, GLbitfield mask)
_swrast_Clear(ctx, mask);
}
- swapped = r300->radeon.sarea->pfCurrentPage == 1;
-
/* Make sure it fits there. */
r300EnsureCmdBufSpace(r300, 421 * 3, __FUNCTION__);
if (flags || bits)
r300EmitClearState(ctx);
if (flags & BUFFER_BIT_FRONT_LEFT) {
- r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped);
+ rrb = (void *)fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+ r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, rrb);
bits = 0;
}
if (flags & BUFFER_BIT_BACK_LEFT) {
- r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped ^ 1);
+ rrb = (void *)fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, rrb);
bits = 0;
}
if (bits)
- r300ClearBuffer(r300, bits, 0);
+ r300ClearBuffer(r300, bits, NULL);
+ COMMIT_BATCH();
}
void r300Flush(GLcontext * ctx)
@@ -541,16 +549,12 @@ void r300Flush(GLcontext * ctx)
if (rmesa->dma.flush)
rmesa->dma.flush( rmesa );
- if (rmesa->cmdbuf.count_used > rmesa->cmdbuf.count_reemit)
+ if (rmesa->cmdbuf.committed > rmesa->cmdbuf.reemit)
r300FlushCmdBuf(rmesa, __FUNCTION__);
}
-#ifdef USER_BUFFERS
-#include "r300_mem.h"
-
void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size)
{
- struct r300_dma_buffer *dmabuf;
size = MAX2(size, RADEON_BUFFER_SIZE * 16);
if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
@@ -560,71 +564,24 @@ void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size)
rmesa->dma.flush(rmesa);
}
- if (rmesa->dma.current.buf) {
-#ifdef USER_BUFFERS
- r300_mem_use(rmesa, rmesa->dma.current.buf->id);
-#endif
- r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
+ if (rmesa->dma.current) {
+ dri_bo_unreference(rmesa->dma.current);
+ rmesa->dma.current = 0;
}
if (rmesa->dma.nr_released_bufs > 4)
r300FlushCmdBuf(rmesa, __FUNCTION__);
- dmabuf = CALLOC_STRUCT(r300_dma_buffer);
- dmabuf->buf = (void *)1; /* hack */
- dmabuf->refcount = 1;
-
- dmabuf->id = r300_mem_alloc(rmesa, 4, size);
- if (dmabuf->id == 0) {
- LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
-
- r300FlushCmdBufLocked(rmesa, __FUNCTION__);
- radeonWaitForIdleLocked(&rmesa->radeon);
-
- dmabuf->id = r300_mem_alloc(rmesa, 4, size);
-
- UNLOCK_HARDWARE(&rmesa->radeon);
-
- if (dmabuf->id == 0) {
- fprintf(stderr,
- "Error: Could not get dma buffer... exiting\n");
- _mesa_exit(-1);
- }
- }
-
- rmesa->dma.current.buf = dmabuf;
- rmesa->dma.current.address = r300_mem_ptr(rmesa, dmabuf->id);
- rmesa->dma.current.end = size;
- rmesa->dma.current.start = 0;
- rmesa->dma.current.ptr = 0;
-}
-
-void r300ReleaseDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region, const char *caller)
-{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (!region->buf)
- return;
-
- if (rmesa->dma.flush)
- rmesa->dma.flush(rmesa);
-
- if (--region->buf->refcount == 0) {
- r300_mem_free(rmesa, region->buf->id);
- FREE(region->buf);
- rmesa->dma.nr_released_bufs++;
- }
-
- region->buf = 0;
- region->start = 0;
+ rmesa->dma.current = dri_bo_alloc(&rmesa->radeon.bufmgr->base, "DMA regions",
+ size, 4, DRM_BO_MEM_DMA);
+ rmesa->dma.current_used = 0;
+ rmesa->dma.current_vertexptr = 0;
}
/* Allocates a region from rmesa->dma.current. If there isn't enough
* space in current, grab a new buffer (and discard what was left of current)
*/
void r300AllocDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region,
+ dri_bo **pbo, int *poffset,
int bytes, int alignment)
{
if (RADEON_DEBUG & DEBUG_IOCTL)
@@ -633,207 +590,23 @@ void r300AllocDmaRegion(r300ContextPtr rmesa,
if (rmesa->dma.flush)
rmesa->dma.flush(rmesa);
- if (region->buf)
- r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
+ assert(rmesa->dma.current_used == rmesa->dma.current_vertexptr);
alignment--;
- rmesa->dma.current.start = rmesa->dma.current.ptr =
- (rmesa->dma.current.ptr + alignment) & ~alignment;
-
- if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
- r300RefillCurrentDmaRegion(rmesa, (bytes + 0x7) & ~0x7);
-
- region->start = rmesa->dma.current.start;
- region->ptr = rmesa->dma.current.start;
- region->end = rmesa->dma.current.start + bytes;
- region->address = rmesa->dma.current.address;
- region->buf = rmesa->dma.current.buf;
- region->buf->refcount++;
+ rmesa->dma.current_used = (rmesa->dma.current_used + alignment) & ~alignment;
- rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
- rmesa->dma.current.start =
- rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
-
- assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
-}
+ if (!rmesa->dma.current || rmesa->dma.current_used + bytes > rmesa->dma.current->size)
+ r300RefillCurrentDmaRegion(rmesa, (bytes + 15) & ~15);
-#else
-static void r300RefillCurrentDmaRegion(r300ContextPtr rmesa)
-{
- struct r300_dma_buffer *dmabuf;
- int fd = rmesa->radeon.dri.fd;
- int index = 0;
- int size = 0;
- drmDMAReq dma;
- int ret;
+ *poffset = rmesa->dma.current_used;
+ *pbo = rmesa->dma.current;
+ dri_bo_reference(*pbo);
- if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
- fprintf(stderr, "%s\n", __FUNCTION__);
+ /* Always align to at least 16 bytes */
+ rmesa->dma.current_used = (rmesa->dma.current_used + bytes + 15) & ~15;
+ rmesa->dma.current_vertexptr = rmesa->dma.current_used;
- if (rmesa->dma.flush) {
- rmesa->dma.flush(rmesa);
- }
-
- if (rmesa->dma.current.buf)
- r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
-
- if (rmesa->dma.nr_released_bufs > 4)
- r300FlushCmdBuf(rmesa, __FUNCTION__);
-
- dma.context = rmesa->radeon.dri.hwContext;
- dma.send_count = 0;
- dma.send_list = NULL;
- dma.send_sizes = NULL;
- dma.flags = 0;
- dma.request_count = 1;
- dma.request_size = RADEON_BUFFER_SIZE;
- dma.request_list = &index;
- dma.request_sizes = &size;
- dma.granted_count = 0;
-
- LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
-
- ret = drmDMA(fd, &dma);
-
- if (ret != 0) {
- /* Try to release some buffers and wait until we can't get any more */
- if (rmesa->dma.nr_released_bufs) {
- r300FlushCmdBufLocked(rmesa, __FUNCTION__);
- }
-
- if (RADEON_DEBUG & DEBUG_DMA)
- fprintf(stderr, "Waiting for buffers\n");
-
- radeonWaitForIdleLocked(&rmesa->radeon);
- ret = drmDMA(fd, &dma);
-
- if (ret != 0) {
- UNLOCK_HARDWARE(&rmesa->radeon);
- fprintf(stderr,
- "Error: Could not get dma buffer... exiting\n");
- _mesa_exit(-1);
- }
- }
-
- UNLOCK_HARDWARE(&rmesa->radeon);
-
- if (RADEON_DEBUG & DEBUG_DMA)
- fprintf(stderr, "Allocated buffer %d\n", index);
-
- dmabuf = CALLOC_STRUCT(r300_dma_buffer);
- dmabuf->buf = &rmesa->radeon.radeonScreen->buffers->list[index];
- dmabuf->refcount = 1;
-
- rmesa->dma.current.buf = dmabuf;
- rmesa->dma.current.address = dmabuf->buf->address;
- rmesa->dma.current.end = dmabuf->buf->total;
- rmesa->dma.current.start = 0;
- rmesa->dma.current.ptr = 0;
-}
-
-void r300ReleaseDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region, const char *caller)
-{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (!region->buf)
- return;
-
- if (rmesa->dma.flush)
- rmesa->dma.flush(rmesa);
-
- if (--region->buf->refcount == 0) {
- drm_radeon_cmd_header_t *cmd;
-
- if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
- fprintf(stderr, "%s -- DISCARD BUF %d\n",
- __FUNCTION__, region->buf->buf->idx);
- cmd =
- (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa,
- sizeof
- (*cmd) / 4,
- __FUNCTION__);
- cmd->dma.cmd_type = R300_CMD_DMA_DISCARD;
- cmd->dma.buf_idx = region->buf->buf->idx;
-
- FREE(region->buf);
- rmesa->dma.nr_released_bufs++;
- }
-
- region->buf = 0;
- region->start = 0;
-}
-
-/* Allocates a region from rmesa->dma.current. If there isn't enough
- * space in current, grab a new buffer (and discard what was left of current)
- */
-void r300AllocDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region,
- int bytes, int alignment)
-{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
-
- if (rmesa->dma.flush)
- rmesa->dma.flush(rmesa);
-
- if (region->buf)
- r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
-
- alignment--;
- rmesa->dma.current.start = rmesa->dma.current.ptr =
- (rmesa->dma.current.ptr + alignment) & ~alignment;
-
- if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
- r300RefillCurrentDmaRegion(rmesa);
-
- region->start = rmesa->dma.current.start;
- region->ptr = rmesa->dma.current.start;
- region->end = rmesa->dma.current.start + bytes;
- region->address = rmesa->dma.current.address;
- region->buf = rmesa->dma.current.buf;
- region->buf->refcount++;
-
- rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
- rmesa->dma.current.start =
- rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
-
- assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
-}
-
-#endif
-
-GLboolean r300IsGartMemory(r300ContextPtr rmesa, const GLvoid * pointer,
- GLint size)
-{
- int offset =
- (char *)pointer -
- (char *)rmesa->radeon.radeonScreen->gartTextures.map;
- int valid = (size >= 0 && offset >= 0
- && offset + size <
- rmesa->radeon.radeonScreen->gartTextures.size);
-
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "r300IsGartMemory( %p ) : %d\n", pointer,
- valid);
-
- return valid;
-}
-
-GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa, const GLvoid * pointer)
-{
- int offset =
- (char *)pointer -
- (char *)rmesa->radeon.radeonScreen->gartTextures.map;
-
- //fprintf(stderr, "offset=%08x\n", offset);
-
- if (offset < 0
- || offset > rmesa->radeon.radeonScreen->gartTextures.size)
- return ~0;
- else
- return rmesa->radeon.radeonScreen->gart_texture_offset + offset;
+ assert(rmesa->dma.current_used <= rmesa->dma.current->size);
}
void r300InitIoctlFuncs(struct dd_function_table *functions)
diff --git a/src/mesa/drivers/dri/r300/r300_ioctl.h b/src/mesa/drivers/dri/r300/r300_ioctl.h
index e1143fb..c743478 100644
--- a/src/mesa/drivers/dri/r300/r300_ioctl.h
+++ b/src/mesa/drivers/dri/r300/r300_ioctl.h
@@ -39,20 +39,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r300_context.h"
#include "radeon_drm.h"
-extern GLboolean r300IsGartMemory(r300ContextPtr rmesa,
- const GLvoid * pointer, GLint size);
-
-extern GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa,
- const GLvoid * pointer);
-
extern void r300Flush(GLcontext * ctx);
-extern void r300ReleaseDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region,
- const char *caller);
extern void r300AllocDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region, int bytes,
- int alignment);
+ dri_bo **pbo, int *poffset,
+ int bytes, int alignment);
extern void r300InitIoctlFuncs(struct dd_function_table *functions);
diff --git a/src/mesa/drivers/dri/r300/r300_mem.c b/src/mesa/drivers/dri/r300/r300_mem.c
index f8f9d4f..b045393 100644
--- a/src/mesa/drivers/dri/r300/r300_mem.c
+++ b/src/mesa/drivers/dri/r300/r300_mem.c
@@ -27,359 +27,843 @@
/**
* \file
+ * Simulate a real memory manager for R300 in the old-style scheme.
+ *
+ * NOTE: Right now, this is DMA-only and really only a skeleton of a true bufmgr.
*
* \author Aapo Tahkola <aet@rasterburn.org>
*/
+#include "r300_mem.h"
+
+#include <errno.h>
#include <unistd.h>
-#include "r300_context.h"
-#include "r300_cmdbuf.h"
-#include "r300_ioctl.h"
-#include "r300_mem.h"
+#include "simple_list.h"
+
#include "radeon_ioctl.h"
+#include "r300_cmdbuf.h"
-#ifdef USER_BUFFERS
+typedef struct _radeon_bufmgr_classic radeon_bufmgr_classic;
+typedef struct _radeon_bo_classic radeon_bo_classic;
+typedef struct _radeon_bo_functions radeon_bo_functions;
+typedef struct _radeon_reloc radeon_reloc;
+typedef struct _radeon_bo_vram radeon_bo_vram;
+
+struct _radeon_bufmgr_classic {
+ radeon_bufmgr base;
+ r300ContextPtr rmesa;
+
+ radeon_bo_classic *buffers; /** Unsorted linked list of all buffer objects */
+
+ radeon_bo_classic *pending; /** Age-sorted linked list of pending buffer objects */
+ radeon_bo_classic **pending_tail;
+
+ /* Texture heap bookkeeping */
+ driTexHeap *texture_heap;
+ GLuint texture_offset;
+ driTextureObject texture_swapped;
+};
+
+struct _radeon_reloc {
+ uint64_t flags;
+ GLuint offset; /**< Offset (in bytes) into command buffer to relocated dword */
+ radeon_bo_classic *target;
+ GLuint delta;
+};
+
+struct _radeon_bo_functions {
+ /**
+ * Free a buffer object. Caller has verified that the object is not
+ * referenced or pending.
+ */
+ void (*free)(radeon_bo_classic*);
+
+ /**
+ * Validate the given buffer. Must set the validated flag to 1.
+ *
+ * May be null for buffer objects that are always valid.
+ * Always called with lock held.
+ */
+ void (*validate)(radeon_bo_classic*);
+
+ /**
+ * Called when a writing map of the buffer is taken, to note that
+ * the buffer will have to be re-validated.
+ *
+ * May be null for buffer objects that don't need it.
+ */
+ void (*dirty)(radeon_bo_classic*);
+
+ /**
+ * Indicate that the buffer object is now used by the hardware.
+ *
+ * May be null.
+ */
+ void (*bind)(radeon_bo_classic*);
+
+ /**
+ * Indicate that the buffer object is no longer used by the hardware.
+ *
+ * May be null.
+ */
+ void (*unbind)(radeon_bo_classic*);
+};
-static void resize_u_list(r300ContextPtr rmesa)
-{
- void *temp;
- int nsize;
+/**
+ * A buffer object. There are three types of buffer objects:
+ * 1. cmdbuf: Ordinary malloc()ed memory, used for command buffers
+ * 2. dma: GART memory allocated via the DRM_RADEON_ALLOC ioctl.
+ * 3. vram: Objects with malloc()ed backing store that will be uploaded
+ * into VRAM on demand; used for textures.
+ * There is a @ref functions table for operations that depend on the
+ * buffer object type.
+ *
+ * Fencing is handled the same way all buffer objects. During command buffer
+ * submission, the pending flag and corresponding variables are set accordingly.
+ */
+struct _radeon_bo_classic {
+ dri_bo base;
- temp = rmesa->rmm->u_list;
- nsize = rmesa->rmm->u_size * 2;
+ const radeon_bo_functions *functions;
- rmesa->rmm->u_list = _mesa_malloc(nsize * sizeof(*rmesa->rmm->u_list));
- _mesa_memset(rmesa->rmm->u_list, 0,
- nsize * sizeof(*rmesa->rmm->u_list));
+ radeon_bo_classic *next; /** Unsorted linked list of all buffer objects */
+ radeon_bo_classic **pprev;
- if (temp) {
- r300FlushCmdBuf(rmesa, __FUNCTION__);
+ /**
+ * Number of software references to this buffer.
+ * A buffer is freed automatically as soon as its reference count reaches 0
+ * *and* it is no longer pending.
+ */
+ unsigned int refcount;
+ unsigned int mapcount; /** mmap count; mutually exclusive to being pending */
- _mesa_memcpy(rmesa->rmm->u_list, temp,
- rmesa->rmm->u_size * sizeof(*rmesa->rmm->u_list));
- _mesa_free(temp);
- }
+ unsigned int validated:1; /** whether the buffer is validated for hardware use right now */
+ unsigned int used:1; /* only for communication between process_relocs and post_submit */
+
+ unsigned int pending:1;
+ radeon_bo_classic *pending_next; /** Age-sorted linked list of pending buffer objects */
+ radeon_bo_classic **pending_pprev;
- rmesa->rmm->u_size = nsize;
+ /* The following two variables are intricately linked to the DRM interface,
+ * and must be in this physical memory order, or else chaos ensues.
+ * See the DRM's implementation of R300_CMD_SCRATCH for details.
+ */
+ uint32_t pending_age; /** Buffer object pending until this age is reached, written by the DRM */
+ uint32_t pending_count; /** Number of pending R300_CMD_SCRATCH references to this object */
+
+ radeon_reloc *relocs; /** Array of relocations in this buffer */
+ GLuint relocs_used; /** # of relocations in relocation array */
+ GLuint relocs_size; /** # of reloc records reserved in relocation array */
+};
+
+typedef struct _radeon_vram_wrapper radeon_vram_wrapper;
+
+/** Wrapper around heap object */
+struct _radeon_vram_wrapper {
+ driTextureObject base;
+ radeon_bo_vram *bo;
+};
+
+struct _radeon_bo_vram {
+ radeon_bo_classic base;
+
+ unsigned int backing_store_dirty:1; /** Backing store has changed, block must be reuploaded */
+
+ radeon_vram_wrapper *vram; /** Block in VRAM (if any) */
+};
+
+static radeon_bufmgr_classic* get_bufmgr_classic(dri_bufmgr *bufmgr_ctx)
+{
+ return (radeon_bufmgr_classic*)bufmgr_ctx;
}
-void r300_mem_init(r300ContextPtr rmesa)
+static radeon_bo_classic* get_bo_classic(dri_bo *bo_base)
{
- rmesa->rmm = malloc(sizeof(struct r300_memory_manager));
- memset(rmesa->rmm, 0, sizeof(struct r300_memory_manager));
+ return (radeon_bo_classic*)bo_base;
+}
- rmesa->rmm->u_size = 128;
- resize_u_list(rmesa);
+static radeon_bo_vram* get_bo_vram(radeon_bo_classic *bo_base)
+{
+ return (radeon_bo_vram*)bo_base;
}
-void r300_mem_destroy(r300ContextPtr rmesa)
+/**
+ * Really free a given buffer object.
+ */
+static void bo_free(radeon_bo_classic *bo)
{
- _mesa_free(rmesa->rmm->u_list);
- rmesa->rmm->u_list = NULL;
+ assert(!bo->refcount);
+ assert(!bo->pending);
+ assert(!bo->mapcount);
+
+ if (bo->relocs) {
+ int i;
+ for(i = 0; i < bo->relocs_used; ++i)
+ dri_bo_unreference(&bo->relocs[i].target->base);
+ free(bo->relocs);
+ bo->relocs = 0;
+ }
+
+ *bo->pprev = bo->next;
+ if (bo->next)
+ bo->next->pprev = bo->pprev;
- _mesa_free(rmesa->rmm);
- rmesa->rmm = NULL;
+ bo->functions->free(bo);
}
-void *r300_mem_ptr(r300ContextPtr rmesa, int id)
+
+/**
+ * Keep track of which buffer objects are still pending, i.e. waiting for
+ * some hardware operation to complete.
+ */
+static void track_pending_buffers(radeon_bufmgr_classic *bufmgr)
{
- assert(id <= rmesa->rmm->u_last);
- return rmesa->rmm->u_list[id].ptr;
+ uint32_t currentage = radeonGetAge((radeonContextPtr)bufmgr->rmesa);
+
+ while(bufmgr->pending) {
+ radeon_bo_classic *bo = bufmgr->pending;
+
+ assert(bo->pending);
+
+ if (bo->pending_count ||
+ bo->pending_age > currentage) // TODO: Age counter wraparound!
+ break;
+
+ bo->pending = 0;
+ bufmgr->pending = bo->pending_next;
+ if (bufmgr->pending)
+ bufmgr->pending->pending_pprev = &bufmgr->pending;
+ else
+ bufmgr->pending_tail = &bufmgr->pending;
+
+ if (bo->functions->unbind)
+ (*bo->functions->unbind)(bo);
+ if (!bo->refcount)
+ bo_free(bo);
+ }
}
-int r300_mem_find(r300ContextPtr rmesa, void *ptr)
+/**
+ * Initialize common buffer object data.
+ */
+static void init_buffer(radeon_bufmgr_classic *bufmgr, radeon_bo_classic *bo, unsigned long size)
{
- int i;
+ bo->base.bufmgr = &bufmgr->base.base;
+ bo->base.size = size;
+ bo->refcount = 1;
+
+ bo->pprev = &bufmgr->buffers;
+ bo->next = bufmgr->buffers;
+ if (bo->next)
+ bo->next->pprev = &bo->next;
+ bufmgr->buffers = bo;
+}
- for (i = 1; i < rmesa->rmm->u_size + 1; i++)
- if (rmesa->rmm->u_list[i].ptr &&
- ptr >= rmesa->rmm->u_list[i].ptr &&
- ptr <
- rmesa->rmm->u_list[i].ptr + rmesa->rmm->u_list[i].size)
- break;
- if (i < rmesa->rmm->u_size + 1)
- return i;
+/**
+ * Free a DMA-based buffer.
+ */
+static void dma_free(radeon_bo_classic *bo)
+{
+ radeon_bufmgr_classic* bufmgr = get_bufmgr_classic(bo->base.bufmgr);
+ drm_radeon_mem_free_t memfree;
+ int ret;
+
+ memfree.region = RADEON_MEM_REGION_GART;
+ memfree.region_offset = bo->base.offset;
+ memfree.region_offset -= bufmgr->rmesa->radeon.radeonScreen->gart_texture_offset;
- fprintf(stderr, "%p failed\n", ptr);
- return 0;
+ ret = drmCommandWrite(bufmgr->rmesa->radeon.radeonScreen->driScreen->fd,
+ DRM_RADEON_FREE, &memfree, sizeof(memfree));
+ if (ret) {
+ fprintf(stderr, "Failed to free bo[%p] at %08x\n", bo, memfree.region_offset);
+ fprintf(stderr, "ret = %s\n", strerror(-ret));
+ exit(1);
+ }
+
+ free(bo);
}
-//#define MM_DEBUG
-int r300_mem_alloc(r300ContextPtr rmesa, int alignment, int size)
+static const radeon_bo_functions dma_bo_functions = {
+ .free = &dma_free
+};
+
+/**
+ * Call the DRM to allocate GART memory for the given (incomplete)
+ * buffer object.
+ */
+static int try_dma_alloc(radeon_bufmgr_classic *bufmgr, radeon_bo_classic *bo,
+ unsigned long size, unsigned int alignment)
{
drm_radeon_mem_alloc_t alloc;
- int offset = 0, ret;
- int i, free = -1;
- int done_age;
- drm_radeon_mem_free_t memfree;
- int tries = 0;
- static int bytes_wasted = 0, allocated = 0;
+ int baseoffset;
+ int ret;
- if (size < 4096)
- bytes_wasted += 4096 - size;
+ alloc.region = RADEON_MEM_REGION_GART;
+ alloc.alignment = alignment;
+ alloc.size = size;
+ alloc.region_offset = &baseoffset;
+
+ ret = drmCommandWriteRead(bufmgr->rmesa->radeon.dri.fd,
+ DRM_RADEON_ALLOC, &alloc, sizeof(alloc));
+ if (ret) {
+ if (RADEON_DEBUG & DEBUG_MEMORY)
+ fprintf(stderr, "DRM_RADEON_ALLOC failed: %d\n", ret);
+ return 0;
+ }
- allocated += size;
+ bo->base.virtual = (char*)bufmgr->rmesa->radeon.radeonScreen->gartTextures.map + baseoffset;
+ bo->base.offset = bufmgr->rmesa->radeon.radeonScreen->gart_texture_offset + baseoffset;
-#if 0
- static int t = 0;
- if (t != time(NULL)) {
- t = time(NULL);
- fprintf(stderr, "slots used %d, wasted %d kb, allocated %d\n",
- rmesa->rmm->u_last, bytes_wasted / 1024,
- allocated / 1024);
+ return 1;
+}
+
+/**
+ * Allocate a DMA buffer.
+ */
+static dri_bo *dma_alloc(radeon_bufmgr_classic *bufmgr, const char *name,
+ unsigned long size, unsigned int alignment)
+{
+ radeon_bo_classic* bo = (radeon_bo_classic*)calloc(1, sizeof(radeon_bo_classic));
+
+ bo->functions = &dma_bo_functions;
+
+ track_pending_buffers(bufmgr);
+ if (!try_dma_alloc(bufmgr, bo, size, alignment)) {
+ if (RADEON_DEBUG & DEBUG_MEMORY)
+ fprintf(stderr, "Failed to allocate %ld bytes, finishing command buffer...\n", size);
+ radeonFinish(bufmgr->rmesa->radeon.glCtx);
+ track_pending_buffers(bufmgr);
+ if (!try_dma_alloc(bufmgr, bo, size, alignment)) {
+ WARN_ONCE(
+ "Ran out of GART memory (for %ld)!\n"
+ "Please consider adjusting GARTSize option.\n",
+ size);
+ free(bo);
+ return 0;
+ }
}
-#endif
- memfree.region = RADEON_MEM_REGION_GART;
+ init_buffer(bufmgr, bo, size);
+ bo->validated = 1; /* DMA buffer offsets are always valid */
- again:
+ return &bo->base;
+}
- done_age = radeonGetAge((radeonContextPtr) rmesa);
+/**
+ * Free a command buffer
+ */
+static void cmdbuf_free(radeon_bo_classic *bo)
+{
+ free(bo->base.virtual);
+ free(bo);
+}
- if (rmesa->rmm->u_last + 1 >= rmesa->rmm->u_size)
- resize_u_list(rmesa);
+static const radeon_bo_functions cmdbuf_bo_functions = {
+ .free = cmdbuf_free
+};
- for (i = rmesa->rmm->u_last + 1; i > 0; i--) {
- if (rmesa->rmm->u_list[i].ptr == NULL) {
- free = i;
- continue;
+/**
+ * Allocate a command buffer.
+ *
+ * Command buffers are really just malloc'ed buffers. They are managed by
+ * the bufmgr to enable relocations.
+ */
+static dri_bo *cmdbuf_alloc(radeon_bufmgr_classic *bufmgr, const char *name,
+ unsigned long size)
+{
+ radeon_bo_classic* bo = (radeon_bo_classic*)calloc(1, sizeof(radeon_bo_classic));
+
+ bo->functions = &cmdbuf_bo_functions;
+ bo->base.virtual = malloc(size);
+
+ init_buffer(bufmgr, bo, size);
+ return &bo->base;
+}
+
+/**
+ * Free a VRAM-based buffer object.
+ */
+static void vram_free(radeon_bo_classic *bo_base)
+{
+ radeon_bo_vram *bo = get_bo_vram(bo_base);
+
+ if (bo->vram) {
+ driDestroyTextureObject(&bo->vram->base);
+ bo->vram = 0;
+ }
+
+ free(bo->base.base.virtual);
+ free(bo);
+}
+
+/**
+ * Allocate/update the copy in vram.
+ *
+ * Note: Assume we're called with the DRI lock held.
+ */
+static void vram_validate(radeon_bo_classic *bo_base)
+{
+ radeon_bufmgr_classic *bufmgr = get_bufmgr_classic(bo_base->base.bufmgr);
+ radeon_bo_vram *bo = get_bo_vram(bo_base);
+
+ if (!bo->vram) {
+ bo->backing_store_dirty = 1;
+
+ bo->vram = (radeon_vram_wrapper*)calloc(1, sizeof(radeon_vram_wrapper));
+ bo->vram->bo = bo;
+ make_empty_list(&bo->vram->base);
+ bo->vram->base.totalSize = bo->base.base.size;
+ if (driAllocateTexture(&bufmgr->texture_heap, 1, &bo->vram->base) < 0) {
+ fprintf(stderr, "Ouch! vram_validate failed\n");
+ free(bo->vram);
+ bo->base.base.offset = 0;
+ bo->vram = 0;
+ return;
}
+ }
+
+ assert(bo->vram->base.memBlock);
+
+ bo->base.base.offset = bufmgr->texture_offset + bo->vram->base.memBlock->ofs;
+
+ if (bo->backing_store_dirty) {
+ /* Copy to VRAM using a blit.
+ * All memory is 4K aligned. We're using 1024 pixels wide blits.
+ */
+ drm_radeon_texture_t tex;
+ drm_radeon_tex_image_t tmp;
+ int ret;
- if (rmesa->rmm->u_list[i].h_pending == 0 &&
- rmesa->rmm->u_list[i].pending
- && rmesa->rmm->u_list[i].age <= done_age) {
- memfree.region_offset =
- (char *)rmesa->rmm->u_list[i].ptr -
- (char *)rmesa->radeon.radeonScreen->gartTextures.
- map;
+ tex.offset = bo->base.base.offset;
+ tex.image = &tmp;
- ret =
- drmCommandWrite(rmesa->radeon.radeonScreen->
- driScreen->fd, DRM_RADEON_FREE,
- &memfree, sizeof(memfree));
+ assert(!(tex.offset & 1023));
+ tmp.x = 0;
+ tmp.y = 0;
+ if (bo->base.base.size < 4096) {
+ tmp.width = (bo->base.base.size + 3) / 4;
+ tmp.height = 1;
+ } else {
+ tmp.width = 1024;
+ tmp.height = (bo->base.base.size + 4095) / 4096;
+ }
+ tmp.data = bo->base.base.virtual;
+
+ tex.format = RADEON_TXFORMAT_ARGB8888;
+ tex.width = tmp.width;
+ tex.height = tmp.height;
+ tex.pitch = MAX2(tmp.width / 16, 1);
+
+ do {
+ ret = drmCommandWriteRead(bufmgr->rmesa->radeon.dri.fd,
+ DRM_RADEON_TEXTURE, &tex,
+ sizeof(drm_radeon_texture_t));
if (ret) {
- fprintf(stderr, "Failed to free at %p\n",
- rmesa->rmm->u_list[i].ptr);
- fprintf(stderr, "ret = %s\n", strerror(-ret));
- exit(1);
- } else {
-#ifdef MM_DEBUG
- fprintf(stderr, "really freed %d at age %x\n",
- i,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
- if (i == rmesa->rmm->u_last)
- rmesa->rmm->u_last--;
-
- if (rmesa->rmm->u_list[i].size < 4096)
- bytes_wasted -=
- 4096 - rmesa->rmm->u_list[i].size;
-
- allocated -= rmesa->rmm->u_list[i].size;
- rmesa->rmm->u_list[i].pending = 0;
- rmesa->rmm->u_list[i].ptr = NULL;
- free = i;
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr,
+ "DRM_RADEON_TEXTURE: again!\n");
+ usleep(1);
}
- }
+ } while (ret == -EAGAIN);
+
+ bo->backing_store_dirty = 0;
}
- rmesa->rmm->u_head = i;
-
- if (free == -1) {
- WARN_ONCE("Ran out of slots!\n");
- //usleep(100);
- r300FlushCmdBuf(rmesa, __FUNCTION__);
- tries++;
- if (tries > 100) {
- WARN_ONCE("Ran out of slots!\n");
- exit(1);
- }
- goto again;
+
+ bo->base.validated = 1;
+}
+
+static void vram_dirty(radeon_bo_classic *bo_base)
+{
+ radeon_bo_vram *bo = get_bo_vram(bo_base);
+
+ bo->base.validated = 0;
+ bo->backing_store_dirty = 1;
+}
+
+static void vram_bind(radeon_bo_classic *bo_base)
+{
+ radeon_bo_vram *bo = get_bo_vram(bo_base);
+
+ if (bo->vram) {
+ bo->vram->base.bound = 1;
+ driUpdateTextureLRU(&bo->vram->base);
}
+}
- alloc.region = RADEON_MEM_REGION_GART;
- alloc.alignment = alignment;
- alloc.size = size;
- alloc.region_offset = &offset;
+static void vram_unbind(radeon_bo_classic *bo_base)
+{
+ radeon_bo_vram *bo = get_bo_vram(bo_base);
- ret =
- drmCommandWriteRead(rmesa->radeon.dri.fd, DRM_RADEON_ALLOC, &alloc,
- sizeof(alloc));
- if (ret) {
-#if 0
- WARN_ONCE("Ran out of mem!\n");
- r300FlushCmdBuf(rmesa, __FUNCTION__);
- //usleep(100);
- tries2++;
- tries = 0;
- if (tries2 > 100) {
- WARN_ONCE("Ran out of GART memory!\n");
- exit(1);
- }
- goto again;
-#else
- WARN_ONCE
- ("Ran out of GART memory (for %d)!\nPlease consider adjusting GARTSize option.\n",
- size);
- return 0;
-#endif
+ if (bo->vram)
+ bo->vram->base.bound = 0;
+}
+
+/** Callback function called by the texture heap when a texture is evicted */
+static void destroy_vram_wrapper(void *data, driTextureObject *t)
+{
+ radeon_vram_wrapper *wrapper = (radeon_vram_wrapper*)t;
+
+ if (wrapper->bo && wrapper->bo->vram == wrapper) {
+ wrapper->bo->base.validated = 0;
+ wrapper->bo->vram = 0;
}
+}
- i = free;
+static const radeon_bo_functions vram_bo_functions = {
+ .free = vram_free,
+ .validate = vram_validate,
+ .dirty = vram_dirty,
+ .bind = vram_bind,
+ .unbind = vram_unbind
+};
- if (i > rmesa->rmm->u_last)
- rmesa->rmm->u_last = i;
+/**
+ * Free a VRAM-based buffer object.
+ */
+static void static_free(radeon_bo_classic *bo_base)
+{
+ radeon_bo_vram *bo = get_bo_vram(bo_base);
- rmesa->rmm->u_list[i].ptr =
- ((GLubyte *) rmesa->radeon.radeonScreen->gartTextures.map) + offset;
- rmesa->rmm->u_list[i].size = size;
- rmesa->rmm->u_list[i].age = 0;
- //fprintf(stderr, "alloc %p at id %d\n", rmesa->rmm->u_list[i].ptr, i);
+ free(bo);
+}
-#ifdef MM_DEBUG
- fprintf(stderr, "allocated %d at age %x\n", i,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
+static void static_bind(radeon_bo_classic *bo_base)
+{
+}
- return i;
+static void static_unbind(radeon_bo_classic *bo_base)
+{
}
-void r300_mem_use(r300ContextPtr rmesa, int id)
+static void static_validate(radeon_bo_classic *bo_base)
{
- uint64_t ull;
-#ifdef MM_DEBUG
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
- drm_r300_cmd_header_t *cmd;
+}
- assert(id <= rmesa->rmm->u_last);
+static void static_dirty(radeon_bo_classic *bo_base)
+{
+}
- if (id == 0)
- return;
+static const radeon_bo_functions static_bo_functions = {
+ .free = static_free,
+ .validate = static_validate,
+ .dirty = static_dirty,
+ .bind = static_bind,
+ .unbind = static_unbind
+};
- cmd =
- (drm_r300_cmd_header_t *) r300AllocCmdBuf(rmesa,
- 2 + sizeof(ull) / 4,
- __FUNCTION__);
- cmd[0].scratch.cmd_type = R300_CMD_SCRATCH;
- cmd[0].scratch.reg = R300_MEM_SCRATCH;
- cmd[0].scratch.n_bufs = 1;
- cmd[0].scratch.flags = 0;
- cmd++;
- ull = (uint64_t) (intptr_t) & rmesa->rmm->u_list[id].age;
- _mesa_memcpy(cmd, &ull, sizeof(ull));
- cmd += sizeof(ull) / 4;
+/**
+ * Allocate a backing store buffer object that is validated into VRAM.
+ */
+static dri_bo *vram_alloc(radeon_bufmgr_classic *bufmgr, const char *name,
+ unsigned long size, unsigned int alignment)
+{
+ radeon_bo_vram* bo = (radeon_bo_vram*)calloc(1, sizeof(radeon_bo_vram));
+
+ bo->base.functions = &vram_bo_functions;
+ bo->base.base.virtual = malloc(size);
+ init_buffer(bufmgr, &bo->base, size);
+ return &bo->base.base;
+}
- cmd[0].u = /*id */ 0;
- LOCK_HARDWARE(&rmesa->radeon); /* Protect from DRM. */
- rmesa->rmm->u_list[id].h_pending++;
- UNLOCK_HARDWARE(&rmesa->radeon);
+static dri_bo *bufmgr_classic_bo_alloc(dri_bufmgr *bufmgr_ctx, const char *name,
+ unsigned long size, unsigned int alignment,
+ uint64_t location_mask)
+{
+ radeon_bufmgr_classic* bufmgr = get_bufmgr_classic(bufmgr_ctx);
+
+ if (location_mask & DRM_BO_MEM_CMDBUF) {
+ return cmdbuf_alloc(bufmgr, name, size);
+ } else if (location_mask & DRM_BO_MEM_DMA) {
+ return dma_alloc(bufmgr, name, size, alignment);
+ } else {
+ return vram_alloc(bufmgr, name, size, alignment);
+ }
}
-unsigned long r300_mem_offset(r300ContextPtr rmesa, int id)
+static dri_bo *bufmgr_classic_bo_alloc_static(dri_bufmgr *bufmgr_ctx, const char *name,
+ unsigned long offset, unsigned long size,
+ void *virtual, uint64_t location_mask)
{
- unsigned long offset;
+ radeon_bufmgr_classic* bufmgr = get_bufmgr_classic(bufmgr_ctx);
+ radeon_bo_vram* bo = (radeon_bo_vram*)calloc(1, sizeof(radeon_bo_vram));
- assert(id <= rmesa->rmm->u_last);
+ bo->base.functions = &static_bo_functions;
+ bo->base.base.virtual = virtual;
+ bo->base.base.offset = offset + bufmgr->rmesa->radeon.radeonScreen->fbLocation;
+ bo->base.validated = 1; /* Static buffer offsets are always valid */
- offset = (char *)rmesa->rmm->u_list[id].ptr -
- (char *)rmesa->radeon.radeonScreen->gartTextures.map;
- offset += rmesa->radeon.radeonScreen->gart_texture_offset;
+ init_buffer(bufmgr, &bo->base, size);
+ return &bo->base.base;
- return offset;
}
-void *r300_mem_map(r300ContextPtr rmesa, int id, int access)
+
+
+static void bufmgr_classic_bo_reference(dri_bo *bo_base)
{
-#ifdef MM_DEBUG
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
- void *ptr;
- int tries = 0;
+ radeon_bo_classic *bo = get_bo_classic(bo_base);
+ bo->refcount++;
+ assert(bo->refcount > 0);
+}
- assert(id <= rmesa->rmm->u_last);
+static void bufmgr_classic_bo_unreference(dri_bo *bo_base)
+{
+ radeon_bo_classic *bo = get_bo_classic(bo_base);
- if (access == R300_MEM_R) {
+ if (!bo_base)
+ return;
- if (rmesa->rmm->u_list[id].mapped == 1)
- WARN_ONCE("buffer %d already mapped\n", id);
+ assert(bo->refcount > 0);
+ bo->refcount--;
+ if (!bo->refcount) {
+ // Ugly HACK - figure out whether this is really necessary
+ get_bufmgr_classic(bo_base->bufmgr)->rmesa->dma.nr_released_bufs++;
- rmesa->rmm->u_list[id].mapped = 1;
- ptr = r300_mem_ptr(rmesa, id);
+ assert(!bo->mapcount);
+ if (!bo->pending)
+ bo_free(bo);
+ }
+}
- return ptr;
+static int bufmgr_classic_bo_map(dri_bo *bo_base, GLboolean write_enable)
+{
+ radeon_bufmgr_classic *bufmgr = get_bufmgr_classic(bo_base->bufmgr);
+ radeon_bo_classic *bo = get_bo_classic(bo_base);
+ assert(bo->refcount > 0);
+
+ if (bo->pending) {
+ track_pending_buffers(bufmgr);
+ if (bo->pending) {
+ // TODO: Better fence waiting
+ if (RADEON_DEBUG & DEBUG_MEMORY)
+ fprintf(stderr, "bo_map: buffer is pending. Flushing...\n");
+ radeonFinish(bufmgr->rmesa->radeon.glCtx);
+ track_pending_buffers(bufmgr);
+ if (bo->pending) {
+ fprintf(stderr, "Internal error or hardware lockup: bo_map: buffer is still pending.\n");
+ abort();
+ }
+ }
}
- if (rmesa->rmm->u_list[id].h_pending)
- r300FlushCmdBuf(rmesa, __FUNCTION__);
+ if (write_enable && bo->functions->dirty)
+ bo->functions->dirty(bo);
- if (rmesa->rmm->u_list[id].h_pending) {
- return NULL;
- }
+ bo->mapcount++;
+ assert(bo->mapcount > 0);
+ return 0;
+}
- while (rmesa->rmm->u_list[id].age >
- radeonGetAge((radeonContextPtr) rmesa) && tries++ < 1000)
- usleep(10);
+static int bufmgr_classic_bo_unmap(dri_bo *buf)
+{
+ radeon_bo_classic *bo = get_bo_classic(buf);
+ assert(bo->refcount > 0);
+ assert(bo->mapcount > 0);
+ bo->mapcount--;
+ return 0;
+}
- if (tries >= 1000) {
- fprintf(stderr, "Idling failed (%x vs %x)\n",
- rmesa->rmm->u_list[id].age,
- radeonGetAge((radeonContextPtr) rmesa));
- return NULL;
+/**
+ * Mark the given buffer as pending and move it to the tail
+ * of the pending list.
+ * The caller is responsible for setting up pending_count and pending_age.
+ */
+static void move_to_pending_tail(radeon_bo_classic *bo)
+{
+ radeon_bufmgr_classic *bufmgr = get_bufmgr_classic(bo->base.bufmgr);
+
+ if (bo->pending) {
+ *bo->pending_pprev = bo->pending_next;
+ if (bo->pending_next)
+ bo->pending_next->pending_pprev = bo->pending_pprev;
+ else
+ bufmgr->pending_tail = bo->pending_pprev;
}
- if (rmesa->rmm->u_list[id].mapped == 1)
- WARN_ONCE("buffer %d already mapped\n", id);
+ bo->pending = 1;
+ bo->pending_pprev = bufmgr->pending_tail;
+ bo->pending_next = 0;
+ *bufmgr->pending_tail = bo;
+ bufmgr->pending_tail = &bo->pending_next;
+}
- rmesa->rmm->u_list[id].mapped = 1;
- ptr = r300_mem_ptr(rmesa, id);
+/**
+ * Emit commands to the batch buffer that cause the guven buffer's
+ * pending_count and pending_age to be updated.
+ */
+static void emit_age_for_buffer(radeon_bo_classic* bo)
+{
+ radeon_bufmgr_classic *bufmgr = get_bufmgr_classic(bo->base.bufmgr);
+ BATCH_LOCALS(bufmgr->rmesa);
+ drm_r300_cmd_header_t cmd;
+ uint64_t ull;
- return ptr;
+ cmd.scratch.cmd_type = R300_CMD_SCRATCH;
+ cmd.scratch.reg = 2; /* Scratch register 2 corresponds to what radeonGetAge polls */
+ cmd.scratch.n_bufs = 1;
+ cmd.scratch.flags = 0;
+ ull = (uint64_t) (intptr_t) &bo->pending_age;
+
+ BEGIN_BATCH(4);
+ OUT_BATCH(cmd.u);
+ OUT_BATCH(ull & 0xffffffff);
+ OUT_BATCH(ull >> 32);
+ OUT_BATCH(0);
+ END_BATCH();
+ COMMIT_BATCH();
+
+ bo->pending_count++;
}
-void r300_mem_unmap(r300ContextPtr rmesa, int id)
+static int bufmgr_classic_emit_reloc(dri_bo *batch_buf, uint64_t flags, GLuint delta,
+ GLuint offset, dri_bo *target)
{
-#ifdef MM_DEBUG
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
+ radeon_bo_classic *bo = get_bo_classic(batch_buf);
+ radeon_reloc *reloc;
- assert(id <= rmesa->rmm->u_last);
+ if (bo->relocs_used >= bo->relocs_size) {
+ bo->relocs_size *= 2;
+ if (bo->relocs_size < 32)
+ bo->relocs_size = 32;
- if (rmesa->rmm->u_list[id].mapped == 0)
- WARN_ONCE("buffer %d not mapped\n", id);
+ bo->relocs = (radeon_reloc*)realloc(bo->relocs, bo->relocs_size*sizeof(radeon_reloc));
+ }
- rmesa->rmm->u_list[id].mapped = 0;
+ reloc = &bo->relocs[bo->relocs_used++];
+ reloc->flags = flags;
+ reloc->offset = offset;
+ reloc->delta = delta;
+ reloc->target = get_bo_classic(target);
+ dri_bo_reference(target);
+ return 0;
}
-void r300_mem_free(r300ContextPtr rmesa, int id)
+/* process_relocs is called just before the given command buffer
+ * is executed. It ensures that all referenced buffers are in
+ * the right GPU domain.
+ */
+static void *bufmgr_classic_process_relocs(dri_bo *batch_buf, GLuint *count)
{
-#ifdef MM_DEBUG
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
+ radeon_bo_classic *batch_bo = get_bo_classic(batch_buf);
+ int i;
- assert(id <= rmesa->rmm->u_last);
+ // Warning: At this point, we append something to the batch buffer
+ // during flush.
+ emit_age_for_buffer(batch_bo);
+
+ dri_bo_map(batch_buf, GL_TRUE);
+ for(i = 0; i < batch_bo->relocs_used; ++i) {
+ radeon_reloc *reloc = &batch_bo->relocs[i];
+ uint32_t *dest = (uint32_t*)((char*)batch_buf->virtual + reloc->offset);
+ uint32_t offset;
+
+ if (!reloc->target->validated)
+ reloc->target->functions->validate(reloc->target);
+ reloc->target->used = 1;
+ offset = reloc->target->base.offset + reloc->delta;
+
+ if (reloc->flags & DRM_RELOC_BLITTER)
+ *dest = (*dest & 0xffc00000) | (offset >> 10);
+ else if (reloc->flags & DRM_RELOC_TXOFFSET)
+ *dest = (*dest & 31) | (offset & ~31);
+ else
+ *dest = offset;
+ }
+ dri_bo_unmap(batch_buf);
+ return 0;
+}
- if (id == 0)
- return;
+/* post_submit is called just after the given command buffer
+ * is executed. It ensures that buffers are properly marked as
+ * pending.
+ */
+static void bufmgr_classic_post_submit(dri_bo *batch_buf, dri_fence **fence)
+{
+ radeon_bo_classic *batch_bo = get_bo_classic(batch_buf);
+ int i;
- if (rmesa->rmm->u_list[id].ptr == NULL) {
- WARN_ONCE("Not allocated!\n");
- return;
+ assert(!batch_bo->pending_count);
+
+ for(i = 0; i < batch_bo->relocs_used; ++i) {
+ radeon_reloc *reloc = &batch_bo->relocs[i];
+
+ if (reloc->target->used) {
+ reloc->target->used = 0;
+ assert(!reloc->target->pending_count);
+ reloc->target->pending_age = batch_bo->pending_age;
+ move_to_pending_tail(reloc->target);
+ if (reloc->target->functions->bind)
+ (*reloc->target->functions->bind)(reloc->target);
+ }
}
+}
- if (rmesa->rmm->u_list[id].pending) {
- WARN_ONCE("%p already pended!\n", rmesa->rmm->u_list[id].ptr);
- return;
+static void bufmgr_classic_destroy(dri_bufmgr *bufmgr_ctx)
+{
+ radeon_bufmgr_classic* bufmgr = get_bufmgr_classic(bufmgr_ctx);
+
+ track_pending_buffers(bufmgr);
+ if (bufmgr->pending)
+ radeonFinish(bufmgr->rmesa->radeon.glCtx);
+ track_pending_buffers(bufmgr);
+
+ if (bufmgr->buffers) {
+ fprintf(stderr, "Warning: Buffer objects have leaked\n");
+ while(bufmgr->buffers) {
+ fprintf(stderr, " Leak of size %ld\n", bufmgr->buffers->base.size);
+ bufmgr->buffers->refcount = 0;
+ bufmgr->buffers->mapcount = 0;
+ bufmgr->buffers->pending = 0;
+ bo_free(bufmgr->buffers);
+ }
}
- rmesa->rmm->u_list[id].pending = 1;
+ driDestroyTextureHeap(bufmgr->texture_heap);
+ bufmgr->texture_heap = 0;
+ assert(is_empty_list(&bufmgr->texture_swapped));
+
+ free(bufmgr);
+}
+
+radeon_bufmgr* radeonBufmgrClassicInit(r300ContextPtr rmesa)
+{
+ radeon_bufmgr_classic* bufmgr = (radeon_bufmgr_classic*)calloc(1, sizeof(radeon_bufmgr_classic));
+
+ bufmgr->rmesa = rmesa;
+ bufmgr->base.base.bo_alloc = &bufmgr_classic_bo_alloc;
+ bufmgr->base.base.bo_alloc_static = bufmgr_classic_bo_alloc_static;
+ bufmgr->base.base.bo_reference = &bufmgr_classic_bo_reference;
+ bufmgr->base.base.bo_unreference = &bufmgr_classic_bo_unreference;
+ bufmgr->base.base.bo_map = &bufmgr_classic_bo_map;
+ bufmgr->base.base.bo_unmap = &bufmgr_classic_bo_unmap;
+ bufmgr->base.base.emit_reloc = &bufmgr_classic_emit_reloc;
+ bufmgr->base.base.process_relocs = &bufmgr_classic_process_relocs;
+ bufmgr->base.base.post_submit = &bufmgr_classic_post_submit;
+ bufmgr->base.base.destroy = &bufmgr_classic_destroy;
+
+ bufmgr->pending_tail = &bufmgr->pending;
+
+ /* Init texture heap */
+ make_empty_list(&bufmgr->texture_swapped);
+ bufmgr->texture_heap = driCreateTextureHeap(0, bufmgr,
+ rmesa->radeon.radeonScreen->texSize[0], 12, RADEON_NR_TEX_REGIONS,
+ (drmTextureRegionPtr)rmesa->radeon.sarea->tex_list[0],
+ &rmesa->radeon.sarea->tex_age[0],
+ &bufmgr->texture_swapped, sizeof(radeon_vram_wrapper),
+ &destroy_vram_wrapper);
+ bufmgr->texture_offset = rmesa->radeon.radeonScreen->texOffset[0];
+
+ return &bufmgr->base;
+}
+
+void radeonBufmgrContendedLockTake(radeon_bufmgr* bufmgr_ctx)
+{
+ radeon_bufmgr_classic *bufmgr = get_bufmgr_classic(&bufmgr_ctx->base);
+
+ DRI_AGE_TEXTURES(bufmgr->texture_heap);
}
-#endif
diff --git a/src/mesa/drivers/dri/r300/r300_mem.h b/src/mesa/drivers/dri/r300/r300_mem.h
index 625a7f6..4e9be65 100644
--- a/src/mesa/drivers/dri/r300/r300_mem.h
+++ b/src/mesa/drivers/dri/r300/r300_mem.h
@@ -1,37 +1,22 @@
#ifndef __R300_MEM_H__
#define __R300_MEM_H__
-//#define R300_MEM_PDL 0
-#define R300_MEM_UL 1
+#include "glheader.h"
+#include "dri_bufmgr.h"
-#define R300_MEM_R 1
-#define R300_MEM_W 2
-#define R300_MEM_RW (R300_MEM_R | R300_MEM_W)
+#include "r300_context.h"
-#define R300_MEM_SCRATCH 2
-struct r300_memory_manager {
- struct {
- void *ptr;
- uint32_t size;
- uint32_t age;
- uint32_t h_pending;
- int pending;
- int mapped;
- } *u_list;
- int u_head, u_size, u_last;
+/* Note: The following flags should probably be ultimately eliminated,
+ * or replaced by something else.
+ */
+#define DRM_BO_MEM_DMA (1 << 27) /** Use for transient buffers (texture upload, vertex buffers...) */
+#define DRM_BO_MEM_CMDBUF (1 << 28) /** Use for command buffers */
-};
+#define DRM_RELOC_BLITTER (1 << 23) /** Offset overwrites lower 22 bits (used with blit packet3) */
+#define DRM_RELOC_TXOFFSET (1 << 24) /** Offset overwrites everything but low bits (used for texture offsets) */
-extern void r300_mem_init(r300ContextPtr rmesa);
-extern void r300_mem_destroy(r300ContextPtr rmesa);
-extern void *r300_mem_ptr(r300ContextPtr rmesa, int id);
-extern int r300_mem_find(r300ContextPtr rmesa, void *ptr);
-extern int r300_mem_alloc(r300ContextPtr rmesa, int alignment, int size);
-extern void r300_mem_use(r300ContextPtr rmesa, int id);
-extern unsigned long r300_mem_offset(r300ContextPtr rmesa, int id);
-extern void *r300_mem_map(r300ContextPtr rmesa, int id, int access);
-extern void r300_mem_unmap(r300ContextPtr rmesa, int id);
-extern void r300_mem_free(r300ContextPtr rmesa, int id);
+radeon_bufmgr* radeonBufmgrClassicInit(r300ContextPtr rmesa);
+void radeonBufmgrContendedLockTake(radeon_bufmgr* bufmgr_ctx);
#endif
diff --git a/src/mesa/drivers/dri/r300/r300_mipmap_tree.c b/src/mesa/drivers/dri/r300/r300_mipmap_tree.c
new file mode 100644
index 0000000..c3b918c
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/r300_mipmap_tree.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2008 Nicolai Haehnle.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "r300_mipmap_tree.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "simple_list.h"
+#include "texcompress.h"
+#include "texformat.h"
+
+#include "r300_mem.h"
+
+static GLuint r300_compressed_texture_size(GLcontext *ctx,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLuint mesaFormat)
+{
+ GLuint size = _mesa_compressed_texture_size(ctx, width, height, depth, mesaFormat);
+
+ if (mesaFormat == MESA_FORMAT_RGB_DXT1 ||
+ mesaFormat == MESA_FORMAT_RGBA_DXT1) {
+ if (width + 3 < 8) /* width one block */
+ size = size * 4;
+ else if (width + 3 < 16)
+ size = size * 2;
+ } else {
+ /* DXT3/5, 16 bytes per block */
+ WARN_ONCE("DXT 3/5 suffers from multitexturing problems!\n");
+ if (width + 3 < 8)
+ size = size * 2;
+ }
+
+ return size;
+}
+
+/**
+ * Compute sizes and fill in offset and blit information for the given
+ * image (determined by \p face and \p level).
+ *
+ * \param curOffset points to the offset at which the image is to be stored
+ * and is updated by this function according to the size of the image.
+ */
+static void compute_tex_image_offset(r300_mipmap_tree *mt,
+ GLuint face, GLuint level, GLuint* curOffset)
+{
+ r300_mipmap_level *lvl = &mt->levels[level];
+
+ /* Find image size in bytes */
+ if (mt->compressed) {
+ lvl->size = r300_compressed_texture_size(mt->r300->radeon.glCtx,
+ lvl->width, lvl->height, lvl->depth, mt->compressed);
+ } else if (mt->target == GL_TEXTURE_RECTANGLE_NV) {
+ lvl->size = ((lvl->width * mt->bpp + 63) & ~63) * lvl->height;
+ } else if (mt->tilebits & R300_TXO_MICRO_TILE) {
+ /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
+ * though the actual offset may be different (if texture is less than
+ * 32 bytes width) to the untiled case */
+ int w = (lvl->width * mt->bpp * 2 + 31) & ~31;
+ lvl->size = (w * ((lvl->height + 1) / 2)) * lvl->depth;
+ } else {
+ int w = (lvl->width * mt->bpp + 31) & ~31;
+ lvl->size = w * lvl->height * lvl->depth;
+ }
+ assert(lvl->size > 0);
+
+ /* All images are aligned to a 32-byte offset */
+ *curOffset = (*curOffset + 0x1f) & ~0x1f;
+ lvl->faces[face].offset = *curOffset;
+ *curOffset += lvl->size;
+}
+
+static GLuint minify(GLuint size, GLuint levels)
+{
+ size = size >> levels;
+ if (size < 1)
+ size = 1;
+ return size;
+}
+
+static void calculate_miptree_layout(r300_mipmap_tree *mt)
+{
+ GLuint curOffset;
+ GLuint numLevels;
+ GLuint i;
+
+ numLevels = mt->lastLevel - mt->firstLevel + 1;
+ assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
+
+ curOffset = 0;
+ for(i = 0; i < numLevels; i++) {
+ GLuint face;
+
+ mt->levels[i].width = minify(mt->width0, mt->firstLevel + i);
+ mt->levels[i].height = minify(mt->height0, mt->firstLevel + i);
+ mt->levels[i].depth = minify(mt->depth0, mt->firstLevel + i);
+
+ for(face = 0; face < mt->faces; face++)
+ compute_tex_image_offset(mt, face, i, &curOffset);
+ }
+
+ /* Note the required size in memory */
+ mt->totalsize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
+}
+
+
+/**
+ * Create a new mipmap tree, calculate its layout and allocate memory.
+ */
+r300_mipmap_tree* r300_miptree_create(r300ContextPtr rmesa, r300TexObj *t,
+ GLenum target, GLuint firstLevel, GLuint lastLevel,
+ GLuint width0, GLuint height0, GLuint depth0,
+ GLuint bpp, GLuint tilebits, GLuint compressed)
+{
+ r300_mipmap_tree *mt = CALLOC_STRUCT(_r300_mipmap_tree);
+
+ mt->r300 = rmesa;
+ mt->t = t;
+ mt->target = target;
+ mt->faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ mt->firstLevel = firstLevel;
+ mt->lastLevel = lastLevel;
+ mt->width0 = width0;
+ mt->height0 = height0;
+ mt->depth0 = depth0;
+ mt->bpp = bpp;
+ mt->tilebits = tilebits;
+ mt->compressed = compressed;
+
+ calculate_miptree_layout(mt);
+
+ mt->bo = dri_bo_alloc(&rmesa->radeon.bufmgr->base, "texture", mt->totalsize, 1024, 0);
+
+ return mt;
+}
+
+/**
+ * Destroy the given mipmap tree.
+ */
+void r300_miptree_destroy(r300_mipmap_tree *mt)
+{
+ dri_bo_unreference(mt->bo);
+ free(mt);
+}
+
+/*
+ * XXX Move this into core Mesa?
+ */
+static void
+_mesa_copy_rect(GLubyte * dst,
+ GLuint cpp,
+ GLuint dst_pitch,
+ GLuint dst_x,
+ GLuint dst_y,
+ GLuint width,
+ GLuint height,
+ const GLubyte * src,
+ GLuint src_pitch, GLuint src_x, GLuint src_y)
+{
+ GLuint i;
+
+ dst_pitch *= cpp;
+ src_pitch *= cpp;
+ dst += dst_x * cpp;
+ src += src_x * cpp;
+ dst += dst_y * dst_pitch;
+ src += src_y * dst_pitch;
+ width *= cpp;
+
+ if (width == dst_pitch && width == src_pitch)
+ memcpy(dst, src, height * width);
+ else {
+ for (i = 0; i < height; i++) {
+ memcpy(dst, src, width);
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+ }
+}
+
+/**
+ * Upload the given texture image to the given face/level of the mipmap tree.
+ * \param level of the texture, i.e. \c level==mt->firstLevel is the first hw level
+ */
+void r300_miptree_upload_image(r300_mipmap_tree *mt, GLuint face, GLuint level,
+ struct gl_texture_image *texImage)
+{
+ GLuint hwlevel = level - mt->firstLevel;
+ r300_mipmap_level *lvl = &mt->levels[hwlevel];
+ void *dest;
+
+ assert(face < mt->faces);
+ assert(level >= mt->firstLevel && level <= mt->lastLevel);
+ assert(texImage && texImage->Data);
+ assert(texImage->Width == lvl->width);
+ assert(texImage->Height == lvl->height);
+ assert(texImage->Depth == lvl->depth);
+
+ dri_bo_map(mt->bo, GL_TRUE);
+
+ dest = mt->bo->virtual + lvl->faces[face].offset;
+
+ if (mt->tilebits)
+ WARN_ONCE("%s: tiling not supported yet", __FUNCTION__);
+
+ if (!mt->compressed) {
+ GLuint dst_align;
+ GLuint dst_pitch = lvl->width;
+ GLuint src_pitch = lvl->width;
+
+ if (mt->target == GL_TEXTURE_RECTANGLE_NV)
+ dst_align = 64 / mt->bpp;
+ else
+ dst_align = 32 / mt->bpp;
+ dst_pitch = (dst_pitch + dst_align - 1) & ~(dst_align - 1);
+
+ _mesa_copy_rect(dest, mt->bpp, dst_pitch, 0, 0, lvl->width, lvl->height,
+ texImage->Data, src_pitch, 0, 0);
+ } else {
+ memcpy(dest, texImage->Data, lvl->size);
+ }
+
+ dri_bo_unmap(mt->bo);
+}
diff --git a/src/mesa/drivers/dri/r300/r300_mipmap_tree.h b/src/mesa/drivers/dri/r300/r300_mipmap_tree.h
new file mode 100644
index 0000000..a888ecf
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/r300_mipmap_tree.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2008 Nicolai Haehnle.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __R300_MIPMAP_TREE_H_
+#define __R300_MIPMAP_TREE_H_
+
+#include "r300_context.h"
+
+typedef struct _r300_mipmap_tree r300_mipmap_tree;
+typedef struct _r300_mipmap_level r300_mipmap_level;
+typedef struct _r300_mipmap_image r300_mipmap_image;
+
+struct _r300_mipmap_image {
+ GLuint offset; /** Offset of this image from the start of mipmap tree, in bytes */
+};
+
+struct _r300_mipmap_level {
+ GLuint width;
+ GLuint height;
+ GLuint depth;
+ GLuint size; /** Size of each image, in bytes */
+ r300_mipmap_image faces[6];
+};
+
+
+/**
+ * A mipmap tree contains texture images in the layout that the hardware
+ * expects.
+ *
+ * The meta-data of mipmap trees is immutable, i.e. you cannot change the
+ * layout on-the-fly; however, the texture contents (i.e. texels) can be
+ * changed.
+ */
+struct _r300_mipmap_tree {
+ r300ContextPtr r300;
+ r300TexObj *t;
+ dri_bo *bo;
+
+ GLuint totalsize; /** total size of the miptree, in bytes */
+
+ GLenum target; /** GL_TEXTURE_xxx */
+ GLuint faces; /** # of faces: 6 for cubemaps, 1 otherwise */
+ GLuint firstLevel; /** First mip level stored in this mipmap tree */
+ GLuint lastLevel; /** Last mip level stored in this mipmap tree */
+
+ GLuint width0; /** Width of level 0 image */
+ GLuint height0; /** Height of level 0 image */
+ GLuint depth0; /** Depth of level 0 image */
+
+ GLuint bpp; /** Bytes per texel */
+ GLuint tilebits; /** R300_TXO_xxx_TILE */
+ GLuint compressed; /** MESA_FORMAT_xxx indicating a compressed format, or 0 if uncompressed */
+
+ r300_mipmap_level levels[RADEON_MAX_TEXTURE_LEVELS];
+};
+
+r300_mipmap_tree* r300_miptree_create(r300ContextPtr rmesa, r300TexObj *t,
+ GLenum target, GLuint firstLevel, GLuint lastLevel,
+ GLuint width0, GLuint height0, GLuint depth0,
+ GLuint bpp, GLuint tilebits, GLuint compressed);
+void r300_miptree_destroy(r300_mipmap_tree *mt);
+
+void r300_miptree_upload_image(r300_mipmap_tree *mt, GLuint face, GLuint level,
+ struct gl_texture_image *texImage);
+
+
+#endif /* __R300_MIPMAP_TREE_H_ */
diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c
index 0a199e6..209fae9 100644
--- a/src/mesa/drivers/dri/r300/r300_render.c
+++ b/src/mesa/drivers/dri/r300/r300_render.c
@@ -175,89 +175,79 @@ int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim)
static void r300EmitElts(GLcontext * ctx, void *elts, unsigned long n_elts)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct r300_dma_region *rvb = &rmesa->state.elt_dma;
void *out;
- if (r300IsGartMemory(rmesa, elts, n_elts * 4)) {
- rvb->address = rmesa->radeon.radeonScreen->gartTextures.map;
- rvb->start = ((char *)elts) - rvb->address;
- rvb->aos_offset =
- rmesa->radeon.radeonScreen->gart_texture_offset +
- rvb->start;
- return;
- } else if (r300IsGartMemory(rmesa, elts, 1)) {
- WARN_ONCE("Pointer not within GART memory!\n");
- _mesa_exit(-1);
- }
-
- r300AllocDmaRegion(rmesa, rvb, n_elts * 4, 4);
- rvb->aos_offset = GET_START(rvb);
+ r300AllocDmaRegion(rmesa, &rmesa->state.elt_dma_bo, &rmesa->state.elt_dma_offset,
+ n_elts * 4, 4);
- out = rvb->address + rvb->start;
+ out = rmesa->state.elt_dma_bo->virtual + rmesa->state.elt_dma_offset;
memcpy(out, elts, n_elts * 4);
}
-static void r300FireEB(r300ContextPtr rmesa, unsigned long addr,
- int vertex_count, int type)
+static void r300FireEB(r300ContextPtr rmesa, int vertex_count, int type)
{
- int cmd_reserved = 0;
- int cmd_written = 0;
- drm_radeon_cmd_header_t *cmd = NULL;
+ BATCH_LOCALS(rmesa);
- start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_INDX_2, 0), 0);
- e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count << 16) | type | R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
+ BEGIN_BATCH(8);
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_INDX_2, 0);
+ OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count << 16) | type | R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
- start_packet3(CP_PACKET3(R300_PACKET3_INDX_BUFFER, 2), 2);
- e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
- e32(addr);
- e32(vertex_count);
+ OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER, 2);
+ OUT_BATCH(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
+ OUT_BATCH_RELOC(0, rmesa->state.elt_dma_bo, rmesa->state.elt_dma_offset, 0);
+ OUT_BATCH(vertex_count);
+ END_BATCH();
}
static void r300EmitAOS(r300ContextPtr rmesa, GLuint nr, GLuint offset)
{
+ BATCH_LOCALS(rmesa);
int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
int i;
- int cmd_reserved = 0;
- int cmd_written = 0;
- drm_radeon_cmd_header_t *cmd = NULL;
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__, nr,
offset);
- start_packet3(CP_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1), sz - 1);
- e32(nr);
+ BEGIN_BATCH(sz+2);
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1);
+ OUT_BATCH(nr);
for (i = 0; i + 1 < nr; i += 2) {
- e32((rmesa->state.aos[i].aos_size << 0) |
- (rmesa->state.aos[i].aos_stride << 8) |
- (rmesa->state.aos[i + 1].aos_size << 16) |
- (rmesa->state.aos[i + 1].aos_stride << 24));
-
- e32(rmesa->state.aos[i].aos_offset + offset * 4 * rmesa->state.aos[i].aos_stride);
- e32(rmesa->state.aos[i + 1].aos_offset + offset * 4 * rmesa->state.aos[i + 1].aos_stride);
+ OUT_BATCH((rmesa->state.aos[i].components << 0) |
+ (rmesa->state.aos[i].stride << 8) |
+ (rmesa->state.aos[i + 1].components << 16) |
+ (rmesa->state.aos[i + 1].stride << 24));
+
+ OUT_BATCH_RELOC(0, rmesa->state.aos[i].bo,
+ rmesa->state.aos[i].offset + offset * 4 * rmesa->state.aos[i].stride, 0);
+ OUT_BATCH_RELOC(0, rmesa->state.aos[i+1].bo,
+ rmesa->state.aos[i+1].offset + offset * 4 * rmesa->state.aos[i + 1].stride, 0);
}
if (nr & 1) {
- e32((rmesa->state.aos[nr - 1].aos_size << 0) |
- (rmesa->state.aos[nr - 1].aos_stride << 8));
- e32(rmesa->state.aos[nr - 1].aos_offset + offset * 4 * rmesa->state.aos[nr - 1].aos_stride);
+ OUT_BATCH((rmesa->state.aos[nr - 1].components << 0) |
+ (rmesa->state.aos[nr - 1].stride << 8));
+ OUT_BATCH_RELOC(0, rmesa->state.aos[nr - 1].bo,
+ rmesa->state.aos[nr - 1].offset + offset * 4 * rmesa->state.aos[nr - 1].stride, 0);
}
+ END_BATCH();
}
static void r300FireAOS(r300ContextPtr rmesa, int vertex_count, int type)
{
- int cmd_reserved = 0;
- int cmd_written = 0;
- drm_radeon_cmd_header_t *cmd = NULL;
+ BATCH_LOCALS(rmesa);
- start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0), 0);
- e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (vertex_count << 16) | type);
+ BEGIN_BATCH(3);
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
+ OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (vertex_count << 16) | type);
+ END_BATCH();
}
static void r300RunRenderPrimitive(r300ContextPtr rmesa, GLcontext * ctx,
int start, int end, int prim)
{
+ BATCH_LOCALS(rmesa);
int type, num_verts;
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *vb = &tnl->vb;
@@ -268,6 +258,12 @@ static void r300RunRenderPrimitive(r300ContextPtr rmesa, GLcontext * ctx,
if (type < 0 || num_verts <= 0)
return;
+ /* Make space for at least 64 dwords.
+ * This is supposed to ensure that we can get all rendering
+ * commands into a single command buffer.
+ */
+ r300EnsureCmdBufSpace(rmesa, 64, __FUNCTION__);
+
if (vb->Elts) {
if (num_verts > 65535) {
/* not implemented yet */
@@ -287,11 +283,12 @@ static void r300RunRenderPrimitive(r300ContextPtr rmesa, GLcontext * ctx,
*/
r300EmitElts(ctx, vb->Elts, num_verts);
r300EmitAOS(rmesa, rmesa->state.aos_count, start);
- r300FireEB(rmesa, rmesa->state.elt_dma.aos_offset, num_verts, type);
+ r300FireEB(rmesa, num_verts, type);
} else {
r300EmitAOS(rmesa, rmesa->state.aos_count, start);
r300FireAOS(rmesa, num_verts, type);
}
+ COMMIT_BATCH();
}
static GLboolean r300RunRender(GLcontext * ctx,
@@ -324,10 +321,6 @@ static GLboolean r300RunRender(GLcontext * ctx,
r300EmitCacheFlush(rmesa);
-#ifdef USER_BUFFERS
- r300UseArrays(ctx);
-#endif
-
r300ReleaseArrays(ctx);
return GL_FALSE;
diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c
index cce07d3..b314764 100644
--- a/src/mesa/drivers/dri/r300/r300_state.c
+++ b/src/mesa/drivers/dri/r300/r300_state.c
@@ -55,6 +55,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_ioctl.h"
#include "radeon_state.h"
+#include "radeon_buffer.h"
#include "r300_context.h"
#include "r300_ioctl.h"
#include "r300_state.h"
@@ -1148,39 +1149,25 @@ void r300UpdateDrawBuffer(GLcontext * ctx)
r300ContextPtr rmesa = R300_CONTEXT(ctx);
r300ContextPtr r300 = rmesa;
struct gl_framebuffer *fb = ctx->DrawBuffer;
- driRenderbuffer *drb;
+ struct radeon_renderbuffer *rrb;
if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
/* draw to front */
- drb =
- (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].
- Renderbuffer;
+ rrb =
+ (void *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
} else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
/* draw to back */
- drb =
- (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].
- Renderbuffer;
+ rrb = (void *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
} else {
/* drawing to multiple buffers, or none */
return;
}
- assert(drb);
- assert(drb->flippedPitch);
+ assert(rrb);
+ assert(rrb->pitch);
R300_STATECHANGE(rmesa, cb);
- r300->hw.cb.cmd[R300_CB_OFFSET] = drb->flippedOffset + //r300->radeon.state.color.drawOffset +
- r300->radeon.radeonScreen->fbLocation;
- r300->hw.cb.cmd[R300_CB_PITCH] = drb->flippedPitch; //r300->radeon.state.color.drawPitch;
-
- if (r300->radeon.radeonScreen->cpp == 4)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_ARGB8888;
- else
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_RGB565;
-
- if (r300->radeon.sarea->tiling_enabled)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_TILE_ENABLE;
#if 0
R200_STATECHANGE(rmesa, ctx);
@@ -1499,14 +1486,9 @@ static void r300SetupTextures(GLcontext * ctx)
/* We cannot let disabled tmu offsets pass DRM */
for (i = 0; i < mtu; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled) {
-
-#if 0 /* Enables old behaviour */
- hw_tmu = i;
-#endif
tmu_mappings[i] = hw_tmu;
- t = r300->state.texture.unit[i].texobj;
- /* XXX questionable fix for bug 9170: */
+ t = r300_tex_obj(ctx->Texture.Unit[i]._Current);
if (!t)
continue;
@@ -1532,21 +1514,20 @@ static void r300SetupTextures(GLcontext * ctx)
*/
r300->hw.tex.filter_1.cmd[R300_TEX_VALUE_0 + hw_tmu] =
t->filter_1 |
- translate_lod_bias(ctx->Texture.Unit[i].LodBias + t->base.tObj->LodBias);
+ translate_lod_bias(ctx->Texture.Unit[i].LodBias + t->base.LodBias);
r300->hw.tex.size.cmd[R300_TEX_VALUE_0 + hw_tmu] =
t->size;
r300->hw.tex.format.cmd[R300_TEX_VALUE_0 +
hw_tmu] = t->format;
r300->hw.tex.pitch.cmd[R300_TEX_VALUE_0 + hw_tmu] =
t->pitch_reg;
- r300->hw.tex.offset.cmd[R300_TEX_VALUE_0 +
- hw_tmu] = t->offset;
+ r300->hw.textures[hw_tmu] = t;
- if (t->offset & R300_TXO_MACRO_TILE) {
+ if (t->tile_bits & R300_TXO_MACRO_TILE) {
WARN_ONCE("macro tiling enabled!\n");
}
- if (t->offset & R300_TXO_MICRO_TILE) {
+ if (t->tile_bits & R300_TXO_MICRO_TILE) {
WARN_ONCE("micro tiling enabled!\n");
}
@@ -2373,20 +2354,6 @@ static void r300ResetHwState(r300ContextPtr r300)
r300BlendColor(ctx, ctx->Color.BlendColor);
- /* Again, r300ClearBuffer uses this */
- r300->hw.cb.cmd[R300_CB_OFFSET] =
- r300->radeon.state.color.drawOffset +
- r300->radeon.radeonScreen->fbLocation;
- r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.state.color.drawPitch;
-
- if (r300->radeon.radeonScreen->cpp == 4)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_ARGB8888;
- else
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_RGB565;
-
- if (r300->radeon.sarea->tiling_enabled)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_TILE_ENABLE;
-
r300->hw.rb3d_dither_ctl.cmd[1] = 0;
r300->hw.rb3d_dither_ctl.cmd[2] = 0;
r300->hw.rb3d_dither_ctl.cmd[3] = 0;
@@ -2402,10 +2369,6 @@ static void r300ResetHwState(r300ContextPtr r300)
r300->hw.rb3d_discard_src_pixel_lte_threshold.cmd[1] = 0x00000000;
r300->hw.rb3d_discard_src_pixel_lte_threshold.cmd[2] = 0xffffffff;
- r300->hw.zb.cmd[R300_ZB_OFFSET] =
- r300->radeon.radeonScreen->depthOffset +
- r300->radeon.radeonScreen->fbLocation;
- r300->hw.zb.cmd[R300_ZB_PITCH] = r300->radeon.radeonScreen->depthPitch;
if (r300->radeon.sarea->tiling_enabled) {
/* XXX: Turn off when clearing buffers ? */
diff --git a/src/mesa/drivers/dri/r300/r300_state.h b/src/mesa/drivers/dri/r300/r300_state.h
index 0589ab7..96177ba 100644
--- a/src/mesa/drivers/dri/r300/r300_state.h
+++ b/src/mesa/drivers/dri/r300/r300_state.h
@@ -59,7 +59,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R300_FIREVERTICES( r300 ) \
do { \
\
- if ( (r300)->cmdbuf.count_used || (r300)->dma.flush ) { \
+ if ( (r300)->cmdbuf.committed || (r300)->dma.flush ) { \
r300Flush( (r300)->radeon.glCtx ); \
} \
\
diff --git a/src/mesa/drivers/dri/r300/r300_swtcl.c b/src/mesa/drivers/dri/r300/r300_swtcl.c
index 8aebd9b..f4a0b7f 100644
--- a/src/mesa/drivers/dri/r300/r300_swtcl.c
+++ b/src/mesa/drivers/dri/r300/r300_swtcl.c
@@ -61,7 +61,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
static void flush_last_swtcl_prim( r300ContextPtr rmesa );
-void r300EmitVertexAOS(r300ContextPtr rmesa, GLuint vertex_size, GLuint offset);
+void r300EmitVertexAOS(r300ContextPtr rmesa, GLuint vertex_size, dri_bo *bo, GLuint offset);
void r300EmitVbufPrim(r300ContextPtr rmesa, GLuint primitive, GLuint vertex_nr);
#define EMIT_ATTR( ATTR, STYLE ) \
do { \
@@ -175,7 +175,7 @@ static void r300SetVertexFormat( GLcontext *ctx )
inputs[i] = -1;
}
}
-
+
/* Fixed, apply to vir0 only */
if (InputsRead & (1 << VERT_ATTRIB_POS))
inputs[VERT_ATTRIB_POS] = 0;
@@ -186,16 +186,16 @@ static void r300SetVertexFormat( GLcontext *ctx )
for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++)
if (InputsRead & (1 << i))
inputs[i] = 6 + (i - VERT_ATTRIB_TEX0);
-
+
for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) {
if (InputsRead & (1 << i)) {
tab[nr++] = i;
}
}
-
+
for (i = 0; i < nr; i++) {
int ci;
-
+
swizzle[i][0] = SWIZZLE_ZERO;
swizzle[i][1] = SWIZZLE_ZERO;
swizzle[i][2] = SWIZZLE_ZERO;
@@ -215,21 +215,21 @@ static void r300SetVertexFormat( GLcontext *ctx )
((drm_r300_cmd_header_t *) rmesa->hw.vir[1].cmd)->packet0.count =
r300VAPInputRoute1(&rmesa->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle,
nr);
-
+
R300_STATECHANGE(rmesa, vic);
rmesa->hw.vic.cmd[R300_VIC_CNTL_0] = r300VAPInputCntl0(ctx, InputsRead);
rmesa->hw.vic.cmd[R300_VIC_CNTL_1] = r300VAPInputCntl1(ctx, InputsRead);
-
+
R300_STATECHANGE(rmesa, vof);
rmesa->hw.vof.cmd[R300_VOF_CNTL_0] = r300VAPOutputCntl0(ctx, OutputsWritten);
rmesa->hw.vof.cmd[R300_VOF_CNTL_1] = vap_fmt_1;
-
+
rmesa->swtcl.vertex_size =
_tnl_install_attrs( ctx,
- rmesa->swtcl.vertex_attrs,
+ rmesa->swtcl.vertex_attrs,
rmesa->swtcl.vertex_attr_count,
NULL, 0 );
-
+
rmesa->swtcl.vertex_size /= 4;
RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset );
@@ -245,38 +245,40 @@ static void r300SetVertexFormat( GLcontext *ctx )
*/
static void flush_last_swtcl_prim( r300ContextPtr rmesa )
{
+ BATCH_LOCALS(rmesa);
+
if (RADEON_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
-
+
rmesa->dma.flush = NULL;
- if (rmesa->dma.current.buf) {
- struct r300_dma_region *current = &rmesa->dma.current;
- GLuint current_offset = GET_START(current);
+ if (rmesa->dma.current) {
+ GLuint current_offset = rmesa->dma.current_used;
- assert (current->start +
+ assert (rmesa->dma.current_used +
rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
- current->ptr);
+ rmesa->dma.current_vertexptr);
- if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
+ if (rmesa->dma.current_used != rmesa->dma.current_vertexptr) {
+ rmesa->dma.current_used = rmesa->dma.current_vertexptr;
r300EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size + (12*sizeof(int)), __FUNCTION__);
-
+
r300EmitState(rmesa);
-
+
r300EmitVertexAOS( rmesa,
rmesa->swtcl.vertex_size,
- current_offset);
-
+ rmesa->dma.current, current_offset);
+
r300EmitVbufPrim( rmesa,
rmesa->swtcl.hw_primitive,
rmesa->swtcl.numverts);
-
+
r300EmitCacheFlush(rmesa);
+ COMMIT_BATCH();
}
-
+
rmesa->swtcl.numverts = 0;
- current->start = current->ptr;
}
}
@@ -287,7 +289,7 @@ r300AllocDmaLowVerts( r300ContextPtr rmesa, int nverts, int vsize )
{
GLuint bytes = vsize * nverts;
- if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
+ if (!rmesa->dma.current || rmesa->dma.current_vertexptr + bytes > rmesa->dma.current->size)
r300RefillCurrentDmaRegion( rmesa, bytes);
if (!rmesa->dma.flush) {
@@ -297,13 +299,13 @@ r300AllocDmaLowVerts( r300ContextPtr rmesa, int nverts, int vsize )
ASSERT( vsize == rmesa->swtcl.vertex_size * 4 );
ASSERT( rmesa->dma.flush == flush_last_swtcl_prim );
- ASSERT( rmesa->dma.current.start +
+ ASSERT( rmesa->dma.current_used +
rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
- rmesa->dma.current.ptr );
+ rmesa->dma.current_vertexptr );
{
- GLubyte *head = (GLubyte *) (rmesa->dma.current.address + rmesa->dma.current.ptr);
- rmesa->dma.current.ptr += bytes;
+ GLubyte *head = (GLubyte *) (rmesa->dma.current->virtual + rmesa->dma.current_vertexptr);
+ rmesa->dma.current_vertexptr += bytes;
rmesa->swtcl.numverts += nverts;
return head;
}
@@ -352,7 +354,7 @@ static void r300RenderPrimitive( GLcontext *ctx, GLenum prim );
r300ContextPtr rmesa = R300_CONTEXT(ctx); \
const char *r300verts = (char *)rmesa->swtcl.verts;
#define VERT(x) (r300Vertex *)(r300verts + ((x) * vertsize * sizeof(int)))
-#define VERTEX r300Vertex
+#define VERTEX r300Vertex
#define DO_DEBUG_VERTS (1 && (RADEON_DEBUG & DEBUG_VERTS))
#define PRINT_VERTEX(x)
#undef TAG
@@ -572,15 +574,15 @@ static void r300RenderStart(GLcontext *ctx)
r300ContextPtr rmesa = R300_CONTEXT( ctx );
// fprintf(stderr, "%s\n", __FUNCTION__);
- r300ChooseRenderState(ctx);
+ r300ChooseRenderState(ctx);
r300SetVertexFormat(ctx);
r300UpdateShaders(rmesa);
r300UpdateShaderStates(rmesa);
r300EmitCacheFlush(rmesa);
-
- if (rmesa->dma.flush != 0 &&
+
+ if (rmesa->dma.flush != 0 &&
rmesa->dma.flush != flush_last_swtcl_prim)
rmesa->dma.flush( rmesa );
@@ -593,7 +595,7 @@ static void r300RenderFinish(GLcontext *ctx)
static void r300RasterPrimitive( GLcontext *ctx, GLuint hwprim )
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
-
+
if (rmesa->swtcl.hw_primitive != hwprim) {
R300_NEWPRIM( rmesa );
rmesa->swtcl.hw_primitive = hwprim;
@@ -611,7 +613,7 @@ static void r300RenderPrimitive(GLcontext *ctx, GLenum prim)
r300RasterPrimitive( ctx, reduced_prim[prim] );
// fprintf(stderr, "%s\n", __FUNCTION__);
-
+
}
static void r300ResetLineStipple(GLcontext *ctx)
@@ -625,12 +627,12 @@ void r300InitSwtcl(GLcontext *ctx)
TNLcontext *tnl = TNL_CONTEXT(ctx);
r300ContextPtr rmesa = R300_CONTEXT(ctx);
static int firsttime = 1;
-
+
if (firsttime) {
init_rast_tab();
firsttime = 0;
}
-
+
tnl->Driver.Render.Start = r300RenderStart;
tnl->Driver.Render.Finish = r300RenderFinish;
tnl->Driver.Render.PrimitiveNotify = r300RenderPrimitive;
@@ -638,15 +640,15 @@ void r300InitSwtcl(GLcontext *ctx)
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
tnl->Driver.Render.Interp = _tnl_interp;
-
+
/* FIXME: what are these numbers? */
- _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
+ _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
48 * sizeof(GLfloat) );
-
+
rmesa->swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
rmesa->swtcl.RenderIndex = ~0;
rmesa->swtcl.render_primitive = GL_TRIANGLES;
- rmesa->swtcl.hw_primitive = 0;
+ rmesa->swtcl.hw_primitive = 0;
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
@@ -655,9 +657,9 @@ void r300InitSwtcl(GLcontext *ctx)
_tnl_need_projected_coords( ctx, GL_FALSE );
r300ChooseRenderState(ctx);
- _mesa_validate_all_lighting_tables( ctx );
+ _mesa_validate_all_lighting_tables( ctx );
- tnl->Driver.NotifyMaterialChange =
+ tnl->Driver.NotifyMaterialChange =
_mesa_validate_all_lighting_tables;
}
@@ -665,33 +667,32 @@ void r300DestroySwtcl(GLcontext *ctx)
{
}
-void r300EmitVertexAOS(r300ContextPtr rmesa, GLuint vertex_size, GLuint offset)
+void r300EmitVertexAOS(r300ContextPtr rmesa, GLuint vertex_size, dri_bo *bo, GLuint offset)
{
- int cmd_reserved = 0;
- int cmd_written = 0;
+ BATCH_LOCALS(rmesa);
- drm_radeon_cmd_header_t *cmd = NULL;
if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s: vertex_size %d, offset 0x%x \n",
- __FUNCTION__, vertex_size, offset);
-
- start_packet3(CP_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, 2), 2);
- e32(1);
- e32(vertex_size | (vertex_size << 8));
- e32(offset);
+ fprintf(stderr, "%s: vertex_size %d, offset 0x%x \n",
+ __FUNCTION__, vertex_size, offset);
+
+ BEGIN_BATCH(5);
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, 2);
+ OUT_BATCH(1);
+ OUT_BATCH(vertex_size | (vertex_size << 8));
+ OUT_BATCH_RELOC(0, bo, offset, 0);
+ END_BATCH();
}
void r300EmitVbufPrim(r300ContextPtr rmesa, GLuint primitive, GLuint vertex_nr)
{
-
- int cmd_reserved = 0;
- int cmd_written = 0;
+ BATCH_LOCALS(rmesa);
int type, num_verts;
- drm_radeon_cmd_header_t *cmd = NULL;
type = r300PrimitiveType(rmesa, primitive);
num_verts = r300NumVerts(rmesa, vertex_nr, primitive);
-
- start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0), 0);
- e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (num_verts << 16) | type);
+
+ BEGIN_BATCH(3);
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
+ OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (num_verts << 16) | type);
+ END_BATCH();
}
diff --git a/src/mesa/drivers/dri/r300/r300_tex.c b/src/mesa/drivers/dri/r300/r300_tex.c
index f7f4972..c6ee1b5 100644
--- a/src/mesa/drivers/dri/r300/r300_tex.c
+++ b/src/mesa/drivers/dri/r300/r300_tex.c
@@ -48,6 +48,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r300_context.h"
#include "r300_state.h"
#include "r300_ioctl.h"
+#include "r300_mipmap_tree.h"
#include "r300_tex.h"
#include "xmlpool.h"
@@ -78,7 +79,7 @@ static unsigned int translate_wrap_mode(GLenum wrapmode)
*/
static void r300UpdateTexWrap(r300TexObjPtr t)
{
- struct gl_texture_object *tObj = t->base.tObj;
+ struct gl_texture_object *tObj = &t->base;
t->filter &=
~(R300_TX_WRAP_S_MASK | R300_TX_WRAP_T_MASK | R300_TX_WRAP_R_MASK);
@@ -175,39 +176,6 @@ static void r300SetTexBorderColor(r300TexObjPtr t, GLubyte c[4])
t->pp_border_color = PACK_COLOR_8888(c[3], c[0], c[1], c[2]);
}
-/**
- * Allocate space for and load the mesa images into the texture memory block.
- * This will happen before drawing with a new texture, or drawing with a
- * texture after it was swapped out or teximaged again.
- */
-
-static r300TexObjPtr r300AllocTexObj(struct gl_texture_object *texObj)
-{
- r300TexObjPtr t;
-
- t = CALLOC_STRUCT(r300_tex_obj);
- texObj->DriverData = t;
- if (t != NULL) {
- if (RADEON_DEBUG & DEBUG_TEXTURE) {
- fprintf(stderr, "%s( %p, %p )\n", __FUNCTION__,
- (void *)texObj, (void *)t);
- }
-
- /* Initialize non-image-dependent parts of the state:
- */
- t->base.tObj = texObj;
- t->border_fallback = GL_FALSE;
-
- make_empty_list(&t->base);
-
- r300UpdateTexWrap(t);
- r300SetTexFilter(t, texObj->MinFilter, texObj->MagFilter, texObj->MaxAnisotropy);
- r300SetTexBorderColor(t, texObj->_BorderChan);
- }
-
- return t;
-}
-
/* try to find a format which will only need a memcopy */
static const struct gl_texture_format *r300Choose8888TexFormat(GLenum srcFormat,
GLenum srcType)
@@ -433,95 +401,14 @@ static const struct gl_texture_format *r300ChooseTextureFormat(GLcontext * ctx,
return NULL; /* never get here */
}
-static GLboolean
-r300ValidateClientStorage(GLcontext * ctx, GLenum target,
- GLint internalFormat,
- GLint srcWidth, GLint srcHeight,
- GLenum format, GLenum type, const void *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
+/**
+ * Marks the given face/level pair as dirty.
+ * This will cause an appropriate texture reupload the next time this
+ * texture is validated.
+ */
+static void mark_texture_image_dirty(r300TexObj *t, int face, int level)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
-
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "intformat %s format %s type %s\n",
- _mesa_lookup_enum_by_nr(internalFormat),
- _mesa_lookup_enum_by_nr(format),
- _mesa_lookup_enum_by_nr(type));
-
- if (!ctx->Unpack.ClientStorage)
- return 0;
-
- if (ctx->_ImageTransferState ||
- texImage->IsCompressed || texObj->GenerateMipmap)
- return 0;
-
- /* This list is incomplete, may be different on ppc???
- */
- switch (internalFormat) {
- case GL_RGBA:
- if (format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
- texImage->TexFormat = _dri_texformat_argb8888;
- } else
- return 0;
- break;
-
- case GL_RGB:
- if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
- texImage->TexFormat = _dri_texformat_rgb565;
- } else
- return 0;
- break;
-
- case GL_YCBCR_MESA:
- if (format == GL_YCBCR_MESA &&
- type == GL_UNSIGNED_SHORT_8_8_REV_APPLE) {
- texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
- } else if (format == GL_YCBCR_MESA &&
- (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
- type == GL_UNSIGNED_BYTE)) {
- texImage->TexFormat = &_mesa_texformat_ycbcr;
- } else
- return 0;
- break;
-
- default:
- return 0;
- }
-
- /* Could deal with these packing issues, but currently don't:
- */
- if (packing->SkipPixels ||
- packing->SkipRows || packing->SwapBytes || packing->LsbFirst) {
- return 0;
- }
-
- GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
- format, type);
-
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: srcRowStride %d/%x\n",
- __FUNCTION__, srcRowStride, srcRowStride);
-
- /* Could check this later in upload, pitch restrictions could be
- * relaxed, but would need to store the image pitch somewhere,
- * as packing details might change before image is uploaded:
- */
- if (!r300IsGartMemory(rmesa, pixels, srcHeight * srcRowStride)
- || (srcRowStride & 63))
- return 0;
-
- /* Have validated that _mesa_transfer_teximage would be a straight
- * memcpy at this point. NOTE: future calls to TexSubImage will
- * overwrite the client data. This is explicitly mentioned in the
- * extension spec.
- */
- texImage->Data = (void *)pixels;
- texImage->IsClientData = GL_TRUE;
- texImage->RowStride = srcRowStride / texImage->TexFormat->TexelBytes;
-
- return 1;
+ t->dirty_images[face] |= 1 << level;
}
static void r300TexImage1D(GLcontext * ctx, GLenum target, GLint level,
@@ -532,24 +419,13 @@ static void r300TexImage1D(GLcontext * ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
+ r300TexObj* t = r300_tex_obj(texObj);
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
- return;
- }
- }
-
- /* Note, this will call ChooseTextureFormat */
_mesa_store_teximage1d(ctx, target, level, internalFormat,
width, border, format, type, pixels,
&ctx->Unpack, texObj, texImage);
- t->dirty_images[0] |= (1 << level);
+ mark_texture_image_dirty(t, 0, level);
}
static void r300TexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
@@ -561,24 +437,13 @@ static void r300TexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
-
- assert(t); /* this _should_ be true */
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
- return;
- }
- }
+ r300TexObj* t = r300_tex_obj(texObj);
_mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
format, type, pixels, packing, texObj,
texImage);
- t->dirty_images[0] |= (1 << level);
+ mark_texture_image_dirty(t, 0, level);
}
static void r300TexImage2D(GLcontext * ctx, GLenum target, GLint level,
@@ -589,7 +454,7 @@ static void r300TexImage2D(GLcontext * ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
+ r300TexObj* t = r300_tex_obj(texObj);
GLuint face;
/* which cube face or ordinary 2D image */
@@ -608,43 +473,23 @@ static void r300TexImage2D(GLcontext * ctx, GLenum target, GLint level,
face = 0;
}
- if (t != NULL) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
- return;
- }
- }
-
texImage->IsClientData = GL_FALSE;
- if (r300ValidateClientStorage(ctx, target,
- internalFormat,
- width, height,
- format, type, pixels,
- packing, texObj, texImage)) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using client storage\n",
- __FUNCTION__);
- } else {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using normal storage\n",
- __FUNCTION__);
-
- /* Normal path: copy (to cached memory) and eventually upload
- * via another copy to GART memory and then a blit... Could
- * eliminate one copy by going straight to (permanent) GART.
- *
- * Note, this will call r300ChooseTextureFormat.
- */
- _mesa_store_teximage2d(ctx, target, level, internalFormat,
- width, height, border, format, type,
- pixels, &ctx->Unpack, texObj, texImage);
+ if (RADEON_DEBUG & DEBUG_TEXTURE)
+ fprintf(stderr, "%s: Using normal storage\n",
+ __FUNCTION__);
+
+ /* Normal path: copy (to cached memory) and eventually upload
+ * via another copy to GART memory and then a blit... Could
+ * eliminate one copy by going straight to (permanent) GART.
+ *
+ * Note, this will call r300ChooseTextureFormat.
+ */
+ _mesa_store_teximage2d(ctx, target, level, internalFormat,
+ width, height, border, format, type,
+ pixels, &ctx->Unpack, texObj, texImage);
- t->dirty_images[face] |= (1 << level);
- }
+ mark_texture_image_dirty(t, face, level);
}
static void r300TexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
@@ -656,7 +501,7 @@ static void r300TexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
+ r300TexObj* t = r300_tex_obj(texObj);
GLuint face;
/* which cube face or ordinary 2D image */
@@ -675,22 +520,11 @@ static void r300TexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
face = 0;
}
- assert(t); /* this _should_ be true */
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
- return;
- }
- }
-
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, type, pixels, packing, texObj,
texImage);
- t->dirty_images[face] |= (1 << level);
+ mark_texture_image_dirty(t, face, level);
}
static void r300CompressedTexImage2D(GLcontext * ctx, GLenum target,
@@ -700,7 +534,7 @@ static void r300CompressedTexImage2D(GLcontext * ctx, GLenum target,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
+ r300TexObj* t = r300_tex_obj(texObj);
GLuint face;
/* which cube face or ordinary 2D image */
@@ -719,49 +553,24 @@ static void r300CompressedTexImage2D(GLcontext * ctx, GLenum target,
face = 0;
}
- if (t != NULL) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY,
- "glCompressedTexImage2D");
- return;
- }
- }
-
texImage->IsClientData = GL_FALSE;
- /* can't call this, different parameters. Would never evaluate to true anyway currently */
-#if 0
- if (r300ValidateClientStorage(ctx, target,
- internalFormat,
- width, height,
- format, type, pixels,
- packing, texObj, texImage)) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using client storage\n",
- __FUNCTION__);
- } else
-#endif
- {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using normal storage\n",
- __FUNCTION__);
-
- /* Normal path: copy (to cached memory) and eventually upload
- * via another copy to GART memory and then a blit... Could
- * eliminate one copy by going straight to (permanent) GART.
- *
- * Note, this will call r300ChooseTextureFormat.
- */
- _mesa_store_compressed_teximage2d(ctx, target, level,
- internalFormat, width, height,
- border, imageSize, data,
- texObj, texImage);
+ if (RADEON_DEBUG & DEBUG_TEXTURE)
+ fprintf(stderr, "%s: Using normal storage\n",
+ __FUNCTION__);
+
+ /* Normal path: copy (to cached memory) and eventually upload
+ * via another copy to GART memory and then a blit... Could
+ * eliminate one copy by going straight to (permanent) GART.
+ *
+ * Note, this will call r300ChooseTextureFormat.
+ */
+ _mesa_store_compressed_teximage2d(ctx, target, level,
+ internalFormat, width, height,
+ border, imageSize, data,
+ texObj, texImage);
- t->dirty_images[face] |= (1 << level);
- }
+ mark_texture_image_dirty(t, face, level);
}
static void r300CompressedTexSubImage2D(GLcontext * ctx, GLenum target,
@@ -772,7 +581,7 @@ static void r300CompressedTexSubImage2D(GLcontext * ctx, GLenum target,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
+ r300TexObj* t = r300_tex_obj(texObj);
GLuint face;
/* which cube face or ordinary 2D image */
@@ -791,23 +600,11 @@ static void r300CompressedTexSubImage2D(GLcontext * ctx, GLenum target,
face = 0;
}
- assert(t); /* this _should_ be true */
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY,
- "glCompressedTexSubImage3D");
- return;
- }
- }
-
_mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset,
yoffset, width, height, format,
imageSize, data, texObj, texImage);
- t->dirty_images[face] |= (1 << level);
+ mark_texture_image_dirty(t, face, level);
}
static void r300TexImage3D(GLcontext * ctx, GLenum target, GLint level,
@@ -819,49 +616,26 @@ static void r300TexImage3D(GLcontext * ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
-
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
- return;
- }
- }
+ r300TexObj* t = r300_tex_obj(texObj);
texImage->IsClientData = GL_FALSE;
-#if 0
- if (r300ValidateClientStorage(ctx, target,
- internalFormat,
- width, height,
- format, type, pixels,
- packing, texObj, texImage)) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using client storage\n",
- __FUNCTION__);
- } else
-#endif
- {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using normal storage\n",
- __FUNCTION__);
-
- /* Normal path: copy (to cached memory) and eventually upload
- * via another copy to GART memory and then a blit... Could
- * eliminate one copy by going straight to (permanent) GART.
- *
- * Note, this will call r300ChooseTextureFormat.
- */
- _mesa_store_teximage3d(ctx, target, level, internalFormat,
- width, height, depth, border,
- format, type, pixels,
- &ctx->Unpack, texObj, texImage);
+ if (RADEON_DEBUG & DEBUG_TEXTURE)
+ fprintf(stderr, "%s: Using normal storage\n",
+ __FUNCTION__);
+
+ /* Normal path: copy (to cached memory) and eventually upload
+ * via another copy to GART memory and then a blit... Could
+ * eliminate one copy by going straight to (permanent) GART.
+ *
+ * Note, this will call r300ChooseTextureFormat.
+ */
+ _mesa_store_teximage3d(ctx, target, level, internalFormat,
+ width, height, depth, border,
+ format, type, pixels,
+ &ctx->Unpack, texObj, texImage);
- t->dirty_images[0] |= (1 << level);
- }
+ mark_texture_image_dirty(t, 0, level);
}
static void
@@ -874,28 +648,14 @@ r300TexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
-
-/* fprintf(stderr, "%s\n", __FUNCTION__); */
-
- assert(t); /* this _should_ be true */
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
- return;
- }
- texObj->DriverData = t;
- }
+ r300TexObj* t = r300_tex_obj(texObj);
_mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing, texObj,
texImage);
- t->dirty_images[0] |= (1 << level);
+ mark_texture_image_dirty(t, 0, level);
}
/**
@@ -907,7 +667,7 @@ static void r300TexParameter(GLcontext * ctx, GLenum target,
struct gl_texture_object *texObj,
GLenum pname, const GLfloat * params)
{
- r300TexObjPtr t = (r300TexObjPtr) texObj->DriverData;
+ r300TexObj* t = r300_tex_obj(texObj);
if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
fprintf(stderr, "%s( %s )\n", __FUNCTION__,
@@ -940,7 +700,10 @@ static void r300TexParameter(GLcontext * ctx, GLenum target,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
- driSwapOutTextureObject((driTextureObject *) t);
+ if (t->mt) {
+ r300_miptree_destroy(t->mt);
+ t->mt = 0;
+ }
break;
case GL_DEPTH_TEXTURE_MODE:
@@ -963,27 +726,10 @@ static void r300TexParameter(GLcontext * ctx, GLenum target,
}
}
-static void r300BindTexture(GLcontext * ctx, GLenum target,
- struct gl_texture_object *texObj)
-{
- if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
- fprintf(stderr, "%s( %p ) unit=%d\n", __FUNCTION__,
- (void *)texObj, ctx->Texture.CurrentUnit);
- }
-
- if ((target == GL_TEXTURE_1D)
- || (target == GL_TEXTURE_2D)
- || (target == GL_TEXTURE_3D)
- || (target == GL_TEXTURE_CUBE_MAP)
- || (target == GL_TEXTURE_RECTANGLE_NV)) {
- assert(texObj->DriverData != NULL);
- }
-}
-
static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
+ r300TexObj* t = r300_tex_obj(texObj);
if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__,
@@ -991,14 +737,19 @@ static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
_mesa_lookup_enum_by_nr(texObj->Target));
}
- if (t != NULL) {
- if (rmesa) {
- R300_FIREVERTICES(rmesa);
- }
+ if (rmesa) {
+ int i;
+ R300_FIREVERTICES(rmesa);
+
+ for(i = 0; i < R300_MAX_TEXTURE_UNITS; ++i)
+ if (rmesa->hw.textures[i] == t)
+ rmesa->hw.textures[i] = 0;
+ }
- driDestroyTextureObject(t);
+ if (t->mt) {
+ r300_miptree_destroy(t->mt);
+ t->mt = 0;
}
- /* Free mipmap images and the texture object itself */
_mesa_delete_texture_object(ctx, texObj);
}
@@ -1007,8 +758,6 @@ static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
* Called via ctx->Driver.NewTextureObject.
* Note: this function will be called during context creation to
* allocate the default texture objects.
- * Note: we could use containment here to 'derive' the driver-specific
- * texture object from the core mesa gl_texture_object. Not done at this time.
* Fixup MaxAnisotropy according to user preference.
*/
static struct gl_texture_object *r300NewTextureObject(GLcontext * ctx,
@@ -1016,14 +765,23 @@ static struct gl_texture_object *r300NewTextureObject(GLcontext * ctx,
GLenum target)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct gl_texture_object *obj;
- obj = _mesa_new_texture_object(ctx, name, target);
- if (!obj)
- return NULL;
- obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
+ r300TexObj* t = CALLOC_STRUCT(r300_tex_obj);
+
+
+ if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
+ fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__,
+ t, _mesa_lookup_enum_by_nr(target));
+ }
+
+ _mesa_initialize_texture_object(&t->base, name, target);
+ t->base.MaxAnisotropy = rmesa->initialMaxAnisotropy;
+
+ /* Initialize hardware state */
+ r300UpdateTexWrap(t);
+ r300SetTexFilter(t, t->base.MinFilter, t->base.MagFilter, t->base.MaxAnisotropy);
+ r300SetTexBorderColor(t, t->base._BorderChan);
- r300AllocTexObj(obj);
- return obj;
+ return &t->base;
}
void r300InitTextureFuncs(struct dd_function_table *functions)
@@ -1039,7 +797,6 @@ void r300InitTextureFuncs(struct dd_function_table *functions)
functions->TexSubImage2D = r300TexSubImage2D;
functions->TexSubImage3D = r300TexSubImage3D;
functions->NewTextureObject = r300NewTextureObject;
- functions->BindTexture = r300BindTexture;
functions->DeleteTexture = r300DeleteTexture;
functions->IsTextureResident = driIsTextureResident;
diff --git a/src/mesa/drivers/dri/r300/r300_tex.h b/src/mesa/drivers/dri/r300/r300_tex.h
index b86d45b..5d7f21e 100644
--- a/src/mesa/drivers/dri/r300/r300_tex.h
+++ b/src/mesa/drivers/dri/r300/r300_tex.h
@@ -46,8 +46,6 @@ extern void r300UpdateTextureState(GLcontext * ctx);
extern int r300UploadTexImages(r300ContextPtr rmesa, r300TexObjPtr t,
GLuint face);
-extern void r300DestroyTexObj(r300ContextPtr rmesa, r300TexObjPtr t);
-
extern void r300InitTextureFuncs(struct dd_function_table *functions);
#endif /* __r300_TEX_H__ */
diff --git a/src/mesa/drivers/dri/r300/r300_texmem.c b/src/mesa/drivers/dri/r300/r300_texmem.c
index 69847a4..b3b501b 100644
--- a/src/mesa/drivers/dri/r300/r300_texmem.c
+++ b/src/mesa/drivers/dri/r300/r300_texmem.c
@@ -48,439 +48,15 @@ SOFTWARE.
#include "r300_context.h"
#include "r300_state.h"
#include "r300_cmdbuf.h"
+#include "r300_emit.h"
+#include "r300_mipmap_tree.h"
#include "radeon_ioctl.h"
#include "r300_tex.h"
#include "r300_ioctl.h"
#include <unistd.h> /* for usleep() */
-#ifdef USER_BUFFERS
#include "r300_mem.h"
-#endif
-/**
- * Destroy any device-dependent state associated with the texture. This may
- * include NULLing out hardware state that points to the texture.
- */
-void r300DestroyTexObj(r300ContextPtr rmesa, r300TexObjPtr t)
-{
- int i;
-
- if (RADEON_DEBUG & DEBUG_TEXTURE) {
- fprintf(stderr, "%s( %p, %p )\n", __FUNCTION__,
- (void *)t, (void *)t->base.tObj);
- }
-
- for (i = 0; i < rmesa->radeon.glCtx->Const.MaxTextureUnits; i++) {
- if (rmesa->state.texture.unit[i].texobj == t) {
- rmesa->state.texture.unit[i].texobj = NULL;
- }
- }
-}
-
-/* ------------------------------------------------------------
- * Texture image conversions
- */
-
-static void r300UploadGARTClientSubImage(r300ContextPtr rmesa,
- r300TexObjPtr t,
- struct gl_texture_image *texImage,
- GLint hwlevel,
- GLint x, GLint y,
- GLint width, GLint height)
-{
- const struct gl_texture_format *texFormat = texImage->TexFormat;
- GLuint srcPitch, dstPitch;
- int blit_format;
- int srcOffset;
-
- /*
- * XXX it appears that we always upload the full image, not a subimage.
- * I.e. x==0, y==0, width=texWidth, height=texWidth. If this is ever
- * changed, the src pitch will have to change.
- */
- switch (texFormat->TexelBytes) {
- case 1:
- blit_format = R300_CP_COLOR_FORMAT_CI8;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- case 2:
- blit_format = R300_CP_COLOR_FORMAT_RGB565;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- case 4:
- blit_format = R300_CP_COLOR_FORMAT_ARGB8888;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- case 8:
- case 16:
- blit_format = R300_CP_COLOR_FORMAT_CI8;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- default:
- return;
- }
-
- t->image[0][hwlevel].data = texImage->Data;
- srcOffset = r300GartOffsetFromVirtual(rmesa, texImage->Data);
-
- assert(srcOffset != ~0);
-
- /* Don't currently need to cope with small pitches?
- */
- width = texImage->Width;
- height = texImage->Height;
-
- if (texFormat->TexelBytes > 4) {
- width *= texFormat->TexelBytes;
- }
-
- r300EmitWait(rmesa, R300_WAIT_3D);
-
- r300EmitBlit(rmesa, blit_format,
- srcPitch,
- srcOffset,
- dstPitch,
- t->bufAddr,
- x,
- y,
- t->image[0][hwlevel].x + x,
- t->image[0][hwlevel].y + y, width, height);
-
- r300EmitWait(rmesa, R300_WAIT_2D);
-}
-
-static void r300UploadRectSubImage(r300ContextPtr rmesa,
- r300TexObjPtr t,
- struct gl_texture_image *texImage,
- GLint x, GLint y, GLint width, GLint height)
-{
- const struct gl_texture_format *texFormat = texImage->TexFormat;
- int blit_format, dstPitch, done;
-
- switch (texFormat->TexelBytes) {
- case 1:
- blit_format = R300_CP_COLOR_FORMAT_CI8;
- break;
- case 2:
- blit_format = R300_CP_COLOR_FORMAT_RGB565;
- break;
- case 4:
- blit_format = R300_CP_COLOR_FORMAT_ARGB8888;
- break;
- case 8:
- case 16:
- blit_format = R300_CP_COLOR_FORMAT_CI8;
- break;
- default:
- return;
- }
-
- t->image[0][0].data = texImage->Data;
-
- /* Currently don't need to cope with small pitches.
- */
- width = texImage->Width;
- height = texImage->Height;
- dstPitch = t->pitch;
-
- if (texFormat->TexelBytes > 4) {
- width *= texFormat->TexelBytes;
- }
-
- if (rmesa->prefer_gart_client_texturing && texImage->IsClientData) {
- /* In this case, could also use GART texturing. This is
- * currently disabled, but has been tested & works.
- */
- t->offset = r300GartOffsetFromVirtual(rmesa, texImage->Data);
- t->pitch = texImage->RowStride * texFormat->TexelBytes - 32;
-
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr,
- "Using GART texturing for rectangular client texture\n");
-
- /* Release FB memory allocated for this image:
- */
- /* FIXME This may not be correct as driSwapOutTextureObject sets
- * FIXME dirty_images. It may be fine, though.
- */
- if (t->base.memBlock) {
- driSwapOutTextureObject((driTextureObject *) t);
- }
- } else if (texImage->IsClientData) {
- /* Data already in GART memory, with usable pitch.
- */
- GLuint srcPitch;
- srcPitch = texImage->RowStride * texFormat->TexelBytes;
- r300EmitBlit(rmesa,
- blit_format,
- srcPitch,
- r300GartOffsetFromVirtual(rmesa, texImage->Data),
- dstPitch, t->bufAddr, 0, 0, 0, 0, width, height);
- } else {
- /* Data not in GART memory, or bad pitch.
- */
- for (done = 0; done < height;) {
- struct r300_dma_region region;
- int lines =
- MIN2(height - done, RADEON_BUFFER_SIZE / dstPitch);
- int src_pitch;
- char *tex;
-
- src_pitch = texImage->RowStride * texFormat->TexelBytes;
-
- tex = (char *)texImage->Data + done * src_pitch;
-
- memset(&region, 0, sizeof(region));
- r300AllocDmaRegion(rmesa, &region, lines * dstPitch,
- 1024);
-
- /* Copy texdata to dma:
- */
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr,
- "%s: src_pitch %d dst_pitch %d\n",
- __FUNCTION__, src_pitch, dstPitch);
-
- if (src_pitch == dstPitch) {
- memcpy(region.address + region.start, tex,
- lines * src_pitch);
- } else {
- char *buf = region.address + region.start;
- int i;
- for (i = 0; i < lines; i++) {
- memcpy(buf, tex, src_pitch);
- buf += dstPitch;
- tex += src_pitch;
- }
- }
-
- r300EmitWait(rmesa, R300_WAIT_3D);
-
- /* Blit to framebuffer
- */
- r300EmitBlit(rmesa,
- blit_format,
- dstPitch, GET_START(&region),
- dstPitch | (t->tile_bits >> 16),
- t->bufAddr, 0, 0, 0, done, width, lines);
-
- r300EmitWait(rmesa, R300_WAIT_2D);
-#ifdef USER_BUFFERS
- r300_mem_use(rmesa, region.buf->id);
-#endif
-
- r300ReleaseDmaRegion(rmesa, &region, __FUNCTION__);
- done += lines;
- }
- }
-}
-
-/**
- * Upload the texture image associated with texture \a t at the specified
- * level at the address relative to \a start.
- */
-static void r300UploadSubImage(r300ContextPtr rmesa, r300TexObjPtr t,
- GLint hwlevel,
- GLint x, GLint y, GLint width, GLint height,
- GLuint face)
-{
- struct gl_texture_image *texImage = NULL;
- GLuint offset;
- GLint imageWidth, imageHeight;
- GLint ret;
- drm_radeon_texture_t tex;
- drm_radeon_tex_image_t tmp;
- const int level = hwlevel + t->base.firstLevel;
-
- if (RADEON_DEBUG & DEBUG_TEXTURE) {
- fprintf(stderr,
- "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n",
- __FUNCTION__, (void *)t, (void *)t->base.tObj, level,
- width, height, face);
- }
-
- ASSERT(face < 6);
-
- /* Ensure we have a valid texture to upload */
- if ((hwlevel < 0) || (hwlevel >= RADEON_MAX_TEXTURE_LEVELS)) {
- _mesa_problem(NULL, "bad texture level in %s", __FUNCTION__);
- return;
- }
-
- texImage = t->base.tObj->Image[face][level];
-
- if (!texImage) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: texImage %d is NULL!\n",
- __FUNCTION__, level);
- return;
- }
- if (!texImage->Data) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: image data is NULL!\n",
- __FUNCTION__);
- return;
- }
-
- if (t->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
- assert(level == 0);
- assert(hwlevel == 0);
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: image data is rectangular\n",
- __FUNCTION__);
- r300UploadRectSubImage(rmesa, t, texImage, x, y, width, height);
- return;
- } else if (texImage->IsClientData) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr,
- "%s: image data is in GART client storage\n",
- __FUNCTION__);
- r300UploadGARTClientSubImage(rmesa, t, texImage, hwlevel, x, y,
- width, height);
- return;
- } else if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: image data is in normal memory\n",
- __FUNCTION__);
-
- imageWidth = texImage->Width;
- imageHeight = texImage->Height;
-
- offset = t->bufAddr;
-
- if (RADEON_DEBUG & (DEBUG_TEXTURE | DEBUG_IOCTL)) {
- GLint imageX = 0;
- GLint imageY = 0;
- GLint blitX = t->image[face][hwlevel].x;
- GLint blitY = t->image[face][hwlevel].y;
- GLint blitWidth = t->image[face][hwlevel].width;
- GLint blitHeight = t->image[face][hwlevel].height;
- fprintf(stderr, " upload image: %d,%d at %d,%d\n",
- imageWidth, imageHeight, imageX, imageY);
- fprintf(stderr, " upload blit: %d,%d at %d,%d\n",
- blitWidth, blitHeight, blitX, blitY);
- fprintf(stderr, " blit ofs: 0x%07x level: %d/%d\n",
- (GLuint) offset, hwlevel, level);
- }
-
- t->image[face][hwlevel].data = texImage->Data;
-
- /* Init the DRM_RADEON_TEXTURE command / drm_radeon_texture_t struct.
- * NOTE: we're always use a 1KB-wide blit and I8 texture format.
- * We used to use 1, 2 and 4-byte texels and used to use the texture
- * width to dictate the blit width - but that won't work for compressed
- * textures. (Brian)
- * NOTE: can't do that with texture tiling. (sroland)
- */
- tex.offset = offset;
- tex.image = &tmp;
- /* copy (x,y,width,height,data) */
- memcpy(&tmp, &t->image[face][hwlevel], sizeof(tmp));
-
- if (texImage->TexFormat->TexelBytes > 4) {
- const int log2TexelBytes =
- (3 + (texImage->TexFormat->TexelBytes >> 4));
- tex.format = RADEON_TXFORMAT_I8; /* any 1-byte texel format */
- tex.pitch =
- MAX2((texImage->Width * texImage->TexFormat->TexelBytes) /
- 64, 1);
- tex.height = imageHeight;
- tex.width = imageWidth << log2TexelBytes;
- tex.offset += (tmp.x << log2TexelBytes) & ~1023;
- tmp.x = tmp.x % (1024 >> log2TexelBytes);
- tmp.width = tmp.width << log2TexelBytes;
- } else if (texImage->TexFormat->TexelBytes) {
- /* use multi-byte upload scheme */
- tex.height = imageHeight;
- tex.width = imageWidth;
- switch (texImage->TexFormat->TexelBytes) {
- case 1:
- tex.format = RADEON_TXFORMAT_I8;
- break;
- case 2:
- tex.format = RADEON_TXFORMAT_AI88;
- break;
- case 4:
- tex.format = RADEON_TXFORMAT_ARGB8888;
- break;
- }
- tex.pitch =
- MAX2((texImage->Width * texImage->TexFormat->TexelBytes) /
- 64, 1);
- tex.offset += tmp.x & ~1023;
- tmp.x = tmp.x % 1024;
-
- if (t->tile_bits & R300_TXO_MICRO_TILE) {
- /* need something like "tiled coordinates" ? */
- tmp.y = tmp.x / (tex.pitch * 128) * 2;
- tmp.x =
- tmp.x % (tex.pitch * 128) / 2 /
- texImage->TexFormat->TexelBytes;
- tex.pitch |= RADEON_DST_TILE_MICRO >> 22;
- } else {
- tmp.x = tmp.x >> (texImage->TexFormat->TexelBytes >> 1);
- }
-#if 1
- if ((t->tile_bits & R300_TXO_MACRO_TILE) &&
- (texImage->Width * texImage->TexFormat->TexelBytes >= 256)
- && ((!(t->tile_bits & R300_TXO_MICRO_TILE)
- && (texImage->Height >= 8))
- || (texImage->Height >= 16))) {
- /* weird: R200 disables macro tiling if mip width is smaller than 256 bytes,
- OR if height is smaller than 8 automatically, but if micro tiling is active
- the limit is height 16 instead ? */
- tex.pitch |= RADEON_DST_TILE_MACRO >> 22;
- }
-#endif
- } else {
- /* In case of for instance 8x8 texture (2x2 dxt blocks),
- padding after the first two blocks is needed (only
- with dxt1 since 2 dxt3/dxt5 blocks already use 32 Byte). */
- /* set tex.height to 1/4 since 1 "macropixel" (dxt-block)
- has 4 real pixels. Needed so the kernel module reads
- the right amount of data. */
- tex.format = RADEON_TXFORMAT_I8; /* any 1-byte texel format */
- tex.pitch = (R300_BLIT_WIDTH_BYTES / 64);
- tex.height = (imageHeight + 3) / 4;
- tex.width = (imageWidth + 3) / 4;
- if ((t->format & R300_TX_FORMAT_DXT1) == R300_TX_FORMAT_DXT1) {
- tex.width *= 8;
- } else {
- tex.width *= 16;
- }
- }
-
- LOCK_HARDWARE(&rmesa->radeon);
- do {
- ret =
- drmCommandWriteRead(rmesa->radeon.dri.fd,
- DRM_RADEON_TEXTURE, &tex,
- sizeof(drm_radeon_texture_t));
- if (ret) {
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr,
- "DRM_RADEON_TEXTURE: again!\n");
- usleep(1);
- }
- } while (ret == -EAGAIN);
-
- UNLOCK_HARDWARE(&rmesa->radeon);
-
- if (ret) {
- fprintf(stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret);
- fprintf(stderr, " offset=0x%08x\n", offset);
- fprintf(stderr, " image width=%d height=%d\n",
- imageWidth, imageHeight);
- fprintf(stderr, " blit width=%d height=%d data=%p\n",
- t->image[face][hwlevel].width,
- t->image[face][hwlevel].height,
- t->image[face][hwlevel].data);
- _mesa_exit(-1);
- }
-}
/**
* Upload the texture images associated with texture \a t. This might
@@ -493,69 +69,32 @@ static void r300UploadSubImage(r300ContextPtr rmesa, r300TexObjPtr t,
int r300UploadTexImages(r300ContextPtr rmesa, r300TexObjPtr t, GLuint face)
{
- const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
-
if (t->image_override)
return 0;
+ if (!t->mt)
+ return 0;
if (RADEON_DEBUG & (DEBUG_TEXTURE | DEBUG_IOCTL)) {
- fprintf(stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__,
- (void *)rmesa->radeon.glCtx, (void *)t->base.tObj,
- t->base.totalSize, t->base.firstLevel,
- t->base.lastLevel);
+ fprintf(stderr, "%s( %p, %p ) lvls=%d-%d\n", __FUNCTION__,
+ (void *)rmesa->radeon.glCtx, t,
+ t->mt->firstLevel, t->mt->lastLevel);
}
- if (t->base.totalSize == 0)
- return 0;
-
if (RADEON_DEBUG & DEBUG_SYNC) {
fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
radeonFinish(rmesa->radeon.glCtx);
}
- LOCK_HARDWARE(&rmesa->radeon);
-
- if (t->base.memBlock == NULL) {
- int heap;
-
- heap = driAllocateTexture(rmesa->texture_heaps, rmesa->nr_heaps,
- (driTextureObject *) t);
- if (heap == -1) {
- UNLOCK_HARDWARE(&rmesa->radeon);
- return -1;
- }
-
- /* Set the base offset of the texture image */
- t->bufAddr = rmesa->radeon.radeonScreen->texOffset[heap]
- + t->base.memBlock->ofs;
- t->offset = t->bufAddr;
-
- if (!(t->base.tObj->Image[0][0]->IsClientData)) {
- /* hope it's safe to add that here... */
- t->offset |= t->tile_bits;
- }
- }
-
- /* Let the world know we've used this memory recently.
- */
- driUpdateTextureLRU((driTextureObject *) t);
- UNLOCK_HARDWARE(&rmesa->radeon);
-
/* Upload any images that are new */
- if (t->base.dirty_images[face]) {
- int i;
+ if (t->dirty_images[face]) {
+ int i, numLevels = t->mt->lastLevel - t->mt->firstLevel + 1;
for (i = 0; i < numLevels; i++) {
- if ((t->base.
- dirty_images[face] & (1 <<
- (i + t->base.firstLevel))) !=
- 0) {
- r300UploadSubImage(rmesa, t, i, 0, 0,
- t->image[face][i].width,
- t->image[face][i].height,
- face);
+ if (t->dirty_images[face] & (1 << (i + t->mt->firstLevel))) {
+ r300_miptree_upload_image(t->mt, face, t->mt->firstLevel + i,
+ t->base.Image[face][t->mt->firstLevel + i]);
}
}
- t->base.dirty_images[face] = 0;
+ t->dirty_images[face] = 0;
}
if (RADEON_DEBUG & DEBUG_SYNC) {
diff --git a/src/mesa/drivers/dri/r300/r300_texstate.c b/src/mesa/drivers/dri/r300/r300_texstate.c
index bdd20b1..1b24738 100644
--- a/src/mesa/drivers/dri/r300/r300_texstate.c
+++ b/src/mesa/drivers/dri/r300/r300_texstate.c
@@ -48,6 +48,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r300_state.h"
#include "r300_ioctl.h"
#include "radeon_ioctl.h"
+#include "r300_mipmap_tree.h"
#include "r300_tex.h"
#include "r300_reg.h"
@@ -148,8 +149,7 @@ void r300SetDepthTexMode(struct gl_texture_object *tObj)
if (!tObj)
return;
- t = (r300TexObjPtr) tObj->DriverData;
-
+ t = r300_tex_obj(tObj);
switch (tObj->Image[0][tObj->BaseLevel]->TexFormat->MesaFormat) {
case MESA_FORMAT_Z16:
@@ -189,118 +189,59 @@ void r300SetDepthTexMode(struct gl_texture_object *tObj)
}
-/**
- * Compute sizes and fill in offset and blit information for the given
- * image (determined by \p face and \p level).
- *
- * \param curOffset points to the offset at which the image is to be stored
- * and is updated by this function according to the size of the image.
- */
-static void compute_tex_image_offset(
- struct gl_texture_object *tObj,
- GLuint face,
- GLint level,
- GLint* curOffset)
+static void calculate_first_last_level(struct gl_texture_object *tObj,
+ GLuint *pfirstLevel, GLuint *plastLevel)
{
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
- const struct gl_texture_image* texImage;
- GLuint blitWidth = R300_BLIT_WIDTH_BYTES;
- GLuint texelBytes;
- GLuint size;
-
- texImage = tObj->Image[0][level + t->base.firstLevel];
- if (!texImage)
- return;
-
- texelBytes = texImage->TexFormat->TexelBytes;
-
- /* find image size in bytes */
- if (texImage->IsCompressed) {
- if ((t->format & R300_TX_FORMAT_DXT1) ==
- R300_TX_FORMAT_DXT1) {
- // fprintf(stderr,"DXT 1 %d %08X\n", texImage->Width, t->format);
- if ((texImage->Width + 3) < 8) /* width one block */
- size = texImage->CompressedSize * 4;
- else if ((texImage->Width + 3) < 16)
- size = texImage->CompressedSize * 2;
- else
- size = texImage->CompressedSize;
+ const struct gl_texture_image * const baseImage =
+ tObj->Image[0][tObj->BaseLevel];
+
+ /* These must be signed values. MinLod and MaxLod can be negative numbers,
+ * and having firstLevel and lastLevel as signed prevents the need for
+ * extra sign checks.
+ */
+ int firstLevel;
+ int lastLevel;
+
+ /* Yes, this looks overly complicated, but it's all needed.
+ */
+ switch (tObj->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+ /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+ */
+ firstLevel = lastLevel = tObj->BaseLevel;
} else {
- /* DXT3/5, 16 bytes per block */
- WARN_ONCE
- ("DXT 3/5 suffers from multitexturing problems!\n");
- // fprintf(stderr,"DXT 3/5 %d\n", texImage->Width);
- if ((texImage->Width + 3) < 8)
- size = texImage->CompressedSize * 2;
- else
- size = texImage->CompressedSize;
+ firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
}
- } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
- size =
- ((texImage->Width * texelBytes +
- 63) & ~63) * texImage->Height;
- blitWidth = 64 / texelBytes;
- } else if (t->tile_bits & R300_TXO_MICRO_TILE) {
- /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
- though the actual offset may be different (if texture is less than
- 32 bytes width) to the untiled case */
- int w = (texImage->Width * texelBytes * 2 + 31) & ~31;
- size =
- (w * ((texImage->Height + 1) / 2)) *
- texImage->Depth;
- blitWidth = MAX2(texImage->Width, 64 / texelBytes);
- } else {
- int w = (texImage->Width * texelBytes + 31) & ~31;
- size = w * texImage->Height * texImage->Depth;
- blitWidth = MAX2(texImage->Width, 64 / texelBytes);
- }
- assert(size > 0);
-
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "w=%d h=%d d=%d tb=%d intFormat=%d\n",
- texImage->Width, texImage->Height,
- texImage->Depth,
- texImage->TexFormat->TexelBytes,
- texImage->InternalFormat);
-
- /* All images are aligned to a 32-byte offset */
- *curOffset = (*curOffset + 0x1f) & ~0x1f;
-
- if (texelBytes) {
- /* fix x and y coords up later together with offset */
- t->image[face][level].x = *curOffset;
- t->image[face][level].y = 0;
- t->image[face][level].width =
- MIN2(size / texelBytes, blitWidth);
- t->image[face][level].height =
- (size / texelBytes) / t->image[face][level].width;
- } else {
- t->image[face][level].x = *curOffset % R300_BLIT_WIDTH_BYTES;
- t->image[face][level].y = *curOffset / R300_BLIT_WIDTH_BYTES;
- t->image[face][level].width =
- MIN2(size, R300_BLIT_WIDTH_BYTES);
- t->image[face][level].height = size / t->image[face][level].width;
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_TEXTURE_4D_SGIS:
+ firstLevel = lastLevel = 0;
+ break;
+ default:
+ return;
}
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr,
- "level %d, face %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
- level, face, texImage->Width, texImage->Height,
- t->image[face][level].x, t->image[face][level].y,
- t->image[face][level].width, t->image[face][level].height,
- size, *curOffset);
-
- *curOffset += size;
+ /* save these values */
+ *pfirstLevel = firstLevel;
+ *plastLevel = lastLevel;
}
-
/**
- * This function computes the number of bytes of storage needed for
- * the given texture object (all mipmap levels, all cube faces).
- * The \c image[face][level].x/y/width/height parameters for upload/blitting
- * are computed here. \c filter, \c format, etc. will be set here
- * too.
+ * This function ensures a validated miptree is available.
+ *
+ * Additionally, some texture format bits are configured here.
*
* \param rmesa Context pointer
* \param tObj GL texture object whose images are to be posted to
@@ -309,13 +250,13 @@ static void compute_tex_image_offset(
static void r300SetTexImages(r300ContextPtr rmesa,
struct gl_texture_object *tObj)
{
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
+ r300TexObjPtr t = r300_tex_obj(tObj);
const struct gl_texture_image *baseImage =
tObj->Image[0][tObj->BaseLevel];
- GLint curOffset;
- GLint i, texelBytes;
- GLint numLevels;
- GLint log2Width, log2Height, log2Depth;
+ GLint texelBytes;
+ GLuint firstLevel = 0, lastLevel = 0;
+
+ calculate_first_last_level(tObj, &firstLevel, &lastLevel);
/* Set the hardware texture format
*/
@@ -335,107 +276,59 @@ static void r300SetTexImages(r300ContextPtr rmesa,
}
texelBytes = baseImage->TexFormat->TexelBytes;
-
- /* Compute which mipmap levels we really want to send to the hardware.
- */
- driCalculateTextureFirstLastLevel((driTextureObject *) t);
- log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
- log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
- log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2;
-
- numLevels = t->base.lastLevel - t->base.firstLevel + 1;
-
- assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
-
- /* Calculate mipmap offsets and dimensions for blitting (uploading)
- * The idea is that we lay out the mipmap levels within a block of
- * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
- */
t->tile_bits = 0;
- /* figure out if this texture is suitable for tiling. */
-#if 0 /* Disabled for now */
- if (texelBytes) {
- if ((tObj->Target != GL_TEXTURE_RECTANGLE_NV) &&
- /* texrect might be able to use micro tiling too in theory? */
- (baseImage->Height > 1)) {
-
- /* allow 32 (bytes) x 1 mip (which will use two times the space
- the non-tiled version would use) max if base texture is large enough */
- if ((numLevels == 1) ||
- (((baseImage->Width * texelBytes /
- baseImage->Height) <= 32)
- && (baseImage->Width * texelBytes > 64))
- ||
- ((baseImage->Width * texelBytes /
- baseImage->Height) <= 16)) {
- t->tile_bits |= R300_TXO_MICRO_TILE;
- }
- }
+ if (tObj->Target == GL_TEXTURE_CUBE_MAP)
+ t->format |= R300_TX_FORMAT_CUBIC_MAP;
- if (tObj->Target != GL_TEXTURE_RECTANGLE_NV) {
- /* we can set macro tiling even for small textures, they will be untiled anyway */
- t->tile_bits |= R300_TXO_MACRO_TILE;
+ if (!t->image_override) {
+ GLuint compressed = baseImage->IsCompressed ? baseImage->TexFormat->MesaFormat : 0;
+
+ if (t->mt) {
+ if (t->mt->firstLevel != firstLevel ||
+ t->mt->lastLevel != lastLevel ||
+ t->mt->width0 != baseImage->Width ||
+ t->mt->height0 != baseImage->Height ||
+ t->mt->depth0 != baseImage->Depth ||
+ t->mt->bpp != texelBytes ||
+ t->mt->tilebits != t->tile_bits ||
+ t->mt->compressed != compressed) {
+ r300_miptree_destroy(t->mt);
+ t->mt = 0;
+ }
}
- }
-#endif
-
- curOffset = 0;
- if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
- ASSERT(log2Width == log2Height);
- t->format |= R300_TX_FORMAT_CUBIC_MAP;
-
- for(i = 0; i < numLevels; i++) {
- GLuint face;
- for(face = 0; face < 6; face++)
- compute_tex_image_offset(tObj, face, i, &curOffset);
+ if (!t->mt) {
+ t->mt = r300_miptree_create(rmesa, t, tObj->Target,
+ firstLevel, lastLevel,
+ baseImage->Width, baseImage->Height, baseImage->Depth,
+ texelBytes, t->tile_bits, compressed);
+ memset(t->dirty_images, 0xff, sizeof(t->dirty_images));
}
- } else {
- for (i = 0; i < numLevels; i++)
- compute_tex_image_offset(tObj, 0, i, &curOffset);
}
- /* Align the total size of texture memory block.
- */
- t->base.totalSize =
- (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
-
- t->size =
- (((tObj->Image[0][t->base.firstLevel]->Width -
- 1) << R300_TX_WIDTHMASK_SHIFT)
- | ((tObj->Image[0][t->base.firstLevel]->Height - 1) <<
- R300_TX_HEIGHTMASK_SHIFT))
- | ((numLevels - 1) << R300_TX_MAX_MIP_LEVEL_SHIFT);
-
+ t->size = (((tObj->Image[0][firstLevel]->Width - 1) << R300_TX_WIDTHMASK_SHIFT)
+ | ((tObj->Image[0][firstLevel]->Height - 1) << R300_TX_HEIGHTMASK_SHIFT))
+ | ((lastLevel - firstLevel) << R300_TX_MAX_MIP_LEVEL_SHIFT);
t->pitch = 0;
- /* Only need to round to nearest 32 for textures, but the blitter
- * requires 64-byte aligned pitches, and we may/may not need the
- * blitter. NPOT only!
- */
if (baseImage->IsCompressed) {
- t->pitch |=
- (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
+ t->pitch |= (tObj->Image[0][firstLevel]->Width + 63) & ~(63);
} else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
unsigned int align = (64 / texelBytes) - 1;
- t->pitch |= ((tObj->Image[0][t->base.firstLevel]->Width *
+ t->pitch |= ((tObj->Image[0][firstLevel]->Width *
texelBytes) + 63) & ~(63);
t->size |= R300_TX_SIZE_TXPITCH_EN;
if (!t->image_override)
- t->pitch_reg =
- (((tObj->Image[0][t->base.firstLevel]->Width) +
- align) & ~align) - 1;
+ t->pitch_reg = (((tObj->Image[0][firstLevel]->Width) + align) & ~align) - 1;
} else {
- t->pitch |=
- ((tObj->Image[0][t->base.firstLevel]->Width *
- texelBytes) + 63) & ~(63);
+ t->pitch |= ((tObj->Image[0][firstLevel]->Width * texelBytes) + 63) & ~(63);
}
if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
- if (tObj->Image[0][t->base.firstLevel]->Width > 2048)
+ if (tObj->Image[0][firstLevel]->Width > 2048)
t->pitch_reg |= R500_TXWIDTH_BIT11;
- if (tObj->Image[0][t->base.firstLevel]->Height > 2048)
+ if (tObj->Image[0][firstLevel]->Height > 2048)
t->pitch_reg |= R500_TXHEIGHT_BIT11;
}
}
@@ -449,17 +342,15 @@ static GLboolean r300EnableTexture2D(GLcontext * ctx, int unit)
r300ContextPtr rmesa = R300_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
+ r300TexObjPtr t = r300_tex_obj(tObj);
ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
- if (t->base.dirty_images[0]) {
+ if (!t->mt || t->dirty_images[0]) {
R300_FIREVERTICES(rmesa);
r300SetTexImages(rmesa, tObj);
- r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
- if (!t->base.memBlock && !t->image_override)
- return GL_FALSE;
+ r300UploadTexImages(rmesa, t, 0);
}
return GL_TRUE;
@@ -470,7 +361,7 @@ static GLboolean r300EnableTexture3D(GLcontext * ctx, int unit)
r300ContextPtr rmesa = R300_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
+ r300TexObjPtr t = r300_tex_obj(tObj);
ASSERT(tObj->Target == GL_TEXTURE_3D);
@@ -479,12 +370,10 @@ static GLboolean r300EnableTexture3D(GLcontext * ctx, int unit)
return GL_FALSE;
}
- if (t->base.dirty_images[0]) {
+ if (!t->mt || t->dirty_images[0]) {
R300_FIREVERTICES(rmesa);
r300SetTexImages(rmesa, tObj);
- r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
- if (!t->base.memBlock)
- return GL_FALSE;
+ r300UploadTexImages(rmesa, t, 0);
}
return GL_TRUE;
@@ -495,14 +384,15 @@ static GLboolean r300EnableTextureCube(GLcontext * ctx, int unit)
r300ContextPtr rmesa = R300_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
+ r300TexObjPtr t = r300_tex_obj(tObj);
GLuint face;
ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
- if (t->base.dirty_images[0] || t->base.dirty_images[1] ||
- t->base.dirty_images[2] || t->base.dirty_images[3] ||
- t->base.dirty_images[4] || t->base.dirty_images[5]) {
+ if (!t->mt ||
+ t->dirty_images[0] || t->dirty_images[1] ||
+ t->dirty_images[2] || t->dirty_images[3] ||
+ t->dirty_images[4] || t->dirty_images[5]) {
/* flush */
R300_FIREVERTICES(rmesa);
/* layout memory space, once for all faces */
@@ -511,18 +401,11 @@ static GLboolean r300EnableTextureCube(GLcontext * ctx, int unit)
/* upload (per face) */
for (face = 0; face < 6; face++) {
- if (t->base.dirty_images[face]) {
- r300UploadTexImages(rmesa,
- (r300TexObjPtr) tObj->DriverData,
- face);
+ if (t->dirty_images[face]) {
+ r300UploadTexImages(rmesa, t, face);
}
}
- if (!t->base.memBlock) {
- /* texmem alloc failed, use s/w fallback */
- return GL_FALSE;
- }
-
return GL_TRUE;
}
@@ -531,18 +414,15 @@ static GLboolean r300EnableTextureRect(GLcontext * ctx, int unit)
r300ContextPtr rmesa = R300_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
+ r300TexObjPtr t = r300_tex_obj(tObj);
ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
- if (t->base.dirty_images[0]) {
+ if (!t->mt || t->dirty_images[0]) {
R300_FIREVERTICES(rmesa);
r300SetTexImages(rmesa, tObj);
- r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
- if (!t->base.memBlock && !t->image_override &&
- !rmesa->prefer_gart_client_texturing)
- return GL_FALSE;
+ r300UploadTexImages(rmesa, t, 0);
}
return GL_TRUE;
@@ -550,34 +430,19 @@ static GLboolean r300EnableTextureRect(GLcontext * ctx, int unit)
static GLboolean r300UpdateTexture(GLcontext * ctx, int unit)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
+ r300TexObjPtr t = r300_tex_obj(tObj);
/* Fallback if there's a texture border */
if (tObj->Image[0][tObj->BaseLevel]->Border > 0)
return GL_FALSE;
- /* Update state if this is a different texture object to last
- * time.
- */
- if (rmesa->state.texture.unit[unit].texobj != t) {
- if (rmesa->state.texture.unit[unit].texobj != NULL) {
- /* The old texture is no longer bound to this texture unit.
- * Mark it as such.
- */
-
- rmesa->state.texture.unit[unit].texobj->base.bound &=
- ~(1 << unit);
- }
-
- rmesa->state.texture.unit[unit].texobj = t;
- t->base.bound |= (1 << unit);
- driUpdateTextureLRU((driTextureObject *) t); /* XXX: should be locked! */
- }
+ /* Fallback if memory upload didn't work */
+ if (!t->mt)
+ return GL_FALSE;
- return !t->border_fallback;
+ return GL_TRUE;
}
void r300SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
@@ -586,20 +451,18 @@ void r300SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
r300ContextPtr rmesa = pDRICtx->driverPrivate;
struct gl_texture_object *tObj =
_mesa_lookup_texture(rmesa->radeon.glCtx, texname);
- r300TexObjPtr t;
+ r300TexObjPtr t = r300_tex_obj(tObj);
uint32_t pitch_val;
if (!tObj)
return;
- t = (r300TexObjPtr) tObj->DriverData;
-
t->image_override = GL_TRUE;
if (!offset)
return;
- t->offset = offset;
+ t->override_offset = offset;
t->pitch_reg &= (1 << 13) -1;
pitch_val = pitch;
diff --git a/src/mesa/drivers/dri/r300/radeon_context.c b/src/mesa/drivers/dri/r300/radeon_context.c
index 3fc724a..a84c8fc 100644
--- a/src/mesa/drivers/dri/r300/radeon_context.c
+++ b/src/mesa/drivers/dri/r300/radeon_context.c
@@ -42,6 +42,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "state.h"
#include "matrix.h"
#include "framebuffer.h"
+#include "drirenderbuffer.h"
#include "drivers/common/driverfuncs.h"
#include "swrast/swrast.h"
@@ -258,6 +259,52 @@ void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
}
}
+static void
+radeon_make_renderbuffer_current(radeonContextPtr radeon,
+ GLframebuffer *draw)
+{
+ int size = radeon->radeonScreen->driScreen->fbSize;
+ void *map = 0;
+ /* if radeon->fake */
+ struct radeon_renderbuffer *rb;
+ uint32_t offset;
+ if (!radeon->bufmgr)
+ return;
+
+ if ((rb = (void *)draw->Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
+
+ offset = radeon->radeonScreen->kernel_mm ? radeon->radeonScreen->front.offset : radeon->radeonScreen->frontOffset;
+ if (!rb->bo)
+ rb->bo = dri_bo_alloc_static(&radeon->bufmgr->base, "front buffer",
+ radeon->radeonScreen->frontOffset, size, map,
+ DRM_BO_FLAG_MEM_VRAM);
+ fprintf(stderr,"front is %p\n", rb->bo);
+ rb->cpp = radeon->radeonScreen->cpp;
+ rb->pitch = radeon->radeonScreen->frontPitch;
+ }
+ if ((rb = (void *)draw->Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
+ offset = radeon->radeonScreen->kernel_mm ? radeon->radeonScreen->back.offset : radeon->radeonScreen->backOffset;
+ if (!rb->bo)
+ rb->bo = dri_bo_alloc_static(&radeon->bufmgr->base, "back buffer",
+ radeon->radeonScreen->backOffset, size, map,
+ DRM_BO_FLAG_MEM_VRAM);
+ fprintf(stderr,"back is %p\n", rb->bo);
+ rb->cpp = radeon->radeonScreen->cpp;
+ rb->pitch = radeon->radeonScreen->backPitch;
+ }
+ if ((rb = (void *)draw->Attachment[BUFFER_DEPTH].Renderbuffer)) {
+ offset = radeon->radeonScreen->kernel_mm ? radeon->radeonScreen->depth.offset : radeon->radeonScreen->depthOffset;
+ if (!rb->bo)
+ rb->bo = dri_bo_alloc_static(&radeon->bufmgr->base, "depth buffer",
+ radeon->radeonScreen->depthOffset, size, map,
+ DRM_BO_FLAG_MEM_VRAM);
+ fprintf(stderr,"depth is %p\n", rb->bo);
+ rb->cpp = radeon->radeonScreen->cpp;
+ rb->pitch = radeon->radeonScreen->depthPitch;
+ }
+}
+
+
/* Force the context `c' to be the current context and associate with it
* buffer `b'.
*/
@@ -265,51 +312,57 @@ GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
__DRIdrawablePrivate * driDrawPriv,
__DRIdrawablePrivate * driReadPriv)
{
- if (driContextPriv) {
- radeonContextPtr radeon =
- (radeonContextPtr) driContextPriv->driverPrivate;
+ radeonContextPtr radeon;
+ GLframebuffer *dfb, *rfb;
+ if (!driContextPriv) {
if (RADEON_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
- radeon->glCtx);
-
- if (radeon->dri.drawable != driDrawPriv) {
- if (driDrawPriv->swap_interval == (unsigned)-1) {
- driDrawPriv->vblFlags =
- (radeon->radeonScreen->irq != 0)
- ? driGetDefaultVBlankFlags(&radeon->
- optionCache)
- : VBLANK_FLAG_NO_IRQ;
+ fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
+ _mesa_make_current(NULL, NULL, NULL);
+ return GL_TRUE;
+ }
- driDrawableInitVBlank(driDrawPriv);
- }
- }
+ radeon = (radeonContextPtr) driContextPriv->driverPrivate;
+ dfb = driDrawPriv->driverPrivate;
+ rfb = driReadPriv->driverPrivate;
- radeon->dri.readable = driReadPriv;
+ if (RADEON_DEBUG & DEBUG_DRI)
+ fprintf(stderr, "%s ctx %p\n", __FUNCTION__, radeon->glCtx);
- if (radeon->dri.drawable != driDrawPriv ||
- radeon->lastStamp != driDrawPriv->lastStamp) {
- radeon->dri.drawable = driDrawPriv;
+ driUpdateFramebufferSize(radeon->glCtx, driDrawPriv);
+ if (driReadPriv != driDrawPriv)
+ driUpdateFramebufferSize(radeon->glCtx, driReadPriv);
- radeonSetCliprects(radeon);
- r300UpdateViewportOffset(radeon->glCtx);
- }
+ radeon_make_renderbuffer_current(radeon, dfb);
- _mesa_make_current(radeon->glCtx,
- (GLframebuffer *) driDrawPriv->
- driverPrivate,
- (GLframebuffer *) driReadPriv->
- driverPrivate);
+ _mesa_make_current(radeon->glCtx, dfb, rfb);
- _mesa_update_state(radeon->glCtx);
+ if (radeon->dri.drawable != driDrawPriv) {
+ if (driDrawPriv->swap_interval == (unsigned)-1) {
+ driDrawPriv->vblFlags =
+ (radeon->radeonScreen->irq != 0)
+ ? driGetDefaultVBlankFlags(&radeon->
+ optionCache)
+ : VBLANK_FLAG_NO_IRQ;
+
+ driDrawableInitVBlank(driDrawPriv);
+ }
+ }
- radeonUpdatePageFlipping(radeon);
- } else {
- if (RADEON_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
- _mesa_make_current(0, 0, 0);
+ radeon->dri.readable = driReadPriv;
+
+ if (radeon->dri.drawable != driDrawPriv ||
+ radeon->lastStamp != driDrawPriv->lastStamp) {
+ radeon->dri.drawable = driDrawPriv;
+
+ radeonSetCliprects(radeon);
+ r300UpdateViewportOffset(radeon->glCtx);
}
+ _mesa_update_state(radeon->glCtx);
+
+ radeonUpdatePageFlipping(radeon);
+
if (RADEON_DEBUG & DEBUG_DRI)
fprintf(stderr, "End %s\n", __FUNCTION__);
return GL_TRUE;
diff --git a/src/mesa/drivers/dri/r300/radeon_context.h b/src/mesa/drivers/dri/r300/radeon_context.h
index 7458d63..828853b 100644
--- a/src/mesa/drivers/dri/r300/radeon_context.h
+++ b/src/mesa/drivers/dri/r300/radeon_context.h
@@ -48,6 +48,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "drm.h"
#include "dri_util.h"
#include "colormac.h"
+#include "radeon_buffer.h"
struct radeon_context;
typedef struct radeon_context radeonContextRec;
@@ -132,12 +133,13 @@ struct radeon_scissor_state {
struct radeon_colorbuffer_state {
GLuint clear;
- GLint drawOffset, drawPitch;
+ struct radeon_renderbuffer *rrb;
};
struct radeon_state {
struct radeon_colorbuffer_state color;
struct radeon_scissor_state scissor;
+ struct radeon_renderbuffer *depth_buffer;
};
/**
@@ -185,6 +187,8 @@ struct radeon_context {
/* Configuration cache
*/
driOptionCache optionCache;
+
+ struct radeon_bufmgr *bufmgr;
};
#define RADEON_CONTEXT(glctx) ((radeonContextPtr)(ctx->DriverCtx))
diff --git a/src/mesa/drivers/dri/r300/radeon_ioctl.c b/src/mesa/drivers/dri/r300/radeon_ioctl.c
index 0c1a195..486ce8e 100644
--- a/src/mesa/drivers/dri/r300/radeon_ioctl.c
+++ b/src/mesa/drivers/dri/r300/radeon_ioctl.c
@@ -42,6 +42,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "swrast/swrast.h"
#include "r300_context.h"
#include "radeon_ioctl.h"
+#include "radeon_buffer.h"
#include "r300_ioctl.h"
#include "r300_state.h"
#include "radeon_reg.h"
@@ -171,7 +172,7 @@ void radeonCopyBuffer(__DRIdrawablePrivate * dPriv,
assert(dPriv->driContextPriv->driverPrivate);
radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
-
+
if (RADEON_DEBUG & DEBUG_IOCTL) {
fprintf(stderr, "\n%s( %p )\n\n", __FUNCTION__,
(void *)radeon->glCtx);
@@ -261,6 +262,8 @@ void radeonPageFlip(__DRIdrawablePrivate * dPriv)
GLint ret;
GLboolean missed_target;
__DRIscreenPrivate *psp = dPriv->driScreenPriv;
+ GLframebuffer *fb = dPriv->driverPrivate;
+ struct radeon_renderbuffer *rrb;
assert(dPriv);
assert(dPriv->driContextPriv);
@@ -268,6 +271,8 @@ void radeonPageFlip(__DRIdrawablePrivate * dPriv)
radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+ rrb = (void *)fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+
if (RADEON_DEBUG & DEBUG_IOCTL) {
fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__,
radeon->sarea->pfCurrentPage);
@@ -315,32 +320,10 @@ void radeonPageFlip(__DRIdrawablePrivate * dPriv)
radeon->swap_count++;
(void)(*psp->systemTime->getUST) (&radeon->swap_ust);
- driFlipRenderbuffers(radeon->glCtx->WinSysDrawBuffer,
+ driFlipRenderbuffers(radeon->glCtx->WinSysDrawBuffer,
radeon->sarea->pfCurrentPage);
- if (radeon->sarea->pfCurrentPage == 1) {
- radeon->state.color.drawOffset = radeon->radeonScreen->frontOffset;
- radeon->state.color.drawPitch = radeon->radeonScreen->frontPitch;
- } else {
- radeon->state.color.drawOffset = radeon->radeonScreen->backOffset;
- radeon->state.color.drawPitch = radeon->radeonScreen->backPitch;
- }
-
- if (IS_R300_CLASS(radeon->radeonScreen)) {
- r300ContextPtr r300 = (r300ContextPtr)radeon;
- R300_STATECHANGE(r300, cb);
- r300->hw.cb.cmd[R300_CB_OFFSET] = r300->radeon.state.color.drawOffset +
- r300->radeon.radeonScreen->fbLocation;
- r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.state.color.drawPitch;
-
- if (r300->radeon.radeonScreen->cpp == 4)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_ARGB8888;
- else
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_RGB565;
-
- if (r300->radeon.sarea->tiling_enabled)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_TILE_ENABLE;
- }
+ radeon->state.color.rrb = rrb;
}
void radeonWaitForIdleLocked(radeonContextPtr radeon)
diff --git a/src/mesa/drivers/dri/r300/radeon_lock.c b/src/mesa/drivers/dri/r300/radeon_lock.c
index d54a821..3529555 100644
--- a/src/mesa/drivers/dri/r300/radeon_lock.c
+++ b/src/mesa/drivers/dri/r300/radeon_lock.c
@@ -44,6 +44,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_state.h"
#include "r300_context.h"
#include "r300_state.h"
+#include "r300_mem.h"
#include "framebuffer.h"
@@ -59,6 +60,8 @@ int prevLockLine = 0;
void radeonUpdatePageFlipping(radeonContextPtr rmesa)
{
int use_back;
+ __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
+ GLframebuffer *fb = drawable->driverPrivate;
rmesa->doPageFlip = rmesa->sarea->pfState;
if (rmesa->glCtx->WinSysDrawBuffer) {
@@ -72,16 +75,12 @@ void radeonUpdatePageFlipping(radeonContextPtr rmesa)
BUFFER_BACK_LEFT) : 1;
use_back ^= (rmesa->sarea->pfCurrentPage == 1);
- if (use_back) {
- rmesa->state.color.drawOffset =
- rmesa->radeonScreen->backOffset;
- rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
- } else {
- rmesa->state.color.drawOffset =
- rmesa->radeonScreen->frontOffset;
- rmesa->state.color.drawPitch =
- rmesa->radeonScreen->frontPitch;
- }
+ if (use_back)
+ rmesa->state.color.rrb = (void *)fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ else
+ rmesa->state.color.rrb = (void *)fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+
+ rmesa->state.depth_buffer = (void *)fb->Attachment[BUFFER_DEPTH].Renderbuffer;
}
/* Update the hardware state. This is called if another context has
@@ -125,12 +124,8 @@ void radeonGetLock(radeonContextPtr rmesa, GLuint flags)
}
if (sarea->ctx_owner != rmesa->dri.hwContext) {
- int i;
-
sarea->ctx_owner = rmesa->dri.hwContext;
- for (i = 0; i < r300->nr_heaps; i++) {
- DRI_AGE_TEXTURES(r300->texture_heaps[i]);
- }
+ radeonBufmgrContendedLockTake(r300->radeon.bufmgr);
}
rmesa->lost_context = GL_TRUE;
diff --git a/src/mesa/drivers/dri/r300/radeon_span.c b/src/mesa/drivers/dri/r300/radeon_span.c
index f1bc56e..7ea0842 100644
--- a/src/mesa/drivers/dri/r300/radeon_span.c
+++ b/src/mesa/drivers/dri/r300/radeon_span.c
@@ -48,7 +48,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r300_ioctl.h"
#include "radeon_span.h"
-#include "drirenderbuffer.h"
+#include "radeon_buffer.h"
#define DBG 0
@@ -58,21 +58,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* information.
*/
#define LOCAL_VARS \
- driRenderbuffer *drb = (driRenderbuffer *) rb; \
- const __DRIdrawablePrivate *dPriv = drb->dPriv; \
+ struct radeon_renderbuffer *rrb = (void *) rb; \
+ const __DRIdrawablePrivate *dPriv = rrb->dPriv; \
const GLuint bottom = dPriv->h - 1; \
- GLubyte *buf = (GLubyte *) drb->flippedData \
- + (dPriv->y * drb->flippedPitch + dPriv->x) * drb->cpp; \
+ GLubyte *buf = (GLubyte *) rrb->bo->virtual \
+ + (dPriv->y * rrb->pitch + dPriv->x) * rrb->cpp; \
GLuint p; \
(void) p;
#define LOCAL_DEPTH_VARS \
- driRenderbuffer *drb = (driRenderbuffer *) rb; \
- const __DRIdrawablePrivate *dPriv = drb->dPriv; \
+ struct radeon_renderbuffer *rrb = (void *) rb; \
+ const __DRIdrawablePrivate *dPriv = rrb->dPriv; \
const GLuint bottom = dPriv->h - 1; \
GLuint xo = dPriv->x; \
GLuint yo = dPriv->y; \
- GLubyte *buf = (GLubyte *) drb->Base.Data;
+ GLubyte *buf = (GLubyte *) rrb->base.Data;
#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
@@ -93,7 +93,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define TAG(x) radeon##x##_RGB565
#define TAG2(x,y) radeon##x##_RGB565##y
-#define GET_PTR(X,Y) (buf + ((Y) * drb->flippedPitch + (X)) * 2)
+#define GET_PTR(X,Y) (buf + ((Y) * rrb->pitch + (X)) * 2)
#include "spantmp2.h"
/* 32 bit, ARGB8888 color spanline and pixel functions
@@ -103,7 +103,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define TAG(x) radeon##x##_ARGB8888
#define TAG2(x,y) radeon##x##_ARGB8888##y
-#define GET_PTR(X,Y) (buf + ((Y) * drb->flippedPitch + (X)) * 4)
+#define GET_PTR(X,Y) (buf + ((Y) * rrb->pitch + (X)) * 4)
#include "spantmp2.h"
/* ================================================================
@@ -120,10 +120,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* too...
*/
-static GLuint radeon_mba_z32(const driRenderbuffer * drb, GLint x, GLint y)
+static GLuint radeon_mba_z32(const struct radeon_renderbuffer * rrb,
+ GLint x, GLint y)
{
- GLuint pitch = drb->pitch;
- if (drb->depthHasSurface) {
+ GLuint pitch = rrb->pitch;
+ if (rrb->depthHasSurface) {
return 4 * (x + y * pitch);
} else {
GLuint ba, address = 0; /* a[0..1] = 0 */
@@ -148,10 +149,10 @@ static GLuint radeon_mba_z32(const driRenderbuffer * drb, GLint x, GLint y)
}
static INLINE GLuint
-radeon_mba_z16(const driRenderbuffer * drb, GLint x, GLint y)
+radeon_mba_z16(const struct radeon_renderbuffer *rrb, GLint x, GLint y)
{
- GLuint pitch = drb->pitch;
- if (drb->depthHasSurface) {
+ GLuint pitch = rrb->pitch;
+ if (rrb->depthHasSurface) {
return 2 * (x + y * pitch);
} else {
GLuint ba, address = 0; /* a[0] = 0 */
@@ -173,10 +174,10 @@ radeon_mba_z16(const driRenderbuffer * drb, GLint x, GLint y)
/* 16-bit depth buffer functions
*/
#define WRITE_DEPTH( _x, _y, d ) \
- *(GLushort *)(buf + radeon_mba_z16( drb, _x + xo, _y + yo )) = d;
+ *(GLushort *)(buf + radeon_mba_z16( rrb, _x + xo, _y + yo )) = d;
#define READ_DEPTH( d, _x, _y ) \
- d = *(GLushort *)(buf + radeon_mba_z16( drb, _x + xo, _y + yo ));
+ d = *(GLushort *)(buf + radeon_mba_z16( rrb, _x + xo, _y + yo ));
#define TAG(x) radeon##x##_z16
#include "depthtmp.h"
@@ -189,7 +190,7 @@ radeon_mba_z16(const driRenderbuffer * drb, GLint x, GLint y)
#ifdef COMPILE_R300
#define WRITE_DEPTH( _x, _y, d ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
+ GLuint offset = radeon_mba_z32( rrb, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0x000000ff; \
tmp |= ((d << 8) & 0xffffff00); \
@@ -198,7 +199,7 @@ do { \
#else
#define WRITE_DEPTH( _x, _y, d ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
+ GLuint offset = radeon_mba_z32( rrb, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0xff000000; \
tmp |= ((d) & 0x00ffffff); \
@@ -209,12 +210,12 @@ do { \
#ifdef COMPILE_R300
#define READ_DEPTH( d, _x, _y ) \
do { \
- d = (*(GLuint *)(buf + radeon_mba_z32( drb, _x + xo, \
+ d = (*(GLuint *)(buf + radeon_mba_z32( rrb, _x + xo, \
_y + yo )) & 0xffffff00) >> 8; \
}while(0)
#else
#define READ_DEPTH( d, _x, _y ) \
- d = *(GLuint *)(buf + radeon_mba_z32( drb, _x + xo, \
+ d = *(GLuint *)(buf + radeon_mba_z32( rrb, _x + xo, \
_y + yo )) & 0x00ffffff;
#endif
@@ -230,7 +231,7 @@ do { \
#ifdef COMPILE_R300
#define WRITE_STENCIL( _x, _y, d ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
+ GLuint offset = radeon_mba_z32( rrb, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0xffffff00; \
tmp |= (d) & 0xff; \
@@ -239,7 +240,7 @@ do { \
#else
#define WRITE_STENCIL( _x, _y, d ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
+ GLuint offset = radeon_mba_z32( rrb, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
tmp &= 0x00ffffff; \
tmp |= (((d) & 0xff) << 24); \
@@ -250,14 +251,14 @@ do { \
#ifdef COMPILE_R300
#define READ_STENCIL( d, _x, _y ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
+ GLuint offset = radeon_mba_z32( rrb, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
d = tmp & 0x000000ff; \
} while (0)
#else
#define READ_STENCIL( d, _x, _y ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
+ GLuint offset = radeon_mba_z32( rrb, _x + xo, _y + yo ); \
GLuint tmp = *(GLuint *)(buf + offset); \
d = (tmp & 0xff000000) >> 24; \
} while (0)
@@ -300,10 +301,10 @@ static void radeonSpanRenderStart(GLcontext * ctx)
*/
{
int p;
- driRenderbuffer *drb =
- (driRenderbuffer *) ctx->WinSysDrawBuffer->_ColorDrawBuffers[0];
+ struct radeon_renderbuffer *rrb =
+ (void *) ctx->WinSysDrawBuffer->_ColorDrawBuffers[0];
volatile int *buf =
- (volatile int *)(rmesa->dri.screen->pFB + drb->offset);
+ (volatile int *)(rmesa->dri.screen->pFB + rrb->bo->offset);
p = *buf;
}
}
@@ -326,20 +327,17 @@ void radeonInitSpanFuncs(GLcontext * ctx)
/**
* Plug in the Get/Put routines for the given driRenderbuffer.
*/
-void radeonSetSpanFunctions(driRenderbuffer * drb, const GLvisual * vis)
+void radeonSetSpanFunctions(struct radeon_renderbuffer *rrb)
{
- if (drb->Base.InternalFormat == GL_RGBA) {
- if (vis->redBits == 5 && vis->greenBits == 6
- && vis->blueBits == 5) {
- radeonInitPointers_RGB565(&drb->Base);
- } else {
- radeonInitPointers_ARGB8888(&drb->Base);
- }
- } else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
- radeonInitDepthPointers_z16(&drb->Base);
- } else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
- radeonInitDepthPointers_z24_s8(&drb->Base);
- } else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
- radeonInitStencilPointers_z24_s8(&drb->Base);
- }
+ if (rrb->base.InternalFormat == GL_RGB5) {
+ radeonInitPointers_RGB565(&rrb->base);
+ } else if (rrb->base.InternalFormat == GL_RGBA8) {
+ radeonInitPointers_ARGB8888(&rrb->base);
+ } else if (rrb->base.InternalFormat == GL_DEPTH_COMPONENT16) {
+ radeonInitDepthPointers_z16(&rrb->base);
+ } else if (rrb->base.InternalFormat == GL_DEPTH_COMPONENT24) {
+ radeonInitDepthPointers_z24_s8(&rrb->base);
+ } else if (rrb->base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
+ radeonInitStencilPointers_z24_s8(&rrb->base);
+ }
}
diff --git a/src/mesa/drivers/dri/r300/radeon_state.c b/src/mesa/drivers/dri/r300/radeon_state.c
index d81318c..a7720da 100644
--- a/src/mesa/drivers/dri/r300/radeon_state.c
+++ b/src/mesa/drivers/dri/r300/radeon_state.c
@@ -222,14 +222,6 @@ void radeonEnable(GLcontext* ctx, GLenum cap, GLboolean state)
void radeonInitState(radeonContextPtr radeon)
{
radeon->Fallback = 0;
-
- if (radeon->glCtx->Visual.doubleBufferMode && radeon->sarea->pfCurrentPage == 0) {
- radeon->state.color.drawOffset = radeon->radeonScreen->backOffset;
- radeon->state.color.drawPitch = radeon->radeonScreen->backPitch;
- } else {
- radeon->state.color.drawOffset = radeon->radeonScreen->frontOffset;
- radeon->state.color.drawPitch = radeon->radeonScreen->frontPitch;
- }
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_buffer.h b/src/mesa/drivers/dri/radeon/radeon_buffer.h
new file mode 100644
index 0000000..730c40b
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_buffer.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software")
+ * to deal in the software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * them Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Adam Jackson <ajax@redhat.com>
+ */
+
+#ifndef RADEON_BUFFER_H
+#define RADEON_BUFFER_H
+
+#include "dri_bufmgr.h"
+
+struct radeon_renderbuffer
+{
+ struct gl_renderbuffer base;
+ dri_bo *bo;
+ unsigned int cpp;
+ /* unsigned int offset; */
+ unsigned int pitch;
+ unsigned int height;
+
+ /* boo Xorg 6.8.2 compat */
+ int depthHasSurface;
+
+ __DRIdrawablePrivate *dPriv;
+};
+
+struct radeon_bufmgr {
+ dri_bufmgr base;
+};
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index 84b5c46..10a49d2 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -46,6 +46,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_chipset.h"
#include "radeon_macros.h"
#include "radeon_screen.h"
+#include "radeon_buffer.h"
#if !RADEON_COMMON
#include "radeon_context.h"
#include "radeon_span.h"
@@ -69,6 +70,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "GL/internal/dri_interface.h"
+#include <errno.h>
+#include <sys/ioctl.h>
+
/* Radeon configuration
*/
#include "xmlpool.h"
@@ -350,6 +354,79 @@ static const __DRItexOffsetExtension r300texOffsetExtension = {
};
#endif
+
+static void
+radeon_gem_update_handle(radeonScreenPtr screen, __DRIscreenPrivate *sPriv,
+ struct radeon_gem_object *gem_obj)
+{
+ struct drm_gem_close close_args;
+ struct drm_gem_open args;
+ struct drm_radeon_gem_mmap mmap_args;
+ struct drm_radeon_gem_pin pin_args;
+ int ret;
+
+ if (gem_obj->gem_handle) {
+ close_args.handle = gem_obj->gem_handle;
+
+ ioctl(sPriv->fd, DRM_IOCTL_GEM_CLOSE, &close_args);
+ gem_obj->gem_handle = 0;
+ }
+
+ /* do open */
+ args.name = gem_obj->gem_name;
+ ret = ioctl(sPriv->fd, DRM_IOCTL_GEM_OPEN, &args);
+ if (ret)
+ return;
+
+ gem_obj->gem_handle = args.handle;
+ gem_obj->size = args.size;
+
+ mmap_args.handle = gem_obj->gem_handle;
+ mmap_args.size = gem_obj->size;
+ mmap_args.offset = 0;
+
+ ret = drmCommandWriteRead(sPriv->fd, DRM_RADEON_GEM_MMAP, &mmap_args,
+ sizeof(mmap_args));
+
+ if (ret)
+ return;
+
+ gem_obj->map = (void *)(unsigned long)(mmap_args.addr_ptr);
+
+ pin_args.handle = gem_obj->gem_handle;
+ pin_args.alignment = 0;
+
+ ret = drmCommandWriteRead(sPriv->fd, DRM_RADEON_GEM_PIN, &pin_args,
+ sizeof(pin_args));
+
+ if (ret)
+ return;
+
+ gem_obj->offset = pin_args.offset;
+
+ fprintf(stderr,"handle %d, size %llx, ptr %p, offset %llx\n", gem_obj->gem_handle,
+ gem_obj->size, gem_obj->map, gem_obj->offset);
+}
+
+static int
+radeon_init_mm_buffers(radeonScreenPtr screen, __DRIscreenPrivate *sPriv,
+ RADEONDRIPtr dri_priv)
+{
+ /* STOP GAP HERE */
+
+ screen->front.gem_name = dri_priv->frontOffset;
+ radeon_gem_update_handle(screen, sPriv, &screen->front);
+ screen->back.gem_name = dri_priv->backOffset;
+ radeon_gem_update_handle(screen, sPriv, &screen->back);
+ screen->depth.gem_name = dri_priv->depthOffset;
+ radeon_gem_update_handle(screen, sPriv, &screen->depth);
+
+ screen->vram_texture.gem_name = dri_priv->textureOffset;
+ radeon_gem_update_handle(screen, sPriv, &screen->vram_texture);
+ screen->vram_texture.gem_name = dri_priv->gartTexHandle;
+ radeon_gem_update_handle(screen, sPriv, &screen->gart_texture);
+}
+
/* Create the device specific screen private data struct.
*/
static radeonScreenPtr
@@ -389,6 +466,21 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
screen->card_type = (dri_priv->IsPCI ? RADEON_CARD_PCI : RADEON_CARD_AGP);
{
int ret;
+
+#ifdef RADEON_PARAM_KERNEL_MM
+ ret = radeonGetParam( sPriv->fd, RADEON_PARAM_KERNEL_MM,
+ &screen->kernel_mm);
+
+ if (ret && ret != -EINVAL) {
+ FREE( screen );
+ fprintf(stderr, "drm_radeon_getparam_t (RADEON_OFFSET): %d\n", ret);
+ return NULL;
+ }
+
+ if (ret == -EINVAL)
+ screen->kernel_mm = 0;
+#endif
+
ret = radeonGetParam( sPriv->fd, RADEON_PARAM_GART_BUFFER_OFFSET,
&screen->gart_buffer_offset);
@@ -422,32 +514,34 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
screen->drmSupportsVertexProgram = (sPriv->drm_version.minor >= 25);
}
- screen->mmio.handle = dri_priv->registerHandle;
- screen->mmio.size = dri_priv->registerSize;
- if ( drmMap( sPriv->fd,
- screen->mmio.handle,
- screen->mmio.size,
- &screen->mmio.map ) ) {
- FREE( screen );
- __driUtilMessage("%s: drmMap failed\n", __FUNCTION__ );
- return NULL;
- }
+ if (!screen->kernel_mm) {
+ screen->mmio.handle = dri_priv->registerHandle;
+ screen->mmio.size = dri_priv->registerSize;
+ if ( drmMap( sPriv->fd,
+ screen->mmio.handle,
+ screen->mmio.size,
+ &screen->mmio.map ) ) {
+ FREE( screen );
+ __driUtilMessage("%s: drmMap failed\n", __FUNCTION__ );
+ return NULL;
+ }
- RADEONMMIO = screen->mmio.map;
+ RADEONMMIO = screen->mmio.map;
- screen->status.handle = dri_priv->statusHandle;
- screen->status.size = dri_priv->statusSize;
- if ( drmMap( sPriv->fd,
- screen->status.handle,
- screen->status.size,
- &screen->status.map ) ) {
- drmUnmap( screen->mmio.map, screen->mmio.size );
- FREE( screen );
- __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__ );
- return NULL;
+ screen->status.handle = dri_priv->statusHandle;
+ screen->status.size = dri_priv->statusSize;
+ if ( drmMap( sPriv->fd,
+ screen->status.handle,
+ screen->status.size,
+ &screen->status.map ) ) {
+ drmUnmap( screen->mmio.map, screen->mmio.size );
+ FREE( screen );
+ __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__ );
+ return NULL;
+ }
+ screen->scratch = (__volatile__ u_int32_t *)
+ ((GLubyte *)screen->status.map + RADEON_SCRATCH_REG_OFFSET);
}
- screen->scratch = (__volatile__ u_int32_t *)
- ((GLubyte *)screen->status.map + RADEON_SCRATCH_REG_OFFSET);
screen->buffers = drmMapBufs( sPriv->fd );
if ( !screen->buffers ) {
@@ -458,22 +552,24 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
return NULL;
}
- if ( dri_priv->gartTexHandle && dri_priv->gartTexMapSize ) {
- screen->gartTextures.handle = dri_priv->gartTexHandle;
- screen->gartTextures.size = dri_priv->gartTexMapSize;
- if ( drmMap( sPriv->fd,
- screen->gartTextures.handle,
- screen->gartTextures.size,
- (drmAddressPtr)&screen->gartTextures.map ) ) {
- drmUnmapBufs( screen->buffers );
- drmUnmap( screen->status.map, screen->status.size );
- drmUnmap( screen->mmio.map, screen->mmio.size );
- FREE( screen );
- __driUtilMessage("%s: drmMap failed for GART texture area\n", __FUNCTION__);
- return NULL;
+ if (!screen->kernel_mm) {
+ if ( dri_priv->gartTexHandle && dri_priv->gartTexMapSize ) {
+ screen->gartTextures.handle = dri_priv->gartTexHandle;
+ screen->gartTextures.size = dri_priv->gartTexMapSize;
+ if ( drmMap( sPriv->fd,
+ screen->gartTextures.handle,
+ screen->gartTextures.size,
+ (drmAddressPtr)&screen->gartTextures.map ) ) {
+ drmUnmapBufs( screen->buffers );
+ drmUnmap( screen->status.map, screen->status.size );
+ drmUnmap( screen->mmio.map, screen->mmio.size );
+ FREE( screen );
+ __driUtilMessage("%s: drmMap failed for GART texture area\n", __FUNCTION__);
+ return NULL;
+ }
+
+ screen->gart_texture_offset = dri_priv->gartTexOffset + screen->gart_base;
}
-
- screen->gart_texture_offset = dri_priv->gartTexOffset + screen->gart_base;
}
screen->chip_flags = 0;
@@ -840,7 +936,7 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
ret = radeonGetParam( sPriv->fd, RADEON_PARAM_FB_LOCATION,
&temp);
if (ret) {
- if (screen->chip_family < CHIP_FAMILY_RS690)
+ if (screen->chip_family < CHIP_FAMILY_RS690 && !screen->kernel_mm)
screen->fbLocation = ( INREG( RADEON_MC_FB_LOCATION ) & 0xffff) << 16;
else {
FREE( screen );
@@ -881,55 +977,58 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
}
}
- if ( sPriv->drm_version.minor >= 10 ) {
- drm_radeon_setparam_t sp;
+ if (!screen->kernel_mm) {
+ if ( sPriv->drm_version.minor >= 10 ) {
+ drm_radeon_setparam_t sp;
- sp.param = RADEON_SETPARAM_FB_LOCATION;
- sp.value = screen->fbLocation;
+ sp.param = RADEON_SETPARAM_FB_LOCATION;
+ sp.value = screen->fbLocation;
- drmCommandWrite( sPriv->fd, DRM_RADEON_SETPARAM,
- &sp, sizeof( sp ) );
- }
-
- screen->frontOffset = dri_priv->frontOffset;
- screen->frontPitch = dri_priv->frontPitch;
- screen->backOffset = dri_priv->backOffset;
- screen->backPitch = dri_priv->backPitch;
- screen->depthOffset = dri_priv->depthOffset;
- screen->depthPitch = dri_priv->depthPitch;
-
- /* Check if ddx has set up a surface reg to cover depth buffer */
- screen->depthHasSurface = (sPriv->ddx_version.major > 4) ||
- /* these chips don't use tiled z without hyperz. So always pretend
- we have set up a surface which will cause linear reads/writes */
- ((screen->chip_family & RADEON_CLASS_R100) &&
- !(screen->chip_flags & RADEON_CHIPSET_TCL));
-
- if ( dri_priv->textureSize == 0 ) {
- screen->texOffset[RADEON_LOCAL_TEX_HEAP] = screen->gart_texture_offset;
- screen->texSize[RADEON_LOCAL_TEX_HEAP] = dri_priv->gartTexMapSize;
- screen->logTexGranularity[RADEON_LOCAL_TEX_HEAP] =
- dri_priv->log2GARTTexGran;
- } else {
- screen->texOffset[RADEON_LOCAL_TEX_HEAP] = dri_priv->textureOffset
- + screen->fbLocation;
- screen->texSize[RADEON_LOCAL_TEX_HEAP] = dri_priv->textureSize;
- screen->logTexGranularity[RADEON_LOCAL_TEX_HEAP] =
- dri_priv->log2TexGran;
- }
+ drmCommandWrite( sPriv->fd, DRM_RADEON_SETPARAM,
+ &sp, sizeof( sp ) );
+ }
- if ( !screen->gartTextures.map || dri_priv->textureSize == 0
- || getenv( "RADEON_GARTTEXTURING_FORCE_DISABLE" ) ) {
- screen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1;
- screen->texOffset[RADEON_GART_TEX_HEAP] = 0;
- screen->texSize[RADEON_GART_TEX_HEAP] = 0;
- screen->logTexGranularity[RADEON_GART_TEX_HEAP] = 0;
+ screen->frontOffset = dri_priv->frontOffset;
+ screen->frontPitch = dri_priv->frontPitch;
+ screen->backOffset = dri_priv->backOffset;
+ screen->backPitch = dri_priv->backPitch;
+ screen->depthOffset = dri_priv->depthOffset;
+ screen->depthPitch = dri_priv->depthPitch;
+
+ /* Check if ddx has set up a surface reg to cover depth buffer */
+ screen->depthHasSurface = (sPriv->ddx_version.major > 4) ||
+ /* these chips don't use tiled z without hyperz. So always pretend
+ we have set up a surface which will cause linear reads/writes */
+ ((screen->chip_family & RADEON_CLASS_R100) &&
+ !(screen->chip_flags & RADEON_CHIPSET_TCL));
+
+ if ( dri_priv->textureSize == 0 ) {
+ screen->texOffset[RADEON_LOCAL_TEX_HEAP] = screen->gart_texture_offset;
+ screen->texSize[RADEON_LOCAL_TEX_HEAP] = dri_priv->gartTexMapSize;
+ screen->logTexGranularity[RADEON_LOCAL_TEX_HEAP] =
+ dri_priv->log2GARTTexGran;
+ } else {
+ screen->texOffset[RADEON_LOCAL_TEX_HEAP] = dri_priv->textureOffset
+ + screen->fbLocation;
+ screen->texSize[RADEON_LOCAL_TEX_HEAP] = dri_priv->textureSize;
+ screen->logTexGranularity[RADEON_LOCAL_TEX_HEAP] =
+ dri_priv->log2TexGran;
+ }
+
+ if ( !screen->gartTextures.map || dri_priv->textureSize == 0
+ || getenv( "RADEON_GARTTEXTURING_FORCE_DISABLE" ) ) {
+ screen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1;
+ screen->texOffset[RADEON_GART_TEX_HEAP] = 0;
+ screen->texSize[RADEON_GART_TEX_HEAP] = 0;
+ screen->logTexGranularity[RADEON_GART_TEX_HEAP] = 0;
+ } else {
+ screen->numTexHeaps = RADEON_NR_TEX_HEAPS;
+ screen->texOffset[RADEON_GART_TEX_HEAP] = screen->gart_texture_offset;
+ screen->texSize[RADEON_GART_TEX_HEAP] = dri_priv->gartTexMapSize;
+ screen->logTexGranularity[RADEON_GART_TEX_HEAP] = dri_priv->log2GARTTexGran;
+ }
} else {
- screen->numTexHeaps = RADEON_NR_TEX_HEAPS;
- screen->texOffset[RADEON_GART_TEX_HEAP] = screen->gart_texture_offset;
- screen->texSize[RADEON_GART_TEX_HEAP] = dri_priv->gartTexMapSize;
- screen->logTexGranularity[RADEON_GART_TEX_HEAP] =
- dri_priv->log2GARTTexGran;
+ radeon_init_mm_buffers(screen, sPriv, dri_priv);
}
i = 0;
@@ -975,12 +1074,14 @@ radeonDestroyScreen( __DRIscreenPrivate *sPriv )
if (!screen)
return;
- if ( screen->gartTextures.map ) {
- drmUnmap( screen->gartTextures.map, screen->gartTextures.size );
- }
drmUnmapBufs( screen->buffers );
- drmUnmap( screen->status.map, screen->status.size );
- drmUnmap( screen->mmio.map, screen->mmio.size );
+ if (!screen->kernel_mm) {
+ if ( screen->gartTextures.map ) {
+ drmUnmap( screen->gartTextures.map, screen->gartTextures.size );
+ }
+ drmUnmap( screen->status.map, screen->status.size );
+ drmUnmap( screen->mmio.map, screen->mmio.size );
+ }
/* free all option information */
driDestroyOptionInfo (&screen->optionCache);
@@ -1004,6 +1105,158 @@ radeonInitDriver( __DRIscreenPrivate *sPriv )
return GL_TRUE;
}
+#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R300)
+static GLboolean
+radeon_alloc_window_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum intFormat, GLuint w, GLuint h)
+{
+ rb->Width = w;
+ rb->Height = h;
+ rb->_ActualFormat = intFormat;
+
+ return GL_TRUE;
+}
+
+
+static struct radeon_renderbuffer *
+radeon_create_renderbuffer(GLenum format)
+{
+ struct radeon_renderbuffer *ret;
+
+ ret = CALLOC_STRUCT(radeon_renderbuffer);
+ if (!ret)
+ return NULL;
+
+ _mesa_init_renderbuffer(&ret->base, 0);
+
+ /* XXX format junk */
+ switch (format) {
+ case GL_RGB5:
+ ret->base._ActualFormat = GL_RGB5;
+ ret->base._BaseFormat = GL_RGBA;
+ ret->base.RedBits = 5;
+ ret->base.GreenBits = 6;
+ ret->base.BlueBits = 5;
+ ret->base.DataType = GL_UNSIGNED_BYTE;
+ break;
+ case GL_RGBA8:
+ ret->base._ActualFormat = GL_RGBA8;
+ ret->base._BaseFormat = GL_RGBA;
+ ret->base.RedBits = 8;
+ ret->base.GreenBits = 8;
+ ret->base.BlueBits = 8;
+ ret->base.AlphaBits = 8;
+ ret->base.DataType = GL_UNSIGNED_BYTE;
+ break;
+ case GL_STENCIL_INDEX8_EXT:
+ ret->base._ActualFormat = GL_STENCIL_INDEX8_EXT;
+ ret->base._BaseFormat = GL_STENCIL_INDEX;
+ ret->base.StencilBits = 8;
+ ret->base.DataType = GL_UNSIGNED_BYTE;
+ break;
+ case GL_DEPTH_COMPONENT16:
+ ret->base._ActualFormat = GL_DEPTH_COMPONENT16;
+ ret->base._BaseFormat = GL_DEPTH_COMPONENT;
+ ret->base.DepthBits = 16;
+ ret->base.DataType = GL_UNSIGNED_SHORT;
+ break;
+ case GL_DEPTH_COMPONENT24:
+ ret->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+ ret->base._BaseFormat = GL_DEPTH_COMPONENT;
+ ret->base.DepthBits = 24;
+ ret->base.DataType = GL_UNSIGNED_INT;
+ break;
+ case GL_DEPTH24_STENCIL8_EXT:
+ ret->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+ ret->base._BaseFormat = GL_DEPTH_STENCIL_EXT;
+ ret->base.DepthBits = 24;
+ ret->base.StencilBits = 8;
+ ret->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ break;
+ default:
+ /* whoops */
+ break;
+ }
+
+ ret->base.InternalFormat = format;
+
+ ret->base.AllocStorage = radeon_alloc_window_storage;
+
+ radeonSetSpanFunctions(ret);
+
+ return ret;
+}
+
+/**
+ * Create the Mesa framebuffer and renderbuffers for a given window/drawable.
+ *
+ * \todo This function (and its interface) will need to be updated to support
+ * pbuffers.
+ */
+static GLboolean
+radeonCreateBuffer( __DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *mesaVis,
+ GLboolean isPixmap )
+{
+ radeonScreenPtr screen = (radeonScreenPtr) driScrnPriv->private;
+
+ const GLboolean swDepth = GL_FALSE;
+ const GLboolean swAlpha = GL_FALSE;
+ const GLboolean swAccum = mesaVis->accumRedBits > 0;
+ const GLboolean swStencil = mesaVis->stencilBits > 0 &&
+ mesaVis->depthBits != 24;
+ GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8);
+ GLenum depthFormat = GL_NONE;
+ struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
+
+ if (mesaVis->depthBits == 16)
+ depthFormat = GL_DEPTH_COMPONENT16;
+ else if (mesaVis->depthBits == 24)
+ depthFormat = GL_DEPTH_COMPONENT24;
+
+ /* front color renderbuffer */
+ {
+ struct radeon_renderbuffer *front =
+ radeon_create_renderbuffer(rgbFormat);
+ _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &front->base);
+ }
+
+ /* back color renderbuffer */
+ if (mesaVis->doubleBufferMode) {
+ struct radeon_renderbuffer *back =
+ radeon_create_renderbuffer(GL_RGBA);
+ _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &back->base);
+ }
+
+ /* depth renderbuffer */
+ if (depthFormat != GL_NONE) {
+ struct radeon_renderbuffer *depth =
+ radeon_create_renderbuffer(depthFormat);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depth->base);
+ depth->depthHasSurface = screen->depthHasSurface;
+ }
+
+ /* stencil renderbuffer */
+ if (mesaVis->stencilBits > 0 && !swStencil) {
+ struct radeon_renderbuffer *stencil =
+ radeon_create_renderbuffer(GL_STENCIL_INDEX8_EXT);
+ _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencil->base);
+ stencil->depthHasSurface = screen->depthHasSurface;
+ }
+
+ _mesa_add_soft_renderbuffers(fb,
+ GL_FALSE, /* color */
+ swDepth,
+ swStencil,
+ swAccum,
+ swAlpha,
+ GL_FALSE /* aux */);
+ driDrawPriv->driverPrivate = (void *) fb;
+
+ return (driDrawPriv->driverPrivate != NULL);
+}
+#else
/**
* Create the Mesa framebuffer and renderbuffers for a given window/drawable.
@@ -1105,6 +1358,11 @@ radeonCreateBuffer( __DRIscreenPrivate *driScrnPriv,
}
+
+
+#endif
+
+
static void
radeonDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
@@ -1199,11 +1457,11 @@ radeonInitScreen(__DRIscreenPrivate *psp)
if (!radeonInitDriver(psp))
return NULL;
+ /* for now fill in all modes */
return radeonFillInModes( psp,
dri_priv->bpp,
(dri_priv->bpp == 16) ? 16 : 24,
- (dri_priv->bpp == 16) ? 0 : 8,
- (dri_priv->backOffset != dri_priv->depthOffset) );
+ (dri_priv->bpp == 16) ? 0 : 8, 1);
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.h b/src/mesa/drivers/dri/radeon/radeon_screen.h
index ab859d5..82eb7d8 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.h
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.h
@@ -55,6 +55,14 @@ typedef struct {
drmAddress map; /* Mapping of the DRM region */
} radeonRegionRec, *radeonRegionPtr;
+struct radeon_gem_object {
+ uint32_t gem_name;
+ uint32_t gem_handle;
+ uint64_t size;
+ void *map;
+ uint64_t offset;
+};
+
typedef struct {
int chip_family;
int chip_flags;
@@ -107,6 +115,13 @@ typedef struct {
const __DRIextension *extensions[8];
int num_gb_pipes;
+
+ int kernel_mm;
+ struct radeon_gem_object front;
+ struct radeon_gem_object back;
+ struct radeon_gem_object depth;
+ struct radeon_gem_object vram_texture;
+ struct radeon_gem_object gart_texture;
} radeonScreenRec, *radeonScreenPtr;
#define IS_R100_CLASS(screen) \
diff --git a/src/mesa/drivers/dri/radeon/radeon_span.h b/src/mesa/drivers/dri/radeon/radeon_span.h
index 9abe086..1650a9b 100644
--- a/src/mesa/drivers/dri/radeon/radeon_span.h
+++ b/src/mesa/drivers/dri/radeon/radeon_span.h
@@ -44,7 +44,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "drirenderbuffer.h"
+#include "radeon_buffer.h"
+
extern void radeonInitSpanFuncs(GLcontext * ctx);
-extern void radeonSetSpanFunctions(driRenderbuffer * rb, const GLvisual * vis);
+#if COMPILE_R300
+extern void radeonSetSpanFunctions(struct radeon_renderbuffer *rrb);
+#else
+extern void radeonSetSpanFunctions(driRenderbuffer * rb, const GLvisual * vis);
+#endif
#endif