⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t_vp_build.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Mesa 3-D graphics library * Version:  7.1 * * Copyright (C) 2007  Tungsten Graphics   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, sublicense, * 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 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 NONINFRINGEMENT.  IN NO EVENT SHALL * TUNGSTEN GRAPHICS 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. *//** * \file t_vp_build.c * Create a vertex program to execute the current fixed function T&L pipeline. * \author Keith Whitwell */#include "glheader.h"#include "macros.h"#include "enums.h"#include "shader/program.h"#include "shader/prog_instruction.h"#include "shader/prog_parameter.h"#include "shader/prog_print.h"#include "shader/prog_statevars.h"#include "t_context.h" /* NOTE: very light dependency on this */#include "t_vp_build.h"struct state_key {   unsigned light_global_enabled:1;   unsigned light_local_viewer:1;   unsigned light_twoside:1;   unsigned light_color_material:1;   unsigned light_color_material_mask:12;   unsigned light_material_mask:12;   unsigned normalize:1;   unsigned rescale_normals:1;   unsigned fog_source_is_depth:1;   unsigned tnl_do_vertex_fog:1;   unsigned separate_specular:1;   unsigned fog_mode:2;   unsigned point_attenuated:1;   unsigned texture_enabled_global:1;   unsigned fragprog_inputs_read:12;   struct {      unsigned light_enabled:1;      unsigned light_eyepos3_is_zero:1;      unsigned light_spotcutoff_is_180:1;      unsigned light_attenuated:1;            unsigned texunit_really_enabled:1;      unsigned texmat_enabled:1;      unsigned texgen_enabled:4;      unsigned texgen_mode0:4;      unsigned texgen_mode1:4;      unsigned texgen_mode2:4;      unsigned texgen_mode3:4;   } unit[8];};#define FOG_NONE   0#define FOG_LINEAR 1#define FOG_EXP    2#define FOG_EXP2   3static GLuint translate_fog_mode( GLenum mode ){   switch (mode) {   case GL_LINEAR: return FOG_LINEAR;   case GL_EXP: return FOG_EXP;   case GL_EXP2: return FOG_EXP2;   default: return FOG_NONE;   }}#define TXG_NONE           0#define TXG_OBJ_LINEAR     1#define TXG_EYE_LINEAR     2#define TXG_SPHERE_MAP     3#define TXG_REFLECTION_MAP 4#define TXG_NORMAL_MAP     5static GLuint translate_texgen( GLboolean enabled, GLenum mode ){   if (!enabled)      return TXG_NONE;   switch (mode) {   case GL_OBJECT_LINEAR: return TXG_OBJ_LINEAR;   case GL_EYE_LINEAR: return TXG_EYE_LINEAR;   case GL_SPHERE_MAP: return TXG_SPHERE_MAP;   case GL_REFLECTION_MAP_NV: return TXG_REFLECTION_MAP;   case GL_NORMAL_MAP_NV: return TXG_NORMAL_MAP;   default: return TXG_NONE;   }}static struct state_key *make_state_key( GLcontext *ctx ){   TNLcontext *tnl = TNL_CONTEXT(ctx);   struct vertex_buffer *VB = &tnl->vb;   const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;   struct state_key *key = CALLOC_STRUCT(state_key);   GLuint i;   /* This now relies on texenvprogram.c being active:    */   assert(fp);   key->fragprog_inputs_read = fp->Base.InputsRead;   key->separate_specular = (ctx->Light.Model.ColorControl ==			     GL_SEPARATE_SPECULAR_COLOR);   if (ctx->Light.Enabled) {      key->light_global_enabled = 1;      if (ctx->Light.Model.LocalViewer)	 key->light_local_viewer = 1;      if (ctx->Light.Model.TwoSide)	 key->light_twoside = 1;      if (ctx->Light.ColorMaterialEnabled) {	 key->light_color_material = 1;	 key->light_color_material_mask = ctx->Light.ColorMaterialBitmask;      }      for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) 	 if (VB->AttribPtr[i]->stride) 	    key->light_material_mask |= 1<<(i-_TNL_ATTRIB_MAT_FRONT_AMBIENT);      for (i = 0; i < MAX_LIGHTS; i++) {	 struct gl_light *light = &ctx->Light.Light[i];	 if (light->Enabled) {	    key->unit[i].light_enabled = 1;	    if (light->EyePosition[3] == 0.0)	       key->unit[i].light_eyepos3_is_zero = 1;	    	    if (light->SpotCutoff == 180.0)	       key->unit[i].light_spotcutoff_is_180 = 1;	    if (light->ConstantAttenuation != 1.0 ||		light->LinearAttenuation != 0.0 ||		light->QuadraticAttenuation != 0.0)	       key->unit[i].light_attenuated = 1;	 }      }   }   if (ctx->Transform.Normalize)      key->normalize = 1;   if (ctx->Transform.RescaleNormals)      key->rescale_normals = 1;   key->fog_mode = translate_fog_mode(fp->FogOption);      if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)      key->fog_source_is_depth = 1;      if (tnl->_DoVertexFog)      key->tnl_do_vertex_fog = 1;   if (ctx->Point._Attenuated)      key->point_attenuated = 1;   if (ctx->Texture._TexGenEnabled ||       ctx->Texture._TexMatEnabled ||       ctx->Texture._EnabledUnits)      key->texture_enabled_global = 1;         for (i = 0; i < MAX_TEXTURE_UNITS; i++) {      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];      if (texUnit->_ReallyEnabled)	 key->unit[i].texunit_really_enabled = 1;      if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))      	 key->unit[i].texmat_enabled = 1;            if (texUnit->TexGenEnabled) {	 key->unit[i].texgen_enabled = 1;      	 key->unit[i].texgen_mode0 = 	    translate_texgen( texUnit->TexGenEnabled & (1<<0),			      texUnit->GenModeS );	 key->unit[i].texgen_mode1 = 	    translate_texgen( texUnit->TexGenEnabled & (1<<1),			      texUnit->GenModeT );	 key->unit[i].texgen_mode2 = 	    translate_texgen( texUnit->TexGenEnabled & (1<<2),			      texUnit->GenModeR );	 key->unit[i].texgen_mode3 = 	    translate_texgen( texUnit->TexGenEnabled & (1<<3),			      texUnit->GenModeQ );      }   }      return key;}   /* Very useful debugging tool - produces annotated listing of * generated program with line/function references for each * instruction back into this file: */#define DISASSEM (MESA_VERBOSE&VERBOSE_DISASSEM)/* Should be tunable by the driver - do we want to do matrix * multiplications with DP4's or with MUL/MAD's?  SSE works better * with the latter, drivers may differ. */#define PREFER_DP4 0#define MAX_INSN 350/* Use uregs to represent registers internally, translate to Mesa's * expected formats on emit.   * * NOTE: These are passed by value extensively in this file rather * than as usual by pointer reference.  If this disturbs you, try * remembering they are just 32bits in size. * * GCC is smart enough to deal with these dword-sized structures in * much the same way as if I had defined them as dwords and was using * macros to access and set the fields.  This is much nicer and easier * to evolve. */struct ureg {   GLuint file:4;   GLint idx:8;      /* relative addressing may be negative */   GLuint negate:1;   GLuint swz:12;   GLuint pad:7;};struct tnl_program {   const struct state_key *state;   struct gl_vertex_program *program;      GLuint temp_in_use;   GLuint temp_reserved;      struct ureg eye_position;   struct ureg eye_position_normalized;   struct ureg eye_normal;   struct ureg identity;   GLuint materials;   GLuint color_materials;};static const struct ureg undef = {    PROGRAM_UNDEFINED,   ~0,   0,   0,   0};/* Local shorthand: */#define X    SWIZZLE_X#define Y    SWIZZLE_Y#define Z    SWIZZLE_Z#define W    SWIZZLE_W/* Construct a ureg: */static struct ureg make_ureg(GLuint file, GLint idx){   struct ureg reg;   reg.file = file;   reg.idx = idx;   reg.negate = 0;   reg.swz = SWIZZLE_NOOP;   reg.pad = 0;   return reg;}static struct ureg negate( struct ureg reg ){   reg.negate ^= 1;   return reg;} static struct ureg swizzle( struct ureg reg, int x, int y, int z, int w ){   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),			   GET_SWZ(reg.swz, y),			   GET_SWZ(reg.swz, z),			   GET_SWZ(reg.swz, w));   return reg;}static struct ureg swizzle1( struct ureg reg, int x ){   return swizzle(reg, x, x, x, x);}static struct ureg get_temp( struct tnl_program *p ){   int bit = _mesa_ffs( ~p->temp_in_use );   if (!bit) {      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);      _mesa_exit(1);   }   if ((GLuint) bit > p->program->Base.NumTemporaries)      p->program->Base.NumTemporaries = bit;   p->temp_in_use |= 1<<(bit-1);   return make_ureg(PROGRAM_TEMPORARY, bit-1);}static struct ureg reserve_temp( struct tnl_program *p ){   struct ureg temp = get_temp( p );   p->temp_reserved |= 1<<temp.idx;   return temp;}static void release_temp( struct tnl_program *p, struct ureg reg ){   if (reg.file == PROGRAM_TEMPORARY) {      p->temp_in_use &= ~(1<<reg.idx);      p->temp_in_use |= p->temp_reserved; /* can't release reserved temps */   }}static void release_temps( struct tnl_program *p ){   p->temp_in_use = p->temp_reserved;}static struct ureg register_input( struct tnl_program *p, GLuint input ){   p->program->Base.InputsRead |= (1<<input);   return make_ureg(PROGRAM_INPUT, input);}static struct ureg register_output( struct tnl_program *p, GLuint output ){   p->program->Base.OutputsWritten |= (1<<output);   return make_ureg(PROGRAM_OUTPUT, output);}static struct ureg register_const4f( struct tnl_program *p, 			      GLfloat s0,			      GLfloat s1,			      GLfloat s2,			      GLfloat s3){   GLfloat values[4];   GLint idx;   GLuint swizzle;   values[0] = s0;   values[1] = s1;   values[2] = s2;   values[3] = s3;   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,                                     &swizzle );   ASSERT(swizzle == SWIZZLE_NOOP);   return make_ureg(PROGRAM_STATE_VAR, idx);}#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)#define register_scalar_const(p, s0)    register_const4f(p, s0, s0, s0, s0)#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)static GLboolean is_undef( struct ureg reg ){   return reg.file == PROGRAM_UNDEFINED;}static struct ureg get_identity_param( struct tnl_program *p ){   if (is_undef(p->identity))       p->identity = register_const4f(p, 0,0,0,1);   return p->identity;}static struct ureg register_param5(struct tnl_program *p, 				   GLint s0,				   GLint s1,				   GLint s2,				   GLint s3,                                   GLint s4){   gl_state_index tokens[STATE_LENGTH];   GLint idx;   tokens[0] = s0;   tokens[1] = s1;   tokens[2] = s2;   tokens[3] = s3;   tokens[4] = s4;   idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );   return make_ureg(PROGRAM_STATE_VAR, idx);}#define register_param1(p,s0)          register_param5(p,s0,0,0,0,0)#define register_param2(p,s0,s1)       register_param5(p,s0,s1,0,0,0)#define register_param3(p,s0,s1,s2)    register_param5(p,s0,s1,s2,0,0)#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)static void register_matrix_param5( struct tnl_program *p,				    GLint s0, /* modelview, projection, etc */				    GLint s1, /* texture matrix number */				    GLint s2, /* first row */				    GLint s3, /* last row */				    GLint s4, /* inverse, transpose, etc */				    struct ureg *matrix ){   GLint i;   /* This is a bit sad as the support is there to pull the whole    * matrix out in one go:    */   for (i = 0; i <= s3 - s2; i++)       matrix[i] = register_param5( p, s0, s1, i, i, s4 );}/** * Convert a ureg source register to a prog_src_register. */static void emit_arg( struct prog_src_register *src,		      struct ureg reg ){   assert(reg.file != PROGRAM_OUTPUT);   src->File = reg.file;   src->Index = reg.idx;   src->Swizzle = reg.swz;   src->NegateBase = reg.negate ? NEGATE_XYZW : 0;   src->Abs = 0;   src->NegateAbs = 0;   src->RelAddr = 0;}/** * Convert a ureg dest register to a prog_dst_register. */static void emit_dst( struct prog_dst_register *dst,		      struct ureg reg, GLuint mask ){   /* Check for legal output register type.  UNDEFINED will occur in    * instruction that don't produce a result (like END).    */   assert(reg.file == PROGRAM_TEMPORARY ||          reg.file == PROGRAM_OUTPUT ||          reg.file == PROGRAM_UNDEFINED);   dst->File = reg.file;   dst->Index = reg.idx;   /* allow zero as a shorthand for xyzw */   dst->WriteMask = mask ? mask : WRITEMASK_XYZW;    dst->CondMask = COND_TR;  /* always pass cond test */   dst->CondSwizzle = SWIZZLE_NOOP;   dst->CondSrc = 0;   dst->pad = 0;}static void debug_insn( struct prog_instruction *inst, const char *fn,			GLuint line ){   if (DISASSEM) {      static const char *last_fn;         if (fn != last_fn) {	 last_fn = fn;	 _mesa_printf("%s:\n", fn);      }	       _mesa_printf("%d:\t", line);      _mesa_print_instruction(inst);   }}static void emit_op3fn(struct tnl_program *p,                       enum prog_opcode op,		       struct ureg dest,		       GLuint mask,		       struct ureg src0,		       struct ureg src1,		       struct ureg src2,		       const char *fn,		       GLuint line){   GLuint nr = p->program->Base.NumInstructions++;   struct prog_instruction *inst = &p->program->Base.Instructions[nr];         if (p->program->Base.NumInstructions > MAX_INSN) {      _mesa_problem(0, "Out of instructions in emit_op3fn\n");      return;   }         inst->Opcode = (enum prog_opcode) op;    inst->StringPos = 0;   inst->Data = 0;      emit_arg( &inst->SrcReg[0], src0 );   emit_arg( &inst->SrcReg[1], src1 );   emit_arg( &inst->SrcReg[2], src2 );      emit_dst( &inst->DstReg, dest, mask );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -