mesa: remove dd_function_table::BindProgram
[mesa.git] / src / mesa / main / 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 "main/dispatch.h"
32 #include "main/atifragshader.h"
33 #include "program/program.h"
34
35 #define MESA_DEBUG_ATI_FS 0
36
37 static struct ati_fragment_shader DummyShader;
38
39
40 /**
41 * Allocate and initialize a new ATI fragment shader object.
42 */
43 struct ati_fragment_shader *
44 _mesa_new_ati_fragment_shader(struct gl_context *ctx, GLuint id)
45 {
46 struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
47 (void) ctx;
48 if (s) {
49 s->Id = id;
50 s->RefCount = 1;
51 }
52 return s;
53 }
54
55
56 /**
57 * Delete the given ati fragment shader
58 */
59 void
60 _mesa_delete_ati_fragment_shader(struct gl_context *ctx, struct ati_fragment_shader *s)
61 {
62 GLuint i;
63 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
64 free(s->Instructions[i]);
65 free(s->SetupInst[i]);
66 }
67 _mesa_reference_program(ctx, &s->Program, NULL);
68 free(s);
69 }
70
71
72
73 static void
74 new_arith_inst(struct ati_fragment_shader *prog)
75 {
76 /* set "default" instruction as not all may get defined.
77 there is no specified way to express a nop with ati fragment shaders we use
78 GL_NONE as the op enum and just set some params to 0 - so nothing to do here */
79 prog->numArithInstr[prog->cur_pass >> 1]++;
80 }
81
82 static void
83 new_tex_inst(struct ati_fragment_shader *prog)
84 {
85 }
86
87 static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
88 {
89 if (optype == curProg->last_optype) {
90 curProg->last_optype = 1;
91 }
92 }
93
94 #if MESA_DEBUG_ATI_FS
95 static char *
96 create_dst_mod_str(GLuint mod)
97 {
98 static char ret_str[1024];
99
100 memset(ret_str, 0, 1024);
101 if (mod & GL_2X_BIT_ATI)
102 strncat(ret_str, "|2X", 1024);
103
104 if (mod & GL_4X_BIT_ATI)
105 strncat(ret_str, "|4X", 1024);
106
107 if (mod & GL_8X_BIT_ATI)
108 strncat(ret_str, "|8X", 1024);
109 if (mod & GL_HALF_BIT_ATI)
110 strncat(ret_str, "|HA", 1024);
111 if (mod & GL_QUARTER_BIT_ATI)
112 strncat(ret_str, "|QU", 1024);
113 if (mod & GL_EIGHTH_BIT_ATI)
114 strncat(ret_str, "|EI", 1024);
115
116 if (mod & GL_SATURATE_BIT_ATI)
117 strncat(ret_str, "|SAT", 1024);
118
119 if (strlen(ret_str) == 0)
120 strncat(ret_str, "NONE", 1024);
121 return ret_str;
122 }
123
124 static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
125 "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
126
127 static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
128 GLuint dstMask, GLuint dstMod, GLuint arg1,
129 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
130 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
131 GLuint arg3Rep, GLuint arg3Mod)
132 {
133 char *op_name;
134
135 op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
136
137 fprintf(stderr, "%s(%s, %s", op_name, _mesa_enum_to_string(op),
138 _mesa_enum_to_string(dst));
139 if (!optype)
140 fprintf(stderr, ", %d", dstMask);
141
142 fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
143
144 fprintf(stderr, ", %s, %s, %d", _mesa_enum_to_string(arg1),
145 _mesa_enum_to_string(arg1Rep), arg1Mod);
146 if (arg_count>1)
147 fprintf(stderr, ", %s, %s, %d", _mesa_enum_to_string(arg2),
148 _mesa_enum_to_string(arg2Rep), arg2Mod);
149 if (arg_count>2)
150 fprintf(stderr, ", %s, %s, %d", _mesa_enum_to_string(arg3),
151 _mesa_enum_to_string(arg3Rep), arg3Mod);
152
153 fprintf(stderr,")\n");
154
155 }
156 #endif
157
158 static int check_arith_arg(struct ati_fragment_shader *curProg,
159 GLuint optype, GLuint arg, GLuint argRep)
160 {
161 GET_CURRENT_CONTEXT(ctx);
162
163 if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) &&
164 ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) &&
165 (arg != GL_ZERO) && (arg != GL_ONE) &&
166 (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) {
167 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)");
168 return 0;
169 }
170 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
171 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
172 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
173 return 0;
174 }
175 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
176 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
177 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
178 return 0;
179 }
180 if ((curProg->cur_pass == 1) &&
181 ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
182 curProg->interpinp1 = GL_TRUE;
183 }
184 return 1;
185 }
186
187 GLuint GLAPIENTRY
188 _mesa_GenFragmentShadersATI(GLuint range)
189 {
190 GLuint first;
191 GLuint i;
192 GET_CURRENT_CONTEXT(ctx);
193
194 if (range == 0) {
195 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)");
196 return 0;
197 }
198
199 if (ctx->ATIFragmentShader.Compiling) {
200 _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)");
201 return 0;
202 }
203
204 _mesa_HashLockMutex(ctx->Shared->ATIShaders);
205
206 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
207 for (i = 0; i < range; i++) {
208 _mesa_HashInsertLocked(ctx->Shared->ATIShaders, first + i, &DummyShader);
209 }
210
211 _mesa_HashUnlockMutex(ctx->Shared->ATIShaders);
212
213 return first;
214 }
215
216 void GLAPIENTRY
217 _mesa_BindFragmentShaderATI(GLuint id)
218 {
219 GET_CURRENT_CONTEXT(ctx);
220 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
221 struct ati_fragment_shader *newProg;
222
223 if (ctx->ATIFragmentShader.Compiling) {
224 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
225 return;
226 }
227
228 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
229
230 if (curProg->Id == id) {
231 return;
232 }
233
234 /* unbind current */
235 if (curProg->Id != 0) {
236 curProg->RefCount--;
237 if (curProg->RefCount <= 0) {
238 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
239 }
240 }
241
242 /* find new shader */
243 if (id == 0) {
244 newProg = ctx->Shared->DefaultFragmentShader;
245 }
246 else {
247 newProg = (struct ati_fragment_shader *)
248 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
249 if (!newProg || newProg == &DummyShader) {
250 /* allocate a new program now */
251 newProg = _mesa_new_ati_fragment_shader(ctx, id);
252 if (!newProg) {
253 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
254 return;
255 }
256 _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
257 }
258
259 }
260
261 /* do actual bind */
262 ctx->ATIFragmentShader.Current = newProg;
263
264 assert(ctx->ATIFragmentShader.Current);
265 if (newProg)
266 newProg->RefCount++;
267 }
268
269 void GLAPIENTRY
270 _mesa_DeleteFragmentShaderATI(GLuint id)
271 {
272 GET_CURRENT_CONTEXT(ctx);
273
274 if (ctx->ATIFragmentShader.Compiling) {
275 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
276 return;
277 }
278
279 if (id != 0) {
280 struct ati_fragment_shader *prog = (struct ati_fragment_shader *)
281 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
282 if (prog == &DummyShader) {
283 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
284 }
285 else if (prog) {
286 if (ctx->ATIFragmentShader.Current &&
287 ctx->ATIFragmentShader.Current->Id == id) {
288 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
289 _mesa_BindFragmentShaderATI(0);
290 }
291 }
292
293 /* The ID is immediately available for re-use now */
294 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
295 if (prog) {
296 prog->RefCount--;
297 if (prog->RefCount <= 0) {
298 assert(prog != &DummyShader);
299 _mesa_delete_ati_fragment_shader(ctx, prog);
300 }
301 }
302 }
303 }
304
305
306 void GLAPIENTRY
307 _mesa_BeginFragmentShaderATI(void)
308 {
309 GLint i;
310 GET_CURRENT_CONTEXT(ctx);
311
312 if (ctx->ATIFragmentShader.Compiling) {
313 _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
314 return;
315 }
316
317 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
318
319 /* if the shader was already defined free instructions and get new ones
320 (or, could use the same mem but would need to reinitialize) */
321 /* no idea if it's allowed to redefine a shader */
322 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
323 free(ctx->ATIFragmentShader.Current->Instructions[i]);
324 free(ctx->ATIFragmentShader.Current->SetupInst[i]);
325 }
326
327 _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, NULL);
328
329 /* malloc the instructions here - not sure if the best place but its
330 a start */
331 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
332 ctx->ATIFragmentShader.Current->Instructions[i] =
333 calloc(sizeof(struct atifs_instruction),
334 MAX_NUM_INSTRUCTIONS_PER_PASS_ATI);
335 ctx->ATIFragmentShader.Current->SetupInst[i] =
336 calloc(sizeof(struct atifs_setupinst),
337 MAX_NUM_FRAGMENT_REGISTERS_ATI);
338 }
339
340 /* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
341 ctx->ATIFragmentShader.Current->LocalConstDef = 0;
342 ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
343 ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
344 ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
345 ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
346 ctx->ATIFragmentShader.Current->NumPasses = 0;
347 ctx->ATIFragmentShader.Current->cur_pass = 0;
348 ctx->ATIFragmentShader.Current->last_optype = 0;
349 ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
350 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
351 ctx->ATIFragmentShader.Current->swizzlerq = 0;
352 ctx->ATIFragmentShader.Compiling = 1;
353 #if MESA_DEBUG_ATI_FS
354 _mesa_debug(ctx, "%s %u\n", __func__, ctx->ATIFragmentShader.Current->Id);
355 #endif
356 }
357
358 void GLAPIENTRY
359 _mesa_EndFragmentShaderATI(void)
360 {
361 GET_CURRENT_CONTEXT(ctx);
362 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
363 #if MESA_DEBUG_ATI_FS
364 GLint i, j;
365 #endif
366
367 if (!ctx->ATIFragmentShader.Compiling) {
368 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
369 return;
370 }
371 if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
372 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
373 /* according to spec, DON'T return here */
374 }
375
376 match_pair_inst(curProg, 0);
377 ctx->ATIFragmentShader.Compiling = 0;
378 ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
379 if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
380 (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
381 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
382 }
383 if (ctx->ATIFragmentShader.Current->cur_pass > 1)
384 ctx->ATIFragmentShader.Current->NumPasses = 2;
385 else
386 ctx->ATIFragmentShader.Current->NumPasses = 1;
387
388 ctx->ATIFragmentShader.Current->cur_pass = 0;
389
390 #if MESA_DEBUG_ATI_FS
391 for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
392 for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
393 GLuint op = curProg->SetupInst[j][i].Opcode;
394 const char *op_enum = op > 5 ? _mesa_enum_to_string(op) : "0";
395 GLuint src = curProg->SetupInst[j][i].src;
396 GLuint swizzle = curProg->SetupInst[j][i].swizzle;
397 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
398 swizzle);
399 }
400 for (i = 0; i < curProg->numArithInstr[j]; i++) {
401 GLuint op0 = curProg->Instructions[j][i].Opcode[0];
402 GLuint op1 = curProg->Instructions[j][i].Opcode[1];
403 const char *op0_enum = op0 > 5 ? _mesa_enum_to_string(op0) : "0";
404 const char *op1_enum = op1 > 5 ? _mesa_enum_to_string(op1) : "0";
405 GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
406 GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
407 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
408 op1, op1_enum, count1);
409 }
410 }
411 #endif
412
413 if (ctx->Driver.NewATIfs) {
414 struct gl_program *prog = ctx->Driver.NewATIfs(ctx,
415 ctx->ATIFragmentShader.Current);
416 _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, prog);
417 }
418
419 if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI,
420 curProg->Program)) {
421 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
422 /* XXX is this the right error? */
423 _mesa_error(ctx, GL_INVALID_OPERATION,
424 "glEndFragmentShaderATI(driver rejected shader)");
425 }
426 }
427
428 void GLAPIENTRY
429 _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
430 {
431 GET_CURRENT_CONTEXT(ctx);
432 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
433 struct atifs_setupinst *curI;
434
435 if (!ctx->ATIFragmentShader.Compiling) {
436 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
437 return;
438 }
439
440 if (curProg->cur_pass == 1) {
441 match_pair_inst(curProg, 0);
442 curProg->cur_pass = 2;
443 }
444 if ((curProg->cur_pass > 2) ||
445 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
446 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
447 return;
448 }
449 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
450 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
451 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
452 return;
453 }
454 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
455 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
456 ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
457 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
458 return;
459 }
460 if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
461 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
462 return;
463 }
464 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
465 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
466 return;
467 }
468 if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
469 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
470 return;
471 }
472 if (coord <= GL_TEXTURE7_ARB) {
473 GLuint tmp = coord - GL_TEXTURE0_ARB;
474 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
475 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
476 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
477 return;
478 } else {
479 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
480 }
481 }
482
483 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
484 new_tex_inst(curProg);
485
486 /* add the instructions */
487 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
488
489 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
490 curI->src = coord;
491 curI->swizzle = swizzle;
492
493 #if MESA_DEBUG_ATI_FS
494 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
495 _mesa_enum_to_string(dst), _mesa_enum_to_string(coord),
496 _mesa_enum_to_string(swizzle));
497 #endif
498 }
499
500 void GLAPIENTRY
501 _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
502 {
503 GET_CURRENT_CONTEXT(ctx);
504 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
505 struct atifs_setupinst *curI;
506
507 if (!ctx->ATIFragmentShader.Compiling) {
508 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
509 return;
510 }
511
512 if (curProg->cur_pass == 1) {
513 match_pair_inst(curProg, 0);
514 curProg->cur_pass = 2;
515 }
516 if ((curProg->cur_pass > 2) ||
517 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
518 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
519 return;
520 }
521 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
522 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
523 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
524 return;
525 }
526 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
527 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
528 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
529 /* is this texture5 or texture7? spec is a bit unclear there */
530 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
531 return;
532 }
533 if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
534 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
535 return;
536 }
537 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
538 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
539 return;
540 }
541 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
542 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
543 return;
544 }
545 if (interp <= GL_TEXTURE7_ARB) {
546 GLuint tmp = interp - GL_TEXTURE0_ARB;
547 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
548 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
549 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
550 return;
551 } else {
552 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
553 }
554 }
555
556 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
557 new_tex_inst(curProg);
558
559 /* add the instructions */
560 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
561
562 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
563 curI->src = interp;
564 curI->swizzle = swizzle;
565
566 #if MESA_DEBUG_ATI_FS
567 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
568 _mesa_enum_to_string(dst), _mesa_enum_to_string(interp),
569 _mesa_enum_to_string(swizzle));
570 #endif
571 }
572
573 static void
574 _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
575 GLuint dstMask, GLuint dstMod, GLuint arg1,
576 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
577 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
578 GLuint arg3Rep, GLuint arg3Mod)
579 {
580 GET_CURRENT_CONTEXT(ctx);
581 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
582 GLint ci;
583 struct atifs_instruction *curI;
584 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
585
586 if (!ctx->ATIFragmentShader.Compiling) {
587 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
588 return;
589 }
590
591 if (curProg->cur_pass==0)
592 curProg->cur_pass=1;
593
594 else if (curProg->cur_pass==2)
595 curProg->cur_pass=3;
596
597 /* decide whether this is a new instruction or not ... all color instructions are new,
598 and alpha instructions might also be new if there was no preceding color inst */
599 if ((optype == 0) || (curProg->last_optype == optype)) {
600 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
601 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
602 return;
603 }
604 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
605 match_pair_inst(curProg, optype);
606 new_arith_inst(curProg);
607 }
608 curProg->last_optype = optype;
609 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
610
611 /* add the instructions */
612 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
613
614 /* error checking */
615 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
616 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
617 return;
618 }
619 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
620 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
621 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
622 (modtemp != GL_EIGHTH_BIT_ATI)) {
623 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
624 return;
625 }
626 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
627 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
628 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
629 return;
630 }
631 if (optype == 1) {
632 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
633 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
634 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
635 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
636 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
637 return;
638 }
639 }
640 if ((op == GL_DOT4_ATI) &&
641 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
642 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
643 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
644 }
645
646 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
647 return;
648 }
649 if (arg2) {
650 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
651 return;
652 }
653 }
654 if (arg3) {
655 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
656 return;
657 }
658 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
659 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
660 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
661 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
662 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
663 return;
664 }
665 }
666
667 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
668
669 curI->Opcode[optype] = op;
670 curI->SrcReg[optype][0].Index = arg1;
671 curI->SrcReg[optype][0].argRep = arg1Rep;
672 curI->SrcReg[optype][0].argMod = arg1Mod;
673 curI->ArgCount[optype] = arg_count;
674
675 if (arg2) {
676 curI->SrcReg[optype][1].Index = arg2;
677 curI->SrcReg[optype][1].argRep = arg2Rep;
678 curI->SrcReg[optype][1].argMod = arg2Mod;
679 }
680
681 if (arg3) {
682 curI->SrcReg[optype][2].Index = arg3;
683 curI->SrcReg[optype][2].argRep = arg3Rep;
684 curI->SrcReg[optype][2].argMod = arg3Mod;
685 }
686
687 curI->DstReg[optype].Index = dst;
688 curI->DstReg[optype].dstMod = dstMod;
689 curI->DstReg[optype].dstMask = dstMask;
690
691 #if MESA_DEBUG_ATI_FS
692 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
693 #endif
694
695 }
696
697 void GLAPIENTRY
698 _mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
699 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
700 GLuint arg1Mod)
701 {
702 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
703 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
704 }
705
706 void GLAPIENTRY
707 _mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
708 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
709 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
710 GLuint arg2Mod)
711 {
712 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
713 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
714 arg2Mod, 0, 0, 0);
715 }
716
717 void GLAPIENTRY
718 _mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
719 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
720 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
721 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
722 GLuint arg3Mod)
723 {
724 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
725 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
726 arg2Mod, arg3, arg3Rep, arg3Mod);
727 }
728
729 void GLAPIENTRY
730 _mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
731 GLuint arg1Rep, GLuint arg1Mod)
732 {
733 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
734 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
735 }
736
737 void GLAPIENTRY
738 _mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
739 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
740 GLuint arg2Rep, GLuint arg2Mod)
741 {
742 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
743 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
744 0);
745 }
746
747 void GLAPIENTRY
748 _mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
749 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
750 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
751 GLuint arg3Rep, GLuint arg3Mod)
752 {
753 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
754 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
755 arg3Rep, arg3Mod);
756 }
757
758 void GLAPIENTRY
759 _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
760 {
761 GLuint dstindex;
762 GET_CURRENT_CONTEXT(ctx);
763
764 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
765 /* spec says nothing about what should happen here but we can't just segfault...*/
766 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
767 return;
768 }
769
770 dstindex = dst - GL_CON_0_ATI;
771 if (ctx->ATIFragmentShader.Compiling) {
772 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
773 COPY_4V(curProg->Constants[dstindex], value);
774 curProg->LocalConstDef |= 1 << dstindex;
775 }
776 else {
777 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
778 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
779 }
780 }