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