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