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
r200VertexProgUpdateParams(struct gl_context * ctx,struct r200_vertex_program * vp)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
t_dst_mask(GLuint mask)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
t_dst(struct prog_dst_register * dst)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
t_src_class(gl_register_file file)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
t_swizzle(GLubyte swizzle)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
t_src_index(struct r200_vertex_program * vp,struct prog_src_register * src)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
t_src(struct r200_vertex_program * vp,struct prog_src_register * src)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
t_src_scalar(struct r200_vertex_program * vp,struct prog_src_register * src)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
t_opcode(enum prog_opcode opcode)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
op_operands(enum prog_opcode opcode)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 */
r200_translate_vertex_program(struct gl_context * ctx,struct r200_vertex_program * vp)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->arb.NumInstructions == 0)
413 return GL_FALSE;
414
415 #if 0
416 if ((mesa_vp->info.inputs_read &
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->info.inputs_read);
423 }
424 return GL_FALSE;
425 }
426 #endif
427
428 if ((mesa_vp->info.outputs_written &
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->info.outputs_written);
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->arb.IsPositionInvariant &&
449 /* make sure we only do this once */
450 !(mesa_vp->info.outputs_written & (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->info.outputs_written & (1 << VARYING_SLOT_FOGC)) &&
457 !vp->fogpidx) {
458 struct gl_program_parameter_list *paramList;
459 gl_state_index tokens[STATE_LENGTH] = { STATE_FOG_PARAMS, 0, 0, 0, 0 };
460 paramList = mesa_vp->Parameters;
461 vp->fogpidx = _mesa_add_state_reference(paramList, tokens);
462 }
463
464 vp->pos_end = 0;
465 mesa_vp->arb.NumNativeInstructions = 0;
466 if (mesa_vp->Parameters)
467 mesa_vp->arb.NumNativeParameters = mesa_vp->Parameters->NumParameters;
468 else
469 mesa_vp->arb.NumNativeParameters = 0;
470
471 for(i = 0; i < VERT_ATTRIB_MAX; i++)
472 vp->inputs[i] = -1;
473 for(i = 0; i < 15; i++)
474 vp->inputmap_rev[i] = 255;
475 free_inputs = 0x2ffd;
476
477 /* fglrx uses fixed inputs as follows for conventional attribs.
478 generic attribs use non-fixed assignment, fglrx will always use the
479 lowest attrib values available. We'll just do the same.
480 There are 12 generic attribs possible, corresponding to attrib 0, 2-11
481 and 13 in a hw vertex prog.
482 attr 1 and 12 aren't used for generic attribs as those cannot be made vec4
483 (correspond to vertex normal/weight - maybe weight actually could be made vec4).
484 Additionally, not more than 12 arrays in total are possible I think.
485 attr 0 is pos, R200_VTX_XY1|R200_VTX_Z1|R200_VTX_W1 in R200_SE_VTX_FMT_0
486 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)
487 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)
488 attr 13 uses vtx1 pos (R200_VTX_XY1|R200_VTX_Z1|R200_VTX_W1 in R200_SE_VTX_FMT_0)
489 */
490
491 /* attr 4,5 and 13 are only used with generic attribs.
492 Haven't seen attr 14 used, maybe that's for the hw pointsize vec1 (which is
493 not possibe to use with vertex progs as it is lacking in vert prog specification) */
494 /* may look different when using idx buf / input_route instead of se_vtx_fmt? */
495 if (mesa_vp->info.inputs_read & VERT_BIT_POS) {
496 vp->inputs[VERT_ATTRIB_POS] = 0;
497 vp->inputmap_rev[0] = VERT_ATTRIB_POS;
498 free_inputs &= ~(1 << 0);
499 array_count++;
500 }
501 if (mesa_vp->info.inputs_read & VERT_BIT_WEIGHT) {
502 vp->inputs[VERT_ATTRIB_WEIGHT] = 12;
503 vp->inputmap_rev[1] = VERT_ATTRIB_WEIGHT;
504 array_count++;
505 }
506 if (mesa_vp->info.inputs_read & VERT_BIT_NORMAL) {
507 vp->inputs[VERT_ATTRIB_NORMAL] = 1;
508 vp->inputmap_rev[2] = VERT_ATTRIB_NORMAL;
509 array_count++;
510 }
511 if (mesa_vp->info.inputs_read & VERT_BIT_COLOR0) {
512 vp->inputs[VERT_ATTRIB_COLOR0] = 2;
513 vp->inputmap_rev[4] = VERT_ATTRIB_COLOR0;
514 free_inputs &= ~(1 << 2);
515 array_count++;
516 }
517 if (mesa_vp->info.inputs_read & VERT_BIT_COLOR1) {
518 vp->inputs[VERT_ATTRIB_COLOR1] = 3;
519 vp->inputmap_rev[5] = VERT_ATTRIB_COLOR1;
520 free_inputs &= ~(1 << 3);
521 array_count++;
522 }
523 if (mesa_vp->info.inputs_read & VERT_BIT_FOG) {
524 vp->inputs[VERT_ATTRIB_FOG] = 15; array_count++;
525 vp->inputmap_rev[3] = VERT_ATTRIB_FOG;
526 array_count++;
527 }
528 /* VERT_ATTRIB_TEX0-5 */
529 for (i = 0; i <= 5; i++) {
530 if (mesa_vp->info.inputs_read & VERT_BIT_TEX(i)) {
531 vp->inputs[VERT_ATTRIB_TEX(i)] = i + 6;
532 vp->inputmap_rev[8 + i] = VERT_ATTRIB_TEX(i);
533 free_inputs &= ~(1 << (i + 6));
534 array_count++;
535 }
536 }
537 /* using VERT_ATTRIB_TEX6/7 would be illegal */
538 for (; i < VERT_ATTRIB_TEX_MAX; i++) {
539 if (mesa_vp->info.inputs_read & VERT_BIT_TEX(i)) {
540 if (R200_DEBUG & RADEON_FALLBACKS) {
541 fprintf(stderr, "texture attribute %d in vert prog\n", i);
542 }
543 return GL_FALSE;
544 }
545 }
546 /* completely ignore aliasing? */
547 for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
548 int j;
549 /* completely ignore aliasing? */
550 if (mesa_vp->info.inputs_read & VERT_BIT_GENERIC(i)) {
551 array_count++;
552 if (array_count > 12) {
553 if (R200_DEBUG & RADEON_FALLBACKS) {
554 fprintf(stderr, "more than 12 attribs used in vert prog\n");
555 }
556 return GL_FALSE;
557 }
558 for (j = 0; j < 14; j++) {
559 /* will always find one due to limited array_count */
560 if (free_inputs & (1 << j)) {
561 free_inputs &= ~(1 << j);
562 vp->inputs[VERT_ATTRIB_GENERIC(i)] = j;
563 if (j == 0) {
564 /* mapped to pos */
565 vp->inputmap_rev[j] = VERT_ATTRIB_GENERIC(i);
566 } else if (j < 12) {
567 /* mapped to col/tex */
568 vp->inputmap_rev[j + 2] = VERT_ATTRIB_GENERIC(i);
569 } else {
570 /* mapped to pos1 */
571 vp->inputmap_rev[j + 1] = VERT_ATTRIB_GENERIC(i);
572 }
573 break;
574 }
575 }
576 }
577 }
578
579 if (!(mesa_vp->info.outputs_written & (1 << VARYING_SLOT_POS))) {
580 if (R200_DEBUG & RADEON_FALLBACKS) {
581 fprintf(stderr, "can't handle vert prog without position output\n");
582 }
583 return GL_FALSE;
584 }
585 if (free_inputs & 1) {
586 if (R200_DEBUG & RADEON_FALLBACKS) {
587 fprintf(stderr, "can't handle vert prog without position input\n");
588 }
589 return GL_FALSE;
590 }
591
592 o_inst = vp->instr;
593 for (vpi = mesa_vp->arb.Instructions; vpi->Opcode != OPCODE_END; vpi++, o_inst++){
594 operands = op_operands(vpi->Opcode);
595 are_srcs_scalar = operands & SCALAR_FLAG;
596 operands &= OP_MASK;
597
598 for(i = 0; i < operands; i++) {
599 src[i] = vpi->SrcReg[i];
600 /* hack up default attrib values as per spec as swizzling.
601 normal, fog, secondary color. Crazy?
602 May need more if we don't submit vec4 elements? */
603 if (src[i].File == PROGRAM_INPUT) {
604 if (src[i].Index == VERT_ATTRIB_NORMAL) {
605 int j;
606 for (j = 0; j < 4; j++) {
607 if (GET_SWZ(src[i].Swizzle, j) == SWIZZLE_W) {
608 src[i].Swizzle &= ~(SWIZZLE_W << (j*3));
609 src[i].Swizzle |= SWIZZLE_ONE << (j*3);
610 }
611 }
612 }
613 else if (src[i].Index == VERT_ATTRIB_COLOR1) {
614 int j;
615 for (j = 0; j < 4; j++) {
616 if (GET_SWZ(src[i].Swizzle, j) == SWIZZLE_W) {
617 src[i].Swizzle &= ~(SWIZZLE_W << (j*3));
618 src[i].Swizzle |= SWIZZLE_ZERO << (j*3);
619 }
620 }
621 }
622 else if (src[i].Index == VERT_ATTRIB_FOG) {
623 int j;
624 for (j = 0; j < 4; j++) {
625 if (GET_SWZ(src[i].Swizzle, j) == SWIZZLE_W) {
626 src[i].Swizzle &= ~(SWIZZLE_W << (j*3));
627 src[i].Swizzle |= SWIZZLE_ONE << (j*3);
628 }
629 else if ((GET_SWZ(src[i].Swizzle, j) == SWIZZLE_Y) ||
630 GET_SWZ(src[i].Swizzle, j) == SWIZZLE_Z) {
631 src[i].Swizzle &= ~(SWIZZLE_W << (j*3));
632 src[i].Swizzle |= SWIZZLE_ZERO << (j*3);
633 }
634 }
635 }
636 }
637 }
638
639 if(operands == 3){
640 if( CMP_SRCS(src[1], src[2]) || CMP_SRCS(src[0], src[2]) ){
641 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD,
642 (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
643 VSF_FLAG_ALL);
644
645 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[2]),
646 SWIZZLE_X, SWIZZLE_Y,
647 SWIZZLE_Z, SWIZZLE_W,
648 t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4);
649
650 o_inst->src1 = ZERO_SRC_0;
651 o_inst->src2 = UNUSED_SRC_1;
652 o_inst++;
653
654 src[2].File = PROGRAM_TEMPORARY;
655 src[2].Index = u_temp_i;
656 src[2].RelAddr = 0;
657 u_temp_i--;
658 }
659 }
660
661 if(operands >= 2){
662 if( CMP_SRCS(src[1], src[0]) ){
663 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD,
664 (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
665 VSF_FLAG_ALL);
666
667 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
668 SWIZZLE_X, SWIZZLE_Y,
669 SWIZZLE_Z, SWIZZLE_W,
670 t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4);
671
672 o_inst->src1 = ZERO_SRC_0;
673 o_inst->src2 = UNUSED_SRC_1;
674 o_inst++;
675
676 src[0].File = PROGRAM_TEMPORARY;
677 src[0].Index = u_temp_i;
678 src[0].RelAddr = 0;
679 u_temp_i--;
680 }
681 }
682
683 dst = vpi->DstReg;
684 if (dst.File == PROGRAM_OUTPUT &&
685 dst.Index == VARYING_SLOT_FOGC &&
686 dst.WriteMask & WRITEMASK_X) {
687 fog_temp_i = u_temp_i;
688 dst.File = PROGRAM_TEMPORARY;
689 dst.Index = fog_temp_i;
690 dofogfix = 1;
691 u_temp_i--;
692 }
693
694 /* These ops need special handling. */
695 switch(vpi->Opcode){
696 case OPCODE_POW:
697 /* pow takes only one argument, first scalar is in slot x, 2nd in slot z (other slots don't matter).
698 So may need to insert additional instruction */
699 if ((src[0].File == src[1].File) &&
700 (src[0].Index == src[1].Index)) {
701 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_POW, t_dst(&dst),
702 t_dst_mask(dst.WriteMask));
703 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
704 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
705 SWIZZLE_ZERO,
706 t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
707 SWIZZLE_ZERO,
708 t_src_class(src[0].File),
709 src[0].Negate) | (src[0].RelAddr << 4);
710 o_inst->src1 = UNUSED_SRC_0;
711 o_inst->src2 = UNUSED_SRC_0;
712 }
713 else {
714 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD,
715 (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
716 VSF_FLAG_ALL);
717 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
718 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
719 SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO,
720 t_src_class(src[0].File),
721 src[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
722 o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
723 SWIZZLE_ZERO, SWIZZLE_ZERO,
724 t_swizzle(GET_SWZ(src[1].Swizzle, 0)), SWIZZLE_ZERO,
725 t_src_class(src[1].File),
726 src[1].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
727 o_inst->src2 = UNUSED_SRC_1;
728 o_inst++;
729
730 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_POW, t_dst(&dst),
731 t_dst_mask(dst.WriteMask));
732 o_inst->src0 = MAKE_VSF_SOURCE(u_temp_i,
733 VSF_IN_COMPONENT_X,
734 VSF_IN_COMPONENT_Y,
735 VSF_IN_COMPONENT_Z,
736 VSF_IN_COMPONENT_W,
737 VSF_IN_CLASS_TMP,
738 VSF_FLAG_NONE);
739 o_inst->src1 = UNUSED_SRC_0;
740 o_inst->src2 = UNUSED_SRC_0;
741 u_temp_i--;
742 }
743 goto next;
744
745 case OPCODE_MOV://ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO}
746 case OPCODE_SWZ:
747 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst),
748 t_dst_mask(dst.WriteMask));
749 o_inst->src0 = t_src(vp, &src[0]);
750 o_inst->src1 = ZERO_SRC_0;
751 o_inst->src2 = UNUSED_SRC_1;
752 goto next;
753
754 case OPCODE_MAD:
755 /* only 2 read ports into temp memory thus may need the macro op MAD_2
756 instead (requiring 2 clocks) if all inputs are in temp memory
757 (and, only if they actually reference 3 distinct temps) */
758 hw_op=(src[0].File == PROGRAM_TEMPORARY &&
759 src[1].File == PROGRAM_TEMPORARY &&
760 src[2].File == PROGRAM_TEMPORARY &&
761 (((src[0].RelAddr << 8) | src[0].Index) != ((src[1].RelAddr << 8) | src[1].Index)) &&
762 (((src[0].RelAddr << 8) | src[0].Index) != ((src[2].RelAddr << 8) | src[2].Index)) &&
763 (((src[1].RelAddr << 8) | src[1].Index) != ((src[2].RelAddr << 8) | src[2].Index))) ?
764 R200_VPI_OUT_OP_MAD_2 : R200_VPI_OUT_OP_MAD;
765
766 o_inst->op = MAKE_VSF_OP(hw_op, t_dst(&dst),
767 t_dst_mask(dst.WriteMask));
768 o_inst->src0 = t_src(vp, &src[0]);
769 #if 0
770 if ((o_inst - vp->instr) == 31) {
771 /* fix up the broken vertex program of quake4 demo... */
772 o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
773 SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X,
774 t_src_class(src[1].File),
775 src[1].Negate) | (src[1].RelAddr << 4);
776 o_inst->src2 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
777 SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y,
778 t_src_class(src[1].File),
779 src[1].Negate) | (src[1].RelAddr << 4);
780 }
781 else {
782 o_inst->src1 = t_src(vp, &src[1]);
783 o_inst->src2 = t_src(vp, &src[2]);
784 }
785 #else
786 o_inst->src1 = t_src(vp, &src[1]);
787 o_inst->src2 = t_src(vp, &src[2]);
788 #endif
789 goto next;
790
791 case OPCODE_DP3://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO}
792 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_DOT, t_dst(&dst),
793 t_dst_mask(dst.WriteMask));
794
795 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
796 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
797 t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
798 t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
799 SWIZZLE_ZERO,
800 t_src_class(src[0].File),
801 src[0].Negate) | (src[0].RelAddr << 4);
802
803 o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
804 t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
805 t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
806 t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
807 SWIZZLE_ZERO,
808 t_src_class(src[1].File),
809 src[1].Negate) | (src[1].RelAddr << 4);
810
811 o_inst->src2 = UNUSED_SRC_1;
812 goto next;
813
814 case OPCODE_DPH://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W}
815 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_DOT, t_dst(&dst),
816 t_dst_mask(dst.WriteMask));
817
818 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
819 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
820 t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
821 t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
822 VSF_IN_COMPONENT_ONE,
823 t_src_class(src[0].File),
824 src[0].Negate) | (src[0].RelAddr << 4);
825 o_inst->src1 = t_src(vp, &src[1]);
826 o_inst->src2 = UNUSED_SRC_1;
827 goto next;
828
829 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
830 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst),
831 t_dst_mask(dst.WriteMask));
832
833 o_inst->src0 = t_src(vp, &src[0]);
834 o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
835 t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
836 t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
837 t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
838 t_swizzle(GET_SWZ(src[1].Swizzle, 3)),
839 t_src_class(src[1].File),
840 (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
841 o_inst->src2 = UNUSED_SRC_1;
842 goto next;
843
844 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
845 o_inst->op=MAKE_VSF_OP(R200_VPI_OUT_OP_MAX, t_dst(&dst),
846 t_dst_mask(dst.WriteMask));
847
848 o_inst->src0=t_src(vp, &src[0]);
849 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
850 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
851 t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
852 t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
853 t_swizzle(GET_SWZ(src[0].Swizzle, 3)),
854 t_src_class(src[0].File),
855 (!src[0].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
856 o_inst->src2 = UNUSED_SRC_1;
857 goto next;
858
859 case OPCODE_FLR:
860 /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W}
861 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 */
862
863 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_FRC,
864 (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
865 t_dst_mask(dst.WriteMask));
866
867 o_inst->src0 = t_src(vp, &src[0]);
868 o_inst->src1 = UNUSED_SRC_0;
869 o_inst->src2 = UNUSED_SRC_1;
870 o_inst++;
871
872 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst),
873 t_dst_mask(dst.WriteMask));
874
875 o_inst->src0 = t_src(vp, &src[0]);
876 o_inst->src1 = MAKE_VSF_SOURCE(u_temp_i,
877 VSF_IN_COMPONENT_X,
878 VSF_IN_COMPONENT_Y,
879 VSF_IN_COMPONENT_Z,
880 VSF_IN_COMPONENT_W,
881 VSF_IN_CLASS_TMP,
882 /* Not 100% sure about this */
883 (!src[0].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/);
884
885 o_inst->src2 = UNUSED_SRC_0;
886 u_temp_i--;
887 goto next;
888
889 case OPCODE_XPD:
890 /* mul r0, r1.yzxw, r2.zxyw
891 mad r0, -r2.yzxw, r1.zxyw, r0
892 */
893 hw_op=(src[0].File == PROGRAM_TEMPORARY &&
894 src[1].File == PROGRAM_TEMPORARY &&
895 (((src[0].RelAddr << 8) | src[0].Index) != ((src[1].RelAddr << 8) | src[1].Index))) ?
896 R200_VPI_OUT_OP_MAD_2 : R200_VPI_OUT_OP_MAD;
897
898 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL,
899 (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
900 t_dst_mask(dst.WriteMask));
901
902 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
903 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),
908 src[0].Negate) | (src[0].RelAddr << 4);
909
910 o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
911 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),
916 src[1].Negate) | (src[1].RelAddr << 4);
917
918 o_inst->src2 = UNUSED_SRC_1;
919 o_inst++;
920 u_temp_i--;
921
922 o_inst->op = MAKE_VSF_OP(hw_op, t_dst(&dst),
923 t_dst_mask(dst.WriteMask));
924
925 o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
926 t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y
927 t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z
928 t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x
929 t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w
930 t_src_class(src[1].File),
931 (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
932
933 o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
934 t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z
935 t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
936 t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
937 t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
938 t_src_class(src[0].File),
939 src[0].Negate) | (src[0].RelAddr << 4);
940
941 o_inst->src2 = MAKE_VSF_SOURCE(u_temp_i+1,
942 VSF_IN_COMPONENT_X,
943 VSF_IN_COMPONENT_Y,
944 VSF_IN_COMPONENT_Z,
945 VSF_IN_COMPONENT_W,
946 VSF_IN_CLASS_TMP,
947 VSF_FLAG_NONE);
948 goto next;
949
950 case OPCODE_END:
951 assert(0);
952 default:
953 break;
954 }
955
956 o_inst->op = MAKE_VSF_OP(t_opcode(vpi->Opcode), t_dst(&dst),
957 t_dst_mask(dst.WriteMask));
958
959 if(are_srcs_scalar){
960 switch(operands){
961 case 1:
962 o_inst->src0 = t_src_scalar(vp, &src[0]);
963 o_inst->src1 = UNUSED_SRC_0;
964 o_inst->src2 = UNUSED_SRC_1;
965 break;
966
967 case 2:
968 o_inst->src0 = t_src_scalar(vp, &src[0]);
969 o_inst->src1 = t_src_scalar(vp, &src[1]);
970 o_inst->src2 = UNUSED_SRC_1;
971 break;
972
973 case 3:
974 o_inst->src0 = t_src_scalar(vp, &src[0]);
975 o_inst->src1 = t_src_scalar(vp, &src[1]);
976 o_inst->src2 = t_src_scalar(vp, &src[2]);
977 break;
978
979 default:
980 fprintf(stderr, "illegal number of operands %lu\n", operands);
981 exit(-1);
982 break;
983 }
984 } else {
985 switch(operands){
986 case 1:
987 o_inst->src0 = t_src(vp, &src[0]);
988 o_inst->src1 = UNUSED_SRC_0;
989 o_inst->src2 = UNUSED_SRC_1;
990 break;
991
992 case 2:
993 o_inst->src0 = t_src(vp, &src[0]);
994 o_inst->src1 = t_src(vp, &src[1]);
995 o_inst->src2 = UNUSED_SRC_1;
996 break;
997
998 case 3:
999 o_inst->src0 = t_src(vp, &src[0]);
1000 o_inst->src1 = t_src(vp, &src[1]);
1001 o_inst->src2 = t_src(vp, &src[2]);
1002 break;
1003
1004 default:
1005 fprintf(stderr, "illegal number of operands %lu\n", operands);
1006 exit(-1);
1007 break;
1008 }
1009 }
1010 next:
1011
1012 if (dofogfix) {
1013 o_inst++;
1014 if (vp->fogmode == GL_EXP) {
1015 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL,
1016 (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
1017 VSF_FLAG_X);
1018 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE);
1019 o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, X, X, X, X, PARAM, NONE);
1020 o_inst->src2 = UNUSED_SRC_1;
1021 o_inst++;
1022 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_EXP_E,
1023 R200_VSF_OUT_CLASS_RESULT_FOGC,
1024 VSF_FLAG_X);
1025 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL);
1026 o_inst->src1 = UNUSED_SRC_0;
1027 o_inst->src2 = UNUSED_SRC_1;
1028 }
1029 else if (vp->fogmode == GL_EXP2) {
1030 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL,
1031 (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
1032 VSF_FLAG_X);
1033 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE);
1034 o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, X, X, X, X, PARAM, NONE);
1035 o_inst->src2 = UNUSED_SRC_1;
1036 o_inst++;
1037 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL,
1038 (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
1039 VSF_FLAG_X);
1040 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE);
1041 o_inst->src1 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE);
1042 o_inst->src2 = UNUSED_SRC_1;
1043 o_inst++;
1044 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_EXP_E,
1045 R200_VSF_OUT_CLASS_RESULT_FOGC,
1046 VSF_FLAG_X);
1047 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL);
1048 o_inst->src1 = UNUSED_SRC_0;
1049 o_inst->src2 = UNUSED_SRC_1;
1050 }
1051 else { /* fogmode == GL_LINEAR */
1052 /* could do that with single op (dot) if using params like
1053 with fixed function pipeline fog */
1054 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD,
1055 (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP,
1056 VSF_FLAG_X);
1057 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL);
1058 o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, Z, Z, Z, Z, PARAM, NONE);
1059 o_inst->src2 = UNUSED_SRC_1;
1060 o_inst++;
1061 o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL,
1062 R200_VSF_OUT_CLASS_RESULT_FOGC,
1063 VSF_FLAG_X);
1064 o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE);
1065 o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, W, W, W, W, PARAM, NONE);
1066 o_inst->src2 = UNUSED_SRC_1;
1067
1068 }
1069 dofogfix = 0;
1070 }
1071
1072 u_temp_used = (R200_VSF_MAX_TEMPS - 1) - u_temp_i;
1073 if (mesa_vp->arb.NumNativeTemporaries <
1074 (mesa_vp->arb.NumTemporaries + u_temp_used)) {
1075 mesa_vp->arb.NumNativeTemporaries =
1076 mesa_vp->arb.NumTemporaries + u_temp_used;
1077 }
1078 if ((mesa_vp->arb.NumTemporaries + u_temp_used) > R200_VSF_MAX_TEMPS) {
1079 if (R200_DEBUG & RADEON_FALLBACKS) {
1080 fprintf(stderr, "Ran out of temps, num temps %d, us %d\n", mesa_vp->arb.NumTemporaries, u_temp_used);
1081 }
1082 return GL_FALSE;
1083 }
1084 u_temp_i = R200_VSF_MAX_TEMPS - 1;
1085 if(o_inst - vp->instr >= R200_VSF_MAX_INST) {
1086 mesa_vp->arb.NumNativeInstructions = 129;
1087 if (R200_DEBUG & RADEON_FALLBACKS) {
1088 fprintf(stderr, "more than 128 native instructions\n");
1089 }
1090 return GL_FALSE;
1091 }
1092 if ((o_inst->op & R200_VSF_OUT_CLASS_MASK) == R200_VSF_OUT_CLASS_RESULT_POS) {
1093 vp->pos_end = (o_inst - vp->instr);
1094 }
1095 }
1096
1097 vp->native = GL_TRUE;
1098 mesa_vp->arb.NumNativeInstructions = (o_inst - vp->instr);
1099 #if 0
1100 fprintf(stderr, "hw program:\n");
1101 for(i=0; i < vp->program.length; i++)
1102 fprintf(stderr, "%08x\n", vp->instr[i]);
1103 #endif
1104 return GL_TRUE;
1105 }
1106
r200SetupVertexProg(struct gl_context * ctx)1107 void r200SetupVertexProg( struct gl_context *ctx ) {
1108 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1109 struct r200_vertex_program *vp = (struct r200_vertex_program *)ctx->VertexProgram.Current;
1110 GLboolean fallback;
1111 GLint i;
1112
1113 if (!vp->translated || (ctx->Fog.Enabled && ctx->Fog.Mode != vp->fogmode)) {
1114 rmesa->curr_vp_hw = NULL;
1115 r200_translate_vertex_program(ctx, vp);
1116 }
1117 /* could optimize setting up vertex progs away for non-tcl hw */
1118 fallback = !(vp->native && r200VertexProgUpdateParams(ctx, vp));
1119 TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, fallback);
1120 if (rmesa->radeon.TclFallback) return;
1121
1122 R200_STATECHANGE( rmesa, vap );
1123 /* FIXME: fglrx sets R200_VAP_SINGLE_BUF_STATE_ENABLE too. Do we need it?
1124 maybe only when using more than 64 inst / 96 param? */
1125 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_PROG_VTX_SHADER_ENABLE /*| R200_VAP_SINGLE_BUF_STATE_ENABLE*/;
1126
1127 R200_STATECHANGE( rmesa, pvs );
1128
1129 rmesa->hw.pvs.cmd[PVS_CNTL_1] = (0 << R200_PVS_CNTL_1_PROGRAM_START_SHIFT) |
1130 ((vp->mesa_program.arb.NumNativeInstructions - 1) << R200_PVS_CNTL_1_PROGRAM_END_SHIFT) |
1131 (vp->pos_end << R200_PVS_CNTL_1_POS_END_SHIFT);
1132 rmesa->hw.pvs.cmd[PVS_CNTL_2] = (0 << R200_PVS_CNTL_2_PARAM_OFFSET_SHIFT) |
1133 (vp->mesa_program.arb.NumNativeParameters << R200_PVS_CNTL_2_PARAM_COUNT_SHIFT);
1134
1135 /* maybe user clip planes just work with vertex progs... untested */
1136 if (ctx->Transform.ClipPlanesEnabled) {
1137 R200_STATECHANGE( rmesa, tcl );
1138 if (vp->mesa_program.arb.IsPositionInvariant) {
1139 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (ctx->Transform.ClipPlanesEnabled << 2);
1140 }
1141 else {
1142 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(0xfc);
1143 }
1144 }
1145
1146 if (vp != rmesa->curr_vp_hw) {
1147 GLuint count = vp->mesa_program.arb.NumNativeInstructions;
1148 drm_radeon_cmd_header_t tmp;
1149
1150 R200_STATECHANGE( rmesa, vpi[0] );
1151 R200_STATECHANGE( rmesa, vpi[1] );
1152
1153 /* FIXME: what about using a memcopy... */
1154 for (i = 0; (i < 64) && i < count; i++) {
1155 rmesa->hw.vpi[0].cmd[VPI_OPDST_0 + 4 * i] = vp->instr[i].op;
1156 rmesa->hw.vpi[0].cmd[VPI_SRC0_0 + 4 * i] = vp->instr[i].src0;
1157 rmesa->hw.vpi[0].cmd[VPI_SRC1_0 + 4 * i] = vp->instr[i].src1;
1158 rmesa->hw.vpi[0].cmd[VPI_SRC2_0 + 4 * i] = vp->instr[i].src2;
1159 }
1160 /* hack up the cmd_size so not the whole state atom is emitted always.
1161 This may require some more thought, we may emit half progs on lost state, but
1162 hopefully it won't matter?
1163 WARNING: must not use R200_DB_STATECHANGE, this will produce bogus (and rejected)
1164 packet emits (due to the mismatched cmd_size and count in cmd/last_cmd) */
1165 rmesa->hw.vpi[0].cmd_size = 1 + 4 * ((count > 64) ? 64 : count);
1166 tmp.i = rmesa->hw.vpi[0].cmd[VPI_CMD_0];
1167 tmp.veclinear.count = (count > 64) ? 64 : count;
1168 rmesa->hw.vpi[0].cmd[VPI_CMD_0] = tmp.i;
1169 if (count > 64) {
1170 for (i = 0; i < (count - 64); i++) {
1171 rmesa->hw.vpi[1].cmd[VPI_OPDST_0 + 4 * i] = vp->instr[i + 64].op;
1172 rmesa->hw.vpi[1].cmd[VPI_SRC0_0 + 4 * i] = vp->instr[i + 64].src0;
1173 rmesa->hw.vpi[1].cmd[VPI_SRC1_0 + 4 * i] = vp->instr[i + 64].src1;
1174 rmesa->hw.vpi[1].cmd[VPI_SRC2_0 + 4 * i] = vp->instr[i + 64].src2;
1175 }
1176 rmesa->hw.vpi[1].cmd_size = 1 + 4 * (count - 64);
1177 tmp.i = rmesa->hw.vpi[1].cmd[VPI_CMD_0];
1178 tmp.veclinear.count = count - 64;
1179 rmesa->hw.vpi[1].cmd[VPI_CMD_0] = tmp.i;
1180 }
1181 rmesa->curr_vp_hw = vp;
1182 }
1183 }
1184
1185
1186 static void
r200BindProgram(struct gl_context * ctx,GLenum target,struct gl_program * prog)1187 r200BindProgram(struct gl_context *ctx, GLenum target, struct gl_program *prog)
1188 {
1189 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1190
1191 switch(target){
1192 case GL_VERTEX_PROGRAM_ARB:
1193 rmesa->curr_vp_hw = NULL;
1194 break;
1195 default:
1196 _mesa_problem(ctx, "Target not supported yet!");
1197 break;
1198 }
1199 }
1200
1201 static struct gl_program *
r200NewProgram(struct gl_context * ctx,GLenum target,GLuint id,bool is_arb_asm)1202 r200NewProgram(struct gl_context *ctx, GLenum target, GLuint id,
1203 bool is_arb_asm)
1204 {
1205 switch(target){
1206 case GL_VERTEX_PROGRAM_ARB: {
1207 struct r200_vertex_program *vp = rzalloc(NULL,
1208 struct r200_vertex_program);
1209 return _mesa_init_gl_program(&vp->mesa_program, target, id, is_arb_asm);
1210 }
1211 case GL_FRAGMENT_PROGRAM_ARB: {
1212 struct gl_program *prog = rzalloc(NULL, struct gl_program);
1213 return _mesa_init_gl_program(prog, target, id, is_arb_asm);
1214 }
1215 default:
1216 _mesa_problem(ctx, "Bad target in r200NewProgram");
1217 return NULL;
1218 }
1219 }
1220
1221
1222 static void
r200DeleteProgram(struct gl_context * ctx,struct gl_program * prog)1223 r200DeleteProgram(struct gl_context *ctx, struct gl_program *prog)
1224 {
1225 _mesa_delete_program(ctx, prog);
1226 }
1227
1228 static GLboolean
r200ProgramStringNotify(struct gl_context * ctx,GLenum target,struct gl_program * prog)1229 r200ProgramStringNotify(struct gl_context *ctx, GLenum target, struct gl_program *prog)
1230 {
1231 struct r200_vertex_program *vp = (void *)prog;
1232 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1233
1234 switch(target) {
1235 case GL_VERTEX_PROGRAM_ARB:
1236 vp->translated = GL_FALSE;
1237 vp->fogpidx = 0;
1238 /* memset(&vp->translated, 0, sizeof(struct r200_vertex_program) - sizeof(struct gl_program));*/
1239 r200_translate_vertex_program(ctx, vp);
1240 rmesa->curr_vp_hw = NULL;
1241 break;
1242 case GL_FRAGMENT_SHADER_ATI:
1243 rmesa->afs_loaded = NULL;
1244 break;
1245 }
1246 /* need this for tcl fallbacks */
1247 (void) _tnl_program_string(ctx, target, prog);
1248
1249 /* XXX check if program is legal, within limits */
1250 return GL_TRUE;
1251 }
1252
1253 static GLboolean
r200IsProgramNative(struct gl_context * ctx,GLenum target,struct gl_program * prog)1254 r200IsProgramNative(struct gl_context *ctx, GLenum target, struct gl_program *prog)
1255 {
1256 struct r200_vertex_program *vp = (void *)prog;
1257
1258 switch(target){
1259 case GL_VERTEX_PROGRAM_ARB:
1260 if (!vp->translated) {
1261 r200_translate_vertex_program(ctx, vp);
1262 }
1263 /* does not take parameters etc. into account */
1264 return vp->native;
1265 default:
1266 _mesa_problem(ctx, "Bad target in r200NewProgram");
1267 }
1268 return 0;
1269 }
1270
r200InitShaderFuncs(struct dd_function_table * functions)1271 void r200InitShaderFuncs(struct dd_function_table *functions)
1272 {
1273 functions->NewProgram = r200NewProgram;
1274 functions->BindProgram = r200BindProgram;
1275 functions->DeleteProgram = r200DeleteProgram;
1276 functions->ProgramStringNotify = r200ProgramStringNotify;
1277 functions->IsProgramNative = r200IsProgramNative;
1278 }
1279