blob: d349a496dc718fc651fe45f4a3d23616bff860ea [file] [log] [blame]
Dave Airlie7f752fe2004-12-19 03:06:59 +00001/**
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 "glheader.h"
25#include "context.h"
26#include "hash.h"
27#include "imports.h"
28#include "macros.h"
29#include "enums.h"
30#include "mtypes.h"
31#include "atifragshader.h"
32
33#define MESA_DEBUG_ATI_FS 0
34
Brian Paul63d68302005-11-19 16:43:04 +000035static struct ati_fragment_shader DummyShader;
36
37
38/**
39 * Allocate and initialize a new ATI fragment shader object.
40 */
41struct ati_fragment_shader *
42_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id)
43{
44 struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
45 (void) ctx;
46 if (s) {
47 s->Id = id;
48 s->RefCount = 1;
49 }
50 return s;
51}
52
53
54/**
55 * Delete the given ati fragment shader
56 */
57void
58_mesa_delete_ati_fragment_shader(GLcontext *ctx, struct ati_fragment_shader *s)
59{
60 GLuint i;
61 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
62 if (s->Instructions[i])
63 _mesa_free(s->Instructions[i]);
64 if (s->SetupInst[i])
65 _mesa_free(s->SetupInst[i]);
66 }
67 _mesa_free(s);
68}
69
70
Dave Airlie7f752fe2004-12-19 03:06:59 +000071
72static void
Roland Scheideggerf519a772005-09-02 01:11:53 +000073new_arith_inst(struct ati_fragment_shader *prog)
Dave Airlie7f752fe2004-12-19 03:06:59 +000074{
Roland Scheideggerf519a772005-09-02 01:11:53 +000075/* set "default" instruction as not all may get defined.
76 there is no specified way to express a nop with ati fragment shaders we use
77 GL_NONE as the op enum and just set some params to 0 - so nothing to do here */
78 prog->numArithInstr[prog->cur_pass >> 1]++;
79}
80
81static void
82new_tex_inst(struct ati_fragment_shader *prog)
83{
84}
85
86static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
87{
88 if (optype == curProg->last_optype) {
89 curProg->last_optype = 1;
90 }
Dave Airlie7f752fe2004-12-19 03:06:59 +000091}
92
93#if MESA_DEBUG_ATI_FS
94static char *
95create_dst_mod_str(GLuint mod)
96{
97 static char ret_str[1024];
98
99 _mesa_memset(ret_str, 0, 1024);
100 if (mod & GL_2X_BIT_ATI)
101 _mesa_strncat(ret_str, "|2X", 1024);
102
103 if (mod & GL_4X_BIT_ATI)
104 _mesa_strncat(ret_str, "|4X", 1024);
105
106 if (mod & GL_8X_BIT_ATI)
107 _mesa_strncat(ret_str, "|8X", 1024);
108 if (mod & GL_HALF_BIT_ATI)
109 _mesa_strncat(ret_str, "|HA", 1024);
110 if (mod & GL_QUARTER_BIT_ATI)
111 _mesa_strncat(ret_str, "|QU", 1024);
112 if (mod & GL_EIGHTH_BIT_ATI)
113 _mesa_strncat(ret_str, "|EI", 1024);
114
115 if (mod & GL_SATURATE_BIT_ATI)
116 _mesa_strncat(ret_str, "|SAT", 1024);
117
118 if (_mesa_strlen(ret_str) == 0)
119 _mesa_strncat(ret_str, "NONE", 1024);
120 return ret_str;
121}
122
123static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
124 "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
125
126static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
127 GLuint dstMask, GLuint dstMod, GLuint arg1,
128 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
129 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
130 GLuint arg3Rep, GLuint arg3Mod)
131{
132 char *op_name;
133
134 op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
135
136 fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op),
137 _mesa_lookup_enum_by_nr(dst));
138 if (!optype)
139 fprintf(stderr, ", %d", dstMask);
140
141 fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
142
143 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1),
144 _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod);
145 if (arg_count>1)
146 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2),
147 _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod);
148 if (arg_count>2)
149 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3),
150 _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod);
151
152 fprintf(stderr,")\n");
153
154}
155#endif
156
Roland Scheideggerf519a772005-09-02 01:11:53 +0000157static int check_arith_arg(struct ati_fragment_shader *curProg,
158 GLuint optype, GLuint arg, GLuint argRep)
159{
160 GET_CURRENT_CONTEXT(ctx);
161
162 if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) &&
163 ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) &&
164 (arg != GL_ZERO) && (arg != GL_ONE) &&
165 (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) {
166 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)");
167 return 0;
168 }
169 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
170 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
171 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
172 return 0;
173 }
174 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
175 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
176 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
177 return 0;
178 }
179 if ((curProg->cur_pass == 1) &&
180 ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
181 curProg->interpinp1 = GL_TRUE;
182 }
183 return 1;
184}
185
Dave Airlie7f752fe2004-12-19 03:06:59 +0000186GLuint GLAPIENTRY
187_mesa_GenFragmentShadersATI(GLuint range)
188{
189 GLuint first;
190 GLuint i;
191 GET_CURRENT_CONTEXT(ctx);
192
Roland Scheideggerf519a772005-09-02 01:11:53 +0000193 if (range == 0) {
194 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)");
195 return 0;
196 }
197
198 if (ctx->ATIFragmentShader.Compiling) {
199 _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)");
200 return 0;
201 }
202
Brian Paul63d68302005-11-19 16:43:04 +0000203 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000204 for (i = 0; i < range; i++) {
Brian Paul63d68302005-11-19 16:43:04 +0000205 _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000206 }
207
208 return first;
209}
210
211void GLAPIENTRY
212_mesa_BindFragmentShaderATI(GLuint id)
213{
Dave Airlie7f752fe2004-12-19 03:06:59 +0000214 GET_CURRENT_CONTEXT(ctx);
215 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Brian Paul63d68302005-11-19 16:43:04 +0000216 struct ati_fragment_shader *newProg;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000217
Roland Scheideggerf519a772005-09-02 01:11:53 +0000218 if (ctx->ATIFragmentShader.Compiling) {
219 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
220 return;
221 }
222
Dave Airlie7f752fe2004-12-19 03:06:59 +0000223 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
224
Brian Paul63d68302005-11-19 16:43:04 +0000225 if (curProg->Id == id) {
Dave Airlie7f752fe2004-12-19 03:06:59 +0000226 return;
227 }
228
Brian Paul63d68302005-11-19 16:43:04 +0000229 /* unbind current */
230 if (curProg->Id != 0) {
231 curProg->RefCount--;
232 if (curProg->RefCount <= 0) {
233 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000234 }
235 }
236
Brian Paul63d68302005-11-19 16:43:04 +0000237 /* find new shader */
Dave Airlie7f752fe2004-12-19 03:06:59 +0000238 if (id == 0) {
Brian Paul63d68302005-11-19 16:43:04 +0000239 newProg = ctx->Shared->DefaultFragmentShader;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000240 }
241 else {
Brian Paul63d68302005-11-19 16:43:04 +0000242 newProg = (struct ati_fragment_shader *)
243 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
244 if (!newProg || newProg == &DummyShader) {
Dave Airlie7f752fe2004-12-19 03:06:59 +0000245 /* allocate a new program now */
Brian Paul63d68302005-11-19 16:43:04 +0000246 newProg = _mesa_new_ati_fragment_shader(ctx, id);
247 if (!newProg) {
Dave Airlie7f752fe2004-12-19 03:06:59 +0000248 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
249 return;
250 }
Brian Paul63d68302005-11-19 16:43:04 +0000251 _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000252 }
253
254 }
255
256 /* do actual bind */
Brian Paul63d68302005-11-19 16:43:04 +0000257 ctx->ATIFragmentShader.Current = newProg;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000258
259 ASSERT(ctx->ATIFragmentShader.Current);
Brian Paul63d68302005-11-19 16:43:04 +0000260 if (newProg)
261 newProg->RefCount++;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000262
263 /*if (ctx->Driver.BindProgram)
264 ctx->Driver.BindProgram(ctx, target, prog); */
265}
266
267void GLAPIENTRY
268_mesa_DeleteFragmentShaderATI(GLuint id)
269{
270 GET_CURRENT_CONTEXT(ctx);
271
Roland Scheideggerf519a772005-09-02 01:11:53 +0000272 if (ctx->ATIFragmentShader.Compiling) {
273 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
274 return;
275 }
276
Dave Airlie7f752fe2004-12-19 03:06:59 +0000277 if (id != 0) {
Brian Paul63d68302005-11-19 16:43:04 +0000278 struct ati_fragment_shader *prog = (struct ati_fragment_shader *)
279 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
280 if (prog == &DummyShader) {
281 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000282 }
283 else if (prog) {
284 if (ctx->ATIFragmentShader.Current &&
Brian Paul63d68302005-11-19 16:43:04 +0000285 ctx->ATIFragmentShader.Current->Id == id) {
Roland Scheideggerce335072005-09-08 00:12:57 +0000286 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000287 _mesa_BindFragmentShaderATI(0);
288 }
289 }
Brian Paul63d68302005-11-19 16:43:04 +0000290
Brian Paulea2943e2005-01-20 04:02:02 +0000291 /* The ID is immediately available for re-use now */
Brian Paul63d68302005-11-19 16:43:04 +0000292 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
Brian Paulea2943e2005-01-20 04:02:02 +0000293 prog->RefCount--;
294 if (prog->RefCount <= 0) {
Brian Paul63d68302005-11-19 16:43:04 +0000295 _mesa_free(prog);
Brian Paulea2943e2005-01-20 04:02:02 +0000296 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000297 }
298}
299
Brian Paul63d68302005-11-19 16:43:04 +0000300
Dave Airlie7f752fe2004-12-19 03:06:59 +0000301void GLAPIENTRY
302_mesa_BeginFragmentShaderATI(void)
303{
Roland Scheideggerf519a772005-09-02 01:11:53 +0000304 GLint i;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000305 GET_CURRENT_CONTEXT(ctx);
306
Roland Scheideggerf519a772005-09-02 01:11:53 +0000307 if (ctx->ATIFragmentShader.Compiling) {
308 _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
309 return;
310 }
311
Roland Scheideggerce335072005-09-08 00:12:57 +0000312 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
313
Roland Scheideggerf519a772005-09-02 01:11:53 +0000314 /* if the shader was already defined free instructions and get new ones
315 (or, could use the same mem but would need to reinitialize) */
316 /* no idea if it's allowed to redefine a shader */
317 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
318 if (ctx->ATIFragmentShader.Current->Instructions[i])
319 _mesa_free(ctx->ATIFragmentShader.Current->Instructions[i]);
320 if (ctx->ATIFragmentShader.Current->SetupInst[i])
321 _mesa_free(ctx->ATIFragmentShader.Current->SetupInst[i]);
322 }
323
Dave Airlie7f752fe2004-12-19 03:06:59 +0000324 /* malloc the instructions here - not sure if the best place but its
325 a start */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000326 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
327 ctx->ATIFragmentShader.Current->Instructions[i] =
328 (struct atifs_instruction *)
329 _mesa_calloc(sizeof(struct atifs_instruction) *
330 (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
331 ctx->ATIFragmentShader.Current->SetupInst[i] =
332 (struct atifs_setupinst *)
333 _mesa_calloc(sizeof(struct atifs_setupinst) *
334 (MAX_NUM_FRAGMENT_REGISTERS_ATI));
335 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000336
Roland Scheideggerf519a772005-09-02 01:11:53 +0000337/* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
Brian Paul63d68302005-11-19 16:43:04 +0000338 ctx->ATIFragmentShader.Current->LocalConstDef = 0;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000339 ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
340 ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
341 ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
342 ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
343 ctx->ATIFragmentShader.Current->NumPasses = 0;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000344 ctx->ATIFragmentShader.Current->cur_pass = 0;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000345 ctx->ATIFragmentShader.Current->last_optype = 0;
346 ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
347 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
348 ctx->ATIFragmentShader.Current->swizzlerq = 0;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000349 ctx->ATIFragmentShader.Compiling = 1;
350}
351
352void GLAPIENTRY
353_mesa_EndFragmentShaderATI(void)
354{
355 GET_CURRENT_CONTEXT(ctx);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000356 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000357#if MESA_DEBUG_ATI_FS
358 GLint i, j;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000359#endif
360
Roland Scheideggerf519a772005-09-02 01:11:53 +0000361 if (!ctx->ATIFragmentShader.Compiling) {
362 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
363 return;
364 }
365 if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
366 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
367 /* according to spec, DON'T return here */
368 }
369
370 match_pair_inst(curProg, 0);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000371 ctx->ATIFragmentShader.Compiling = 0;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000372 ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
373 if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
374 (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
375 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
376 }
377 if (ctx->ATIFragmentShader.Current->cur_pass > 1)
378 ctx->ATIFragmentShader.Current->NumPasses = 2;
379 else ctx->ATIFragmentShader.Current->NumPasses = 1;
Dave Airlie3aa69b32005-01-30 06:24:30 +0000380 ctx->ATIFragmentShader.Current->cur_pass=0;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000381#if MESA_DEBUG_ATI_FS
Roland Scheideggerf519a772005-09-02 01:11:53 +0000382 for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
383 for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
384 GLuint op = curProg->SetupInst[j][i].Opcode;
385 const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0";
386 GLuint src = curProg->SetupInst[j][i].src;
387 GLuint swizzle = curProg->SetupInst[j][i].swizzle;
388 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
389 swizzle);
390 }
391 for (i = 0; i < curProg->numArithInstr[j]; i++) {
392 GLuint op0 = curProg->Instructions[j][i].Opcode[0];
393 GLuint op1 = curProg->Instructions[j][i].Opcode[1];
394 const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0";
395 const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0";
396 GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
397 GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
398 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
Dave Airlie7f752fe2004-12-19 03:06:59 +0000399 op1, op1_enum, count1);
Roland Scheideggerf519a772005-09-02 01:11:53 +0000400 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000401 }
402#endif
403}
404
405void GLAPIENTRY
406_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
407{
408 GET_CURRENT_CONTEXT(ctx);
409 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000410 struct atifs_setupinst *curI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000411
Roland Scheideggerf519a772005-09-02 01:11:53 +0000412 if (!ctx->ATIFragmentShader.Compiling) {
413 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
414 return;
415 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000416
Roland Scheideggerf519a772005-09-02 01:11:53 +0000417 if (curProg->cur_pass == 1) {
418 match_pair_inst(curProg, 0);
419 curProg->cur_pass = 2;
420 }
421 if ((curProg->cur_pass > 2) ||
422 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
423 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
424 return;
425 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000426 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
427 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000428 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
429 return;
430 }
431 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000432 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
433 ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000434 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
435 return;
436 }
437 if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
438 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
439 return;
440 }
441 if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
442 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
443 return;
444 }
445 if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
446 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
447 return;
448 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000449 if (coord <= GL_TEXTURE7_ARB) {
450 GLuint tmp = coord - GL_TEXTURE0_ARB;
451 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
452 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000453 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
454 return;
455 } else {
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000456 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
Roland Scheideggerf519a772005-09-02 01:11:53 +0000457 }
458 }
459
460 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
461 new_tex_inst(curProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000462
463 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000464 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
Dave Airlie7f752fe2004-12-19 03:06:59 +0000465
Roland Scheideggerf519a772005-09-02 01:11:53 +0000466 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
467 curI->src = coord;
468 curI->swizzle = swizzle;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000469
470#if MESA_DEBUG_ATI_FS
471 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
472 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
473 _mesa_lookup_enum_by_nr(swizzle));
474#endif
475}
476
477void GLAPIENTRY
478_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
479{
480 GET_CURRENT_CONTEXT(ctx);
481 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000482 struct atifs_setupinst *curI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000483
Roland Scheideggerf519a772005-09-02 01:11:53 +0000484 if (!ctx->ATIFragmentShader.Compiling) {
485 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
486 return;
487 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000488
Roland Scheideggerf519a772005-09-02 01:11:53 +0000489 if (curProg->cur_pass == 1) {
490 match_pair_inst(curProg, 0);
491 curProg->cur_pass = 2;
492 }
493 if ((curProg->cur_pass > 2) ||
494 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
495 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
496 return;
497 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000498 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
499 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000500 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
501 return;
502 }
503 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000504 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
505 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000506 /* is this texture5 or texture7? spec is a bit unclear there */
507 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
508 return;
509 }
510 if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
511 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
512 return;
513 }
514 if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
515 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
516 return;
517 }
518 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
519 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
520 return;
521 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000522 if (interp <= GL_TEXTURE7_ARB) {
523 GLuint tmp = interp - GL_TEXTURE0_ARB;
524 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
525 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000526 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
527 return;
528 } else {
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000529 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
Roland Scheideggerf519a772005-09-02 01:11:53 +0000530 }
531 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000532
Roland Scheideggerf519a772005-09-02 01:11:53 +0000533 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
534 new_tex_inst(curProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000535
Dave Airlie7f752fe2004-12-19 03:06:59 +0000536 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000537 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
Dave Airlie7f752fe2004-12-19 03:06:59 +0000538
Roland Scheideggerf519a772005-09-02 01:11:53 +0000539 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
540 curI->src = interp;
541 curI->swizzle = swizzle;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000542
543#if MESA_DEBUG_ATI_FS
544 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
545 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
546 _mesa_lookup_enum_by_nr(swizzle));
547#endif
548}
549
550static void
551_mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
552 GLuint dstMask, GLuint dstMod, GLuint arg1,
553 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
554 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
555 GLuint arg3Rep, GLuint arg3Mod)
556{
557 GET_CURRENT_CONTEXT(ctx);
558 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
559 GLint ci;
560 struct atifs_instruction *curI;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000561 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000562
Roland Scheideggerf519a772005-09-02 01:11:53 +0000563 if (!ctx->ATIFragmentShader.Compiling) {
564 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
565 return;
566 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000567
Roland Scheideggerf519a772005-09-02 01:11:53 +0000568 if (curProg->cur_pass==0)
569 curProg->cur_pass=1;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000570
Roland Scheideggerf519a772005-09-02 01:11:53 +0000571 else if (curProg->cur_pass==2)
572 curProg->cur_pass=3;
573
574 /* decide whether this is a new instruction or not ... all color instructions are new,
575 and alpha instructions might also be new if there was no preceding color inst */
576 if ((optype == 0) || (curProg->last_optype == optype)) {
577 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
578 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
579 return;
580 }
581 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
582 match_pair_inst(curProg, optype);
583 new_arith_inst(curProg);
584 }
585 curProg->last_optype = optype;
586 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000587
588 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000589 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
590
591 /* error checking */
592 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
593 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
594 return;
595 }
596 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
597 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
598 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
599 (modtemp != GL_EIGHTH_BIT_ATI)) {
600 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
601 return;
602 }
603 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
604 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
605 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
606 return;
607 }
608 if (optype == 1) {
609 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
610 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
611 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
612 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
613 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
614 return;
615 }
616 }
617 if ((op == GL_DOT4_ATI) &&
618 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
619 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
620 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
621 }
622
623 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
624 return;
625 }
626 if (arg2) {
627 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
628 return;
629 }
630 }
631 if (arg3) {
632 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
633 return;
634 }
635 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
636 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
637 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
638 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
639 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
640 return;
641 }
642 }
643
644 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
Dave Airlie7f752fe2004-12-19 03:06:59 +0000645
646 curI->Opcode[optype] = op;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000647 curI->SrcReg[optype][0].Index = arg1;
648 curI->SrcReg[optype][0].argRep = arg1Rep;
649 curI->SrcReg[optype][0].argMod = arg1Mod;
650 curI->ArgCount[optype] = arg_count;
651
652 if (arg2) {
653 curI->SrcReg[optype][1].Index = arg2;
654 curI->SrcReg[optype][1].argRep = arg2Rep;
655 curI->SrcReg[optype][1].argMod = arg2Mod;
656 }
657
658 if (arg3) {
659 curI->SrcReg[optype][2].Index = arg3;
660 curI->SrcReg[optype][2].argRep = arg3Rep;
661 curI->SrcReg[optype][2].argMod = arg3Mod;
662 }
663
664 curI->DstReg[optype].Index = dst;
665 curI->DstReg[optype].dstMod = dstMod;
666 curI->DstReg[optype].dstMask = dstMask;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000667
Dave Airlie7f752fe2004-12-19 03:06:59 +0000668#if MESA_DEBUG_ATI_FS
669 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
670#endif
671
672}
673
674void GLAPIENTRY
675_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
676 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
677 GLuint arg1Mod)
678{
679 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
680 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
681}
682
683void GLAPIENTRY
684_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
685 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
686 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
687 GLuint arg2Mod)
688{
689 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
690 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
691 arg2Mod, 0, 0, 0);
692}
693
694void GLAPIENTRY
695_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
696 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
697 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
698 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
699 GLuint arg3Mod)
700{
701 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
702 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
703 arg2Mod, arg3, arg3Rep, arg3Mod);
704}
705
706void GLAPIENTRY
707_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
708 GLuint arg1Rep, GLuint arg1Mod)
709{
710 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
711 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
712}
713
714void GLAPIENTRY
715_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
716 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
717 GLuint arg2Rep, GLuint arg2Mod)
718{
719 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
720 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
721 0);
722}
723
724void GLAPIENTRY
725_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
726 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
727 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
728 GLuint arg3Rep, GLuint arg3Mod)
729{
730 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
731 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
732 arg3Rep, arg3Mod);
733}
734
735void GLAPIENTRY
736_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
737{
Karl Schultze81cbd82005-09-05 13:45:23 +0000738 GLuint dstindex;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000739 GET_CURRENT_CONTEXT(ctx);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000740
Roland Scheideggerf519a772005-09-02 01:11:53 +0000741 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
742 /* spec says nothing about what should happen here but we can't just segfault...*/
743 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
744 return;
745 }
746
Karl Schultze81cbd82005-09-05 13:45:23 +0000747 dstindex = dst - GL_CON_0_ATI;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000748 if (ctx->ATIFragmentShader.Compiling) {
749 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
750 COPY_4V(curProg->Constants[dstindex], value);
Brian Paul63d68302005-11-19 16:43:04 +0000751 curProg->LocalConstDef |= 1 << dstindex;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000752 }
753 else {
Roland Scheideggerce335072005-09-08 00:12:57 +0000754 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian Paul63d68302005-11-19 16:43:04 +0000755 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
Roland Scheideggerf519a772005-09-02 01:11:53 +0000756 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000757}