📄 brw_vs_tnl.c
字号:
/* * Mesa 3-D graphics library * Version: 6.3 * * Copyright (C) 2005 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/prog_parameter.h"#include "shader/prog_print.h"#include "brw_vs.h"#include "brw_state.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_option: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 void make_state_key( GLcontext *ctx, struct state_key *key ){ struct brw_context *brw = brw_context(ctx); const struct gl_fragment_program *fp = brw->fragment_program; GLuint i; /* This now relies on texenvprogram.c being active: */ assert(fp); memset(key, 0, sizeof(*key)); /* BRW_NEW_FRAGMENT_PROGRAM */ key->fragprog_inputs_read = fp->Base.InputsRead; /* _NEW_LIGHT */ key->separate_specular = (brw->attribs.Light->Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR); /* _NEW_LIGHT */ if (brw->attribs.Light->Enabled) { key->light_global_enabled = 1; if (brw->attribs.Light->Model.LocalViewer) key->light_local_viewer = 1; if (brw->attribs.Light->Model.TwoSide) key->light_twoside = 1; if (brw->attribs.Light->ColorMaterialEnabled) { key->light_color_material = 1; key->light_color_material_mask = brw->attribs.Light->ColorMaterialBitmask; } /* BRW_NEW_INPUT_VARYING */ /* For these programs, material values are stuffed into the * generic slots: */ for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) if (brw->vb.info.varying & (1<<(VERT_ATTRIB_GENERIC0 + i))) key->light_material_mask |= 1<<i; for (i = 0; i < MAX_LIGHTS; i++) { struct gl_light *light = &brw->attribs.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; } } } /* _NEW_TRANSFORM */ if (brw->attribs.Transform->Normalize) key->normalize = 1; if (brw->attribs.Transform->RescaleNormals) key->rescale_normals = 1; /* BRW_NEW_FRAGMENT_PROGRAM */ key->fog_option = translate_fog_mode(fp->FogOption); if (key->fog_option) key->fragprog_inputs_read |= FRAG_BIT_FOGC; /* _NEW_FOG */ if (brw->attribs.Fog->FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) key->fog_source_is_depth = 1; /* _NEW_HINT, ??? */ if (1) key->tnl_do_vertex_fog = 1; /* _NEW_POINT */ if (brw->attribs.Point->_Attenuated) key->point_attenuated = 1; /* _NEW_TEXTURE */ if (brw->attribs.Texture->_TexGenEnabled || brw->attribs.Texture->_TexMatEnabled || brw->attribs.Texture->_EnabledUnits) key->texture_enabled_global = 1; for (i = 0; i < MAX_TEXTURE_UNITS; i++) { struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[i]; if (texUnit->_ReallyEnabled) key->unit[i].texunit_really_enabled = 1; if (brw->attribs.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 ); } }} /* Very useful debugging tool - produces annotated listing of * generated program with line/function references for each * instruction back into this file: */#define DISASSEM 0/* 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 1/* 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 nr_instructions; 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;};const static 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 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 = ffs( ~p->temp_in_use ); if (!bit) { fprintf(stderr, "%s: out of temporaries\n", __FILE__); assert(0); } if (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 ){ assert(input < 32); 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); /* Need to handle swizzle in reg setup */ 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -