#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "vbo/vbo.h"
+#include "vbo/vbo_split.h"
#include "tnl/tnl.h"
#include "tnl/t_vp_build.h"
-#include "radeon_reg.h"
-#include "radeon_macros.h"
#include "r300_context.h"
#include "r300_ioctl.h"
#include "r300_state.h"
return num_verts - verts_off;
}
-static void r300EmitElts(GLcontext * ctx, unsigned long n_elts)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- void *out;
- GLuint size;
-
- size = ((rmesa->ind_buf.is_32bit ? 4 : 2) * n_elts + 3) & ~3;
-
- radeonAllocDmaRegion(&rmesa->radeon, &rmesa->radeon.tcl.elt_dma_bo,
- &rmesa->radeon.tcl.elt_dma_offset, size, 4);
- radeon_bo_map(rmesa->radeon.tcl.elt_dma_bo, 1);
- out = rmesa->radeon.tcl.elt_dma_bo->ptr + rmesa->radeon.tcl.elt_dma_offset;
- memcpy(out, rmesa->ind_buf.ptr, size);
- radeon_bo_unmap(rmesa->radeon.tcl.elt_dma_bo);
-}
-
-static void r300FireEB(r300ContextPtr rmesa, int vertex_count, int type)
+static void r300FireEB(r300ContextPtr rmesa, int vertex_count, int type, int offset)
{
BATCH_LOCALS(&rmesa->radeon);
+ int size;
+
+ /* offset is in indices */
+ BEGIN_BATCH(10);
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_INDX_2, 0);
+ if (rmesa->ind_buf.is_32bit) {
+ /* convert to bytes */
+ offset *= 4;
+ size = vertex_count;
+ OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
+ (vertex_count << 16) | type |
+ R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
+ } else {
+ /* convert to bytes */
+ offset *= 2;
+ size = (vertex_count + 1) >> 1;
+ OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
+ (vertex_count << 16) | type);
+ }
- r300_emit_scissor(rmesa->radeon.glCtx);
- if (vertex_count > 0) {
- int size;
-
- BEGIN_BATCH(10);
- OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_INDX_2, 0);
- if (rmesa->ind_buf.is_32bit) {
- size = vertex_count;
- OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
- ((vertex_count + 0) << 16) | type |
- R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
- } else {
- size = (vertex_count + 1) >> 1;
- OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
- ((vertex_count + 0) << 16) | type);
- }
-
- if (!rmesa->radeon.radeonScreen->kernel_mm) {
- OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER, 2);
- OUT_BATCH(R300_INDX_BUFFER_ONE_REG_WR | (0 << R300_INDX_BUFFER_SKIP_SHIFT) |
- (R300_VAP_PORT_IDX0 >> 2));
- OUT_BATCH_RELOC(rmesa->radeon.tcl.elt_dma_offset,
- rmesa->radeon.tcl.elt_dma_bo,
- rmesa->radeon.tcl.elt_dma_offset,
- RADEON_GEM_DOMAIN_GTT, 0, 0);
- OUT_BATCH(size);
- } else {
- OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER, 2);
- OUT_BATCH(R300_INDX_BUFFER_ONE_REG_WR | (0 << R300_INDX_BUFFER_SKIP_SHIFT) |
- (R300_VAP_PORT_IDX0 >> 2));
- OUT_BATCH(rmesa->radeon.tcl.elt_dma_offset);
- OUT_BATCH(size);
- radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
- rmesa->radeon.tcl.elt_dma_bo,
- RADEON_GEM_DOMAIN_GTT, 0, 0);
- }
- END_BATCH();
+ if (!rmesa->radeon.radeonScreen->kernel_mm) {
+ OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER, 2);
+ OUT_BATCH(R300_INDX_BUFFER_ONE_REG_WR | (0 << R300_INDX_BUFFER_SKIP_SHIFT) |
+ (R300_VAP_PORT_IDX0 >> 2));
+ OUT_BATCH_RELOC(0, rmesa->ind_buf.bo, rmesa->ind_buf.bo_offset + offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
+ OUT_BATCH(size);
+ } else {
+ OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER, 2);
+ OUT_BATCH(R300_INDX_BUFFER_ONE_REG_WR | (0 << R300_INDX_BUFFER_SKIP_SHIFT) |
+ (R300_VAP_PORT_IDX0 >> 2));
+ OUT_BATCH(rmesa->ind_buf.bo_offset + offset);
+ OUT_BATCH(size);
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->ind_buf.bo, RADEON_GEM_DOMAIN_GTT, 0, 0);
}
+ END_BATCH();
}
static void r300EmitAOS(r300ContextPtr rmesa, GLuint nr, GLuint offset)
int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
int i;
- if (RADEON_DEBUG & DEBUG_VERTS)
+ if (RADEON_DEBUG & RADEON_VERTS)
fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__, nr,
offset);
-
if (!rmesa->radeon.radeonScreen->kernel_mm) {
BEGIN_BATCH(sz+2+(nr * 2));
OUT_BATCH_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1);
{
BATCH_LOCALS(&rmesa->radeon);
- r300_emit_scissor(rmesa->radeon.glCtx);
+ r300_emit_scissor(rmesa->radeon.glCtx);
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);
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.
- */
- rcommonEnsureCmdBufSpace(&rmesa->radeon, 128, __FUNCTION__);
+ if (rmesa->ind_buf.bo) {
+ GLuint first, incr, offset = 0;
- if (rmesa->ind_buf.ptr) {
- if (num_verts > 65535) {
- /* not implemented yet */
- WARN_ONCE("Too many elts\n");
+ if (!split_prim_inplace(prim & PRIM_MODE_MASK, &first, &incr) &&
+ num_verts > 65500) {
+ WARN_ONCE("Fixme: can't handle spliting prim %d\n", prim);
return;
}
- /* Note: The following is incorrect, but it's the best I can do
- * without a major refactoring of how DMA memory is handled.
- * The problem: Ensuring that both vertex arrays *and* index
- * arrays are at the right position, and then ensuring that
- * the LOAD_VBPNTR, DRAW_INDX and INDX_BUFFER packets are emitted
- * at once.
- *
- * So why is the following incorrect? Well, it seems like
- * allocating the index array might actually evict the vertex
- * arrays. *sigh*
- */
- r300EmitElts(ctx, num_verts);
- r300EmitAOS(rmesa, rmesa->radeon.tcl.aos_count, start);
+
+
+ r300EmitAOS(rmesa, rmesa->radeon.tcl.aos_count, 0);
if (rmesa->radeon.radeonScreen->kernel_mm) {
BEGIN_BATCH_NO_AUTOSTATE(2);
OUT_BATCH_REGSEQ(R300_VAP_VF_MAX_VTX_INDX, 1);
OUT_BATCH(rmesa->radeon.tcl.aos[0].count);
END_BATCH();
}
- r300FireEB(rmesa, num_verts, type);
- } else {
- r300EmitAOS(rmesa, rmesa->radeon.tcl.aos_count, start);
- r300FireAOS(rmesa, num_verts, type);
- }
- COMMIT_BATCH();
-}
-
-static void r300RunRender(GLcontext * ctx, struct tnl_pipeline_stage *stage)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- int i;
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *vb = &tnl->vb;
- if (RADEON_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- r300UpdateShaders(rmesa);
- r300EmitArrays(ctx);
+ r300_emit_scissor(rmesa->radeon.glCtx);
+ while (num_verts > 0) {
+ int nr;
+ int align;
+
+ nr = MIN2(num_verts, 65535);
+ nr -= (nr - first) % incr;
+
+ /* get alignment for IB correct */
+ if (nr != num_verts) {
+ do {
+ align = nr * (rmesa->ind_buf.is_32bit ? 4 : 2);
+ if (align % 4)
+ nr -= incr;
+ } while(align % 4);
+ if (nr <= 0) {
+ WARN_ONCE("did the impossible happen? we never aligned nr to dword\n");
+ return;
+ }
+
+ }
+ r300FireEB(rmesa, nr, type, offset);
- r300UpdateShaderStates(rmesa);
+ num_verts -= nr;
+ offset += nr;
+ }
- r300EmitCacheFlush(rmesa);
- radeonEmitState(&rmesa->radeon);
+ } else {
+ GLuint first, incr, offset = 0;
- for (i = 0; i < vb->PrimitiveCount; i++) {
- GLuint prim = _tnl_translate_prim(&vb->Primitive[i]);
- GLuint start = vb->Primitive[i].start;
- GLuint end = vb->Primitive[i].start + vb->Primitive[i].count;
- r300RunRenderPrimitive(ctx, start, end, prim);
+ if (!split_prim_inplace(prim & PRIM_MODE_MASK, &first, &incr) &&
+ num_verts > 65535) {
+ WARN_ONCE("Fixme: can't handle spliting prim %d\n", prim);
+ return;
+ }
+ r300_emit_scissor(rmesa->radeon.glCtx);
+ while (num_verts > 0) {
+ int nr;
+ nr = MIN2(num_verts, 65535);
+ nr -= (nr - first) % incr;
+ r300EmitAOS(rmesa, rmesa->radeon.tcl.aos_count, start + offset);
+ r300FireAOS(rmesa, nr, type);
+ num_verts -= nr;
+ offset += nr;
+ }
}
-
- r300EmitCacheFlush(rmesa);
-
- radeonReleaseArrays(ctx, ~0);
+ COMMIT_BATCH();
}
-
static const char *getFallbackString(uint32_t bit)
{
switch (bit) {
r300ContextPtr rmesa = R300_CONTEXT(ctx);
uint32_t old_fallback = rmesa->fallback;
static uint32_t fallback_warn = 0;
-
+
if (mode) {
if ((fallback_warn & bit) == 0) {
- _mesa_fprintf(stderr, "WARNING! Falling back to software for %s\n", getFallbackString(bit));
+ if (RADEON_DEBUG & RADEON_FALLBACKS)
+ _mesa_fprintf(stderr, "WARNING! Falling back to software for %s\n", getFallbackString(bit));
fallback_warn |= bit;
}
rmesa->fallback |= bit;
/* update only if we change from no raster fallbacks to some raster fallbacks */
if (((old_fallback & R300_RASTER_FALLBACK_MASK) == 0) &&
((bit & R300_RASTER_FALLBACK_MASK) > 0)) {
-
+
radeon_firevertices(&rmesa->radeon);
rmesa->radeon.swtcl.RenderIndex = ~0;
_swsetup_Wakeup( ctx );
/* update only if we have disabled all tcl fallbacks */
if (rmesa->options.hw_tcl_enabled) {
- if ((old_fallback & R300_RASTER_FALLBACK_MASK) == bit) {
+ if ((old_fallback & R300_TCL_FALLBACK_MASK) == bit) {
R300_STATECHANGE(rmesa, vap_cntl_status);
rmesa->hw.vap_cntl_status.cmd[1] &= ~R300_VAP_TCL_BYPASS;
}
/* update only if we have disabled all raster fallbacks */
if ((old_fallback & R300_RASTER_FALLBACK_MASK) == bit) {
_swrast_flush( ctx );
-
+
tnl->Driver.Render.Start = r300RenderStart;
tnl->Driver.Render.Finish = r300RenderFinish;
tnl->Driver.Render.PrimitiveNotify = r300RenderPrimitive;
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
tnl->Driver.Render.Interp = _tnl_interp;
-
+
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
}
}
-
-}
-static GLboolean r300RunNonTCLRender(GLcontext * ctx,
- struct tnl_pipeline_stage *stage)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
-
- if (RADEON_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (rmesa->fallback & R300_RASTER_FALLBACK_MASK)
- return GL_TRUE;
-
- if (rmesa->options.hw_tcl_enabled == GL_FALSE)
- return GL_TRUE;
-
- r300RunRender(ctx, stage);
-
- return GL_FALSE;
}
-
-const struct tnl_pipeline_stage _r300_render_stage = {
- "r300 Hardware Rasterization",
- NULL,
- NULL,
- NULL,
- NULL,
- r300RunNonTCLRender
-};