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