Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[mesa.git] / src / mesa / shader / atifragshader.c
1 /**
2 * \file atifragshader.c
3 * \author David Airlie
4 * Copyright (C) 2004 David Airlie All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "main/glheader.h"
25 #include "main/context.h"
26 #include "main/hash.h"
27 #include "main/imports.h"
28 #include "main/macros.h"
29 #include "main/enums.h"
30 #include "main/mtypes.h"
31 #include "atifragshader.h"
32
33 #define MESA_DEBUG_ATI_FS 0
34
35 static struct ati_fragment_shader DummyShader;
36
37
38 /**
39 * Allocate and initialize a new ATI fragment shader object.
40 */
41 struct 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 */
57 void
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
71
72 static void
73 new_arith_inst(struct ati_fragment_shader *prog)
74 {
75 /* 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
81 static void
82 new_tex_inst(struct ati_fragment_shader *prog)
83 {
84 }
85
86 static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
87 {
88 if (optype == curProg->last_optype) {
89 curProg->last_optype = 1;
90 }
91 }
92
93 #if MESA_DEBUG_ATI_FS
94 static char *
95 create_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
123 static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
124 "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
125
126 static 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
157 static 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
186 GLuint GLAPIENTRY
187 _mesa_GenFragmentShadersATI(GLuint range)
188 {
189 GLuint first;
190 GLuint i;
191 GET_CURRENT_CONTEXT(ctx);
192
193 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
203 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
204 for (i = 0; i < range; i++) {
205 _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
206 }
207
208 return first;
209 }
210
211 void GLAPIENTRY
212 _mesa_BindFragmentShaderATI(GLuint id)
213 {
214 GET_CURRENT_CONTEXT(ctx);
215 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
216 struct ati_fragment_shader *newProg;
217
218 if (ctx->ATIFragmentShader.Compiling) {
219 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
220 return;
221 }
222
223 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
224
225 if (curProg->Id == id) {
226 return;
227 }
228
229 /* unbind current */
230 if (curProg->Id != 0) {
231 curProg->RefCount--;
232 if (curProg->RefCount <= 0) {
233 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
234 }
235 }
236
237 /* find new shader */
238 if (id == 0) {
239 newProg = ctx->Shared->DefaultFragmentShader;
240 }
241 else {
242 newProg = (struct ati_fragment_shader *)
243 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
244 if (!newProg || newProg == &DummyShader) {
245 /* allocate a new program now */
246 newProg = _mesa_new_ati_fragment_shader(ctx, id);
247 if (!newProg) {
248 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
249 return;
250 }
251 _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
252 }
253
254 }
255
256 /* do actual bind */
257 ctx->ATIFragmentShader.Current = newProg;
258
259 ASSERT(ctx->ATIFragmentShader.Current);
260 if (newProg)
261 newProg->RefCount++;
262
263 /*if (ctx->Driver.BindProgram)
264 ctx->Driver.BindProgram(ctx, target, prog); */
265 }
266
267 void GLAPIENTRY
268 _mesa_DeleteFragmentShaderATI(GLuint id)
269 {
270 GET_CURRENT_CONTEXT(ctx);
271
272 if (ctx->ATIFragmentShader.Compiling) {
273 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
274 return;
275 }
276
277 if (id != 0) {
278 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);
282 }
283 else if (prog) {
284 if (ctx->ATIFragmentShader.Current &&
285 ctx->ATIFragmentShader.Current->Id == id) {
286 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
287 _mesa_BindFragmentShaderATI(0);
288 }
289 }
290
291 /* The ID is immediately available for re-use now */
292 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
293 prog->RefCount--;
294 if (prog->RefCount <= 0) {
295 _mesa_free(prog);
296 }
297 }
298 }
299
300
301 void GLAPIENTRY
302 _mesa_BeginFragmentShaderATI(void)
303 {
304 GLint i;
305 GET_CURRENT_CONTEXT(ctx);
306
307 if (ctx->ATIFragmentShader.Compiling) {
308 _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
309 return;
310 }
311
312 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
313
314 /* 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
324 /* malloc the instructions here - not sure if the best place but its
325 a start */
326 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 }
336
337 /* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
338 ctx->ATIFragmentShader.Current->LocalConstDef = 0;
339 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;
344 ctx->ATIFragmentShader.Current->cur_pass = 0;
345 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;
349 ctx->ATIFragmentShader.Compiling = 1;
350 }
351
352 void GLAPIENTRY
353 _mesa_EndFragmentShaderATI(void)
354 {
355 GET_CURRENT_CONTEXT(ctx);
356 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
357 #if MESA_DEBUG_ATI_FS
358 GLint i, j;
359 #endif
360
361 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);
371 ctx->ATIFragmentShader.Compiling = 0;
372 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;
380 ctx->ATIFragmentShader.Current->cur_pass=0;
381 #if MESA_DEBUG_ATI_FS
382 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,
399 op1, op1_enum, count1);
400 }
401 }
402 #endif
403 if (ctx->Driver.ProgramStringNotify)
404 ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_SHADER_ATI, NULL );
405 }
406
407 void 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;
412 struct atifs_setupinst *curI;
413
414 if (!ctx->ATIFragmentShader.Compiling) {
415 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
416 return;
417 }
418
419 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 }
428 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
429 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
430 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
431 return;
432 }
433 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
434 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
435 ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
436 _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 }
443 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
444 _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 }
451 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))) {
455 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
456 return;
457 } else {
458 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
459 }
460 }
461
462 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
463 new_tex_inst(curProg);
464
465 /* add the instructions */
466 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
467
468 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
469 curI->src = coord;
470 curI->swizzle = swizzle;
471
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
479 void 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;
484 struct atifs_setupinst *curI;
485
486 if (!ctx->ATIFragmentShader.Compiling) {
487 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
488 return;
489 }
490
491 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 }
500 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
501 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
502 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
503 return;
504 }
505 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
506 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
507 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
508 /* 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 }
516 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
517 _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 }
524 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))) {
528 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
529 return;
530 } else {
531 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
532 }
533 }
534
535 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
536 new_tex_inst(curProg);
537
538 /* add the instructions */
539 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
540
541 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
542 curI->src = interp;
543 curI->swizzle = swizzle;
544
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
552 static 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;
563 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
564
565 if (!ctx->ATIFragmentShader.Compiling) {
566 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
567 return;
568 }
569
570 if (curProg->cur_pass==0)
571 curProg->cur_pass=1;
572
573 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;
589
590 /* add the instructions */
591 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) */
647
648 curI->Opcode[optype] = op;
649 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;
669
670 #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
676 void 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
685 void 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
696 void 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
708 void 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
716 void 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
726 void 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
737 void GLAPIENTRY
738 _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
739 {
740 GLuint dstindex;
741 GET_CURRENT_CONTEXT(ctx);
742
743 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
749 dstindex = dst - GL_CON_0_ATI;
750 if (ctx->ATIFragmentShader.Compiling) {
751 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
752 COPY_4V(curProg->Constants[dstindex], value);
753 curProg->LocalConstDef |= 1 << dstindex;
754 }
755 else {
756 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
757 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
758 }
759 }