blob: e16c029aa555ff3b10248859027ee2d1573ae6ac [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
35extern struct program _mesa_DummyProgram;
36
37static void
Roland Scheideggerf519a772005-09-02 01:11:53 +000038new_arith_inst(struct ati_fragment_shader *prog)
Dave Airlie7f752fe2004-12-19 03:06:59 +000039{
Roland Scheideggerf519a772005-09-02 01:11:53 +000040/* set "default" instruction as not all may get defined.
41 there is no specified way to express a nop with ati fragment shaders we use
42 GL_NONE as the op enum and just set some params to 0 - so nothing to do here */
43 prog->numArithInstr[prog->cur_pass >> 1]++;
44}
45
46static void
47new_tex_inst(struct ati_fragment_shader *prog)
48{
49}
50
51static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
52{
53 if (optype == curProg->last_optype) {
54 curProg->last_optype = 1;
55 }
Dave Airlie7f752fe2004-12-19 03:06:59 +000056}
57
58#if MESA_DEBUG_ATI_FS
59static char *
60create_dst_mod_str(GLuint mod)
61{
62 static char ret_str[1024];
63
64 _mesa_memset(ret_str, 0, 1024);
65 if (mod & GL_2X_BIT_ATI)
66 _mesa_strncat(ret_str, "|2X", 1024);
67
68 if (mod & GL_4X_BIT_ATI)
69 _mesa_strncat(ret_str, "|4X", 1024);
70
71 if (mod & GL_8X_BIT_ATI)
72 _mesa_strncat(ret_str, "|8X", 1024);
73 if (mod & GL_HALF_BIT_ATI)
74 _mesa_strncat(ret_str, "|HA", 1024);
75 if (mod & GL_QUARTER_BIT_ATI)
76 _mesa_strncat(ret_str, "|QU", 1024);
77 if (mod & GL_EIGHTH_BIT_ATI)
78 _mesa_strncat(ret_str, "|EI", 1024);
79
80 if (mod & GL_SATURATE_BIT_ATI)
81 _mesa_strncat(ret_str, "|SAT", 1024);
82
83 if (_mesa_strlen(ret_str) == 0)
84 _mesa_strncat(ret_str, "NONE", 1024);
85 return ret_str;
86}
87
88static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
89 "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
90
91static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
92 GLuint dstMask, GLuint dstMod, GLuint arg1,
93 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
94 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
95 GLuint arg3Rep, GLuint arg3Mod)
96{
97 char *op_name;
98
99 op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
100
101 fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op),
102 _mesa_lookup_enum_by_nr(dst));
103 if (!optype)
104 fprintf(stderr, ", %d", dstMask);
105
106 fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
107
108 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1),
109 _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod);
110 if (arg_count>1)
111 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2),
112 _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod);
113 if (arg_count>2)
114 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3),
115 _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod);
116
117 fprintf(stderr,")\n");
118
119}
120#endif
121
Roland Scheideggerf519a772005-09-02 01:11:53 +0000122static int check_arith_arg(struct ati_fragment_shader *curProg,
123 GLuint optype, GLuint arg, GLuint argRep)
124{
125 GET_CURRENT_CONTEXT(ctx);
126
127 if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) &&
128 ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) &&
129 (arg != GL_ZERO) && (arg != GL_ONE) &&
130 (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) {
131 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)");
132 return 0;
133 }
134 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
135 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
136 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
137 return 0;
138 }
139 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
140 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
141 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
142 return 0;
143 }
144 if ((curProg->cur_pass == 1) &&
145 ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
146 curProg->interpinp1 = GL_TRUE;
147 }
148 return 1;
149}
150
Dave Airlie7f752fe2004-12-19 03:06:59 +0000151GLuint GLAPIENTRY
152_mesa_GenFragmentShadersATI(GLuint range)
153{
154 GLuint first;
155 GLuint i;
156 GET_CURRENT_CONTEXT(ctx);
157
Roland Scheideggerf519a772005-09-02 01:11:53 +0000158 if (range == 0) {
159 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)");
160 return 0;
161 }
162
163 if (ctx->ATIFragmentShader.Compiling) {
164 _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)");
165 return 0;
166 }
167
Dave Airlie7f752fe2004-12-19 03:06:59 +0000168 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, range);
169 for (i = 0; i < range; i++) {
170 _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
171 }
172
173 return first;
174}
175
176void GLAPIENTRY
177_mesa_BindFragmentShaderATI(GLuint id)
178{
179 struct program *prog;
180 GET_CURRENT_CONTEXT(ctx);
181 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
182
Roland Scheideggerf519a772005-09-02 01:11:53 +0000183 if (ctx->ATIFragmentShader.Compiling) {
184 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
185 return;
186 }
187
Dave Airlie7f752fe2004-12-19 03:06:59 +0000188 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
189
190 if (curProg->Base.Id == id) {
191 return;
192 }
193
194 if (curProg->Base.Id != 0) {
195 curProg->Base.RefCount--;
196 if (curProg->Base.RefCount <= 0) {
197 _mesa_HashRemove(ctx->Shared->Programs, id);
198 }
199 }
200
201 /* Go bind */
202 if (id == 0) {
203 prog = ctx->Shared->DefaultFragmentShader;
204 }
205 else {
206 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
207 if (!prog || prog == &_mesa_DummyProgram) {
208 /* allocate a new program now */
209 prog = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_SHADER_ATI, id);
210 if (!prog) {
211 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
212 return;
213 }
214 _mesa_HashInsert(ctx->Shared->Programs, id, prog);
215 }
216
217 }
218
219 /* do actual bind */
220 ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) prog;
221
222 ASSERT(ctx->ATIFragmentShader.Current);
223 if (prog)
224 prog->RefCount++;
225
226 /*if (ctx->Driver.BindProgram)
227 ctx->Driver.BindProgram(ctx, target, prog); */
228}
229
230void GLAPIENTRY
231_mesa_DeleteFragmentShaderATI(GLuint id)
232{
233 GET_CURRENT_CONTEXT(ctx);
234
Roland Scheideggerf519a772005-09-02 01:11:53 +0000235 if (ctx->ATIFragmentShader.Compiling) {
236 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
237 return;
238 }
239
Dave Airlie7f752fe2004-12-19 03:06:59 +0000240 if (id != 0) {
241 struct program *prog = (struct program *)
242 _mesa_HashLookup(ctx->Shared->Programs, id);
243 if (prog == &_mesa_DummyProgram) {
244 _mesa_HashRemove(ctx->Shared->Programs, id);
245 }
246 else if (prog) {
247 if (ctx->ATIFragmentShader.Current &&
248 ctx->ATIFragmentShader.Current->Base.Id == id) {
Roland Scheideggerce335072005-09-08 00:12:57 +0000249 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000250 _mesa_BindFragmentShaderATI(0);
251 }
252 }
Brian Paulea2943e2005-01-20 04:02:02 +0000253#if 0
Dave Airlie7f752fe2004-12-19 03:06:59 +0000254 if (!prog->DeletePending) {
255 prog->DeletePending = GL_TRUE;
256 prog->RefCount--;
257 }
258 if (prog->RefCount <= 0) {
259 _mesa_HashRemove(ctx->Shared->Programs, id);
260 ctx->Driver.DeleteProgram(ctx, prog);
261 }
Brian Paulea2943e2005-01-20 04:02:02 +0000262#else
263 /* The ID is immediately available for re-use now */
264 _mesa_HashRemove(ctx->Shared->Programs, id);
265 prog->RefCount--;
266 if (prog->RefCount <= 0) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000267 ctx->Driver.DeleteProgram(ctx, prog);
Brian Paulea2943e2005-01-20 04:02:02 +0000268 }
269#endif
Dave Airlie7f752fe2004-12-19 03:06:59 +0000270 }
271}
272
273void GLAPIENTRY
274_mesa_BeginFragmentShaderATI(void)
275{
Roland Scheideggerf519a772005-09-02 01:11:53 +0000276 GLint i;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000277 GET_CURRENT_CONTEXT(ctx);
278
Roland Scheideggerf519a772005-09-02 01:11:53 +0000279 if (ctx->ATIFragmentShader.Compiling) {
280 _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
281 return;
282 }
283
Roland Scheideggerce335072005-09-08 00:12:57 +0000284 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
285
Roland Scheideggerf519a772005-09-02 01:11:53 +0000286 /* if the shader was already defined free instructions and get new ones
287 (or, could use the same mem but would need to reinitialize) */
288 /* no idea if it's allowed to redefine a shader */
289 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
290 if (ctx->ATIFragmentShader.Current->Instructions[i])
291 _mesa_free(ctx->ATIFragmentShader.Current->Instructions[i]);
292 if (ctx->ATIFragmentShader.Current->SetupInst[i])
293 _mesa_free(ctx->ATIFragmentShader.Current->SetupInst[i]);
294 }
295
Dave Airlie7f752fe2004-12-19 03:06:59 +0000296 /* malloc the instructions here - not sure if the best place but its
297 a start */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000298 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
299 ctx->ATIFragmentShader.Current->Instructions[i] =
300 (struct atifs_instruction *)
301 _mesa_calloc(sizeof(struct atifs_instruction) *
302 (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
303 ctx->ATIFragmentShader.Current->SetupInst[i] =
304 (struct atifs_setupinst *)
305 _mesa_calloc(sizeof(struct atifs_setupinst) *
306 (MAX_NUM_FRAGMENT_REGISTERS_ATI));
307 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000308
Roland Scheideggerf519a772005-09-02 01:11:53 +0000309/* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
310 ctx->ATIFragmentShader.Current->localConstDef = 0;
311 ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
312 ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
313 ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
314 ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
315 ctx->ATIFragmentShader.Current->NumPasses = 0;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000316 ctx->ATIFragmentShader.Current->cur_pass = 0;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000317 ctx->ATIFragmentShader.Current->last_optype = 0;
318 ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
319 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
320 ctx->ATIFragmentShader.Current->swizzlerq = 0;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000321 ctx->ATIFragmentShader.Compiling = 1;
322}
323
324void GLAPIENTRY
325_mesa_EndFragmentShaderATI(void)
326{
327 GET_CURRENT_CONTEXT(ctx);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000328 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000329#if MESA_DEBUG_ATI_FS
330 GLint i, j;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000331#endif
332
Roland Scheideggerf519a772005-09-02 01:11:53 +0000333 if (!ctx->ATIFragmentShader.Compiling) {
334 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
335 return;
336 }
337 if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
338 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
339 /* according to spec, DON'T return here */
340 }
341
342 match_pair_inst(curProg, 0);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000343 ctx->ATIFragmentShader.Compiling = 0;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000344 ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
345 if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
346 (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
347 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
348 }
349 if (ctx->ATIFragmentShader.Current->cur_pass > 1)
350 ctx->ATIFragmentShader.Current->NumPasses = 2;
351 else ctx->ATIFragmentShader.Current->NumPasses = 1;
Dave Airlie3aa69b32005-01-30 06:24:30 +0000352 ctx->ATIFragmentShader.Current->cur_pass=0;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000353#if MESA_DEBUG_ATI_FS
Roland Scheideggerf519a772005-09-02 01:11:53 +0000354 for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
355 for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
356 GLuint op = curProg->SetupInst[j][i].Opcode;
357 const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0";
358 GLuint src = curProg->SetupInst[j][i].src;
359 GLuint swizzle = curProg->SetupInst[j][i].swizzle;
360 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
361 swizzle);
362 }
363 for (i = 0; i < curProg->numArithInstr[j]; i++) {
364 GLuint op0 = curProg->Instructions[j][i].Opcode[0];
365 GLuint op1 = curProg->Instructions[j][i].Opcode[1];
366 const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0";
367 const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0";
368 GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
369 GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
370 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
Dave Airlie7f752fe2004-12-19 03:06:59 +0000371 op1, op1_enum, count1);
Roland Scheideggerf519a772005-09-02 01:11:53 +0000372 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000373 }
374#endif
375}
376
377void GLAPIENTRY
378_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
379{
380 GET_CURRENT_CONTEXT(ctx);
381 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000382 struct atifs_setupinst *curI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000383
Roland Scheideggerf519a772005-09-02 01:11:53 +0000384 if (!ctx->ATIFragmentShader.Compiling) {
385 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
386 return;
387 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000388
Roland Scheideggerf519a772005-09-02 01:11:53 +0000389 if (curProg->cur_pass == 1) {
390 match_pair_inst(curProg, 0);
391 curProg->cur_pass = 2;
392 }
393 if ((curProg->cur_pass > 2) ||
394 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
395 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
396 return;
397 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000398 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
399 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000400 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
401 return;
402 }
403 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000404 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
405 ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000406 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
407 return;
408 }
409 if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
410 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
411 return;
412 }
413 if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
414 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
415 return;
416 }
417 if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
418 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
419 return;
420 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000421 if (coord <= GL_TEXTURE7_ARB) {
422 GLuint tmp = coord - GL_TEXTURE0_ARB;
423 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
424 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000425 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
426 return;
427 } else {
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000428 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
Roland Scheideggerf519a772005-09-02 01:11:53 +0000429 }
430 }
431
432 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
433 new_tex_inst(curProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000434
435 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000436 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
Dave Airlie7f752fe2004-12-19 03:06:59 +0000437
Roland Scheideggerf519a772005-09-02 01:11:53 +0000438 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
439 curI->src = coord;
440 curI->swizzle = swizzle;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000441
442#if MESA_DEBUG_ATI_FS
443 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
444 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
445 _mesa_lookup_enum_by_nr(swizzle));
446#endif
447}
448
449void GLAPIENTRY
450_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
451{
452 GET_CURRENT_CONTEXT(ctx);
453 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000454 struct atifs_setupinst *curI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000455
Roland Scheideggerf519a772005-09-02 01:11:53 +0000456 if (!ctx->ATIFragmentShader.Compiling) {
457 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
458 return;
459 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000460
Roland Scheideggerf519a772005-09-02 01:11:53 +0000461 if (curProg->cur_pass == 1) {
462 match_pair_inst(curProg, 0);
463 curProg->cur_pass = 2;
464 }
465 if ((curProg->cur_pass > 2) ||
466 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
467 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
468 return;
469 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000470 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
471 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000472 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
473 return;
474 }
475 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000476 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
477 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000478 /* is this texture5 or texture7? spec is a bit unclear there */
479 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
480 return;
481 }
482 if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
483 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
484 return;
485 }
486 if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
487 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
488 return;
489 }
490 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
491 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
492 return;
493 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000494 if (interp <= GL_TEXTURE7_ARB) {
495 GLuint tmp = interp - GL_TEXTURE0_ARB;
496 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
497 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000498 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
499 return;
500 } else {
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000501 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
Roland Scheideggerf519a772005-09-02 01:11:53 +0000502 }
503 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000504
Roland Scheideggerf519a772005-09-02 01:11:53 +0000505 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
506 new_tex_inst(curProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000507
Dave Airlie7f752fe2004-12-19 03:06:59 +0000508 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000509 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
Dave Airlie7f752fe2004-12-19 03:06:59 +0000510
Roland Scheideggerf519a772005-09-02 01:11:53 +0000511 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
512 curI->src = interp;
513 curI->swizzle = swizzle;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000514
515#if MESA_DEBUG_ATI_FS
516 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
517 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
518 _mesa_lookup_enum_by_nr(swizzle));
519#endif
520}
521
522static void
523_mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
524 GLuint dstMask, GLuint dstMod, GLuint arg1,
525 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
526 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
527 GLuint arg3Rep, GLuint arg3Mod)
528{
529 GET_CURRENT_CONTEXT(ctx);
530 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
531 GLint ci;
532 struct atifs_instruction *curI;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000533 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000534
Roland Scheideggerf519a772005-09-02 01:11:53 +0000535 if (!ctx->ATIFragmentShader.Compiling) {
536 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
537 return;
538 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000539
Roland Scheideggerf519a772005-09-02 01:11:53 +0000540 if (curProg->cur_pass==0)
541 curProg->cur_pass=1;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000542
Roland Scheideggerf519a772005-09-02 01:11:53 +0000543 else if (curProg->cur_pass==2)
544 curProg->cur_pass=3;
545
546 /* decide whether this is a new instruction or not ... all color instructions are new,
547 and alpha instructions might also be new if there was no preceding color inst */
548 if ((optype == 0) || (curProg->last_optype == optype)) {
549 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
550 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
551 return;
552 }
553 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
554 match_pair_inst(curProg, optype);
555 new_arith_inst(curProg);
556 }
557 curProg->last_optype = optype;
558 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000559
560 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000561 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
562
563 /* error checking */
564 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
565 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
566 return;
567 }
568 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
569 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
570 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
571 (modtemp != GL_EIGHTH_BIT_ATI)) {
572 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
573 return;
574 }
575 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
576 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
577 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
578 return;
579 }
580 if (optype == 1) {
581 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
582 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
583 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
584 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
585 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
586 return;
587 }
588 }
589 if ((op == GL_DOT4_ATI) &&
590 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
591 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
592 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
593 }
594
595 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
596 return;
597 }
598 if (arg2) {
599 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
600 return;
601 }
602 }
603 if (arg3) {
604 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
605 return;
606 }
607 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
608 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
609 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
610 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
611 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
612 return;
613 }
614 }
615
616 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
Dave Airlie7f752fe2004-12-19 03:06:59 +0000617
618 curI->Opcode[optype] = op;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000619 curI->SrcReg[optype][0].Index = arg1;
620 curI->SrcReg[optype][0].argRep = arg1Rep;
621 curI->SrcReg[optype][0].argMod = arg1Mod;
622 curI->ArgCount[optype] = arg_count;
623
624 if (arg2) {
625 curI->SrcReg[optype][1].Index = arg2;
626 curI->SrcReg[optype][1].argRep = arg2Rep;
627 curI->SrcReg[optype][1].argMod = arg2Mod;
628 }
629
630 if (arg3) {
631 curI->SrcReg[optype][2].Index = arg3;
632 curI->SrcReg[optype][2].argRep = arg3Rep;
633 curI->SrcReg[optype][2].argMod = arg3Mod;
634 }
635
636 curI->DstReg[optype].Index = dst;
637 curI->DstReg[optype].dstMod = dstMod;
638 curI->DstReg[optype].dstMask = dstMask;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000639
Dave Airlie7f752fe2004-12-19 03:06:59 +0000640#if MESA_DEBUG_ATI_FS
641 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
642#endif
643
644}
645
646void GLAPIENTRY
647_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
648 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
649 GLuint arg1Mod)
650{
651 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
652 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
653}
654
655void GLAPIENTRY
656_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
657 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
658 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
659 GLuint arg2Mod)
660{
661 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
662 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
663 arg2Mod, 0, 0, 0);
664}
665
666void GLAPIENTRY
667_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
668 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
669 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
670 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
671 GLuint arg3Mod)
672{
673 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
674 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
675 arg2Mod, arg3, arg3Rep, arg3Mod);
676}
677
678void GLAPIENTRY
679_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
680 GLuint arg1Rep, GLuint arg1Mod)
681{
682 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
683 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
684}
685
686void GLAPIENTRY
687_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
688 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
689 GLuint arg2Rep, GLuint arg2Mod)
690{
691 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
692 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
693 0);
694}
695
696void GLAPIENTRY
697_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
698 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
699 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
700 GLuint arg3Rep, GLuint arg3Mod)
701{
702 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
703 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
704 arg3Rep, arg3Mod);
705}
706
707void GLAPIENTRY
708_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
709{
Karl Schultze81cbd82005-09-05 13:45:23 +0000710 GLuint dstindex;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000711 GET_CURRENT_CONTEXT(ctx);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000712
Roland Scheideggerf519a772005-09-02 01:11:53 +0000713 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
714 /* spec says nothing about what should happen here but we can't just segfault...*/
715 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
716 return;
717 }
718
Karl Schultze81cbd82005-09-05 13:45:23 +0000719 dstindex = dst - GL_CON_0_ATI;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000720 if (ctx->ATIFragmentShader.Compiling) {
721 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
722 COPY_4V(curProg->Constants[dstindex], value);
723 curProg->localConstDef |= 1 << dstindex;
724 }
725 else {
Roland Scheideggerce335072005-09-08 00:12:57 +0000726 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Roland Scheideggerf519a772005-09-02 01:11:53 +0000727 COPY_4V(ctx->ATIFragmentShader.globalConstants[dstindex], value);
728 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000729}