t_vb_arbprogram.c

来自「mesa-6.5-minigui源码」· C语言 代码 · 共 1,571 行 · 第 1/3 页

C
1,571
字号
      if (result == REG_RES) {	 op = cvp_next_instruction(cp);	 *op = fixup;      }      break;   }   case OPCODE_END:      break;   default:      result = cvp_choose_result( cp, &inst->DstReg, &fixup );      nr_args = _mesa_num_inst_src_regs(inst->Opcode);      for (i = 0; i < nr_args; i++) 	 reg[i] = cvp_emit_arg( cp, &inst->SrcReg[i], REG_ARG0 + i );      op = cvp_next_instruction(cp);      op->alu.opcode = inst->Opcode;      op->alu.file0 = reg[0].file;      op->alu.idx0 = reg[0].idx;      op->alu.file1 = reg[1].file;      op->alu.idx1 = reg[1].idx;      op->alu.dst = result;      if (result == REG_RES) {	 op = cvp_next_instruction(cp);	 *op = fixup;      }      	       break;   }}static void free_tnl_data( struct vertex_program *program  ){   struct tnl_compiled_program *p = (struct tnl_compiled_program *) program->TnlData;   if (p->compiled_func)      _mesa_free((void *)p->compiled_func);   _mesa_free(p);   program->TnlData = NULL;}static void compile_vertex_program( struct vertex_program *program,				    GLboolean try_codegen ){    struct compilation cp;   struct tnl_compiled_program *p = CALLOC_STRUCT(tnl_compiled_program);   GLuint i;   if (program->TnlData)       free_tnl_data( program );      program->TnlData = p;   /* Initialize cp.  Note that ctx and VB aren't used in compilation    * so we don't have to worry about statechanges:    */   _mesa_memset(&cp, 0, sizeof(cp));   cp.csr = p->instructions;   /* Compile instructions:    */   for (i = 0; i < program->Base.NumInstructions; i++) {      cvp_emit_inst(&cp, &program->Base.Instructions[i]);   }   /* Finish up:    */   p->nr_instructions = cp.csr - p->instructions;   /* Print/disassemble:    */   if (DISASSEM) {      for (i = 0; i < p->nr_instructions; i++) {	 _tnl_disassem_vba_insn(p->instructions[i]);      }      _mesa_printf("\n\n");   }   #ifdef USE_SSE_ASM   if (try_codegen)      _tnl_sse_codegen_vertex_program(p);#endif}/* ---------------------------------------------------------------------- * Execution */static void userclip( GLcontext *ctx,		      GLvector4f *clip,		      GLubyte *clipmask,		      GLubyte *clipormask,		      GLubyte *clipandmask ){   GLuint p;   for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {      if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {	 GLuint nr, i;	 const GLfloat a = ctx->Transform._ClipUserPlane[p][0];	 const GLfloat b = ctx->Transform._ClipUserPlane[p][1];	 const GLfloat c = ctx->Transform._ClipUserPlane[p][2];	 const GLfloat d = ctx->Transform._ClipUserPlane[p][3];         GLfloat *coord = (GLfloat *)clip->data;         GLuint stride = clip->stride;         GLuint count = clip->count;	 for (nr = 0, i = 0 ; i < count ; i++) {	    GLfloat dp = (coord[0] * a + 			  coord[1] * b +			  coord[2] * c +			  coord[3] * d);	    if (dp < 0) {	       nr++;	       clipmask[i] |= CLIP_USER_BIT;	    }	    STRIDE_F(coord, stride);	 }	 if (nr > 0) {	    *clipormask |= CLIP_USER_BIT;	    if (nr == count) {	       *clipandmask |= CLIP_USER_BIT;	       return;	    }	 }      }   }}static GLbooleando_ndc_cliptest(GLcontext *ctx, struct arb_vp_machine *m){   TNLcontext *tnl = TNL_CONTEXT(ctx);   struct vertex_buffer *VB = m->VB;   /* Cliptest and perspective divide.  Clip functions must clear    * the clipmask.    */   m->ormask = 0;   m->andmask = CLIP_ALL_BITS;   if (tnl->NeedNdcCoords) {      VB->NdcPtr =         _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,                                            &m->ndcCoords,                                            m->clipmask,                                            &m->ormask,                                            &m->andmask );   }   else {      VB->NdcPtr = NULL;      _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,                                            NULL,                                            m->clipmask,                                            &m->ormask,                                            &m->andmask );   }   if (m->andmask) {      /* All vertices are outside the frustum */      return GL_FALSE;   }   /* Test userclip planes.  This contributes to VB->ClipMask.    */   if (ctx->Transform.ClipPlanesEnabled && !ctx->VertexProgram._Enabled) {      userclip( ctx,		VB->ClipPtr,		m->clipmask,		&m->ormask,		&m->andmask );      if (m->andmask) {	 return GL_FALSE;      }   }   VB->ClipAndMask = m->andmask;   VB->ClipOrMask = m->ormask;   VB->ClipMask = m->clipmask;   return GL_TRUE;}static INLINE void call_func( struct tnl_compiled_program *p,			      struct arb_vp_machine *m ){   p->compiled_func(m);}/** * Execute the given vertex program.   *  * TODO: Integrate the t_vertex.c code here, to build machine vertices * directly at this point. * * TODO: Eliminate the VB struct entirely and just use * struct arb_vertex_machine. */static GLbooleanrun_arb_vertex_program(GLcontext *ctx, struct tnl_pipeline_stage *stage){   struct vertex_program *program;   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;   struct arb_vp_machine *m = ARB_VP_MACHINE(stage);   struct tnl_compiled_program *p;   GLuint i, j;   GLbitfield outputs;   if (ctx->ShaderObjects._VertexShaderPresent)      return GL_TRUE;   program = (ctx->VertexProgram._Enabled ? ctx->VertexProgram.Current : ctx->_TnlProgram);   if (!program || program->IsNVProgram)      return GL_TRUE;      if (program->Base.Parameters) {      _mesa_load_state_parameters(ctx, program->Base.Parameters);   }         p = (struct tnl_compiled_program *)program->TnlData;   assert(p);   m->nr_inputs = m->nr_outputs = 0;   for (i = 0; i < _TNL_ATTRIB_MAX; i++) {      if (program->Base.InputsRead & (1<<i) ||	  (i == VERT_ATTRIB_POS && program->IsPositionInvariant)) {	 GLuint j = m->nr_inputs++;	 m->input[j].idx = i;	 m->input[j].data = (GLfloat *)m->VB->AttribPtr[i]->data;	 m->input[j].stride = m->VB->AttribPtr[i]->stride;	 m->input[j].size = m->VB->AttribPtr[i]->size;	 ASSIGN_4V(m->File[0][REG_IN0 + i], 0, 0, 0, 1);      }   }        for (i = 0; i < VERT_RESULT_MAX; i++) {      if (program->Base.OutputsWritten & (1 << i) ||	  (i == VERT_RESULT_HPOS && program->IsPositionInvariant)) {	 GLuint j = m->nr_outputs++;	 m->output[j].idx = i;	 m->output[j].data = (GLfloat *)m->attribs[i].data;      }   }        /* Run the actual program:    */   for (m->vtx_nr = 0; m->vtx_nr < VB->Count; m->vtx_nr++) {      for (j = 0; j < m->nr_inputs; j++) {	 GLuint idx = REG_IN0 + m->input[j].idx;	 switch (m->input[j].size) {	 case 4: m->File[0][idx][3] = m->input[j].data[3];	 case 3: m->File[0][idx][2] = m->input[j].data[2];	 case 2: m->File[0][idx][1] = m->input[j].data[1];	 case 1: m->File[0][idx][0] = m->input[j].data[0];	 }	 STRIDE_F(m->input[j].data, m->input[j].stride);      }      if (p->compiled_func) {	 call_func( p, m );      }      else {	 for (j = 0; j < p->nr_instructions; j++) {	    union instruction inst = p->instructions[j];	 	    opcode_func[inst.alu.opcode]( m, inst );	 }      }      /* If the program is position invariant, multiply the input position       * by the MVP matrix and store in the vertex position result register.       */      if (program->IsPositionInvariant) {	 TRANSFORM_POINT( m->File[0][REG_OUT0+0], 			  ctx->_ModelProjectMatrix.m, 			  m->File[0][REG_IN0+0]);      }      for (j = 0; j < m->nr_outputs; j++) {	 GLuint idx = REG_OUT0 + m->output[j].idx;	 m->output[j].data[0] = m->File[0][idx][0];	 m->output[j].data[1] = m->File[0][idx][1];	 m->output[j].data[2] = m->File[0][idx][2];	 m->output[j].data[3] = m->File[0][idx][3];	 m->output[j].data += 4;      }   }   /* Setup the VB pointers so that the next pipeline stages get    * their data from the right place (the program output arrays).    *    * TODO: 1) Have tnl use these RESULT values for outputs rather    * than trying to shoe-horn inputs and outputs into one set of    * values.    *    * TODO: 2) Integrate t_vertex.c so that we just go straight ahead    * and build machine vertices here.    */   VB->ClipPtr = &m->attribs[VERT_RESULT_HPOS];   VB->ClipPtr->count = VB->Count;   outputs = program->Base.OutputsWritten;   if (program->IsPositionInvariant)       outputs |= (1<<VERT_RESULT_HPOS);   if (outputs & (1<<VERT_RESULT_COL0)) {      VB->ColorPtr[0] = &m->attribs[VERT_RESULT_COL0];      VB->AttribPtr[VERT_ATTRIB_COLOR0] = VB->ColorPtr[0];   }   if (outputs & (1<<VERT_RESULT_BFC0)) {      VB->ColorPtr[1] = &m->attribs[VERT_RESULT_BFC0];   }   if (outputs & (1<<VERT_RESULT_COL1)) {      VB->SecondaryColorPtr[0] = &m->attribs[VERT_RESULT_COL1];      VB->AttribPtr[VERT_ATTRIB_COLOR1] = VB->SecondaryColorPtr[0];   }   if (outputs & (1<<VERT_RESULT_BFC1)) {      VB->SecondaryColorPtr[1] = &m->attribs[VERT_RESULT_BFC1];   }   if (outputs & (1<<VERT_RESULT_FOGC)) {      VB->FogCoordPtr = &m->attribs[VERT_RESULT_FOGC];      VB->AttribPtr[VERT_ATTRIB_FOG] = VB->FogCoordPtr;   }   if (outputs & (1<<VERT_RESULT_PSIZ)) {      VB->PointSizePtr = &m->attribs[VERT_RESULT_PSIZ];      VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &m->attribs[VERT_RESULT_PSIZ];   }   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {      if (outputs & (1<<(VERT_RESULT_TEX0+i))) {	 VB->TexCoordPtr[i] = &m->attribs[VERT_RESULT_TEX0 + i];	 VB->AttribPtr[VERT_ATTRIB_TEX0+i] = VB->TexCoordPtr[i];      }   }#if 0   for (i = 0; i < VB->Count; i++) {      printf("Out %d: %f %f %f %f %f %f %f %f\n", i,	     VEC_ELT(VB->ClipPtr, GLfloat, i)[0],	     VEC_ELT(VB->ClipPtr, GLfloat, i)[1],	     VEC_ELT(VB->ClipPtr, GLfloat, i)[2],	     VEC_ELT(VB->ClipPtr, GLfloat, i)[3],	     VEC_ELT(VB->TexCoordPtr[0], GLfloat, i)[0],	     VEC_ELT(VB->TexCoordPtr[0], GLfloat, i)[1],	     VEC_ELT(VB->TexCoordPtr[0], GLfloat, i)[2],	     VEC_ELT(VB->TexCoordPtr[0], GLfloat, i)[3]);   }#endif   /* Perform NDC and cliptest operations:    */   return do_ndc_cliptest(ctx, m);}static voidvalidate_vertex_program( GLcontext *ctx, struct tnl_pipeline_stage *stage ){   struct arb_vp_machine *m = ARB_VP_MACHINE(stage);   struct vertex_program *program;   if (ctx->ShaderObjects._VertexShaderPresent)      return;   program = (ctx->VertexProgram._Enabled ? ctx->VertexProgram.Current : 0);   if (!program && ctx->_MaintainTnlProgram) {      program = ctx->_TnlProgram;   }   if (program) {      if (!program->TnlData)	 compile_vertex_program( program, m->try_codegen );            /* Grab the state GL state and put into registers:       */      m->File[FILE_LOCAL_PARAM] = program->Base.LocalParams;      m->File[FILE_ENV_PARAM] = ctx->VertexProgram.Parameters;      /* GL_NV_vertex_programs can't reference GL state */      if (program->Base.Parameters)         m->File[FILE_STATE_PARAM] = program->Base.Parameters->ParameterValues;      else         m->File[FILE_STATE_PARAM] = NULL;   }}/** * Called the first time stage->run is called.  In effect, don't * allocate data until the first time the stage is run. */static GLboolean init_vertex_program( GLcontext *ctx,				      struct tnl_pipeline_stage *stage ){   TNLcontext *tnl = TNL_CONTEXT(ctx);   struct vertex_buffer *VB = &(tnl->vb);   struct arb_vp_machine *m;   const GLuint size = VB->Size;   GLuint i;   stage->privatePtr = _mesa_calloc(sizeof(*m));   m = ARB_VP_MACHINE(stage);   if (!m)      return GL_FALSE;   /* arb_vertex_machine struct should subsume the VB:    */   m->VB = VB;   m->File[0] = (GLfloat(*)[4])ALIGN_MALLOC(REG_MAX * sizeof(GLfloat) * 4, 16);   /* Initialize regs where necessary:    */   ASSIGN_4V(m->File[0][REG_ID], 0, 0, 0, 1);   ASSIGN_4V(m->File[0][REG_ONES], 1, 1, 1, 1);   ASSIGN_4V(m->File[0][REG_SWZ], -1, 1, 0, 0);   ASSIGN_4V(m->File[0][REG_NEG], -1, -1, -1, -1);   ASSIGN_4V(m->File[0][REG_LIT], 1, 0, 0, 1);   ASSIGN_4V(m->File[0][REG_LIT2], 1, .5, .2, 1); /* debug value */   if (_mesa_getenv("MESA_EXPERIMENTAL"))      m->try_codegen = GL_TRUE;   /* Allocate arrays of vertex output values */   for (i = 0; i < VERT_RESULT_MAX; i++) {      _mesa_vector4f_alloc( &m->attribs[i], 0, size, 32 );      m->attribs[i].size = 4;   }   /* a few other misc allocations */   _mesa_vector4f_alloc( &m->ndcCoords, 0, size, 32 );   m->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );   if (ctx->_MaintainTnlProgram)      _mesa_allow_light_in_model( ctx, GL_FALSE );   m->fpucntl_rnd_neg = RND_NEG_FPU; /* const value */   m->fpucntl_restore = RESTORE_FPU; /* const value */   return GL_TRUE;}/** * Destructor for this pipeline stage. */static void dtr( struct tnl_pipeline_stage *stage ){   struct arb_vp_machine *m = ARB_VP_MACHINE(stage);   if (m) {      GLuint i;      /* free the vertex program result arrays */      for (i = 0; i < VERT_RESULT_MAX; i++)         _mesa_vector4f_free( &m->attribs[i] );      /* free misc arrays */      _mesa_vector4f_free( &m->ndcCoords );      ALIGN_FREE( m->clipmask );      ALIGN_FREE( m->File[0] );      _mesa_free( m );      stage->privatePtr = NULL;   }}/** * Public description of this pipeline stage. */const struct tnl_pipeline_stage _tnl_arb_vertex_program_stage ={   "vertex-program",   NULL,			/* private_data */   init_vertex_program,		/* create */   dtr,				/* destroy */   validate_vertex_program,	/* validate */   run_arb_vertex_program	/* run */};/** * Called via ctx->Driver.ProgramStringNotify() after a new vertex program * string has been parsed. */void_tnl_program_string(GLcontext *ctx, GLenum target, struct program *program){   if (program->Target == GL_VERTEX_PROGRAM_ARB) {      /* free any existing tnl data hanging off the program */      struct vertex_program *vprog = (struct vertex_program *) program;      if (vprog->TnlData) {         free_tnl_data(vprog);      }   }}

⌨️ 快捷键说明

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