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 THE COPYRIGHT OWNER(S) AND/OR ITS 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>
36 #include "nvvertexec.h"
38 #include "r300_context.h"
39 #include "r300_program.h"
40 #include "program_instruction.h"
42 #define SCALAR_FLAG (1<<31)
43 #define FLAG_MASK (1<<31)
44 #define OP_MASK (0xf) /* we are unlikely to have more than 15 */
45 #define OPN(operator, ip, op) {#operator, OPCODE_##operator, ip, op}
50 unsigned long ip
; /* number of input operands and flags */
55 OPN(ARL
, 1, 1|SCALAR_FLAG
),
56 OPN(DP3
, 2, 3|SCALAR_FLAG
),
57 OPN(DP4
, 2, 3|SCALAR_FLAG
),
58 OPN(DPH
, 2, 3|SCALAR_FLAG
),
60 OPN(EX2
, 1|SCALAR_FLAG
, 4|SCALAR_FLAG
),
61 OPN(EXP
, 1|SCALAR_FLAG
, 1),
64 OPN(LG2
, 1|SCALAR_FLAG
, 4|SCALAR_FLAG
),
66 OPN(LOG
, 1|SCALAR_FLAG
, 1),
72 OPN(POW
, 2|SCALAR_FLAG
, 4|SCALAR_FLAG
),
73 OPN(RCP
, 1|SCALAR_FLAG
, 4|SCALAR_FLAG
),
74 OPN(RSQ
, 1|SCALAR_FLAG
, 4|SCALAR_FLAG
),
80 OPN(RCC
, 0, 0), //extra
86 int r300VertexProgUpdateParams(GLcontext
*ctx
, struct r300_vertex_program
*vp
, float *dst
)
89 struct vertex_program
*mesa_vp
=(void *)vp
;
91 struct program_parameter_list
*paramList
;
93 if (mesa_vp
->IsNVProgram
) {
94 _mesa_init_vp_per_primitive_registers(ctx
);
96 for (pi
=0; pi
< MAX_NV_VERTEX_PROGRAM_PARAMS
; pi
++) {
97 *dst
++=ctx
->VertexProgram
.Parameters
[pi
][0];
98 *dst
++=ctx
->VertexProgram
.Parameters
[pi
][1];
99 *dst
++=ctx
->VertexProgram
.Parameters
[pi
][2];
100 *dst
++=ctx
->VertexProgram
.Parameters
[pi
][3];
105 assert(mesa_vp
->Base
.Parameters
);
106 _mesa_load_state_parameters(ctx
, mesa_vp
->Base
.Parameters
);
108 if(mesa_vp
->Base
.Parameters
->NumParameters
* 4 > VSF_MAX_FRAGMENT_LENGTH
){
109 fprintf(stderr
, "%s:Params exhausted\n", __FUNCTION__
);
113 paramList
= mesa_vp
->Base
.Parameters
;
114 for(pi
=0; pi
< paramList
->NumParameters
; pi
++){
115 switch(paramList
->Parameters
[pi
].Type
){
117 case PROGRAM_STATE_VAR
:
118 case PROGRAM_NAMED_PARAM
:
119 //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
120 case PROGRAM_CONSTANT
:
121 *dst
++=paramList
->ParameterValues
[pi
][0];
122 *dst
++=paramList
->ParameterValues
[pi
][1];
123 *dst
++=paramList
->ParameterValues
[pi
][2];
124 *dst
++=paramList
->ParameterValues
[pi
][3];
127 default: _mesa_problem(NULL
, "Bad param type in %s", __FUNCTION__
);
135 static unsigned long t_dst_mask(GLuint mask
)
137 unsigned long flags
=0;
139 if(mask
& WRITEMASK_X
) flags
|= VSF_FLAG_X
;
140 if(mask
& WRITEMASK_Y
) flags
|= VSF_FLAG_Y
;
141 if(mask
& WRITEMASK_Z
) flags
|= VSF_FLAG_Z
;
142 if(mask
& WRITEMASK_W
) flags
|= VSF_FLAG_W
;
147 static unsigned long t_dst_class(enum register_file file
)
151 case PROGRAM_TEMPORARY
:
152 return VSF_OUT_CLASS_TMP
;
154 return VSF_OUT_CLASS_RESULT
;
155 case PROGRAM_ADDRESS
:
156 return VSF_OUT_CLASS_ADDR
;
159 case PROGRAM_LOCAL_PARAM:
160 case PROGRAM_ENV_PARAM:
161 case PROGRAM_NAMED_PARAM:
162 case PROGRAM_STATE_VAR:
163 case PROGRAM_WRITE_ONLY:
164 case PROGRAM_ADDRESS:
167 fprintf(stderr
, "problem in %s", __FUNCTION__
);
172 static unsigned long t_dst_index(struct r300_vertex_program
*vp
, struct prog_dst_register
*dst
)
174 if(dst
->File
== PROGRAM_OUTPUT
) {
175 if (vp
->outputs
[dst
->Index
] != -1)
176 return vp
->outputs
[dst
->Index
];
178 WARN_ONCE("Unknown output %d\n", dst
->Index
);
181 }else if(dst
->File
== PROGRAM_ADDRESS
) {
182 assert(dst
->Index
== 0);
188 static unsigned long t_src_class(enum register_file file
)
192 case PROGRAM_TEMPORARY
:
193 return VSF_IN_CLASS_TMP
;
196 return VSF_IN_CLASS_ATTR
;
198 case PROGRAM_LOCAL_PARAM
:
199 case PROGRAM_ENV_PARAM
:
200 case PROGRAM_NAMED_PARAM
:
201 case PROGRAM_STATE_VAR
:
202 return VSF_IN_CLASS_PARAM
;
205 case PROGRAM_WRITE_ONLY:
206 case PROGRAM_ADDRESS:
209 fprintf(stderr
, "problem in %s", __FUNCTION__
);
214 static unsigned long t_swizzle(GLubyte swizzle
)
217 case SWIZZLE_X
: return VSF_IN_COMPONENT_X
;
218 case SWIZZLE_Y
: return VSF_IN_COMPONENT_Y
;
219 case SWIZZLE_Z
: return VSF_IN_COMPONENT_Z
;
220 case SWIZZLE_W
: return VSF_IN_COMPONENT_W
;
221 case SWIZZLE_ZERO
: return VSF_IN_COMPONENT_ZERO
;
222 case SWIZZLE_ONE
: return VSF_IN_COMPONENT_ONE
;
224 fprintf(stderr
, "problem in %s", __FUNCTION__
);
230 static void vp_dump_inputs(struct r300_vertex_program
*vp
, char *caller
)
235 fprintf(stderr
, "vp null in call to %s from %s\n", __FUNCTION__
, caller
);
239 fprintf(stderr
, "%s:<", caller
);
240 for(i
=0; i
< VERT_ATTRIB_MAX
; i
++)
241 fprintf(stderr
, "%d ", vp
->inputs
[i
]);
242 fprintf(stderr
, ">\n");
247 static unsigned long t_src_index(struct r300_vertex_program
*vp
, struct prog_src_register
*src
)
252 if(src
->File
== PROGRAM_INPUT
){
253 if(vp
->inputs
[src
->Index
] != -1)
254 return vp
->inputs
[src
->Index
];
256 for(i
=0; i
< VERT_ATTRIB_MAX
; i
++)
257 if(vp
->inputs
[i
] > max_reg
)
258 max_reg
=vp
->inputs
[i
];
260 vp
->inputs
[src
->Index
]=max_reg
+1;
262 //vp_dump_inputs(vp, __FUNCTION__);
264 return vp
->inputs
[src
->Index
];
270 static unsigned long t_src(struct r300_vertex_program
*vp
, struct prog_src_register
*src
)
273 return MAKE_VSF_SOURCE(t_src_index(vp
, src
),
274 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
275 t_swizzle(GET_SWZ(src
->Swizzle
, 1)),
276 t_swizzle(GET_SWZ(src
->Swizzle
, 2)),
277 t_swizzle(GET_SWZ(src
->Swizzle
, 3)),
278 t_src_class(src
->File
),
279 src
->NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
->RelAddr
<< 4);
282 static unsigned long t_src_scalar(struct r300_vertex_program
*vp
, struct prog_src_register
*src
)
285 return MAKE_VSF_SOURCE(t_src_index(vp
, src
),
286 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
287 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
288 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
289 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
290 t_src_class(src
->File
),
291 src
->NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
294 static unsigned long t_opcode(enum prog_opcode opcode
)
298 case OPCODE_DST
: return R300_VPI_OUT_OP_DST
;
299 case OPCODE_EX2
: return R300_VPI_OUT_OP_EX2
;
300 case OPCODE_EXP
: return R300_VPI_OUT_OP_EXP
;
301 case OPCODE_FRC
: return R300_VPI_OUT_OP_FRC
;
302 case OPCODE_LG2
: return R300_VPI_OUT_OP_LG2
;
303 case OPCODE_LOG
: return R300_VPI_OUT_OP_LOG
;
304 case OPCODE_MAX
: return R300_VPI_OUT_OP_MAX
;
305 case OPCODE_MIN
: return R300_VPI_OUT_OP_MIN
;
306 case OPCODE_MUL
: return R300_VPI_OUT_OP_MUL
;
307 case OPCODE_RCP
: return R300_VPI_OUT_OP_RCP
;
308 case OPCODE_RSQ
: return R300_VPI_OUT_OP_RSQ
;
309 case OPCODE_SGE
: return R300_VPI_OUT_OP_SGE
;
310 case OPCODE_SLT
: return R300_VPI_OUT_OP_SLT
;
311 case OPCODE_DP4
: return R300_VPI_OUT_OP_DOT
;
314 fprintf(stderr
, "%s: Should not be called with opcode %d!", __FUNCTION__
, opcode
);
320 static unsigned long op_operands(enum prog_opcode opcode
)
324 /* Can we trust mesas opcodes to be in order ? */
325 for(i
=0; i
< sizeof(op_names
) / sizeof(*op_names
); i
++)
326 if(op_names
[i
].opcode
== opcode
)
327 return op_names
[i
].ip
;
329 fprintf(stderr
, "op %d not found in op_names\n", opcode
);
334 /* TODO: Get rid of t_src_class call */
335 #define CMP_SRCS(a, b) (a.Index != b.Index && \
336 ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \
337 t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \
338 (t_src_class(a.File) == VSF_IN_CLASS_ATTR && \
339 t_src_class(b.File) == VSF_IN_CLASS_ATTR))) \
341 #define ZERO_SRC_0 MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \
342 SWIZZLE_ZERO, SWIZZLE_ZERO, \
343 SWIZZLE_ZERO, SWIZZLE_ZERO, \
344 t_src_class(src[0].File), VSF_FLAG_NONE)
346 #define ZERO_SRC_1 MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \
347 SWIZZLE_ZERO, SWIZZLE_ZERO, \
348 SWIZZLE_ZERO, SWIZZLE_ZERO, \
349 t_src_class(src[1].File), VSF_FLAG_NONE)
351 #define ZERO_SRC_2 MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \
352 SWIZZLE_ZERO, SWIZZLE_ZERO, \
353 SWIZZLE_ZERO, SWIZZLE_ZERO, \
354 t_src_class(src[2].File), VSF_FLAG_NONE)
356 #define ONE_SRC_0 MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \
357 SWIZZLE_ONE, SWIZZLE_ONE, \
358 SWIZZLE_ONE, SWIZZLE_ONE, \
359 t_src_class(src[0].File), VSF_FLAG_NONE)
361 #define ONE_SRC_1 MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \
362 SWIZZLE_ONE, SWIZZLE_ONE, \
363 SWIZZLE_ONE, SWIZZLE_ONE, \
364 t_src_class(src[1].File), VSF_FLAG_NONE)
366 #define ONE_SRC_2 MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \
367 SWIZZLE_ONE, SWIZZLE_ONE, \
368 SWIZZLE_ONE, SWIZZLE_ONE, \
369 t_src_class(src[2].File), VSF_FLAG_NONE)
371 /* DP4 version seems to trigger some hw peculiarity */
374 #define FREE_TEMPS() \
376 if(u_temp_i < vp->num_temporaries) { \
377 WARN_ONCE("Ran out of temps, num temps %d, us %d\n", vp->num_temporaries, u_temp_i); \
378 vp->native = GL_FALSE; \
380 u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; \
383 void r300_translate_vertex_shader(struct r300_vertex_program
*vp
)
385 struct vertex_program
*mesa_vp
=(void *)vp
;
386 struct prog_instruction
*vpi
;
388 VERTEX_SHADER_INSTRUCTION
*o_inst
;
389 unsigned long operands
;
392 /* Initial value should be last tmp reg that hw supports.
393 Strangely enough r300 doesnt mind even though these would be out of range.
394 Smart enough to realize that it doesnt need it? */
395 int u_temp_i
=VSF_MAX_FRAGMENT_TEMPS
-1;
396 struct prog_src_register src
[3];
398 if (getenv("R300_VP_SAFETY")) {
399 WARN_ONCE("R300_VP_SAFETY enabled.\n");
401 vpi
= malloc((mesa_vp
->Base
.NumInstructions
+ VSF_MAX_FRAGMENT_TEMPS
) * sizeof(struct prog_instruction
));
402 memset(vpi
, 0, VSF_MAX_FRAGMENT_TEMPS
* sizeof(struct prog_instruction
));
404 for (i
=0; i
< VSF_MAX_FRAGMENT_TEMPS
; i
++) {
405 vpi
[i
].Opcode
= OPCODE_MOV
;
406 vpi
[i
].StringPos
= 0;
409 vpi
[i
].DstReg
.File
= PROGRAM_TEMPORARY
;
410 vpi
[i
].DstReg
.Index
= i
;
411 vpi
[i
].DstReg
.WriteMask
= WRITEMASK_XYZW
;
412 vpi
[i
].DstReg
.CondMask
= COND_TR
;
414 vpi
[i
].SrcReg
[0].File
= PROGRAM_STATE_VAR
;
415 vpi
[i
].SrcReg
[0].Index
= 0;
416 vpi
[i
].SrcReg
[0].Swizzle
= MAKE_SWIZZLE4(SWIZZLE_ONE
, SWIZZLE_ONE
, SWIZZLE_ONE
, SWIZZLE_ONE
);
419 memcpy(&vpi
[i
], mesa_vp
->Base
.Instructions
, mesa_vp
->Base
.NumInstructions
* sizeof(struct prog_instruction
));
421 free(mesa_vp
->Base
.Instructions
);
423 mesa_vp
->Base
.Instructions
= vpi
;
425 mesa_vp
->Base
.NumInstructions
+= VSF_MAX_FRAGMENT_TEMPS
;
426 vpi
= &mesa_vp
->Base
.Instructions
[mesa_vp
->Base
.NumInstructions
-1];
428 assert(vpi
->Opcode
== OPCODE_END
);
431 if (mesa_vp
->IsPositionInvariant
) {
432 struct program_parameter_list
*paramList
;
433 GLint tokens
[6] = { STATE_MATRIX
, STATE_MVP
, 0, 0, 0, STATE_MATRIX
};
436 tokens
[5] = STATE_MATRIX
;
438 tokens
[5] = STATE_MATRIX_TRANSPOSE
;
440 paramList
= mesa_vp
->Base
.Parameters
;
442 vpi
= malloc((mesa_vp
->Base
.NumInstructions
+ 4) * sizeof(struct prog_instruction
));
443 memset(vpi
, 0, 4 * sizeof(struct prog_instruction
));
445 for (i
=0; i
< 4; i
++) {
447 tokens
[3] = tokens
[4] = i
;
448 idx
= _mesa_add_state_reference(paramList
, tokens
);
450 vpi
[i
].Opcode
= OPCODE_DP4
;
451 vpi
[i
].StringPos
= 0;
454 vpi
[i
].DstReg
.File
= PROGRAM_OUTPUT
;
455 vpi
[i
].DstReg
.Index
= VERT_RESULT_HPOS
;
456 vpi
[i
].DstReg
.WriteMask
= 1 << i
;
457 vpi
[i
].DstReg
.CondMask
= COND_TR
;
459 vpi
[i
].SrcReg
[0].File
= PROGRAM_STATE_VAR
;
460 vpi
[i
].SrcReg
[0].Index
= idx
;
461 vpi
[i
].SrcReg
[0].Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
, SWIZZLE_Z
, SWIZZLE_W
);
463 vpi
[i
].SrcReg
[1].File
= PROGRAM_INPUT
;
464 vpi
[i
].SrcReg
[1].Index
= VERT_ATTRIB_POS
;
465 vpi
[i
].SrcReg
[1].Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
, SWIZZLE_Z
, SWIZZLE_W
);
468 vpi
[i
].Opcode
= OPCODE_MUL
;
470 vpi
[i
].Opcode
= OPCODE_MAD
;
472 vpi
[i
].StringPos
= 0;
476 vpi
[i
].DstReg
.File
= PROGRAM_OUTPUT
;
478 vpi
[i
].DstReg
.File
= PROGRAM_TEMPORARY
;
479 vpi
[i
].DstReg
.Index
= 0;
480 vpi
[i
].DstReg
.WriteMask
= 0xf;
481 vpi
[i
].DstReg
.CondMask
= COND_TR
;
483 vpi
[i
].SrcReg
[0].File
= PROGRAM_STATE_VAR
;
484 vpi
[i
].SrcReg
[0].Index
= idx
;
485 vpi
[i
].SrcReg
[0].Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
, SWIZZLE_Z
, SWIZZLE_W
);
487 vpi
[i
].SrcReg
[1].File
= PROGRAM_INPUT
;
488 vpi
[i
].SrcReg
[1].Index
= VERT_ATTRIB_POS
;
489 vpi
[i
].SrcReg
[1].Swizzle
= MAKE_SWIZZLE4(i
, i
, i
, i
);
492 vpi
[i
].SrcReg
[2].File
= PROGRAM_TEMPORARY
;
493 vpi
[i
].SrcReg
[2].Index
= 0;
494 vpi
[i
].SrcReg
[2].Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
, SWIZZLE_Z
, SWIZZLE_W
);
499 memcpy(&vpi
[i
], mesa_vp
->Base
.Instructions
, mesa_vp
->Base
.NumInstructions
* sizeof(struct prog_instruction
));
501 free(mesa_vp
->Base
.Instructions
);
503 mesa_vp
->Base
.Instructions
= vpi
;
505 mesa_vp
->Base
.NumInstructions
+= 4;
506 vpi
= &mesa_vp
->Base
.Instructions
[mesa_vp
->Base
.NumInstructions
-1];
508 assert(vpi
->Opcode
== OPCODE_END
);
510 mesa_vp
->Base
.InputsRead
|= (1 << VERT_ATTRIB_POS
);
511 mesa_vp
->Base
.OutputsWritten
|= (1 << VERT_RESULT_HPOS
);
513 //fprintf(stderr, "IsPositionInvariant is set!\n");
514 //_mesa_print_program(&mesa_vp->Base);
517 vp
->pos_end
=0; /* Not supported yet */
518 vp
->program
.length
=0;
519 vp
->num_temporaries
=mesa_vp
->Base
.NumTemporaries
;
521 for(i
=0; i
< VERT_ATTRIB_MAX
; i
++)
524 for(i
=0; i
< VERT_RESULT_MAX
; i
++)
527 assert(mesa_vp
->Base
.OutputsWritten
& (1 << VERT_RESULT_HPOS
));
530 if(mesa_vp
->Base
.OutputsWritten
& (1 << VERT_RESULT_HPOS
))
531 vp
->outputs
[VERT_RESULT_HPOS
] = cur_reg
++;
533 if(mesa_vp
->Base
.OutputsWritten
& (1 << VERT_RESULT_PSIZ
))
534 vp
->outputs
[VERT_RESULT_PSIZ
] = cur_reg
++;
536 if(mesa_vp
->Base
.OutputsWritten
& (1 << VERT_RESULT_COL0
))
537 vp
->outputs
[VERT_RESULT_COL0
] = cur_reg
++;
539 if(mesa_vp
->Base
.OutputsWritten
& (1 << VERT_RESULT_COL1
))
540 vp
->outputs
[VERT_RESULT_COL1
] = cur_reg
++;
542 #if 0 /* Not supported yet */
543 if(mesa_vp
->Base
.OutputsWritten
& (1 << VERT_RESULT_BFC0
))
544 vp
->outputs
[VERT_RESULT_BFC0
] = cur_reg
++;
546 if(mesa_vp
->Base
.OutputsWritten
& (1 << VERT_RESULT_BFC1
))
547 vp
->outputs
[VERT_RESULT_BFC1
] = cur_reg
++;
549 if(mesa_vp
->Base
.OutputsWritten
& (1 << VERT_RESULT_FOGC
))
550 vp
->outputs
[VERT_RESULT_FOGC
] = cur_reg
++;
553 for(i
=VERT_RESULT_TEX0
; i
<= VERT_RESULT_TEX7
; i
++)
554 if(mesa_vp
->Base
.OutputsWritten
& (1 << i
))
555 vp
->outputs
[i
] = cur_reg
++;
557 vp
->translated
= GL_TRUE
;
558 vp
->native
= GL_TRUE
;
560 o_inst
=vp
->program
.body
.i
;
561 for(vpi
=mesa_vp
->Base
.Instructions
; vpi
->Opcode
!= OPCODE_END
; vpi
++, o_inst
++){
564 operands
=op_operands(vpi
->Opcode
);
565 are_srcs_scalar
=operands
& SCALAR_FLAG
;
568 for(i
=0; i
< operands
; i
++)
569 src
[i
]=vpi
->SrcReg
[i
];
571 if(operands
== 3){ /* TODO: scalars */
572 if( CMP_SRCS(src
[1], src
[2]) || CMP_SRCS(src
[0], src
[2]) ){
573 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, u_temp_i
,
574 VSF_FLAG_ALL
, VSF_OUT_CLASS_TMP
);
576 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[2]),
577 SWIZZLE_X
, SWIZZLE_Y
,
578 SWIZZLE_Z
, SWIZZLE_W
,
579 t_src_class(src
[2].File
), VSF_FLAG_NONE
);
581 o_inst
->src2
=ZERO_SRC_2
;
582 o_inst
->src3
=ZERO_SRC_2
;
585 src
[2].File
=PROGRAM_TEMPORARY
;
586 src
[2].Index
=u_temp_i
;
593 if( CMP_SRCS(src
[1], src
[0]) ){
594 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, u_temp_i
,
595 VSF_FLAG_ALL
, VSF_OUT_CLASS_TMP
);
597 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
598 SWIZZLE_X
, SWIZZLE_Y
,
599 SWIZZLE_Z
, SWIZZLE_W
,
600 t_src_class(src
[0].File
), VSF_FLAG_NONE
);
602 o_inst
->src2
=ZERO_SRC_0
;
603 o_inst
->src3
=ZERO_SRC_0
;
606 src
[0].File
=PROGRAM_TEMPORARY
;
607 src
[0].Index
=u_temp_i
;
612 /* These ops need special handling. */
615 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ARL
, t_dst_index(vp
, &vpi
->DstReg
),
616 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
617 o_inst
->src1
=t_src_scalar(vp
, &src
[0]);
618 o_inst
->src2
=ZERO_SRC_0
;
619 o_inst
->src3
=ZERO_SRC_0
;
623 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_POW
, t_dst_index(vp
, &vpi
->DstReg
),
624 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
625 o_inst
->src1
=t_src_scalar(vp
, &src
[0]);
626 o_inst
->src2
=ZERO_SRC_0
;
627 o_inst
->src3
=t_src_scalar(vp
, &src
[1]);
630 case OPCODE_MOV
://ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO}
632 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, t_dst_index(vp
, &vpi
->DstReg
),
633 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
634 o_inst
->src1
=t_src(vp
, &src
[0]);
635 o_inst
->src2
=ZERO_SRC_0
;
636 o_inst
->src3
=ZERO_SRC_0
;
638 hw_op
=(src
[0].File
== PROGRAM_TEMPORARY
) ? R300_VPI_OUT_OP_MAD_2
: R300_VPI_OUT_OP_MAD
;
640 o_inst
->op
=MAKE_VSF_OP(hw_op
, t_dst_index(vp
, &vpi
->DstReg
),
641 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
642 o_inst
->src1
=t_src(vp
, &src
[0]);
643 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
644 SWIZZLE_ONE
, SWIZZLE_ONE
,
645 SWIZZLE_ONE
, SWIZZLE_ONE
,
646 t_src_class(src
[0].File
), VSF_FLAG_NONE
);
649 o_inst
->src3
=ZERO_SRC_0
;
656 hw_op
=(src
[0].File
== PROGRAM_TEMPORARY
&&
657 src
[1].File
== PROGRAM_TEMPORARY
) ? R300_VPI_OUT_OP_MAD_2
: R300_VPI_OUT_OP_MAD
;
659 o_inst
->op
=MAKE_VSF_OP(hw_op
, t_dst_index(vp
, &vpi
->DstReg
),
660 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
661 o_inst
->src1
=ONE_SRC_0
;
662 o_inst
->src2
=t_src(vp
, &src
[0]);
663 o_inst
->src3
=t_src(vp
, &src
[1]);
665 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, t_dst_index(vp
, &vpi
->DstReg
),
666 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
667 o_inst
->src1
=t_src(vp
, &src
[0]);
668 o_inst
->src2
=t_src(vp
, &src
[1]);
669 o_inst
->src3
=ZERO_SRC_1
;
675 hw_op
=(src
[0].File
== PROGRAM_TEMPORARY
&&
676 src
[1].File
== PROGRAM_TEMPORARY
&&
677 src
[2].File
== PROGRAM_TEMPORARY
) ? R300_VPI_OUT_OP_MAD_2
: R300_VPI_OUT_OP_MAD
;
679 o_inst
->op
=MAKE_VSF_OP(hw_op
, t_dst_index(vp
, &vpi
->DstReg
),
680 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
681 o_inst
->src1
=t_src(vp
, &src
[0]);
682 o_inst
->src2
=t_src(vp
, &src
[1]);
683 o_inst
->src3
=t_src(vp
, &src
[2]);
686 case OPCODE_MUL
: /* HW mul can take third arg but appears to have some other limitations. */
687 hw_op
=(src
[0].File
== PROGRAM_TEMPORARY
&&
688 src
[1].File
== PROGRAM_TEMPORARY
) ? R300_VPI_OUT_OP_MAD_2
: R300_VPI_OUT_OP_MAD
;
690 o_inst
->op
=MAKE_VSF_OP(hw_op
, t_dst_index(vp
, &vpi
->DstReg
),
691 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
692 o_inst
->src1
=t_src(vp
, &src
[0]);
693 o_inst
->src2
=t_src(vp
, &src
[1]);
695 o_inst
->src3
=ZERO_SRC_1
;
698 case OPCODE_DP3
://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO}
699 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT
, t_dst_index(vp
, &vpi
->DstReg
),
700 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
702 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
703 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
704 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)),
705 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)),
707 t_src_class(src
[0].File
),
708 src
[0].NegateBase
? VSF_FLAG_XYZ
: VSF_FLAG_NONE
);
710 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[1]),
711 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)),
712 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)),
713 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)),
715 t_src_class(src
[1].File
),
716 src
[1].NegateBase
? VSF_FLAG_XYZ
: VSF_FLAG_NONE
);
718 o_inst
->src3
=ZERO_SRC_1
;
721 case 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
723 hw_op
=(src
[0].File
== PROGRAM_TEMPORARY
&&
724 src
[1].File
== PROGRAM_TEMPORARY
) ? R300_VPI_OUT_OP_MAD_2
: R300_VPI_OUT_OP_MAD
;
726 o_inst
->op
=MAKE_VSF_OP(hw_op
, t_dst_index(vp
, &vpi
->DstReg
),
727 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
728 o_inst
->src1
=t_src(vp
, &src
[0]);
729 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
730 SWIZZLE_ONE
, SWIZZLE_ONE
,
731 SWIZZLE_ONE
, SWIZZLE_ONE
,
732 t_src_class(src
[0].File
), VSF_FLAG_NONE
);
733 o_inst
->src3
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[1]),
734 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)),
735 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)),
736 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)),
737 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)),
738 t_src_class(src
[1].File
),
739 (!src
[1].NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
741 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, t_dst_index(vp
, &vpi
->DstReg
),
742 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
744 o_inst
->src1
=t_src(vp
, &src
[0]);
745 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[1]),
746 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)),
747 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)),
748 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)),
749 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)),
750 t_src_class(src
[1].File
),
751 (!src
[1].NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
756 case 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
757 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_MAX
, t_dst_index(vp
, &vpi
->DstReg
),
758 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
760 o_inst
->src1
=t_src(vp
, &src
[0]);
761 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
762 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
763 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)),
764 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)),
765 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)),
766 t_src_class(src
[0].File
),
767 (!src
[0].NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
772 /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W}
773 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 */
775 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_FRC
, u_temp_i
,
776 t_dst_mask(vpi
->DstReg
.WriteMask
), VSF_OUT_CLASS_TMP
);
778 o_inst
->src1
=t_src(vp
, &src
[0]);
779 o_inst
->src2
=ZERO_SRC_0
;
780 o_inst
->src3
=ZERO_SRC_0
;
783 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, t_dst_index(vp
, &vpi
->DstReg
),
784 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
786 o_inst
->src1
=t_src(vp
, &src
[0]);
787 o_inst
->src2
=MAKE_VSF_SOURCE(u_temp_i
,
793 /* Not 100% sure about this */
794 (!src
[1].NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
/*VSF_FLAG_ALL*/);
796 o_inst
->src3
=ZERO_SRC_0
;
800 case OPCODE_LG2
:// LG2 RESULT 1.X Y Z W PARAM 0{} {X X X X}
801 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_LG2
, t_dst_index(vp
, &vpi
->DstReg
),
802 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
804 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
805 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
806 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
807 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
808 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
809 t_src_class(src
[0].File
),
810 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
811 o_inst
->src2
=ZERO_SRC_0
;
812 o_inst
->src3
=ZERO_SRC_0
;
815 case OPCODE_LIT
://LIT TMP 1.Y Z TMP 1{} {X W Z Y} TMP 1{} {Y W Z X} TMP 1{} {Y X Z W}
816 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_LIT
, t_dst_index(vp
, &vpi
->DstReg
),
817 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
818 /* NOTE: Users swizzling might not work. */
819 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
820 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // x
821 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // w
822 VSF_IN_COMPONENT_ZERO
, // z
823 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // y
824 t_src_class(src
[0].File
),
825 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
826 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
827 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // y
828 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // w
829 VSF_IN_COMPONENT_ZERO
, // z
830 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // x
831 t_src_class(src
[0].File
),
832 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
833 o_inst
->src3
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
834 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // y
835 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // x
836 VSF_IN_COMPONENT_ZERO
, // z
837 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // w
838 t_src_class(src
[0].File
),
839 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
842 case OPCODE_DPH
://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W}
843 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT
, t_dst_index(vp
, &vpi
->DstReg
),
844 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
846 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
847 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
848 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)),
849 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)),
850 VSF_IN_COMPONENT_ONE
,
851 t_src_class(src
[0].File
),
852 src
[0].NegateBase
? VSF_FLAG_XYZ
: VSF_FLAG_NONE
);
853 o_inst
->src2
=t_src(vp
, &src
[1]);
854 o_inst
->src3
=ZERO_SRC_1
;
858 /* mul r0, r1.yzxw, r2.zxyw
859 mad r0, -r2.yzxw, r1.zxyw, r0
860 NOTE: might need MAD_2
863 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_MAD
, u_temp_i
,
864 t_dst_mask(vpi
->DstReg
.WriteMask
), VSF_OUT_CLASS_TMP
);
866 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
867 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // y
868 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)), // z
869 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // x
870 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // w
871 t_src_class(src
[0].File
),
872 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
874 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[1]),
875 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)), // z
876 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)), // x
877 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)), // y
878 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)), // w
879 t_src_class(src
[1].File
),
880 src
[1].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
882 o_inst
->src3
=ZERO_SRC_1
;
886 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_MAD
, t_dst_index(vp
, &vpi
->DstReg
),
887 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
889 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[1]),
890 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)), // y
891 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)), // z
892 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)), // x
893 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)), // w
894 t_src_class(src
[1].File
),
895 (!src
[1].NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
897 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
898 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)), // z
899 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // x
900 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // y
901 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // w
902 t_src_class(src
[0].File
),
903 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
);
905 o_inst
->src3
=MAKE_VSF_SOURCE(u_temp_i
+1,
916 fprintf(stderr
, "Dont know how to handle op %d yet\n", vpi
->Opcode
);
925 o_inst
->op
=MAKE_VSF_OP(t_opcode(vpi
->Opcode
), t_dst_index(vp
, &vpi
->DstReg
),
926 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
931 o_inst
->src1
=t_src_scalar(vp
, &src
[0]);
932 o_inst
->src2
=ZERO_SRC_0
;
933 o_inst
->src3
=ZERO_SRC_0
;
937 o_inst
->src1
=t_src_scalar(vp
, &src
[0]);
938 o_inst
->src2
=t_src_scalar(vp
, &src
[1]);
939 o_inst
->src3
=ZERO_SRC_1
;
943 o_inst
->src1
=t_src_scalar(vp
, &src
[0]);
944 o_inst
->src2
=t_src_scalar(vp
, &src
[1]);
945 o_inst
->src3
=t_src_scalar(vp
, &src
[2]);
949 fprintf(stderr
, "scalars and op RCC not handled yet");
956 o_inst
->src1
=t_src(vp
, &src
[0]);
957 o_inst
->src2
=ZERO_SRC_0
;
958 o_inst
->src3
=ZERO_SRC_0
;
962 o_inst
->src1
=t_src(vp
, &src
[0]);
963 o_inst
->src2
=t_src(vp
, &src
[1]);
964 o_inst
->src3
=ZERO_SRC_1
;
968 o_inst
->src1
=t_src(vp
, &src
[0]);
969 o_inst
->src2
=t_src(vp
, &src
[1]);
970 o_inst
->src3
=t_src(vp
, &src
[2]);
974 fprintf(stderr
, "scalars and op RCC not handled yet");
982 /* Will most likely segfault before we get here... fix later. */
983 if(o_inst
- vp
->program
.body
.i
>= VSF_MAX_FRAGMENT_LENGTH
/4) {
984 vp
->program
.length
= 0;
985 vp
->native
= GL_FALSE
;
988 vp
->program
.length
=(o_inst
- vp
->program
.body
.i
) * 4;
990 fprintf(stderr
, "hw program:\n");
991 for(i
=0; i
< vp
->program
.length
; i
++)
992 fprintf(stderr
, "%08x\n", vp
->program
.body
.d
[i
]);