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