Support for idx buffers. Leaving it on by default as it doesnt seem to cause any...
[mesa.git] / src / mesa / drivers / dri / r300 / r300_vertexprog.c
1 /**************************************************************************
2
3 Copyright (C) 2005 Aapo Tahkola.
4
5 All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
16 Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Aapo Tahkola <aet@rasterburn.org>
31 */
32 #include "glheader.h"
33 #include "macros.h"
34 #include "enums.h"
35
36 #include "program.h"
37 #include "r300_context.h"
38 #include "nvvertprog.h"
39
40 #define SCALAR_FLAG (1<<31)
41 #define FLAG_MASK (1<<31)
42 #define OP_MASK (0xf) /* we are unlikely to have more than 15 */
43 #define OPN(operator, ip, op) {#operator, VP_OPCODE_##operator, ip, op}
44
45 struct{
46 char *name;
47 int opcode;
48 unsigned long ip; /* number of input operands and flags */
49 unsigned long op;
50 }op_names[]={
51 OPN(ABS, 1, 1),
52 OPN(ADD, 2, 1),
53 OPN(ARL, 1, 1|SCALAR_FLAG),
54 OPN(DP3, 2, 3|SCALAR_FLAG),
55 OPN(DP4, 2, 3|SCALAR_FLAG),
56 OPN(DPH, 2, 3|SCALAR_FLAG),
57 OPN(DST, 2, 1),
58 OPN(EX2, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
59 OPN(EXP, 1|SCALAR_FLAG, 1),
60 OPN(FLR, 1, 1),
61 OPN(FRC, 1, 1),
62 OPN(LG2, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
63 OPN(LIT, 1, 1),
64 OPN(LOG, 1|SCALAR_FLAG, 1),
65 OPN(MAD, 3, 1),
66 OPN(MAX, 2, 1),
67 OPN(MIN, 2, 1),
68 OPN(MOV, 1, 1),
69 OPN(MUL, 2, 1),
70 OPN(POW, 2|SCALAR_FLAG, 4|SCALAR_FLAG),
71 OPN(RCP, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
72 OPN(RSQ, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
73 OPN(SGE, 2, 1),
74 OPN(SLT, 2, 1),
75 OPN(SUB, 2, 1),
76 OPN(SWZ, 1, 1),
77 OPN(XPD, 2, 1),
78 OPN(RCC, 0, 0), //extra
79 OPN(PRINT, 0, 0),
80 OPN(END, 0, 0),
81 };
82 #undef OPN
83 #define OPN(rf) {#rf, PROGRAM_##rf}
84
85 struct{
86 char *name;
87 int id;
88 }register_file_names[]={
89 OPN(TEMPORARY),
90 OPN(INPUT),
91 OPN(OUTPUT),
92 OPN(LOCAL_PARAM),
93 OPN(ENV_PARAM),
94 OPN(NAMED_PARAM),
95 OPN(STATE_VAR),
96 OPN(WRITE_ONLY),
97 OPN(ADDRESS),
98 };
99
100 char *dst_mask_names[4]={ "X", "Y", "Z", "W" };
101
102 /* from vertex program spec:
103 Instruction Inputs Output Description
104 ----------- ------ ------ --------------------------------
105 ABS v v absolute value
106 ADD v,v v add
107 ARL v a address register load
108 DP3 v,v ssss 3-component dot product
109 DP4 v,v ssss 4-component dot product
110 DPH v,v ssss homogeneous dot product
111 DST v,v v distance vector
112 EX2 s ssss exponential base 2
113 EXP s v exponential base 2 (approximate)
114 FLR v v floor
115 FRC v v fraction
116 LG2 s ssss logarithm base 2
117 LIT v v compute light coefficients
118 LOG s v logarithm base 2 (approximate)
119 MAD v,v,v v multiply and add
120 MAX v,v v maximum
121 MIN v,v v minimum
122 MOV v v move
123 MUL v,v v multiply
124 POW s,s ssss exponentiate
125 RCP s ssss reciprocal
126 RSQ s ssss reciprocal square root
127 SGE v,v v set on greater than or equal
128 SLT v,v v set on less than
129 SUB v,v v subtract
130 SWZ v v extended swizzle
131 XPD v,v v cross product
132 */
133
134 void dump_program_params(GLcontext *ctx, struct vertex_program *vp)
135 {
136 int i;
137 int pi;
138
139 fprintf(stderr, "NumInstructions=%d\n", vp->Base.NumInstructions);
140 fprintf(stderr, "NumTemporaries=%d\n", vp->Base.NumTemporaries);
141 fprintf(stderr, "NumParameters=%d\n", vp->Base.NumParameters);
142 fprintf(stderr, "NumAttributes=%d\n", vp->Base.NumAttributes);
143 fprintf(stderr, "NumAddressRegs=%d\n", vp->Base.NumAddressRegs);
144
145 _mesa_load_state_parameters(ctx, vp->Parameters);
146
147 #if 0
148 for(pi=0; pi < vp->Base.NumParameters; pi++){
149 fprintf(stderr, "{ ");
150 for(i=0; i < 4; i++)
151 fprintf(stderr, "%f ", vp->Base.LocalParams[pi][i]);
152 fprintf(stderr, "}\n");
153 }
154 #endif
155 for(pi=0; pi < vp->Parameters->NumParameters; pi++){
156 fprintf(stderr, "param %02d:", pi);
157
158 switch(vp->Parameters->Parameters[pi].Type){
159
160 case NAMED_PARAMETER:
161 fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
162 fprintf(stderr, "(NAMED_PARAMETER)");
163 break;
164
165 case CONSTANT:
166 fprintf(stderr, "(CONSTANT)");
167 break;
168
169 case STATE:
170 fprintf(stderr, "(STATE)\n");
171 break;
172
173 }
174
175 fprintf(stderr, "{ ");
176 for(i=0; i < 4; i++)
177 fprintf(stderr, "%f ", vp->Parameters->Parameters[pi].Values[i]);
178 fprintf(stderr, "}\n");
179
180 }
181 }
182
183 static void debug_vp(GLcontext *ctx, struct vertex_program *vp)
184 {
185 struct vp_instruction *vpi;
186 int i, operand_index;
187 int operator_index;
188
189 dump_program_params(ctx, vp);
190
191 vpi=vp->Instructions;
192
193 for(;; vpi++){
194 if(vpi->Opcode == VP_OPCODE_END)
195 break;
196
197 for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++){
198 if(vpi->Opcode == op_names[i].opcode){
199 fprintf(stderr, "%s ", op_names[i].name);
200 break;
201 }
202 }
203 operator_index=i;
204
205 for(i=0; i < sizeof(register_file_names) / sizeof(*register_file_names); i++){
206 if(vpi->DstReg.File == register_file_names[i].id){
207 fprintf(stderr, "%s ", register_file_names[i].name);
208 break;
209 }
210 }
211
212 fprintf(stderr, "%d.", vpi->DstReg.Index);
213
214 for(i=0; i < 4; i++)
215 if(vpi->DstReg.WriteMask[i])
216 fprintf(stderr, "%s", dst_mask_names[i]);
217 fprintf(stderr, " ");
218
219 for(operand_index=0; operand_index < (op_names[operator_index].ip & (~FLAG_MASK));
220 operand_index++){
221
222 if(vpi->SrcReg[operand_index].Negate)
223 fprintf(stderr, "-");
224
225 for(i=0; i < sizeof(register_file_names) / sizeof(*register_file_names); i++){
226 if(vpi->SrcReg[operand_index].File == register_file_names[i].id){
227 fprintf(stderr, "%s ", register_file_names[i].name);
228 break;
229 }
230 }
231 fprintf(stderr, "%d.", vpi->SrcReg[operand_index].Index);
232
233 for(i=0; i < 4; i++)
234 fprintf(stderr, "%s", dst_mask_names[vpi->SrcReg[operand_index].Swizzle[i]]);
235
236 if(operand_index+1 < (op_names[operator_index].ip & (~FLAG_MASK)) )
237 fprintf(stderr, ",");
238 }
239 fprintf(stderr, "\n");
240 }
241
242 }
243
244 void r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program *vp)
245 {
246 int pi;
247 struct vertex_program *mesa_vp=(void *)vp;
248 int dst_index;
249
250 _mesa_load_state_parameters(ctx, mesa_vp->Parameters);
251
252 //debug_vp(ctx, mesa_vp);
253
254 dst_index=0;
255 for(pi=0; pi < mesa_vp->Parameters->NumParameters; pi++){
256 switch(mesa_vp->Parameters->Parameters[pi].Type){
257
258 case STATE:
259 case NAMED_PARAMETER:
260 //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
261 case CONSTANT:
262 vp->params.body.f[dst_index++]=mesa_vp->Parameters->Parameters[pi].Values[0];
263 vp->params.body.f[dst_index++]=mesa_vp->Parameters->Parameters[pi].Values[1];
264 vp->params.body.f[dst_index++]=mesa_vp->Parameters->Parameters[pi].Values[2];
265 vp->params.body.f[dst_index++]=mesa_vp->Parameters->Parameters[pi].Values[3];
266 break;
267
268 default: _mesa_problem(NULL, "Bad param type in %s", __FUNCTION__);
269 }
270
271 }
272
273 vp->params.length=dst_index;
274 }
275
276 static unsigned long t_dst_mask(GLboolean *mask)
277 {
278 unsigned long flags=0;
279
280 if(mask[0]) flags |= VSF_FLAG_X;
281 if(mask[1]) flags |= VSF_FLAG_Y;
282 if(mask[2]) flags |= VSF_FLAG_Z;
283 if(mask[3]) flags |= VSF_FLAG_W;
284
285 return flags;
286 }
287
288 static unsigned long t_dst_class(enum register_file file)
289 {
290
291 switch(file){
292 case PROGRAM_TEMPORARY:
293 return VSF_OUT_CLASS_TMP;
294 case PROGRAM_OUTPUT:
295 return VSF_OUT_CLASS_RESULT;
296 /*
297 case PROGRAM_INPUT:
298 case PROGRAM_LOCAL_PARAM:
299 case PROGRAM_ENV_PARAM:
300 case PROGRAM_NAMED_PARAM:
301 case PROGRAM_STATE_VAR:
302 case PROGRAM_WRITE_ONLY:
303 case PROGRAM_ADDRESS:
304 */
305 default:
306 fprintf(stderr, "problem in %s", __FUNCTION__);
307 exit(0);
308 }
309 }
310
311 static unsigned long t_src_class(enum register_file file)
312 {
313
314 switch(file){
315 case PROGRAM_TEMPORARY:
316 return VSF_IN_CLASS_TMP;
317
318 case PROGRAM_INPUT:
319 return VSF_IN_CLASS_ATTR;
320
321 case PROGRAM_LOCAL_PARAM:
322 case PROGRAM_ENV_PARAM:
323 case PROGRAM_NAMED_PARAM:
324 case PROGRAM_STATE_VAR:
325 return VSF_IN_CLASS_PARAM;
326 /*
327 case PROGRAM_OUTPUT:
328 case PROGRAM_WRITE_ONLY:
329 case PROGRAM_ADDRESS:
330 */
331 default:
332 fprintf(stderr, "problem in %s", __FUNCTION__);
333 exit(0);
334 }
335 }
336
337 static unsigned long t_swizzle(GLubyte swizzle)
338 {
339 switch(swizzle){
340 case 0: return VSF_IN_COMPONENT_X;
341 case 1: return VSF_IN_COMPONENT_Y;
342 case 2: return VSF_IN_COMPONENT_Z;
343 case 3: return VSF_IN_COMPONENT_W;
344
345 case SWIZZLE_ZERO:
346 case SWIZZLE_ONE:
347 default:
348 fprintf(stderr, "problem in %s", __FUNCTION__);
349 exit(0);
350 }
351 }
352
353 static unsigned long t_src_index(struct r300_vertex_program *vp, struct vp_src_register *src)
354 {
355 int i;
356 int max_reg=-1;
357
358 if(src->File == PROGRAM_INPUT){
359 /*
360 switch(src->Index){
361 case 0: return 0;
362 case 3: return 1;
363
364 case 2: return 2;
365 case 8: return 8;
366
367 default: printf("unknown input index %d\n", src->Index); exit(0); break;
368 }*/
369
370 if(vp->inputs[src->Index] != -1)
371 return vp->inputs[src->Index];
372
373 for(i=0; i < VERT_ATTRIB_MAX; i++)
374 if(vp->inputs[i] > max_reg)
375 max_reg=vp->inputs[i];
376
377 vp->inputs[src->Index]=max_reg+1;
378
379 return vp->inputs[src->Index];
380 }else{
381 return src->Index;
382 }
383 }
384
385 static unsigned long t_src(struct r300_vertex_program *vp, struct vp_src_register *src)
386 {
387
388 return MAKE_VSF_SOURCE(t_src_index(vp, src),
389 t_swizzle(src->Swizzle[0]),
390 t_swizzle(src->Swizzle[1]),
391 t_swizzle(src->Swizzle[2]),
392 t_swizzle(src->Swizzle[3]),
393 t_src_class(src->File),
394 src->Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE);
395 }
396
397 static unsigned long t_opcode(enum vp_opcode opcode)
398 {
399
400 switch(opcode){
401 case VP_OPCODE_ADD: return R300_VPI_OUT_OP_ADD;
402 case VP_OPCODE_DST: return R300_VPI_OUT_OP_DST;
403 case VP_OPCODE_EX2: return R300_VPI_OUT_OP_EX2;
404 case VP_OPCODE_EXP: return R300_VPI_OUT_OP_EXP;
405 case VP_OPCODE_FRC: return R300_VPI_OUT_OP_FRC;
406 case VP_OPCODE_LG2: return R300_VPI_OUT_OP_LG2;
407 case VP_OPCODE_LIT: return R300_VPI_OUT_OP_LIT;
408 case VP_OPCODE_LOG: return R300_VPI_OUT_OP_LOG;
409 case VP_OPCODE_MAD: return R300_VPI_OUT_OP_MAD;
410 case VP_OPCODE_MAX: return R300_VPI_OUT_OP_MAX;
411 case VP_OPCODE_MIN: return R300_VPI_OUT_OP_MIN;
412 case VP_OPCODE_MUL: return R300_VPI_OUT_OP_MUL;
413 case VP_OPCODE_POW: return R300_VPI_OUT_OP_POW;
414 case VP_OPCODE_RCP: return R300_VPI_OUT_OP_RCP;
415 case VP_OPCODE_RSQ: return R300_VPI_OUT_OP_RSQ;
416 case VP_OPCODE_SGE: return R300_VPI_OUT_OP_SGE;
417 case VP_OPCODE_SLT: return R300_VPI_OUT_OP_SLT;
418 case VP_OPCODE_DP4: return R300_VPI_OUT_OP_DOT;
419
420 default:
421 fprintf(stderr, "%s: Should not be called with opcode %d!", __FUNCTION__, opcode);
422 }
423 exit(-1);
424 return 0;
425 }
426
427 static unsigned long op_operands(enum vp_opcode opcode)
428 {
429 int i;
430
431 /* Can we trust mesas opcodes to be in order ? */
432 for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++)
433 if(op_names[i].opcode == opcode)
434 return op_names[i].ip & OP_MASK;
435
436 fprintf(stderr, "op %d not found in op_names\n", opcode);
437 exit(-1);
438 return 0;
439 }
440
441 /* TODO: Get rid of t_src_class call */
442 #define CMP_SRCS(a, b) (a.Index != b.Index && \
443 ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \
444 t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \
445 (t_src_class(a.File) == VSF_IN_CLASS_ATTR && \
446 t_src_class(b.File) == VSF_IN_CLASS_ATTR))) \
447
448 #define SRCS_WRITABLE 1
449 static void translate_program(struct r300_vertex_program *vp)
450 {
451 struct vertex_program *mesa_vp=(void *)vp;
452 struct vp_instruction *vpi;
453 int operand_index, i;
454 VERTEX_SHADER_INSTRUCTION t2rs[1024];
455 VERTEX_SHADER_INSTRUCTION *o_inst;
456 unsigned long operands;
457 int u_temp_i=63; /* Initial value should be last tmp reg that hw supports */
458 #ifdef SRCS_WRITABLE
459 struct vp_src_register src[3];
460 #else
461 #define src vpi->SrcReg
462 #endif
463 vp->t2rs=0;
464 vp->program.length=0;
465 vp->num_temporaries=mesa_vp->Base.NumTemporaries;
466
467 for(i=0; i < VERT_ATTRIB_MAX; i++)
468 vp->inputs[i]=-1;
469
470 o_inst=vp->program.body.i;
471 for(vpi=mesa_vp->Instructions; vpi->Opcode != VP_OPCODE_END; vpi++, o_inst++){
472
473 operands=op_operands(vpi->Opcode);
474
475 for(i=0; i < operands; i++)
476 src[i]=vpi->SrcReg[i];
477
478 if(operands == 3){ /* TODO: scalars */
479 if( CMP_SRCS(src[1], src[2]) || CMP_SRCS(src[0], src[2]) ){
480 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i,
481 VSF_FLAG_ALL, VSF_OUT_CLASS_TMP);
482
483 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[2]),
484 SWIZZLE_X, SWIZZLE_Y,
485 SWIZZLE_Z, SWIZZLE_W,
486 t_src_class(src[0].File), VSF_FLAG_NONE);
487
488 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[2]),
489 SWIZZLE_ZERO, SWIZZLE_ZERO,
490 SWIZZLE_ZERO, SWIZZLE_ZERO,
491 t_src_class(src[0].File), VSF_FLAG_NONE);
492 o_inst->src3=0;
493 o_inst++;
494
495 src[2].File=PROGRAM_TEMPORARY;
496 src[2].Index=u_temp_i;
497 u_temp_i--;
498 }
499
500 }
501 if(operands >= 2){
502 if( CMP_SRCS(src[1], src[0]) ){
503 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i,
504 VSF_FLAG_ALL, VSF_OUT_CLASS_TMP);
505
506 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
507 SWIZZLE_X, SWIZZLE_Y,
508 SWIZZLE_Z, SWIZZLE_W,
509 t_src_class(src[0].File), VSF_FLAG_NONE);
510
511 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
512 SWIZZLE_ZERO, SWIZZLE_ZERO,
513 SWIZZLE_ZERO, SWIZZLE_ZERO,
514 t_src_class(src[0].File), VSF_FLAG_NONE);
515 o_inst->src3=0;
516 o_inst++;
517
518 src[0].File=PROGRAM_TEMPORARY;
519 src[0].Index=u_temp_i;
520 u_temp_i--;
521 }
522 }
523
524 /* these ops need special handling.
525 Ops that need temp vars should probably be given reg indexes starting at the end of tmp area. */
526 switch(vpi->Opcode){
527 case VP_OPCODE_MOV://ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO}
528 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, vpi->DstReg.Index,
529 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
530 o_inst->src1=t_src(vp, &src[0]);
531 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
532 SWIZZLE_ZERO, SWIZZLE_ZERO,
533 SWIZZLE_ZERO, SWIZZLE_ZERO,
534 t_src_class(src[0].File), VSF_FLAG_NONE);
535
536 o_inst->src3=0;
537 goto next;
538
539 case VP_OPCODE_DP3://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO}
540 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, vpi->DstReg.Index,
541 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
542
543 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
544 t_swizzle(src[0].Swizzle[0]),
545 t_swizzle(src[0].Swizzle[1]),
546 t_swizzle(src[0].Swizzle[2]),
547 SWIZZLE_ZERO,
548 t_src_class(src[0].File),
549 src[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE);
550
551 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
552 t_swizzle(src[1].Swizzle[0]),
553 t_swizzle(src[1].Swizzle[1]),
554 t_swizzle(src[1].Swizzle[2]),
555 SWIZZLE_ZERO,
556 t_src_class(src[1].File),
557 src[1].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE);
558
559 o_inst->src3=0;
560 goto next;
561
562 case VP_OPCODE_SUB://ADD RESULT 1.X Y Z W TMP 0{} {X Y Z W} PARAM 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W
563 #ifdef SRCS_WRITABLE
564 vpi->Opcode=VP_OPCODE_ADD;
565 src[1].Negate=!src[1].Negate;
566 break;
567 #else
568 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, vpi->DstReg.Index,
569 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
570
571 o_inst->src1=t_src(vp, &src[0]);
572 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
573 t_swizzle(src[1].Swizzle[0]),
574 t_swizzle(src[1].Swizzle[1]),
575 t_swizzle(src[1].Swizzle[2]),
576 t_swizzle(src[1].Swizzle[3]),
577 t_src_class(src[1].File),
578 (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE);
579 o_inst->src3=0;
580 goto next;
581 #endif
582 case VP_OPCODE_ABS://MAX RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W
583 #ifdef SRCS_WRITABLE
584 vpi->Opcode=VP_OPCODE_MAX;
585 src[1]=src[0];
586 src[1].Negate=GL_TRUE;
587 break;
588 #else
589 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MAX, vpi->DstReg.Index,
590 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
591
592 o_inst->src1=t_src(vp, &src[0]);
593 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
594 t_swizzle(src[0].Swizzle[0]),
595 t_swizzle(src[0].Swizzle[1]),
596 t_swizzle(src[0].Swizzle[2]),
597 t_swizzle(src[0].Swizzle[3]),
598 t_src_class(src[0].File),
599 VSF_FLAG_ALL);
600 o_inst->src3=0;
601 goto next;
602 #endif
603 case VP_OPCODE_FLR:
604 /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W}
605 ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} TMP 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W */
606
607 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_FRC, u_temp_i,
608 t_dst_mask(vpi->DstReg.WriteMask), VSF_OUT_CLASS_TMP);
609
610 o_inst->src1=t_src(vp, &src[0]);
611 o_inst->src2=0;
612 o_inst->src3=0;
613 o_inst++;
614
615 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, vpi->DstReg.Index,
616 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
617
618 o_inst->src1=t_src(vp, &src[0]);
619 o_inst->src2=MAKE_VSF_SOURCE(u_temp_i,
620 VSF_IN_COMPONENT_X,
621 VSF_IN_COMPONENT_Y,
622 VSF_IN_COMPONENT_Z,
623 VSF_IN_COMPONENT_W,
624 VSF_IN_CLASS_TMP,
625 /* Not 100% sure about this */
626 (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/);
627
628 o_inst->src3=0;
629 u_temp_i--;
630 goto next;
631
632 case VP_OPCODE_DPH://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W}
633 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, vpi->DstReg.Index,
634 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
635
636 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
637 t_swizzle(src[0].Swizzle[0]),
638 t_swizzle(src[0].Swizzle[1]),
639 t_swizzle(src[0].Swizzle[2]),
640 VSF_IN_COMPONENT_ONE,
641 t_src_class(src[0].File),
642 src[1].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE);
643 o_inst->src2=t_src(vp, &src[1]);
644 o_inst->src3=0;
645 goto next;
646
647 case VP_OPCODE_XPD:
648 /* ADD TMP 0.X Y Z PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO}
649 MUL TMP 1.X Y Z W TMP 0{} {Z X Y ZERO} PARAM 1{} {Y Z X ZERO}
650 MAD RESULT 1.X Y Z W TMP 0{} {Y Z X ONE} PARAM 1{} {Z X Y ONE} TMP 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W*/
651
652 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i,
653 t_dst_mask(vpi->DstReg.WriteMask), VSF_OUT_CLASS_TMP);
654
655 o_inst->src1=t_src(vp, &src[0]);
656 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
657 SWIZZLE_ZERO, SWIZZLE_ZERO,
658 SWIZZLE_ZERO, SWIZZLE_ZERO,
659 t_src_class(src[0].File), VSF_FLAG_NONE);
660 o_inst->src3=0;
661 o_inst++;
662 u_temp_i--;
663
664 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MUL, u_temp_i,
665 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
666
667 o_inst->src1=MAKE_VSF_SOURCE(u_temp_i+1,
668 VSF_IN_COMPONENT_X,
669 VSF_IN_COMPONENT_Y,
670 VSF_IN_COMPONENT_Z,
671 SWIZZLE_ZERO,
672 VSF_IN_CLASS_TMP,
673 /* Not 100% sure about this */
674 (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/);
675 o_inst->src2=t_src(vp, &src[1]);
676 o_inst->src3=0;
677 u_temp_i--;
678 o_inst++;
679
680 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, vpi->DstReg.Index,
681 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
682
683 o_inst->src1=MAKE_VSF_SOURCE(u_temp_i+2,
684 VSF_IN_COMPONENT_X,
685 VSF_IN_COMPONENT_Y,
686 VSF_IN_COMPONENT_Z,
687 SWIZZLE_ONE,
688 VSF_IN_CLASS_TMP,
689 /* Not 100% sure about this */
690 src[1].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/);
691
692 o_inst->src2=MAKE_VSF_SOURCE(u_temp_i+1,
693 VSF_IN_COMPONENT_X,
694 VSF_IN_COMPONENT_Y,
695 VSF_IN_COMPONENT_Z,
696 VSF_IN_COMPONENT_W,
697 VSF_IN_CLASS_TMP,
698 /* Not 100% sure about this */
699 (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/);
700 o_inst->src3=0;
701 goto next;
702
703 case VP_OPCODE_ARL:
704 case VP_OPCODE_SWZ:
705 case VP_OPCODE_RCC:
706 case VP_OPCODE_PRINT:
707 //vp->num_temporaries++;
708 fprintf(stderr, "Dont know how to handle op %d yet\n", vpi->Opcode);
709 exit(-1);
710 break;
711 case VP_OPCODE_END:
712 break;
713 default:
714 break;
715 }
716
717 o_inst->op=MAKE_VSF_OP(t_opcode(vpi->Opcode), vpi->DstReg.Index,
718 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
719
720 switch(operands){
721 case 1:
722 o_inst->src1=t_src(vp, &src[0]);
723 o_inst->src2=0;
724 o_inst->src3=0;
725 break;
726
727 case 2:
728 o_inst->src1=t_src(vp, &src[0]);
729 o_inst->src2=t_src(vp, &src[1]);
730 o_inst->src3=0;
731 break;
732
733 case 3:
734 o_inst->src1=t_src(vp, &src[0]);
735 o_inst->src2=t_src(vp, &src[1]);
736 o_inst->src3=t_src(vp, &src[2]);
737 break;
738
739 default:
740 fprintf(stderr, "scalars and op RCC not handled yet");
741 exit(-1);
742 break;
743 }
744 next:
745
746 /* If instruction writes to result and one of the inputs is tmp, we move it at the end of program */
747 if(vpi->DstReg.File == PROGRAM_OUTPUT){
748 for(operand_index=0; operand_index < operands; operand_index++)
749 if(src[operand_index].File == PROGRAM_TEMPORARY){
750 t2rs[vp->t2rs++]=*o_inst;
751 o_inst--; /* FIXME */
752 break;
753 }
754 }
755
756 }
757
758 /* Put "tmp to result" instructions in */
759 for(i=0; i < vp->t2rs; i++, o_inst++)
760 *o_inst=t2rs[i];
761
762 vp->program.length=(o_inst - vp->program.body.i) * 4;
763
764 if(u_temp_i < vp->num_temporaries)
765 vp->translated=GL_FALSE; /* temps exhausted - program cannot be run */
766 else
767 vp->translated=GL_TRUE;
768 }
769
770 static void r300BindProgram(GLcontext *ctx, GLenum target, struct program *prog)
771 {
772 r300ContextPtr rmesa = R300_CONTEXT(ctx);
773 struct r300_vertex_program *vp=(void *)prog;
774 #if 0
775 fprintf(stderr, "r300BindProgram\n");
776 #endif
777 if(rmesa->current_vp == vp)
778 return ;
779
780 rmesa->current_vp = vp;
781 }
782
783 /* Mesa doesnt seem to have prototype for this */
784 struct program *
785 _mesa_init_ati_fragment_shader( GLcontext *ctx, struct ati_fragment_shader *prog,
786 GLenum target, GLuint id);
787
788 static struct program *r300NewProgram(GLcontext *ctx, GLenum target, GLuint id)
789 {
790 struct r300_vertex_program *vp;
791 struct fragment_program *fp;
792 struct ati_fragment_shader *afs;
793 #if 0
794 fprintf(stderr, "r300NewProgram, target=%d, id=%d\n", target, id);
795 #endif
796 switch(target){
797 case GL_VERTEX_PROGRAM_ARB:
798 vp=CALLOC_STRUCT(r300_vertex_program);
799 return _mesa_init_vertex_program(ctx, &vp->mesa_program, target, id);
800
801 case GL_FRAGMENT_PROGRAM_ARB:
802 fp=CALLOC_STRUCT(fragment_program);
803 return _mesa_init_fragment_program(ctx, fp, target, id);
804
805 case GL_FRAGMENT_PROGRAM_NV:
806 fp=CALLOC_STRUCT(fragment_program);
807 return _mesa_init_fragment_program(ctx, fp, target, id);
808
809 case GL_FRAGMENT_SHADER_ATI:
810 afs=CALLOC_STRUCT(ati_fragment_shader);
811 return _mesa_init_ati_fragment_shader(ctx, afs, target, id);
812 }
813
814 return NULL;
815 }
816
817
818 static void r300DeleteProgram(GLcontext *ctx, struct program *prog)
819 {
820 r300ContextPtr rmesa = R300_CONTEXT(ctx);
821 struct r300_vertex_program *vp=(void *)prog;
822 #if 0
823 fprintf(stderr, "r300DeleteProgram\n");
824 #endif
825 if(rmesa->current_vp == vp)
826 rmesa->current_vp = NULL;
827
828 _mesa_delete_program(ctx, prog);
829 }
830
831 static GLboolean r300IsProgramNative(GLcontext *ctx, GLenum target,
832 struct program *prog);
833
834 static void r300ProgramStringNotify(GLcontext *ctx, GLenum target,
835 struct program *prog)
836 {
837 struct r300_vertex_program *vp=(void *)prog;
838 #if 0
839 fprintf(stderr, "r300ProgramStringNotify\n");
840 #endif
841
842 switch(target) {
843 case GL_VERTEX_PROGRAM_ARB:
844 vp->translated=GL_FALSE;
845 break;
846 }
847
848 /* XXX: There is still something wrong as mesa doesnt call r300IsProgramNative at all */
849 (void)r300IsProgramNative(ctx, target, prog);
850
851 }
852
853 static GLboolean r300IsProgramNative(GLcontext *ctx, GLenum target,
854 struct program *prog)
855 {
856 struct r300_vertex_program *vp=(void *)prog;
857 r300ContextPtr rmesa = R300_CONTEXT(ctx);
858
859 #if 0
860 fprintf(stderr, "r300IsProgramNative\n");
861 //exit(0);
862 debug_vp(ctx, vp);
863 #endif
864 translate_program(vp);
865 //r300VertexProgUpdateParams(ctx, vp);
866
867 return 1;
868 }
869
870 /* This is misnamed and shouldnt be here since fragment programs use these functions too */
871 void r300InitVertexProgFuncs(struct dd_function_table *functions)
872 {
873 functions->NewProgram=r300NewProgram;
874 functions->BindProgram=r300BindProgram;
875 functions->DeleteProgram=r300DeleteProgram;
876 functions->ProgramStringNotify=r300ProgramStringNotify;
877 functions->IsProgramNative=r300IsProgramNative;
878 }