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