blob: 3117467c3cfb3b970679ddf25111d1afb5d2942d [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) {
249 _mesa_BindFragmentShaderATI(0);
250 }
251 }
Brian Paulea2943e2005-01-20 04:02:02 +0000252#if 0
Dave Airlie7f752fe2004-12-19 03:06:59 +0000253 if (!prog->DeletePending) {
254 prog->DeletePending = GL_TRUE;
255 prog->RefCount--;
256 }
257 if (prog->RefCount <= 0) {
258 _mesa_HashRemove(ctx->Shared->Programs, id);
259 ctx->Driver.DeleteProgram(ctx, prog);
260 }
Brian Paulea2943e2005-01-20 04:02:02 +0000261#else
262 /* The ID is immediately available for re-use now */
263 _mesa_HashRemove(ctx->Shared->Programs, id);
264 prog->RefCount--;
265 if (prog->RefCount <= 0) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000266 ctx->Driver.DeleteProgram(ctx, prog);
Brian Paulea2943e2005-01-20 04:02:02 +0000267 }
268#endif
Dave Airlie7f752fe2004-12-19 03:06:59 +0000269 }
270}
271
272void GLAPIENTRY
273_mesa_BeginFragmentShaderATI(void)
274{
Roland Scheideggerf519a772005-09-02 01:11:53 +0000275 GLint i;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000276 GET_CURRENT_CONTEXT(ctx);
277
Roland Scheideggerf519a772005-09-02 01:11:53 +0000278 if (ctx->ATIFragmentShader.Compiling) {
279 _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
280 return;
281 }
282
283 /* if the shader was already defined free instructions and get new ones
284 (or, could use the same mem but would need to reinitialize) */
285 /* no idea if it's allowed to redefine a shader */
286 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
287 if (ctx->ATIFragmentShader.Current->Instructions[i])
288 _mesa_free(ctx->ATIFragmentShader.Current->Instructions[i]);
289 if (ctx->ATIFragmentShader.Current->SetupInst[i])
290 _mesa_free(ctx->ATIFragmentShader.Current->SetupInst[i]);
291 }
292
Dave Airlie7f752fe2004-12-19 03:06:59 +0000293 /* malloc the instructions here - not sure if the best place but its
294 a start */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000295 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
296 ctx->ATIFragmentShader.Current->Instructions[i] =
297 (struct atifs_instruction *)
298 _mesa_calloc(sizeof(struct atifs_instruction) *
299 (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
300 ctx->ATIFragmentShader.Current->SetupInst[i] =
301 (struct atifs_setupinst *)
302 _mesa_calloc(sizeof(struct atifs_setupinst) *
303 (MAX_NUM_FRAGMENT_REGISTERS_ATI));
304 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000305
Roland Scheideggerf519a772005-09-02 01:11:53 +0000306/* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
307 ctx->ATIFragmentShader.Current->localConstDef = 0;
308 ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
309 ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
310 ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
311 ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
312 ctx->ATIFragmentShader.Current->NumPasses = 0;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000313 ctx->ATIFragmentShader.Current->cur_pass = 0;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000314 ctx->ATIFragmentShader.Current->last_optype = 0;
315 ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
316 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
317 ctx->ATIFragmentShader.Current->swizzlerq = 0;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000318 ctx->ATIFragmentShader.Compiling = 1;
319}
320
321void GLAPIENTRY
322_mesa_EndFragmentShaderATI(void)
323{
324 GET_CURRENT_CONTEXT(ctx);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000325 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000326#if MESA_DEBUG_ATI_FS
327 GLint i, j;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000328#endif
329
Roland Scheideggerf519a772005-09-02 01:11:53 +0000330 if (!ctx->ATIFragmentShader.Compiling) {
331 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
332 return;
333 }
334 if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
335 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
336 /* according to spec, DON'T return here */
337 }
338
339 match_pair_inst(curProg, 0);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000340 ctx->ATIFragmentShader.Compiling = 0;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000341 ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
342 if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
343 (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
344 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
345 }
346 if (ctx->ATIFragmentShader.Current->cur_pass > 1)
347 ctx->ATIFragmentShader.Current->NumPasses = 2;
348 else ctx->ATIFragmentShader.Current->NumPasses = 1;
Dave Airlie3aa69b32005-01-30 06:24:30 +0000349 ctx->ATIFragmentShader.Current->cur_pass=0;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000350#if MESA_DEBUG_ATI_FS
Roland Scheideggerf519a772005-09-02 01:11:53 +0000351 for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
352 for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
353 GLuint op = curProg->SetupInst[j][i].Opcode;
354 const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0";
355 GLuint src = curProg->SetupInst[j][i].src;
356 GLuint swizzle = curProg->SetupInst[j][i].swizzle;
357 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
358 swizzle);
359 }
360 for (i = 0; i < curProg->numArithInstr[j]; i++) {
361 GLuint op0 = curProg->Instructions[j][i].Opcode[0];
362 GLuint op1 = curProg->Instructions[j][i].Opcode[1];
363 const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0";
364 const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0";
365 GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
366 GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
367 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
Dave Airlie7f752fe2004-12-19 03:06:59 +0000368 op1, op1_enum, count1);
Roland Scheideggerf519a772005-09-02 01:11:53 +0000369 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000370 }
371#endif
372}
373
374void GLAPIENTRY
375_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
376{
377 GET_CURRENT_CONTEXT(ctx);
378 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000379 struct atifs_setupinst *curI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000380
Roland Scheideggerf519a772005-09-02 01:11:53 +0000381 if (!ctx->ATIFragmentShader.Compiling) {
382 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
383 return;
384 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000385
Roland Scheideggerf519a772005-09-02 01:11:53 +0000386 if (curProg->cur_pass == 1) {
387 match_pair_inst(curProg, 0);
388 curProg->cur_pass = 2;
389 }
390 if ((curProg->cur_pass > 2) ||
391 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
392 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
393 return;
394 }
395 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
396 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
397 return;
398 }
399 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
400 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE5_ARB))) {
401 /* is this texture5 or texture7? spec is a bit unclear there */
402 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
403 return;
404 }
405 if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
406 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
407 return;
408 }
409 if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
410 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
411 return;
412 }
413 if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
414 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
415 return;
416 }
417 if (coord <= GL_TEXTURE5) {
418 if ((((curProg->swizzlerq >> (coord * 2)) & 3) != 0) &&
419 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (coord * 2)) & 3))) {
420 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
421 return;
422 } else {
423 curProg->swizzlerq |= (((swizzle & 1) + 1) << (coord * 2));
424 }
425 }
426
427 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
428 new_tex_inst(curProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000429
430 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000431 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
Dave Airlie7f752fe2004-12-19 03:06:59 +0000432
Roland Scheideggerf519a772005-09-02 01:11:53 +0000433 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
434 curI->src = coord;
435 curI->swizzle = swizzle;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000436
437#if MESA_DEBUG_ATI_FS
438 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
439 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
440 _mesa_lookup_enum_by_nr(swizzle));
441#endif
442}
443
444void GLAPIENTRY
445_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
446{
447 GET_CURRENT_CONTEXT(ctx);
448 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000449 struct atifs_setupinst *curI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000450
Roland Scheideggerf519a772005-09-02 01:11:53 +0000451 if (!ctx->ATIFragmentShader.Compiling) {
452 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
453 return;
454 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000455
Roland Scheideggerf519a772005-09-02 01:11:53 +0000456 if (curProg->cur_pass == 1) {
457 match_pair_inst(curProg, 0);
458 curProg->cur_pass = 2;
459 }
460 if ((curProg->cur_pass > 2) ||
461 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
462 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
463 return;
464 }
465 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
466 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
467 return;
468 }
469 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
470 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE5_ARB))) {
471 /* is this texture5 or texture7? spec is a bit unclear there */
472 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
473 return;
474 }
475 if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
476 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
477 return;
478 }
479 if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
480 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
481 return;
482 }
483 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
484 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
485 return;
486 }
487 if (interp <= GL_TEXTURE5) {
488 if ((((curProg->swizzlerq >> (interp * 2)) & 3) != 0) &&
489 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (interp * 2)) & 3))) {
490 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
491 return;
492 } else {
493 curProg->swizzlerq |= (((swizzle & 1) + 1) << (interp * 2));
494 }
495 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000496
Roland Scheideggerf519a772005-09-02 01:11:53 +0000497 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
498 new_tex_inst(curProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000499
Dave Airlie7f752fe2004-12-19 03:06:59 +0000500 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000501 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
Dave Airlie7f752fe2004-12-19 03:06:59 +0000502
Roland Scheideggerf519a772005-09-02 01:11:53 +0000503 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
504 curI->src = interp;
505 curI->swizzle = swizzle;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000506
507#if MESA_DEBUG_ATI_FS
508 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
509 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
510 _mesa_lookup_enum_by_nr(swizzle));
511#endif
512}
513
514static void
515_mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
516 GLuint dstMask, GLuint dstMod, GLuint arg1,
517 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
518 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
519 GLuint arg3Rep, GLuint arg3Mod)
520{
521 GET_CURRENT_CONTEXT(ctx);
522 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
523 GLint ci;
524 struct atifs_instruction *curI;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000525 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000526
Roland Scheideggerf519a772005-09-02 01:11:53 +0000527 if (!ctx->ATIFragmentShader.Compiling) {
528 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
529 return;
530 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000531
Roland Scheideggerf519a772005-09-02 01:11:53 +0000532 if (curProg->cur_pass==0)
533 curProg->cur_pass=1;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000534
Roland Scheideggerf519a772005-09-02 01:11:53 +0000535 else if (curProg->cur_pass==2)
536 curProg->cur_pass=3;
537
538 /* decide whether this is a new instruction or not ... all color instructions are new,
539 and alpha instructions might also be new if there was no preceding color inst */
540 if ((optype == 0) || (curProg->last_optype == optype)) {
541 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
542 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
543 return;
544 }
545 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
546 match_pair_inst(curProg, optype);
547 new_arith_inst(curProg);
548 }
549 curProg->last_optype = optype;
550 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000551
552 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000553 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
554
555 /* error checking */
556 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
557 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
558 return;
559 }
560 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
561 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
562 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
563 (modtemp != GL_EIGHTH_BIT_ATI)) {
564 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
565 return;
566 }
567 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
568 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
569 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
570 return;
571 }
572 if (optype == 1) {
573 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
574 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
575 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
576 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
577 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
578 return;
579 }
580 }
581 if ((op == GL_DOT4_ATI) &&
582 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
583 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
584 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
585 }
586
587 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
588 return;
589 }
590 if (arg2) {
591 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
592 return;
593 }
594 }
595 if (arg3) {
596 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
597 return;
598 }
599 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
600 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
601 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
602 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
603 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
604 return;
605 }
606 }
607
608 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
Dave Airlie7f752fe2004-12-19 03:06:59 +0000609
610 curI->Opcode[optype] = op;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000611 curI->SrcReg[optype][0].Index = arg1;
612 curI->SrcReg[optype][0].argRep = arg1Rep;
613 curI->SrcReg[optype][0].argMod = arg1Mod;
614 curI->ArgCount[optype] = arg_count;
615
616 if (arg2) {
617 curI->SrcReg[optype][1].Index = arg2;
618 curI->SrcReg[optype][1].argRep = arg2Rep;
619 curI->SrcReg[optype][1].argMod = arg2Mod;
620 }
621
622 if (arg3) {
623 curI->SrcReg[optype][2].Index = arg3;
624 curI->SrcReg[optype][2].argRep = arg3Rep;
625 curI->SrcReg[optype][2].argMod = arg3Mod;
626 }
627
628 curI->DstReg[optype].Index = dst;
629 curI->DstReg[optype].dstMod = dstMod;
630 curI->DstReg[optype].dstMask = dstMask;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000631
Dave Airlie7f752fe2004-12-19 03:06:59 +0000632#if MESA_DEBUG_ATI_FS
633 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
634#endif
635
636}
637
638void GLAPIENTRY
639_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
640 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
641 GLuint arg1Mod)
642{
643 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
644 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
645}
646
647void GLAPIENTRY
648_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
649 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
650 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
651 GLuint arg2Mod)
652{
653 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
654 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
655 arg2Mod, 0, 0, 0);
656}
657
658void GLAPIENTRY
659_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
660 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
661 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
662 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
663 GLuint arg3Mod)
664{
665 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
666 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
667 arg2Mod, arg3, arg3Rep, arg3Mod);
668}
669
670void GLAPIENTRY
671_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
672 GLuint arg1Rep, GLuint arg1Mod)
673{
674 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
675 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
676}
677
678void GLAPIENTRY
679_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
680 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
681 GLuint arg2Rep, GLuint arg2Mod)
682{
683 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
684 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
685 0);
686}
687
688void GLAPIENTRY
689_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
690 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
691 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
692 GLuint arg3Rep, GLuint arg3Mod)
693{
694 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
695 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
696 arg3Rep, arg3Mod);
697}
698
699void GLAPIENTRY
700_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
701{
Karl Schultze81cbd82005-09-05 13:45:23 +0000702 GLuint dstindex;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000703 GET_CURRENT_CONTEXT(ctx);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000704
Roland Scheideggerf519a772005-09-02 01:11:53 +0000705 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
706 /* spec says nothing about what should happen here but we can't just segfault...*/
707 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
708 return;
709 }
710
Karl Schultze81cbd82005-09-05 13:45:23 +0000711 dstindex = dst - GL_CON_0_ATI;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000712 if (ctx->ATIFragmentShader.Compiling) {
713 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
714 COPY_4V(curProg->Constants[dstindex], value);
715 curProg->localConstDef |= 1 << dstindex;
716 }
717 else {
718 COPY_4V(ctx->ATIFragmentShader.globalConstants[dstindex], value);
719 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000720}