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