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

📄 t_vp_build.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
	    emit_op1(p, OPCODE_LIT, lit, 0, negate(swizzle(dots,X,Y,W,Z)));	    if (!is_undef(att)) 	       emit_op2(p, OPCODE_MUL, lit, 0, lit, att);	    if (count == nr_lights) {	       if (separate) {		  mask0 = WRITEMASK_XYZ;		  mask1 = WRITEMASK_XYZ;		  res0 = register_output( p, VERT_RESULT_BFC0 );		  res1 = register_output( p, VERT_RESULT_BFC1 );	       }	       else {		  mask0 = 0;		  mask1 = WRITEMASK_XYZ;		  res0 = _bfc0;		  res1 = register_output( p, VERT_RESULT_BFC0 );	       }	    } else {	       res0 = _bfc0;	       res1 = _bfc1;	       mask0 = 0;	       mask1 = 0;	    }	    emit_op3(p, OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0);	    emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0);	    emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1);	    release_temp(p, ambient);	    release_temp(p, diffuse);	    release_temp(p, specular);	 }	 release_temp(p, att);      }   }   release_temps( p );}static void build_fog( struct tnl_program *p ){   struct ureg fog = register_output(p, VERT_RESULT_FOGC);   struct ureg input;   if (p->state->fog_source_is_depth) {      input = swizzle1(get_eye_position(p), Z);   }   else {      input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X);   }   if (p->state->fog_mode && p->state->tnl_do_vertex_fog) {      struct ureg params = register_param2(p, STATE_INTERNAL,					   STATE_FOG_PARAMS_OPTIMIZED);      struct ureg tmp = get_temp(p);      GLboolean useabs = (p->state->fog_mode != FOG_EXP2);      if (useabs) {	 emit_op1(p, OPCODE_ABS, tmp, 0, input);      }      switch (p->state->fog_mode) {      case FOG_LINEAR: {	 struct ureg id = get_identity_param(p);	 emit_op3(p, OPCODE_MAD, tmp, 0, useabs ? tmp : input,			swizzle1(params,X), swizzle1(params,Y));	 emit_op2(p, OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */	 emit_op2(p, OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W));	 break;      }      case FOG_EXP:	 emit_op2(p, OPCODE_MUL, tmp, 0, useabs ? tmp : input,			swizzle1(params,Z));	 emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp));	 break;      case FOG_EXP2:	 emit_op2(p, OPCODE_MUL, tmp, 0, input, swizzle1(params,W));	 emit_op2(p, OPCODE_MUL, tmp, 0, tmp, tmp);	 emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp));	 break;      }      release_temp(p, tmp);   }   else {      /* results = incoming fog coords (compute fog per-fragment later)        *       * KW:  Is it really necessary to do anything in this case?       * BP: Yes, we always need to compute the absolute value, unless       * we want to push that down into the fragment program...       */      GLboolean useabs = GL_TRUE;      emit_op1(p, useabs ? OPCODE_ABS : OPCODE_MOV, fog, WRITEMASK_X, input);   }} static void build_reflect_texgen( struct tnl_program *p,				  struct ureg dest,				  GLuint writemask ){   struct ureg normal = get_eye_normal(p);   struct ureg eye_hat = get_eye_position_normalized(p);   struct ureg tmp = get_temp(p);   /* n.u */   emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);    /* 2n.u */   emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);    /* (-2n.u)n + u */   emit_op3(p, OPCODE_MAD, dest, writemask, negate(tmp), normal, eye_hat);   release_temp(p, tmp);}static void build_sphere_texgen( struct tnl_program *p,				 struct ureg dest,				 GLuint writemask ){   struct ureg normal = get_eye_normal(p);   struct ureg eye_hat = get_eye_position_normalized(p);   struct ureg tmp = get_temp(p);   struct ureg half = register_scalar_const(p, .5);   struct ureg r = get_temp(p);   struct ureg inv_m = get_temp(p);   struct ureg id = get_identity_param(p);   /* Could share the above calculations, but it would be    * a fairly odd state for someone to set (both sphere and    * reflection active for different texture coordinate    * components.  Of course - if two texture units enable    * reflect and/or sphere, things start to tilt in favour    * of seperating this out:    */   /* n.u */   emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);    /* 2n.u */   emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);    /* (-2n.u)n + u */   emit_op3(p, OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat);    /* r + 0,0,1 */   emit_op2(p, OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z));    /* rx^2 + ry^2 + (rz+1)^2 */   emit_op2(p, OPCODE_DP3, tmp, 0, tmp, tmp);    /* 2/m */   emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);    /* 1/m */   emit_op2(p, OPCODE_MUL, inv_m, 0, tmp, half);    /* r/m + 1/2 */   emit_op3(p, OPCODE_MAD, dest, writemask, r, inv_m, half); 	          release_temp(p, tmp);   release_temp(p, r);   release_temp(p, inv_m);}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_TEX(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);      }   }}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);   /* dist = |eyez| */   emit_op1(p, OPCODE_ABS, ut, WRITEMASK_Y, swizzle1(eye, Z));   /* p1 + dist * (p2 + dist * p3); */   emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),		swizzle1(state_attenuation, Z), swizzle1(state_attenuation, Y));   emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),		ut, swizzle1(state_attenuation, X));   /* 1 / sqrt(factor) */   emit_op1(p, OPCODE_RSQ, ut, WRITEMASK_X, ut );#if 1   /* out = pointSize / sqrt(factor) */   emit_op2(p, OPCODE_MUL, out, WRITEMASK_X, ut, state_size);#else   /* not sure, might make sense to do clamping here,      but it's not done in t_vb_points neither */   emit_op2(p, OPCODE_MUL, ut, WRITEMASK_X, ut, state_size);   emit_op2(p, OPCODE_MAX, ut, WRITEMASK_X, ut, swizzle1(state_size, Y));   emit_op2(p, OPCODE_MIN, out, WRITEMASK_X, ut, swizzle1(state_size, Z));#endif   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_mode != 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 voidcreate_new_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;      if (max_temps >= sizeof(int) * 8)      p.temp_reserved = 0;   else      p.temp_reserved = ~((1<<max_temps)-1);   p.program->Base.Instructions = _mesa_alloc_instructions(MAX_INSN);   p.program->Base.String = NULL;   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 struct gl_vertex_program *search_cache(struct tnl_cache *cache, GLuint hash,             const void *key, GLuint keysize){   struct tnl_cache_item *c;   for (c = cache->items[hash % cache->size]; c; c = c->next) {      if (c->hash == hash && _mesa_memcmp(c->key, key, keysize) == 0)	 return c->prog;   }   return NULL;}static void rehash( struct tnl_cache *cache ){   struct tnl_cache_item **items;   struct tnl_cache_item *c, *next;   GLuint size, i;   size = cache->size * 3;   items = (struct 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( GLcontext *ctx,                        struct tnl_cache *cache,			GLuint hash,			void *key,			struct gl_vertex_program *prog ){   struct tnl_cache_item *c = CALLOC_STRUCT(tnl_cache_item);   c->hash = hash;   c->key = key;   c->prog = prog;   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;}void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx ){   TNLcontext *tnl = TNL_CONTEXT(ctx);   struct state_key *key;   GLuint hash;   const struct gl_vertex_program *prev = ctx->VertexProgram._Current;   if (!ctx->VertexProgram._Current ||       ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram) {      struct gl_vertex_program *newProg;      /* Grab all the relevent state and put it in a single structure:       */      key = make_state_key(ctx);      hash = hash_key(key);      /* Look for an already-prepared program for this state:       */      newProg = search_cache( tnl->vp_cache, hash, key, sizeof(*key));         /* OK, we'll have to build a new one:       */      if (!newProg) {	 if (0)	    _mesa_printf("Build new TNL program\n");	 	 newProg = (struct gl_vertex_program *)	    ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); 	 create_new_program( key, newProg, ctx->Const.VertexProgram.MaxTemps );	 if (ctx->Driver.ProgramStringNotify)	    ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB,                                              &newProg->Base );         /* Our ownership of newProg is transferred to the cache */	 cache_item(ctx, tnl->vp_cache, hash, key, newProg);      }      else {	 FREE(key);      }      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, newProg);      _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, newProg);   }   /* Tell the driver about the change.  Could define a new target for    * this?    */   if (ctx->VertexProgram._Current != prev && ctx->Driver.BindProgram) {      ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,                            (struct gl_program *) ctx->VertexProgram._Current);   }}void _tnl_ProgramCacheInit( GLcontext *ctx ){   TNLcontext *tnl = TNL_CONTEXT(ctx);   tnl->vp_cache = (struct tnl_cache *) MALLOC(sizeof(*tnl->vp_cache));   tnl->vp_cache->size = 17;   tnl->vp_cache->n_items = 0;   tnl->vp_cache->items = (struct tnl_cache_item**)      _mesa_calloc(tnl->vp_cache->size * sizeof(*tnl->vp_cache->items));}void _tnl_ProgramCacheDestroy( GLcontext *ctx ){   TNLcontext *tnl = TNL_CONTEXT(ctx);   struct tnl_cache_item *c, *next;   GLuint i;   for (i = 0; i < tnl->vp_cache->size; i++)      for (c = tnl->vp_cache->items[i]; c; c = next) {	 next = c->next;	 FREE(c->key);	 _mesa_reference_vertprog(ctx, &c->prog, NULL);	 FREE(c);      }   FREE(tnl->vp_cache->items);   FREE(tnl->vp_cache);}

⌨️ 快捷键说明

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