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 "shader/prog_instruction.h"
37 #include "shader/prog_parameter.h"
38 #include "shader/prog_statevars.h"
41 #include "r300_context.h"
42 #include "r300_program.h"
44 #if SWIZZLE_X != VSF_IN_COMPONENT_X || \
45 SWIZZLE_Y != VSF_IN_COMPONENT_Y || \
46 SWIZZLE_Z != VSF_IN_COMPONENT_Z || \
47 SWIZZLE_W != VSF_IN_COMPONENT_W || \
48 SWIZZLE_ZERO != VSF_IN_COMPONENT_ZERO || \
49 SWIZZLE_ONE != VSF_IN_COMPONENT_ONE || \
50 WRITEMASK_X != VSF_FLAG_X || \
51 WRITEMASK_Y != VSF_FLAG_Y || \
52 WRITEMASK_Z != VSF_FLAG_Z || \
53 WRITEMASK_W != VSF_FLAG_W
54 #error Cannot change these!
57 #define SCALAR_FLAG (1<<31)
58 #define FLAG_MASK (1<<31)
59 #define OP_MASK (0xf) /* we are unlikely to have more than 15 */
60 #define OPN(operator, ip) {#operator, OPCODE_##operator, ip}
65 unsigned long ip
; /* number of input operands and flags */
69 OPN(ARL
, 1|SCALAR_FLAG
),
74 OPN(EX2
, 1|SCALAR_FLAG
),
75 OPN(EXP
, 1|SCALAR_FLAG
),
78 OPN(LG2
, 1|SCALAR_FLAG
),
80 OPN(LOG
, 1|SCALAR_FLAG
),
86 OPN(POW
, 2|SCALAR_FLAG
),
87 OPN(RCP
, 1|SCALAR_FLAG
),
88 OPN(RSQ
, 1|SCALAR_FLAG
),
100 int r300VertexProgUpdateParams(GLcontext
*ctx
, struct r300_vertex_program_cont
*vp
, float *dst
)
103 struct gl_vertex_program
*mesa_vp
= &vp
->mesa_program
;
105 struct gl_program_parameter_list
*paramList
;
107 if (mesa_vp
->IsNVProgram
) {
108 _mesa_load_tracked_matrices(ctx
);
110 for (pi
=0; pi
< MAX_NV_VERTEX_PROGRAM_PARAMS
; pi
++) {
111 *dst
++=ctx
->VertexProgram
.Parameters
[pi
][0];
112 *dst
++=ctx
->VertexProgram
.Parameters
[pi
][1];
113 *dst
++=ctx
->VertexProgram
.Parameters
[pi
][2];
114 *dst
++=ctx
->VertexProgram
.Parameters
[pi
][3];
119 assert(mesa_vp
->Base
.Parameters
);
120 _mesa_load_state_parameters(ctx
, mesa_vp
->Base
.Parameters
);
122 if(mesa_vp
->Base
.Parameters
->NumParameters
* 4 > VSF_MAX_FRAGMENT_LENGTH
){
123 fprintf(stderr
, "%s:Params exhausted\n", __FUNCTION__
);
127 paramList
= mesa_vp
->Base
.Parameters
;
128 for(pi
=0; pi
< paramList
->NumParameters
; pi
++){
129 switch(paramList
->Parameters
[pi
].Type
){
131 case PROGRAM_STATE_VAR
:
132 case PROGRAM_NAMED_PARAM
:
133 //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
134 case PROGRAM_CONSTANT
:
135 *dst
++=paramList
->ParameterValues
[pi
][0];
136 *dst
++=paramList
->ParameterValues
[pi
][1];
137 *dst
++=paramList
->ParameterValues
[pi
][2];
138 *dst
++=paramList
->ParameterValues
[pi
][3];
141 default: _mesa_problem(NULL
, "Bad param type in %s", __FUNCTION__
);
149 static unsigned long t_dst_mask(GLuint mask
)
151 /* WRITEMASK_* is equivalent to VSF_FLAG_* */
152 return mask
& VSF_FLAG_ALL
;
155 static unsigned long t_dst_class(enum register_file file
)
159 case PROGRAM_TEMPORARY
:
160 return VSF_OUT_CLASS_TMP
;
162 return VSF_OUT_CLASS_RESULT
;
163 case PROGRAM_ADDRESS
:
164 return VSF_OUT_CLASS_ADDR
;
167 case PROGRAM_LOCAL_PARAM:
168 case PROGRAM_ENV_PARAM:
169 case PROGRAM_NAMED_PARAM:
170 case PROGRAM_STATE_VAR:
171 case PROGRAM_WRITE_ONLY:
172 case PROGRAM_ADDRESS:
175 fprintf(stderr
, "problem in %s", __FUNCTION__
);
180 static unsigned long t_dst_index(struct r300_vertex_program
*vp
, struct prog_dst_register
*dst
)
182 if(dst
->File
== PROGRAM_OUTPUT
)
183 return vp
->outputs
[dst
->Index
];
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 __inline
unsigned long t_swizzle(GLubyte swizzle
)
216 /* this is in fact a NOP as the Mesa SWIZZLE_* are all identical to VSF_IN_COMPONENT_* */
221 static void vp_dump_inputs(struct r300_vertex_program
*vp
, char *caller
)
226 fprintf(stderr
, "vp null in call to %s from %s\n", __FUNCTION__
, caller
);
230 fprintf(stderr
, "%s:<", caller
);
231 for(i
=0; i
< VERT_ATTRIB_MAX
; i
++)
232 fprintf(stderr
, "%d ", vp
->inputs
[i
]);
233 fprintf(stderr
, ">\n");
238 static unsigned long t_src_index(struct r300_vertex_program
*vp
, struct prog_src_register
*src
)
243 if(src
->File
== PROGRAM_INPUT
){
244 if(vp
->inputs
[src
->Index
] != -1)
245 return vp
->inputs
[src
->Index
];
247 for(i
=0; i
< VERT_ATTRIB_MAX
; i
++)
248 if(vp
->inputs
[i
] > max_reg
)
249 max_reg
=vp
->inputs
[i
];
251 vp
->inputs
[src
->Index
]=max_reg
+1;
253 //vp_dump_inputs(vp, __FUNCTION__);
255 return vp
->inputs
[src
->Index
];
257 if (src
->Index
< 0) {
258 fprintf(stderr
, "WARNING negative offsets for indirect addressing do not work\n");
265 static unsigned long t_src(struct r300_vertex_program
*vp
, struct prog_src_register
*src
)
267 /* src->NegateBase uses the NEGATE_ flags from program_instruction.h,
268 * which equal our VSF_FLAGS_ values, so it's safe to just pass it here.
270 return MAKE_VSF_SOURCE(t_src_index(vp
, src
),
271 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
272 t_swizzle(GET_SWZ(src
->Swizzle
, 1)),
273 t_swizzle(GET_SWZ(src
->Swizzle
, 2)),
274 t_swizzle(GET_SWZ(src
->Swizzle
, 3)),
275 t_src_class(src
->File
),
276 src
->NegateBase
) | (src
->RelAddr
<< 4);
279 static unsigned long t_src_scalar(struct r300_vertex_program
*vp
, struct prog_src_register
*src
)
282 return MAKE_VSF_SOURCE(t_src_index(vp
, src
),
283 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
284 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
285 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
286 t_swizzle(GET_SWZ(src
->Swizzle
, 0)),
287 t_src_class(src
->File
),
288 src
->NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
->RelAddr
<< 4);
291 static unsigned long t_opcode(enum prog_opcode opcode
)
295 case OPCODE_ARL
: return R300_VPI_OUT_OP_ARL
;
296 case OPCODE_DST
: return R300_VPI_OUT_OP_DST
;
297 case OPCODE_EX2
: return R300_VPI_OUT_OP_EX2
;
298 case OPCODE_EXP
: return R300_VPI_OUT_OP_EXP
;
299 case OPCODE_FRC
: return R300_VPI_OUT_OP_FRC
;
300 case OPCODE_LG2
: return R300_VPI_OUT_OP_LG2
;
301 case OPCODE_LOG
: return R300_VPI_OUT_OP_LOG
;
302 case OPCODE_MAX
: return R300_VPI_OUT_OP_MAX
;
303 case OPCODE_MIN
: return R300_VPI_OUT_OP_MIN
;
304 case OPCODE_MUL
: return R300_VPI_OUT_OP_MUL
;
305 case OPCODE_RCP
: return R300_VPI_OUT_OP_RCP
;
306 case OPCODE_RSQ
: return R300_VPI_OUT_OP_RSQ
;
307 case OPCODE_SGE
: return R300_VPI_OUT_OP_SGE
;
308 case OPCODE_SLT
: return R300_VPI_OUT_OP_SLT
;
309 case OPCODE_DP4
: return R300_VPI_OUT_OP_DOT
;
312 fprintf(stderr
, "%s: Should not be called with opcode %d!", __FUNCTION__
, opcode
);
318 static unsigned long op_operands(enum prog_opcode opcode
)
322 /* Can we trust mesas opcodes to be in order ? */
323 for(i
=0; i
< sizeof(op_names
) / sizeof(*op_names
); i
++)
324 if(op_names
[i
].opcode
== opcode
)
325 return op_names
[i
].ip
;
327 fprintf(stderr
, "op %d not found in op_names\n", opcode
);
332 static GLboolean
valid_dst(struct r300_vertex_program
*vp
, struct prog_dst_register
*dst
)
334 if(dst
->File
== PROGRAM_OUTPUT
&& vp
->outputs
[dst
->Index
] == -1){
335 WARN_ONCE("Output %d not used by fragment program\n", dst
->Index
);
337 }else if(dst
->File
== PROGRAM_ADDRESS
) {
338 assert(dst
->Index
== 0);
344 /* TODO: Get rid of t_src_class call */
345 #define CMP_SRCS(a, b) ((a.RelAddr != b.RelAddr) || (a.Index != b.Index && \
346 ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \
347 t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \
348 (t_src_class(a.File) == VSF_IN_CLASS_ATTR && \
349 t_src_class(b.File) == VSF_IN_CLASS_ATTR)))) \
351 #define ZERO_SRC_0 (MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \
352 SWIZZLE_ZERO, SWIZZLE_ZERO, \
353 SWIZZLE_ZERO, SWIZZLE_ZERO, \
354 t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4))
356 #define ZERO_SRC_1 (MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \
357 SWIZZLE_ZERO, SWIZZLE_ZERO, \
358 SWIZZLE_ZERO, SWIZZLE_ZERO, \
359 t_src_class(src[1].File), VSF_FLAG_NONE) | (src[1].RelAddr << 4))
361 #define ZERO_SRC_2 (MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \
362 SWIZZLE_ZERO, SWIZZLE_ZERO, \
363 SWIZZLE_ZERO, SWIZZLE_ZERO, \
364 t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4))
366 #define ONE_SRC_0 (MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \
367 SWIZZLE_ONE, SWIZZLE_ONE, \
368 SWIZZLE_ONE, SWIZZLE_ONE, \
369 t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4))
371 #define ONE_SRC_1 (MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \
372 SWIZZLE_ONE, SWIZZLE_ONE, \
373 SWIZZLE_ONE, SWIZZLE_ONE, \
374 t_src_class(src[1].File), VSF_FLAG_NONE) | (src[1].RelAddr << 4))
376 #define ONE_SRC_2 (MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \
377 SWIZZLE_ONE, SWIZZLE_ONE, \
378 SWIZZLE_ONE, SWIZZLE_ONE, \
379 t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4))
381 /* DP4 version seems to trigger some hw peculiarity */
384 #define FREE_TEMPS() \
386 if(u_temp_i < vp->num_temporaries) { \
387 WARN_ONCE("Ran out of temps, num temps %d, us %d\n", vp->num_temporaries, u_temp_i); \
388 vp->native = GL_FALSE; \
390 u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; \
393 static void r300_translate_vertex_shader(struct r300_vertex_program
*vp
, struct prog_instruction
*vpi
)
396 VERTEX_SHADER_INSTRUCTION
*o_inst
;
397 unsigned long operands
;
400 /* Initial value should be last tmp reg that hw supports.
401 Strangely enough r300 doesnt mind even though these would be out of range.
402 Smart enough to realize that it doesnt need it? */
403 int u_temp_i
=VSF_MAX_FRAGMENT_TEMPS
-1;
404 struct prog_src_register src
[3];
406 vp
->pos_end
=0; /* Not supported yet */
407 vp
->program
.length
=0;
408 /*vp->num_temporaries=mesa_vp->Base.NumTemporaries;*/
410 for(i
=0; i
< VERT_ATTRIB_MAX
; i
++)
413 for(i
=0; i
< VERT_RESULT_MAX
; i
++)
416 assert(vp
->key
.OutputsWritten
& (1 << VERT_RESULT_HPOS
));
419 if(vp
->key
.OutputsWritten
& (1 << VERT_RESULT_HPOS
))
420 vp
->outputs
[VERT_RESULT_HPOS
] = cur_reg
++;
422 if(vp
->key
.OutputsWritten
& (1 << VERT_RESULT_PSIZ
))
423 vp
->outputs
[VERT_RESULT_PSIZ
] = cur_reg
++;
425 if(vp
->key
.OutputsWritten
& (1 << VERT_RESULT_COL0
))
426 vp
->outputs
[VERT_RESULT_COL0
] = cur_reg
++;
428 if(vp
->key
.OutputsWritten
& (1 << VERT_RESULT_COL1
))
429 vp
->outputs
[VERT_RESULT_COL1
] = cur_reg
++;
431 #if 0 /* Not supported yet */
432 if(vp
->key
.OutputsWritten
& (1 << VERT_RESULT_BFC0
))
433 vp
->outputs
[VERT_RESULT_BFC0
] = cur_reg
++;
435 if(vp
->key
.OutputsWritten
& (1 << VERT_RESULT_BFC1
))
436 vp
->outputs
[VERT_RESULT_BFC1
] = cur_reg
++;
438 if(vp
->key
.OutputsWritten
& (1 << VERT_RESULT_FOGC
))
439 vp
->outputs
[VERT_RESULT_FOGC
] = cur_reg
++;
442 for(i
=VERT_RESULT_TEX0
; i
<= VERT_RESULT_TEX7
; i
++)
443 if(vp
->key
.OutputsWritten
& (1 << i
))
444 vp
->outputs
[i
] = cur_reg
++;
446 vp
->translated
= GL_TRUE
;
447 vp
->native
= GL_TRUE
;
449 o_inst
=vp
->program
.body
.i
;
450 for(; vpi
->Opcode
!= OPCODE_END
; vpi
++, o_inst
++){
453 if(!valid_dst(vp
, &vpi
->DstReg
))
455 /* redirect result to unused temp */
456 vpi
->DstReg
.File
= PROGRAM_TEMPORARY
;
457 vpi
->DstReg
.Index
= u_temp_i
;
460 operands
=op_operands(vpi
->Opcode
);
461 are_srcs_scalar
=operands
& SCALAR_FLAG
;
464 for(i
=0; i
< operands
; i
++)
465 src
[i
]=vpi
->SrcReg
[i
];
467 if(operands
== 3){ /* TODO: scalars */
468 if( CMP_SRCS(src
[1], src
[2]) || CMP_SRCS(src
[0], src
[2]) ){
469 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, u_temp_i
,
470 VSF_FLAG_ALL
, VSF_OUT_CLASS_TMP
);
472 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[2]),
473 SWIZZLE_X
, SWIZZLE_Y
,
474 SWIZZLE_Z
, SWIZZLE_W
,
475 t_src_class(src
[2].File
), VSF_FLAG_NONE
) | (src
[2].RelAddr
<< 4);
477 o_inst
->src2
=ZERO_SRC_2
;
478 o_inst
->src3
=ZERO_SRC_2
;
481 src
[2].File
=PROGRAM_TEMPORARY
;
482 src
[2].Index
=u_temp_i
;
490 if( CMP_SRCS(src
[1], src
[0]) ){
491 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, u_temp_i
,
492 VSF_FLAG_ALL
, VSF_OUT_CLASS_TMP
);
494 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
495 SWIZZLE_X
, SWIZZLE_Y
,
496 SWIZZLE_Z
, SWIZZLE_W
,
497 t_src_class(src
[0].File
), VSF_FLAG_NONE
) | (src
[0].RelAddr
<< 4);
499 o_inst
->src2
=ZERO_SRC_0
;
500 o_inst
->src3
=ZERO_SRC_0
;
503 src
[0].File
=PROGRAM_TEMPORARY
;
504 src
[0].Index
=u_temp_i
;
510 /* These ops need special handling. */
513 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_POW
, t_dst_index(vp
, &vpi
->DstReg
),
514 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
515 o_inst
->src1
=t_src_scalar(vp
, &src
[0]);
516 o_inst
->src2
=ZERO_SRC_0
;
517 o_inst
->src3
=t_src_scalar(vp
, &src
[1]);
520 case OPCODE_MOV
://ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO}
523 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, t_dst_index(vp
, &vpi
->DstReg
),
524 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
525 o_inst
->src1
=t_src(vp
, &src
[0]);
526 o_inst
->src2
=ZERO_SRC_0
;
527 o_inst
->src3
=ZERO_SRC_0
;
529 hw_op
=(src
[0].File
== PROGRAM_TEMPORARY
) ? R300_VPI_OUT_OP_MAD_2
: R300_VPI_OUT_OP_MAD
;
531 o_inst
->op
=MAKE_VSF_OP(hw_op
, t_dst_index(vp
, &vpi
->DstReg
),
532 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
533 o_inst
->src1
=t_src(vp
, &src
[0]);
534 o_inst
->src2
=ONE_SRC_0
;
535 o_inst
->src3
=ZERO_SRC_0
;
542 hw_op
=(src
[0].File
== PROGRAM_TEMPORARY
&&
543 src
[1].File
== PROGRAM_TEMPORARY
) ? R300_VPI_OUT_OP_MAD_2
: R300_VPI_OUT_OP_MAD
;
545 o_inst
->op
=MAKE_VSF_OP(hw_op
, t_dst_index(vp
, &vpi
->DstReg
),
546 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
547 o_inst
->src1
=ONE_SRC_0
;
548 o_inst
->src2
=t_src(vp
, &src
[0]);
549 o_inst
->src3
=t_src(vp
, &src
[1]);
551 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, t_dst_index(vp
, &vpi
->DstReg
),
552 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
553 o_inst
->src1
=t_src(vp
, &src
[0]);
554 o_inst
->src2
=t_src(vp
, &src
[1]);
555 o_inst
->src3
=ZERO_SRC_1
;
561 hw_op
=(src
[0].File
== PROGRAM_TEMPORARY
&&
562 src
[1].File
== PROGRAM_TEMPORARY
&&
563 src
[2].File
== PROGRAM_TEMPORARY
) ? R300_VPI_OUT_OP_MAD_2
: R300_VPI_OUT_OP_MAD
;
565 o_inst
->op
=MAKE_VSF_OP(hw_op
, t_dst_index(vp
, &vpi
->DstReg
),
566 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
567 o_inst
->src1
=t_src(vp
, &src
[0]);
568 o_inst
->src2
=t_src(vp
, &src
[1]);
569 o_inst
->src3
=t_src(vp
, &src
[2]);
572 case OPCODE_MUL
: /* HW mul can take third arg but appears to have some other limitations. */
573 hw_op
=(src
[0].File
== PROGRAM_TEMPORARY
&&
574 src
[1].File
== PROGRAM_TEMPORARY
) ? R300_VPI_OUT_OP_MAD_2
: R300_VPI_OUT_OP_MAD
;
576 o_inst
->op
=MAKE_VSF_OP(hw_op
, t_dst_index(vp
, &vpi
->DstReg
),
577 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
578 o_inst
->src1
=t_src(vp
, &src
[0]);
579 o_inst
->src2
=t_src(vp
, &src
[1]);
581 o_inst
->src3
=ZERO_SRC_1
;
584 case OPCODE_DP3
://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO}
585 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT
, t_dst_index(vp
, &vpi
->DstReg
),
586 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
588 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
589 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
590 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)),
591 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)),
593 t_src_class(src
[0].File
),
594 src
[0].NegateBase
? VSF_FLAG_XYZ
: VSF_FLAG_NONE
) | (src
[0].RelAddr
<< 4);
596 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[1]),
597 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)),
598 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)),
599 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)),
601 t_src_class(src
[1].File
),
602 src
[1].NegateBase
? VSF_FLAG_XYZ
: VSF_FLAG_NONE
) | (src
[1].RelAddr
<< 4);
604 o_inst
->src3
=ZERO_SRC_1
;
607 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
609 hw_op
=(src
[0].File
== PROGRAM_TEMPORARY
&&
610 src
[1].File
== PROGRAM_TEMPORARY
) ? R300_VPI_OUT_OP_MAD_2
: R300_VPI_OUT_OP_MAD
;
612 o_inst
->op
=MAKE_VSF_OP(hw_op
, t_dst_index(vp
, &vpi
->DstReg
),
613 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
614 o_inst
->src1
=t_src(vp
, &src
[0]);
615 o_inst
->src2
=ONE_SRC_0
;
616 o_inst
->src3
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[1]),
617 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)),
618 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)),
619 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)),
620 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)),
621 t_src_class(src
[1].File
),
622 (!src
[1].NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
[1].RelAddr
<< 4);
624 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, t_dst_index(vp
, &vpi
->DstReg
),
625 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
627 o_inst
->src1
=t_src(vp
, &src
[0]);
628 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[1]),
629 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)),
630 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)),
631 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)),
632 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)),
633 t_src_class(src
[1].File
),
634 (!src
[1].NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
[1].RelAddr
<< 4);
639 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
640 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_MAX
, t_dst_index(vp
, &vpi
->DstReg
),
641 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
643 o_inst
->src1
=t_src(vp
, &src
[0]);
644 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
645 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
646 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)),
647 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)),
648 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)),
649 t_src_class(src
[0].File
),
650 (!src
[0].NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
[0].RelAddr
<< 4);
655 /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W}
656 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 */
658 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_FRC
, u_temp_i
,
659 t_dst_mask(vpi
->DstReg
.WriteMask
), VSF_OUT_CLASS_TMP
);
661 o_inst
->src1
=t_src(vp
, &src
[0]);
662 o_inst
->src2
=ZERO_SRC_0
;
663 o_inst
->src3
=ZERO_SRC_0
;
666 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD
, t_dst_index(vp
, &vpi
->DstReg
),
667 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
669 o_inst
->src1
=t_src(vp
, &src
[0]);
670 o_inst
->src2
=MAKE_VSF_SOURCE(u_temp_i
,
676 /* Not 100% sure about this */
677 (!src
[0].NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
/*VSF_FLAG_ALL*/);
679 o_inst
->src3
=ZERO_SRC_0
;
683 case OPCODE_LG2
:// LG2 RESULT 1.X Y Z W PARAM 0{} {X X X X}
684 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_LG2
, t_dst_index(vp
, &vpi
->DstReg
),
685 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
687 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
688 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
689 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
690 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
691 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
692 t_src_class(src
[0].File
),
693 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
[0].RelAddr
<< 4);
694 o_inst
->src2
=ZERO_SRC_0
;
695 o_inst
->src3
=ZERO_SRC_0
;
698 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}
699 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_LIT
, t_dst_index(vp
, &vpi
->DstReg
),
700 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
701 /* NOTE: Users swizzling might not work. */
702 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
703 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // x
704 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // w
705 VSF_IN_COMPONENT_ZERO
, // z
706 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // y
707 t_src_class(src
[0].File
),
708 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
[0].RelAddr
<< 4);
709 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
710 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // y
711 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // w
712 VSF_IN_COMPONENT_ZERO
, // z
713 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // x
714 t_src_class(src
[0].File
),
715 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
[0].RelAddr
<< 4);
716 o_inst
->src3
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
717 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // y
718 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // x
719 VSF_IN_COMPONENT_ZERO
, // z
720 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // w
721 t_src_class(src
[0].File
),
722 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
[0].RelAddr
<< 4);
725 case OPCODE_DPH
://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W}
726 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT
, t_dst_index(vp
, &vpi
->DstReg
),
727 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
729 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
730 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)),
731 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)),
732 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)),
733 VSF_IN_COMPONENT_ONE
,
734 t_src_class(src
[0].File
),
735 src
[0].NegateBase
? VSF_FLAG_XYZ
: VSF_FLAG_NONE
) | (src
[0].RelAddr
<< 4);
736 o_inst
->src2
=t_src(vp
, &src
[1]);
737 o_inst
->src3
=ZERO_SRC_1
;
741 /* mul r0, r1.yzxw, r2.zxyw
742 mad r0, -r2.yzxw, r1.zxyw, r0
743 NOTE: might need MAD_2
746 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_MAD
, u_temp_i
,
747 t_dst_mask(vpi
->DstReg
.WriteMask
), VSF_OUT_CLASS_TMP
);
749 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
750 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // y
751 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)), // z
752 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // x
753 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // w
754 t_src_class(src
[0].File
),
755 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
[0].RelAddr
<< 4);
757 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[1]),
758 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)), // z
759 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)), // x
760 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)), // y
761 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)), // w
762 t_src_class(src
[1].File
),
763 src
[1].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
[1].RelAddr
<< 4);
765 o_inst
->src3
=ZERO_SRC_1
;
769 o_inst
->op
=MAKE_VSF_OP(R300_VPI_OUT_OP_MAD
, t_dst_index(vp
, &vpi
->DstReg
),
770 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
772 o_inst
->src1
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[1]),
773 t_swizzle(GET_SWZ(src
[1].Swizzle
, 1)), // y
774 t_swizzle(GET_SWZ(src
[1].Swizzle
, 2)), // z
775 t_swizzle(GET_SWZ(src
[1].Swizzle
, 0)), // x
776 t_swizzle(GET_SWZ(src
[1].Swizzle
, 3)), // w
777 t_src_class(src
[1].File
),
778 (!src
[1].NegateBase
) ? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
[1].RelAddr
<< 4);
780 o_inst
->src2
=MAKE_VSF_SOURCE(t_src_index(vp
, &src
[0]),
781 t_swizzle(GET_SWZ(src
[0].Swizzle
, 2)), // z
782 t_swizzle(GET_SWZ(src
[0].Swizzle
, 0)), // x
783 t_swizzle(GET_SWZ(src
[0].Swizzle
, 1)), // y
784 t_swizzle(GET_SWZ(src
[0].Swizzle
, 3)), // w
785 t_src_class(src
[0].File
),
786 src
[0].NegateBase
? VSF_FLAG_ALL
: VSF_FLAG_NONE
) | (src
[0].RelAddr
<< 4);
788 o_inst
->src3
=MAKE_VSF_SOURCE(u_temp_i
+1,
799 fprintf(stderr
, "Dont know how to handle op %d yet\n", vpi
->Opcode
);
808 o_inst
->op
=MAKE_VSF_OP(t_opcode(vpi
->Opcode
), t_dst_index(vp
, &vpi
->DstReg
),
809 t_dst_mask(vpi
->DstReg
.WriteMask
), t_dst_class(vpi
->DstReg
.File
));
814 o_inst
->src1
=t_src_scalar(vp
, &src
[0]);
815 o_inst
->src2
=ZERO_SRC_0
;
816 o_inst
->src3
=ZERO_SRC_0
;
820 o_inst
->src1
=t_src_scalar(vp
, &src
[0]);
821 o_inst
->src2
=t_src_scalar(vp
, &src
[1]);
822 o_inst
->src3
=ZERO_SRC_1
;
826 o_inst
->src1
=t_src_scalar(vp
, &src
[0]);
827 o_inst
->src2
=t_src_scalar(vp
, &src
[1]);
828 o_inst
->src3
=t_src_scalar(vp
, &src
[2]);
832 fprintf(stderr
, "scalars and op RCC not handled yet");
839 o_inst
->src1
=t_src(vp
, &src
[0]);
840 o_inst
->src2
=ZERO_SRC_0
;
841 o_inst
->src3
=ZERO_SRC_0
;
845 o_inst
->src1
=t_src(vp
, &src
[0]);
846 o_inst
->src2
=t_src(vp
, &src
[1]);
847 o_inst
->src3
=ZERO_SRC_1
;
851 o_inst
->src1
=t_src(vp
, &src
[0]);
852 o_inst
->src2
=t_src(vp
, &src
[1]);
853 o_inst
->src3
=t_src(vp
, &src
[2]);
857 fprintf(stderr
, "scalars and op RCC not handled yet");
865 /* Will most likely segfault before we get here... fix later. */
866 if(o_inst
- vp
->program
.body
.i
>= VSF_MAX_FRAGMENT_LENGTH
/4) {
867 vp
->program
.length
= 0;
868 vp
->native
= GL_FALSE
;
871 vp
->program
.length
=(o_inst
- vp
->program
.body
.i
) * 4;
873 fprintf(stderr
, "hw program:\n");
874 for(i
=0; i
< vp
->program
.length
; i
++)
875 fprintf(stderr
, "%08x\n", vp
->program
.body
.d
[i
]);
879 static void position_invariant(struct gl_program
*prog
)
881 struct prog_instruction
*vpi
;
882 struct gl_program_parameter_list
*paramList
;
885 gl_state_index tokens
[STATE_LENGTH
] = { STATE_MVP_MATRIX
, 0, 0, 0, 0 };
888 tokens
[5] = STATE_MATRIX
;
890 tokens
[5] = STATE_MATRIX_TRANSPOSE
;
892 paramList
= prog
->Parameters
;
894 vpi
= _mesa_alloc_instructions (prog
->NumInstructions
+ 4);
895 _mesa_init_instructions (vpi
, prog
->NumInstructions
+ 4);
897 for (i
=0; i
< 4; i
++) {
899 tokens
[3] = tokens
[4] = i
;
900 idx
= _mesa_add_state_reference(paramList
, tokens
);
902 vpi
[i
].Opcode
= OPCODE_DP4
;
903 vpi
[i
].StringPos
= 0;
906 vpi
[i
].DstReg
.File
= PROGRAM_OUTPUT
;
907 vpi
[i
].DstReg
.Index
= VERT_RESULT_HPOS
;
908 vpi
[i
].DstReg
.WriteMask
= 1 << i
;
909 vpi
[i
].DstReg
.CondMask
= COND_TR
;
911 vpi
[i
].SrcReg
[0].File
= PROGRAM_STATE_VAR
;
912 vpi
[i
].SrcReg
[0].Index
= idx
;
913 vpi
[i
].SrcReg
[0].Swizzle
= SWIZZLE_XYZW
;
915 vpi
[i
].SrcReg
[1].File
= PROGRAM_INPUT
;
916 vpi
[i
].SrcReg
[1].Index
= VERT_ATTRIB_POS
;
917 vpi
[i
].SrcReg
[1].Swizzle
= SWIZZLE_XYZW
;
920 vpi
[i
].Opcode
= OPCODE_MUL
;
922 vpi
[i
].Opcode
= OPCODE_MAD
;
924 vpi
[i
].StringPos
= 0;
928 vpi
[i
].DstReg
.File
= PROGRAM_OUTPUT
;
930 vpi
[i
].DstReg
.File
= PROGRAM_TEMPORARY
;
931 vpi
[i
].DstReg
.Index
= 0;
932 vpi
[i
].DstReg
.WriteMask
= 0xf;
933 vpi
[i
].DstReg
.CondMask
= COND_TR
;
935 vpi
[i
].SrcReg
[0].File
= PROGRAM_STATE_VAR
;
936 vpi
[i
].SrcReg
[0].Index
= idx
;
937 vpi
[i
].SrcReg
[0].Swizzle
= SWIZZLE_XYZW
;
939 vpi
[i
].SrcReg
[1].File
= PROGRAM_INPUT
;
940 vpi
[i
].SrcReg
[1].Index
= VERT_ATTRIB_POS
;
941 vpi
[i
].SrcReg
[1].Swizzle
= MAKE_SWIZZLE4(i
, i
, i
, i
);
944 vpi
[i
].SrcReg
[2].File
= PROGRAM_TEMPORARY
;
945 vpi
[i
].SrcReg
[2].Index
= 0;
946 vpi
[i
].SrcReg
[2].Swizzle
= SWIZZLE_XYZW
;
951 _mesa_copy_instructions (&vpi
[i
], prog
->Instructions
, prog
->NumInstructions
);
953 free(prog
->Instructions
);
955 prog
->Instructions
= vpi
;
957 prog
->NumInstructions
+= 4;
958 vpi
= &prog
->Instructions
[prog
->NumInstructions
-1];
960 assert(vpi
->Opcode
== OPCODE_END
);
963 static void insert_wpos(struct r300_vertex_program
*vp
,
964 struct gl_program
*prog
,
967 struct prog_instruction
*vpi
;
968 struct prog_instruction
*vpi_insert
;
971 vpi
= _mesa_alloc_instructions (prog
->NumInstructions
+ 2);
972 _mesa_init_instructions (vpi
, prog
->NumInstructions
+ 2);
974 _mesa_copy_instructions (vpi
, prog
->Instructions
, prog
->NumInstructions
- 1);
976 _mesa_copy_instructions (&vpi
[prog
->NumInstructions
+ 1],
977 &prog
->Instructions
[prog
->NumInstructions
- 1],
979 vpi_insert
= &vpi
[prog
->NumInstructions
- 1];
981 vpi_insert
[i
].Opcode
= OPCODE_MOV
;
983 vpi_insert
[i
].DstReg
.File
= PROGRAM_OUTPUT
;
984 vpi_insert
[i
].DstReg
.Index
= VERT_RESULT_HPOS
;
985 vpi_insert
[i
].DstReg
.WriteMask
= WRITEMASK_XYZW
;
986 vpi_insert
[i
].DstReg
.CondMask
= COND_TR
;
988 vpi_insert
[i
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
989 vpi_insert
[i
].SrcReg
[0].Index
= temp_index
;
990 vpi_insert
[i
].SrcReg
[0].Swizzle
= SWIZZLE_XYZW
;
993 vpi_insert
[i
].Opcode
= OPCODE_MOV
;
995 vpi_insert
[i
].DstReg
.File
= PROGRAM_OUTPUT
;
996 vpi_insert
[i
].DstReg
.Index
= VERT_RESULT_TEX0
+vp
->wpos_idx
;
997 vpi_insert
[i
].DstReg
.WriteMask
= WRITEMASK_XYZW
;
998 vpi_insert
[i
].DstReg
.CondMask
= COND_TR
;
1000 vpi_insert
[i
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
1001 vpi_insert
[i
].SrcReg
[0].Index
= temp_index
;
1002 vpi_insert
[i
].SrcReg
[0].Swizzle
= SWIZZLE_XYZW
;
1005 free(prog
->Instructions
);
1007 prog
->Instructions
= vpi
;
1009 prog
->NumInstructions
+= i
;
1010 vpi
= &prog
->Instructions
[prog
->NumInstructions
-1];
1012 assert(vpi
->Opcode
== OPCODE_END
);
1015 static void pos_as_texcoord(struct r300_vertex_program
*vp
,
1016 struct gl_program
*prog
)
1018 struct prog_instruction
*vpi
;
1019 GLuint tempregi
= prog
->NumTemporaries
;
1020 /* should do something else if no temps left... */
1021 prog
->NumTemporaries
++;
1023 for(vpi
= prog
->Instructions
; vpi
->Opcode
!= OPCODE_END
; vpi
++){
1024 if( vpi
->DstReg
.File
== PROGRAM_OUTPUT
&&
1025 vpi
->DstReg
.Index
== VERT_RESULT_HPOS
){
1026 vpi
->DstReg
.File
= PROGRAM_TEMPORARY
;
1027 vpi
->DstReg
.Index
= tempregi
;
1030 insert_wpos(vp
, prog
, tempregi
);
1033 static struct r300_vertex_program
*build_program(struct r300_vertex_program_key
*wanted_key
,
1034 struct gl_vertex_program
*mesa_vp
,
1037 struct r300_vertex_program
*vp
;
1039 vp
= _mesa_calloc(sizeof(*vp
));
1040 _mesa_memcpy(&vp
->key
, wanted_key
, sizeof(vp
->key
));
1042 vp
->wpos_idx
= wpos_idx
;
1044 if(mesa_vp
->IsPositionInvariant
) {
1045 position_invariant(&mesa_vp
->Base
);
1049 pos_as_texcoord(vp
, &mesa_vp
->Base
);
1051 assert(mesa_vp
->Base
.NumInstructions
);
1053 vp
->num_temporaries
=mesa_vp
->Base
.NumTemporaries
;
1055 r300_translate_vertex_shader(vp
, mesa_vp
->Base
.Instructions
);
1060 void r300_select_vertex_shader(r300ContextPtr r300
)
1062 GLcontext
*ctx
= ctx
= r300
->radeon
.glCtx
;
1064 struct r300_vertex_program_key wanted_key
= { 0 };
1066 struct r300_vertex_program_cont
*vpc
;
1067 struct r300_vertex_program
*vp
;
1070 vpc
= (struct r300_vertex_program_cont
*)ctx
->VertexProgram
._Current
;
1071 InputsRead
= ctx
->FragmentProgram
._Current
->Base
.InputsRead
;
1073 wanted_key
.OutputsWritten
|= 1 << VERT_RESULT_HPOS
;
1076 if (InputsRead
& FRAG_BIT_WPOS
){
1077 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++)
1078 if (!(InputsRead
& (FRAG_BIT_TEX0
<< i
)))
1081 if(i
== ctx
->Const
.MaxTextureUnits
){
1082 fprintf(stderr
, "\tno free texcoord found\n");
1086 InputsRead
|= (FRAG_BIT_TEX0
<< i
);
1090 if (InputsRead
& FRAG_BIT_COL0
)
1091 wanted_key
.OutputsWritten
|= 1 << VERT_RESULT_COL0
;
1093 if ((InputsRead
& FRAG_BIT_COL1
) /*||
1094 (InputsRead & FRAG_BIT_FOGC)*/)
1095 wanted_key
.OutputsWritten
|= 1 << VERT_RESULT_COL1
;
1097 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++)
1098 if (InputsRead
& (FRAG_BIT_TEX0
<< i
))
1099 wanted_key
.OutputsWritten
|= 1 << (VERT_RESULT_TEX0
+ i
);
1101 wanted_key
.InputsRead
= vpc
->mesa_program
.Base
.InputsRead
;
1102 if(vpc
->mesa_program
.IsPositionInvariant
) {
1103 /* we wan't position don't we ? */
1104 wanted_key
.InputsRead
|= (1 << VERT_ATTRIB_POS
);
1107 for (vp
= vpc
->progs
; vp
; vp
= vp
->next
)
1108 if (_mesa_memcmp(&vp
->key
, &wanted_key
, sizeof(wanted_key
)) == 0) {
1109 r300
->selected_vp
= vp
;
1113 //_mesa_print_program(&vpc->mesa_program.Base);
1115 vp
= build_program(&wanted_key
, &vpc
->mesa_program
, wpos_idx
);
1116 vp
->next
= vpc
->progs
;
1118 r300
->selected_vp
= vp
;