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 *
_mesa_new_ati_fragment_shader(struct gl_context * ctx,GLuint id)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
_mesa_delete_ati_fragment_shader(struct gl_context * ctx,struct ati_fragment_shader * s)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
new_arith_inst(struct ati_fragment_shader * prog)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
new_tex_inst(struct ati_fragment_shader * prog)83 new_tex_inst(struct ati_fragment_shader *prog)
84 {
85 }
86
match_pair_inst(struct ati_fragment_shader * curProg,GLuint optype)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 *
create_dst_mod_str(GLuint mod)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
debug_op(GLint optype,GLuint arg_count,GLenum op,GLuint dst,GLuint dstMask,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod,GLuint arg3,GLuint arg3Rep,GLuint arg3Mod)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
check_arith_arg(struct ati_fragment_shader * curProg,GLuint optype,GLuint arg,GLuint argRep)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
_mesa_GenFragmentShadersATI(GLuint range)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
_mesa_BindFragmentShaderATI(GLuint id)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 /*if (ctx->Driver.BindProgram)
269 ctx->Driver.BindProgram(ctx, target, prog); */
270 }
271
272 void GLAPIENTRY
_mesa_DeleteFragmentShaderATI(GLuint id)273 _mesa_DeleteFragmentShaderATI(GLuint id)
274 {
275 GET_CURRENT_CONTEXT(ctx);
276
277 if (ctx->ATIFragmentShader.Compiling) {
278 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
279 return;
280 }
281
282 if (id != 0) {
283 struct ati_fragment_shader *prog = (struct ati_fragment_shader *)
284 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
285 if (prog == &DummyShader) {
286 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
287 }
288 else if (prog) {
289 if (ctx->ATIFragmentShader.Current &&
290 ctx->ATIFragmentShader.Current->Id == id) {
291 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
292 _mesa_BindFragmentShaderATI(0);
293 }
294 }
295
296 /* The ID is immediately available for re-use now */
297 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
298 if (prog) {
299 prog->RefCount--;
300 if (prog->RefCount <= 0) {
301 assert(prog != &DummyShader);
302 _mesa_delete_ati_fragment_shader(ctx, prog);
303 }
304 }
305 }
306 }
307
308
309 void GLAPIENTRY
_mesa_BeginFragmentShaderATI(void)310 _mesa_BeginFragmentShaderATI(void)
311 {
312 GLint i;
313 GET_CURRENT_CONTEXT(ctx);
314
315 if (ctx->ATIFragmentShader.Compiling) {
316 _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
317 return;
318 }
319
320 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
321
322 /* if the shader was already defined free instructions and get new ones
323 (or, could use the same mem but would need to reinitialize) */
324 /* no idea if it's allowed to redefine a shader */
325 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
326 free(ctx->ATIFragmentShader.Current->Instructions[i]);
327 free(ctx->ATIFragmentShader.Current->SetupInst[i]);
328 }
329
330 _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, NULL);
331
332 /* malloc the instructions here - not sure if the best place but its
333 a start */
334 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
335 ctx->ATIFragmentShader.Current->Instructions[i] =
336 calloc(sizeof(struct atifs_instruction),
337 MAX_NUM_INSTRUCTIONS_PER_PASS_ATI);
338 ctx->ATIFragmentShader.Current->SetupInst[i] =
339 calloc(sizeof(struct atifs_setupinst),
340 MAX_NUM_FRAGMENT_REGISTERS_ATI);
341 }
342
343 /* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
344 ctx->ATIFragmentShader.Current->LocalConstDef = 0;
345 ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
346 ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
347 ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
348 ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
349 ctx->ATIFragmentShader.Current->NumPasses = 0;
350 ctx->ATIFragmentShader.Current->cur_pass = 0;
351 ctx->ATIFragmentShader.Current->last_optype = 0;
352 ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
353 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
354 ctx->ATIFragmentShader.Current->swizzlerq = 0;
355 ctx->ATIFragmentShader.Compiling = 1;
356 #if MESA_DEBUG_ATI_FS
357 _mesa_debug(ctx, "%s %u\n", __func__, ctx->ATIFragmentShader.Current->Id);
358 #endif
359 }
360
361 void GLAPIENTRY
_mesa_EndFragmentShaderATI(void)362 _mesa_EndFragmentShaderATI(void)
363 {
364 GET_CURRENT_CONTEXT(ctx);
365 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
366 #if MESA_DEBUG_ATI_FS
367 GLint i, j;
368 #endif
369
370 if (!ctx->ATIFragmentShader.Compiling) {
371 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
372 return;
373 }
374 if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
375 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
376 /* according to spec, DON'T return here */
377 }
378
379 match_pair_inst(curProg, 0);
380 ctx->ATIFragmentShader.Compiling = 0;
381 ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
382 if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
383 (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
384 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
385 }
386 if (ctx->ATIFragmentShader.Current->cur_pass > 1)
387 ctx->ATIFragmentShader.Current->NumPasses = 2;
388 else
389 ctx->ATIFragmentShader.Current->NumPasses = 1;
390
391 ctx->ATIFragmentShader.Current->cur_pass = 0;
392
393 #if MESA_DEBUG_ATI_FS
394 for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
395 for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
396 GLuint op = curProg->SetupInst[j][i].Opcode;
397 const char *op_enum = op > 5 ? _mesa_enum_to_string(op) : "0";
398 GLuint src = curProg->SetupInst[j][i].src;
399 GLuint swizzle = curProg->SetupInst[j][i].swizzle;
400 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
401 swizzle);
402 }
403 for (i = 0; i < curProg->numArithInstr[j]; i++) {
404 GLuint op0 = curProg->Instructions[j][i].Opcode[0];
405 GLuint op1 = curProg->Instructions[j][i].Opcode[1];
406 const char *op0_enum = op0 > 5 ? _mesa_enum_to_string(op0) : "0";
407 const char *op1_enum = op1 > 5 ? _mesa_enum_to_string(op1) : "0";
408 GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
409 GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
410 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
411 op1, op1_enum, count1);
412 }
413 }
414 #endif
415
416 if (ctx->Driver.NewATIfs) {
417 struct gl_program *prog = ctx->Driver.NewATIfs(ctx,
418 ctx->ATIFragmentShader.Current);
419 _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, prog);
420 }
421
422 if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI,
423 curProg->Program)) {
424 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
425 /* XXX is this the right error? */
426 _mesa_error(ctx, GL_INVALID_OPERATION,
427 "glEndFragmentShaderATI(driver rejected shader)");
428 }
429 }
430
431 void GLAPIENTRY
_mesa_PassTexCoordATI(GLuint dst,GLuint coord,GLenum swizzle)432 _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
433 {
434 GET_CURRENT_CONTEXT(ctx);
435 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
436 struct atifs_setupinst *curI;
437
438 if (!ctx->ATIFragmentShader.Compiling) {
439 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
440 return;
441 }
442
443 if (curProg->cur_pass == 1) {
444 match_pair_inst(curProg, 0);
445 curProg->cur_pass = 2;
446 }
447 if ((curProg->cur_pass > 2) ||
448 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
449 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
450 return;
451 }
452 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
453 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
454 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
455 return;
456 }
457 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
458 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
459 ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
460 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
461 return;
462 }
463 if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
464 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
465 return;
466 }
467 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
468 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
469 return;
470 }
471 if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
472 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
473 return;
474 }
475 if (coord <= GL_TEXTURE7_ARB) {
476 GLuint tmp = coord - GL_TEXTURE0_ARB;
477 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
478 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
479 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
480 return;
481 } else {
482 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
483 }
484 }
485
486 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
487 new_tex_inst(curProg);
488
489 /* add the instructions */
490 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
491
492 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
493 curI->src = coord;
494 curI->swizzle = swizzle;
495
496 #if MESA_DEBUG_ATI_FS
497 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
498 _mesa_enum_to_string(dst), _mesa_enum_to_string(coord),
499 _mesa_enum_to_string(swizzle));
500 #endif
501 }
502
503 void GLAPIENTRY
_mesa_SampleMapATI(GLuint dst,GLuint interp,GLenum swizzle)504 _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
505 {
506 GET_CURRENT_CONTEXT(ctx);
507 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
508 struct atifs_setupinst *curI;
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 match_pair_inst(curProg, 0);
517 curProg->cur_pass = 2;
518 }
519 if ((curProg->cur_pass > 2) ||
520 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
521 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
522 return;
523 }
524 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
525 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
526 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
527 return;
528 }
529 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
530 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
531 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
532 /* is this texture5 or texture7? spec is a bit unclear there */
533 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
534 return;
535 }
536 if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
537 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
538 return;
539 }
540 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
541 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
542 return;
543 }
544 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
545 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
546 return;
547 }
548 if (interp <= GL_TEXTURE7_ARB) {
549 GLuint tmp = interp - GL_TEXTURE0_ARB;
550 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
551 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
552 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
553 return;
554 } else {
555 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
556 }
557 }
558
559 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
560 new_tex_inst(curProg);
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
_mesa_FragmentOpXATI(GLint optype,GLuint arg_count,GLenum op,GLuint dst,GLuint dstMask,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod,GLuint arg3,GLuint arg3Rep,GLuint arg3Mod)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
589 if (!ctx->ATIFragmentShader.Compiling) {
590 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
591 return;
592 }
593
594 if (curProg->cur_pass==0)
595 curProg->cur_pass=1;
596
597 else if (curProg->cur_pass==2)
598 curProg->cur_pass=3;
599
600 /* decide whether this is a new instruction or not ... all color instructions are new,
601 and alpha instructions might also be new if there was no preceding color inst */
602 if ((optype == 0) || (curProg->last_optype == optype)) {
603 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
604 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
605 return;
606 }
607 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
608 match_pair_inst(curProg, optype);
609 new_arith_inst(curProg);
610 }
611 curProg->last_optype = optype;
612 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
613
614 /* add the instructions */
615 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
616
617 /* error checking */
618 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
619 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
620 return;
621 }
622 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
623 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
624 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
625 (modtemp != GL_EIGHTH_BIT_ATI)) {
626 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
627 return;
628 }
629 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
630 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
631 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
632 return;
633 }
634 if (optype == 1) {
635 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
636 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
637 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
638 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
639 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
640 return;
641 }
642 }
643 if ((op == GL_DOT4_ATI) &&
644 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
645 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
646 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
647 }
648
649 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
650 return;
651 }
652 if (arg2) {
653 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
654 return;
655 }
656 }
657 if (arg3) {
658 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
659 return;
660 }
661 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
662 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
663 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
664 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
665 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
666 return;
667 }
668 }
669
670 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
671
672 curI->Opcode[optype] = op;
673 curI->SrcReg[optype][0].Index = arg1;
674 curI->SrcReg[optype][0].argRep = arg1Rep;
675 curI->SrcReg[optype][0].argMod = arg1Mod;
676 curI->ArgCount[optype] = arg_count;
677
678 if (arg2) {
679 curI->SrcReg[optype][1].Index = arg2;
680 curI->SrcReg[optype][1].argRep = arg2Rep;
681 curI->SrcReg[optype][1].argMod = arg2Mod;
682 }
683
684 if (arg3) {
685 curI->SrcReg[optype][2].Index = arg3;
686 curI->SrcReg[optype][2].argRep = arg3Rep;
687 curI->SrcReg[optype][2].argMod = arg3Mod;
688 }
689
690 curI->DstReg[optype].Index = dst;
691 curI->DstReg[optype].dstMod = dstMod;
692 curI->DstReg[optype].dstMask = dstMask;
693
694 #if MESA_DEBUG_ATI_FS
695 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
696 #endif
697
698 }
699
700 void GLAPIENTRY
_mesa_ColorFragmentOp1ATI(GLenum op,GLuint dst,GLuint dstMask,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod)701 _mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
702 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
703 GLuint arg1Mod)
704 {
705 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
706 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
707 }
708
709 void GLAPIENTRY
_mesa_ColorFragmentOp2ATI(GLenum op,GLuint dst,GLuint dstMask,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod)710 _mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
711 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
712 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
713 GLuint arg2Mod)
714 {
715 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
716 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
717 arg2Mod, 0, 0, 0);
718 }
719
720 void GLAPIENTRY
_mesa_ColorFragmentOp3ATI(GLenum op,GLuint dst,GLuint dstMask,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod,GLuint arg3,GLuint arg3Rep,GLuint arg3Mod)721 _mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
722 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
723 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
724 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
725 GLuint arg3Mod)
726 {
727 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
728 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
729 arg2Mod, arg3, arg3Rep, arg3Mod);
730 }
731
732 void GLAPIENTRY
_mesa_AlphaFragmentOp1ATI(GLenum op,GLuint dst,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod)733 _mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
734 GLuint arg1Rep, GLuint arg1Mod)
735 {
736 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
737 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
738 }
739
740 void GLAPIENTRY
_mesa_AlphaFragmentOp2ATI(GLenum op,GLuint dst,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod)741 _mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
742 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
743 GLuint arg2Rep, GLuint arg2Mod)
744 {
745 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
746 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
747 0);
748 }
749
750 void GLAPIENTRY
_mesa_AlphaFragmentOp3ATI(GLenum op,GLuint dst,GLuint dstMod,GLuint arg1,GLuint arg1Rep,GLuint arg1Mod,GLuint arg2,GLuint arg2Rep,GLuint arg2Mod,GLuint arg3,GLuint arg3Rep,GLuint arg3Mod)751 _mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
752 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
753 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
754 GLuint arg3Rep, GLuint arg3Mod)
755 {
756 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
757 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
758 arg3Rep, arg3Mod);
759 }
760
761 void GLAPIENTRY
_mesa_SetFragmentShaderConstantATI(GLuint dst,const GLfloat * value)762 _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
763 {
764 GLuint dstindex;
765 GET_CURRENT_CONTEXT(ctx);
766
767 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
768 /* spec says nothing about what should happen here but we can't just segfault...*/
769 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
770 return;
771 }
772
773 dstindex = dst - GL_CON_0_ATI;
774 if (ctx->ATIFragmentShader.Compiling) {
775 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
776 COPY_4V(curProg->Constants[dstindex], value);
777 curProg->LocalConstDef |= 1 << dstindex;
778 }
779 else {
780 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
781 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
782 }
783 }
784