blob: 854c91187415179d94ad57849ce4a7a6ca15990e [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
Roland Scheidegger5785e322006-11-29 16:41:28 +0000403 if (ctx->Driver.ProgramStringNotify)
404 ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_SHADER_ATI, NULL );
Dave Airlie7f752fe2004-12-19 03:06:59 +0000405}
406
407void GLAPIENTRY
408_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
409{
410 GET_CURRENT_CONTEXT(ctx);
411 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000412 struct atifs_setupinst *curI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000413
Roland Scheideggerf519a772005-09-02 01:11:53 +0000414 if (!ctx->ATIFragmentShader.Compiling) {
415 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
416 return;
417 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000418
Roland Scheideggerf519a772005-09-02 01:11:53 +0000419 if (curProg->cur_pass == 1) {
420 match_pair_inst(curProg, 0);
421 curProg->cur_pass = 2;
422 }
423 if ((curProg->cur_pass > 2) ||
424 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
425 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
426 return;
427 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000428 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
429 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000430 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
431 return;
432 }
433 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000434 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
435 ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000436 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
437 return;
438 }
439 if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
440 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
441 return;
442 }
Brian217e5b52007-08-07 21:42:34 +0100443 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000444 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
445 return;
446 }
447 if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
448 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
449 return;
450 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000451 if (coord <= GL_TEXTURE7_ARB) {
452 GLuint tmp = coord - GL_TEXTURE0_ARB;
453 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
454 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000455 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
456 return;
457 } else {
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000458 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
Roland Scheideggerf519a772005-09-02 01:11:53 +0000459 }
460 }
461
462 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
463 new_tex_inst(curProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000464
465 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000466 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
Dave Airlie7f752fe2004-12-19 03:06:59 +0000467
Roland Scheideggerf519a772005-09-02 01:11:53 +0000468 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
469 curI->src = coord;
470 curI->swizzle = swizzle;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000471
472#if MESA_DEBUG_ATI_FS
473 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
474 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
475 _mesa_lookup_enum_by_nr(swizzle));
476#endif
477}
478
479void GLAPIENTRY
480_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
481{
482 GET_CURRENT_CONTEXT(ctx);
483 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000484 struct atifs_setupinst *curI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000485
Roland Scheideggerf519a772005-09-02 01:11:53 +0000486 if (!ctx->ATIFragmentShader.Compiling) {
487 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
488 return;
489 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000490
Roland Scheideggerf519a772005-09-02 01:11:53 +0000491 if (curProg->cur_pass == 1) {
492 match_pair_inst(curProg, 0);
493 curProg->cur_pass = 2;
494 }
495 if ((curProg->cur_pass > 2) ||
496 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
497 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
498 return;
499 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000500 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
501 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000502 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
503 return;
504 }
505 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000506 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
507 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000508 /* is this texture5 or texture7? spec is a bit unclear there */
509 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
510 return;
511 }
512 if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
513 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
514 return;
515 }
Brian217e5b52007-08-07 21:42:34 +0100516 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000517 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
518 return;
519 }
520 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
521 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
522 return;
523 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000524 if (interp <= GL_TEXTURE7_ARB) {
525 GLuint tmp = interp - GL_TEXTURE0_ARB;
526 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
527 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000528 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
529 return;
530 } else {
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000531 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
Roland Scheideggerf519a772005-09-02 01:11:53 +0000532 }
533 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000534
Roland Scheideggerf519a772005-09-02 01:11:53 +0000535 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
536 new_tex_inst(curProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000537
Dave Airlie7f752fe2004-12-19 03:06:59 +0000538 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000539 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
Dave Airlie7f752fe2004-12-19 03:06:59 +0000540
Roland Scheideggerf519a772005-09-02 01:11:53 +0000541 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
542 curI->src = interp;
543 curI->swizzle = swizzle;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000544
545#if MESA_DEBUG_ATI_FS
546 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
547 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
548 _mesa_lookup_enum_by_nr(swizzle));
549#endif
550}
551
552static void
553_mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
554 GLuint dstMask, GLuint dstMod, GLuint arg1,
555 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
556 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
557 GLuint arg3Rep, GLuint arg3Mod)
558{
559 GET_CURRENT_CONTEXT(ctx);
560 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
561 GLint ci;
562 struct atifs_instruction *curI;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000563 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000564
Roland Scheideggerf519a772005-09-02 01:11:53 +0000565 if (!ctx->ATIFragmentShader.Compiling) {
566 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
567 return;
568 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000569
Roland Scheideggerf519a772005-09-02 01:11:53 +0000570 if (curProg->cur_pass==0)
571 curProg->cur_pass=1;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000572
Roland Scheideggerf519a772005-09-02 01:11:53 +0000573 else if (curProg->cur_pass==2)
574 curProg->cur_pass=3;
575
576 /* decide whether this is a new instruction or not ... all color instructions are new,
577 and alpha instructions might also be new if there was no preceding color inst */
578 if ((optype == 0) || (curProg->last_optype == optype)) {
579 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
580 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
581 return;
582 }
583 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
584 match_pair_inst(curProg, optype);
585 new_arith_inst(curProg);
586 }
587 curProg->last_optype = optype;
588 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000589
590 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000591 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
592
593 /* error checking */
594 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
595 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
596 return;
597 }
598 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
599 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
600 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
601 (modtemp != GL_EIGHTH_BIT_ATI)) {
602 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
603 return;
604 }
605 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
606 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
607 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
608 return;
609 }
610 if (optype == 1) {
611 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
612 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
613 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
614 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
615 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
616 return;
617 }
618 }
619 if ((op == GL_DOT4_ATI) &&
620 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
621 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
622 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
623 }
624
625 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
626 return;
627 }
628 if (arg2) {
629 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
630 return;
631 }
632 }
633 if (arg3) {
634 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
635 return;
636 }
637 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
638 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
639 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
640 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
641 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
642 return;
643 }
644 }
645
646 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
Dave Airlie7f752fe2004-12-19 03:06:59 +0000647
648 curI->Opcode[optype] = op;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000649 curI->SrcReg[optype][0].Index = arg1;
650 curI->SrcReg[optype][0].argRep = arg1Rep;
651 curI->SrcReg[optype][0].argMod = arg1Mod;
652 curI->ArgCount[optype] = arg_count;
653
654 if (arg2) {
655 curI->SrcReg[optype][1].Index = arg2;
656 curI->SrcReg[optype][1].argRep = arg2Rep;
657 curI->SrcReg[optype][1].argMod = arg2Mod;
658 }
659
660 if (arg3) {
661 curI->SrcReg[optype][2].Index = arg3;
662 curI->SrcReg[optype][2].argRep = arg3Rep;
663 curI->SrcReg[optype][2].argMod = arg3Mod;
664 }
665
666 curI->DstReg[optype].Index = dst;
667 curI->DstReg[optype].dstMod = dstMod;
668 curI->DstReg[optype].dstMask = dstMask;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000669
Dave Airlie7f752fe2004-12-19 03:06:59 +0000670#if MESA_DEBUG_ATI_FS
671 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
672#endif
673
674}
675
676void GLAPIENTRY
677_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
678 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
679 GLuint arg1Mod)
680{
681 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
682 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
683}
684
685void GLAPIENTRY
686_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
687 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
688 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
689 GLuint arg2Mod)
690{
691 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
692 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
693 arg2Mod, 0, 0, 0);
694}
695
696void GLAPIENTRY
697_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
698 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
699 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
700 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
701 GLuint arg3Mod)
702{
703 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
704 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
705 arg2Mod, arg3, arg3Rep, arg3Mod);
706}
707
708void GLAPIENTRY
709_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
710 GLuint arg1Rep, GLuint arg1Mod)
711{
712 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
713 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
714}
715
716void GLAPIENTRY
717_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
718 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
719 GLuint arg2Rep, GLuint arg2Mod)
720{
721 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
722 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
723 0);
724}
725
726void GLAPIENTRY
727_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
728 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
729 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
730 GLuint arg3Rep, GLuint arg3Mod)
731{
732 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
733 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
734 arg3Rep, arg3Mod);
735}
736
737void GLAPIENTRY
738_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
739{
Karl Schultze81cbd82005-09-05 13:45:23 +0000740 GLuint dstindex;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000741 GET_CURRENT_CONTEXT(ctx);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000742
Roland Scheideggerf519a772005-09-02 01:11:53 +0000743 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
744 /* spec says nothing about what should happen here but we can't just segfault...*/
745 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
746 return;
747 }
748
Karl Schultze81cbd82005-09-05 13:45:23 +0000749 dstindex = dst - GL_CON_0_ATI;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000750 if (ctx->ATIFragmentShader.Compiling) {
751 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
752 COPY_4V(curProg->Constants[dstindex], value);
Brian Paul63d68302005-11-19 16:43:04 +0000753 curProg->LocalConstDef |= 1 << dstindex;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000754 }
755 else {
Roland Scheideggerce335072005-09-08 00:12:57 +0000756 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian Paul63d68302005-11-19 16:43:04 +0000757 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
Roland Scheideggerf519a772005-09-02 01:11:53 +0000758 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000759}