📄 brw_vs_tnl.c
字号:
static void build_texture_transform( struct tnl_program *p ){ GLuint i, j; for (i = 0; i < MAX_TEXTURE_UNITS; i++) { if (!(p->state->fragprog_inputs_read & (FRAG_BIT_TEX0<<i))) continue; if (p->state->unit[i].texgen_enabled || p->state->unit[i].texmat_enabled) { GLuint texmat_enabled = p->state->unit[i].texmat_enabled; struct ureg out = register_output(p, VERT_RESULT_TEX0 + i); struct ureg out_texgen = undef; if (p->state->unit[i].texgen_enabled) { GLuint copy_mask = 0; GLuint sphere_mask = 0; GLuint reflect_mask = 0; GLuint normal_mask = 0; GLuint modes[4]; if (texmat_enabled) out_texgen = get_temp(p); else out_texgen = out; modes[0] = p->state->unit[i].texgen_mode0; modes[1] = p->state->unit[i].texgen_mode1; modes[2] = p->state->unit[i].texgen_mode2; modes[3] = p->state->unit[i].texgen_mode3; for (j = 0; j < 4; j++) { switch (modes[j]) { case TXG_OBJ_LINEAR: { struct ureg obj = register_input(p, VERT_ATTRIB_POS); struct ureg plane = register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_OBJECT_S + j); emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, obj, plane ); break; } case TXG_EYE_LINEAR: { struct ureg eye = get_eye_position(p); struct ureg plane = register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_EYE_S + j); emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, eye, plane ); break; } case TXG_SPHERE_MAP: sphere_mask |= WRITEMASK_X << j; break; case TXG_REFLECTION_MAP: reflect_mask |= WRITEMASK_X << j; break; case TXG_NORMAL_MAP: normal_mask |= WRITEMASK_X << j; break; case TXG_NONE: copy_mask |= WRITEMASK_X << j; } } if (sphere_mask) { build_sphere_texgen(p, out_texgen, sphere_mask); } if (reflect_mask) { build_reflect_texgen(p, out_texgen, reflect_mask); } if (normal_mask) { struct ureg normal = get_eye_normal(p); emit_op1(p, OPCODE_MOV, out_texgen, normal_mask, normal ); } if (copy_mask) { struct ureg in = register_input(p, VERT_ATTRIB_TEX0+i); emit_op1(p, OPCODE_MOV, out_texgen, copy_mask, in ); } } if (texmat_enabled) { struct ureg texmat[4]; struct ureg in = (!is_undef(out_texgen) ? out_texgen : register_input(p, VERT_ATTRIB_TEX0+i)); if (PREFER_DP4) { register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3, 0, texmat ); emit_matrix_transform_vec4( p, out, texmat, in ); } else { register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3, STATE_MATRIX_TRANSPOSE, texmat ); emit_transpose_matrix_transform_vec4( p, out, texmat, in ); } } release_temps(p); } else { emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i); } }}/* Seems like it could be tighter: */static void build_pointsize( struct tnl_program *p ){ struct ureg eye = get_eye_position(p); struct ureg state_size = register_param1(p, STATE_POINT_SIZE); struct ureg state_attenuation = register_param1(p, STATE_POINT_ATTENUATION); struct ureg out = register_output(p, VERT_RESULT_PSIZ); struct ureg ut = get_temp(p); /* 1, Z, Z * Z, 1 */ emit_op1(p, OPCODE_MOV, ut, WRITEMASK_XW, swizzle1(get_identity_param(p), W)); emit_op1(p, OPCODE_ABS, ut, WRITEMASK_YZ, swizzle1(eye, Z)); emit_op2(p, OPCODE_MUL, ut, WRITEMASK_Z, ut, ut); /* p1 + p2 * dist + p3 * dist * dist, 0 */ emit_op2(p, OPCODE_DP3, ut, WRITEMASK_X, ut, state_attenuation); /* 1 / sqrt(factor) */ emit_op1(p, OPCODE_RSQ, ut, WRITEMASK_X, ut ); /* ut = pointSize / factor */ emit_op2(p, OPCODE_MUL, ut, WRITEMASK_X, ut, state_size); /* Clamp to min/max - state_size.[yz] */ emit_op2(p, OPCODE_MAX, ut, WRITEMASK_X, ut, swizzle1(state_size, Y)); emit_op2(p, OPCODE_MIN, out, 0, swizzle1(ut, X), swizzle1(state_size, Z)); release_temp(p, ut);}static void build_tnl_program( struct tnl_program *p ){ /* Emit the program, starting with modelviewproject: */ build_hpos(p); /* Lighting calculations: */ if (p->state->fragprog_inputs_read & (FRAG_BIT_COL0|FRAG_BIT_COL1)) { if (p->state->light_global_enabled) build_lighting(p); else { if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL0); if (p->state->fragprog_inputs_read & FRAG_BIT_COL1) emit_passthrough(p, VERT_ATTRIB_COLOR1, VERT_RESULT_COL1); } } if ((p->state->fragprog_inputs_read & FRAG_BIT_FOGC) || p->state->fog_option != FOG_NONE) build_fog(p); if (p->state->fragprog_inputs_read & FRAG_BITS_TEX_ANY) build_texture_transform(p); if (p->state->point_attenuated) build_pointsize(p); /* Finish up: */ emit_op1(p, OPCODE_END, undef, 0, undef); /* Disassemble: */ if (DISASSEM) { _mesa_printf ("\n"); }}static void build_new_tnl_program( const struct state_key *key, struct gl_vertex_program *program, GLuint max_temps){ struct tnl_program p; _mesa_memset(&p, 0, sizeof(p)); p.state = key; p.program = program; p.eye_position = undef; p.eye_position_normalized = undef; p.eye_normal = undef; p.identity = undef; p.temp_in_use = 0; p.nr_instructions = 16; if (max_temps >= sizeof(int) * 8) p.temp_reserved = 0; else p.temp_reserved = ~((1<<max_temps)-1); p.program->Base.Instructions = _mesa_malloc(sizeof(struct prog_instruction) * p.nr_instructions); p.program->Base.String = 0; p.program->Base.NumInstructions = p.program->Base.NumTemporaries = p.program->Base.NumParameters = p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0; p.program->Base.Parameters = _mesa_new_parameter_list(); p.program->Base.InputsRead = 0; p.program->Base.OutputsWritten = 0; build_tnl_program( &p );}static void *search_cache( struct brw_tnl_cache *cache, GLuint hash, const void *key, GLuint keysize){ struct brw_tnl_cache_item *c; for (c = cache->items[hash % cache->size]; c; c = c->next) { if (c->hash == hash && memcmp(c->key, key, keysize) == 0) return c->data; } return NULL;}static void rehash( struct brw_tnl_cache *cache ){ struct brw_tnl_cache_item **items; struct brw_tnl_cache_item *c, *next; GLuint size, i; size = cache->size * 3; items = (struct brw_tnl_cache_item**) _mesa_malloc(size * sizeof(*items)); _mesa_memset(items, 0, size * sizeof(*items)); for (i = 0; i < cache->size; i++) for (c = cache->items[i]; c; c = next) { next = c->next; c->next = items[c->hash % size]; items[c->hash % size] = c; } FREE(cache->items); cache->items = items; cache->size = size;}static void cache_item( struct brw_tnl_cache *cache, GLuint hash, const struct state_key *key, void *data ){ struct brw_tnl_cache_item *c = MALLOC(sizeof(*c)); c->hash = hash; c->key = malloc(sizeof(*key)); memcpy(c->key, key, sizeof(*key)); c->data = data; if (++cache->n_items > cache->size * 1.5) rehash(cache); c->next = cache->items[hash % cache->size]; cache->items[hash % cache->size] = c;}static GLuint hash_key( struct state_key *key ){ GLuint *ikey = (GLuint *)key; GLuint hash = 0, i; /* I'm sure this can be improved on, but speed is important: */ for (i = 0; i < sizeof(*key)/sizeof(GLuint); i++) hash += ikey[i]; return hash;}static int prepare_tnl_program( struct brw_context *brw ){ GLcontext *ctx = &brw->intel.ctx; struct state_key key; GLuint hash; struct gl_vertex_program *old = brw->tnl_program; /* _NEW_PROGRAM */ if (brw->attribs.VertexProgram->_Current) return 0; /* Grab all the relevent state and put it in a single structure: */ make_state_key(ctx, &key); hash = hash_key(&key); /* Look for an already-prepared program for this state: */ brw->tnl_program = (struct gl_vertex_program *) search_cache( &brw->tnl_program_cache, hash, &key, sizeof(key) ); /* OK, we'll have to build a new one: */ if (!brw->tnl_program) { brw->tnl_program = (struct gl_vertex_program *) ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); build_new_tnl_program( &key, brw->tnl_program, /* ctx->Const.MaxVertexProgramTemps */ 32 ); if (ctx->Driver.ProgramStringNotify) ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB, &brw->tnl_program->Base ); cache_item( &brw->tnl_program_cache, hash, &key, brw->tnl_program ); } if (old != brw->tnl_program) brw->state.dirty.brw |= BRW_NEW_TNL_PROGRAM; return 0;}/* Note: See brw_draw.c - the vertex program must not rely on * brw->primitive or brw->reduced_prim. */const struct brw_tracked_state brw_tnl_vertprog = { .dirty = { .mesa = (_NEW_PROGRAM | _NEW_LIGHT | _NEW_TRANSFORM | _NEW_FOG | _NEW_HINT | _NEW_POINT | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX), .brw = (BRW_NEW_FRAGMENT_PROGRAM | BRW_NEW_INPUT_VARYING), .cache = 0 }, .prepare = prepare_tnl_program};static int prepare_active_vertprog( struct brw_context *brw ){ const struct gl_vertex_program *prev = brw->vertex_program; /* NEW_PROGRAM */ if (brw->attribs.VertexProgram->_Current) { brw->vertex_program = brw->attribs.VertexProgram->_Current; } else { /* BRW_NEW_TNL_PROGRAM */ brw->vertex_program = brw->tnl_program; } if (brw->vertex_program != prev) brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM; return 0;}const struct brw_tracked_state brw_active_vertprog = { .dirty = { .mesa = _NEW_PROGRAM, .brw = BRW_NEW_TNL_PROGRAM, .cache = 0 }, .prepare = prepare_active_vertprog};void brw_ProgramCacheInit( GLcontext *ctx ){ struct brw_context *brw = brw_context(ctx); brw->tnl_program_cache.size = 17; brw->tnl_program_cache.n_items = 0; brw->tnl_program_cache.items = (struct brw_tnl_cache_item **) _mesa_calloc(brw->tnl_program_cache.size * sizeof(struct brw_tnl_cache_item));}void brw_ProgramCacheDestroy( GLcontext *ctx ){ struct brw_context *brw = brw_context(ctx); struct brw_tnl_cache_item *c, *next; GLuint i; for (i = 0; i < brw->tnl_program_cache.size; i++) for (c = brw->tnl_program_cache.items[i]; c; c = next) { next = c->next; FREE(c->key); FREE(c->data); FREE(c); } FREE(brw->tnl_program_cache.items);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -