1 /**************************************************************************
3 Copyright (C) 2005 Aapo Tahkola.
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:
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
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.
26 **************************************************************************/
30 * Aapo Tahkola <aet@rasterburn.org>
37 #include "r300_context.h"
38 #include "nvvertprog.h"
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}
48 unsigned long ip
; /* number of input operands and flags */
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
),
58 OPN(EX2
, 1|SCALAR_FLAG
, 4|SCALAR_FLAG
),
59 OPN(EXP
, 1|SCALAR_FLAG
, 1),
62 OPN(LG2
, 1|SCALAR_FLAG
, 4|SCALAR_FLAG
),
64 OPN(LOG
, 1|SCALAR_FLAG
, 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
),
78 OPN(RCC
, 0, 0), //extra
83 #define OPN(rf) {#rf, PROGRAM_##rf}
88 }register_file_names
[]={
100 char *dst_mask_names
[4]={ "X", "Y", "Z", "W" };
102 /* from vertex program spec:
103 Instruction Inputs Output Description
104 ----------- ------ ------ --------------------------------
105 ABS v v absolute value
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)
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
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
130 SWZ v v extended swizzle
131 XPD v,v v cross product
134 void dump_program_params(GLcontext
*ctx
, struct vertex_program
*vp
)
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
);
145 _mesa_load_state_parameters(ctx
, vp
->Parameters
);
148 for(pi
=0; pi
< vp
->Base
.NumParameters
; pi
++){
149 fprintf(stderr
, "{ ");
151 fprintf(stderr
, "%f ", vp
->Base
.LocalParams
[pi
][i
]);
152 fprintf(stderr
, "}\n");
155 for(pi
=0; pi
< vp
->Parameters
->NumParameters
; pi
++){
156 fprintf(stderr
, "param %02d:", pi
);
158 switch(vp
->Parameters
->Parameters
[pi
].Type
){
160 case NAMED_PARAMETER
:
161 fprintf(stderr
, "%s", vp
->Parameters
->Parameters
[pi
].Name
);
162 fprintf(stderr
, "(NAMED_PARAMETER)");
166 fprintf(stderr
, "(CONSTANT)");
170 fprintf(stderr
, "(STATE)\n");
175 fprintf(stderr
, "{ ");
177 fprintf(stderr
, "%f ", vp
->Parameters
->Parameters
[pi
].Values
[i
]);
178 fprintf(stderr
, "}\n");
183 static void debug_vp(GLcontext
*ctx
, struct vertex_program
*vp
)
185 struct vp_instruction
*vpi
;
186 int i
, operand_index
;
189 dump_program_params(ctx
, vp
);
191 vpi
=vp
->Instructions
;
194 if(vpi
->Opcode
== VP_OPCODE_END
)
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
);
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
);
212 fprintf(stderr
, "%d.", vpi
->DstReg
.Index
);
215 if(vpi
->DstReg
.WriteMask
[i
])
216 fprintf(stderr
, "%s", dst_mask_names
[i
]);
217 fprintf(stderr
, " ");
219 for(operand_index
=0; operand_index
< (op_names
[operator_index
].ip
& (~FLAG_MASK
));
222 if(vpi
->SrcReg
[operand_index
].Negate
)
223 fprintf(stderr
, "-");
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
);
231 fprintf(stderr
, "%d.", vpi
->SrcReg
[operand_index
].Index
);
234 fprintf(stderr
, "%s", dst_mask_names
[vpi
->SrcReg
[operand_index
].Swizzle
[i
]]);
236 if(operand_index
+1 < (op_names
[operator_index
].ip
& (~FLAG_MASK
)) )
237 fprintf(stderr
, ",");
239 fprintf(stderr
, "\n");
244 void r300VertexProgUpdateParams(GLcontext
*ctx
, struct r300_vertex_program
*vp
)
247 struct vertex_program
*mesa_vp
=(void *)vp
;
250 _mesa_load_state_parameters(ctx
, mesa_vp
->Parameters
);
252 //debug_vp(ctx, mesa_vp);
255 for(pi
=0; pi
< mesa_vp
->Parameters
->NumParameters
; pi
++){
256 switch(mesa_vp
->Parameters
->Parameters
[pi
].Type
){
259 case NAMED_PARAMETER
:
260 //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
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];
268 default: _mesa_problem(NULL
, "Bad param type in %s", __FUNCTION__
);
273 vp
->params
.length
=dst_index
;
276 static unsigned long t_dst_mask(GLboolean
*mask
)
278 unsigned long flags
=0;
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
;
288 static unsigned long t_dst_class(enum register_file file
)
292 case PROGRAM_TEMPORARY
:
293 return VSF_OUT_CLASS_TMP
;
295 return VSF_OUT_CLASS_RESULT
;
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:
306 fprintf(stderr
, "problem in %s", __FUNCTION__
);
311 static unsigned long t_src_class(enum register_file file
)
315 case PROGRAM_TEMPORARY
:
316 return VSF_IN_CLASS_TMP
;
319 return VSF_IN_CLASS_ATTR
;
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
;
328 case PROGRAM_WRITE_ONLY:
329 case PROGRAM_ADDRESS:
332 fprintf(stderr
, "problem in %s", __FUNCTION__
);
337 static unsigned long t_swizzle(GLubyte 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
;
348 fprintf(stderr
, "problem in %s", __FUNCTION__
);
353 static unsigned long t_src_index(struct r300_vertex_program
*vp
, struct vp_src_register
*src
)
358 if(src
->File
== PROGRAM_INPUT
){
367 default: printf("unknown input index %d\n", src->Index); exit(0); break;
370 if(vp
->inputs
[src
->Index
] != -1)
371 return vp
->inputs
[src
->Index
];
373 for(i
=0; i
< VERT_ATTRIB_MAX
; i
++)
374 if(vp
->inputs
[i
] > max_reg
)
375 max_reg
=vp
->inputs
[i
];
377 vp
->inputs
[src
->Index
]=max_reg
+1;
379 return vp
->inputs
[src
->Index
];
385 static unsigned long t_src(struct r300_vertex_program
*vp
, struct vp_src_register
*src
)
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
);
397 static unsigned long t_opcode(enum vp_opcode 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
;
421 fprintf(stderr
, "%s: Should not be called with opcode %d!", __FUNCTION__
, opcode
);
427 static unsigned long op_operands(enum vp_opcode opcode
)
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
;
436 fprintf(stderr
, "op %d not found in op_names\n", opcode
);
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))) \
448 #define SRCS_WRITABLE 1
449 static void translate_program(struct r300_vertex_program
*vp
)
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 */
459 struct vp_src_register src
[3];
461 #define src vpi->SrcReg
464 vp
->program
.length
=0;
465 vp
->num_temporaries
=mesa_vp
->Base
.NumTemporaries
;
467 for(i
=0; i
< VERT_ATTRIB_MAX
; i
++)
470 o_inst
=vp
->program
.body
.i
;
471 for(vpi
=mesa_vp
->Instructions
; vpi
->Opcode
!= VP_OPCODE_END
; vpi
++, o_inst
++){
473 operands
=op_operands(vpi
->Opcode
);
475 for(i
=0; i
< operands
; i
++)
476 src
[i
]=vpi
->SrcReg
[i
];
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
);
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
);
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
);
495 src
[2].File
=PROGRAM_TEMPORARY
;
496 src
[2].Index
=u_temp_i
;
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
);
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
);
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
);
518 src
[0].File
=PROGRAM_TEMPORARY
;
519 src
[0].Index
=u_temp_i
;
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. */
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
);
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
));
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]),
548 t_src_class(src
[0].File
),
549 src
[0].Negate
? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
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]),
556 t_src_class(src
[1].File
),
557 src
[1].Negate
? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
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
564 vpi
->Opcode
=VP_OPCODE_ADD
;
565 src
[1].Negate
=!src
[1].Negate
;
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
));
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
);
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
584 vpi
->Opcode
=VP_OPCODE_MAX
;
586 src
[1].Negate
=GL_TRUE
;
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
));
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
),
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 */
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
);
610 o_inst
->src1
=t_src(vp
, &src
[0]);
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
));
618 o_inst
->src1
=t_src(vp
, &src
[0]);
619 o_inst
->src2
=MAKE_VSF_SOURCE(u_temp_i
,
625 /* Not 100% sure about this */
626 (!src
[1].Negate
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
/*VSF_FLAG_ALL*/);
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
));
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]);
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*/
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
);
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
);
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
));
667 o_inst
->src1
=MAKE_VSF_SOURCE(u_temp_i
+1,
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]);
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
));
683 o_inst
->src1
=MAKE_VSF_SOURCE(u_temp_i
+2,
689 /* Not 100% sure about this */
690 src
[1].Negate
? VSF_FLAG_ALL
: VSF_FLAG_NONE
/*VSF_FLAG_ALL*/);
692 o_inst
->src2
=MAKE_VSF_SOURCE(u_temp_i
+1,
698 /* Not 100% sure about this */
699 (!src
[1].Negate
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
/*VSF_FLAG_ALL*/);
706 case VP_OPCODE_PRINT
:
707 //vp->num_temporaries++;
708 fprintf(stderr
, "Dont know how to handle op %d yet\n", vpi
->Opcode
);
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
));
722 o_inst
->src1
=t_src(vp
, &src
[0]);
728 o_inst
->src1
=t_src(vp
, &src
[0]);
729 o_inst
->src2
=t_src(vp
, &src
[1]);
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]);
740 fprintf(stderr
, "scalars and op RCC not handled yet");
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 */
758 /* Put "tmp to result" instructions in */
759 for(i
=0; i
< vp
->t2rs
; i
++, o_inst
++)
762 vp
->program
.length
=(o_inst
- vp
->program
.body
.i
) * 4;
764 if(u_temp_i
< vp
->num_temporaries
)
765 vp
->translated
=GL_FALSE
; /* temps exhausted - program cannot be run */
767 vp
->translated
=GL_TRUE
;
770 static void r300BindProgram(GLcontext
*ctx
, GLenum target
, struct program
*prog
)
772 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
773 struct r300_vertex_program
*vp
=(void *)prog
;
775 fprintf(stderr
, "r300BindProgram\n");
777 if(rmesa
->current_vp
== vp
)
780 rmesa
->current_vp
= vp
;
783 /* Mesa doesnt seem to have prototype for this */
785 _mesa_init_ati_fragment_shader( GLcontext
*ctx
, struct ati_fragment_shader
*prog
,
786 GLenum target
, GLuint id
);
788 static struct program
*r300NewProgram(GLcontext
*ctx
, GLenum target
, GLuint id
)
790 struct r300_vertex_program
*vp
;
791 struct fragment_program
*fp
;
792 struct ati_fragment_shader
*afs
;
794 fprintf(stderr
, "r300NewProgram, target=%d, id=%d\n", target
, id
);
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
);
801 case GL_FRAGMENT_PROGRAM_ARB
:
802 fp
=CALLOC_STRUCT(fragment_program
);
803 return _mesa_init_fragment_program(ctx
, fp
, target
, id
);
805 case GL_FRAGMENT_PROGRAM_NV
:
806 fp
=CALLOC_STRUCT(fragment_program
);
807 return _mesa_init_fragment_program(ctx
, fp
, target
, id
);
809 case GL_FRAGMENT_SHADER_ATI
:
810 afs
=CALLOC_STRUCT(ati_fragment_shader
);
811 return _mesa_init_ati_fragment_shader(ctx
, afs
, target
, id
);
818 static void r300DeleteProgram(GLcontext
*ctx
, struct program
*prog
)
820 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
821 struct r300_vertex_program
*vp
=(void *)prog
;
823 fprintf(stderr
, "r300DeleteProgram\n");
825 if(rmesa
->current_vp
== vp
)
826 rmesa
->current_vp
= NULL
;
828 _mesa_delete_program(ctx
, prog
);
831 static GLboolean
r300IsProgramNative(GLcontext
*ctx
, GLenum target
,
832 struct program
*prog
);
834 static void r300ProgramStringNotify(GLcontext
*ctx
, GLenum target
,
835 struct program
*prog
)
837 struct r300_vertex_program
*vp
=(void *)prog
;
839 fprintf(stderr
, "r300ProgramStringNotify\n");
843 case GL_VERTEX_PROGRAM_ARB
:
844 vp
->translated
=GL_FALSE
;
848 /* XXX: There is still something wrong as mesa doesnt call r300IsProgramNative at all */
849 (void)r300IsProgramNative(ctx
, target
, prog
);
853 static GLboolean
r300IsProgramNative(GLcontext
*ctx
, GLenum target
,
854 struct program
*prog
)
856 struct r300_vertex_program
*vp
=(void *)prog
;
857 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
860 fprintf(stderr
, "r300IsProgramNative\n");
864 translate_program(vp
);
865 //r300VertexProgUpdateParams(ctx, vp);
870 /* This is misnamed and shouldnt be here since fragment programs use these functions too */
871 void r300InitVertexProgFuncs(struct dd_function_table
*functions
)
873 functions
->NewProgram
=r300NewProgram
;
874 functions
->BindProgram
=r300BindProgram
;
875 functions
->DeleteProgram
=r300DeleteProgram
;
876 functions
->ProgramStringNotify
=r300ProgramStringNotify
;
877 functions
->IsProgramNative
=r300IsProgramNative
;