mesa: fix deleting the dummy ATI_fs
[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 are new,
601 and alpha instructions might also be new if there was no preceding color inst */
602 if ((optype == 0) || (curProg->last_optype == optype)) {
603 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
604 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
605 return;
606 }
607 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
608 match_pair_inst(curProg, optype);
609 new_arith_inst(curProg);
610 }
611 curProg->last_optype = optype;
612 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
613
614 /* add the instructions */
615 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
616
617 /* error checking */
618 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
619 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
620 return;
621 }
622 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
623 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
624 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
625 (modtemp != GL_EIGHTH_BIT_ATI)) {
626 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
627 return;
628 }
629 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
630 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
631 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
632 return;
633 }
634 if (optype == 1) {
635 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
636 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
637 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
638 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
639 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
640 return;
641 }
642 }
643 if ((op == GL_DOT4_ATI) &&
644 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
645 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
646 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
647 }
648
649 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
650 return;
651 }
652 if (arg2) {
653 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
654 return;
655 }
656 }
657 if (arg3) {
658 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
659 return;
660 }
661 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
662 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
663 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
664 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
665 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
666 return;
667 }
668 }
669
670 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
671
672 curI->Opcode[optype] = op;
673 curI->SrcReg[optype][0].Index = arg1;
674 curI->SrcReg[optype][0].argRep = arg1Rep;
675 curI->SrcReg[optype][0].argMod = arg1Mod;
676 curI->ArgCount[optype] = arg_count;
677
678 if (arg2) {
679 curI->SrcReg[optype][1].Index = arg2;
680 curI->SrcReg[optype][1].argRep = arg2Rep;
681 curI->SrcReg[optype][1].argMod = arg2Mod;
682 }
683
684 if (arg3) {
685 curI->SrcReg[optype][2].Index = arg3;
686 curI->SrcReg[optype][2].argRep = arg3Rep;
687 curI->SrcReg[optype][2].argMod = arg3Mod;
688 }
689
690 curI->DstReg[optype].Index = dst;
691 curI->DstReg[optype].dstMod = dstMod;
692 curI->DstReg[optype].dstMask = dstMask;
693
694 #if MESA_DEBUG_ATI_FS
695 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
696 #endif
697
698 }
699
700 void GLAPIENTRY
701 _mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
702 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
703 GLuint arg1Mod)
704 {
705 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
706 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
707 }
708
709 void GLAPIENTRY
710 _mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
711 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
712 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
713 GLuint arg2Mod)
714 {
715 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
716 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
717 arg2Mod, 0, 0, 0);
718 }
719
720 void GLAPIENTRY
721 _mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
722 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
723 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
724 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
725 GLuint arg3Mod)
726 {
727 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
728 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
729 arg2Mod, arg3, arg3Rep, arg3Mod);
730 }
731
732 void GLAPIENTRY
733 _mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
734 GLuint arg1Rep, GLuint arg1Mod)
735 {
736 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
737 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
738 }
739
740 void GLAPIENTRY
741 _mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
742 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
743 GLuint arg2Rep, GLuint arg2Mod)
744 {
745 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
746 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
747 0);
748 }
749
750 void GLAPIENTRY
751 _mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
752 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
753 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
754 GLuint arg3Rep, GLuint arg3Mod)
755 {
756 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
757 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
758 arg3Rep, arg3Mod);
759 }
760
761 void GLAPIENTRY
762 _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
763 {
764 GLuint dstindex;
765 GET_CURRENT_CONTEXT(ctx);
766
767 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
768 /* spec says nothing about what should happen here but we can't just segfault...*/
769 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
770 return;
771 }
772
773 dstindex = dst - GL_CON_0_ATI;
774 if (ctx->ATIFragmentShader.Compiling) {
775 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
776 COPY_4V(curProg->Constants[dstindex], value);
777 curProg->LocalConstDef |= 1 << dstindex;
778 }
779 else {
780 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
781 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
782 }
783 }