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