enable feedback rendering
[mesa.git] / src / mesa / drivers / dri / r300 / r300_vertexprog.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 */
32 #include "glheader.h"
33 #include "macros.h"
34 #include "enums.h"
35 #include "program.h"
36 #include "nvvertexec.h"
37
38 #include "r300_context.h"
39 #include "r300_program.h"
40 #include "program_instruction.h"
41
42 #define SCALAR_FLAG (1<<31)
43 #define FLAG_MASK (1<<31)
44 #define OP_MASK (0xf) /* we are unlikely to have more than 15 */
45 #define OPN(operator, ip, op) {#operator, OPCODE_##operator, ip, op}
46
47 static struct{
48 char *name;
49 int opcode;
50 unsigned long ip; /* number of input operands and flags */
51 unsigned long op;
52 }op_names[]={
53 OPN(ABS, 1, 1),
54 OPN(ADD, 2, 1),
55 OPN(ARL, 1, 1|SCALAR_FLAG),
56 OPN(DP3, 2, 3|SCALAR_FLAG),
57 OPN(DP4, 2, 3|SCALAR_FLAG),
58 OPN(DPH, 2, 3|SCALAR_FLAG),
59 OPN(DST, 2, 1),
60 OPN(EX2, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
61 OPN(EXP, 1|SCALAR_FLAG, 1),
62 OPN(FLR, 1, 1),
63 OPN(FRC, 1, 1),
64 OPN(LG2, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
65 OPN(LIT, 1, 1),
66 OPN(LOG, 1|SCALAR_FLAG, 1),
67 OPN(MAD, 3, 1),
68 OPN(MAX, 2, 1),
69 OPN(MIN, 2, 1),
70 OPN(MOV, 1, 1),
71 OPN(MUL, 2, 1),
72 OPN(POW, 2|SCALAR_FLAG, 4|SCALAR_FLAG),
73 OPN(RCP, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
74 OPN(RSQ, 1|SCALAR_FLAG, 4|SCALAR_FLAG),
75 OPN(SGE, 2, 1),
76 OPN(SLT, 2, 1),
77 OPN(SUB, 2, 1),
78 OPN(SWZ, 1, 1),
79 OPN(XPD, 2, 1),
80 OPN(RCC, 0, 0), //extra
81 OPN(PRINT, 0, 0),
82 OPN(END, 0, 0),
83 };
84 #undef OPN
85
86 int r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program *vp, float *dst)
87 {
88 int pi;
89 struct vertex_program *mesa_vp=(void *)vp;
90 float *dst_o=dst;
91 struct program_parameter_list *paramList;
92
93 if (mesa_vp->IsNVProgram) {
94 _mesa_init_vp_per_primitive_registers(ctx);
95
96 for (pi=0; pi < MAX_NV_VERTEX_PROGRAM_PARAMS; pi++) {
97 *dst++=ctx->VertexProgram.Parameters[pi][0];
98 *dst++=ctx->VertexProgram.Parameters[pi][1];
99 *dst++=ctx->VertexProgram.Parameters[pi][2];
100 *dst++=ctx->VertexProgram.Parameters[pi][3];
101 }
102 return dst - dst_o;
103 }
104
105 assert(mesa_vp->Base.Parameters);
106 _mesa_load_state_parameters(ctx, mesa_vp->Base.Parameters);
107
108 if(mesa_vp->Base.Parameters->NumParameters * 4 > VSF_MAX_FRAGMENT_LENGTH){
109 fprintf(stderr, "%s:Params exhausted\n", __FUNCTION__);
110 exit(-1);
111 }
112
113 paramList = mesa_vp->Base.Parameters;
114 for(pi=0; pi < paramList->NumParameters; pi++){
115 switch(paramList->Parameters[pi].Type){
116
117 case PROGRAM_STATE_VAR:
118 case PROGRAM_NAMED_PARAM:
119 //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
120 case PROGRAM_CONSTANT:
121 *dst++=paramList->ParameterValues[pi][0];
122 *dst++=paramList->ParameterValues[pi][1];
123 *dst++=paramList->ParameterValues[pi][2];
124 *dst++=paramList->ParameterValues[pi][3];
125 break;
126
127 default: _mesa_problem(NULL, "Bad param type in %s", __FUNCTION__);
128 }
129
130 }
131
132 return dst - dst_o;
133 }
134
135 static unsigned long t_dst_mask(GLuint mask)
136 {
137 unsigned long flags=0;
138
139 if(mask & WRITEMASK_X) flags |= VSF_FLAG_X;
140 if(mask & WRITEMASK_Y) flags |= VSF_FLAG_Y;
141 if(mask & WRITEMASK_Z) flags |= VSF_FLAG_Z;
142 if(mask & WRITEMASK_W) flags |= VSF_FLAG_W;
143
144 return flags;
145 }
146
147 static unsigned long t_dst_class(enum register_file file)
148 {
149
150 switch(file){
151 case PROGRAM_TEMPORARY:
152 return VSF_OUT_CLASS_TMP;
153 case PROGRAM_OUTPUT:
154 return VSF_OUT_CLASS_RESULT;
155 case PROGRAM_ADDRESS:
156 return VSF_OUT_CLASS_ADDR;
157 /*
158 case PROGRAM_INPUT:
159 case PROGRAM_LOCAL_PARAM:
160 case PROGRAM_ENV_PARAM:
161 case PROGRAM_NAMED_PARAM:
162 case PROGRAM_STATE_VAR:
163 case PROGRAM_WRITE_ONLY:
164 case PROGRAM_ADDRESS:
165 */
166 default:
167 fprintf(stderr, "problem in %s", __FUNCTION__);
168 exit(0);
169 }
170 }
171
172 static unsigned long t_dst_index(struct r300_vertex_program *vp, struct prog_dst_register *dst)
173 {
174 if(dst->File == PROGRAM_OUTPUT) {
175 if (vp->outputs[dst->Index] != -1)
176 return vp->outputs[dst->Index];
177 else {
178 WARN_ONCE("Unknown output %d\n", dst->Index);
179 return 10;
180 }
181 }else if(dst->File == PROGRAM_ADDRESS) {
182 assert(dst->Index == 0);
183 }
184
185 return dst->Index;
186 }
187
188 static unsigned long t_src_class(enum register_file file)
189 {
190
191 switch(file){
192 case PROGRAM_TEMPORARY:
193 return VSF_IN_CLASS_TMP;
194
195 case PROGRAM_INPUT:
196 return VSF_IN_CLASS_ATTR;
197
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;
203 /*
204 case PROGRAM_OUTPUT:
205 case PROGRAM_WRITE_ONLY:
206 case PROGRAM_ADDRESS:
207 */
208 default:
209 fprintf(stderr, "problem in %s", __FUNCTION__);
210 exit(0);
211 }
212 }
213
214 static unsigned long t_swizzle(GLubyte swizzle)
215 {
216 switch(swizzle){
217 case SWIZZLE_X: return VSF_IN_COMPONENT_X;
218 case SWIZZLE_Y: return VSF_IN_COMPONENT_Y;
219 case SWIZZLE_Z: return VSF_IN_COMPONENT_Z;
220 case SWIZZLE_W: return VSF_IN_COMPONENT_W;
221 case SWIZZLE_ZERO: return VSF_IN_COMPONENT_ZERO;
222 case SWIZZLE_ONE: return VSF_IN_COMPONENT_ONE;
223 default:
224 fprintf(stderr, "problem in %s", __FUNCTION__);
225 exit(0);
226 }
227 }
228
229 #if 0
230 static void vp_dump_inputs(struct r300_vertex_program *vp, char *caller)
231 {
232 int i;
233
234 if(vp == NULL){
235 fprintf(stderr, "vp null in call to %s from %s\n", __FUNCTION__, caller);
236 return ;
237 }
238
239 fprintf(stderr, "%s:<", caller);
240 for(i=0; i < VERT_ATTRIB_MAX; i++)
241 fprintf(stderr, "%d ", vp->inputs[i]);
242 fprintf(stderr, ">\n");
243
244 }
245 #endif
246
247 static unsigned long t_src_index(struct r300_vertex_program *vp, struct prog_src_register *src)
248 {
249 int i;
250 int max_reg=-1;
251
252 if(src->File == PROGRAM_INPUT){
253 if(vp->inputs[src->Index] != -1)
254 return vp->inputs[src->Index];
255
256 for(i=0; i < VERT_ATTRIB_MAX; i++)
257 if(vp->inputs[i] > max_reg)
258 max_reg=vp->inputs[i];
259
260 vp->inputs[src->Index]=max_reg+1;
261
262 //vp_dump_inputs(vp, __FUNCTION__);
263
264 return vp->inputs[src->Index];
265 }else{
266 return src->Index;
267 }
268 }
269
270 static unsigned long t_src(struct r300_vertex_program *vp, struct prog_src_register *src)
271 {
272
273 return MAKE_VSF_SOURCE(t_src_index(vp, src),
274 t_swizzle(GET_SWZ(src->Swizzle, 0)),
275 t_swizzle(GET_SWZ(src->Swizzle, 1)),
276 t_swizzle(GET_SWZ(src->Swizzle, 2)),
277 t_swizzle(GET_SWZ(src->Swizzle, 3)),
278 t_src_class(src->File),
279 src->NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src->RelAddr << 4);
280 }
281
282 static unsigned long t_src_scalar(struct r300_vertex_program *vp, struct prog_src_register *src)
283 {
284
285 return MAKE_VSF_SOURCE(t_src_index(vp, src),
286 t_swizzle(GET_SWZ(src->Swizzle, 0)),
287 t_swizzle(GET_SWZ(src->Swizzle, 0)),
288 t_swizzle(GET_SWZ(src->Swizzle, 0)),
289 t_swizzle(GET_SWZ(src->Swizzle, 0)),
290 t_src_class(src->File),
291 src->NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE);
292 }
293
294 static unsigned long t_opcode(enum prog_opcode opcode)
295 {
296
297 switch(opcode){
298 case OPCODE_DST: return R300_VPI_OUT_OP_DST;
299 case OPCODE_EX2: return R300_VPI_OUT_OP_EX2;
300 case OPCODE_EXP: return R300_VPI_OUT_OP_EXP;
301 case OPCODE_FRC: return R300_VPI_OUT_OP_FRC;
302 case OPCODE_LG2: return R300_VPI_OUT_OP_LG2;
303 case OPCODE_LOG: return R300_VPI_OUT_OP_LOG;
304 case OPCODE_MAX: return R300_VPI_OUT_OP_MAX;
305 case OPCODE_MIN: return R300_VPI_OUT_OP_MIN;
306 case OPCODE_MUL: return R300_VPI_OUT_OP_MUL;
307 case OPCODE_RCP: return R300_VPI_OUT_OP_RCP;
308 case OPCODE_RSQ: return R300_VPI_OUT_OP_RSQ;
309 case OPCODE_SGE: return R300_VPI_OUT_OP_SGE;
310 case OPCODE_SLT: return R300_VPI_OUT_OP_SLT;
311 case OPCODE_DP4: return R300_VPI_OUT_OP_DOT;
312
313 default:
314 fprintf(stderr, "%s: Should not be called with opcode %d!", __FUNCTION__, opcode);
315 }
316 exit(-1);
317 return 0;
318 }
319
320 static unsigned long op_operands(enum prog_opcode opcode)
321 {
322 int i;
323
324 /* Can we trust mesas opcodes to be in order ? */
325 for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++)
326 if(op_names[i].opcode == opcode)
327 return op_names[i].ip;
328
329 fprintf(stderr, "op %d not found in op_names\n", opcode);
330 exit(-1);
331 return 0;
332 }
333
334 /* TODO: Get rid of t_src_class call */
335 #define CMP_SRCS(a, b) (a.Index != b.Index && \
336 ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \
337 t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \
338 (t_src_class(a.File) == VSF_IN_CLASS_ATTR && \
339 t_src_class(b.File) == VSF_IN_CLASS_ATTR))) \
340
341 #define ZERO_SRC_0 MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \
342 SWIZZLE_ZERO, SWIZZLE_ZERO, \
343 SWIZZLE_ZERO, SWIZZLE_ZERO, \
344 t_src_class(src[0].File), VSF_FLAG_NONE)
345
346 #define ZERO_SRC_1 MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \
347 SWIZZLE_ZERO, SWIZZLE_ZERO, \
348 SWIZZLE_ZERO, SWIZZLE_ZERO, \
349 t_src_class(src[1].File), VSF_FLAG_NONE)
350
351 #define ZERO_SRC_2 MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \
352 SWIZZLE_ZERO, SWIZZLE_ZERO, \
353 SWIZZLE_ZERO, SWIZZLE_ZERO, \
354 t_src_class(src[2].File), VSF_FLAG_NONE)
355
356 #define ONE_SRC_0 MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \
357 SWIZZLE_ONE, SWIZZLE_ONE, \
358 SWIZZLE_ONE, SWIZZLE_ONE, \
359 t_src_class(src[0].File), VSF_FLAG_NONE)
360
361 #define ONE_SRC_1 MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \
362 SWIZZLE_ONE, SWIZZLE_ONE, \
363 SWIZZLE_ONE, SWIZZLE_ONE, \
364 t_src_class(src[1].File), VSF_FLAG_NONE)
365
366 #define ONE_SRC_2 MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \
367 SWIZZLE_ONE, SWIZZLE_ONE, \
368 SWIZZLE_ONE, SWIZZLE_ONE, \
369 t_src_class(src[2].File), VSF_FLAG_NONE)
370
371 /* DP4 version seems to trigger some hw peculiarity */
372 //#define PREFER_DP4
373
374 #define FREE_TEMPS() \
375 do { \
376 if(u_temp_i < vp->num_temporaries) { \
377 WARN_ONCE("Ran out of temps, num temps %d, us %d\n", vp->num_temporaries, u_temp_i); \
378 vp->native = GL_FALSE; \
379 } \
380 u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; \
381 } while (0)
382
383 void r300_translate_vertex_shader(struct r300_vertex_program *vp)
384 {
385 struct vertex_program *mesa_vp=(void *)vp;
386 struct prog_instruction *vpi;
387 int i, cur_reg=0;
388 VERTEX_SHADER_INSTRUCTION *o_inst;
389 unsigned long operands;
390 int are_srcs_scalar;
391 unsigned long hw_op;
392 /* Initial value should be last tmp reg that hw supports.
393 Strangely enough r300 doesnt mind even though these would be out of range.
394 Smart enough to realize that it doesnt need it? */
395 int u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1;
396 struct prog_src_register src[3];
397
398 if (getenv("R300_VP_SAFETY")) {
399 WARN_ONCE("R300_VP_SAFETY enabled.\n");
400
401 vpi = malloc((mesa_vp->Base.NumInstructions + VSF_MAX_FRAGMENT_TEMPS) * sizeof(struct prog_instruction));
402 memset(vpi, 0, VSF_MAX_FRAGMENT_TEMPS * sizeof(struct prog_instruction));
403
404 for (i=0; i < VSF_MAX_FRAGMENT_TEMPS; i++) {
405 vpi[i].Opcode = OPCODE_MOV;
406 vpi[i].StringPos = 0;
407 vpi[i].Data = 0;
408
409 vpi[i].DstReg.File = PROGRAM_TEMPORARY;
410 vpi[i].DstReg.Index = i;
411 vpi[i].DstReg.WriteMask = WRITEMASK_XYZW;
412 vpi[i].DstReg.CondMask = COND_TR;
413
414 vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR;
415 vpi[i].SrcReg[0].Index = 0;
416 vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE);
417 }
418
419 memcpy(&vpi[i], mesa_vp->Base.Instructions, mesa_vp->Base.NumInstructions * sizeof(struct prog_instruction));
420
421 free(mesa_vp->Base.Instructions);
422
423 mesa_vp->Base.Instructions = vpi;
424
425 mesa_vp->Base.NumInstructions += VSF_MAX_FRAGMENT_TEMPS;
426 vpi = &mesa_vp->Base.Instructions[mesa_vp->Base.NumInstructions-1];
427
428 assert(vpi->Opcode == OPCODE_END);
429 }
430
431 if (mesa_vp->IsPositionInvariant) {
432 struct program_parameter_list *paramList;
433 GLint tokens[6] = { STATE_MATRIX, STATE_MVP, 0, 0, 0, STATE_MATRIX };
434
435 #ifdef PREFER_DP4
436 tokens[5] = STATE_MATRIX;
437 #else
438 tokens[5] = STATE_MATRIX_TRANSPOSE;
439 #endif
440 paramList = mesa_vp->Base.Parameters;
441
442 vpi = malloc((mesa_vp->Base.NumInstructions + 4) * sizeof(struct prog_instruction));
443 memset(vpi, 0, 4 * sizeof(struct prog_instruction));
444
445 for (i=0; i < 4; i++) {
446 GLint idx;
447 tokens[3] = tokens[4] = i;
448 idx = _mesa_add_state_reference(paramList, tokens);
449 #ifdef PREFER_DP4
450 vpi[i].Opcode = OPCODE_DP4;
451 vpi[i].StringPos = 0;
452 vpi[i].Data = 0;
453
454 vpi[i].DstReg.File = PROGRAM_OUTPUT;
455 vpi[i].DstReg.Index = VERT_RESULT_HPOS;
456 vpi[i].DstReg.WriteMask = 1 << i;
457 vpi[i].DstReg.CondMask = COND_TR;
458
459 vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR;
460 vpi[i].SrcReg[0].Index = idx;
461 vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W);
462
463 vpi[i].SrcReg[1].File = PROGRAM_INPUT;
464 vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS;
465 vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W);
466 #else
467 if (i == 0)
468 vpi[i].Opcode = OPCODE_MUL;
469 else
470 vpi[i].Opcode = OPCODE_MAD;
471
472 vpi[i].StringPos = 0;
473 vpi[i].Data = 0;
474
475 if (i == 3)
476 vpi[i].DstReg.File = PROGRAM_OUTPUT;
477 else
478 vpi[i].DstReg.File = PROGRAM_TEMPORARY;
479 vpi[i].DstReg.Index = 0;
480 vpi[i].DstReg.WriteMask = 0xf;
481 vpi[i].DstReg.CondMask = COND_TR;
482
483 vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR;
484 vpi[i].SrcReg[0].Index = idx;
485 vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W);
486
487 vpi[i].SrcReg[1].File = PROGRAM_INPUT;
488 vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS;
489 vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(i, i, i, i);
490
491 if (i > 0) {
492 vpi[i].SrcReg[2].File = PROGRAM_TEMPORARY;
493 vpi[i].SrcReg[2].Index = 0;
494 vpi[i].SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W);
495 }
496 #endif
497 }
498
499 memcpy(&vpi[i], mesa_vp->Base.Instructions, mesa_vp->Base.NumInstructions * sizeof(struct prog_instruction));
500
501 free(mesa_vp->Base.Instructions);
502
503 mesa_vp->Base.Instructions = vpi;
504
505 mesa_vp->Base.NumInstructions += 4;
506 vpi = &mesa_vp->Base.Instructions[mesa_vp->Base.NumInstructions-1];
507
508 assert(vpi->Opcode == OPCODE_END);
509
510 mesa_vp->Base.InputsRead |= (1 << VERT_ATTRIB_POS);
511 mesa_vp->Base.OutputsWritten |= (1 << VERT_RESULT_HPOS);
512
513 //fprintf(stderr, "IsPositionInvariant is set!\n");
514 //_mesa_print_program(&mesa_vp->Base);
515 }
516
517 vp->pos_end=0; /* Not supported yet */
518 vp->program.length=0;
519 vp->num_temporaries=mesa_vp->Base.NumTemporaries;
520
521 for(i=0; i < VERT_ATTRIB_MAX; i++)
522 vp->inputs[i] = -1;
523
524 for(i=0; i < VERT_RESULT_MAX; i++)
525 vp->outputs[i] = -1;
526
527 assert(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_HPOS));
528
529 /* Assign outputs */
530 if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_HPOS))
531 vp->outputs[VERT_RESULT_HPOS] = cur_reg++;
532
533 if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_PSIZ))
534 vp->outputs[VERT_RESULT_PSIZ] = cur_reg++;
535
536 if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_COL0))
537 vp->outputs[VERT_RESULT_COL0] = cur_reg++;
538
539 if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_COL1))
540 vp->outputs[VERT_RESULT_COL1] = cur_reg++;
541
542 #if 0 /* Not supported yet */
543 if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_BFC0))
544 vp->outputs[VERT_RESULT_BFC0] = cur_reg++;
545
546 if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_BFC1))
547 vp->outputs[VERT_RESULT_BFC1] = cur_reg++;
548
549 if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_FOGC))
550 vp->outputs[VERT_RESULT_FOGC] = cur_reg++;
551 #endif
552
553 for(i=VERT_RESULT_TEX0; i <= VERT_RESULT_TEX7; i++)
554 if(mesa_vp->Base.OutputsWritten & (1 << i))
555 vp->outputs[i] = cur_reg++;
556
557 vp->translated = GL_TRUE;
558 vp->native = GL_TRUE;
559
560 o_inst=vp->program.body.i;
561 for(vpi=mesa_vp->Base.Instructions; vpi->Opcode != OPCODE_END; vpi++, o_inst++){
562 FREE_TEMPS();
563
564 operands=op_operands(vpi->Opcode);
565 are_srcs_scalar=operands & SCALAR_FLAG;
566 operands &= OP_MASK;
567
568 for(i=0; i < operands; i++)
569 src[i]=vpi->SrcReg[i];
570
571 if(operands == 3){ /* TODO: scalars */
572 if( CMP_SRCS(src[1], src[2]) || CMP_SRCS(src[0], src[2]) ){
573 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i,
574 VSF_FLAG_ALL, VSF_OUT_CLASS_TMP);
575
576 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[2]),
577 SWIZZLE_X, SWIZZLE_Y,
578 SWIZZLE_Z, SWIZZLE_W,
579 t_src_class(src[2].File), VSF_FLAG_NONE);
580
581 o_inst->src2=ZERO_SRC_2;
582 o_inst->src3=ZERO_SRC_2;
583 o_inst++;
584
585 src[2].File=PROGRAM_TEMPORARY;
586 src[2].Index=u_temp_i;
587 u_temp_i--;
588 }
589
590 }
591
592 if(operands >= 2){
593 if( CMP_SRCS(src[1], src[0]) ){
594 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i,
595 VSF_FLAG_ALL, VSF_OUT_CLASS_TMP);
596
597 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
598 SWIZZLE_X, SWIZZLE_Y,
599 SWIZZLE_Z, SWIZZLE_W,
600 t_src_class(src[0].File), VSF_FLAG_NONE);
601
602 o_inst->src2=ZERO_SRC_0;
603 o_inst->src3=ZERO_SRC_0;
604 o_inst++;
605
606 src[0].File=PROGRAM_TEMPORARY;
607 src[0].Index=u_temp_i;
608 u_temp_i--;
609 }
610 }
611
612 /* These ops need special handling. */
613 switch(vpi->Opcode){
614 case OPCODE_ARL:
615 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ARL, t_dst_index(vp, &vpi->DstReg),
616 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
617 o_inst->src1=t_src_scalar(vp, &src[0]);
618 o_inst->src2=ZERO_SRC_0;
619 o_inst->src3=ZERO_SRC_0;
620 goto next;
621
622 case OPCODE_POW:
623 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_POW, t_dst_index(vp, &vpi->DstReg),
624 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
625 o_inst->src1=t_src_scalar(vp, &src[0]);
626 o_inst->src2=ZERO_SRC_0;
627 o_inst->src3=t_src_scalar(vp, &src[1]);
628 goto next;
629
630 case OPCODE_MOV://ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO}
631 #if 1
632 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg),
633 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
634 o_inst->src1=t_src(vp, &src[0]);
635 o_inst->src2=ZERO_SRC_0;
636 o_inst->src3=ZERO_SRC_0;
637 #else
638 hw_op=(src[0].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD;
639
640 o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg),
641 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
642 o_inst->src1=t_src(vp, &src[0]);
643 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
644 SWIZZLE_ONE, SWIZZLE_ONE,
645 SWIZZLE_ONE, SWIZZLE_ONE,
646 t_src_class(src[0].File), VSF_FLAG_NONE);
647
648
649 o_inst->src3=ZERO_SRC_0;
650 #endif
651
652 goto next;
653
654 case OPCODE_ADD:
655 #if 1
656 hw_op=(src[0].File == PROGRAM_TEMPORARY &&
657 src[1].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD;
658
659 o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg),
660 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
661 o_inst->src1=ONE_SRC_0;
662 o_inst->src2=t_src(vp, &src[0]);
663 o_inst->src3=t_src(vp, &src[1]);
664 #else
665 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg),
666 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
667 o_inst->src1=t_src(vp, &src[0]);
668 o_inst->src2=t_src(vp, &src[1]);
669 o_inst->src3=ZERO_SRC_1;
670
671 #endif
672 goto next;
673
674 case OPCODE_MAD:
675 hw_op=(src[0].File == PROGRAM_TEMPORARY &&
676 src[1].File == PROGRAM_TEMPORARY &&
677 src[2].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD;
678
679 o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg),
680 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
681 o_inst->src1=t_src(vp, &src[0]);
682 o_inst->src2=t_src(vp, &src[1]);
683 o_inst->src3=t_src(vp, &src[2]);
684 goto next;
685
686 case OPCODE_MUL: /* HW mul can take third arg but appears to have some other limitations. */
687 hw_op=(src[0].File == PROGRAM_TEMPORARY &&
688 src[1].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD;
689
690 o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg),
691 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
692 o_inst->src1=t_src(vp, &src[0]);
693 o_inst->src2=t_src(vp, &src[1]);
694
695 o_inst->src3=ZERO_SRC_1;
696 goto next;
697
698 case OPCODE_DP3://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO}
699 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, t_dst_index(vp, &vpi->DstReg),
700 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
701
702 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
703 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
704 t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
705 t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
706 SWIZZLE_ZERO,
707 t_src_class(src[0].File),
708 src[0].NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE);
709
710 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
711 t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
712 t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
713 t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
714 SWIZZLE_ZERO,
715 t_src_class(src[1].File),
716 src[1].NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE);
717
718 o_inst->src3=ZERO_SRC_1;
719 goto next;
720
721 case OPCODE_SUB://ADD RESULT 1.X Y Z W TMP 0{} {X Y Z W} PARAM 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W
722 #if 1
723 hw_op=(src[0].File == PROGRAM_TEMPORARY &&
724 src[1].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD;
725
726 o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg),
727 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
728 o_inst->src1=t_src(vp, &src[0]);
729 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
730 SWIZZLE_ONE, SWIZZLE_ONE,
731 SWIZZLE_ONE, SWIZZLE_ONE,
732 t_src_class(src[0].File), VSF_FLAG_NONE);
733 o_inst->src3=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
734 t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
735 t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
736 t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
737 t_swizzle(GET_SWZ(src[1].Swizzle, 3)),
738 t_src_class(src[1].File),
739 (!src[1].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE);
740 #else
741 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg),
742 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
743
744 o_inst->src1=t_src(vp, &src[0]);
745 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
746 t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
747 t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
748 t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
749 t_swizzle(GET_SWZ(src[1].Swizzle, 3)),
750 t_src_class(src[1].File),
751 (!src[1].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE);
752 o_inst->src3=0;
753 #endif
754 goto next;
755
756 case OPCODE_ABS://MAX RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W
757 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MAX, t_dst_index(vp, &vpi->DstReg),
758 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
759
760 o_inst->src1=t_src(vp, &src[0]);
761 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
762 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
763 t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
764 t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
765 t_swizzle(GET_SWZ(src[0].Swizzle, 3)),
766 t_src_class(src[0].File),
767 (!src[0].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE);
768 o_inst->src3=0;
769 goto next;
770
771 case OPCODE_FLR:
772 /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W}
773 ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} TMP 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W */
774
775 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_FRC, u_temp_i,
776 t_dst_mask(vpi->DstReg.WriteMask), VSF_OUT_CLASS_TMP);
777
778 o_inst->src1=t_src(vp, &src[0]);
779 o_inst->src2=ZERO_SRC_0;
780 o_inst->src3=ZERO_SRC_0;
781 o_inst++;
782
783 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg),
784 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
785
786 o_inst->src1=t_src(vp, &src[0]);
787 o_inst->src2=MAKE_VSF_SOURCE(u_temp_i,
788 VSF_IN_COMPONENT_X,
789 VSF_IN_COMPONENT_Y,
790 VSF_IN_COMPONENT_Z,
791 VSF_IN_COMPONENT_W,
792 VSF_IN_CLASS_TMP,
793 /* Not 100% sure about this */
794 (!src[1].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/);
795
796 o_inst->src3=ZERO_SRC_0;
797 u_temp_i--;
798 goto next;
799
800 case OPCODE_LG2:// LG2 RESULT 1.X Y Z W PARAM 0{} {X X X X}
801 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_LG2, t_dst_index(vp, &vpi->DstReg),
802 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
803
804 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
805 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
806 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
807 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
808 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
809 t_src_class(src[0].File),
810 src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE);
811 o_inst->src2=ZERO_SRC_0;
812 o_inst->src3=ZERO_SRC_0;
813 goto next;
814
815 case OPCODE_LIT://LIT TMP 1.Y Z TMP 1{} {X W Z Y} TMP 1{} {Y W Z X} TMP 1{} {Y X Z W}
816 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_LIT, t_dst_index(vp, &vpi->DstReg),
817 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
818 /* NOTE: Users swizzling might not work. */
819 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
820 t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
821 t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
822 VSF_IN_COMPONENT_ZERO, // z
823 t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
824 t_src_class(src[0].File),
825 src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE);
826 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
827 t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
828 t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
829 VSF_IN_COMPONENT_ZERO, // z
830 t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
831 t_src_class(src[0].File),
832 src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE);
833 o_inst->src3=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
834 t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
835 t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
836 VSF_IN_COMPONENT_ZERO, // z
837 t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
838 t_src_class(src[0].File),
839 src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE);
840 goto next;
841
842 case OPCODE_DPH://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W}
843 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, t_dst_index(vp, &vpi->DstReg),
844 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
845
846 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
847 t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
848 t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
849 t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
850 VSF_IN_COMPONENT_ONE,
851 t_src_class(src[0].File),
852 src[0].NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE);
853 o_inst->src2=t_src(vp, &src[1]);
854 o_inst->src3=ZERO_SRC_1;
855 goto next;
856
857 case OPCODE_XPD:
858 /* mul r0, r1.yzxw, r2.zxyw
859 mad r0, -r2.yzxw, r1.zxyw, r0
860 NOTE: might need MAD_2
861 */
862
863 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, u_temp_i,
864 t_dst_mask(vpi->DstReg.WriteMask), VSF_OUT_CLASS_TMP);
865
866 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
867 t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
868 t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z
869 t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
870 t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
871 t_src_class(src[0].File),
872 src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE);
873
874 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
875 t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z
876 t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x
877 t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y
878 t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w
879 t_src_class(src[1].File),
880 src[1].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE);
881
882 o_inst->src3=ZERO_SRC_1;
883 o_inst++;
884 u_temp_i--;
885
886 o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, t_dst_index(vp, &vpi->DstReg),
887 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
888
889 o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
890 t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y
891 t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z
892 t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x
893 t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w
894 t_src_class(src[1].File),
895 (!src[1].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE);
896
897 o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
898 t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z
899 t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
900 t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
901 t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
902 t_src_class(src[0].File),
903 src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE);
904
905 o_inst->src3=MAKE_VSF_SOURCE(u_temp_i+1,
906 VSF_IN_COMPONENT_X,
907 VSF_IN_COMPONENT_Y,
908 VSF_IN_COMPONENT_Z,
909 VSF_IN_COMPONENT_W,
910 VSF_IN_CLASS_TMP,
911 VSF_FLAG_NONE);
912
913 goto next;
914
915 case OPCODE_RCC:
916 fprintf(stderr, "Dont know how to handle op %d yet\n", vpi->Opcode);
917 exit(-1);
918 break;
919 case OPCODE_END:
920 break;
921 default:
922 break;
923 }
924
925 o_inst->op=MAKE_VSF_OP(t_opcode(vpi->Opcode), t_dst_index(vp, &vpi->DstReg),
926 t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
927
928 if(are_srcs_scalar){
929 switch(operands){
930 case 1:
931 o_inst->src1=t_src_scalar(vp, &src[0]);
932 o_inst->src2=ZERO_SRC_0;
933 o_inst->src3=ZERO_SRC_0;
934 break;
935
936 case 2:
937 o_inst->src1=t_src_scalar(vp, &src[0]);
938 o_inst->src2=t_src_scalar(vp, &src[1]);
939 o_inst->src3=ZERO_SRC_1;
940 break;
941
942 case 3:
943 o_inst->src1=t_src_scalar(vp, &src[0]);
944 o_inst->src2=t_src_scalar(vp, &src[1]);
945 o_inst->src3=t_src_scalar(vp, &src[2]);
946 break;
947
948 default:
949 fprintf(stderr, "scalars and op RCC not handled yet");
950 exit(-1);
951 break;
952 }
953 }else{
954 switch(operands){
955 case 1:
956 o_inst->src1=t_src(vp, &src[0]);
957 o_inst->src2=ZERO_SRC_0;
958 o_inst->src3=ZERO_SRC_0;
959 break;
960
961 case 2:
962 o_inst->src1=t_src(vp, &src[0]);
963 o_inst->src2=t_src(vp, &src[1]);
964 o_inst->src3=ZERO_SRC_1;
965 break;
966
967 case 3:
968 o_inst->src1=t_src(vp, &src[0]);
969 o_inst->src2=t_src(vp, &src[1]);
970 o_inst->src3=t_src(vp, &src[2]);
971 break;
972
973 default:
974 fprintf(stderr, "scalars and op RCC not handled yet");
975 exit(-1);
976 break;
977 }
978 }
979 next: ;
980 }
981
982 /* Will most likely segfault before we get here... fix later. */
983 if(o_inst - vp->program.body.i >= VSF_MAX_FRAGMENT_LENGTH/4) {
984 vp->program.length = 0;
985 vp->native = GL_FALSE;
986 return ;
987 }
988 vp->program.length=(o_inst - vp->program.body.i) * 4;
989 #if 0
990 fprintf(stderr, "hw program:\n");
991 for(i=0; i < vp->program.length; i++)
992 fprintf(stderr, "%08x\n", vp->program.body.d[i]);
993 #endif
994 }
995