📄 r200_vtxfmt.c
字号:
/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_vtxfmt.c,v 1.4 2003/05/06 23:52:08 daenzer Exp $ *//*Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.The Weather Channel (TM) funded Tungsten Graphics to develop theinitial release of the Radeon 8500 driver under the XFree86 license.This notice must be preserved.Permission is hereby granted, free of charge, to any person obtaininga copy of this software and associated documentation files (the"Software"), to deal in the Software without restriction, includingwithout limitation the rights to use, copy, modify, merge, publish,distribute, sublicense, and/or sell copies of the Software, and topermit persons to whom the Software is furnished to do so, subject tothe following conditions:The above copyright notice and this permission notice (including thenext paragraph) shall be included in all copies or substantialportions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OFMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BELIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTIONOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTIONWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.**************************************************************************//* * Authors: * Keith Whitwell <keith@tungstengraphics.com> */#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"#include "dispatch.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( "TexCoord3f", &rmesa->vb.dfn_cache.TexCoord3f ); count_func( "TexCoord3fv", &rmesa->vb.dfn_cache.TexCoord3fv ); 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( "MultiTexCoord3fARB", &rmesa->vb.dfn_cache.MultiTexCoord3fARB ); count_func( "MultiTexCoord3fvARB", &rmesa->vb.dfn_cache.MultiTexCoord3fvARB ); 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 );/* count_func( "FogCoordfEXT", &rmesa->vb.dfn_cache.FogCoordfEXT ); count_func( "FogCoordfvEXT", &rmesa->vb.dfn_cache.FogCoordfvEXT );*/}void r200_copy_to_current( GLcontext *ctx ) { r200ContextPtr rmesa = R200_CONTEXT(ctx); unsigned i; 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]; } if (rmesa->vb.vtxfmt_0 & R200_VTX_DISCRETE_FOG) { ctx->Current.Attrib[VERT_ATTRIB_FOG][0] = rmesa->vb.fogptr[0]; } 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 ); } for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) { const unsigned count = VTX_TEXn_COUNT( rmesa->vb.vtxfmt_1, i ); GLfloat * const src = rmesa->vb.texcoordptr[i]; if ( count != 0 ) { switch( count ) { case 3: ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][1] = src[1]; ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][2] = src[2]; break; case 2: ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][1] = src[1]; ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][2] = 0.0F; break; case 1: ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][1] = 0.0F; ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][2] = 0.0F; break; } ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][0] = src[0]; ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][3] = 1.0F; } } ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;}static GLboolean discreet_gl_prim[GL_POLYGON+1] = { 1, /* 0 points */ 1, /* 1 lines */ 0, /* 2 line_strip */ 0, /* 3 line_loop */ 1, /* 4 tris */ 0, /* 5 tri_fan */ 0, /* 6 tri_strip */ 1, /* 7 quads */ 0, /* 8 quadstrip */ 0, /* 9 poly */};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 = NULL; /* Optimize the primitive list: */ 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]; }}/* NOTE: This actually reads the copied vertices back from uncached * memory. Could also use the counter/notify mechanism to populate * tmp on the fly as vertices are generated. */static GLuint copy_dma_verts( r200ContextPtr rmesa, GLfloat (*tmp)[R200_MAX_VERTEX_SIZE] ){ 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 ); /* clear state so fell_back sticks */ _tnl_wakeup_exec( ctx ); ctx->Driver.FlushVertices = r200FlushVertices; assert( rmesa->dma.flush == 0 ); rmesa->vb.fell_back = GL_TRUE; rmesa->vb.installed = GL_FALSE;}/** * \todo * An interesting optimization of this function would be to have 3 element * table with the dispatch offsets of the TexCoord?fv functions, use count * to look-up the table, and a specialized version of GL_CALL that used the * offset number instead of the name.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -