Merge remote-tracking branch 'public/master' into vulkan
[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 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
205 for (i = 0; i < range; i++) {
206 _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
207 }
208
209 return first;
210 }
211
212 void GLAPIENTRY
213 _mesa_BindFragmentShaderATI(GLuint id)
214 {
215 GET_CURRENT_CONTEXT(ctx);
216 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
217 struct ati_fragment_shader *newProg;
218
219 if (ctx->ATIFragmentShader.Compiling) {
220 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
221 return;
222 }
223
224 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
225
226 if (curProg->Id == id) {
227 return;
228 }
229
230 /* unbind current */
231 if (curProg->Id != 0) {
232 curProg->RefCount--;
233 if (curProg->RefCount <= 0) {
234 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
235 }
236 }
237
238 /* find new shader */
239 if (id == 0) {
240 newProg = ctx->Shared->DefaultFragmentShader;
241 }
242 else {
243 newProg = (struct ati_fragment_shader *)
244 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
245 if (!newProg || newProg == &DummyShader) {
246 /* allocate a new program now */
247 newProg = _mesa_new_ati_fragment_shader(ctx, id);
248 if (!newProg) {
249 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
250 return;
251 }
252 _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
253 }
254
255 }
256
257 /* do actual bind */
258 ctx->ATIFragmentShader.Current = newProg;
259
260 assert(ctx->ATIFragmentShader.Current);
261 if (newProg)
262 newProg->RefCount++;
263
264 /*if (ctx->Driver.BindProgram)
265 ctx->Driver.BindProgram(ctx, target, prog); */
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 assert(prog != &DummyShader);
298 _mesa_delete_ati_fragment_shader(ctx, prog);
299 }
300 }
301 }
302 }
303
304
305 void GLAPIENTRY
306 _mesa_BeginFragmentShaderATI(void)
307 {
308 GLint i;
309 GET_CURRENT_CONTEXT(ctx);
310
311 if (ctx->ATIFragmentShader.Compiling) {
312 _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
313 return;
314 }
315
316 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
317
318 /* if the shader was already defined free instructions and get new ones
319 (or, could use the same mem but would need to reinitialize) */
320 /* no idea if it's allowed to redefine a shader */
321 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
322 free(ctx->ATIFragmentShader.Current->Instructions[i]);
323 free(ctx->ATIFragmentShader.Current->SetupInst[i]);
324 }
325
326 _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, NULL);
327
328 /* malloc the instructions here - not sure if the best place but its
329 a start */
330 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
331 ctx->ATIFragmentShader.Current->Instructions[i] =
332 calloc(sizeof(struct atifs_instruction),
333 MAX_NUM_INSTRUCTIONS_PER_PASS_ATI);
334 ctx->ATIFragmentShader.Current->SetupInst[i] =
335 calloc(sizeof(struct atifs_setupinst),
336 MAX_NUM_FRAGMENT_REGISTERS_ATI);
337 }
338
339 /* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
340 ctx->ATIFragmentShader.Current->LocalConstDef = 0;
341 ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
342 ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
343 ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
344 ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
345 ctx->ATIFragmentShader.Current->NumPasses = 0;
346 ctx->ATIFragmentShader.Current->cur_pass = 0;
347 ctx->ATIFragmentShader.Current->last_optype = 0;
348 ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
349 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
350 ctx->ATIFragmentShader.Current->swizzlerq = 0;
351 ctx->ATIFragmentShader.Compiling = 1;
352 #if MESA_DEBUG_ATI_FS
353 _mesa_debug(ctx, "%s %u\n", __func__, ctx->ATIFragmentShader.Current->Id);
354 #endif
355 }
356
357 void GLAPIENTRY
358 _mesa_EndFragmentShaderATI(void)
359 {
360 GET_CURRENT_CONTEXT(ctx);
361 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
362 #if MESA_DEBUG_ATI_FS
363 GLint i, j;
364 #endif
365
366 if (!ctx->ATIFragmentShader.Compiling) {
367 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
368 return;
369 }
370 if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
371 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
372 /* according to spec, DON'T return here */
373 }
374
375 match_pair_inst(curProg, 0);
376 ctx->ATIFragmentShader.Compiling = 0;
377 ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
378 if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
379 (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
380 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
381 }
382 if (ctx->ATIFragmentShader.Current->cur_pass > 1)
383 ctx->ATIFragmentShader.Current->NumPasses = 2;
384 else
385 ctx->ATIFragmentShader.Current->NumPasses = 1;
386
387 ctx->ATIFragmentShader.Current->cur_pass = 0;
388
389 #if MESA_DEBUG_ATI_FS
390 for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
391 for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
392 GLuint op = curProg->SetupInst[j][i].Opcode;
393 const char *op_enum = op > 5 ? _mesa_enum_to_string(op) : "0";
394 GLuint src = curProg->SetupInst[j][i].src;
395 GLuint swizzle = curProg->SetupInst[j][i].swizzle;
396 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
397 swizzle);
398 }
399 for (i = 0; i < curProg->numArithInstr[j]; i++) {
400 GLuint op0 = curProg->Instructions[j][i].Opcode[0];
401 GLuint op1 = curProg->Instructions[j][i].Opcode[1];
402 const char *op0_enum = op0 > 5 ? _mesa_enum_to_string(op0) : "0";
403 const char *op1_enum = op1 > 5 ? _mesa_enum_to_string(op1) : "0";
404 GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
405 GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
406 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
407 op1, op1_enum, count1);
408 }
409 }
410 #endif
411
412 if (ctx->Driver.NewATIfs) {
413 struct gl_program *prog = ctx->Driver.NewATIfs(ctx,
414 ctx->ATIFragmentShader.Current);
415 _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, prog);
416 }
417
418 if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI,
419 curProg->Program)) {
420 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
421 /* XXX is this the right error? */
422 _mesa_error(ctx, GL_INVALID_OPERATION,
423 "glEndFragmentShaderATI(driver rejected shader)");
424 }
425 }
426
427 void GLAPIENTRY
428 _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
429 {
430 GET_CURRENT_CONTEXT(ctx);
431 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
432 struct atifs_setupinst *curI;
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 match_pair_inst(curProg, 0);
441 curProg->cur_pass = 2;
442 }
443 if ((curProg->cur_pass > 2) ||
444 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
445 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
446 return;
447 }
448 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
449 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
450 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
451 return;
452 }
453 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
454 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
455 ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
456 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
457 return;
458 }
459 if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
460 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
461 return;
462 }
463 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
464 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
465 return;
466 }
467 if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
468 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
469 return;
470 }
471 if (coord <= GL_TEXTURE7_ARB) {
472 GLuint tmp = coord - GL_TEXTURE0_ARB;
473 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
474 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
475 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
476 return;
477 } else {
478 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
479 }
480 }
481
482 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
483 new_tex_inst(curProg);
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
506 if (!ctx->ATIFragmentShader.Compiling) {
507 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
508 return;
509 }
510
511 if (curProg->cur_pass == 1) {
512 match_pair_inst(curProg, 0);
513 curProg->cur_pass = 2;
514 }
515 if ((curProg->cur_pass > 2) ||
516 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
517 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
518 return;
519 }
520 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
521 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
522 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
523 return;
524 }
525 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
526 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
527 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
528 /* is this texture5 or texture7? spec is a bit unclear there */
529 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
530 return;
531 }
532 if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
533 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
534 return;
535 }
536 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
537 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
538 return;
539 }
540 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
541 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
542 return;
543 }
544 if (interp <= GL_TEXTURE7_ARB) {
545 GLuint tmp = interp - GL_TEXTURE0_ARB;
546 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
547 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
548 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
549 return;
550 } else {
551 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
552 }
553 }
554
555 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
556 new_tex_inst(curProg);
557
558 /* add the instructions */
559 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
560
561 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
562 curI->src = interp;
563 curI->swizzle = swizzle;
564
565 #if MESA_DEBUG_ATI_FS
566 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
567 _mesa_enum_to_string(dst), _mesa_enum_to_string(interp),
568 _mesa_enum_to_string(swizzle));
569 #endif
570 }
571
572 static void
573 _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
574 GLuint dstMask, GLuint dstMod, GLuint arg1,
575 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
576 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
577 GLuint arg3Rep, GLuint arg3Mod)
578 {
579 GET_CURRENT_CONTEXT(ctx);
580 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
581 GLint ci;
582 struct atifs_instruction *curI;
583 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
584
585 if (!ctx->ATIFragmentShader.Compiling) {
586 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
587 return;
588 }
589
590 if (curProg->cur_pass==0)
591 curProg->cur_pass=1;
592
593 else if (curProg->cur_pass==2)
594 curProg->cur_pass=3;
595
596 /* decide whether this is a new instruction or not ... all color instructions are new,
597 and alpha instructions might also be new if there was no preceding color inst */
598 if ((optype == 0) || (curProg->last_optype == optype)) {
599 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
600 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
601 return;
602 }
603 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
604 match_pair_inst(curProg, optype);
605 new_arith_inst(curProg);
606 }
607 curProg->last_optype = optype;
608 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
609
610 /* add the instructions */
611 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
612
613 /* error checking */
614 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
615 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
616 return;
617 }
618 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
619 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
620 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
621 (modtemp != GL_EIGHTH_BIT_ATI)) {
622 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
623 return;
624 }
625 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
626 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
627 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
628 return;
629 }
630 if (optype == 1) {
631 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
632 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
633 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
634 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
635 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
636 return;
637 }
638 }
639 if ((op == GL_DOT4_ATI) &&
640 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
641 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
642 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
643 }
644
645 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
646 return;
647 }
648 if (arg2) {
649 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
650 return;
651 }
652 }
653 if (arg3) {
654 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
655 return;
656 }
657 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
658 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
659 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
660 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
661 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
662 return;
663 }
664 }
665
666 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
667
668 curI->Opcode[optype] = op;
669 curI->SrcReg[optype][0].Index = arg1;
670 curI->SrcReg[optype][0].argRep = arg1Rep;
671 curI->SrcReg[optype][0].argMod = arg1Mod;
672 curI->ArgCount[optype] = arg_count;
673
674 if (arg2) {
675 curI->SrcReg[optype][1].Index = arg2;
676 curI->SrcReg[optype][1].argRep = arg2Rep;
677 curI->SrcReg[optype][1].argMod = arg2Mod;
678 }
679
680 if (arg3) {
681 curI->SrcReg[optype][2].Index = arg3;
682 curI->SrcReg[optype][2].argRep = arg3Rep;
683 curI->SrcReg[optype][2].argMod = arg3Mod;
684 }
685
686 curI->DstReg[optype].Index = dst;
687 curI->DstReg[optype].dstMod = dstMod;
688 curI->DstReg[optype].dstMask = dstMask;
689
690 #if MESA_DEBUG_ATI_FS
691 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
692 #endif
693
694 }
695
696 void GLAPIENTRY
697 _mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
698 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
699 GLuint arg1Mod)
700 {
701 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
702 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
703 }
704
705 void GLAPIENTRY
706 _mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
707 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
708 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
709 GLuint arg2Mod)
710 {
711 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
712 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
713 arg2Mod, 0, 0, 0);
714 }
715
716 void GLAPIENTRY
717 _mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
718 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
719 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
720 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
721 GLuint arg3Mod)
722 {
723 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
724 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
725 arg2Mod, arg3, arg3Rep, arg3Mod);
726 }
727
728 void GLAPIENTRY
729 _mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
730 GLuint arg1Rep, GLuint arg1Mod)
731 {
732 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
733 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
734 }
735
736 void GLAPIENTRY
737 _mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
738 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
739 GLuint arg2Rep, GLuint arg2Mod)
740 {
741 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
742 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
743 0);
744 }
745
746 void GLAPIENTRY
747 _mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
748 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
749 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
750 GLuint arg3Rep, GLuint arg3Mod)
751 {
752 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
753 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
754 arg3Rep, arg3Mod);
755 }
756
757 void GLAPIENTRY
758 _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
759 {
760 GLuint dstindex;
761 GET_CURRENT_CONTEXT(ctx);
762
763 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
764 /* spec says nothing about what should happen here but we can't just segfault...*/
765 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
766 return;
767 }
768
769 dstindex = dst - GL_CON_0_ATI;
770 if (ctx->ATIFragmentShader.Compiling) {
771 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
772 COPY_4V(curProg->Constants[dstindex], value);
773 curProg->LocalConstDef |= 1 << dstindex;
774 }
775 else {
776 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
777 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
778 }
779 }