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 + -
显示快捷键?