📄 savagerender.c
字号:
/* * Copyright 2005 Felix Kuehling * 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, sub license, * 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 * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING 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. *//* * Render unclipped vertex buffers by emitting vertices directly to * dma buffers. Use strip/fan hardware primitives where possible. * Simulate missing primitives with indexed vertices. */#include "glheader.h"#include "context.h"#include "macros.h"#include "imports.h"#include "mtypes.h"#include "tnl/t_context.h"#include "savagecontext.h"#include "savagetris.h"#include "savagestate.h"#include "savageioctl.h"/* * Standard render tab for Savage4 and smooth shading on Savage3D */#define HAVE_POINTS 0#define HAVE_LINES 0#define HAVE_LINE_STRIPS 0#define HAVE_TRIANGLES 1#define HAVE_TRI_STRIPS 1#define HAVE_TRI_STRIP_1 0#define HAVE_TRI_FANS 1#define HAVE_POLYGONS 0#define HAVE_QUADS 0#define HAVE_QUAD_STRIPS 0#define HAVE_ELTS 1#define LOCAL_VARS savageContextPtr imesa = SAVAGE_CONTEXT(ctx) #define INIT( prim ) do { \ if (0) fprintf(stderr, "%s\n", __FUNCTION__); \ savageFlushVertices(imesa); \ switch (prim) { \ case GL_TRIANGLES: imesa->HwPrim = SAVAGE_PRIM_TRILIST; break; \ case GL_TRIANGLE_STRIP: imesa->HwPrim = SAVAGE_PRIM_TRISTRIP; break; \ case GL_TRIANGLE_FAN: imesa->HwPrim = SAVAGE_PRIM_TRIFAN; break; \ } \} while (0)#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() \ (imesa->bufferSize/4 / imesa->HwVertexSize)#define ALLOC_VERTS( nr ) \ savageAllocVtxBuf( imesa, (nr) * imesa->HwVertexSize )#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"/* * On Savage3D triangle fans and strips are broken with flat * shading. With triangles it wants the color for flat shading in the * first vertex! So we make another template instance which uses * triangles only (with reordered vertices: SAVAGE_PRIM_TRILIST_201). * The reordering is done by the DRM. */#undef HAVE_TRI_STRIPS#undef HAVE_TRI_FANS#define HAVE_TRI_STRIPS 0#define HAVE_TRI_FANS 0#undef INIT#define INIT( prim ) do { \ if (0) fprintf(stderr, "%s\n", __FUNCTION__); \ savageFlushVertices(imesa); \ imesa->HwPrim = SAVAGE_PRIM_TRILIST_201; \} while(0)#undef TAG#define TAG(x) savage_flat_##x##_s3d#include "tnl_dd/t_dd_dmatmp.h"/**********************************************************************//* Render pipeline stage *//**********************************************************************/static GLboolean savage_run_render( GLcontext *ctx, struct tnl_pipeline_stage *stage ){ savageContextPtr imesa = SAVAGE_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; tnl_render_func *tab, *tab_elts; GLboolean valid; GLuint i; if (savageHaveIndexedVerts(imesa)) 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 vertex manipulations. */ if (imesa->RenderIndex != 0 || !valid) { return GL_TRUE; } tnl->Driver.Render.Start( ctx ); /* Check RenderIndex again. The ptexHack is detected late in RenderStart. * Also check for ptex fallbacks detected late. */ if (imesa->RenderIndex != 0 || imesa->Fallback != 0) { return GL_TRUE; } /* 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++) { GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); GLuint start = VB->Primitive[i].start; GLuint length = VB->Primitive[i].count; if (length) tab[prim & PRIM_MODE_MASK]( ctx, start, start+length, prim); } tnl->Driver.Render.Finish( ctx ); return GL_FALSE; /* finished the pipe */}struct tnl_pipeline_stage _savage_render_stage = { "savage render", NULL, NULL, NULL, NULL, savage_run_render /* run */};/**********************************************************************//* Pipeline stage for texture coordinate normalization *//**********************************************************************/struct texnorm_stage_data { GLboolean active; GLvector4f texcoord[MAX_TEXTURE_UNITS];};#define TEXNORM_STAGE_DATA(stage) ((struct texnorm_stage_data *)stage->privatePtr)static GLboolean run_texnorm_stage( GLcontext *ctx, struct tnl_pipeline_stage *stage ){ struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage); savageContextPtr imesa = SAVAGE_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; GLuint i; if (imesa->Fallback || !store->active) return GL_TRUE; for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { const GLbitfield reallyEnabled = ctx->Texture.Unit[i]._ReallyEnabled; if (reallyEnabled) { const struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current; const GLboolean normalizeS = (texObj->WrapS == GL_REPEAT); const GLboolean normalizeT = (reallyEnabled & TEXTURE_2D_BIT) && (texObj->WrapT == GL_REPEAT); const GLfloat *in = (GLfloat *)VB->TexCoordPtr[i]->data; const GLint instride = VB->TexCoordPtr[i]->stride; GLfloat (*out)[4] = store->texcoord[i].data; GLint j; if (!ctx->Texture.Unit[i]._ReallyEnabled || VB->TexCoordPtr[i]->size == 4) /* Never try to normalize homogenous tex coords! */ continue; if (normalizeS && normalizeT) { /* take first texcoords as rough estimate of mean value */ GLfloat correctionS = -floor(in[0]+0.5); GLfloat correctionT = -floor(in[1]+0.5); for (j = 0; j < VB->Count; ++j) { out[j][0] = in[0] + correctionS; out[j][1] = in[1] + correctionT; in = (GLfloat *)((GLubyte *)in + instride); } } else if (normalizeS) { /* take first texcoords as rough estimate of mean value */ GLfloat correctionS = -floor(in[0]+0.5); if (reallyEnabled & TEXTURE_2D_BIT) { for (j = 0; j < VB->Count; ++j) { out[j][0] = in[0] + correctionS; out[j][1] = in[1]; in = (GLfloat *)((GLubyte *)in + instride); } } else { for (j = 0; j < VB->Count; ++j) { out[j][0] = in[0] + correctionS; in = (GLfloat *)((GLubyte *)in + instride); } } } else if (normalizeT) { /* take first texcoords as rough estimate of mean value */ GLfloat correctionT = -floor(in[1]+0.5); for (j = 0; j < VB->Count; ++j) { out[j][0] = in[0]; out[j][1] = in[1] + correctionT; in = (GLfloat *)((GLubyte *)in + instride); } } if (normalizeS || normalizeT) VB->AttribPtr[VERT_ATTRIB_TEX0+i] = VB->TexCoordPtr[i] = &store->texcoord[i]; } } return GL_TRUE;}/* Called the first time stage->run() is invoked. */static GLboolean alloc_texnorm_data( GLcontext *ctx, struct tnl_pipeline_stage *stage ){ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; struct texnorm_stage_data *store; GLuint i; stage->privatePtr = CALLOC(sizeof(*store)); store = TEXNORM_STAGE_DATA(stage); if (!store) return GL_FALSE; for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 ); return GL_TRUE;}static void validate_texnorm( GLcontext *ctx, struct tnl_pipeline_stage *stage ){ struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage); GLuint flags = 0; if (((ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) && (ctx->Texture.Unit[0]._Current->WrapS == GL_REPEAT)) || ((ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_2D_BIT) && (ctx->Texture.Unit[0]._Current->WrapT == GL_REPEAT))) flags |= VERT_BIT_TEX0; if (((ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) && (ctx->Texture.Unit[1]._Current->WrapS == GL_REPEAT)) || ((ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_2D_BIT) && (ctx->Texture.Unit[1]._Current->WrapT == GL_REPEAT))) flags |= VERT_BIT_TEX1; store->active = (flags != 0);}static void free_texnorm_data( struct tnl_pipeline_stage *stage ){ struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage); GLuint i; if (store) { for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) if (store->texcoord[i].data) _mesa_vector4f_free( &store->texcoord[i] ); FREE( store ); stage->privatePtr = 0; }}struct tnl_pipeline_stage _savage_texnorm_stage ={ "savage texture coordinate normalization stage", /* name */ NULL, /* private data */ alloc_texnorm_data, /* run -- initially set to init */ free_texnorm_data, /* destructor */ validate_texnorm, run_texnorm_stage};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -