Merge commit 'origin/gallium-draw-retval'
[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 "main/glheader.h"
25 #include "main/context.h"
26 #include "main/hash.h"
27 #include "main/imports.h"
28 #include "main/macros.h"
29 #include "main/enums.h"
30 #include "main/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 if (prog) {
294 prog->RefCount--;
295 if (prog->RefCount <= 0) {
296 _mesa_free(prog);
297 }
298 }
299 }
300 }
301
302
303 void GLAPIENTRY
304 _mesa_BeginFragmentShaderATI(void)
305 {
306 GLint i;
307 GET_CURRENT_CONTEXT(ctx);
308
309 if (ctx->ATIFragmentShader.Compiling) {
310 _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
311 return;
312 }
313
314 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
315
316 /* if the shader was already defined free instructions and get new ones
317 (or, could use the same mem but would need to reinitialize) */
318 /* no idea if it's allowed to redefine a shader */
319 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
320 if (ctx->ATIFragmentShader.Current->Instructions[i])
321 _mesa_free(ctx->ATIFragmentShader.Current->Instructions[i]);
322 if (ctx->ATIFragmentShader.Current->SetupInst[i])
323 _mesa_free(ctx->ATIFragmentShader.Current->SetupInst[i]);
324 }
325
326 /* malloc the instructions here - not sure if the best place but its
327 a start */
328 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
329 ctx->ATIFragmentShader.Current->Instructions[i] =
330 (struct atifs_instruction *)
331 _mesa_calloc(sizeof(struct atifs_instruction) *
332 (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
333 ctx->ATIFragmentShader.Current->SetupInst[i] =
334 (struct atifs_setupinst *)
335 _mesa_calloc(sizeof(struct atifs_setupinst) *
336 (MAX_NUM_FRAGMENT_REGISTERS_ATI));
337 }
338
339 /* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
340 ctx->ATIFragmentShader.Current->LocalConstDef = 0;
341 ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
342 ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
343 ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
344 ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
345 ctx->ATIFragmentShader.Current->NumPasses = 0;
346 ctx->ATIFragmentShader.Current->cur_pass = 0;
347 ctx->ATIFragmentShader.Current->last_optype = 0;
348 ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
349 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
350 ctx->ATIFragmentShader.Current->swizzlerq = 0;
351 ctx->ATIFragmentShader.Compiling = 1;
352 }
353
354 void GLAPIENTRY
355 _mesa_EndFragmentShaderATI(void)
356 {
357 GET_CURRENT_CONTEXT(ctx);
358 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
359 #if MESA_DEBUG_ATI_FS
360 GLint i, j;
361 #endif
362
363 if (!ctx->ATIFragmentShader.Compiling) {
364 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
365 return;
366 }
367 if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
368 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
369 /* according to spec, DON'T return here */
370 }
371
372 match_pair_inst(curProg, 0);
373 ctx->ATIFragmentShader.Compiling = 0;
374 ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
375 if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
376 (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
377 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
378 }
379 if (ctx->ATIFragmentShader.Current->cur_pass > 1)
380 ctx->ATIFragmentShader.Current->NumPasses = 2;
381 else ctx->ATIFragmentShader.Current->NumPasses = 1;
382 ctx->ATIFragmentShader.Current->cur_pass=0;
383 #if MESA_DEBUG_ATI_FS
384 for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
385 for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
386 GLuint op = curProg->SetupInst[j][i].Opcode;
387 const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0";
388 GLuint src = curProg->SetupInst[j][i].src;
389 GLuint swizzle = curProg->SetupInst[j][i].swizzle;
390 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
391 swizzle);
392 }
393 for (i = 0; i < curProg->numArithInstr[j]; i++) {
394 GLuint op0 = curProg->Instructions[j][i].Opcode[0];
395 GLuint op1 = curProg->Instructions[j][i].Opcode[1];
396 const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0";
397 const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0";
398 GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
399 GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
400 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
401 op1, op1_enum, count1);
402 }
403 }
404 #endif
405 if (ctx->Driver.ProgramStringNotify)
406 ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_SHADER_ATI, NULL );
407 }
408
409 void GLAPIENTRY
410 _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
411 {
412 GET_CURRENT_CONTEXT(ctx);
413 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
414 struct atifs_setupinst *curI;
415
416 if (!ctx->ATIFragmentShader.Compiling) {
417 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
418 return;
419 }
420
421 if (curProg->cur_pass == 1) {
422 match_pair_inst(curProg, 0);
423 curProg->cur_pass = 2;
424 }
425 if ((curProg->cur_pass > 2) ||
426 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
427 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
428 return;
429 }
430 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
431 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
432 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
433 return;
434 }
435 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
436 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
437 ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
438 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
439 return;
440 }
441 if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
442 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
443 return;
444 }
445 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
446 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
447 return;
448 }
449 if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
450 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
451 return;
452 }
453 if (coord <= GL_TEXTURE7_ARB) {
454 GLuint tmp = coord - GL_TEXTURE0_ARB;
455 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
456 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
457 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
458 return;
459 } else {
460 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
461 }
462 }
463
464 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
465 new_tex_inst(curProg);
466
467 /* add the instructions */
468 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
469
470 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
471 curI->src = coord;
472 curI->swizzle = swizzle;
473
474 #if MESA_DEBUG_ATI_FS
475 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
476 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
477 _mesa_lookup_enum_by_nr(swizzle));
478 #endif
479 }
480
481 void GLAPIENTRY
482 _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
483 {
484 GET_CURRENT_CONTEXT(ctx);
485 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
486 struct atifs_setupinst *curI;
487
488 if (!ctx->ATIFragmentShader.Compiling) {
489 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
490 return;
491 }
492
493 if (curProg->cur_pass == 1) {
494 match_pair_inst(curProg, 0);
495 curProg->cur_pass = 2;
496 }
497 if ((curProg->cur_pass > 2) ||
498 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
499 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
500 return;
501 }
502 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
503 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
504 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
505 return;
506 }
507 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
508 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
509 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
510 /* is this texture5 or texture7? spec is a bit unclear there */
511 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
512 return;
513 }
514 if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
515 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
516 return;
517 }
518 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
519 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
520 return;
521 }
522 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
523 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
524 return;
525 }
526 if (interp <= GL_TEXTURE7_ARB) {
527 GLuint tmp = interp - GL_TEXTURE0_ARB;
528 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
529 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
530 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
531 return;
532 } else {
533 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
534 }
535 }
536
537 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
538 new_tex_inst(curProg);
539
540 /* add the instructions */
541 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
542
543 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
544 curI->src = interp;
545 curI->swizzle = swizzle;
546
547 #if MESA_DEBUG_ATI_FS
548 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
549 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
550 _mesa_lookup_enum_by_nr(swizzle));
551 #endif
552 }
553
554 static void
555 _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
556 GLuint dstMask, GLuint dstMod, GLuint arg1,
557 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
558 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
559 GLuint arg3Rep, GLuint arg3Mod)
560 {
561 GET_CURRENT_CONTEXT(ctx);
562 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
563 GLint ci;
564 struct atifs_instruction *curI;
565 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
566
567 if (!ctx->ATIFragmentShader.Compiling) {
568 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
569 return;
570 }
571
572 if (curProg->cur_pass==0)
573 curProg->cur_pass=1;
574
575 else if (curProg->cur_pass==2)
576 curProg->cur_pass=3;
577
578 /* decide whether this is a new instruction or not ... all color instructions are new,
579 and alpha instructions might also be new if there was no preceding color inst */
580 if ((optype == 0) || (curProg->last_optype == optype)) {
581 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
582 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
583 return;
584 }
585 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
586 match_pair_inst(curProg, optype);
587 new_arith_inst(curProg);
588 }
589 curProg->last_optype = optype;
590 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
591
592 /* add the instructions */
593 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
594
595 /* error checking */
596 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
597 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
598 return;
599 }
600 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
601 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
602 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
603 (modtemp != GL_EIGHTH_BIT_ATI)) {
604 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
605 return;
606 }
607 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
608 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
609 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
610 return;
611 }
612 if (optype == 1) {
613 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
614 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
615 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
616 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
617 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
618 return;
619 }
620 }
621 if ((op == GL_DOT4_ATI) &&
622 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
623 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
624 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
625 }
626
627 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
628 return;
629 }
630 if (arg2) {
631 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
632 return;
633 }
634 }
635 if (arg3) {
636 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
637 return;
638 }
639 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
640 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
641 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
642 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
643 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
644 return;
645 }
646 }
647
648 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
649
650 curI->Opcode[optype] = op;
651 curI->SrcReg[optype][0].Index = arg1;
652 curI->SrcReg[optype][0].argRep = arg1Rep;
653 curI->SrcReg[optype][0].argMod = arg1Mod;
654 curI->ArgCount[optype] = arg_count;
655
656 if (arg2) {
657 curI->SrcReg[optype][1].Index = arg2;
658 curI->SrcReg[optype][1].argRep = arg2Rep;
659 curI->SrcReg[optype][1].argMod = arg2Mod;
660 }
661
662 if (arg3) {
663 curI->SrcReg[optype][2].Index = arg3;
664 curI->SrcReg[optype][2].argRep = arg3Rep;
665 curI->SrcReg[optype][2].argMod = arg3Mod;
666 }
667
668 curI->DstReg[optype].Index = dst;
669 curI->DstReg[optype].dstMod = dstMod;
670 curI->DstReg[optype].dstMask = dstMask;
671
672 #if MESA_DEBUG_ATI_FS
673 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
674 #endif
675
676 }
677
678 void GLAPIENTRY
679 _mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
680 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
681 GLuint arg1Mod)
682 {
683 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
684 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
685 }
686
687 void GLAPIENTRY
688 _mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
689 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
690 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
691 GLuint arg2Mod)
692 {
693 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
694 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
695 arg2Mod, 0, 0, 0);
696 }
697
698 void GLAPIENTRY
699 _mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
700 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
701 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
702 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
703 GLuint arg3Mod)
704 {
705 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
706 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
707 arg2Mod, arg3, arg3Rep, arg3Mod);
708 }
709
710 void GLAPIENTRY
711 _mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
712 GLuint arg1Rep, GLuint arg1Mod)
713 {
714 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
715 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
716 }
717
718 void GLAPIENTRY
719 _mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
720 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
721 GLuint arg2Rep, GLuint arg2Mod)
722 {
723 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
724 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
725 0);
726 }
727
728 void GLAPIENTRY
729 _mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
730 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
731 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
732 GLuint arg3Rep, GLuint arg3Mod)
733 {
734 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
735 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
736 arg3Rep, arg3Mod);
737 }
738
739 void GLAPIENTRY
740 _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
741 {
742 GLuint dstindex;
743 GET_CURRENT_CONTEXT(ctx);
744
745 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
746 /* spec says nothing about what should happen here but we can't just segfault...*/
747 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
748 return;
749 }
750
751 dstindex = dst - GL_CON_0_ATI;
752 if (ctx->ATIFragmentShader.Compiling) {
753 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
754 COPY_4V(curProg->Constants[dstindex], value);
755 curProg->LocalConstDef |= 1 << dstindex;
756 }
757 else {
758 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
759 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
760 }
761 }