#include "glheader.h"
#include "imports.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
#include "r200_tex.h"
#include "r200_tcl.h"
#include "r200_swtcl.h"
#include "r200_vtxfmt.h"
#include "api_noop.h"
#include "api_arrayelt.h"
#include "context.h"
#include "mtypes.h"
#include "enums.h"
#include "glapi.h"
#include "colormac.h"
#include "light.h"
#include "state.h"
#include "vtxfmt.h"
#include "tnl/tnl.h"
#include "tnl/t_context.h"
#include "tnl/t_array_api.h"
static void r200VtxFmtFlushVertices( GLcontext *, GLuint );
static void count_func( const char *name, struct dynfn *l )
{
int i = 0;
struct dynfn *f;
foreach (f, l) i++;
if (i) fprintf(stderr, "%s: %d\n", name, i );
}
static void count_funcs( r200ContextPtr rmesa )
{
count_func( "Vertex2f", &rmesa->vb.dfn_cache.Vertex2f );
count_func( "Vertex2fv", &rmesa->vb.dfn_cache.Vertex2fv );
count_func( "Vertex3f", &rmesa->vb.dfn_cache.Vertex3f );
count_func( "Vertex3fv", &rmesa->vb.dfn_cache.Vertex3fv );
count_func( "Color4ub", &rmesa->vb.dfn_cache.Color4ub );
count_func( "Color4ubv", &rmesa->vb.dfn_cache.Color4ubv );
count_func( "Color3ub", &rmesa->vb.dfn_cache.Color3ub );
count_func( "Color3ubv", &rmesa->vb.dfn_cache.Color3ubv );
count_func( "Color4f", &rmesa->vb.dfn_cache.Color4f );
count_func( "Color4fv", &rmesa->vb.dfn_cache.Color4fv );
count_func( "Color3f", &rmesa->vb.dfn_cache.Color3f );
count_func( "Color3fv", &rmesa->vb.dfn_cache.Color3fv );
count_func( "SecondaryColor3f", &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
count_func( "SecondaryColor3fv", &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
count_func( "SecondaryColor3ub", &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
count_func( "SecondaryColor3ubv", &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
count_func( "Normal3f", &rmesa->vb.dfn_cache.Normal3f );
count_func( "Normal3fv", &rmesa->vb.dfn_cache.Normal3fv );
count_func( "TexCoord2f", &rmesa->vb.dfn_cache.TexCoord2f );
count_func( "TexCoord2fv", &rmesa->vb.dfn_cache.TexCoord2fv );
count_func( "TexCoord1f", &rmesa->vb.dfn_cache.TexCoord1f );
count_func( "TexCoord1fv", &rmesa->vb.dfn_cache.TexCoord1fv );
count_func( "MultiTexCoord2fARB", &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
count_func( "MultiTexCoord2fvARB", &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
count_func( "MultiTexCoord1fARB", &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
count_func( "MultiTexCoord1fvARB", &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
}
void r200_copy_to_current( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT);
if (rmesa->vb.vtxfmt_0 & R200_VTX_N0) {
ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0] = rmesa->vb.normalptr[0];
ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1] = rmesa->vb.normalptr[1];
ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2] = rmesa->vb.normalptr[2];
}
switch( VTX_COLOR(rmesa->vb.vtxfmt_0, 0) ) {
case R200_VTX_PK_RGBA:
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->red );
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->green );
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->blue );
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->alpha );
break;
case R200_VTX_FP_RGB:
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = rmesa->vb.floatcolorptr[0];
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = rmesa->vb.floatcolorptr[1];
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = rmesa->vb.floatcolorptr[2];
break;
case R200_VTX_FP_RGBA:
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = rmesa->vb.floatcolorptr[0];
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = rmesa->vb.floatcolorptr[1];
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = rmesa->vb.floatcolorptr[2];
ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = rmesa->vb.floatcolorptr[3];
break;
default:
break;
}
if (VTX_COLOR(rmesa->vb.vtxfmt_0, 1) == R200_VTX_PK_RGBA) {
ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0] = UBYTE_TO_FLOAT( rmesa->vb.specptr->red );
ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1] = UBYTE_TO_FLOAT( rmesa->vb.specptr->green );
ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2] = UBYTE_TO_FLOAT( rmesa->vb.specptr->blue );
}
if (rmesa->vb.vtxfmt_1 & (7 << R200_VTX_TEX0_COMP_CNT_SHIFT)) {
ctx->Current.Attrib[VERT_ATTRIB_TEX0][0] = rmesa->vb.texcoordptr[0][0];
ctx->Current.Attrib[VERT_ATTRIB_TEX0][1] = rmesa->vb.texcoordptr[0][1];
ctx->Current.Attrib[VERT_ATTRIB_TEX0][2] = 0.0F;
ctx->Current.Attrib[VERT_ATTRIB_TEX0][3] = 1.0F;
}
if (rmesa->vb.vtxfmt_1 & (7 << R200_VTX_TEX1_COMP_CNT_SHIFT)) {
ctx->Current.Attrib[VERT_ATTRIB_TEX1][0] = rmesa->vb.texcoordptr[1][0];
ctx->Current.Attrib[VERT_ATTRIB_TEX1][1] = rmesa->vb.texcoordptr[1][1];
ctx->Current.Attrib[VERT_ATTRIB_TEX1][2] = 0.0F;
ctx->Current.Attrib[VERT_ATTRIB_TEX1][3] = 1.0F;
}
ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
}
static GLboolean discreet_gl_prim[GL_POLYGON+1] = {
1,
1,
0,
0,
1,
0,
0,
1,
0,
0,
};
static void flush_prims( r200ContextPtr rmesa )
{
int i,j;
struct r200_dma_region tmp = rmesa->dma.current;
tmp.buf->refcount++;
tmp.aos_size = rmesa->vb.vertex_size;
tmp.aos_stride = rmesa->vb.vertex_size;
tmp.aos_start = GET_START(&tmp);
rmesa->dma.current.ptr = rmesa->dma.current.start +=
(rmesa->vb.initial_counter - rmesa->vb.counter) *
rmesa->vb.vertex_size * 4;
rmesa->tcl.vertex_format = rmesa->vb.vtxfmt_0;
rmesa->tcl.aos_components[0] = &tmp;
rmesa->tcl.nr_aos_components = 1;
rmesa->dma.flush = 0;
if (rmesa->vb.nrprims > 1) {
for (j = 0, i = 1 ; i < rmesa->vb.nrprims; i++) {
int pj = rmesa->vb.primlist[j].prim & 0xf;
int pi = rmesa->vb.primlist[i].prim & 0xf;
if (pj == pi && discreet_gl_prim[pj] &&
rmesa->vb.primlist[i].start == rmesa->vb.primlist[j].end) {
rmesa->vb.primlist[j].end = rmesa->vb.primlist[i].end;
}
else {
j++;
if (j != i) rmesa->vb.primlist[j] = rmesa->vb.primlist[i];
}
}
rmesa->vb.nrprims = j+1;
}
if (rmesa->vb.vtxfmt_0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0] ||
rmesa->vb.vtxfmt_1 != rmesa->hw.vtx.cmd[VTX_VTXFMT_1]) {
R200_STATECHANGE( rmesa, vtx );
rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = rmesa->vb.vtxfmt_0;
rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = rmesa->vb.vtxfmt_1;
}
for (i = 0 ; i < rmesa->vb.nrprims; i++) {
if (R200_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "vtxfmt prim %d: %s %d..%d\n", i,
_mesa_lookup_enum_by_nr( rmesa->vb.primlist[i].prim &
PRIM_MODE_MASK ),
rmesa->vb.primlist[i].start,
rmesa->vb.primlist[i].end);
if (rmesa->vb.primlist[i].start < rmesa->vb.primlist[i].end)
r200EmitPrimitive( rmesa->glCtx,
rmesa->vb.primlist[i].start,
rmesa->vb.primlist[i].end,
rmesa->vb.primlist[i].prim );
}
rmesa->vb.nrprims = 0;
r200ReleaseDmaRegion( rmesa, &tmp, __FUNCTION__ );
}
static void start_prim( r200ContextPtr rmesa, GLuint mode )
{
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s %d\n", __FUNCTION__,
rmesa->vb.initial_counter - rmesa->vb.counter);
rmesa->vb.primlist[rmesa->vb.nrprims].start =
rmesa->vb.initial_counter - rmesa->vb.counter;
rmesa->vb.primlist[rmesa->vb.nrprims].prim = mode;
}
static void note_last_prim( r200ContextPtr rmesa, GLuint flags )
{
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s %d\n", __FUNCTION__,
rmesa->vb.initial_counter - rmesa->vb.counter);
if (rmesa->vb.prim[0] != GL_POLYGON+1) {
rmesa->vb.primlist[rmesa->vb.nrprims].prim |= flags;
rmesa->vb.primlist[rmesa->vb.nrprims].end =
rmesa->vb.initial_counter - rmesa->vb.counter;
if (++(rmesa->vb.nrprims) == R200_MAX_PRIMS)
flush_prims( rmesa );
}
}
static void copy_vertex( r200ContextPtr rmesa, GLuint n, GLfloat *dst )
{
GLuint i;
GLfloat *src = (GLfloat *)(rmesa->dma.current.address +
rmesa->dma.current.ptr +
(rmesa->vb.primlist[rmesa->vb.nrprims].start + n) *
rmesa->vb.vertex_size * 4);
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "copy_vertex %d\n", rmesa->vb.primlist[rmesa->vb.nrprims].start + n);
for (i = 0 ; i < rmesa->vb.vertex_size; i++) {
dst[i] = src[i];
}
}
static GLuint copy_dma_verts( r200ContextPtr rmesa, GLfloat (*tmp)[15] )
{
GLuint ovf, i;
GLuint nr = (rmesa->vb.initial_counter - rmesa->vb.counter) -
rmesa->vb.primlist[rmesa->vb.nrprims].start;
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s %d verts\n", __FUNCTION__, nr);
switch( rmesa->vb.prim[0] )
{
case GL_POINTS:
return 0;
case GL_LINES:
ovf = nr&1;
for (i = 0 ; i < ovf ; i++)
copy_vertex( rmesa, nr-ovf+i, tmp[i] );
return i;
case GL_TRIANGLES:
ovf = nr%3;
for (i = 0 ; i < ovf ; i++)
copy_vertex( rmesa, nr-ovf+i, tmp[i] );
return i;
case GL_QUADS:
ovf = nr&3;
for (i = 0 ; i < ovf ; i++)
copy_vertex( rmesa, nr-ovf+i, tmp[i] );
return i;
case GL_LINE_STRIP:
if (nr == 0)
return 0;
copy_vertex( rmesa, nr-1, tmp[0] );
return 1;
case GL_LINE_LOOP:
case GL_TRIANGLE_FAN:
case GL_POLYGON:
if (nr == 0)
return 0;
else if (nr == 1) {
copy_vertex( rmesa, 0, tmp[0] );
return 1;
} else {
copy_vertex( rmesa, 0, tmp[0] );
copy_vertex( rmesa, nr-1, tmp[1] );
return 2;
}
case GL_TRIANGLE_STRIP:
ovf = MIN2( nr, 2 );
for (i = 0 ; i < ovf ; i++)
copy_vertex( rmesa, nr-ovf+i, tmp[i] );
return i;
case GL_QUAD_STRIP:
switch (nr) {
case 0: ovf = 0; break;
case 1: ovf = 1; break;
default: ovf = 2 + (nr&1); break;
}
for (i = 0 ; i < ovf ; i++)
copy_vertex( rmesa, nr-ovf+i, tmp[i] );
return i;
default:
assert(0);
return 0;
}
}
static void VFMT_FALLBACK_OUTSIDE_BEGIN_END( const char *caller )
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
if (ctx->Driver.NeedFlush)
r200VtxFmtFlushVertices( ctx, ctx->Driver.NeedFlush );
if (ctx->NewState)
_mesa_update_state( ctx );
_tnl_wakeup_exec( ctx );
ctx->Driver.FlushVertices = r200FlushVertices;
assert( rmesa->dma.flush == 0 );
rmesa->vb.fell_back = GL_TRUE;
rmesa->vb.installed = GL_FALSE;
}
static void VFMT_FALLBACK( const char *caller )
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLfloat tmp[3][15];
GLuint i, prim;
GLuint ind0 = rmesa->vb.vtxfmt_0;
GLuint ind1 = rmesa->vb.vtxfmt_1;
GLuint nrverts;
GLfloat alpha = 1.0;
if (R200_DEBUG & (DEBUG_FALLBACKS|DEBUG_VFMT))
fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
if (rmesa->vb.prim[0] == GL_POLYGON+1) {
VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ );
return;
}
nrverts = copy_dma_verts( rmesa, tmp );
note_last_prim( rmesa, 0 );
flush_prims( rmesa );
prim = rmesa->vb.prim[0];
ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
_tnl_wakeup_exec( ctx );
ctx->Driver.FlushVertices = r200FlushVertices;
assert(rmesa->dma.flush == 0);
rmesa->vb.fell_back = GL_TRUE;
rmesa->vb.installed = GL_FALSE;
glBegin( prim );
if (rmesa->vb.installed_color_3f_sz == 4)
alpha = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
for (i = 0 ; i < nrverts; i++) {
GLuint offset = 3;
if (ind0 & R200_VTX_N0) {
glNormal3fv( &tmp[i][offset] );
offset += 3;
}
if (VTX_COLOR(ind0, 0) == R200_VTX_PK_RGBA) {
glColor4ubv( (GLubyte *)&tmp[i][offset] );
offset++;
}
else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGBA) {
glColor4fv( &tmp[i][offset] );
offset+=4;
}
else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGB) {
glColor3fv( &tmp[i][offset] );
offset+=3;
}
if (VTX_COLOR(ind0, 1) == R200_VTX_PK_RGBA) {
_glapi_Dispatch->SecondaryColor3ubvEXT( (GLubyte *)&tmp[i][offset] );
offset++;
}
if (ind1 & (7 << R200_VTX_TEX0_COMP_CNT_SHIFT)) {
glTexCoord2fv( &tmp[i][offset] );
offset += 2;
}
if (ind1 & (7 << R200_VTX_TEX1_COMP_CNT_SHIFT)) {
glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, &tmp[i][offset] );
offset += 2;
}
glVertex3fv( &tmp[i][0] );
}
if (ind0 & R200_VTX_N0)
glNormal3fv( rmesa->vb.normalptr );
if (VTX_COLOR(ind0, 0) == R200_VTX_PK_RGBA)
glColor4ub( rmesa->vb.colorptr->red, rmesa->vb.colorptr->green, rmesa->vb.colorptr->blue, rmesa->vb.colorptr->alpha );
else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGBA)
glColor4fv( rmesa->vb.floatcolorptr );
else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGB) {
if (rmesa->vb.installed_color_3f_sz == 4 && alpha != 1.0)
glColor4f( rmesa->vb.floatcolorptr[0],
rmesa->vb.floatcolorptr[1],
rmesa->vb.floatcolorptr[2],
alpha );
else
glColor3fv( rmesa->vb.floatcolorptr );
}
if (VTX_COLOR(ind0, 1) == R200_VTX_PK_RGBA)
_glapi_Dispatch->SecondaryColor3ubEXT( rmesa->vb.specptr->red, rmesa->vb.specptr->green, rmesa->vb.specptr->blue );
if (ind1 & (7 << R200_VTX_TEX0_COMP_CNT_SHIFT))
glTexCoord2fv( rmesa->vb.texcoordptr[0] );
if (ind1 & (7 << R200_VTX_TEX1_COMP_CNT_SHIFT))
glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, rmesa->vb.texcoordptr[1] );
}
static void wrap_buffer( void )
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLfloat tmp[3][15];
GLuint i, nrverts;
if (R200_DEBUG & (DEBUG_VFMT|DEBUG_PRIMS))
fprintf(stderr, "%s %d\n", __FUNCTION__,
rmesa->vb.initial_counter - rmesa->vb.counter);
if ((((rmesa->vb.initial_counter - rmesa->vb.counter) -
rmesa->vb.primlist[rmesa->vb.nrprims].start) & 1)) {
rmesa->vb.counter++;
rmesa->vb.initial_counter++;
return;
}
if (rmesa->vb.prim[0] == GL_POLYGON+1)
nrverts = 0;
else {
nrverts = copy_dma_verts( rmesa, tmp );
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%d vertices to copy\n", nrverts);
note_last_prim( rmesa, 0 );
}
flush_prims( rmesa );
r200RefillCurrentDmaRegion( rmesa );
rmesa->vb.dmaptr = (int *)(rmesa->dma.current.ptr + rmesa->dma.current.address);
rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) /
(rmesa->vb.vertex_size * 4);
rmesa->vb.counter--;
rmesa->vb.initial_counter = rmesa->vb.counter;
rmesa->vb.notify = wrap_buffer;
rmesa->dma.flush = flush_prims;
if (rmesa->vb.prim[0] != GL_POLYGON+1)
start_prim( rmesa, rmesa->vb.prim[0] );
for (i = 0 ; i < nrverts; i++) {
if (R200_DEBUG & DEBUG_VERTS) {
int j;
fprintf(stderr, "re-emit vertex %d to %p\n", i, (void *)rmesa->vb.dmaptr);
if (R200_DEBUG & DEBUG_VERBOSE)
for (j = 0 ; j < rmesa->vb.vertex_size; j++)
fprintf(stderr, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]);
}
memcpy( rmesa->vb.dmaptr, tmp[i], rmesa->vb.vertex_size * 4 );
rmesa->vb.dmaptr += rmesa->vb.vertex_size;
rmesa->vb.counter--;
}
}
static GLboolean check_vtx_fmt( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint ind0 = R200_VTX_Z0;
GLuint ind1 = 0;
if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag)
return GL_FALSE;
if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)
ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT );
if (ctx->Light.Enabled) {
ind0 |= R200_VTX_N0;
if (ctx->Light.ColorMaterialEnabled)
ind0 |= R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT;
else
ind0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT;
}
else {
ind0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT;
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
ind0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT;
}
}
if (ctx->Texture.Unit[0]._ReallyEnabled) {
if (ctx->Texture.Unit[0].TexGenEnabled) {
if (rmesa->TexGenNeedNormals[0]) {
ind0 |= R200_VTX_N0;
}
} else {
if (ctx->Current.Attrib[VERT_ATTRIB_TEX0][2] != 0.0F ||
ctx->Current.Attrib[VERT_ATTRIB_TEX0][3] != 1.0) {
if (R200_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
fprintf(stderr, "%s: rq0\n", __FUNCTION__);
return GL_FALSE;
}
ind1 |= 2 << R200_VTX_TEX0_COMP_CNT_SHIFT;
}
}
if (ctx->Texture.Unit[1]._ReallyEnabled) {
if (ctx->Texture.Unit[1].TexGenEnabled) {
if (rmesa->TexGenNeedNormals[1]) {
ind0 |= R200_VTX_N0;
}
} else {
if (ctx->Current.Attrib[VERT_ATTRIB_TEX1][2] != 0.0F ||
ctx->Current.Attrib[VERT_ATTRIB_TEX1][3] != 1.0) {
if (R200_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
fprintf(stderr, "%s: rq1\n", __FUNCTION__);
return GL_FALSE;
}
ind1 |= 2 << R200_VTX_TEX1_COMP_CNT_SHIFT;
}
}
if (R200_DEBUG & (DEBUG_VFMT|DEBUG_STATE))
fprintf(stderr, "%s: format: 0x%x, 0x%x\n", __FUNCTION__, ind0, ind1 );
R200_NEWPRIM(rmesa);
rmesa->vb.vtxfmt_0 = ind0;
rmesa->vb.vtxfmt_1 = ind1;
rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive;
rmesa->vb.vertex_size = 3;
rmesa->vb.normalptr = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
rmesa->vb.colorptr = NULL;
rmesa->vb.floatcolorptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
rmesa->vb.specptr = NULL;
rmesa->vb.floatspecptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
rmesa->vb.texcoordptr[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
rmesa->vb.texcoordptr[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX1];
if (ind0 & R200_VTX_N0) {
rmesa->vb.normalptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
rmesa->vb.vertex_size += 3;
rmesa->vb.normalptr[0] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0];
rmesa->vb.normalptr[1] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1];
rmesa->vb.normalptr[2] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2];
}
if (VTX_COLOR(ind0, 0) == R200_VTX_PK_RGBA) {
rmesa->vb.colorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].color;
rmesa->vb.vertex_size += 1;
UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->red, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] );
UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] );
UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->blue, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] );
UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->alpha, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] );
}
else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGBA) {
rmesa->vb.floatcolorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
rmesa->vb.vertex_size += 4;
rmesa->vb.floatcolorptr[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
rmesa->vb.floatcolorptr[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
rmesa->vb.floatcolorptr[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
rmesa->vb.floatcolorptr[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
}
else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGB) {
rmesa->vb.floatcolorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
rmesa->vb.vertex_size += 3;
rmesa->vb.floatcolorptr[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
rmesa->vb.floatcolorptr[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
rmesa->vb.floatcolorptr[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
}
if (VTX_COLOR(ind0, 1) == R200_VTX_PK_RGBA) {
rmesa->vb.specptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].color;
rmesa->vb.vertex_size += 1;
UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->red, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0] );
UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1] );
UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->blue, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2] );
}
if (ind1 & (7 << R200_VTX_TEX0_COMP_CNT_SHIFT)) {
rmesa->vb.texcoordptr[0] = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
rmesa->vb.vertex_size += 2;
rmesa->vb.texcoordptr[0][0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][0];
rmesa->vb.texcoordptr[0][1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][1];
}
if (ind1 & (7 << R200_VTX_TEX1_COMP_CNT_SHIFT)) {
rmesa->vb.texcoordptr[1] = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
rmesa->vb.vertex_size += 2;
rmesa->vb.texcoordptr[1][0] = ctx->Current.Attrib[VERT_ATTRIB_TEX1][0];
rmesa->vb.texcoordptr[1][1] = ctx->Current.Attrib[VERT_ATTRIB_TEX1][1];
}
if (rmesa->vb.installed_vertex_format != rmesa->vb.vtxfmt_0) {
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "reinstall on vertex_format change\n");
_mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
rmesa->vb.installed_vertex_format = rmesa->vb.vtxfmt_0;
}
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s -- success\n", __FUNCTION__);
return GL_TRUE;
}
void r200VtxfmtInvalidate( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
rmesa->vb.recheck = GL_TRUE;
rmesa->vb.fell_back = GL_FALSE;
}
static void r200NewList( GLcontext *ctx, GLuint list, GLenum mode )
{
VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ );
}
static void r200VtxfmtValidate( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s\n", __FUNCTION__);
if (ctx->Driver.NeedFlush)
ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
rmesa->vb.recheck = GL_FALSE;
if (check_vtx_fmt( ctx )) {
if (!rmesa->vb.installed) {
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "reinstall (new install)\n");
_mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
ctx->Driver.FlushVertices = r200VtxFmtFlushVertices;
ctx->Driver.NewList = r200NewList;
rmesa->vb.installed = GL_TRUE;
}
else if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s: already installed", __FUNCTION__);
}
else {
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s: failed\n", __FUNCTION__);
if (rmesa->vb.installed) {
if (rmesa->dma.flush)
rmesa->dma.flush( rmesa );
_tnl_wakeup_exec( ctx );
ctx->Driver.FlushVertices = r200FlushVertices;
rmesa->vb.installed = GL_FALSE;
}
}
}
static void r200_Materialfv( GLenum face, GLenum pname,
const GLfloat *params )
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa = R200_CONTEXT( ctx );
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s\n", __FUNCTION__);
if (rmesa->vb.prim[0] != GL_POLYGON+1) {
VFMT_FALLBACK( __FUNCTION__ );
glMaterialfv( face, pname, params );
return;
}
_mesa_noop_Materialfv( face, pname, params );
r200UpdateMaterial( ctx );
}
static void r200_Begin( GLenum mode )
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s( %s )\n", __FUNCTION__,
_mesa_lookup_enum_by_nr( mode ));
if (mode > GL_POLYGON) {
_mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
return;
}
if (rmesa->vb.prim[0] != GL_POLYGON+1) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
return;
}
if (ctx->NewState)
_mesa_update_state( ctx );
if (rmesa->NewGLState)
r200ValidateState( ctx );
if (rmesa->vb.recheck)
r200VtxfmtValidate( ctx );
if (!rmesa->vb.installed) {
glBegin( mode );
return;
}
if (rmesa->dma.flush && rmesa->vb.counter < 12) {
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s: flush almost-empty buffers\n", __FUNCTION__);
flush_prims( rmesa );
}
if (!rmesa->dma.flush) {
if (rmesa->dma.current.ptr + 12*rmesa->vb.vertex_size*4 >
rmesa->dma.current.end) {
R200_NEWPRIM( rmesa );
r200RefillCurrentDmaRegion( rmesa );
}
rmesa->vb.dmaptr = (int *)(rmesa->dma.current.address + rmesa->dma.current.ptr);
rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) /
(rmesa->vb.vertex_size * 4);
rmesa->vb.counter--;
rmesa->vb.initial_counter = rmesa->vb.counter;
rmesa->vb.notify = wrap_buffer;
rmesa->dma.flush = flush_prims;
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
}
rmesa->vb.prim[0] = mode;
start_prim( rmesa, mode | PRIM_BEGIN );
}
static void r200_End( void )
{
GET_CURRENT_CONTEXT(ctx);
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s\n", __FUNCTION__);
if (rmesa->vb.prim[0] == GL_POLYGON+1) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
return;
}
note_last_prim( rmesa, PRIM_END );
rmesa->vb.prim[0] = GL_POLYGON+1;
}
#define PRE_LOOPBACK( FUNC ) \
do { \
if (R200_DEBUG & DEBUG_VFMT) \
fprintf(stderr, "%s\n", __FUNCTION__); \
VFMT_FALLBACK( __FUNCTION__ ); \
} while (0)
#define TAG(x) r200_fallback_##x
#include "vtxfmt_tmp.h"
static GLboolean r200NotifyBegin( GLcontext *ctx, GLenum p )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(!rmesa->vb.installed);
if (ctx->NewState)
_mesa_update_state( ctx );
if (rmesa->NewGLState)
r200ValidateState( ctx );
if (ctx->Driver.NeedFlush)
ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
if (rmesa->vb.recheck)
r200VtxfmtValidate( ctx );
if (!rmesa->vb.installed) {
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s -- failed\n", __FUNCTION__);
return GL_FALSE;
}
r200_Begin( p );
return GL_TRUE;
}
static void r200VtxFmtFlushVertices( GLcontext *ctx, GLuint flags )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(rmesa->vb.installed);
if (flags & FLUSH_UPDATE_CURRENT) {
r200_copy_to_current( ctx );
if (R200_DEBUG & DEBUG_VFMT)
fprintf(stderr, "reinstall on update_current\n");
_mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
}
if (flags & FLUSH_STORED_VERTICES) {
assert (rmesa->dma.flush == 0 ||
rmesa->dma.flush == flush_prims);
if (rmesa->dma.flush == flush_prims)
flush_prims( rmesa );
ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
}
}
void r200VtxfmtInit( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
GLvertexformat *vfmt = &(rmesa->vb.vtxfmt);
MEMSET( vfmt, 0, sizeof(GLvertexformat) );
r200VtxfmtInitChoosers( vfmt );
vfmt->Materialfv = r200_Materialfv;
vfmt->ArrayElement = _ae_loopback_array_elt;
vfmt->Rectf = _mesa_noop_Rectf;
vfmt->Begin = r200_Begin;
vfmt->End = r200_End;
vfmt->DrawArrays = r200_fallback_DrawArrays;
vfmt->DrawElements = r200_fallback_DrawElements;
vfmt->DrawRangeElements = r200_fallback_DrawRangeElements;
vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT;
vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT;
vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv;
vfmt->Indexi = _mesa_noop_Indexi;
vfmt->Indexiv = _mesa_noop_Indexiv;
vfmt->CallList = r200_fallback_CallList;
vfmt->EvalCoord1f = r200_fallback_EvalCoord1f;
vfmt->EvalCoord1fv = r200_fallback_EvalCoord1fv;
vfmt->EvalCoord2f = r200_fallback_EvalCoord2f;
vfmt->EvalCoord2fv = r200_fallback_EvalCoord2fv;
vfmt->EvalMesh1 = r200_fallback_EvalMesh1;
vfmt->EvalMesh2 = r200_fallback_EvalMesh2;
vfmt->EvalPoint1 = r200_fallback_EvalPoint1;
vfmt->EvalPoint2 = r200_fallback_EvalPoint2;
vfmt->TexCoord3f = r200_fallback_TexCoord3f;
vfmt->TexCoord3fv = r200_fallback_TexCoord3fv;
vfmt->TexCoord4f = r200_fallback_TexCoord4f;
vfmt->TexCoord4fv = r200_fallback_TexCoord4fv;
vfmt->MultiTexCoord3fARB = r200_fallback_MultiTexCoord3fARB;
vfmt->MultiTexCoord3fvARB = r200_fallback_MultiTexCoord3fvARB;
vfmt->MultiTexCoord4fARB = r200_fallback_MultiTexCoord4fARB;
vfmt->MultiTexCoord4fvARB = r200_fallback_MultiTexCoord4fvARB;
vfmt->Vertex4f = r200_fallback_Vertex4f;
vfmt->Vertex4fv = r200_fallback_Vertex4fv;
(void)r200_fallback_vtxfmt;
TNL_CONTEXT(ctx)->Driver.NotifyBegin = r200NotifyBegin;
rmesa->vb.enabled = 1;
rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive;
rmesa->vb.primflags = 0;
make_empty_list( &rmesa->vb.dfn_cache.Vertex2f );
make_empty_list( &rmesa->vb.dfn_cache.Vertex2fv );
make_empty_list( &rmesa->vb.dfn_cache.Vertex3f );
make_empty_list( &rmesa->vb.dfn_cache.Vertex3fv );
make_empty_list( &rmesa->vb.dfn_cache.Color4ub );
make_empty_list( &rmesa->vb.dfn_cache.Color4ubv );
make_empty_list( &rmesa->vb.dfn_cache.Color3ub );
make_empty_list( &rmesa->vb.dfn_cache.Color3ubv );
make_empty_list( &rmesa->vb.dfn_cache.Color4f );
make_empty_list( &rmesa->vb.dfn_cache.Color4fv );
make_empty_list( &rmesa->vb.dfn_cache.Color3f );
make_empty_list( &rmesa->vb.dfn_cache.Color3fv );
make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
make_empty_list( &rmesa->vb.dfn_cache.Normal3f );
make_empty_list( &rmesa->vb.dfn_cache.Normal3fv );
make_empty_list( &rmesa->vb.dfn_cache.TexCoord2f );
make_empty_list( &rmesa->vb.dfn_cache.TexCoord2fv );
make_empty_list( &rmesa->vb.dfn_cache.TexCoord1f );
make_empty_list( &rmesa->vb.dfn_cache.TexCoord1fv );
make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
r200InitCodegen( &rmesa->vb.codegen );
}
static void free_funcs( struct dynfn *l )
{
struct dynfn *f, *tmp;
foreach_s (f, tmp, l) {
remove_from_list( f );
ALIGN_FREE( f->code );
FREE( f );
}
}
void r200VtxfmtUnbindContext( GLcontext *ctx )
{
}
void r200VtxfmtMakeCurrent( GLcontext *ctx )
{
}
void r200VtxfmtDestroy( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
count_funcs( rmesa );
free_funcs( &rmesa->vb.dfn_cache.Vertex2f );
free_funcs( &rmesa->vb.dfn_cache.Vertex2fv );
free_funcs( &rmesa->vb.dfn_cache.Vertex3f );
free_funcs( &rmesa->vb.dfn_cache.Vertex3fv );
free_funcs( &rmesa->vb.dfn_cache.Color4ub );
free_funcs( &rmesa->vb.dfn_cache.Color4ubv );
free_funcs( &rmesa->vb.dfn_cache.Color3ub );
free_funcs( &rmesa->vb.dfn_cache.Color3ubv );
free_funcs( &rmesa->vb.dfn_cache.Color4f );
free_funcs( &rmesa->vb.dfn_cache.Color4fv );
free_funcs( &rmesa->vb.dfn_cache.Color3f );
free_funcs( &rmesa->vb.dfn_cache.Color3fv );
free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
free_funcs( &rmesa->vb.dfn_cache.Normal3f );
free_funcs( &rmesa->vb.dfn_cache.Normal3fv );
free_funcs( &rmesa->vb.dfn_cache.TexCoord2f );
free_funcs( &rmesa->vb.dfn_cache.TexCoord2fv );
free_funcs( &rmesa->vb.dfn_cache.TexCoord1f );
free_funcs( &rmesa->vb.dfn_cache.TexCoord1fv );
free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
}