Fix pow <small> and a very stypid bug with dummy srcs(0 equals to tmp0.x)</small...
[mesa.git] / src / mesa / shader / atifragshader.c
1 /**
2 * \file atifragshader.c
3 * \author David Airlie
4 * Copyright (C) 2004 David Airlie All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "glheader.h"
25 #include "context.h"
26 #include "hash.h"
27 #include "imports.h"
28 #include "macros.h"
29 #include "enums.h"
30 #include "mtypes.h"
31 #include "atifragshader.h"
32
33 #define MESA_DEBUG_ATI_FS 0
34
35 static struct ati_fragment_shader DummyShader;
36
37
38 /**
39 * Allocate and initialize a new ATI fragment shader object.
40 */
41 struct ati_fragment_shader *
42 _mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id)
43 {
44 struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
45 (void) ctx;
46 if (s) {
47 s->Id = id;
48 s->RefCount = 1;
49 }
50 return s;
51 }
52
53
54 /**
55 * Delete the given ati fragment shader
56 */
57 void
58 _mesa_delete_ati_fragment_shader(GLcontext *ctx, struct ati_fragment_shader *s)
59 {
60 GLuint i;
61 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
62 if (s->Instructions[i])
63 _mesa_free(s->Instructions[i]);
64 if (s->SetupInst[i])
65 _mesa_free(s->SetupInst[i]);
66 }
67 _mesa_free(s);
68 }
69
70
71
72 static void
73 new_arith_inst(struct ati_fragment_shader *prog)
74 {
75 /* set "default" instruction as not all may get defined.
76 there is no specified way to express a nop with ati fragment shaders we use
77 GL_NONE as the op enum and just set some params to 0 - so nothing to do here */
78 prog->numArithInstr[prog->cur_pass >> 1]++;
79 }
80
81 static void
82 new_tex_inst(struct ati_fragment_shader *prog)
83 {
84 }
85
86 static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
87 {
88 if (optype == curProg->last_optype) {
89 curProg->last_optype = 1;
90 }
91 }
92
93 #if MESA_DEBUG_ATI_FS
94 static char *
95 create_dst_mod_str(GLuint mod)
96 {
97 static char ret_str[1024];
98
99 _mesa_memset(ret_str, 0, 1024);
100 if (mod & GL_2X_BIT_ATI)
101 _mesa_strncat(ret_str, "|2X", 1024);
102
103 if (mod & GL_4X_BIT_ATI)
104 _mesa_strncat(ret_str, "|4X", 1024);
105
106 if (mod & GL_8X_BIT_ATI)
107 _mesa_strncat(ret_str, "|8X", 1024);
108 if (mod & GL_HALF_BIT_ATI)
109 _mesa_strncat(ret_str, "|HA", 1024);
110 if (mod & GL_QUARTER_BIT_ATI)
111 _mesa_strncat(ret_str, "|QU", 1024);
112 if (mod & GL_EIGHTH_BIT_ATI)
113 _mesa_strncat(ret_str, "|EI", 1024);
114
115 if (mod & GL_SATURATE_BIT_ATI)
116 _mesa_strncat(ret_str, "|SAT", 1024);
117
118 if (_mesa_strlen(ret_str) == 0)
119 _mesa_strncat(ret_str, "NONE", 1024);
120 return ret_str;
121 }
122
123 static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
124 "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
125
126 static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
127 GLuint dstMask, GLuint dstMod, GLuint arg1,
128 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
129 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
130 GLuint arg3Rep, GLuint arg3Mod)
131 {
132 char *op_name;
133
134 op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
135
136 fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op),
137 _mesa_lookup_enum_by_nr(dst));
138 if (!optype)
139 fprintf(stderr, ", %d", dstMask);
140
141 fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
142
143 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1),
144 _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod);
145 if (arg_count>1)
146 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2),
147 _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod);
148 if (arg_count>2)
149 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3),
150 _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod);
151
152 fprintf(stderr,")\n");
153
154 }
155 #endif
156
157 static int check_arith_arg(struct ati_fragment_shader *curProg,
158 GLuint optype, GLuint arg, GLuint argRep)
159 {
160 GET_CURRENT_CONTEXT(ctx);
161
162 if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) &&
163 ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) &&
164 (arg != GL_ZERO) && (arg != GL_ONE) &&
165 (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) {
166 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)");
167 return 0;
168 }
169 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
170 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
171 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
172 return 0;
173 }
174 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
175 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
176 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
177 return 0;
178 }
179 if ((curProg->cur_pass == 1) &&
180 ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
181 curProg->interpinp1 = GL_TRUE;
182 }
183 return 1;
184 }
185
186 GLuint GLAPIENTRY
187 _mesa_GenFragmentShadersATI(GLuint range)
188 {
189 GLuint first;
190 GLuint i;
191 GET_CURRENT_CONTEXT(ctx);
192
193 if (range == 0) {
194 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)");
195 return 0;
196 }
197
198 if (ctx->ATIFragmentShader.Compiling) {
199 _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)");
200 return 0;
201 }
202
203 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
204 for (i = 0; i < range; i++) {
205 _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
206 }
207
208 return first;
209 }
210
211 void GLAPIENTRY
212 _mesa_BindFragmentShaderATI(GLuint id)
213 {
214 GET_CURRENT_CONTEXT(ctx);
215 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
216 struct ati_fragment_shader *newProg;
217
218 if (ctx->ATIFragmentShader.Compiling) {
219 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
220 return;
221 }
222
223 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
224
225 if (curProg->Id == id) {
226 return;
227 }
228
229 /* unbind current */
230 if (curProg->Id != 0) {
231 curProg->RefCount--;
232 if (curProg->RefCount <= 0) {
233 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
234 }
235 }
236
237 /* find new shader */
238 if (id == 0) {
239 newProg = ctx->Shared->DefaultFragmentShader;
240 }
241 else {
242 newProg = (struct ati_fragment_shader *)
243 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
244 if (!newProg || newProg == &DummyShader) {
245 /* allocate a new program now */
246 newProg = _mesa_new_ati_fragment_shader(ctx, id);
247 if (!newProg) {
248 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
249 return;
250 }
251 _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
252 }
253
254 }
255
256 /* do actual bind */
257 ctx->ATIFragmentShader.Current = newProg;
258
259 ASSERT(ctx->ATIFragmentShader.Current);
260 if (newProg)
261 newProg->RefCount++;
262
263 /*if (ctx->Driver.BindProgram)
264 ctx->Driver.BindProgram(ctx, target, prog); */
265 }
266
267 void GLAPIENTRY
268 _mesa_DeleteFragmentShaderATI(GLuint id)
269 {
270 GET_CURRENT_CONTEXT(ctx);
271
272 if (ctx->ATIFragmentShader.Compiling) {
273 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
274 return;
275 }
276
277 if (id != 0) {
278 struct ati_fragment_shader *prog = (struct ati_fragment_shader *)
279 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
280 if (prog == &DummyShader) {
281 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
282 }
283 else if (prog) {
284 if (ctx->ATIFragmentShader.Current &&
285 ctx->ATIFragmentShader.Current->Id == id) {
286 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
287 _mesa_BindFragmentShaderATI(0);
288 }
289 }
290
291 /* The ID is immediately available for re-use now */
292 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
293 prog->RefCount--;
294 if (prog->RefCount <= 0) {
295 _mesa_free(prog);
296 }
297 }
298 }
299
300
301 void GLAPIENTRY
302 _mesa_BeginFragmentShaderATI(void)
303 {
304 GLint i;
305 GET_CURRENT_CONTEXT(ctx);
306
307 if (ctx->ATIFragmentShader.Compiling) {
308 _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
309 return;
310 }
311
312 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
313
314 /* if the shader was already defined free instructions and get new ones
315 (or, could use the same mem but would need to reinitialize) */
316 /* no idea if it's allowed to redefine a shader */
317 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
318 if (ctx->ATIFragmentShader.Current->Instructions[i])
319 _mesa_free(ctx->ATIFragmentShader.Current->Instructions[i]);
320 if (ctx->ATIFragmentShader.Current->SetupInst[i])
321 _mesa_free(ctx->ATIFragmentShader.Current->SetupInst[i]);
322 }
323
324 /* malloc the instructions here - not sure if the best place but its
325 a start */
326 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
327 ctx->ATIFragmentShader.Current->Instructions[i] =
328 (struct atifs_instruction *)
329 _mesa_calloc(sizeof(struct atifs_instruction) *
330 (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
331 ctx->ATIFragmentShader.Current->SetupInst[i] =
332 (struct atifs_setupinst *)
333 _mesa_calloc(sizeof(struct atifs_setupinst) *
334 (MAX_NUM_FRAGMENT_REGISTERS_ATI));
335 }
336
337 /* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
338 ctx->ATIFragmentShader.Current->LocalConstDef = 0;
339 ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
340 ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
341 ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
342 ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
343 ctx->ATIFragmentShader.Current->NumPasses = 0;
344 ctx->ATIFragmentShader.Current->cur_pass = 0;
345 ctx->ATIFragmentShader.Current->last_optype = 0;
346 ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
347 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
348 ctx->ATIFragmentShader.Current->swizzlerq = 0;
349 ctx->ATIFragmentShader.Compiling = 1;
350 }
351
352 void GLAPIENTRY
353 _mesa_EndFragmentShaderATI(void)
354 {
355 GET_CURRENT_CONTEXT(ctx);
356 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
357 #if MESA_DEBUG_ATI_FS
358 GLint i, j;
359 #endif
360
361 if (!ctx->ATIFragmentShader.Compiling) {
362 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
363 return;
364 }
365 if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
366 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
367 /* according to spec, DON'T return here */
368 }
369
370 match_pair_inst(curProg, 0);
371 ctx->ATIFragmentShader.Compiling = 0;
372 ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
373 if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
374 (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
375 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
376 }
377 if (ctx->ATIFragmentShader.Current->cur_pass > 1)
378 ctx->ATIFragmentShader.Current->NumPasses = 2;
379 else ctx->ATIFragmentShader.Current->NumPasses = 1;
380 ctx->ATIFragmentShader.Current->cur_pass=0;
381 #if MESA_DEBUG_ATI_FS
382 for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
383 for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
384 GLuint op = curProg->SetupInst[j][i].Opcode;
385 const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0";
386 GLuint src = curProg->SetupInst[j][i].src;
387 GLuint swizzle = curProg->SetupInst[j][i].swizzle;
388 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
389 swizzle);
390 }
391 for (i = 0; i < curProg->numArithInstr[j]; i++) {
392 GLuint op0 = curProg->Instructions[j][i].Opcode[0];
393 GLuint op1 = curProg->Instructions[j][i].Opcode[1];
394 const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0";
395 const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0";
396 GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
397 GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
398 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
399 op1, op1_enum, count1);
400 }
401 }
402 #endif
403 }
404
405 void GLAPIENTRY
406 _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
407 {
408 GET_CURRENT_CONTEXT(ctx);
409 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
410 struct atifs_setupinst *curI;
411
412 if (!ctx->ATIFragmentShader.Compiling) {
413 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
414 return;
415 }
416
417 if (curProg->cur_pass == 1) {
418 match_pair_inst(curProg, 0);
419 curProg->cur_pass = 2;
420 }
421 if ((curProg->cur_pass > 2) ||
422 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
423 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
424 return;
425 }
426 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
427 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
428 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
429 return;
430 }
431 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
432 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
433 ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
434 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
435 return;
436 }
437 if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
438 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
439 return;
440 }
441 if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
442 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
443 return;
444 }
445 if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
446 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
447 return;
448 }
449 if (coord <= GL_TEXTURE7_ARB) {
450 GLuint tmp = coord - GL_TEXTURE0_ARB;
451 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
452 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
453 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
454 return;
455 } else {
456 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
457 }
458 }
459
460 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
461 new_tex_inst(curProg);
462
463 /* add the instructions */
464 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
465
466 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
467 curI->src = coord;
468 curI->swizzle = swizzle;
469
470 #if MESA_DEBUG_ATI_FS
471 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
472 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
473 _mesa_lookup_enum_by_nr(swizzle));
474 #endif
475 }
476
477 void GLAPIENTRY
478 _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
479 {
480 GET_CURRENT_CONTEXT(ctx);
481 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
482 struct atifs_setupinst *curI;
483
484 if (!ctx->ATIFragmentShader.Compiling) {
485 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
486 return;
487 }
488
489 if (curProg->cur_pass == 1) {
490 match_pair_inst(curProg, 0);
491 curProg->cur_pass = 2;
492 }
493 if ((curProg->cur_pass > 2) ||
494 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
495 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
496 return;
497 }
498 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
499 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
500 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
501 return;
502 }
503 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
504 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
505 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
506 /* is this texture5 or texture7? spec is a bit unclear there */
507 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
508 return;
509 }
510 if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
511 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
512 return;
513 }
514 if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
515 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
516 return;
517 }
518 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
519 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
520 return;
521 }
522 if (interp <= GL_TEXTURE7_ARB) {
523 GLuint tmp = interp - GL_TEXTURE0_ARB;
524 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
525 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
526 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
527 return;
528 } else {
529 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
530 }
531 }
532
533 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
534 new_tex_inst(curProg);
535
536 /* add the instructions */
537 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
538
539 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
540 curI->src = interp;
541 curI->swizzle = swizzle;
542
543 #if MESA_DEBUG_ATI_FS
544 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
545 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
546 _mesa_lookup_enum_by_nr(swizzle));
547 #endif
548 }
549
550 static void
551 _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
552 GLuint dstMask, GLuint dstMod, GLuint arg1,
553 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
554 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
555 GLuint arg3Rep, GLuint arg3Mod)
556 {
557 GET_CURRENT_CONTEXT(ctx);
558 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
559 GLint ci;
560 struct atifs_instruction *curI;
561 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
562
563 if (!ctx->ATIFragmentShader.Compiling) {
564 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
565 return;
566 }
567
568 if (curProg->cur_pass==0)
569 curProg->cur_pass=1;
570
571 else if (curProg->cur_pass==2)
572 curProg->cur_pass=3;
573
574 /* decide whether this is a new instruction or not ... all color instructions are new,
575 and alpha instructions might also be new if there was no preceding color inst */
576 if ((optype == 0) || (curProg->last_optype == optype)) {
577 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
578 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
579 return;
580 }
581 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
582 match_pair_inst(curProg, optype);
583 new_arith_inst(curProg);
584 }
585 curProg->last_optype = optype;
586 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
587
588 /* add the instructions */
589 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
590
591 /* error checking */
592 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
593 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
594 return;
595 }
596 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
597 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
598 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
599 (modtemp != GL_EIGHTH_BIT_ATI)) {
600 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
601 return;
602 }
603 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
604 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
605 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
606 return;
607 }
608 if (optype == 1) {
609 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
610 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
611 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
612 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
613 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
614 return;
615 }
616 }
617 if ((op == GL_DOT4_ATI) &&
618 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
619 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
620 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
621 }
622
623 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
624 return;
625 }
626 if (arg2) {
627 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
628 return;
629 }
630 }
631 if (arg3) {
632 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
633 return;
634 }
635 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
636 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
637 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
638 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
639 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
640 return;
641 }
642 }
643
644 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
645
646 curI->Opcode[optype] = op;
647 curI->SrcReg[optype][0].Index = arg1;
648 curI->SrcReg[optype][0].argRep = arg1Rep;
649 curI->SrcReg[optype][0].argMod = arg1Mod;
650 curI->ArgCount[optype] = arg_count;
651
652 if (arg2) {
653 curI->SrcReg[optype][1].Index = arg2;
654 curI->SrcReg[optype][1].argRep = arg2Rep;
655 curI->SrcReg[optype][1].argMod = arg2Mod;
656 }
657
658 if (arg3) {
659 curI->SrcReg[optype][2].Index = arg3;
660 curI->SrcReg[optype][2].argRep = arg3Rep;
661 curI->SrcReg[optype][2].argMod = arg3Mod;
662 }
663
664 curI->DstReg[optype].Index = dst;
665 curI->DstReg[optype].dstMod = dstMod;
666 curI->DstReg[optype].dstMask = dstMask;
667
668 #if MESA_DEBUG_ATI_FS
669 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
670 #endif
671
672 }
673
674 void GLAPIENTRY
675 _mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
676 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
677 GLuint arg1Mod)
678 {
679 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
680 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
681 }
682
683 void GLAPIENTRY
684 _mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
685 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
686 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
687 GLuint arg2Mod)
688 {
689 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
690 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
691 arg2Mod, 0, 0, 0);
692 }
693
694 void GLAPIENTRY
695 _mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
696 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
697 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
698 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
699 GLuint arg3Mod)
700 {
701 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
702 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
703 arg2Mod, arg3, arg3Rep, arg3Mod);
704 }
705
706 void GLAPIENTRY
707 _mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
708 GLuint arg1Rep, GLuint arg1Mod)
709 {
710 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
711 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
712 }
713
714 void GLAPIENTRY
715 _mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
716 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
717 GLuint arg2Rep, GLuint arg2Mod)
718 {
719 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
720 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
721 0);
722 }
723
724 void GLAPIENTRY
725 _mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
726 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
727 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
728 GLuint arg3Rep, GLuint arg3Mod)
729 {
730 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
731 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
732 arg3Rep, arg3Mod);
733 }
734
735 void GLAPIENTRY
736 _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
737 {
738 GLuint dstindex;
739 GET_CURRENT_CONTEXT(ctx);
740
741 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
742 /* spec says nothing about what should happen here but we can't just segfault...*/
743 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
744 return;
745 }
746
747 dstindex = dst - GL_CON_0_ATI;
748 if (ctx->ATIFragmentShader.Compiling) {
749 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
750 COPY_4V(curProg->Constants[dstindex], value);
751 curProg->LocalConstDef |= 1 << dstindex;
752 }
753 else {
754 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
755 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
756 }
757 }