glapi / teximage: implement EGLImageTargetTexStorageEXT
[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,
415 NULL);
416 /* Don't use _mesa_reference_program(), just take ownership */
417 ctx->ATIFragmentShader.Current->Program = prog;
418 }
419
420 if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI,
421 curProg->Program)) {
422 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
423 /* XXX is this the right error? */
424 _mesa_error(ctx, GL_INVALID_OPERATION,
425 "glEndFragmentShaderATI(driver rejected shader)");
426 }
427 }
428
429 void GLAPIENTRY
430 _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
431 {
432 GET_CURRENT_CONTEXT(ctx);
433 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
434 struct atifs_setupinst *curI;
435 GLubyte new_pass = curProg->cur_pass;
436
437 if (!ctx->ATIFragmentShader.Compiling) {
438 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
439 return;
440 }
441
442 if (curProg->cur_pass == 1)
443 new_pass = 2;
444 if ((new_pass > 2) ||
445 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[new_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 ((new_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 if (curProg->cur_pass == 1)
484 match_pair_inst(curProg, 0);
485 curProg->cur_pass = new_pass;
486 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
487
488 /* add the instructions */
489 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
490
491 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
492 curI->src = coord;
493 curI->swizzle = swizzle;
494
495 #if MESA_DEBUG_ATI_FS
496 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
497 _mesa_enum_to_string(dst), _mesa_enum_to_string(coord),
498 _mesa_enum_to_string(swizzle));
499 #endif
500 }
501
502 void GLAPIENTRY
503 _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
504 {
505 GET_CURRENT_CONTEXT(ctx);
506 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
507 struct atifs_setupinst *curI;
508 GLubyte new_pass = curProg->cur_pass;
509
510 if (!ctx->ATIFragmentShader.Compiling) {
511 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
512 return;
513 }
514
515 if (curProg->cur_pass == 1)
516 new_pass = 2;
517 if ((new_pass > 2) ||
518 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[new_pass >> 1])) {
519 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
520 return;
521 }
522 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
523 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
524 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
525 return;
526 }
527 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
528 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
529 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
530 /* is this texture5 or texture7? spec is a bit unclear there */
531 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
532 return;
533 }
534 if ((new_pass == 0) && (interp >= GL_REG_0_ATI)) {
535 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
536 return;
537 }
538 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
539 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
540 return;
541 }
542 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
543 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
544 return;
545 }
546 if (interp <= GL_TEXTURE7_ARB) {
547 GLuint tmp = interp - GL_TEXTURE0_ARB;
548 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
549 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
550 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
551 return;
552 } else {
553 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
554 }
555 }
556
557 if (curProg->cur_pass == 1)
558 match_pair_inst(curProg, 0);
559 curProg->cur_pass = new_pass;
560 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
561
562 /* add the instructions */
563 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
564
565 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
566 curI->src = interp;
567 curI->swizzle = swizzle;
568
569 #if MESA_DEBUG_ATI_FS
570 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
571 _mesa_enum_to_string(dst), _mesa_enum_to_string(interp),
572 _mesa_enum_to_string(swizzle));
573 #endif
574 }
575
576 static void
577 _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
578 GLuint dstMask, GLuint dstMod, GLuint arg1,
579 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
580 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
581 GLuint arg3Rep, GLuint arg3Mod)
582 {
583 GET_CURRENT_CONTEXT(ctx);
584 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
585 GLint ci;
586 struct atifs_instruction *curI;
587 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
588 GLubyte new_pass = curProg->cur_pass;
589 GLubyte numArithInstr;
590
591 if (!ctx->ATIFragmentShader.Compiling) {
592 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
593 return;
594 }
595
596 if (curProg->cur_pass == 0)
597 new_pass = 1;
598 else if (curProg->cur_pass == 2)
599 new_pass = 3;
600
601 numArithInstr = curProg->numArithInstr[new_pass >> 1];
602
603 /* Decide whether this is a new instruction or not. All color instructions
604 * are new, and alpha instructions might also be new if there was no
605 * preceding color inst. This may also be the first inst of the pass
606 */
607 if (optype == ATI_FRAGMENT_SHADER_COLOR_OP ||
608 curProg->last_optype == optype ||
609 curProg->numArithInstr[new_pass >> 1] == 0) {
610 if (curProg->numArithInstr[new_pass >> 1] > 7) {
611 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
612 return;
613 }
614 numArithInstr++;
615 }
616 ci = numArithInstr - 1;
617 curI = &curProg->Instructions[new_pass >> 1][ci];
618
619 /* error checking */
620 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
621 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
622 return;
623 }
624 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
625 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
626 (modtemp != GL_HALF_BIT_ATI) && (modtemp != GL_QUARTER_BIT_ATI) &&
627 (modtemp != GL_EIGHTH_BIT_ATI)) {
628 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
629 return;
630 }
631 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
632 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
633 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
634 return;
635 }
636 if (optype == ATI_FRAGMENT_SHADER_ALPHA_OP) {
637 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
638 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
639 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
640 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
641 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
642 return;
643 }
644 }
645 /* The ATI_fragment_shader spec says:
646 *
647 * The error INVALID_OPERATION is generated by... ColorFragmentOp2ATI
648 * if <op> is DOT4_ATI and <argN> is SECONDARY_INTERPOLATOR_ATI and
649 * <argNRep> is ALPHA or NONE.
650 */
651 if (optype == ATI_FRAGMENT_SHADER_COLOR_OP && op == GL_DOT4_ATI &&
652 ((arg1 == GL_SECONDARY_INTERPOLATOR_ATI && (arg1Rep == GL_ALPHA || arg1Rep == GL_NONE)) ||
653 (arg2 == GL_SECONDARY_INTERPOLATOR_ATI && (arg2Rep == GL_ALPHA || arg2Rep == GL_NONE)))) {
654 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interpDOT4)");
655 return;
656 }
657
658 if (!check_arith_arg(optype, arg1, arg1Rep)) {
659 return;
660 }
661 if (arg2) {
662 if (!check_arith_arg(optype, arg2, arg2Rep)) {
663 return;
664 }
665 }
666 if (arg3) {
667 if (!check_arith_arg(optype, arg3, arg3Rep)) {
668 return;
669 }
670 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
671 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
672 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
673 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
674 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
675 return;
676 }
677 }
678
679 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
680
681 curProg->interpinp1 |= check_arg_color(new_pass, arg1);
682 if (arg2)
683 curProg->interpinp1 |= check_arg_color(new_pass, arg2);
684 if (arg3)
685 curProg->interpinp1 |= check_arg_color(new_pass, arg3);
686
687 curProg->numArithInstr[new_pass >> 1] = numArithInstr;
688 curProg->last_optype = optype;
689 curProg->cur_pass = new_pass;
690
691 curI->Opcode[optype] = op;
692 curI->SrcReg[optype][0].Index = arg1;
693 curI->SrcReg[optype][0].argRep = arg1Rep;
694 curI->SrcReg[optype][0].argMod = arg1Mod;
695 curI->ArgCount[optype] = arg_count;
696
697 if (arg2) {
698 curI->SrcReg[optype][1].Index = arg2;
699 curI->SrcReg[optype][1].argRep = arg2Rep;
700 curI->SrcReg[optype][1].argMod = arg2Mod;
701 }
702
703 if (arg3) {
704 curI->SrcReg[optype][2].Index = arg3;
705 curI->SrcReg[optype][2].argRep = arg3Rep;
706 curI->SrcReg[optype][2].argMod = arg3Mod;
707 }
708
709 curI->DstReg[optype].Index = dst;
710 curI->DstReg[optype].dstMod = dstMod;
711 curI->DstReg[optype].dstMask = dstMask;
712
713 #if MESA_DEBUG_ATI_FS
714 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
715 #endif
716
717 }
718
719 void GLAPIENTRY
720 _mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
721 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
722 GLuint arg1Mod)
723 {
724 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
725 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
726 }
727
728 void GLAPIENTRY
729 _mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
730 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
731 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
732 GLuint arg2Mod)
733 {
734 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
735 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
736 arg2Mod, 0, 0, 0);
737 }
738
739 void GLAPIENTRY
740 _mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
741 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
742 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
743 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
744 GLuint arg3Mod)
745 {
746 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
747 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
748 arg2Mod, arg3, arg3Rep, arg3Mod);
749 }
750
751 void GLAPIENTRY
752 _mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
753 GLuint arg1Rep, GLuint arg1Mod)
754 {
755 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
756 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
757 }
758
759 void GLAPIENTRY
760 _mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
761 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
762 GLuint arg2Rep, GLuint arg2Mod)
763 {
764 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
765 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
766 0);
767 }
768
769 void GLAPIENTRY
770 _mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
771 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
772 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
773 GLuint arg3Rep, GLuint arg3Mod)
774 {
775 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
776 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
777 arg3Rep, arg3Mod);
778 }
779
780 void GLAPIENTRY
781 _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
782 {
783 GLuint dstindex;
784 GET_CURRENT_CONTEXT(ctx);
785
786 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
787 /* spec says nothing about what should happen here but we can't just segfault...*/
788 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
789 return;
790 }
791
792 dstindex = dst - GL_CON_0_ATI;
793 if (ctx->ATIFragmentShader.Compiling) {
794 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
795 COPY_4V(curProg->Constants[dstindex], value);
796 curProg->LocalConstDef |= 1 << dstindex;
797 }
798 else {
799 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
800 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
801 }
802 }