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