1 /**************************************************************************
3 Copyright (C) 2005 Aapo Tahkola <aet@rasterburn.org>
4 Copyright (C) 2008 Oliver McFadden <z3ro.geek@gmail.com>
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
27 **************************************************************************/
29 /* Radeon R5xx Acceleration, Revision 1.2 */
31 #include "main/glheader.h"
32 #include "main/macros.h"
33 #include "main/enums.h"
34 #include "shader/program.h"
35 #include "shader/prog_instruction.h"
36 #include "shader/prog_parameter.h"
37 #include "shader/prog_statevars.h"
40 #include "r300_context.h"
42 /* TODO: Get rid of t_src_class call */
43 #define CMP_SRCS(a, b) ((a.RelAddr != b.RelAddr) || (a.Index != b.Index && \
44 ((t_src_class(a.File) == PVS_SRC_REG_CONSTANT && \
45 t_src_class(b.File) == PVS_SRC_REG_CONSTANT) || \
46 (t_src_class(a.File) == PVS_SRC_REG_INPUT && \
47 t_src_class(b.File) == PVS_SRC_REG_INPUT)))) \
50 * Take an already-setup and valid source then swizzle it appropriately to
51 * obtain a constant ZERO or ONE source.
53 #define __CONST(x, y) \
54 (PVS_SRC_OPERAND(t_src_index(vp, &src[x]), \
59 t_src_class(src[x].File), \
60 VSF_FLAG_NONE) | (src[x].RelAddr << 4))
62 #define FREE_TEMPS() \
64 int u_temp_used = (VSF_MAX_FRAGMENT_TEMPS - 1) - u_temp_i; \
65 if((vp->num_temporaries + u_temp_used) > VSF_MAX_FRAGMENT_TEMPS) { \
66 WARN_ONCE("Ran out of temps, num temps %d, us %d\n", vp->num_temporaries, u_temp_used); \
67 vp->native = GL_FALSE; \
69 u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; \
72 int r300VertexProgUpdateParams(GLcontext
* ctx
,
73 struct r300_vertex_program_cont
*vp
, float *dst
)
76 struct gl_vertex_program
*mesa_vp
= &vp
->mesa_program
;
78 struct gl_program_parameter_list
*paramList
;
80 if (mesa_vp
->IsNVProgram
) {
81 _mesa_load_tracked_matrices(ctx
);
83 for (pi
= 0; pi
< MAX_NV_VERTEX_PROGRAM_PARAMS
; pi
++) {
84 *dst
++ = ctx
->VertexProgram
.Parameters
[pi
][0];
85 *dst
++ = ctx
->VertexProgram
.Parameters
[pi
][1];
86 *dst
++ = ctx
->VertexProgram
.Parameters
[pi
][2];
87 *dst
++ = ctx
->VertexProgram
.Parameters
[pi
][3];
92 assert(mesa_vp
->Base
.Parameters
);
93 _mesa_load_state_parameters(ctx
, mesa_vp
->Base
.Parameters
);
95 if (mesa_vp
->Base
.Parameters
->NumParameters
* 4 >
96 VSF_MAX_FRAGMENT_LENGTH
) {
97 fprintf(stderr
, "%s:Params exhausted\n", __FUNCTION__
);
101 paramList
= mesa_vp
->Base
.Parameters
;
102 for (pi
= 0; pi
< paramList
->NumParameters
; pi
++) {
103 switch (paramList
->Parameters
[pi
].Type
) {
104 case PROGRAM_STATE_VAR
:
105 case PROGRAM_NAMED_PARAM
:
106 //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
107 case PROGRAM_CONSTANT
:
108 *dst
++ = paramList
->ParameterValues
[pi
][0];
109 *dst
++ = paramList
->ParameterValues
[pi
][1];
110 *dst
++ = paramList
->ParameterValues
[pi
][2];
111 *dst
++ = paramList
->ParameterValues
[pi
][3];
114 _mesa_problem(NULL
, "Bad param type in %s",
123 static unsigned long t_dst_mask(GLuint mask
)
125 /* WRITEMASK_* is equivalent to VSF_FLAG_* */
126 return mask
& VSF_FLAG_ALL
;
129 static unsigned long t_dst_class(gl_register_file file
)
133 case PROGRAM_TEMPORARY
:
134 return PVS_DST_REG_TEMPORARY
;
136 return PVS_DST_REG_OUT
;
137 case PROGRAM_ADDRESS
:
138 return PVS_DST_REG_A0
;
141 case PROGRAM_LOCAL_PARAM:
142 case PROGRAM_ENV_PARAM:
143 case PROGRAM_NAMED_PARAM:
144 case PROGRAM_STATE_VAR:
145 case PROGRAM_WRITE_ONLY:
146 case PROGRAM_ADDRESS:
149 fprintf(stderr
, "problem in %s", __FUNCTION__
);
155 static unsigned long t_dst_index(struct r300_vertex_program
*vp
,
156 struct prog_dst_register
*dst
)
158 if (dst
->File
== PROGRAM_OUTPUT
)
159 return vp
->outputs
[dst
->Index
];
164 static unsigned long t_src_class(gl_register_file file
)
167 case PROGRAM_TEMPORARY
:
168 return PVS_SRC_REG_TEMPORARY
;
170 return PVS_SRC_REG_INPUT
;
171 case PROGRAM_LOCAL_PARAM
:
172 case PROGRAM_ENV_PARAM
:
173 case PROGRAM_NAMED_PARAM
:
174 case PROGRAM_CONSTANT
:
175 case PROGRAM_STATE_VAR
:
176 return PVS_SRC_REG_CONSTANT
;
179 case PROGRAM_WRITE_ONLY:
180 case PROGRAM_ADDRESS:
183 fprintf(stderr
, "problem in %s", __FUNCTION__
);
189 static INLINE
unsigned long t_swizzle(GLubyte swizzle
)
191 /* this is in fact a NOP as the Mesa SWIZZLE_* are all identical to VSF_IN_COMPONENT_* */
196 static void vp_dump_inputs(struct r300_vertex_program
*vp
, char *caller
)
201 fprintf(stderr
, "vp null in call to %s from %s\n", __FUNCTION__
,
206 fprintf(stderr
, "%s:<", caller
);
207 for (i
= 0; i
< VERT_ATTRIB_MAX
; i
++)
208 fprintf(stderr
, "%d ", vp
->inputs
[i
]);
209 fprintf(stderr
, ">\n");
214 static unsigned long t_src_index(struct r300_vertex_program
*vp
,
215 struct prog_src_register
*src
)
220 if (src
->File
== PROGRAM_INPUT
) {
221 if (vp
->inputs
[src
->Index
] != -1)
222 return vp
->inputs
[src
->Index
];
224 for (i
= 0; i
< VERT_ATTRIB_MAX
; i
++)
225 if (vp
->inputs
[i
] > max_reg
)
226 max_reg
= vp
->inputs
[i
];
228 vp
->inputs
[src
->Index
] = max_reg
+ 1;
230 //vp_dump_inputs(vp, __FUNCTION__);
232 return vp
->inputs
[src
->Index
];
234 if (src
->Index
< 0) {
236 "negative offsets for indirect addressing do not work.\n");
243 /* these two functions should probably be merged... */
245 static unsigned long t_src(struct r300_vertex_program
*vp
,
246 struct prog_src_register
*src
)
248 /* src->NegateBase uses the NEGATE_ flags from program_instruction.h,
249 * which equal our VSF_FLAGS_ values, so it's safe to just pass it here.
251 return PVS_SRC_OPERAND(t_src_index(vp
, src
),
252 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
253 t_swizzle(GET_SWZ(src
->Swizzle
, 1)),
254 t_swizzle(GET_SWZ(src
->Swizzle
, 2)),
255 t_swizzle(GET_SWZ(src
->Swizzle
, 3)),
256 t_src_class(src
->File
),
257 src
->NegateBase
) | (src
->RelAddr
<< 4);
260 static unsigned long t_src_scalar(struct r300_vertex_program
*vp
,
261 struct prog_src_register
*src
)
263 /* src->NegateBase uses the NEGATE_ flags from program_instruction.h,
264 * which equal our VSF_FLAGS_ values, so it's safe to just pass it here.
266 return PVS_SRC_OPERAND(t_src_index(vp
, src
),
267 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
268 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
269 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
270 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
271 t_src_class(src
->File
),
273 NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
277 static GLboolean
valid_dst(struct r300_vertex_program
*vp
,
278 struct prog_dst_register
*dst
)
280 if (dst
->File
== PROGRAM_OUTPUT
&& vp
->outputs
[dst
->Index
] == -1) {
282 } else if (dst
->File
== PROGRAM_ADDRESS
) {
283 assert(dst
->Index
== 0);
289 static GLuint
*r300TranslateOpcodeABS(struct r300_vertex_program
*vp
,
290 struct prog_instruction
*vpi
,
292 struct prog_src_register src
[3])
294 //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
296 inst
[0] = PVS_OP_DST_OPERAND(VE_MAXIMUM
,
299 t_dst_index(vp
, &vpi
->DstReg
),
300 t_dst_mask(vpi
->DstReg
.WriteMask
),
301 t_dst_class(vpi
->DstReg
.File
));
302 inst
[1] = t_src(vp
, &src
[0]);
303 inst
[2] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[0]),
304 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
305 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)),
306 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)),
307 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)),
308 t_src_class(src
[0].File
),
310 NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
311 (src
[0].RelAddr
<< 4);
317 static GLuint
*r300TranslateOpcodeADD(struct r300_vertex_program
*vp
,
318 struct prog_instruction
*vpi
,
320 struct prog_src_register src
[3])
322 inst
[0] = PVS_OP_DST_OPERAND(VE_ADD
,
325 t_dst_index(vp
, &vpi
->DstReg
),
326 t_dst_mask(vpi
->DstReg
.WriteMask
),
327 t_dst_class(vpi
->DstReg
.File
));
328 inst
[1] = t_src(vp
, &src
[0]);
329 inst
[2] = t_src(vp
, &src
[1]);
330 inst
[3] = __CONST(1, SWIZZLE_ZERO
);
335 static GLuint
*r300TranslateOpcodeARL(struct r300_vertex_program
*vp
,
336 struct prog_instruction
*vpi
,
338 struct prog_src_register src
[3])
340 inst
[0] = PVS_OP_DST_OPERAND(VE_FLT2FIX_DX
,
343 t_dst_index(vp
, &vpi
->DstReg
),
344 t_dst_mask(vpi
->DstReg
.WriteMask
),
345 t_dst_class(vpi
->DstReg
.File
));
346 inst
[1] = t_src(vp
, &src
[0]);
347 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
348 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
353 static GLuint
*r300TranslateOpcodeDP3(struct r300_vertex_program
*vp
,
354 struct prog_instruction
*vpi
,
356 struct prog_src_register src
[3])
358 //DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO}
360 inst
[0] = PVS_OP_DST_OPERAND(VE_DOT_PRODUCT
,
363 t_dst_index(vp
, &vpi
->DstReg
),
364 t_dst_mask(vpi
->DstReg
.WriteMask
),
365 t_dst_class(vpi
->DstReg
.File
));
366 inst
[1] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[0]),
367 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
368 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)),
369 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)),
371 t_src_class(src
[0].File
),
373 NegateBase
? VSF_FLAG_XYZ
: VSF_FLAG_NONE
) |
374 (src
[0].RelAddr
<< 4);
376 PVS_SRC_OPERAND(t_src_index(vp
, &src
[1]),
377 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)),
378 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)),
379 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)), SWIZZLE_ZERO
,
380 t_src_class(src
[1].File
),
382 NegateBase
? VSF_FLAG_XYZ
: VSF_FLAG_NONE
) |
383 (src
[1].RelAddr
<< 4);
384 inst
[3] = __CONST(1, SWIZZLE_ZERO
);
389 static GLuint
*r300TranslateOpcodeDP4(struct r300_vertex_program
*vp
,
390 struct prog_instruction
*vpi
,
392 struct prog_src_register src
[3])
394 inst
[0] = PVS_OP_DST_OPERAND(VE_DOT_PRODUCT
,
397 t_dst_index(vp
, &vpi
->DstReg
),
398 t_dst_mask(vpi
->DstReg
.WriteMask
),
399 t_dst_class(vpi
->DstReg
.File
));
400 inst
[1] = t_src(vp
, &src
[0]);
401 inst
[2] = t_src(vp
, &src
[1]);
402 inst
[3] = __CONST(1, SWIZZLE_ZERO
);
407 static GLuint
*r300TranslateOpcodeDPH(struct r300_vertex_program
*vp
,
408 struct prog_instruction
*vpi
,
410 struct prog_src_register src
[3])
412 //DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W}
413 inst
[0] = PVS_OP_DST_OPERAND(VE_DOT_PRODUCT
,
416 t_dst_index(vp
, &vpi
->DstReg
),
417 t_dst_mask(vpi
->DstReg
.WriteMask
),
418 t_dst_class(vpi
->DstReg
.File
));
419 inst
[1] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[0]),
420 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
421 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)),
422 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)),
423 PVS_SRC_SELECT_FORCE_1
,
424 t_src_class(src
[0].File
),
426 NegateBase
? VSF_FLAG_XYZ
: VSF_FLAG_NONE
) |
427 (src
[0].RelAddr
<< 4);
428 inst
[2] = t_src(vp
, &src
[1]);
429 inst
[3] = __CONST(1, SWIZZLE_ZERO
);
434 static GLuint
*r300TranslateOpcodeDST(struct r300_vertex_program
*vp
,
435 struct prog_instruction
*vpi
,
437 struct prog_src_register src
[3])
439 inst
[0] = PVS_OP_DST_OPERAND(VE_DISTANCE_VECTOR
,
442 t_dst_index(vp
, &vpi
->DstReg
),
443 t_dst_mask(vpi
->DstReg
.WriteMask
),
444 t_dst_class(vpi
->DstReg
.File
));
445 inst
[1] = t_src(vp
, &src
[0]);
446 inst
[2] = t_src(vp
, &src
[1]);
447 inst
[3] = __CONST(1, SWIZZLE_ZERO
);
452 static GLuint
*r300TranslateOpcodeEX2(struct r300_vertex_program
*vp
,
453 struct prog_instruction
*vpi
,
455 struct prog_src_register src
[3])
457 inst
[0] = PVS_OP_DST_OPERAND(ME_EXP_BASE2_FULL_DX
,
460 t_dst_index(vp
, &vpi
->DstReg
),
461 t_dst_mask(vpi
->DstReg
.WriteMask
),
462 t_dst_class(vpi
->DstReg
.File
));
463 inst
[1] = t_src_scalar(vp
, &src
[0]);
464 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
465 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
470 static GLuint
*r300TranslateOpcodeEXP(struct r300_vertex_program
*vp
,
471 struct prog_instruction
*vpi
,
473 struct prog_src_register src
[3])
475 inst
[0] = PVS_OP_DST_OPERAND(ME_EXP_BASE2_DX
,
478 t_dst_index(vp
, &vpi
->DstReg
),
479 t_dst_mask(vpi
->DstReg
.WriteMask
),
480 t_dst_class(vpi
->DstReg
.File
));
481 inst
[1] = t_src_scalar(vp
, &src
[0]);
482 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
483 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
488 static GLuint
*r300TranslateOpcodeFLR(struct r300_vertex_program
*vp
,
489 struct prog_instruction
*vpi
,
491 struct prog_src_register src
[3],
494 /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W}
495 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 */
497 inst
[0] = PVS_OP_DST_OPERAND(VE_FRACTION
,
501 t_dst_mask(vpi
->DstReg
.WriteMask
),
502 PVS_DST_REG_TEMPORARY
);
503 inst
[1] = t_src(vp
, &src
[0]);
504 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
505 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
508 inst
[0] = PVS_OP_DST_OPERAND(VE_ADD
,
511 t_dst_index(vp
, &vpi
->DstReg
),
512 t_dst_mask(vpi
->DstReg
.WriteMask
),
513 t_dst_class(vpi
->DstReg
.File
));
514 inst
[1] = t_src(vp
, &src
[0]);
515 inst
[2] = PVS_SRC_OPERAND(*u_temp_i
,
519 PVS_SRC_SELECT_W
, PVS_SRC_REG_TEMPORARY
,
520 /* Not 100% sure about this */
522 NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
524 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
530 static GLuint
*r300TranslateOpcodeFRC(struct r300_vertex_program
*vp
,
531 struct prog_instruction
*vpi
,
533 struct prog_src_register src
[3])
535 inst
[0] = PVS_OP_DST_OPERAND(VE_FRACTION
,
538 t_dst_index(vp
, &vpi
->DstReg
),
539 t_dst_mask(vpi
->DstReg
.WriteMask
),
540 t_dst_class(vpi
->DstReg
.File
));
541 inst
[1] = t_src(vp
, &src
[0]);
542 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
543 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
548 static GLuint
*r300TranslateOpcodeLG2(struct r300_vertex_program
*vp
,
549 struct prog_instruction
*vpi
,
551 struct prog_src_register src
[3])
553 // LG2 RESULT 1.X Y Z W PARAM 0{} {X X X X}
555 inst
[0] = PVS_OP_DST_OPERAND(ME_LOG_BASE2_FULL_DX
,
558 t_dst_index(vp
, &vpi
->DstReg
),
559 t_dst_mask(vpi
->DstReg
.WriteMask
),
560 t_dst_class(vpi
->DstReg
.File
));
561 inst
[1] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[0]),
562 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
563 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
564 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
565 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
566 t_src_class(src
[0].File
),
568 NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
569 (src
[0].RelAddr
<< 4);
570 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
571 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
576 static GLuint
*r300TranslateOpcodeLIT(struct r300_vertex_program
*vp
,
577 struct prog_instruction
*vpi
,
579 struct prog_src_register src
[3])
581 //LIT TMP 1.Y Z TMP 1{} {X W Z Y} TMP 1{} {Y W Z X} TMP 1{} {Y X Z W}
583 inst
[0] = PVS_OP_DST_OPERAND(ME_LIGHT_COEFF_DX
,
586 t_dst_index(vp
, &vpi
->DstReg
),
587 t_dst_mask(vpi
->DstReg
.WriteMask
),
588 t_dst_class(vpi
->DstReg
.File
));
589 /* NOTE: Users swizzling might not work. */
590 inst
[1] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[0]), t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // X
591 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // W
592 PVS_SRC_SELECT_FORCE_0
, // Z
593 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // Y
594 t_src_class(src
[0].File
),
596 NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
597 (src
[0].RelAddr
<< 4);
598 inst
[2] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[0]), t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // Y
599 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // W
600 PVS_SRC_SELECT_FORCE_0
, // Z
601 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // X
602 t_src_class(src
[0].File
),
604 NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
605 (src
[0].RelAddr
<< 4);
606 inst
[3] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[0]), t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // Y
607 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // X
608 PVS_SRC_SELECT_FORCE_0
, // Z
609 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // W
610 t_src_class(src
[0].File
),
612 NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
613 (src
[0].RelAddr
<< 4);
618 static GLuint
*r300TranslateOpcodeLOG(struct r300_vertex_program
*vp
,
619 struct prog_instruction
*vpi
,
621 struct prog_src_register src
[3])
623 inst
[0] = PVS_OP_DST_OPERAND(ME_LOG_BASE2_DX
,
626 t_dst_index(vp
, &vpi
->DstReg
),
627 t_dst_mask(vpi
->DstReg
.WriteMask
),
628 t_dst_class(vpi
->DstReg
.File
));
629 inst
[1] = t_src_scalar(vp
, &src
[0]);
630 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
631 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
636 static GLuint
*r300TranslateOpcodeMAD(struct r300_vertex_program
*vp
,
637 struct prog_instruction
*vpi
,
639 struct prog_src_register src
[3])
641 inst
[0] = PVS_OP_DST_OPERAND(PVS_MACRO_OP_2CLK_MADD
,
644 t_dst_index(vp
, &vpi
->DstReg
),
645 t_dst_mask(vpi
->DstReg
.WriteMask
),
646 t_dst_class(vpi
->DstReg
.File
));
647 inst
[1] = t_src(vp
, &src
[0]);
648 inst
[2] = t_src(vp
, &src
[1]);
649 inst
[3] = t_src(vp
, &src
[2]);
654 static GLuint
*r300TranslateOpcodeMAX(struct r300_vertex_program
*vp
,
655 struct prog_instruction
*vpi
,
657 struct prog_src_register src
[3])
659 inst
[0] = PVS_OP_DST_OPERAND(VE_MAXIMUM
,
662 t_dst_index(vp
, &vpi
->DstReg
),
663 t_dst_mask(vpi
->DstReg
.WriteMask
),
664 t_dst_class(vpi
->DstReg
.File
));
665 inst
[1] = t_src(vp
, &src
[0]);
666 inst
[2] = t_src(vp
, &src
[1]);
667 inst
[3] = __CONST(1, SWIZZLE_ZERO
);
672 static GLuint
*r300TranslateOpcodeMIN(struct r300_vertex_program
*vp
,
673 struct prog_instruction
*vpi
,
675 struct prog_src_register src
[3])
677 inst
[0] = PVS_OP_DST_OPERAND(VE_MINIMUM
,
680 t_dst_index(vp
, &vpi
->DstReg
),
681 t_dst_mask(vpi
->DstReg
.WriteMask
),
682 t_dst_class(vpi
->DstReg
.File
));
683 inst
[1] = t_src(vp
, &src
[0]);
684 inst
[2] = t_src(vp
, &src
[1]);
685 inst
[3] = __CONST(1, SWIZZLE_ZERO
);
690 static GLuint
*r300TranslateOpcodeMOV(struct r300_vertex_program
*vp
,
691 struct prog_instruction
*vpi
,
693 struct prog_src_register src
[3])
695 //ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO}
697 inst
[0] = PVS_OP_DST_OPERAND(VE_ADD
,
700 t_dst_index(vp
, &vpi
->DstReg
),
701 t_dst_mask(vpi
->DstReg
.WriteMask
),
702 t_dst_class(vpi
->DstReg
.File
));
703 inst
[1] = t_src(vp
, &src
[0]);
704 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
705 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
710 static GLuint
*r300TranslateOpcodeMUL(struct r300_vertex_program
*vp
,
711 struct prog_instruction
*vpi
,
713 struct prog_src_register src
[3])
715 inst
[0] = PVS_OP_DST_OPERAND(VE_MULTIPLY
,
718 t_dst_index(vp
, &vpi
->DstReg
),
719 t_dst_mask(vpi
->DstReg
.WriteMask
),
720 t_dst_class(vpi
->DstReg
.File
));
721 inst
[1] = t_src(vp
, &src
[0]);
722 inst
[2] = t_src(vp
, &src
[1]);
723 inst
[3] = __CONST(1, SWIZZLE_ZERO
);
728 static GLuint
*r300TranslateOpcodePOW(struct r300_vertex_program
*vp
,
729 struct prog_instruction
*vpi
,
731 struct prog_src_register src
[3])
733 inst
[0] = PVS_OP_DST_OPERAND(ME_POWER_FUNC_FF
,
736 t_dst_index(vp
, &vpi
->DstReg
),
737 t_dst_mask(vpi
->DstReg
.WriteMask
),
738 t_dst_class(vpi
->DstReg
.File
));
739 inst
[1] = t_src_scalar(vp
, &src
[0]);
740 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
741 inst
[3] = t_src_scalar(vp
, &src
[1]);
746 static GLuint
*r300TranslateOpcodeRCP(struct r300_vertex_program
*vp
,
747 struct prog_instruction
*vpi
,
749 struct prog_src_register src
[3])
751 inst
[0] = PVS_OP_DST_OPERAND(ME_RECIP_DX
,
754 t_dst_index(vp
, &vpi
->DstReg
),
755 t_dst_mask(vpi
->DstReg
.WriteMask
),
756 t_dst_class(vpi
->DstReg
.File
));
757 inst
[1] = t_src_scalar(vp
, &src
[0]);
758 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
759 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
764 static GLuint
*r300TranslateOpcodeRSQ(struct r300_vertex_program
*vp
,
765 struct prog_instruction
*vpi
,
767 struct prog_src_register src
[3])
769 inst
[0] = PVS_OP_DST_OPERAND(ME_RECIP_SQRT_DX
,
772 t_dst_index(vp
, &vpi
->DstReg
),
773 t_dst_mask(vpi
->DstReg
.WriteMask
),
774 t_dst_class(vpi
->DstReg
.File
));
775 inst
[1] = t_src_scalar(vp
, &src
[0]);
776 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
777 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
782 static GLuint
*r300TranslateOpcodeSGE(struct r300_vertex_program
*vp
,
783 struct prog_instruction
*vpi
,
785 struct prog_src_register src
[3])
787 inst
[0] = PVS_OP_DST_OPERAND(VE_SET_GREATER_THAN_EQUAL
,
790 t_dst_index(vp
, &vpi
->DstReg
),
791 t_dst_mask(vpi
->DstReg
.WriteMask
),
792 t_dst_class(vpi
->DstReg
.File
));
793 inst
[1] = t_src(vp
, &src
[0]);
794 inst
[2] = t_src(vp
, &src
[1]);
795 inst
[3] = __CONST(1, SWIZZLE_ZERO
);
800 static GLuint
*r300TranslateOpcodeSLT(struct r300_vertex_program
*vp
,
801 struct prog_instruction
*vpi
,
803 struct prog_src_register src
[3])
805 inst
[0] = PVS_OP_DST_OPERAND(VE_SET_LESS_THAN
,
808 t_dst_index(vp
, &vpi
->DstReg
),
809 t_dst_mask(vpi
->DstReg
.WriteMask
),
810 t_dst_class(vpi
->DstReg
.File
));
811 inst
[1] = t_src(vp
, &src
[0]);
812 inst
[2] = t_src(vp
, &src
[1]);
813 inst
[3] = __CONST(1, SWIZZLE_ZERO
);
818 static GLuint
*r300TranslateOpcodeSUB(struct r300_vertex_program
*vp
,
819 struct prog_instruction
*vpi
,
821 struct prog_src_register src
[3])
823 //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
826 inst
[0] = PVS_OP_DST_OPERAND(VE_ADD
,
829 t_dst_index(vp
, &vpi
->DstReg
),
830 t_dst_mask(vpi
->DstReg
.WriteMask
),
831 t_dst_class(vpi
->DstReg
.File
));
832 inst
[1] = t_src(vp
, &src
[0]);
833 inst
[2] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[1]),
834 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)),
835 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)),
836 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)),
837 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)),
838 t_src_class(src
[1].File
),
840 NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
841 (src
[1].RelAddr
<< 4);
845 PVS_OP_DST_OPERAND(VE_MULTIPLY_ADD
,
848 t_dst_index(vp
, &vpi
->DstReg
),
849 t_dst_mask(vpi
->DstReg
.WriteMask
),
850 t_dst_class(vpi
->DstReg
.File
));
851 inst
[1] = t_src(vp
, &src
[0]);
852 inst
[2] = __CONST(0, SWIZZLE_ONE
);
853 inst
[3] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[1]),
854 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)),
855 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)),
856 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)),
857 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)),
858 t_src_class(src
[1].File
),
860 NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
861 (src
[1].RelAddr
<< 4);
867 static GLuint
*r300TranslateOpcodeSWZ(struct r300_vertex_program
*vp
,
868 struct prog_instruction
*vpi
,
870 struct prog_src_register src
[3])
872 //ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO}
874 inst
[0] = PVS_OP_DST_OPERAND(VE_ADD
,
877 t_dst_index(vp
, &vpi
->DstReg
),
878 t_dst_mask(vpi
->DstReg
.WriteMask
),
879 t_dst_class(vpi
->DstReg
.File
));
880 inst
[1] = t_src(vp
, &src
[0]);
881 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
882 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
887 static GLuint
*r300TranslateOpcodeXPD(struct r300_vertex_program
*vp
,
888 struct prog_instruction
*vpi
,
890 struct prog_src_register src
[3],
893 /* mul r0, r1.yzxw, r2.zxyw
894 mad r0, -r2.yzxw, r1.zxyw, r0
897 inst
[0] = PVS_OP_DST_OPERAND(VE_MULTIPLY_ADD
,
901 t_dst_mask(vpi
->DstReg
.WriteMask
),
902 PVS_DST_REG_TEMPORARY
);
903 inst
[1] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[0]), t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // Y
904 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)), // Z
905 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // X
906 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // W
907 t_src_class(src
[0].File
),
909 NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
910 (src
[0].RelAddr
<< 4);
911 inst
[2] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[1]), t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)), // Z
912 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)), // X
913 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)), // Y
914 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)), // W
915 t_src_class(src
[1].File
),
917 NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
918 (src
[1].RelAddr
<< 4);
919 inst
[3] = __CONST(1, SWIZZLE_ZERO
);
922 inst
[0] = PVS_OP_DST_OPERAND(VE_MULTIPLY_ADD
,
925 t_dst_index(vp
, &vpi
->DstReg
),
926 t_dst_mask(vpi
->DstReg
.WriteMask
),
927 t_dst_class(vpi
->DstReg
.File
));
928 inst
[1] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[1]), t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)), // Y
929 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)), // Z
930 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)), // X
931 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)), // W
932 t_src_class(src
[1].File
),
934 NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
935 (src
[1].RelAddr
<< 4);
936 inst
[2] = PVS_SRC_OPERAND(t_src_index(vp
, &src
[0]), t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)), // Z
937 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // X
938 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // Y
939 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // W
940 t_src_class(src
[0].File
),
942 NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) |
943 (src
[0].RelAddr
<< 4);
945 PVS_SRC_OPERAND(*u_temp_i
, PVS_SRC_SELECT_X
, PVS_SRC_SELECT_Y
,
946 PVS_SRC_SELECT_Z
, PVS_SRC_SELECT_W
,
947 PVS_SRC_REG_TEMPORARY
, VSF_FLAG_NONE
);
954 static void t_inputs_outputs(struct r300_vertex_program
*vp
)
959 for (i
= 0; i
< VERT_ATTRIB_MAX
; i
++)
962 for (i
= 0; i
< VERT_RESULT_MAX
; i
++)
965 assert(vp
->key
.OutputsWritten
& (1 << VERT_RESULT_HPOS
));
967 if (vp
->key
.OutputsWritten
& (1 << VERT_RESULT_HPOS
)) {
968 vp
->outputs
[VERT_RESULT_HPOS
] = cur_reg
++;
971 if (vp
->key
.OutputsWritten
& (1 << VERT_RESULT_PSIZ
)) {
972 vp
->outputs
[VERT_RESULT_PSIZ
] = cur_reg
++;
975 if (vp
->key
.OutputsWritten
& (1 << VERT_RESULT_COL0
)) {
976 vp
->outputs
[VERT_RESULT_COL0
] = cur_reg
++;
979 if (vp
->key
.OutputsWritten
& (1 << VERT_RESULT_COL1
)) {
980 vp
->outputs
[VERT_RESULT_COL1
] =
981 vp
->outputs
[VERT_RESULT_COL0
] + 1;
982 cur_reg
= vp
->outputs
[VERT_RESULT_COL1
] + 1;
985 if (vp
->key
.OutputsWritten
& (1 << VERT_RESULT_BFC0
)) {
986 vp
->outputs
[VERT_RESULT_BFC0
] =
987 vp
->outputs
[VERT_RESULT_COL0
] + 2;
988 cur_reg
= vp
->outputs
[VERT_RESULT_BFC0
] + 2;
991 if (vp
->key
.OutputsWritten
& (1 << VERT_RESULT_BFC1
)) {
992 vp
->outputs
[VERT_RESULT_BFC1
] =
993 vp
->outputs
[VERT_RESULT_COL0
] + 3;
994 cur_reg
= vp
->outputs
[VERT_RESULT_BFC1
] + 1;
997 for (i
= VERT_RESULT_TEX0
; i
<= VERT_RESULT_TEX7
; i
++) {
998 if (vp
->key
.OutputsWritten
& (1 << i
)) {
999 vp
->outputs
[i
] = cur_reg
++;
1003 if (vp
->key
.OutputsWritten
& (1 << VERT_RESULT_FOGC
)) {
1004 vp
->outputs
[VERT_RESULT_FOGC
] = cur_reg
++;
1008 static void r300TranslateVertexShader(struct r300_vertex_program
*vp
,
1009 struct prog_instruction
*vpi
)
1013 unsigned long num_operands
;
1014 /* Initial value should be last tmp reg that hw supports.
1015 Strangely enough r300 doesnt mind even though these would be out of range.
1016 Smart enough to realize that it doesnt need it? */
1017 int u_temp_i
= VSF_MAX_FRAGMENT_TEMPS
- 1;
1018 struct prog_src_register src
[3];
1020 vp
->pos_end
= 0; /* Not supported yet */
1021 vp
->program
.length
= 0;
1022 /*vp->num_temporaries=mesa_vp->Base.NumTemporaries; */
1023 vp
->translated
= GL_TRUE
;
1024 vp
->native
= GL_TRUE
;
1026 t_inputs_outputs(vp
);
1028 for (inst
= vp
->program
.body
.i
; vpi
->Opcode
!= OPCODE_END
;
1033 if (!valid_dst(vp
, &vpi
->DstReg
)) {
1034 /* redirect result to unused temp */
1035 vpi
->DstReg
.File
= PROGRAM_TEMPORARY
;
1036 vpi
->DstReg
.Index
= u_temp_i
;
1039 num_operands
= _mesa_num_inst_src_regs(vpi
->Opcode
);
1041 /* copy the sources (src) from mesa into a local variable... is this needed? */
1042 for (i
= 0; i
< num_operands
; i
++) {
1043 src
[i
] = vpi
->SrcReg
[i
];
1046 if (num_operands
== 3) { /* TODO: scalars */
1047 if (CMP_SRCS(src
[1], src
[2])
1048 || CMP_SRCS(src
[0], src
[2])) {
1049 inst
[0] = PVS_OP_DST_OPERAND(VE_ADD
,
1054 PVS_DST_REG_TEMPORARY
);
1056 PVS_SRC_OPERAND(t_src_index(vp
, &src
[2]),
1061 t_src_class(src
[2].File
),
1062 VSF_FLAG_NONE
) | (src
[2].
1065 inst
[2] = __CONST(2, SWIZZLE_ZERO
);
1066 inst
[3] = __CONST(2, SWIZZLE_ZERO
);
1069 src
[2].File
= PROGRAM_TEMPORARY
;
1070 src
[2].Index
= u_temp_i
;
1076 if (num_operands
>= 2) {
1077 if (CMP_SRCS(src
[1], src
[0])) {
1078 inst
[0] = PVS_OP_DST_OPERAND(VE_ADD
,
1083 PVS_DST_REG_TEMPORARY
);
1085 PVS_SRC_OPERAND(t_src_index(vp
, &src
[0]),
1090 t_src_class(src
[0].File
),
1091 VSF_FLAG_NONE
) | (src
[0].
1094 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
1095 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
1098 src
[0].File
= PROGRAM_TEMPORARY
;
1099 src
[0].Index
= u_temp_i
;
1105 switch (vpi
->Opcode
) {
1107 inst
= r300TranslateOpcodeABS(vp
, vpi
, inst
, src
);
1110 inst
= r300TranslateOpcodeADD(vp
, vpi
, inst
, src
);
1113 inst
= r300TranslateOpcodeARL(vp
, vpi
, inst
, src
);
1116 inst
= r300TranslateOpcodeDP3(vp
, vpi
, inst
, src
);
1119 inst
= r300TranslateOpcodeDP4(vp
, vpi
, inst
, src
);
1122 inst
= r300TranslateOpcodeDPH(vp
, vpi
, inst
, src
);
1125 inst
= r300TranslateOpcodeDST(vp
, vpi
, inst
, src
);
1128 inst
= r300TranslateOpcodeEX2(vp
, vpi
, inst
, src
);
1131 inst
= r300TranslateOpcodeEXP(vp
, vpi
, inst
, src
);
1134 inst
= r300TranslateOpcodeFLR(vp
, vpi
, inst
, src
, /* FIXME */
1138 inst
= r300TranslateOpcodeFRC(vp
, vpi
, inst
, src
);
1141 inst
= r300TranslateOpcodeLG2(vp
, vpi
, inst
, src
);
1144 inst
= r300TranslateOpcodeLIT(vp
, vpi
, inst
, src
);
1147 inst
= r300TranslateOpcodeLOG(vp
, vpi
, inst
, src
);
1150 inst
= r300TranslateOpcodeMAD(vp
, vpi
, inst
, src
);
1153 inst
= r300TranslateOpcodeMAX(vp
, vpi
, inst
, src
);
1156 inst
= r300TranslateOpcodeMIN(vp
, vpi
, inst
, src
);
1159 inst
= r300TranslateOpcodeMOV(vp
, vpi
, inst
, src
);
1162 inst
= r300TranslateOpcodeMUL(vp
, vpi
, inst
, src
);
1165 inst
= r300TranslateOpcodePOW(vp
, vpi
, inst
, src
);
1168 inst
= r300TranslateOpcodeRCP(vp
, vpi
, inst
, src
);
1171 inst
= r300TranslateOpcodeRSQ(vp
, vpi
, inst
, src
);
1174 inst
= r300TranslateOpcodeSGE(vp
, vpi
, inst
, src
);
1177 inst
= r300TranslateOpcodeSLT(vp
, vpi
, inst
, src
);
1180 inst
= r300TranslateOpcodeSUB(vp
, vpi
, inst
, src
);
1183 inst
= r300TranslateOpcodeSWZ(vp
, vpi
, inst
, src
);
1186 inst
= r300TranslateOpcodeXPD(vp
, vpi
, inst
, src
, /* FIXME */
1195 /* Some outputs may be artificially added, to match the inputs
1196 of the fragment program. Blank the outputs here. */
1197 for (i
= 0; i
< VERT_RESULT_MAX
; i
++) {
1198 if (vp
->key
.OutputsAdded
& (1 << i
)) {
1199 inst
[0] = PVS_OP_DST_OPERAND(VE_ADD
,
1205 inst
[1] = __CONST(0, SWIZZLE_ZERO
);
1206 inst
[2] = __CONST(0, SWIZZLE_ZERO
);
1207 inst
[3] = __CONST(0, SWIZZLE_ZERO
);
1212 vp
->program
.length
= (inst
- vp
->program
.body
.i
);
1213 if (vp
->program
.length
>= VSF_MAX_FRAGMENT_LENGTH
) {
1214 vp
->program
.length
= 0;
1215 vp
->native
= GL_FALSE
;
1218 fprintf(stderr
, "hw program:\n");
1219 for (i
= 0; i
< vp
->program
.length
; i
++)
1220 fprintf(stderr
, "%08x\n", vp
->program
.body
.d
[i
]);
1224 /* DP4 version seems to trigger some hw peculiarity */
1225 //#define PREFER_DP4
1227 static void position_invariant(struct gl_program
*prog
)
1229 struct prog_instruction
*vpi
;
1230 struct gl_program_parameter_list
*paramList
;
1233 gl_state_index tokens
[STATE_LENGTH
] = { STATE_MVP_MATRIX
, 0, 0, 0, 0 };
1235 /* tokens[4] = matrix modifier */
1237 tokens
[4] = 0; /* not transposed or inverted */
1239 tokens
[4] = STATE_MATRIX_TRANSPOSE
;
1241 paramList
= prog
->Parameters
;
1243 vpi
= _mesa_alloc_instructions(prog
->NumInstructions
+ 4);
1244 _mesa_init_instructions(vpi
, prog
->NumInstructions
+ 4);
1246 for (i
= 0; i
< 4; i
++) {
1248 tokens
[2] = tokens
[3] = i
; /* matrix row[i]..row[i] */
1249 idx
= _mesa_add_state_reference(paramList
, tokens
);
1251 vpi
[i
].Opcode
= OPCODE_DP4
;
1252 vpi
[i
].StringPos
= 0;
1255 vpi
[i
].DstReg
.File
= PROGRAM_OUTPUT
;
1256 vpi
[i
].DstReg
.Index
= VERT_RESULT_HPOS
;
1257 vpi
[i
].DstReg
.WriteMask
= 1 << i
;
1258 vpi
[i
].DstReg
.CondMask
= COND_TR
;
1260 vpi
[i
].SrcReg
[0].File
= PROGRAM_STATE_VAR
;
1261 vpi
[i
].SrcReg
[0].Index
= idx
;
1262 vpi
[i
].SrcReg
[0].Swizzle
= SWIZZLE_XYZW
;
1264 vpi
[i
].SrcReg
[1].File
= PROGRAM_INPUT
;
1265 vpi
[i
].SrcReg
[1].Index
= VERT_ATTRIB_POS
;
1266 vpi
[i
].SrcReg
[1].Swizzle
= SWIZZLE_XYZW
;
1269 vpi
[i
].Opcode
= OPCODE_MUL
;
1271 vpi
[i
].Opcode
= OPCODE_MAD
;
1276 vpi
[i
].DstReg
.File
= PROGRAM_OUTPUT
;
1278 vpi
[i
].DstReg
.File
= PROGRAM_TEMPORARY
;
1279 vpi
[i
].DstReg
.Index
= 0;
1280 vpi
[i
].DstReg
.WriteMask
= 0xf;
1281 vpi
[i
].DstReg
.CondMask
= COND_TR
;
1283 vpi
[i
].SrcReg
[0].File
= PROGRAM_STATE_VAR
;
1284 vpi
[i
].SrcReg
[0].Index
= idx
;
1285 vpi
[i
].SrcReg
[0].Swizzle
= SWIZZLE_XYZW
;
1287 vpi
[i
].SrcReg
[1].File
= PROGRAM_INPUT
;
1288 vpi
[i
].SrcReg
[1].Index
= VERT_ATTRIB_POS
;
1289 vpi
[i
].SrcReg
[1].Swizzle
= MAKE_SWIZZLE4(i
, i
, i
, i
);
1292 vpi
[i
].SrcReg
[2].File
= PROGRAM_TEMPORARY
;
1293 vpi
[i
].SrcReg
[2].Index
= 0;
1294 vpi
[i
].SrcReg
[2].Swizzle
= SWIZZLE_XYZW
;
1299 _mesa_copy_instructions(&vpi
[i
], prog
->Instructions
,
1300 prog
->NumInstructions
);
1302 free(prog
->Instructions
);
1304 prog
->Instructions
= vpi
;
1306 prog
->NumInstructions
+= 4;
1307 vpi
= &prog
->Instructions
[prog
->NumInstructions
- 1];
1309 assert(vpi
->Opcode
== OPCODE_END
);
1312 static void insert_wpos(struct r300_vertex_program
*vp
, struct gl_program
*prog
,
1315 struct prog_instruction
*vpi
;
1316 struct prog_instruction
*vpi_insert
;
1319 vpi
= _mesa_alloc_instructions(prog
->NumInstructions
+ 2);
1320 _mesa_init_instructions(vpi
, prog
->NumInstructions
+ 2);
1322 _mesa_copy_instructions(vpi
, prog
->Instructions
,
1323 prog
->NumInstructions
- 1);
1325 _mesa_copy_instructions(&vpi
[prog
->NumInstructions
+ 1],
1326 &prog
->Instructions
[prog
->NumInstructions
- 1],
1328 vpi_insert
= &vpi
[prog
->NumInstructions
- 1];
1330 vpi_insert
[i
].Opcode
= OPCODE_MOV
;
1332 vpi_insert
[i
].DstReg
.File
= PROGRAM_OUTPUT
;
1333 vpi_insert
[i
].DstReg
.Index
= VERT_RESULT_HPOS
;
1334 vpi_insert
[i
].DstReg
.WriteMask
= WRITEMASK_XYZW
;
1335 vpi_insert
[i
].DstReg
.CondMask
= COND_TR
;
1337 vpi_insert
[i
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
1338 vpi_insert
[i
].SrcReg
[0].Index
= temp_index
;
1339 vpi_insert
[i
].SrcReg
[0].Swizzle
= SWIZZLE_XYZW
;
1342 vpi_insert
[i
].Opcode
= OPCODE_MOV
;
1344 vpi_insert
[i
].DstReg
.File
= PROGRAM_OUTPUT
;
1345 vpi_insert
[i
].DstReg
.Index
= VERT_RESULT_TEX0
+ vp
->wpos_idx
;
1346 vpi_insert
[i
].DstReg
.WriteMask
= WRITEMASK_XYZW
;
1347 vpi_insert
[i
].DstReg
.CondMask
= COND_TR
;
1349 vpi_insert
[i
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
1350 vpi_insert
[i
].SrcReg
[0].Index
= temp_index
;
1351 vpi_insert
[i
].SrcReg
[0].Swizzle
= SWIZZLE_XYZW
;
1354 free(prog
->Instructions
);
1356 prog
->Instructions
= vpi
;
1358 prog
->NumInstructions
+= i
;
1359 vpi
= &prog
->Instructions
[prog
->NumInstructions
- 1];
1361 assert(vpi
->Opcode
== OPCODE_END
);
1364 static void pos_as_texcoord(struct r300_vertex_program
*vp
,
1365 struct gl_program
*prog
)
1367 struct prog_instruction
*vpi
;
1368 GLuint tempregi
= prog
->NumTemporaries
;
1369 /* should do something else if no temps left... */
1370 prog
->NumTemporaries
++;
1372 for (vpi
= prog
->Instructions
; vpi
->Opcode
!= OPCODE_END
; vpi
++) {
1373 if (vpi
->DstReg
.File
== PROGRAM_OUTPUT
1374 && vpi
->DstReg
.Index
== VERT_RESULT_HPOS
) {
1375 vpi
->DstReg
.File
= PROGRAM_TEMPORARY
;
1376 vpi
->DstReg
.Index
= tempregi
;
1379 insert_wpos(vp
, prog
, tempregi
);
1382 static struct r300_vertex_program
*build_program(struct r300_vertex_program_key
1383 *wanted_key
, struct gl_vertex_program
1384 *mesa_vp
, GLint wpos_idx
)
1386 struct r300_vertex_program
*vp
;
1388 vp
= _mesa_calloc(sizeof(*vp
));
1389 _mesa_memcpy(&vp
->key
, wanted_key
, sizeof(vp
->key
));
1390 vp
->wpos_idx
= wpos_idx
;
1392 if (mesa_vp
->IsPositionInvariant
) {
1393 position_invariant(&mesa_vp
->Base
);
1396 if (wpos_idx
> -1) {
1397 pos_as_texcoord(vp
, &mesa_vp
->Base
);
1400 assert(mesa_vp
->Base
.NumInstructions
);
1401 vp
->num_temporaries
= mesa_vp
->Base
.NumTemporaries
;
1402 r300TranslateVertexShader(vp
, mesa_vp
->Base
.Instructions
);
1407 static void add_outputs(struct r300_vertex_program_key
*key
, GLint vert
)
1409 if (key
->OutputsWritten
& (1 << vert
))
1412 key
->OutputsWritten
|= 1 << vert
;
1413 key
->OutputsAdded
|= 1 << vert
;
1416 void r300SelectVertexShader(r300ContextPtr r300
)
1418 GLcontext
*ctx
= ctx
= r300
->radeon
.glCtx
;
1420 struct r300_vertex_program_key wanted_key
= { 0 };
1422 struct r300_vertex_program_cont
*vpc
;
1423 struct r300_vertex_program
*vp
;
1426 vpc
= (struct r300_vertex_program_cont
*)ctx
->VertexProgram
._Current
;
1427 wanted_key
.InputsRead
= vpc
->mesa_program
.Base
.InputsRead
;
1428 wanted_key
.OutputsWritten
= vpc
->mesa_program
.Base
.OutputsWritten
;
1429 InputsRead
= ctx
->FragmentProgram
._Current
->Base
.InputsRead
;
1432 if (InputsRead
& FRAG_BIT_WPOS
) {
1433 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++)
1434 if (!(InputsRead
& (FRAG_BIT_TEX0
<< i
)))
1437 if (i
== ctx
->Const
.MaxTextureUnits
) {
1438 fprintf(stderr
, "\tno free texcoord found\n");
1442 wanted_key
.OutputsWritten
|= 1 << (VERT_RESULT_TEX0
+ i
);
1446 add_outputs(&wanted_key
, VERT_RESULT_HPOS
);
1448 if (InputsRead
& FRAG_BIT_COL0
) {
1449 add_outputs(&wanted_key
, VERT_RESULT_COL0
);
1452 if (InputsRead
& FRAG_BIT_COL1
) {
1453 add_outputs(&wanted_key
, VERT_RESULT_COL1
);
1456 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
1457 if (InputsRead
& (FRAG_BIT_TEX0
<< i
)) {
1458 add_outputs(&wanted_key
, VERT_RESULT_TEX0
+ i
);
1462 if (vpc
->mesa_program
.IsPositionInvariant
) {
1463 /* we wan't position don't we ? */
1464 wanted_key
.InputsRead
|= (1 << VERT_ATTRIB_POS
);
1467 for (vp
= vpc
->progs
; vp
; vp
= vp
->next
)
1468 if (_mesa_memcmp(&vp
->key
, &wanted_key
, sizeof(wanted_key
))
1470 r300
->selected_vp
= vp
;
1473 //_mesa_print_program(&vpc->mesa_program.Base);
1475 vp
= build_program(&wanted_key
, &vpc
->mesa_program
, wpos_idx
);
1476 vp
->next
= vpc
->progs
;
1478 r300
->selected_vp
= vp
;