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