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
_mesa_init_ati_fragment_shader_dispatch(struct _glapi_table * disp)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 *
_mesa_new_ati_fragment_shader(struct gl_context * ctx,GLuint id)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
_mesa_delete_ati_fragment_shader(struct gl_context * ctx,struct ati_fragment_shader * s)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
new_arith_inst(struct ati_fragment_shader * prog)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
new_tex_inst(struct ati_fragment_shader * prog)106 new_tex_inst(struct ati_fragment_shader *prog)
107 {
108 }
109 
match_pair_inst(struct ati_fragment_shader * curProg,GLuint optype)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 *
create_dst_mod_str(GLuint mod)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 
debug_op(GLint optype,GLuint arg_count,GLenum op,GLuint dst,GLuint dstMask,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod,GLuint arg3,GLuint arg3Rep,GLuint arg3Mod)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 
check_arith_arg(struct ati_fragment_shader * curProg,GLuint optype,GLuint arg,GLuint argRep)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
_mesa_GenFragmentShadersATI(GLuint range)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
_mesa_BindFragmentShaderATI(GLuint id)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
_mesa_DeleteFragmentShaderATI(GLuint id)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
_mesa_BeginFragmentShaderATI(void)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 	 (struct atifs_instruction *)
356 	 calloc(1, sizeof(struct atifs_instruction) *
357 		   (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
358       ctx->ATIFragmentShader.Current->SetupInst[i] =
359 	 (struct atifs_setupinst *)
360 	 calloc(1, sizeof(struct atifs_setupinst) *
361 		   (MAX_NUM_FRAGMENT_REGISTERS_ATI));
362    }
363 
364 /* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
365    ctx->ATIFragmentShader.Current->LocalConstDef = 0;
366    ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
367    ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
368    ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
369    ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
370    ctx->ATIFragmentShader.Current->NumPasses = 0;
371    ctx->ATIFragmentShader.Current->cur_pass = 0;
372    ctx->ATIFragmentShader.Current->last_optype = 0;
373    ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
374    ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
375    ctx->ATIFragmentShader.Current->swizzlerq = 0;
376    ctx->ATIFragmentShader.Compiling = 1;
377 }
378 
379 void GLAPIENTRY
_mesa_EndFragmentShaderATI(void)380 _mesa_EndFragmentShaderATI(void)
381 {
382    GET_CURRENT_CONTEXT(ctx);
383    struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
384 #if MESA_DEBUG_ATI_FS
385    GLint i, j;
386 #endif
387 
388    if (!ctx->ATIFragmentShader.Compiling) {
389       _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
390       return;
391    }
392    if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
393       _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
394    /* according to spec, DON'T return here */
395    }
396 
397    match_pair_inst(curProg, 0);
398    ctx->ATIFragmentShader.Compiling = 0;
399    ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
400    if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
401       (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
402       _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
403    }
404    if (ctx->ATIFragmentShader.Current->cur_pass > 1)
405       ctx->ATIFragmentShader.Current->NumPasses = 2;
406    else
407       ctx->ATIFragmentShader.Current->NumPasses = 1;
408 
409    ctx->ATIFragmentShader.Current->cur_pass = 0;
410 
411 #if MESA_DEBUG_ATI_FS
412    for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
413       for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
414 	 GLuint op = curProg->SetupInst[j][i].Opcode;
415 	 const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0";
416 	 GLuint src = curProg->SetupInst[j][i].src;
417 	 GLuint swizzle = curProg->SetupInst[j][i].swizzle;
418 	 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
419 	      swizzle);
420       }
421       for (i = 0; i < curProg->numArithInstr[j]; i++) {
422 	 GLuint op0 = curProg->Instructions[j][i].Opcode[0];
423 	 GLuint op1 = curProg->Instructions[j][i].Opcode[1];
424 	 const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0";
425 	 const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0";
426 	 GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
427 	 GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
428 	 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
429 	      op1, op1_enum, count1);
430       }
431    }
432 #endif
433 
434    if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, NULL)) {
435       ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
436       /* XXX is this the right error? */
437       _mesa_error(ctx, GL_INVALID_OPERATION,
438                   "glEndFragmentShaderATI(driver rejected shader)");
439    }
440 }
441 
442 void GLAPIENTRY
_mesa_PassTexCoordATI(GLuint dst,GLuint coord,GLenum swizzle)443 _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
444 {
445    GET_CURRENT_CONTEXT(ctx);
446    struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
447    struct atifs_setupinst *curI;
448 
449    if (!ctx->ATIFragmentShader.Compiling) {
450       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
451       return;
452    }
453 
454    if (curProg->cur_pass == 1) {
455       match_pair_inst(curProg, 0);
456       curProg->cur_pass = 2;
457    }
458    if ((curProg->cur_pass > 2) ||
459       ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
460       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
461       return;
462    }
463    if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
464       ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
465       _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
466       return;
467    }
468    if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
469        ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
470        ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
471       _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
472       return;
473    }
474    if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
475       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
476       return;
477    }
478    if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
479       _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
480       return;
481    }
482    if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
483       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
484       return;
485    }
486    if (coord <= GL_TEXTURE7_ARB) {
487       GLuint tmp = coord - GL_TEXTURE0_ARB;
488       if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
489 	   (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
490 	 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
491 	 return;
492       } else {
493 	 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
494       }
495    }
496 
497    curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
498    new_tex_inst(curProg);
499 
500    /* add the instructions */
501    curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
502 
503    curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
504    curI->src = coord;
505    curI->swizzle = swizzle;
506 
507 #if MESA_DEBUG_ATI_FS
508    _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
509 	       _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
510 	       _mesa_lookup_enum_by_nr(swizzle));
511 #endif
512 }
513 
514 void GLAPIENTRY
_mesa_SampleMapATI(GLuint dst,GLuint interp,GLenum swizzle)515 _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
516 {
517    GET_CURRENT_CONTEXT(ctx);
518    struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
519    struct atifs_setupinst *curI;
520 
521    if (!ctx->ATIFragmentShader.Compiling) {
522       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
523       return;
524    }
525 
526    if (curProg->cur_pass == 1) {
527       match_pair_inst(curProg, 0);
528       curProg->cur_pass = 2;
529    }
530    if ((curProg->cur_pass > 2) ||
531       ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
532       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
533       return;
534    }
535    if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
536       ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
537       _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
538       return;
539    }
540    if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
541        ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
542        ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
543    /* is this texture5 or texture7? spec is a bit unclear there */
544       _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
545       return;
546    }
547    if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
548       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
549       return;
550    }
551    if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
552       _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
553       return;
554    }
555    if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
556       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
557       return;
558    }
559    if (interp <= GL_TEXTURE7_ARB) {
560       GLuint tmp = interp - GL_TEXTURE0_ARB;
561       if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
562 	   (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
563 	 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
564 	 return;
565       } else {
566 	 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
567       }
568    }
569 
570    curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
571    new_tex_inst(curProg);
572 
573    /* add the instructions */
574    curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
575 
576    curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
577    curI->src = interp;
578    curI->swizzle = swizzle;
579 
580 #if MESA_DEBUG_ATI_FS
581    _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
582 	       _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
583 	       _mesa_lookup_enum_by_nr(swizzle));
584 #endif
585 }
586 
587 static void
_mesa_FragmentOpXATI(GLint optype,GLuint arg_count,GLenum op,GLuint dst,GLuint dstMask,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod,GLuint arg3,GLuint arg3Rep,GLuint arg3Mod)588 _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
589 		     GLuint dstMask, GLuint dstMod, GLuint arg1,
590 		     GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
591 		     GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
592 		     GLuint arg3Rep, GLuint arg3Mod)
593 {
594    GET_CURRENT_CONTEXT(ctx);
595    struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
596    GLint ci;
597    struct atifs_instruction *curI;
598    GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
599 
600    if (!ctx->ATIFragmentShader.Compiling) {
601       _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
602       return;
603    }
604 
605    if (curProg->cur_pass==0)
606       curProg->cur_pass=1;
607 
608    else if (curProg->cur_pass==2)
609       curProg->cur_pass=3;
610 
611    /* decide whether this is a new instruction or not ... all color instructions are new,
612       and alpha instructions might also be new if there was no preceding color inst */
613    if ((optype == 0) || (curProg->last_optype == optype)) {
614       if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
615 	 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
616 	 return;
617       }
618       /* easier to do that here slight side effect invalid instr will still be inserted as nops */
619       match_pair_inst(curProg, optype);
620       new_arith_inst(curProg);
621    }
622    curProg->last_optype = optype;
623    ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
624 
625    /* add the instructions */
626    curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
627 
628    /* error checking */
629    if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
630       _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
631       return;
632    }
633    if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
634       (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
635       (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
636       (modtemp != GL_EIGHTH_BIT_ATI)) {
637       _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
638       return;
639    }
640    /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
641    if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
642       _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
643       return;
644    }
645    if (optype == 1) {
646       if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
647 	 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
648 	 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
649 	 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
650 	 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
651 	 return;
652       }
653    }
654    if ((op == GL_DOT4_ATI) &&
655       (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
656       (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
657       _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
658    }
659 
660    if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
661       return;
662    }
663    if (arg2) {
664       if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
665 	 return;
666       }
667    }
668    if (arg3) {
669       if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
670 	 return;
671       }
672       if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
673 	  (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
674 	  (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
675 	  (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
676 	 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
677 	 return;
678       }
679    }
680 
681    /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
682 
683    curI->Opcode[optype] = op;
684    curI->SrcReg[optype][0].Index = arg1;
685    curI->SrcReg[optype][0].argRep = arg1Rep;
686    curI->SrcReg[optype][0].argMod = arg1Mod;
687    curI->ArgCount[optype] = arg_count;
688 
689    if (arg2) {
690       curI->SrcReg[optype][1].Index = arg2;
691       curI->SrcReg[optype][1].argRep = arg2Rep;
692       curI->SrcReg[optype][1].argMod = arg2Mod;
693    }
694 
695    if (arg3) {
696       curI->SrcReg[optype][2].Index = arg3;
697       curI->SrcReg[optype][2].argRep = arg3Rep;
698       curI->SrcReg[optype][2].argMod = arg3Mod;
699    }
700 
701    curI->DstReg[optype].Index = dst;
702    curI->DstReg[optype].dstMod = dstMod;
703    curI->DstReg[optype].dstMask = dstMask;
704 
705 #if MESA_DEBUG_ATI_FS
706    debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
707 #endif
708 
709 }
710 
711 void GLAPIENTRY
_mesa_ColorFragmentOp1ATI(GLenum op,GLuint dst,GLuint dstMask,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod)712 _mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
713 			  GLuint dstMod, GLuint arg1, GLuint arg1Rep,
714 			  GLuint arg1Mod)
715 {
716    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
717 			dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
718 }
719 
720 void GLAPIENTRY
_mesa_ColorFragmentOp2ATI(GLenum op,GLuint dst,GLuint dstMask,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod)721 _mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
722 			  GLuint dstMod, GLuint arg1, GLuint arg1Rep,
723 			  GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
724 			  GLuint arg2Mod)
725 {
726    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
727 			dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
728 			arg2Mod, 0, 0, 0);
729 }
730 
731 void GLAPIENTRY
_mesa_ColorFragmentOp3ATI(GLenum op,GLuint dst,GLuint dstMask,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod,GLuint arg3,GLuint arg3Rep,GLuint arg3Mod)732 _mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
733 			  GLuint dstMod, GLuint arg1, GLuint arg1Rep,
734 			  GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
735 			  GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
736 			  GLuint arg3Mod)
737 {
738    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
739 			dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
740 			arg2Mod, arg3, arg3Rep, arg3Mod);
741 }
742 
743 void GLAPIENTRY
_mesa_AlphaFragmentOp1ATI(GLenum op,GLuint dst,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod)744 _mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
745 			  GLuint arg1Rep, GLuint arg1Mod)
746 {
747    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
748 			arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
749 }
750 
751 void GLAPIENTRY
_mesa_AlphaFragmentOp2ATI(GLenum op,GLuint dst,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod)752 _mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
753 			  GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
754 			  GLuint arg2Rep, GLuint arg2Mod)
755 {
756    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
757 			arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
758 			0);
759 }
760 
761 void GLAPIENTRY
_mesa_AlphaFragmentOp3ATI(GLenum op,GLuint dst,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod,GLuint arg3,GLuint arg3Rep,GLuint arg3Mod)762 _mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
763 			  GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
764 			  GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
765 			  GLuint arg3Rep, GLuint arg3Mod)
766 {
767    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
768 			arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
769 			arg3Rep, arg3Mod);
770 }
771 
772 void GLAPIENTRY
_mesa_SetFragmentShaderConstantATI(GLuint dst,const GLfloat * value)773 _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
774 {
775    GLuint dstindex;
776    GET_CURRENT_CONTEXT(ctx);
777 
778    if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
779       /* spec says nothing about what should happen here but we can't just segfault...*/
780       _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
781       return;
782    }
783 
784    dstindex = dst - GL_CON_0_ATI;
785    if (ctx->ATIFragmentShader.Compiling) {
786       struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
787       COPY_4V(curProg->Constants[dstindex], value);
788       curProg->LocalConstDef |= 1 << dstindex;
789    }
790    else {
791       FLUSH_VERTICES(ctx, _NEW_PROGRAM);
792       COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
793    }
794 }
795 
796 #endif /* FEATURE_ATI_fragment_shader */
797