st/mesa/r200/i915/i965: eliminate gl_fragment_program
[mesa.git] / src / mesa / drivers / dri / r200 / r200_vertprog.c
1 /**************************************************************************
2
3 Copyright (C) 2005 Aapo Tahkola.
4
5 All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
16 Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 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.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Aapo Tahkola <aet@rasterburn.org>
31 * Roland Scheidegger <rscheidegger_lists@hispeed.ch>
32 */
33 #include "main/glheader.h"
34 #include "main/macros.h"
35 #include "main/enums.h"
36 #include "program/program.h"
37 #include "program/prog_instruction.h"
38 #include "program/prog_parameter.h"
39 #include "program/prog_statevars.h"
40 #include "program/programopt.h"
41 #include "tnl/tnl.h"
42
43 #include "r200_context.h"
44 #include "r200_vertprog.h"
45 #include "r200_ioctl.h"
46 #include "r200_tcl.h"
47
48 #if SWIZZLE_X != VSF_IN_COMPONENT_X || \
49 SWIZZLE_Y != VSF_IN_COMPONENT_Y || \
50 SWIZZLE_Z != VSF_IN_COMPONENT_Z || \
51 SWIZZLE_W != VSF_IN_COMPONENT_W || \
52 SWIZZLE_ZERO != VSF_IN_COMPONENT_ZERO || \
53 SWIZZLE_ONE != VSF_IN_COMPONENT_ONE || \
54 WRITEMASK_X != VSF_FLAG_X || \
55 WRITEMASK_Y != VSF_FLAG_Y || \
56 WRITEMASK_Z != VSF_FLAG_Z || \
57 WRITEMASK_W != VSF_FLAG_W
58 #error Cannot change these!
59 #endif
60
61 #define SCALAR_FLAG (1<<31)
62 #define FLAG_MASK (1<<31)
63 #define OP_MASK (0xf) /* we are unlikely to have more than 15 */
64 #define OPN(operator, ip) {#operator, OPCODE_##operator, ip}
65
66 static struct{
67 char *name;
68 int opcode;
69 unsigned long ip; /* number of input operands and flags */
70 }op_names[]={
71 OPN(ABS, 1),
72 OPN(ADD, 2),
73 OPN(ARL, 1|SCALAR_FLAG),
74 OPN(DP3, 2),
75 OPN(DP4, 2),
76 OPN(DPH, 2),
77 OPN(DST, 2),
78 OPN(EX2, 1|SCALAR_FLAG),
79 OPN(EXP, 1|SCALAR_FLAG),
80 OPN(FLR, 1),
81 OPN(FRC, 1),
82 OPN(LG2, 1|SCALAR_FLAG),
83 OPN(LIT, 1),
84 OPN(LOG, 1|SCALAR_FLAG),
85 OPN(MAD, 3),
86 OPN(MAX, 2),
87 OPN(MIN, 2),
88 OPN(MOV, 1),
89 OPN(MUL, 2),
90 OPN(POW, 2|SCALAR_FLAG),
91 OPN(RCP, 1|SCALAR_FLAG),
92 OPN(RSQ, 1|SCALAR_FLAG),
93 OPN(SGE, 2),
94 OPN(SLT, 2),
95 OPN(SUB, 2),
96 OPN(SWZ, 1),
97 OPN(XPD, 2),
98 OPN(END, 0),
99 };
100 #undef OPN
101
102 static GLboolean r200VertexProgUpdateParams(struct gl_context *ctx, struct r200_vertex_program *vp)
103 {
104 r200ContextPtr rmesa = R200_CONTEXT( ctx );
105 GLfloat *fcmd = (GLfloat *)&rmesa->hw.vpp[0].cmd[VPP_CMD_0 + 1];
106 int pi;
107 struct gl_program *mesa_vp = &vp->mesa_program;
108 struct gl_program_parameter_list *paramList;
109 drm_radeon_cmd_header_t tmp;
110
111 R200_STATECHANGE( rmesa, vpp[0] );
112 R200_STATECHANGE( rmesa, vpp[1] );
113 assert(mesa_vp->Parameters);
114 _mesa_load_state_parameters(ctx, mesa_vp->Parameters);
115 paramList = mesa_vp->Parameters;
116
117 if(paramList->NumParameters > R200_VSF_MAX_PARAM){
118 fprintf(stderr, "%s:Params exhausted\n", __func__);
119 return GL_FALSE;
120 }
121
122 for(pi = 0; pi < paramList->NumParameters; pi++) {
123 switch(paramList->Parameters[pi].Type) {
124 case PROGRAM_STATE_VAR:
125 //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
126 case PROGRAM_CONSTANT:
127 *fcmd++ = paramList->ParameterValues[pi][0].f;
128 *fcmd++ = paramList->ParameterValues[pi][1].f;
129 *fcmd++ = paramList->ParameterValues[pi][2].f;
130 *fcmd++ = paramList->ParameterValues[pi][3].f;
131 break;
132 default:
133 _mesa_problem(NULL, "Bad param type in %s", __func__);
134 break;
135 }
136 if (pi == 95) {
137 fcmd = (GLfloat *)&rmesa->hw.vpp[1].cmd[VPP_CMD_0 + 1];
138 }
139 }
140 /* hack up the cmd_size so not the whole state atom is emitted always. */
141 rmesa->hw.vpp[0].cmd_size =
142 1 + 4 * ((paramList->NumParameters > 96) ? 96 : paramList->NumParameters);
143 tmp.i = rmesa->hw.vpp[0].cmd[VPP_CMD_0];
144 tmp.veclinear.count = (paramList->NumParameters > 96) ? 96 : paramList->NumParameters;
145 rmesa->hw.vpp[0].cmd[VPP_CMD_0] = tmp.i;
146 if (paramList->NumParameters > 96) {
147 rmesa->hw.vpp[1].cmd_size = 1 + 4 * (paramList->NumParameters - 96);
148 tmp.i = rmesa->hw.vpp[1].cmd[VPP_CMD_0];
149 tmp.veclinear.count = paramList->NumParameters - 96;
150 rmesa->hw.vpp[1].cmd[VPP_CMD_0] = tmp.i;
151 }
152 return GL_TRUE;
153 }
154
155 static inline unsigned long t_dst_mask(GLuint mask)
156 {
157 /* WRITEMASK_* is equivalent to VSF_FLAG_* */
158 return mask & VSF_FLAG_ALL;
159 }
160
161 static unsigned long t_dst(struct prog_dst_register *dst)
162 {
163 switch(dst->File) {
164 case PROGRAM_TEMPORARY:
165 return ((dst->Index << R200_VPI_OUT_REG_INDEX_SHIFT)
166 | R200_VSF_OUT_CLASS_TMP);
167 case PROGRAM_OUTPUT:
168 switch (dst->Index) {
169 case VARYING_SLOT_POS:
170 return R200_VSF_OUT_CLASS_RESULT_POS;
171 case VARYING_SLOT_COL0:
172 return R200_VSF_OUT_CLASS_RESULT_COLOR;
173 case VARYING_SLOT_COL1:
174 return ((1 << R200_VPI_OUT_REG_INDEX_SHIFT)
175 | R200_VSF_OUT_CLASS_RESULT_COLOR);
176 case VARYING_SLOT_FOGC:
177 return R200_VSF_OUT_CLASS_RESULT_FOGC;
178 case VARYING_SLOT_TEX0:
179 case VARYING_SLOT_TEX1:
180 case VARYING_SLOT_TEX2:
181 case VARYING_SLOT_TEX3:
182 case VARYING_SLOT_TEX4:
183 case VARYING_SLOT_TEX5:
184 return (((dst->Index - VARYING_SLOT_TEX0) << R200_VPI_OUT_REG_INDEX_SHIFT)
185 | R200_VSF_OUT_CLASS_RESULT_TEXC);
186 case VARYING_SLOT_PSIZ:
187 return R200_VSF_OUT_CLASS_RESULT_POINTSIZE;
188 default:
189 fprintf(stderr, "problem in %s, unknown dst output reg %d\n", __func__, dst->Index);
190 exit(0);
191 return 0;
192 }
193 case PROGRAM_ADDRESS:
194 assert (dst->Index == 0);
195 return R200_VSF_OUT_CLASS_ADDR;
196 default:
197 fprintf(stderr, "problem in %s, unknown register type %d\n", __func__, dst->File);
198 exit(0);
199 return 0;
200 }
201 }
202
203 static unsigned long t_src_class(gl_register_file file)
204 {
205
206 switch(file){
207 case PROGRAM_TEMPORARY:
208 return VSF_IN_CLASS_TMP;
209
210 case PROGRAM_INPUT:
211 return VSF_IN_CLASS_ATTR;
212
213 case PROGRAM_CONSTANT:
214 case PROGRAM_STATE_VAR:
215 return VSF_IN_CLASS_PARAM;
216 /*
217 case PROGRAM_OUTPUT:
218 case PROGRAM_ADDRESS:
219 */
220 default:
221 fprintf(stderr, "problem in %s", __func__);
222 exit(0);
223 }
224 }
225
226 static inline unsigned long t_swizzle(GLubyte swizzle)
227 {
228 /* this is in fact a NOP as the Mesa SWIZZLE_* are all identical to VSF_IN_COMPONENT_* */
229 return swizzle;
230 }
231
232 #if 0
233 static void vp_dump_inputs(struct r200_vertex_program *vp, char *caller)
234 {
235 int i;
236
237 if(vp == NULL){
238 fprintf(stderr, "vp null in call to %s from %s\n", __func__, caller);
239 return ;
240 }
241
242 fprintf(stderr, "%s:<", caller);
243 for(i=0; i < VERT_ATTRIB_MAX; i++)
244 fprintf(stderr, "%d ", vp->inputs[i]);
245 fprintf(stderr, ">\n");
246
247 }
248 #endif
249
250 static unsigned long t_src_index(struct r200_vertex_program *vp, struct prog_src_register *src)
251 {
252 /*
253 int i;
254 int max_reg = -1;
255 */
256 if(src->File == PROGRAM_INPUT){
257 /* if(vp->inputs[src->Index] != -1)
258 return vp->inputs[src->Index];
259
260 for(i=0; i < VERT_ATTRIB_MAX; i++)
261 if(vp->inputs[i] > max_reg)
262 max_reg = vp->inputs[i];
263
264 vp->inputs[src->Index] = max_reg+1;*/
265
266 //vp_dump_inputs(vp, __func__);
267 assert(vp->inputs[src->Index] != -1);
268 return vp->inputs[src->Index];
269 } else {
270 if (src->Index < 0) {
271 fprintf(stderr, "WARNING negative offsets for indirect addressing do not work\n");
272 return 0;
273 }
274 return src->Index;
275 }
276 }
277
278 static unsigned long t_src(struct r200_vertex_program *vp, struct prog_src_register *src)
279 {
280
281 return MAKE_VSF_SOURCE(t_src_index(vp, src),
282 t_swizzle(GET_SWZ(src->Swizzle, 0)),
283 t_swizzle(GET_SWZ(src->Swizzle, 1)),
284 t_swizzle(GET_SWZ(src->Swizzle, 2)),
285 t_swizzle(GET_SWZ(src->Swizzle, 3)),
286 t_src_class(src->File),
287 src->Negate) | (src->RelAddr << 4);
288 }
289
290 static unsigned long t_src_scalar(struct r200_vertex_program *vp, struct prog_src_register *src)
291 {
292
293 return MAKE_VSF_SOURCE(t_src_index(vp, src),
294 t_swizzle(GET_SWZ(src->Swizzle, 0)),
295 t_swizzle(GET_SWZ(src->Swizzle, 0)),
296 t_swizzle(GET_SWZ(src->Swizzle, 0)),
297 t_swizzle(GET_SWZ(src->Swizzle, 0)),
298 t_src_class(src->File),
299 src->Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src->RelAddr << 4);
300 }
301
302 static unsigned long t_opcode(enum prog_opcode opcode)
303 {
304
305 switch(opcode){
306 case OPCODE_ADD: return R200_VPI_OUT_OP_ADD;
307 /* FIXME: ARL works fine, but negative offsets won't work - fglrx just
308 * seems to ignore neg offsets which isn't quite correct...
309 */
310 case OPCODE_ARL: return R200_VPI_OUT_OP_ARL;
311 case OPCODE_DP4: return R200_VPI_OUT_OP_DOT;
312 case OPCODE_DST: return R200_VPI_OUT_OP_DST;
313 case OPCODE_EX2: return R200_VPI_OUT_OP_EX2;
314 case OPCODE_EXP: return R200_VPI_OUT_OP_EXP;
315 case OPCODE_FRC: return R200_VPI_OUT_OP_FRC;
316 case OPCODE_LG2: return R200_VPI_OUT_OP_LG2;
317 case OPCODE_LIT: return R200_VPI_OUT_OP_LIT;
318 case OPCODE_LOG: return R200_VPI_OUT_OP_LOG;
319 case OPCODE_MAX: return R200_VPI_OUT_OP_MAX;
320 case OPCODE_MIN: return R200_VPI_OUT_OP_MIN;
321 case OPCODE_MUL: return R200_VPI_OUT_OP_MUL;
322 case OPCODE_RCP: return R200_VPI_OUT_OP_RCP;
323 case OPCODE_RSQ: return R200_VPI_OUT_OP_RSQ;
324 case OPCODE_SGE: return R200_VPI_OUT_OP_SGE;
325 case OPCODE_SLT: return R200_VPI_OUT_OP_SLT;
326
327 default:
328 fprintf(stderr, "%s: Should not be called with opcode %d!", __func__, opcode);
329 }
330 exit(-1);
331 return 0;
332 }
333
334 static unsigned long op_operands(enum prog_opcode opcode)
335 {
336 int i;
337
338 /* Can we trust mesas opcodes to be in order ? */
339 for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++)
340 if(op_names[i].opcode == opcode)
341 return op_names[i].ip;
342
343 fprintf(stderr, "op %d not found in op_names\n", opcode);
344 exit(-1);
345 return 0;
346 }
347
348 /* TODO: Get rid of t_src_class call */
349 #define CMP_SRCS(a, b) (((a.RelAddr != b.RelAddr) || (a.Index != b.Index)) && \
350 ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \
351 t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \
352 (t_src_class(a.File) == VSF_IN_CLASS_ATTR && \
353 t_src_class(b.File) == VSF_IN_CLASS_ATTR))) \
354
355 /* fglrx on rv250 codes up unused sources as follows:
356 unused but necessary sources are same as previous source, zero-ed out.
357 unnecessary sources are same as previous source but with VSF_IN_CLASS_NONE set.
358 i.e. an add (2 args) has its 2nd arg (if you use it as mov) zero-ed out, and 3rd arg
359 set to VSF_IN_CLASS_NONE. Not sure if strictly necessary. */
360
361 /* use these simpler definitions. Must obviously not be used with not yet set up regs.
362 Those are NOT semantically equivalent to the r300 ones, requires code changes */
363 #define ZERO_SRC_0 (((o_inst->src0 & ~(0xfff << R200_VPI_IN_X_SHIFT)) \
364 | ((R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_X_SHIFT) \
365 | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Y_SHIFT) \
366 | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Z_SHIFT) \
367 | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_W_SHIFT))))
368
369 #define ZERO_SRC_1 (((o_inst->src1 & ~(0xfff << R200_VPI_IN_X_SHIFT)) \
370 | ((R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_X_SHIFT) \
371 | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Y_SHIFT) \
372 | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Z_SHIFT) \
373 | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_W_SHIFT))))
374
375 #define ZERO_SRC_2 (((o_inst->src2 & ~(0xfff << R200_VPI_IN_X_SHIFT)) \
376 | ((R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_X_SHIFT) \
377 | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Y_SHIFT) \
378 | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Z_SHIFT) \
379 | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_W_SHIFT))))
380
381 #define UNUSED_SRC_0 ((o_inst->src0 & ~15) | 9)
382
383 #define UNUSED_SRC_1 ((o_inst->src1 & ~15) | 9)
384
385 #define UNUSED_SRC_2 ((o_inst->src2 & ~15) | 9)
386
387
388 /**
389 * Generate an R200 vertex program from Mesa's internal representation.
390 *
391 * \return GL_TRUE for success, GL_FALSE for failure.
392 */
393 static GLboolean r200_translate_vertex_program(struct gl_context *ctx, struct r200_vertex_program *vp)
394 {
395 struct gl_program *mesa_vp = &vp->mesa_program;
396 struct prog_instruction *vpi;
397 int i;
398 VERTEX_SHADER_INSTRUCTION *o_inst;
399 unsigned long operands;
400 int are_srcs_scalar;
401 unsigned long hw_op;
402 int dofogfix = 0;
403 int fog_temp_i = 0;
404 int free_inputs;
405 int array_count = 0;
406 int u_temp_used;
407
408 vp->native = GL_FALSE;
409 vp->translated = GL_TRUE;
410 vp->fogmode = ctx->Fog.Mode;
411
412 if (mesa_vp->NumInstructions == 0)
413 return GL_FALSE;
414
415 #if 0
416 if ((mesa_vp->InputsRead &
417 ~(VERT_BIT_POS | VERT_BIT_NORMAL | VERT_BIT_COLOR0 | VERT_BIT_COLOR1 |
418 VERT_BIT_FOG | VERT_BIT_TEX0 | VERT_BIT_TEX1 | VERT_BIT_TEX2 |
419 VERT_BIT_TEX3 | VERT_BIT_TEX4 | VERT_BIT_TEX5)) != 0) {
420 if (R200_DEBUG & RADEON_FALLBACKS) {
421 fprintf(stderr, "can't handle vert prog inputs 0x%x\n",
422 mesa_vp->InputsRead);
423 }
424 return GL_FALSE;
425 }
426 #endif
427
428 if ((mesa_vp->OutputsWritten &
429 ~((1 << VARYING_SLOT_POS) | (1 << VARYING_SLOT_COL0) | (1 << VARYING_SLOT_COL1) |
430 (1 << VARYING_SLOT_FOGC) | (1 << VARYING_SLOT_TEX0) | (1 << VARYING_SLOT_TEX1) |
431 (1 << VARYING_SLOT_TEX2) | (1 << VARYING_SLOT_TEX3) | (1 << VARYING_SLOT_TEX4) |
432 (1 << VARYING_SLOT_TEX5) | (1 << VARYING_SLOT_PSIZ))) != 0) {
433 if (R200_DEBUG & RADEON_FALLBACKS) {
434 fprintf(stderr, "can't handle vert prog outputs 0x%llx\n",
435 (unsigned long long) mesa_vp->OutputsWritten);
436 }
437 return GL_FALSE;
438 }
439
440 /* Initial value should be last tmp reg that hw supports.
441 Strangely enough r300 doesnt mind even though these would be out of range.
442 Smart enough to realize that it doesnt need it? */
443 int u_temp_i = R200_VSF_MAX_TEMPS - 1;
444 struct prog_src_register src[3];
445 struct prog_dst_register dst;
446
447 /* FIXME: is changing the prog safe to do here? */
448 if (mesa_vp->IsPositionInvariant &&
449 /* make sure we only do this once */
450 !(mesa_vp->OutputsWritten & (1 << VARYING_SLOT_POS))) {
451 _mesa_insert_mvp_code(ctx, mesa_vp);
452 }
453
454 /* for fogc, can't change mesa_vp, as it would hose swtnl, and exp with
455 base e isn't directly available neither. */
456 if ((mesa_vp->OutputsWritten & (1 << VARYING_SLOT_FOGC)) && !vp->fogpidx) {
457 struct gl_program_parameter_list *paramList;
458 gl_state_index tokens[STATE_LENGTH] = { STATE_FOG_PARAMS, 0, 0, 0, 0 };
459 paramList = mesa_vp->Parameters;
460 vp->fogpidx = _mesa_add_state_reference(paramList, tokens);
461 }
462
463 vp->pos_end = 0;
464 mesa_vp->NumNativeInstructions = 0;
465 if (mesa_vp->Parameters)
466 mesa_vp->NumNativeParameters = mesa_vp->Parameters->NumParameters;
467 else
468 mesa_vp->NumNativeParameters = 0;
469
470 for(i = 0; i < VERT_ATTRIB_MAX; i++)
471 vp->inputs[i] = -1;
472 for(i = 0; i < 15; i++)
473 vp->inputmap_rev[i] = 255;
474 free_inputs = 0x2ffd;
475
476 /* fglrx uses fixed inputs as follows for conventional attribs.
477 generic attribs use non-fixed assignment, fglrx will always use the
478 lowest attrib values available. We'll just do the same.
479 There are 12 generic attribs possible, corresponding to attrib 0, 2-11
480 and 13 in a hw vertex prog.
481 attr 1 and 12 aren't used for generic attribs as those cannot be made vec4
482 (correspond to vertex normal/weight - maybe weight actually could be made vec4).
483 Additionally, not more than 12 arrays in total are possible I think.
484 attr 0 is pos, R200_VTX_XY1|R200_VTX_Z1|R200_VTX_W1 in R200_SE_VTX_FMT_0
485 attr 2-5 use colors 0-3 (R200_VTX_FP_RGBA << R200_VTX_COLOR_0/1/2/3_SHIFT in R200_SE_VTX_FMT_0)
486 attr 6-11 use tex 0-5 (4 << R200_VTX_TEX0/1/2/3/4/5_COMP_CNT_SHIFT in R200_SE_VTX_FMT_1)
487 attr 13 uses vtx1 pos (R200_VTX_XY1|R200_VTX_Z1|R200_VTX_W1 in R200_SE_VTX_FMT_0)
488 */
489
490 /* attr 4,5 and 13 are only used with generic attribs.
491 Haven't seen attr 14 used, maybe that's for the hw pointsize vec1 (which is
492 not possibe to use with vertex progs as it is lacking in vert prog specification) */
493 /* may look different when using idx buf / input_route instead of se_vtx_fmt? */
494 if (mesa_vp->InputsRead & VERT_BIT_POS) {
495 vp->inputs[VERT_ATTRIB_POS] = 0;
496 vp->inputmap_rev[0] = VERT_ATTRIB_POS;
497 free_inputs &= ~(1 << 0);
498 array_count++;
499 }
500 if (mesa_vp->InputsRead & VERT_BIT_WEIGHT) {
501 vp->inputs[VERT_ATTRIB_WEIGHT] = 12;
502 vp->inputmap_rev[1] = VERT_ATTRIB_WEIGHT;
503 array_count++;
504 }
505 if (mesa_vp->InputsRead & VERT_BIT_NORMAL) {
506 vp->inputs[VERT_ATTRIB_NORMAL] = 1;
507 vp->inputmap_rev[2] = VERT_ATTRIB_NORMAL;
508 array_count++;
509 }
510 if (mesa_vp->InputsRead & VERT_BIT_COLOR0) {
511 vp->inputs[VERT_ATTRIB_COLOR0] = 2;
512 vp->inputmap_rev[4] = VERT_ATTRIB_COLOR0;
513 free_inputs &= ~(1 << 2);
514 array_count++;
515 }
516 if (mesa_vp->InputsRead & VERT_BIT_COLOR1) {
517 vp->inputs[VERT_ATTRIB_COLOR1] = 3;
518 vp->inputmap_rev[5] = VERT_ATTRIB_COLOR1;
519 free_inputs &= ~(1 << 3);
520 array_count++;
521 }
522 if (mesa_vp->InputsRead & VERT_BIT_FOG) {
523 vp->inputs[VERT_ATTRIB_FOG] = 15; array_count++;
524 vp->inputmap_rev[3] = VERT_ATTRIB_FOG;
525 array_count++;
526 }
527 /* VERT_ATTRIB_TEX0-5 */
528 for (i = 0; i <= 5; i++) {
529 if (mesa_vp->InputsRead & VERT_BIT_TEX(i)) {
530 vp->inputs[VERT_ATTRIB_TEX(i)] = i + 6;
531 vp->inputmap_rev[8 + i] = VERT_ATTRIB_TEX(i);
532 free_inputs &= ~(1 << (i + 6));
533 array_count++;
534 }
535 }
536 /* using VERT_ATTRIB_TEX6/7 would be illegal */
537 for (; i < VERT_ATTRIB_TEX_MAX; i++) {
538 if (mesa_vp->InputsRead & VERT_BIT_TEX(i)) {
539 if (R200_DEBUG & RADEON_FALLBACKS) {
540 fprintf(stderr, "texture attribute %d in vert prog\n", i);
541 }
542 return GL_FALSE;
543 }
544 }
545 /* completely ignore aliasing? */
546 for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
547 int j;
548 /* completely ignore aliasing? */
549 if (mesa_vp->InputsRead & VERT_BIT_GENERIC(i)) {
550 array_count++;
551 if (array_count > 12) {
552 if (R200_DEBUG & RADEON_FALLBACKS) {
553 fprintf(stderr, "more than 12 attribs used in vert prog\n");
554 }
555 return GL_FALSE;
556 }
557 for (j = 0; j < 14; j++) {
558 /* will always find one due to limited array_count */
559 if (free_inputs & (1 << j)) {
560 free_inputs &= ~(1 << j);
561 vp->inputs[VERT_ATTRIB_GENERIC(i)] = j;
562 if (j == 0) {
563 /* mapped to pos */
564 vp->inputmap_rev[j] = VERT_ATTRIB_GENERIC(i);
565 } else if (j < 12) {
566 /* mapped to col/tex */
567 vp->inputmap_rev[j + 2] = VERT_ATTRIB_GENERIC(i);
568 } else {
569 /* mapped to pos1 */
570 vp->inputmap_rev[j + 1] = VERT_ATTRIB_GENERIC(i);
571 }
572 break;
573 }
574 }
575 }
576 }
577
578 if (!(mesa_vp->OutputsWritten & (1 << VARYING_SLOT_POS))) {
579 if (R200_DEBUG & RADEON_FALLBACKS) {
580 fprintf(stderr, "can't handle vert prog without position output\n");
581 }
582 return GL_FALSE;
583 }
584 if (free_inputs & 1) {
585 if (R200_DEBUG & RADEON_FALLBACKS) {
586 fprintf(stderr, "can't handle vert prog without position input\n");
587 }
588 return GL_FALSE;
589 }
590
591 o_inst = vp->instr;
592 for (vpi = mesa_vp->Instructions; vpi->Opcode != OPCODE_END; vpi++, o_inst++){
593 operands = op_operands(vpi->Opcode);
594 are_srcs_scalar = operands & SCALAR_FLAG;
595 operands &= OP_MASK;
596
597 for(i = 0; i < operands; i++) {
598 src[i] = vpi->SrcReg[i];
599 /* hack up default attrib values as per spec as swizzling.
600 normal, fog, secondary color. Crazy?
601 May need more if we don't submit vec4 elements? */
602 if (src[i].File == PROGRAM_INPUT) {
603 if (src[i].Index == VERT_ATTRIB_NORMAL) {
604 int j;
605 for (j = 0; j < 4; j++) {
606 if (GET_SWZ(src[i].Swizzle, j) == SWIZZLE_W) {
607 src[i].Swizzle &= ~(SWIZZLE_W << (j*3));
608 src[i].Swizzle |= SWIZZLE_ONE << (j*3);
609 }
610 }
611 }
612 else if (src[i].Index == VERT_ATTRIB_COLOR1) {
613 int j;
614 for (j = 0; j < 4; j++) {
615 if (GET_SWZ(src[i].Swizzle, j) == SWIZZLE_W) {
616 src[i].Swizzle &= ~(SWIZZLE_W << (j*3));
617 src[i].Swizzle |= SWIZZLE_ZERO << (j*3);
618 }
619 }
620 }
621 else if (src[i].Index == VERT_ATTRIB_FOG) {
622 int j;
623 for (j = 0; j < 4; j++) {
624 if (GET_SWZ(src[i].Swizzle, j) == SWIZZLE_W) {
625 src[i].Swizzle &= ~(SWIZZLE_W << (j*3));
626 src[i].Swizzle |= SWIZZLE_ONE << (j*3);
627 }
628 else if ((GET_SWZ(src[i].Swizzle, j) == SWIZZLE_Y) ||
629 GET_SWZ(src[i].Swizzle, j) == SWIZZLE_Z) {
630 src[i].Swizzle &= ~(SWIZZLE_W << (j*3));
631 src[i].Swizzle |= SWIZZLE_ZERO << (j*3);
632 }
633 }
634 }
635 }
636 }
637
638 if(operands == 3){
639 if( CMP_SRCS(src[1], src[2]) || CMP_SRCS(src[0], src[2]) ){
640 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD,
641 (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
642 VSF_FLAG_ALL);
643
644 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[2]),
645 SWIZZLE_X, SWIZZLE_Y,
646 SWIZZLE_Z, SWIZZLE_W,
647 t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4);
648
649 o_inst->src1 = ZERO_SRC_0;
650 o_inst->src2 = UNUSED_SRC_1;
651 o_inst++;
652
653 src[2].File = PROGRAM_TEMPORARY;
654 src[2].Index = u_temp_i;
655 src[2].RelAddr = 0;
656 u_temp_i--;
657 }
658 }
659
660 if(operands >= 2){
661 if( CMP_SRCS(src[1], src[0]) ){
662 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD,
663 (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
664 VSF_FLAG_ALL);
665
666 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
667 SWIZZLE_X, SWIZZLE_Y,
668 SWIZZLE_Z, SWIZZLE_W,
669 t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4);
670
671 o_inst->src1 = ZERO_SRC_0;
672 o_inst->src2 = UNUSED_SRC_1;
673 o_inst++;
674
675 src[0].File = PROGRAM_TEMPORARY;
676 src[0].Index = u_temp_i;
677 src[0].RelAddr = 0;
678 u_temp_i--;
679 }
680 }
681
682 dst = vpi->DstReg;
683 if (dst.File == PROGRAM_OUTPUT &&
684 dst.Index == VARYING_SLOT_FOGC &&
685 dst.WriteMask & WRITEMASK_X) {
686 fog_temp_i = u_temp_i;
687 dst.File = PROGRAM_TEMPORARY;
688 dst.Index = fog_temp_i;
689 dofogfix = 1;
690 u_temp_i--;
691 }
692
693 /* These ops need special handling. */
694 switch(vpi->Opcode){
695 case OPCODE_POW:
696 /* pow takes only one argument, first scalar is in slot x, 2nd in slot z (other slots don't matter).
697 So may need to insert additional instruction */
698 if ((src[0].File == src[1].File) &&
699 (src[0].Index == src[1].Index)) {
700 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_POW, t_dst(&dst),
701 t_dst_mask(dst.WriteMask));
702 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
703 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
704 SWIZZLE_ZERO,
705 t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
706 SWIZZLE_ZERO,
707 t_src_class(src[0].File),
708 src[0].Negate) | (src[0].RelAddr << 4);
709 o_inst->src1 = UNUSED_SRC_0;
710 o_inst->src2 = UNUSED_SRC_0;
711 }
712 else {
713 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD,
714 (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
715 VSF_FLAG_ALL);
716 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
717 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
718 SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO,
719 t_src_class(src[0].File),
720 src[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
721 o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
722 SWIZZLE_ZERO, SWIZZLE_ZERO,
723 t_swizzle(GET_SWZ(src[1].Swizzle, 0)), SWIZZLE_ZERO,
724 t_src_class(src[1].File),
725 src[1].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
726 o_inst->src2 = UNUSED_SRC_1;
727 o_inst++;
728
729 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_POW, t_dst(&dst),
730 t_dst_mask(dst.WriteMask));
731 o_inst->src0 = MAKE_VSF_SOURCE(u_temp_i,
732 VSF_IN_COMPONENT_X,
733 VSF_IN_COMPONENT_Y,
734 VSF_IN_COMPONENT_Z,
735 VSF_IN_COMPONENT_W,
736 VSF_IN_CLASS_TMP,
737 VSF_FLAG_NONE);
738 o_inst->src1 = UNUSED_SRC_0;
739 o_inst->src2 = UNUSED_SRC_0;
740 u_temp_i--;
741 }
742 goto next;
743
744 case OPCODE_MOV://ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO}
745 case OPCODE_SWZ:
746 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst),
747 t_dst_mask(dst.WriteMask));
748 o_inst->src0 = t_src(vp, &src[0]);
749 o_inst->src1 = ZERO_SRC_0;
750 o_inst->src2 = UNUSED_SRC_1;
751 goto next;
752
753 case OPCODE_MAD:
754 /* only 2 read ports into temp memory thus may need the macro op MAD_2
755 instead (requiring 2 clocks) if all inputs are in temp memory
756 (and, only if they actually reference 3 distinct temps) */
757 hw_op=(src[0].File == PROGRAM_TEMPORARY &&
758 src[1].File == PROGRAM_TEMPORARY &&
759 src[2].File == PROGRAM_TEMPORARY &&
760 (((src[0].RelAddr << 8) | src[0].Index) != ((src[1].RelAddr << 8) | src[1].Index)) &&
761 (((src[0].RelAddr << 8) | src[0].Index) != ((src[2].RelAddr << 8) | src[2].Index)) &&
762 (((src[1].RelAddr << 8) | src[1].Index) != ((src[2].RelAddr << 8) | src[2].Index))) ?
763 R200_VPI_OUT_OP_MAD_2 : R200_VPI_OUT_OP_MAD;
764
765 o_inst->op = MAKE_VSF_OP(hw_op, t_dst(&dst),
766 t_dst_mask(dst.WriteMask));
767 o_inst->src0 = t_src(vp, &src[0]);
768 #if 0
769 if ((o_inst - vp->instr) == 31) {
770 /* fix up the broken vertex program of quake4 demo... */
771 o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
772 SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X,
773 t_src_class(src[1].File),
774 src[1].Negate) | (src[1].RelAddr << 4);
775 o_inst->src2 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
776 SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y,
777 t_src_class(src[1].File),
778 src[1].Negate) | (src[1].RelAddr << 4);
779 }
780 else {
781 o_inst->src1 = t_src(vp, &src[1]);
782 o_inst->src2 = t_src(vp, &src[2]);
783 }
784 #else
785 o_inst->src1 = t_src(vp, &src[1]);
786 o_inst->src2 = t_src(vp, &src[2]);
787 #endif
788 goto next;
789
790 case OPCODE_DP3://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO}
791 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_DOT, t_dst(&dst),
792 t_dst_mask(dst.WriteMask));
793
794 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
795 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
796 t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
797 t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
798 SWIZZLE_ZERO,
799 t_src_class(src[0].File),
800 src[0].Negate) | (src[0].RelAddr << 4);
801
802 o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
803 t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
804 t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
805 t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
806 SWIZZLE_ZERO,
807 t_src_class(src[1].File),
808 src[1].Negate) | (src[1].RelAddr << 4);
809
810 o_inst->src2 = UNUSED_SRC_1;
811 goto next;
812
813 case OPCODE_DPH://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W}
814 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_DOT, t_dst(&dst),
815 t_dst_mask(dst.WriteMask));
816
817 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
818 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
819 t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
820 t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
821 VSF_IN_COMPONENT_ONE,
822 t_src_class(src[0].File),
823 src[0].Negate) | (src[0].RelAddr << 4);
824 o_inst->src1 = t_src(vp, &src[1]);
825 o_inst->src2 = UNUSED_SRC_1;
826 goto next;
827
828 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
829 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst),
830 t_dst_mask(dst.WriteMask));
831
832 o_inst->src0 = t_src(vp, &src[0]);
833 o_inst->src1 = MAKE_VSF_SOURCE(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),
839 (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
840 o_inst->src2 = UNUSED_SRC_1;
841 goto next;
842
843 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
844 o_inst->op=MAKE_VSF_OP(R200_VPI_OUT_OP_MAX, t_dst(&dst),
845 t_dst_mask(dst.WriteMask));
846
847 o_inst->src0=t_src(vp, &src[0]);
848 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
849 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
850 t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
851 t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
852 t_swizzle(GET_SWZ(src[0].Swizzle, 3)),
853 t_src_class(src[0].File),
854 (!src[0].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
855 o_inst->src2 = UNUSED_SRC_1;
856 goto next;
857
858 case OPCODE_FLR:
859 /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W}
860 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 */
861
862 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_FRC,
863 (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
864 t_dst_mask(dst.WriteMask));
865
866 o_inst->src0 = t_src(vp, &src[0]);
867 o_inst->src1 = UNUSED_SRC_0;
868 o_inst->src2 = UNUSED_SRC_1;
869 o_inst++;
870
871 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst),
872 t_dst_mask(dst.WriteMask));
873
874 o_inst->src0 = t_src(vp, &src[0]);
875 o_inst->src1 = MAKE_VSF_SOURCE(u_temp_i,
876 VSF_IN_COMPONENT_X,
877 VSF_IN_COMPONENT_Y,
878 VSF_IN_COMPONENT_Z,
879 VSF_IN_COMPONENT_W,
880 VSF_IN_CLASS_TMP,
881 /* Not 100% sure about this */
882 (!src[0].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/);
883
884 o_inst->src2 = UNUSED_SRC_0;
885 u_temp_i--;
886 goto next;
887
888 case OPCODE_XPD:
889 /* mul r0, r1.yzxw, r2.zxyw
890 mad r0, -r2.yzxw, r1.zxyw, r0
891 */
892 hw_op=(src[0].File == PROGRAM_TEMPORARY &&
893 src[1].File == PROGRAM_TEMPORARY &&
894 (((src[0].RelAddr << 8) | src[0].Index) != ((src[1].RelAddr << 8) | src[1].Index))) ?
895 R200_VPI_OUT_OP_MAD_2 : R200_VPI_OUT_OP_MAD;
896
897 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL,
898 (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
899 t_dst_mask(dst.WriteMask));
900
901 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
902 t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
903 t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z
904 t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
905 t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
906 t_src_class(src[0].File),
907 src[0].Negate) | (src[0].RelAddr << 4);
908
909 o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
910 t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z
911 t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x
912 t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y
913 t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w
914 t_src_class(src[1].File),
915 src[1].Negate) | (src[1].RelAddr << 4);
916
917 o_inst->src2 = UNUSED_SRC_1;
918 o_inst++;
919 u_temp_i--;
920
921 o_inst->op = MAKE_VSF_OP(hw_op, t_dst(&dst),
922 t_dst_mask(dst.WriteMask));
923
924 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
925 t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y
926 t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z
927 t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x
928 t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w
929 t_src_class(src[1].File),
930 (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
931
932 o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
933 t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z
934 t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
935 t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
936 t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
937 t_src_class(src[0].File),
938 src[0].Negate) | (src[0].RelAddr << 4);
939
940 o_inst->src2 = MAKE_VSF_SOURCE(u_temp_i+1,
941 VSF_IN_COMPONENT_X,
942 VSF_IN_COMPONENT_Y,
943 VSF_IN_COMPONENT_Z,
944 VSF_IN_COMPONENT_W,
945 VSF_IN_CLASS_TMP,
946 VSF_FLAG_NONE);
947 goto next;
948
949 case OPCODE_END:
950 assert(0);
951 default:
952 break;
953 }
954
955 o_inst->op = MAKE_VSF_OP(t_opcode(vpi->Opcode), t_dst(&dst),
956 t_dst_mask(dst.WriteMask));
957
958 if(are_srcs_scalar){
959 switch(operands){
960 case 1:
961 o_inst->src0 = t_src_scalar(vp, &src[0]);
962 o_inst->src1 = UNUSED_SRC_0;
963 o_inst->src2 = UNUSED_SRC_1;
964 break;
965
966 case 2:
967 o_inst->src0 = t_src_scalar(vp, &src[0]);
968 o_inst->src1 = t_src_scalar(vp, &src[1]);
969 o_inst->src2 = UNUSED_SRC_1;
970 break;
971
972 case 3:
973 o_inst->src0 = t_src_scalar(vp, &src[0]);
974 o_inst->src1 = t_src_scalar(vp, &src[1]);
975 o_inst->src2 = t_src_scalar(vp, &src[2]);
976 break;
977
978 default:
979 fprintf(stderr, "illegal number of operands %lu\n", operands);
980 exit(-1);
981 break;
982 }
983 } else {
984 switch(operands){
985 case 1:
986 o_inst->src0 = t_src(vp, &src[0]);
987 o_inst->src1 = UNUSED_SRC_0;
988 o_inst->src2 = UNUSED_SRC_1;
989 break;
990
991 case 2:
992 o_inst->src0 = t_src(vp, &src[0]);
993 o_inst->src1 = t_src(vp, &src[1]);
994 o_inst->src2 = UNUSED_SRC_1;
995 break;
996
997 case 3:
998 o_inst->src0 = t_src(vp, &src[0]);
999 o_inst->src1 = t_src(vp, &src[1]);
1000 o_inst->src2 = t_src(vp, &src[2]);
1001 break;
1002
1003 default:
1004 fprintf(stderr, "illegal number of operands %lu\n", operands);
1005 exit(-1);
1006 break;
1007 }
1008 }
1009 next:
1010
1011 if (dofogfix) {
1012 o_inst++;
1013 if (vp->fogmode == GL_EXP) {
1014 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL,
1015 (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
1016 VSF_FLAG_X);
1017 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE);
1018 o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, X, X, X, X, PARAM, NONE);
1019 o_inst->src2 = UNUSED_SRC_1;
1020 o_inst++;
1021 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_EXP_E,
1022 R200_VSF_OUT_CLASS_RESULT_FOGC,
1023 VSF_FLAG_X);
1024 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL);
1025 o_inst->src1 = UNUSED_SRC_0;
1026 o_inst->src2 = UNUSED_SRC_1;
1027 }
1028 else if (vp->fogmode == GL_EXP2) {
1029 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL,
1030 (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
1031 VSF_FLAG_X);
1032 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE);
1033 o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, X, X, X, X, PARAM, NONE);
1034 o_inst->src2 = UNUSED_SRC_1;
1035 o_inst++;
1036 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL,
1037 (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
1038 VSF_FLAG_X);
1039 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE);
1040 o_inst->src1 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE);
1041 o_inst->src2 = UNUSED_SRC_1;
1042 o_inst++;
1043 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_EXP_E,
1044 R200_VSF_OUT_CLASS_RESULT_FOGC,
1045 VSF_FLAG_X);
1046 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL);
1047 o_inst->src1 = UNUSED_SRC_0;
1048 o_inst->src2 = UNUSED_SRC_1;
1049 }
1050 else { /* fogmode == GL_LINEAR */
1051 /* could do that with single op (dot) if using params like
1052 with fixed function pipeline fog */
1053 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD,
1054 (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
1055 VSF_FLAG_X);
1056 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL);
1057 o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, Z, Z, Z, Z, PARAM, NONE);
1058 o_inst->src2 = UNUSED_SRC_1;
1059 o_inst++;
1060 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL,
1061 R200_VSF_OUT_CLASS_RESULT_FOGC,
1062 VSF_FLAG_X);
1063 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE);
1064 o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, W, W, W, W, PARAM, NONE);
1065 o_inst->src2 = UNUSED_SRC_1;
1066
1067 }
1068 dofogfix = 0;
1069 }
1070
1071 u_temp_used = (R200_VSF_MAX_TEMPS - 1) - u_temp_i;
1072 if (mesa_vp->NumNativeTemporaries <
1073 (mesa_vp->NumTemporaries + u_temp_used)) {
1074 mesa_vp->NumNativeTemporaries =
1075 mesa_vp->NumTemporaries + u_temp_used;
1076 }
1077 if ((mesa_vp->NumTemporaries + u_temp_used) > R200_VSF_MAX_TEMPS) {
1078 if (R200_DEBUG & RADEON_FALLBACKS) {
1079 fprintf(stderr, "Ran out of temps, num temps %d, us %d\n", mesa_vp->NumTemporaries, u_temp_used);
1080 }
1081 return GL_FALSE;
1082 }
1083 u_temp_i = R200_VSF_MAX_TEMPS - 1;
1084 if(o_inst - vp->instr >= R200_VSF_MAX_INST) {
1085 mesa_vp->NumNativeInstructions = 129;
1086 if (R200_DEBUG & RADEON_FALLBACKS) {
1087 fprintf(stderr, "more than 128 native instructions\n");
1088 }
1089 return GL_FALSE;
1090 }
1091 if ((o_inst->op & R200_VSF_OUT_CLASS_MASK) == R200_VSF_OUT_CLASS_RESULT_POS) {
1092 vp->pos_end = (o_inst - vp->instr);
1093 }
1094 }
1095
1096 vp->native = GL_TRUE;
1097 mesa_vp->NumNativeInstructions = (o_inst - vp->instr);
1098 #if 0
1099 fprintf(stderr, "hw program:\n");
1100 for(i=0; i < vp->program.length; i++)
1101 fprintf(stderr, "%08x\n", vp->instr[i]);
1102 #endif
1103 return GL_TRUE;
1104 }
1105
1106 void r200SetupVertexProg( struct gl_context *ctx ) {
1107 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1108 struct r200_vertex_program *vp = (struct r200_vertex_program *)ctx->VertexProgram.Current;
1109 GLboolean fallback;
1110 GLint i;
1111
1112 if (!vp->translated || (ctx->Fog.Enabled && ctx->Fog.Mode != vp->fogmode)) {
1113 rmesa->curr_vp_hw = NULL;
1114 r200_translate_vertex_program(ctx, vp);
1115 }
1116 /* could optimize setting up vertex progs away for non-tcl hw */
1117 fallback = !(vp->native && r200VertexProgUpdateParams(ctx, vp));
1118 TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, fallback);
1119 if (rmesa->radeon.TclFallback) return;
1120
1121 R200_STATECHANGE( rmesa, vap );
1122 /* FIXME: fglrx sets R200_VAP_SINGLE_BUF_STATE_ENABLE too. Do we need it?
1123 maybe only when using more than 64 inst / 96 param? */
1124 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_PROG_VTX_SHADER_ENABLE /*| R200_VAP_SINGLE_BUF_STATE_ENABLE*/;
1125
1126 R200_STATECHANGE( rmesa, pvs );
1127
1128 rmesa->hw.pvs.cmd[PVS_CNTL_1] = (0 << R200_PVS_CNTL_1_PROGRAM_START_SHIFT) |
1129 ((vp->mesa_program.NumNativeInstructions - 1) << R200_PVS_CNTL_1_PROGRAM_END_SHIFT) |
1130 (vp->pos_end << R200_PVS_CNTL_1_POS_END_SHIFT);
1131 rmesa->hw.pvs.cmd[PVS_CNTL_2] = (0 << R200_PVS_CNTL_2_PARAM_OFFSET_SHIFT) |
1132 (vp->mesa_program.NumNativeParameters << R200_PVS_CNTL_2_PARAM_COUNT_SHIFT);
1133
1134 /* maybe user clip planes just work with vertex progs... untested */
1135 if (ctx->Transform.ClipPlanesEnabled) {
1136 R200_STATECHANGE( rmesa, tcl );
1137 if (vp->mesa_program.IsPositionInvariant) {
1138 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (ctx->Transform.ClipPlanesEnabled << 2);
1139 }
1140 else {
1141 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(0xfc);
1142 }
1143 }
1144
1145 if (vp != rmesa->curr_vp_hw) {
1146 GLuint count = vp->mesa_program.NumNativeInstructions;
1147 drm_radeon_cmd_header_t tmp;
1148
1149 R200_STATECHANGE( rmesa, vpi[0] );
1150 R200_STATECHANGE( rmesa, vpi[1] );
1151
1152 /* FIXME: what about using a memcopy... */
1153 for (i = 0; (i < 64) && i < count; i++) {
1154 rmesa->hw.vpi[0].cmd[VPI_OPDST_0 + 4 * i] = vp->instr[i].op;
1155 rmesa->hw.vpi[0].cmd[VPI_SRC0_0 + 4 * i] = vp->instr[i].src0;
1156 rmesa->hw.vpi[0].cmd[VPI_SRC1_0 + 4 * i] = vp->instr[i].src1;
1157 rmesa->hw.vpi[0].cmd[VPI_SRC2_0 + 4 * i] = vp->instr[i].src2;
1158 }
1159 /* hack up the cmd_size so not the whole state atom is emitted always.
1160 This may require some more thought, we may emit half progs on lost state, but
1161 hopefully it won't matter?
1162 WARNING: must not use R200_DB_STATECHANGE, this will produce bogus (and rejected)
1163 packet emits (due to the mismatched cmd_size and count in cmd/last_cmd) */
1164 rmesa->hw.vpi[0].cmd_size = 1 + 4 * ((count > 64) ? 64 : count);
1165 tmp.i = rmesa->hw.vpi[0].cmd[VPI_CMD_0];
1166 tmp.veclinear.count = (count > 64) ? 64 : count;
1167 rmesa->hw.vpi[0].cmd[VPI_CMD_0] = tmp.i;
1168 if (count > 64) {
1169 for (i = 0; i < (count - 64); i++) {
1170 rmesa->hw.vpi[1].cmd[VPI_OPDST_0 + 4 * i] = vp->instr[i + 64].op;
1171 rmesa->hw.vpi[1].cmd[VPI_SRC0_0 + 4 * i] = vp->instr[i + 64].src0;
1172 rmesa->hw.vpi[1].cmd[VPI_SRC1_0 + 4 * i] = vp->instr[i + 64].src1;
1173 rmesa->hw.vpi[1].cmd[VPI_SRC2_0 + 4 * i] = vp->instr[i + 64].src2;
1174 }
1175 rmesa->hw.vpi[1].cmd_size = 1 + 4 * (count - 64);
1176 tmp.i = rmesa->hw.vpi[1].cmd[VPI_CMD_0];
1177 tmp.veclinear.count = count - 64;
1178 rmesa->hw.vpi[1].cmd[VPI_CMD_0] = tmp.i;
1179 }
1180 rmesa->curr_vp_hw = vp;
1181 }
1182 }
1183
1184
1185 static void
1186 r200BindProgram(struct gl_context *ctx, GLenum target, struct gl_program *prog)
1187 {
1188 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1189
1190 switch(target){
1191 case GL_VERTEX_PROGRAM_ARB:
1192 rmesa->curr_vp_hw = NULL;
1193 break;
1194 default:
1195 _mesa_problem(ctx, "Target not supported yet!");
1196 break;
1197 }
1198 }
1199
1200 static struct gl_program *
1201 r200NewProgram(struct gl_context *ctx, GLenum target, GLuint id)
1202 {
1203 switch(target){
1204 case GL_VERTEX_PROGRAM_ARB: {
1205 struct r200_vertex_program *vp = CALLOC_STRUCT(r200_vertex_program);
1206 return _mesa_init_gl_program(&vp->mesa_program, target, id);
1207 }
1208 case GL_FRAGMENT_PROGRAM_ARB: {
1209 struct gl_program *prog = CALLOC_STRUCT(gl_program);
1210 return _mesa_init_gl_program(prog, target, id);
1211 }
1212 default:
1213 _mesa_problem(ctx, "Bad target in r200NewProgram");
1214 return NULL;
1215 }
1216 }
1217
1218
1219 static void
1220 r200DeleteProgram(struct gl_context *ctx, struct gl_program *prog)
1221 {
1222 _mesa_delete_program(ctx, prog);
1223 }
1224
1225 static GLboolean
1226 r200ProgramStringNotify(struct gl_context *ctx, GLenum target, struct gl_program *prog)
1227 {
1228 struct r200_vertex_program *vp = (void *)prog;
1229 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1230
1231 switch(target) {
1232 case GL_VERTEX_PROGRAM_ARB:
1233 vp->translated = GL_FALSE;
1234 vp->fogpidx = 0;
1235 /* memset(&vp->translated, 0, sizeof(struct r200_vertex_program) - sizeof(struct gl_program));*/
1236 r200_translate_vertex_program(ctx, vp);
1237 rmesa->curr_vp_hw = NULL;
1238 break;
1239 case GL_FRAGMENT_SHADER_ATI:
1240 rmesa->afs_loaded = NULL;
1241 break;
1242 }
1243 /* need this for tcl fallbacks */
1244 (void) _tnl_program_string(ctx, target, prog);
1245
1246 /* XXX check if program is legal, within limits */
1247 return GL_TRUE;
1248 }
1249
1250 static GLboolean
1251 r200IsProgramNative(struct gl_context *ctx, GLenum target, struct gl_program *prog)
1252 {
1253 struct r200_vertex_program *vp = (void *)prog;
1254
1255 switch(target){
1256 case GL_VERTEX_PROGRAM_ARB:
1257 if (!vp->translated) {
1258 r200_translate_vertex_program(ctx, vp);
1259 }
1260 /* does not take parameters etc. into account */
1261 return vp->native;
1262 default:
1263 _mesa_problem(ctx, "Bad target in r200NewProgram");
1264 }
1265 return 0;
1266 }
1267
1268 void r200InitShaderFuncs(struct dd_function_table *functions)
1269 {
1270 functions->NewProgram = r200NewProgram;
1271 functions->BindProgram = r200BindProgram;
1272 functions->DeleteProgram = r200DeleteProgram;
1273 functions->ProgramStringNotify = r200ProgramStringNotify;
1274 functions->IsProgramNative = r200IsProgramNative;
1275 }