From edb9a165c14bd90938340a74a636ac5f65ac4c35 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Thu, 20 Jan 2005 13:59:49 +0000 Subject: [PATCH] Added support for ELTS to the _savage_render_stage. Requires at least Savage DRM version 2.2.0. Otherwise the render stage is disabled. --- src/mesa/drivers/dri/savage/savage_xmesa.c | 19 ++++- src/mesa/drivers/dri/savage/savagecontext.h | 9 ++ src/mesa/drivers/dri/savage/savageioctl.c | 11 ++- src/mesa/drivers/dri/savage/savageioctl.h | 93 ++++++++++++++++++++- src/mesa/drivers/dri/savage/savagerender.c | 77 ++++++++++++----- 5 files changed, 178 insertions(+), 31 deletions(-) diff --git a/src/mesa/drivers/dri/savage/savage_xmesa.c b/src/mesa/drivers/dri/savage/savage_xmesa.c index 9a8e090ab51..742c6e89a9f 100644 --- a/src/mesa/drivers/dri/savage/savage_xmesa.c +++ b/src/mesa/drivers/dri/savage/savage_xmesa.c @@ -109,8 +109,8 @@ static const char *const card_extensions[] = NULL }; -extern const struct tnl_pipeline_stage _savage_texnorm_stage; -extern const struct tnl_pipeline_stage _savage_render_stage; +extern struct tnl_pipeline_stage _savage_texnorm_stage; +extern struct tnl_pipeline_stage _savage_render_stage; static const struct tnl_pipeline_stage *savage_pipeline[] = { @@ -435,6 +435,8 @@ savageCreateContext( const __GLcontextModes *mesaVis, imesa->vtxBuf = &imesa->clientVtxBuf; + imesa->firstElt = -1; + /* Uninitialized vertex format. Force setting the vertex state in * savageRenderStart. */ @@ -463,10 +465,18 @@ savageCreateContext( const __GLcontextModes *mesaVis, /* Install the customized pipeline: */ -#if 1 _tnl_destroy_pipeline( ctx ); _tnl_install_pipeline( ctx, savage_pipeline ); -#endif + /* DRM versions before 2.1.3 would only render triangle lists. ELTS + * support was added in 2.2.0. */ + if (sPriv->drmMinor < 2) { + _savage_render_stage.active = GL_FALSE; + fprintf (stderr, + "*** Disabling fast path because your DRM version is buggy " + "or doesn't\n*** support ELTS. You need at least Savage DRM " + "version 2.2.\n"); + } + /* Configure swrast to match hardware characteristics: */ @@ -508,6 +518,7 @@ savageDestroyContext(__DRIcontextPrivate *driContextPriv) savageTextureObjectPtr next_t, t; savageFlushVertices(imesa); + savageReleaseIndexedVerts(imesa); savageFlushCmdBuf(imesa, GL_TRUE); /* release DMA buffer */ /* update for multi-tex*/ diff --git a/src/mesa/drivers/dri/savage/savagecontext.h b/src/mesa/drivers/dri/savage/savagecontext.h index 5a66bdfa4ef..37aa7d33489 100644 --- a/src/mesa/drivers/dri/savage/savagecontext.h +++ b/src/mesa/drivers/dri/savage/savagecontext.h @@ -141,6 +141,11 @@ struct savage_cmdbuf_t { drm_savage_cmd_header_t *write; /* append stuff here */ }; +struct savage_elt_t { + GLuint n; /* number of elts currently allocated */ + drm_savage_cmd_header_t *cmd; /* the indexed drawing command */ +}; + struct savage_context_t { GLint refcount; @@ -173,6 +178,10 @@ struct savage_context_t { /* Command buffer */ struct savage_cmdbuf_t cmdBuf; + /* Elt book-keeping */ + struct savage_elt_t elts; + GLint firstElt; + /* Vertex buffers */ struct savage_vtxbuf_t dmaVtxBuf, clientVtxBuf; struct savage_vtxbuf_t *vtxBuf; diff --git a/src/mesa/drivers/dri/savage/savageioctl.c b/src/mesa/drivers/dri/savage/savageioctl.c index 62e7142d246..27747c3cd89 100644 --- a/src/mesa/drivers/dri/savage/savageioctl.c +++ b/src/mesa/drivers/dri/savage/savageioctl.c @@ -559,6 +559,9 @@ void savageFlushCmdBufLocked( savageContextPtr imesa, GLboolean discard ) drm_savage_cmd_header_t *start; int ret; + /* complete indexed drawing commands */ + savageFlushElts(imesa); + /* If we lost the context we must restore the initial state (at * the start of the command buffer). */ if (imesa->lostContext) { @@ -609,13 +612,15 @@ void savageFlushCmdBufLocked( savageContextPtr imesa, GLboolean discard ) } if (discard) { + assert (!savageHaveIndexedVerts(imesa)); imesa->dmaVtxBuf.total = 0; imesa->dmaVtxBuf.used = 0; imesa->dmaVtxBuf.flushed = 0; } - imesa->clientVtxBuf.used = 0; - imesa->clientVtxBuf.flushed = 0; - + if (!savageHaveIndexedVerts(imesa)) { + imesa->clientVtxBuf.used = 0; + imesa->clientVtxBuf.flushed = 0; + } imesa->cmdBuf.write = imesa->cmdBuf.base; /* Save the current state at the start of the command buffer. That diff --git a/src/mesa/drivers/dri/savage/savageioctl.h b/src/mesa/drivers/dri/savage/savageioctl.h index 941e74e56b5..8f50324c3f7 100644 --- a/src/mesa/drivers/dri/savage/savageioctl.h +++ b/src/mesa/drivers/dri/savage/savageioctl.h @@ -65,6 +65,18 @@ void savageSwapBuffers( __DRIdrawablePrivate *dPriv ); extern void savageGetDMABuffer( savageContextPtr imesa ); +static __inline +void savageReleaseIndexedVerts( savageContextPtr imesa ) +{ + imesa->firstElt = -1; +} + +static __inline +GLboolean savageHaveIndexedVerts( savageContextPtr imesa ) +{ + return (imesa->firstElt != -1); +} + static __inline u_int32_t *savageAllocVtxBuf( savageContextPtr imesa, GLuint words ) { @@ -80,7 +92,8 @@ u_int32_t *savageAllocVtxBuf( savageContextPtr imesa, GLuint words ) if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG) fprintf (stderr, "... flushing DMA buffer in %s\n", __FUNCTION__); - savageFlushVertices( imesa ); + savageReleaseIndexedVerts(imesa); + savageFlushVertices(imesa); LOCK_HARDWARE(imesa); savageFlushCmdBufLocked(imesa, GL_TRUE); /* discard DMA buffer */ savageGetDMABuffer(imesa); @@ -90,7 +103,8 @@ u_int32_t *savageAllocVtxBuf( savageContextPtr imesa, GLuint words ) if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG) fprintf (stderr, "... flushing client vertex buffer in %s\n", __FUNCTION__); - savageFlushVertices( imesa ); + savageReleaseIndexedVerts(imesa); + savageFlushVertices(imesa); LOCK_HARDWARE(imesa); savageFlushCmdBufLocked(imesa, GL_FALSE); /* free clientVtxBuf */ UNLOCK_HARDWARE(imesa); @@ -102,18 +116,89 @@ u_int32_t *savageAllocVtxBuf( savageContextPtr imesa, GLuint words ) return head; } +static __inline +u_int32_t *savageAllocIndexedVerts( savageContextPtr imesa, GLuint n ) +{ + u_int32_t *ret; + savageFlushVertices(imesa); + ret = savageAllocVtxBuf(imesa, n*imesa->HwVertexSize); + imesa->firstElt = imesa->vtxBuf->flushed / imesa->HwVertexSize; + imesa->vtxBuf->flushed = imesa->vtxBuf->used; + return ret; +} + +/* Flush Elts: + * - Complete the drawing command with the correct number of indices. + * - Actually allocate entries for the indices in the command buffer. + * (This allocation must succeed without wrapping the cmd buffer!) + */ +static __inline +void savageFlushElts( savageContextPtr imesa ) +{ + if (imesa->elts.cmd) { + GLuint qwords = (imesa->elts.n + 3) >> 2; + assert(imesa->cmdBuf.write - imesa->cmdBuf.base + qwords + <= imesa->cmdBuf.size); + imesa->cmdBuf.write += qwords; + + imesa->elts.cmd->idx.count = imesa->elts.n; + imesa->elts.cmd = NULL; + } +} + +/* Allocate a command buffer entry with bytes of arguments: + * - implies savageFlushElts + */ static __inline drm_savage_cmd_header_t *savageAllocCmdBuf( savageContextPtr imesa, GLuint bytes ) { drm_savage_cmd_header_t *ret; GLuint qwords = ((bytes + 7) >> 3) + 1; /* round up */ assert (qwords < imesa->cmdBuf.size); - if (imesa->cmdBuf.write - imesa->cmdBuf.base + qwords > imesa->cmdBuf.size) { + + savageFlushElts(imesa); + + if (imesa->cmdBuf.write - imesa->cmdBuf.base + qwords > imesa->cmdBuf.size) savageFlushCmdBuf(imesa, GL_FALSE); - } + ret = (drm_savage_cmd_header_t *)imesa->cmdBuf.write; imesa->cmdBuf.write += qwords; return ret; } +/* Allocate Elts: + * - if it doesn't fit, flush the cmd buffer first + * - allocates the drawing command on the cmd buffer if there is no + * incomplete indexed drawing command yet + * - increments the number of elts. Final allocation is done in savageFlushElts + */ +static __inline +u_int16_t *savageAllocElts( savageContextPtr imesa, GLuint n ) +{ + u_int16_t *ret; + GLuint qwords; + assert (savageHaveIndexedVerts(imesa)); + + if (imesa->elts.cmd) + qwords = (imesa->elts.n + n + 3) >> 2; + else + qwords = ((n + 3) >> 2) + 1; + if (imesa->cmdBuf.write - imesa->cmdBuf.base + qwords > imesa->cmdBuf.size) + savageFlushCmdBuf(imesa, GL_FALSE); /* implies savageFlushElts */ + + if (!imesa->elts.cmd) { + savageFlushVertices(imesa); + imesa->elts.cmd = savageAllocCmdBuf(imesa, 0); + imesa->elts.cmd->idx.cmd = (imesa->vtxBuf == &imesa->dmaVtxBuf) ? + SAVAGE_CMD_DMA_IDX : SAVAGE_CMD_VB_IDX; + imesa->elts.cmd->idx.prim = imesa->HwPrim; + imesa->elts.cmd->idx.skip = imesa->skip; + imesa->elts.n = 0; + } + + ret = (u_int16_t *)(imesa->elts.cmd+1) + imesa->elts.n; + imesa->elts.n += n; + return ret; +} + #endif diff --git a/src/mesa/drivers/dri/savage/savagerender.c b/src/mesa/drivers/dri/savage/savagerender.c index 50ec9eac685..cdc82c7be8c 100644 --- a/src/mesa/drivers/dri/savage/savagerender.c +++ b/src/mesa/drivers/dri/savage/savagerender.c @@ -54,7 +54,7 @@ #define HAVE_QUADS 0 #define HAVE_QUAD_STRIPS 0 -#define HAVE_ELTS 0 /* for now */ +#define HAVE_ELTS 1 #define LOCAL_VARS savageContextPtr imesa = SAVAGE_CONTEXT(ctx) #define INIT( prim ) do { \ @@ -66,7 +66,8 @@ case GL_TRIANGLE_FAN: imesa->HwPrim = SAVAGE_PRIM_TRIFAN; break; \ } \ } while (0) -#define FLUSH() savageFlushVertices(imesa) +#define FLUSH() savageFlushElts(imesa), savageFlushVertices(imesa) + #define GET_CURRENT_VB_MAX_VERTS() \ ((imesa->bufferSize/4 - imesa->vtxBuf->used) / imesa->HwVertexSize) #define GET_SUBSEQUENT_VB_MAX_VERTS() \ @@ -77,6 +78,38 @@ #define EMIT_VERTS( ctx, j, nr, buf ) \ _tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf ) +#define ELTS_VARS( buf ) GLushort *dest = buf, firstElt = imesa->firstElt +#define ELT_INIT( prim ) INIT(prim) + +/* (size - used - 1 qword for drawing command) * 4 elts per qword */ +#define GET_CURRENT_VB_MAX_ELTS() \ + ((imesa->cmdBuf.size - (imesa->cmdBuf.write - imesa->cmdBuf.base) - 1)*4) +/* (size - space for initial state - 1 qword for drawing command) * 4 elts + * imesa is not defined in validate_render :( */ +#define GET_SUBSEQUENT_VB_MAX_ELTS() \ + ((SAVAGE_CONTEXT(ctx)->cmdBuf.size - \ + (SAVAGE_CONTEXT(ctx)->cmdBuf.start - \ + SAVAGE_CONTEXT(ctx)->cmdBuf.base) - 1)*4) + +#define ALLOC_ELTS(nr) savageAllocElts(imesa, nr) +#define EMIT_ELT(offset, x) do { \ + (dest)[offset] = (GLushort) ((x)+firstElt); \ +} while (0) +#define EMIT_TWO_ELTS(offset, x, y) do { \ + *(GLuint *)(dest + offset) = (((y)+firstElt) << 16) | \ + ((x)+firstElt); \ +} while (0) + +#define INCR_ELTS( nr ) dest += nr +#define ELTPTR dest +#define RELEASE_ELT_VERTS() \ + savageReleaseIndexedVerts(imesa) + +#define EMIT_INDEXED_VERTS( ctx, start, count ) do { \ + GLuint *buf = savageAllocIndexedVerts(imesa, count-start); \ + EMIT_VERTS(ctx, start, count-start, buf); \ +} while (0) + #define TAG(x) savage_##x #include "tnl_dd/t_dd_dmatmp.h" @@ -114,20 +147,25 @@ static GLboolean savage_run_render( GLcontext *ctx, savageContextPtr imesa = SAVAGE_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - tnl_render_func *tab; + tnl_render_func *tab, *tab_elts; GLboolean valid; GLuint i; + if (savageHaveIndexedVerts(imesa) && (!VB->Elts || stage->changed_inputs)) + savageReleaseIndexedVerts(imesa); + if (imesa->savageScreen->chipset < S3_SAVAGE4 && (ctx->_TriangleCaps & DD_FLATSHADE)) { tab = savage_flat_render_tab_verts_s3d; + tab_elts = savage_flat_render_tab_elts_s3d; valid = savage_flat_validate_render_s3d( ctx, VB ); } else { tab = savage_render_tab_verts; + tab_elts = savage_render_tab_elts; valid = savage_validate_render( ctx, VB ); } - /* Don't handle clipping or indexed vertices or vertex manipulations. + /* Don't handle clipping or vertex manipulations. */ if (imesa->RenderIndex != 0 || !valid) { return GL_TRUE; @@ -135,7 +173,7 @@ static GLboolean savage_run_render( GLcontext *ctx, tnl->Driver.Render.Start( ctx ); /* Check RenderIndex again. The ptexHack is detected late in RenderStart. - * Also check for fallbacks detected late. + * Also check for ptex fallbacks detected late. */ if (imesa->RenderIndex != 0 || imesa->Fallback != 0) { return GL_TRUE; @@ -144,7 +182,19 @@ static GLboolean savage_run_render( GLcontext *ctx, /* setup for hardware culling */ imesa->raster_primitive = GL_TRIANGLES; imesa->new_state |= SAVAGE_NEW_CULL; + + /* update and emit state */ savageDDUpdateHwState(ctx); + savageEmitChangedState(imesa); + + if (VB->Elts) { + tab = tab_elts; + if (!savageHaveIndexedVerts(imesa)) { + if (VB->Count > GET_SUBSEQUENT_VB_MAX_VERTS()) + return GL_TRUE; + EMIT_INDEXED_VERTS(ctx, 0, VB->Count); + } + } for (i = 0 ; i < VB->PrimitiveCount ; i++) { @@ -164,20 +214,7 @@ static GLboolean savage_run_render( GLcontext *ctx, static void savage_check_render( GLcontext *ctx, struct tnl_pipeline_stage *stage ) { - __DRIscreenPrivate *driScrnPriv = - SAVAGE_CONTEXT(ctx)->savageScreen->driScrnPriv; stage->inputs = TNL_CONTEXT(ctx)->render_inputs; - /* This hack will go away when we depend on 2.2.x for ELTS. */ - if (driScrnPriv->drmMinor <= 1 && driScrnPriv->drmPatch < 3) { - static GLboolean firstTime = GL_TRUE; - stage->active = GL_FALSE; - if (firstTime) { - fprintf (stderr, - "*** Disabling fast path because your DRM version is buggy.\n" - "*** You need at least Savage DRM version 2.1.3.\n"); - firstTime = GL_FALSE; - } - } } static void dtr( struct tnl_pipeline_stage *stage ) @@ -185,7 +222,7 @@ static void dtr( struct tnl_pipeline_stage *stage ) (void)stage; } -const struct tnl_pipeline_stage _savage_render_stage = +struct tnl_pipeline_stage _savage_render_stage = { "savage render", (_DD_NEW_SEPARATE_SPECULAR | @@ -340,7 +377,7 @@ static void free_texnorm_data( struct tnl_pipeline_stage *stage ) } } -const struct tnl_pipeline_stage _savage_texnorm_stage = +struct tnl_pipeline_stage _savage_texnorm_stage = { "savage texture coordinate normalization stage", /* name */ _NEW_TEXTURE, /* check_state */ -- 2.30.2