6 #include "r300_context.h"
7 #include "nvvertprog.h"
9 #define SCALAR_FLAG (1<<31)
10 #define FLAG_MASK (1<<31)
11 #define OPN(operator, ip, op) {#operator, VP_OPCODE_##operator, ip, op}
13 #warning "This is just a hack to get everything to compile"
14 struct ati_fragment_shader {};
19 unsigned long ip; /* number of input operands and flags */
24 OPN(ARL, 1, 1|SCALAR_FLAG),
25 OPN(DP3, 2, 3|SCALAR_FLAG),
26 OPN(DP4, 2, 3|SCALAR_FLAG),
27 OPN(DPH, 2, 3|SCALAR_FLAG),
29 OPN(EX2, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
30 OPN(EXP, 1|SCALAR_FLAG, 1),
33 OPN(LG2, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
35 OPN(LOG, 1|SCALAR_FLAG, 1),
41 OPN(POW, 2|SCALAR_FLAG, 4|SCALAR_FLAG),
42 OPN(RCP, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
43 OPN(RSQ, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
49 OPN(RCC, 0, 0), //extra
54 #define OPN(rf) {#rf, PROGRAM_##rf}
59 }register_file_names[]={
71 char *dst_mask_names[4]={ "X", "Y", "Z", "W" };
73 /* from vertex program spec:
74 Instruction Inputs Output Description
75 ----------- ------ ------ --------------------------------
76 ABS v v absolute value
78 ARL v a address register load
79 DP3 v,v ssss 3-component dot product
80 DP4 v,v ssss 4-component dot product
81 DPH v,v ssss homogeneous dot product
82 DST v,v v distance vector
83 EX2 s ssss exponential base 2
84 EXP s v exponential base 2 (approximate)
87 LG2 s ssss logarithm base 2
88 LIT v v compute light coefficients
89 LOG s v logarithm base 2 (approximate)
90 MAD v,v,v v multiply and add
95 POW s,s ssss exponentiate
97 RSQ s ssss reciprocal square root
98 SGE v,v v set on greater than or equal
99 SLT v,v v set on less than
101 SWZ v v extended swizzle
102 XPD v,v v cross product
105 void dump_program_params(struct vertex_program *vp)
110 fprintf(stderr, "NumInstructions=%d\n", vp->Base.NumInstructions);
111 fprintf(stderr, "NumTemporaries=%d\n", vp->Base.NumTemporaries);
112 fprintf(stderr, "NumParameters=%d\n", vp->Base.NumParameters);
113 fprintf(stderr, "NumAttributes=%d\n", vp->Base.NumAttributes);
114 fprintf(stderr, "NumAddressRegs=%d\n", vp->Base.NumAddressRegs);
117 for(pi=0; pi < vp->Base.NumParameters; pi++){
118 fprintf(stderr, "{ ");
120 fprintf(stderr, "%f ", vp->Base.LocalParams[pi][i]);
121 fprintf(stderr, "}\n");
124 for(pi=0; pi < vp->Parameters->NumParameters; pi++){
125 fprintf(stderr, "param %02d:", pi);
127 switch(vp->Parameters->Parameters[pi].Type){
129 case NAMED_PARAMETER:
130 fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
131 fprintf(stderr, "(NAMED_PARAMETER)");
135 fprintf(stderr, "(CONSTANT)");
139 fprintf(stderr, "(STATE)\n");
140 /* fetch state info */
146 fprintf(stderr, "{ ");
148 fprintf(stderr, "%f ", vp->Parameters->Parameters[pi].Values[i]);
149 fprintf(stderr, "}\n");
154 static void debug_vp(struct vertex_program *vp)
156 struct vp_instruction *vpi;
157 int i, operand_index;
160 dump_program_params(vp);
162 vpi=vp->Instructions;
165 if(vpi->Opcode == VP_OPCODE_END)
168 for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++){
169 if(vpi->Opcode == op_names[i].opcode){
170 fprintf(stderr, "%s ", op_names[i].name);
176 for(i=0; i < sizeof(register_file_names) / sizeof(*register_file_names); i++){
177 if(vpi->DstReg.File == register_file_names[i].id){
178 fprintf(stderr, "%s ", register_file_names[i].name);
183 fprintf(stderr, "%d.", vpi->DstReg.Index);
186 if(vpi->DstReg.WriteMask[i])
187 fprintf(stderr, "%s", dst_mask_names[i]);
188 fprintf(stderr, " ");
190 for(operand_index=0; operand_index < (op_names[operator_index].ip & (~FLAG_MASK));
193 if(vpi->SrcReg[operand_index].Negate)
194 fprintf(stderr, "-");
196 for(i=0; i < sizeof(register_file_names) / sizeof(*register_file_names); i++){
197 if(vpi->SrcReg[operand_index].File == register_file_names[i].id){
198 fprintf(stderr, "%s ", register_file_names[i].name);
202 fprintf(stderr, "%d.", vpi->SrcReg[operand_index].Index);
205 fprintf(stderr, "%s", dst_mask_names[vpi->SrcReg[operand_index].Swizzle[i]]);
207 if(operand_index+1 < (op_names[operator_index].ip & (~FLAG_MASK)) )
208 fprintf(stderr, ",");
210 fprintf(stderr, "\n");
215 void update_params(struct r300_vertex_program *vp)
218 struct vertex_program *mesa_vp=(void *)vp;
222 /* Temporary solution */
224 for(pi=0; pi < mesa_vp->Parameters->NumParameters; pi++){
225 switch(mesa_vp->Parameters->Parameters[pi].Type){
227 case NAMED_PARAMETER:
228 //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
230 vp->params.body.f[pi*4+0]=mesa_vp->Parameters->Parameters[pi].Values[0];
231 vp->params.body.f[pi*4+1]=mesa_vp->Parameters->Parameters[pi].Values[1];
232 vp->params.body.f[pi*4+2]=mesa_vp->Parameters->Parameters[pi].Values[2];
233 vp->params.body.f[pi*4+3]=mesa_vp->Parameters->Parameters[pi].Values[3];
234 vp->params.length+=4;
238 fprintf(stderr, "State found! bailing out.\n");
240 /* fetch state info */
243 default: _mesa_problem(NULL, "Bad param type in %s", __FUNCTION__);
250 unsigned long translate_dst_mask(GLboolean *mask)
252 unsigned long flags=0;
254 if(mask[0]) flags |= VSF_FLAG_X;
255 if(mask[1]) flags |= VSF_FLAG_Y;
256 if(mask[2]) flags |= VSF_FLAG_Z;
257 if(mask[3]) flags |= VSF_FLAG_W;
262 unsigned long translate_dst_class(enum register_file file)
266 case PROGRAM_TEMPORARY:
267 return R300_VPI_OUT_REG_CLASS_TEMPORARY;
269 return R300_VPI_OUT_REG_CLASS_RESULT;
272 case PROGRAM_LOCAL_PARAM:
273 case PROGRAM_ENV_PARAM:
274 case PROGRAM_NAMED_PARAM:
275 case PROGRAM_STATE_VAR:
276 case PROGRAM_WRITE_ONLY:
277 case PROGRAM_ADDRESS:
280 fprintf(stderr, "problem in %s", __FUNCTION__);
285 unsigned long translate_src_class(enum register_file file)
289 case PROGRAM_TEMPORARY:
290 return R300_VPI_IN_REG_CLASS_TEMPORARY;
294 case PROGRAM_LOCAL_PARAM:
295 case PROGRAM_ENV_PARAM:
296 case PROGRAM_NAMED_PARAM:
297 case PROGRAM_STATE_VAR:
298 return R300_VPI_IN_REG_CLASS_PARAMETER;
301 case PROGRAM_WRITE_ONLY:
302 case PROGRAM_ADDRESS:
305 fprintf(stderr, "problem in %s", __FUNCTION__);
310 unsigned long translate_swizzle(GLubyte swizzle)
313 case 0: return VSF_IN_COMPONENT_X;
314 case 1: return VSF_IN_COMPONENT_Y;
315 case 2: return VSF_IN_COMPONENT_Z;
316 case 3: return VSF_IN_COMPONENT_W;
321 fprintf(stderr, "problem in %s", __FUNCTION__);
326 unsigned long translate_src(struct vp_src_register *src)
328 return MAKE_VSF_SOURCE(src->Index,
329 translate_swizzle(src->Swizzle[0]),
330 translate_swizzle(src->Swizzle[1]),
331 translate_swizzle(src->Swizzle[2]),
332 translate_swizzle(src->Swizzle[3]),
333 translate_src_class(src->File),
334 src->Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE);
337 unsigned long translate_opcode(enum vp_opcode opcode)
341 case VP_OPCODE_ADD: return R300_VPI_OUT_OP_ADD;
342 case VP_OPCODE_DST: return R300_VPI_OUT_OP_DST;
343 case VP_OPCODE_EX2: return R300_VPI_OUT_OP_EX2;
344 case VP_OPCODE_EXP: return R300_VPI_OUT_OP_EXP;
345 case VP_OPCODE_FRC: return R300_VPI_OUT_OP_FRC;
346 case VP_OPCODE_LG2: return R300_VPI_OUT_OP_LG2;
347 case VP_OPCODE_LIT: return R300_VPI_OUT_OP_LIT;
348 case VP_OPCODE_LOG: return R300_VPI_OUT_OP_LOG;
349 case VP_OPCODE_MAD: return R300_VPI_OUT_OP_MAD;
350 case VP_OPCODE_MAX: return R300_VPI_OUT_OP_MAX;
351 case VP_OPCODE_MIN: return R300_VPI_OUT_OP_MIN;
352 case VP_OPCODE_MUL: return R300_VPI_OUT_OP_MUL;
353 case VP_OPCODE_POW: return R300_VPI_OUT_OP_POW;
354 case VP_OPCODE_RCP: return R300_VPI_OUT_OP_RCP;
355 case VP_OPCODE_RSQ: return R300_VPI_OUT_OP_RSQ;
356 case VP_OPCODE_SGE: return R300_VPI_OUT_OP_SGE;
357 case VP_OPCODE_SLT: return R300_VPI_OUT_OP_SLT;
358 /* these ops need special handling */
370 case VP_OPCODE_PRINT:
372 fprintf(stderr, "%s should not be called with opcode %d", __FUNCTION__, opcode);
375 fprintf(stderr, "%s unknown opcode %d", __FUNCTION__, opcode);
381 static void translate_program(struct r300_vertex_program *vp)
383 struct vertex_program *mesa_vp=(void *)vp;
384 struct vp_instruction *vpi;
386 int operand_index, i;
390 vp->program.length=0;
392 for(vpi=mesa_vp->Instructions; vpi->Opcode != VP_OPCODE_END; vpi++, inst_index++){
406 case VP_OPCODE_PRINT:
407 fprintf(stderr, "Dont know how to handle op %d yet\n", vpi->Opcode);
415 vp->program.body.i[inst_index].op=MAKE_VSF_OP(translate_opcode(vpi->Opcode), vpi->DstReg.Index,
416 translate_dst_mask(vpi->DstReg.WriteMask), translate_dst_class(vpi->DstReg.File));
419 for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++)
420 if(op_names[i].opcode == vpi->Opcode){
425 fprintf(stderr, "op %d not found in op_names\n", vpi->Opcode);
429 switch(op_names[i].ip){
431 vp->program.body.i[inst_index].src1=translate_src(&vpi->SrcReg[0]);
432 vp->program.body.i[inst_index].src2=0;
433 vp->program.body.i[inst_index].src3=0;
437 vp->program.body.i[inst_index].src1=translate_src(&vpi->SrcReg[0]);
438 vp->program.body.i[inst_index].src2=translate_src(&vpi->SrcReg[1]);
439 vp->program.body.i[inst_index].src3=0;
443 vp->program.body.i[inst_index].src1=translate_src(&vpi->SrcReg[0]);
444 vp->program.body.i[inst_index].src2=translate_src(&vpi->SrcReg[1]);
445 vp->program.body.i[inst_index].src3=translate_src(&vpi->SrcReg[2]);
449 fprintf(stderr, "scalars and op RCC not handled yet");
454 vp->program.length=inst_index*4;
458 static void r300BindProgram(GLcontext *ctx, GLenum target, struct program *prog)
460 fprintf(stderr, "r300BindProgram\n");
463 /* Mesa doesnt seem to have prototype for this */
465 _mesa_init_ati_fragment_shader( GLcontext *ctx, struct ati_fragment_shader *prog,
466 GLenum target, GLuint id);
468 static struct program *r300NewProgram(GLcontext *ctx, GLenum target, GLuint id)
470 r300ContextPtr rmesa = R300_CONTEXT(ctx);
471 struct r300_vertex_program *vp;
472 struct fragment_program *fp;
473 struct ati_fragment_shader *afs;
475 fprintf(stderr, "r300NewProgram, target=%d, id=%d\n", target, id);
478 case GL_VERTEX_PROGRAM_ARB:
479 fprintf(stderr, "vertex prog\n");
480 vp=CALLOC_STRUCT(r300_vertex_program);
482 /* note that vp points to mesa_program since its first on the struct
484 return _mesa_init_vertex_program(ctx, &vp->mesa_program, target, id);
486 case GL_FRAGMENT_PROGRAM_ARB:
487 fprintf(stderr, "fragment prog\n");
488 fp=CALLOC_STRUCT(fragment_program);
489 return _mesa_init_fragment_program(ctx, fp, target, id);
491 case GL_FRAGMENT_PROGRAM_NV:
492 fprintf(stderr, "nv fragment prog\n");
493 fp=CALLOC_STRUCT(fragment_program);
494 return _mesa_init_fragment_program(ctx, fp, target, id);
496 case GL_FRAGMENT_SHADER_ATI:
497 fprintf(stderr, "ati fragment prog\n");
498 afs=CALLOC_STRUCT(ati_fragment_shader);
499 return _mesa_init_ati_fragment_shader(ctx, afs, target, id);
506 static void r300DeleteProgram(GLcontext *ctx, struct program *prog)
508 fprintf(stderr, "r300DeleteProgram\n");
510 /* check that not active */
511 _mesa_delete_program(ctx, prog);
514 static GLboolean r300IsProgramNative(GLcontext *ctx, GLenum target,
515 struct program *prog);
517 static void r300ProgramStringNotify(GLcontext *ctx, GLenum target,
518 struct program *prog)
520 struct r300_vertex_program *vp=(void *)prog;
522 fprintf(stderr, "r300ProgramStringNotify\n");
523 /* XXX: There is still something wrong as mesa doesnt call r300IsProgramNative at all */
524 (void)r300IsProgramNative(ctx, target, prog);
527 case GL_VERTEX_PROGRAM_ARB:
528 vp->translated=GL_FALSE;
534 static GLboolean r300IsProgramNative(GLcontext *ctx, GLenum target,
535 struct program *prog)
538 fprintf(stderr, "r300IsProgramNative\n");
540 debug_vp((struct vertex_program *)prog);
545 /* This is misnamed and shouldnt be here since fragment programs use these functions too */
546 void r300InitVertexProgFuncs(struct dd_function_table *functions)
549 functions->NewProgram=r300NewProgram;
550 functions->BindProgram=r300BindProgram;
551 functions->DeleteProgram=r300DeleteProgram;
552 functions->ProgramStringNotify=r300ProgramStringNotify;
553 functions->IsProgramNative=r300IsProgramNative;