2 * \file atifragshader.c
4 * Copyright (C) 2004 David Airlie All Rights Reserved.
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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.
31 #include "atifragshader.h"
33 #define MESA_DEBUG_ATI_FS 0
35 extern struct program _mesa_DummyProgram
;
38 new_arith_inst(struct ati_fragment_shader
*prog
)
40 /* set "default" instruction as not all may get defined.
41 there is no specified way to express a nop with ati fragment shaders we use
42 GL_NONE as the op enum and just set some params to 0 - so nothing to do here */
43 prog
->numArithInstr
[prog
->cur_pass
>> 1]++;
47 new_tex_inst(struct ati_fragment_shader
*prog
)
51 static void match_pair_inst(struct ati_fragment_shader
*curProg
, GLuint optype
)
53 if (optype
== curProg
->last_optype
) {
54 curProg
->last_optype
= 1;
60 create_dst_mod_str(GLuint mod
)
62 static char ret_str
[1024];
64 _mesa_memset(ret_str
, 0, 1024);
65 if (mod
& GL_2X_BIT_ATI
)
66 _mesa_strncat(ret_str
, "|2X", 1024);
68 if (mod
& GL_4X_BIT_ATI
)
69 _mesa_strncat(ret_str
, "|4X", 1024);
71 if (mod
& GL_8X_BIT_ATI
)
72 _mesa_strncat(ret_str
, "|8X", 1024);
73 if (mod
& GL_HALF_BIT_ATI
)
74 _mesa_strncat(ret_str
, "|HA", 1024);
75 if (mod
& GL_QUARTER_BIT_ATI
)
76 _mesa_strncat(ret_str
, "|QU", 1024);
77 if (mod
& GL_EIGHTH_BIT_ATI
)
78 _mesa_strncat(ret_str
, "|EI", 1024);
80 if (mod
& GL_SATURATE_BIT_ATI
)
81 _mesa_strncat(ret_str
, "|SAT", 1024);
83 if (_mesa_strlen(ret_str
) == 0)
84 _mesa_strncat(ret_str
, "NONE", 1024);
88 static char *atifs_ops
[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
89 "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
91 static void debug_op(GLint optype
, GLuint arg_count
, GLenum op
, GLuint dst
,
92 GLuint dstMask
, GLuint dstMod
, GLuint arg1
,
93 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
94 GLuint arg2Rep
, GLuint arg2Mod
, GLuint arg3
,
95 GLuint arg3Rep
, GLuint arg3Mod
)
99 op_name
= atifs_ops
[(arg_count
-1)+(optype
?3:0)];
101 fprintf(stderr
, "%s(%s, %s", op_name
, _mesa_lookup_enum_by_nr(op
),
102 _mesa_lookup_enum_by_nr(dst
));
104 fprintf(stderr
, ", %d", dstMask
);
106 fprintf(stderr
, ", %s", create_dst_mod_str(dstMod
));
108 fprintf(stderr
, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1
),
109 _mesa_lookup_enum_by_nr(arg1Rep
), arg1Mod
);
111 fprintf(stderr
, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2
),
112 _mesa_lookup_enum_by_nr(arg2Rep
), arg2Mod
);
114 fprintf(stderr
, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3
),
115 _mesa_lookup_enum_by_nr(arg3Rep
), arg3Mod
);
117 fprintf(stderr
,")\n");
122 static int check_arith_arg(struct ati_fragment_shader
*curProg
,
123 GLuint optype
, GLuint arg
, GLuint argRep
)
125 GET_CURRENT_CONTEXT(ctx
);
127 if (((arg
< GL_CON_0_ATI
) || (arg
> GL_CON_7_ATI
)) &&
128 ((arg
< GL_REG_0_ATI
) || (arg
> GL_REG_5_ATI
)) &&
129 (arg
!= GL_ZERO
) && (arg
!= GL_ONE
) &&
130 (arg
!= GL_PRIMARY_COLOR_ARB
) && (arg
!= GL_SECONDARY_INTERPOLATOR_ATI
)) {
131 _mesa_error(ctx
, GL_INVALID_ENUM
, "C/AFragmentOpATI(arg)");
134 if ((arg
== GL_SECONDARY_INTERPOLATOR_ATI
) && (((optype
== 0) && (argRep
== GL_ALPHA
)) ||
135 ((optype
== 1) && ((arg
== GL_ALPHA
) || (argRep
== GL_NONE
))))) {
136 _mesa_error(ctx
, GL_INVALID_OPERATION
, "C/AFragmentOpATI(sec_interp)");
139 if ((arg
== GL_SECONDARY_INTERPOLATOR_ATI
) && (((optype
== 0) && (argRep
== GL_ALPHA
)) ||
140 ((optype
== 1) && ((arg
== GL_ALPHA
) || (argRep
== GL_NONE
))))) {
141 _mesa_error(ctx
, GL_INVALID_OPERATION
, "C/AFragmentOpATI(sec_interp)");
144 if ((curProg
->cur_pass
== 1) &&
145 ((arg
== GL_PRIMARY_COLOR_ARB
) || (arg
== GL_SECONDARY_INTERPOLATOR_ATI
))) {
146 curProg
->interpinp1
= GL_TRUE
;
152 _mesa_GenFragmentShadersATI(GLuint range
)
156 GET_CURRENT_CONTEXT(ctx
);
159 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenFragmentShadersATI(range)");
163 if (ctx
->ATIFragmentShader
.Compiling
) {
164 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGenFragmentShadersATI(insideShader)");
168 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, range
);
169 for (i
= 0; i
< range
; i
++) {
170 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, &_mesa_DummyProgram
);
177 _mesa_BindFragmentShaderATI(GLuint id
)
179 struct program
*prog
;
180 GET_CURRENT_CONTEXT(ctx
);
181 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
183 if (ctx
->ATIFragmentShader
.Compiling
) {
184 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBindFragmentShaderATI(insideShader)");
188 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
190 if (curProg
->Base
.Id
== id
) {
194 if (curProg
->Base
.Id
!= 0) {
195 curProg
->Base
.RefCount
--;
196 if (curProg
->Base
.RefCount
<= 0) {
197 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
203 prog
= ctx
->Shared
->DefaultFragmentShader
;
206 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
207 if (!prog
|| prog
== &_mesa_DummyProgram
) {
208 /* allocate a new program now */
209 prog
= ctx
->Driver
.NewProgram(ctx
, GL_FRAGMENT_SHADER_ATI
, id
);
211 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindFragmentShaderATI");
214 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, prog
);
220 ctx
->ATIFragmentShader
.Current
= (struct ati_fragment_shader
*) prog
;
222 ASSERT(ctx
->ATIFragmentShader
.Current
);
226 /*if (ctx->Driver.BindProgram)
227 ctx->Driver.BindProgram(ctx, target, prog); */
231 _mesa_DeleteFragmentShaderATI(GLuint id
)
233 GET_CURRENT_CONTEXT(ctx
);
235 if (ctx
->ATIFragmentShader
.Compiling
) {
236 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glDeleteFragmentShaderATI(insideShader)");
241 struct program
*prog
= (struct program
*)
242 _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
243 if (prog
== &_mesa_DummyProgram
) {
244 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
247 if (ctx
->ATIFragmentShader
.Current
&&
248 ctx
->ATIFragmentShader
.Current
->Base
.Id
== id
) {
249 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
250 _mesa_BindFragmentShaderATI(0);
254 if (!prog
->DeletePending
) {
255 prog
->DeletePending
= GL_TRUE
;
258 if (prog
->RefCount
<= 0) {
259 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
260 ctx
->Driver
.DeleteProgram(ctx
, prog
);
263 /* The ID is immediately available for re-use now */
264 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
266 if (prog
->RefCount
<= 0) {
267 ctx
->Driver
.DeleteProgram(ctx
, prog
);
274 _mesa_BeginFragmentShaderATI(void)
277 GET_CURRENT_CONTEXT(ctx
);
279 if (ctx
->ATIFragmentShader
.Compiling
) {
280 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBeginFragmentShaderATI(insideShader)");
284 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
286 /* if the shader was already defined free instructions and get new ones
287 (or, could use the same mem but would need to reinitialize) */
288 /* no idea if it's allowed to redefine a shader */
289 for (i
= 0; i
< MAX_NUM_PASSES_ATI
; i
++) {
290 if (ctx
->ATIFragmentShader
.Current
->Instructions
[i
])
291 _mesa_free(ctx
->ATIFragmentShader
.Current
->Instructions
[i
]);
292 if (ctx
->ATIFragmentShader
.Current
->SetupInst
[i
])
293 _mesa_free(ctx
->ATIFragmentShader
.Current
->SetupInst
[i
]);
296 /* malloc the instructions here - not sure if the best place but its
298 for (i
= 0; i
< MAX_NUM_PASSES_ATI
; i
++) {
299 ctx
->ATIFragmentShader
.Current
->Instructions
[i
] =
300 (struct atifs_instruction
*)
301 _mesa_calloc(sizeof(struct atifs_instruction
) *
302 (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI
));
303 ctx
->ATIFragmentShader
.Current
->SetupInst
[i
] =
304 (struct atifs_setupinst
*)
305 _mesa_calloc(sizeof(struct atifs_setupinst
) *
306 (MAX_NUM_FRAGMENT_REGISTERS_ATI
));
309 /* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
310 ctx
->ATIFragmentShader
.Current
->localConstDef
= 0;
311 ctx
->ATIFragmentShader
.Current
->numArithInstr
[0] = 0;
312 ctx
->ATIFragmentShader
.Current
->numArithInstr
[1] = 0;
313 ctx
->ATIFragmentShader
.Current
->regsAssigned
[0] = 0;
314 ctx
->ATIFragmentShader
.Current
->regsAssigned
[1] = 0;
315 ctx
->ATIFragmentShader
.Current
->NumPasses
= 0;
316 ctx
->ATIFragmentShader
.Current
->cur_pass
= 0;
317 ctx
->ATIFragmentShader
.Current
->last_optype
= 0;
318 ctx
->ATIFragmentShader
.Current
->interpinp1
= GL_FALSE
;
319 ctx
->ATIFragmentShader
.Current
->isValid
= GL_FALSE
;
320 ctx
->ATIFragmentShader
.Current
->swizzlerq
= 0;
321 ctx
->ATIFragmentShader
.Compiling
= 1;
325 _mesa_EndFragmentShaderATI(void)
327 GET_CURRENT_CONTEXT(ctx
);
328 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
329 #if MESA_DEBUG_ATI_FS
333 if (!ctx
->ATIFragmentShader
.Compiling
) {
334 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glEndFragmentShaderATI(outsideShader)");
337 if (curProg
->interpinp1
&& (ctx
->ATIFragmentShader
.Current
->cur_pass
> 1)) {
338 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glEndFragmentShaderATI(interpinfirstpass)");
339 /* according to spec, DON'T return here */
342 match_pair_inst(curProg
, 0);
343 ctx
->ATIFragmentShader
.Compiling
= 0;
344 ctx
->ATIFragmentShader
.Current
->isValid
= GL_TRUE
;
345 if ((ctx
->ATIFragmentShader
.Current
->cur_pass
== 0) ||
346 (ctx
->ATIFragmentShader
.Current
->cur_pass
== 2)) {
347 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glEndFragmentShaderATI(noarithinst)");
349 if (ctx
->ATIFragmentShader
.Current
->cur_pass
> 1)
350 ctx
->ATIFragmentShader
.Current
->NumPasses
= 2;
351 else ctx
->ATIFragmentShader
.Current
->NumPasses
= 1;
352 ctx
->ATIFragmentShader
.Current
->cur_pass
=0;
353 #if MESA_DEBUG_ATI_FS
354 for (j
= 0; j
< MAX_NUM_PASSES_ATI
; j
++) {
355 for (i
= 0; i
< MAX_NUM_FRAGMENT_REGISTERS_ATI
; i
++) {
356 GLuint op
= curProg
->SetupInst
[j
][i
].Opcode
;
357 const char *op_enum
= op
> 5 ? _mesa_lookup_enum_by_nr(op
) : "0";
358 GLuint src
= curProg
->SetupInst
[j
][i
].src
;
359 GLuint swizzle
= curProg
->SetupInst
[j
][i
].swizzle
;
360 fprintf(stderr
, "%2d %04X %s %d %04X\n", i
, op
, op_enum
, src
,
363 for (i
= 0; i
< curProg
->numArithInstr
[j
]; i
++) {
364 GLuint op0
= curProg
->Instructions
[j
][i
].Opcode
[0];
365 GLuint op1
= curProg
->Instructions
[j
][i
].Opcode
[1];
366 const char *op0_enum
= op0
> 5 ? _mesa_lookup_enum_by_nr(op0
) : "0";
367 const char *op1_enum
= op1
> 5 ? _mesa_lookup_enum_by_nr(op1
) : "0";
368 GLuint count0
= curProg
->Instructions
[j
][i
].ArgCount
[0];
369 GLuint count1
= curProg
->Instructions
[j
][i
].ArgCount
[1];
370 fprintf(stderr
, "%2d %04X %s %d %04X %s %d\n", i
, op0
, op0_enum
, count0
,
371 op1
, op1_enum
, count1
);
378 _mesa_PassTexCoordATI(GLuint dst
, GLuint coord
, GLenum swizzle
)
380 GET_CURRENT_CONTEXT(ctx
);
381 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
382 struct atifs_setupinst
*curI
;
384 if (!ctx
->ATIFragmentShader
.Compiling
) {
385 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glPassTexCoordATI(outsideShader)");
389 if (curProg
->cur_pass
== 1) {
390 match_pair_inst(curProg
, 0);
391 curProg
->cur_pass
= 2;
393 if ((curProg
->cur_pass
> 2) ||
394 ((1 << (dst
- GL_REG_0_ATI
)) & curProg
->regsAssigned
[curProg
->cur_pass
>> 1])) {
395 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glPassTexCoord(pass)");
398 if ((dst
< GL_REG_0_ATI
) || (dst
> GL_REG_5_ATI
)) {
399 _mesa_error(ctx
, GL_INVALID_ENUM
, "glPassTexCoordATI(dst)");
402 if (((coord
< GL_REG_0_ATI
) || (coord
> GL_REG_5_ATI
)) &&
403 ((coord
< GL_TEXTURE0_ARB
) || (coord
> GL_TEXTURE5_ARB
))) {
404 /* is this texture5 or texture7? spec is a bit unclear there */
405 _mesa_error(ctx
, GL_INVALID_ENUM
, "glPassTexCoordATI(coord)");
408 if ((curProg
->cur_pass
== 0) && (coord
>= GL_REG_0_ATI
)) {
409 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glPassTexCoordATI(coord)");
412 if ((swizzle
< GL_SWIZZLE_STR_ATI
) && (swizzle
> GL_SWIZZLE_STQ_DQ_ATI
)) {
413 _mesa_error(ctx
, GL_INVALID_ENUM
, "glPassTexCoordATI(swizzle)");
416 if ((swizzle
& 1) && (coord
>= GL_REG_0_ATI
)) {
417 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glPassTexCoordATI(swizzle)");
420 if (coord
<= GL_TEXTURE5
) {
421 if ((((curProg
->swizzlerq
>> (coord
* 2)) & 3) != 0) &&
422 (((swizzle
& 1) + 1) != ((curProg
->swizzlerq
>> (coord
* 2)) & 3))) {
423 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glPassTexCoordATI(swizzle)");
426 curProg
->swizzlerq
|= (((swizzle
& 1) + 1) << (coord
* 2));
430 curProg
->regsAssigned
[curProg
->cur_pass
>> 1] |= 1 << (dst
- GL_REG_0_ATI
);
431 new_tex_inst(curProg
);
433 /* add the instructions */
434 curI
= &curProg
->SetupInst
[curProg
->cur_pass
>> 1][dst
- GL_REG_0_ATI
];
436 curI
->Opcode
= ATI_FRAGMENT_SHADER_PASS_OP
;
438 curI
->swizzle
= swizzle
;
440 #if MESA_DEBUG_ATI_FS
441 _mesa_debug(ctx
, "%s(%s, %s, %s)\n", __FUNCTION__
,
442 _mesa_lookup_enum_by_nr(dst
), _mesa_lookup_enum_by_nr(coord
),
443 _mesa_lookup_enum_by_nr(swizzle
));
448 _mesa_SampleMapATI(GLuint dst
, GLuint interp
, GLenum swizzle
)
450 GET_CURRENT_CONTEXT(ctx
);
451 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
452 struct atifs_setupinst
*curI
;
454 if (!ctx
->ATIFragmentShader
.Compiling
) {
455 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSampleMapATI(outsideShader)");
459 if (curProg
->cur_pass
== 1) {
460 match_pair_inst(curProg
, 0);
461 curProg
->cur_pass
= 2;
463 if ((curProg
->cur_pass
> 2) ||
464 ((1 << (dst
- GL_REG_0_ATI
)) & curProg
->regsAssigned
[curProg
->cur_pass
>> 1])) {
465 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSampleMapATI(pass)");
468 if ((dst
< GL_REG_0_ATI
) || (dst
> GL_REG_5_ATI
)) {
469 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSampleMapATI(dst)");
472 if (((interp
< GL_REG_0_ATI
) || (interp
> GL_REG_5_ATI
)) &&
473 ((interp
< GL_TEXTURE0_ARB
) || (interp
> GL_TEXTURE5_ARB
))) {
474 /* is this texture5 or texture7? spec is a bit unclear there */
475 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSampleMapATI(interp)");
478 if ((curProg
->cur_pass
== 0) && (interp
>= GL_REG_0_ATI
)) {
479 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSampleMapATI(interp)");
482 if ((swizzle
< GL_SWIZZLE_STR_ATI
) && (swizzle
> GL_SWIZZLE_STQ_DQ_ATI
)) {
483 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSampleMapATI(swizzle)");
486 if ((swizzle
& 1) && (interp
>= GL_REG_0_ATI
)) {
487 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSampleMapATI(swizzle)");
490 if (interp
<= GL_TEXTURE5
) {
491 if ((((curProg
->swizzlerq
>> (interp
* 2)) & 3) != 0) &&
492 (((swizzle
& 1) + 1) != ((curProg
->swizzlerq
>> (interp
* 2)) & 3))) {
493 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glSampleMapATI(swizzle)");
496 curProg
->swizzlerq
|= (((swizzle
& 1) + 1) << (interp
* 2));
500 curProg
->regsAssigned
[curProg
->cur_pass
>> 1] |= 1 << (dst
- GL_REG_0_ATI
);
501 new_tex_inst(curProg
);
503 /* add the instructions */
504 curI
= &curProg
->SetupInst
[curProg
->cur_pass
>> 1][dst
- GL_REG_0_ATI
];
506 curI
->Opcode
= ATI_FRAGMENT_SHADER_SAMPLE_OP
;
508 curI
->swizzle
= swizzle
;
510 #if MESA_DEBUG_ATI_FS
511 _mesa_debug(ctx
, "%s(%s, %s, %s)\n", __FUNCTION__
,
512 _mesa_lookup_enum_by_nr(dst
), _mesa_lookup_enum_by_nr(interp
),
513 _mesa_lookup_enum_by_nr(swizzle
));
518 _mesa_FragmentOpXATI(GLint optype
, GLuint arg_count
, GLenum op
, GLuint dst
,
519 GLuint dstMask
, GLuint dstMod
, GLuint arg1
,
520 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
521 GLuint arg2Rep
, GLuint arg2Mod
, GLuint arg3
,
522 GLuint arg3Rep
, GLuint arg3Mod
)
524 GET_CURRENT_CONTEXT(ctx
);
525 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
527 struct atifs_instruction
*curI
;
528 GLuint modtemp
= dstMod
& ~GL_SATURATE_BIT_ATI
;
530 if (!ctx
->ATIFragmentShader
.Compiling
) {
531 _mesa_error(ctx
, GL_INVALID_OPERATION
, "C/AFragmentOpATI(outsideShader)");
535 if (curProg
->cur_pass
==0)
538 else if (curProg
->cur_pass
==2)
541 /* decide whether this is a new instruction or not ... all color instructions are new,
542 and alpha instructions might also be new if there was no preceding color inst */
543 if ((optype
== 0) || (curProg
->last_optype
== optype
)) {
544 if (curProg
->numArithInstr
[curProg
->cur_pass
>> 1] > 7) {
545 _mesa_error(ctx
, GL_INVALID_OPERATION
, "C/AFragmentOpATI(instrCount)");
548 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
549 match_pair_inst(curProg
, optype
);
550 new_arith_inst(curProg
);
552 curProg
->last_optype
= optype
;
553 ci
= curProg
->numArithInstr
[curProg
->cur_pass
>> 1] - 1;
555 /* add the instructions */
556 curI
= &curProg
->Instructions
[curProg
->cur_pass
>> 1][ci
];
559 if ((dst
< GL_REG_0_ATI
) || (dst
> GL_REG_5_ATI
)) {
560 _mesa_error(ctx
, GL_INVALID_ENUM
, "C/AFragmentOpATI(dst)");
563 if ((modtemp
!= GL_NONE
) && (modtemp
!= GL_2X_BIT_ATI
) &&
564 (modtemp
!= GL_4X_BIT_ATI
) && (modtemp
!= GL_8X_BIT_ATI
) &&
565 (modtemp
!= GL_HALF_BIT_ATI
) && !(modtemp
!= GL_QUARTER_BIT_ATI
) &&
566 (modtemp
!= GL_EIGHTH_BIT_ATI
)) {
567 _mesa_error(ctx
, GL_INVALID_ENUM
, "C/AFragmentOpATI(dstMod)%x", modtemp
);
570 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
571 if (((op
< GL_ADD_ATI
) || (op
> GL_DOT2_ADD_ATI
)) && !(op
== GL_MOV_ATI
)) {
572 _mesa_error(ctx
, GL_INVALID_ENUM
, "C/AFragmentOpATI(op)");
576 if (((op
== GL_DOT2_ADD_ATI
) && (curI
->Opcode
[0] != GL_DOT2_ADD_ATI
)) ||
577 ((op
== GL_DOT3_ATI
) && (curI
->Opcode
[0] != GL_DOT3_ATI
)) ||
578 ((op
== GL_DOT4_ATI
) && (curI
->Opcode
[0] != GL_DOT4_ATI
)) ||
579 ((op
!= GL_DOT4_ATI
) && (curI
->Opcode
[0] == GL_DOT4_ATI
))) {
580 _mesa_error(ctx
, GL_INVALID_OPERATION
, "AFragmentOpATI(op)");
584 if ((op
== GL_DOT4_ATI
) &&
585 (((arg1
== GL_SECONDARY_INTERPOLATOR_ATI
) && ((arg1Rep
== GL_ALPHA
) || (arg1Rep
== GL_NONE
))) ||
586 (((arg2
== GL_SECONDARY_INTERPOLATOR_ATI
) && ((arg2Rep
== GL_ALPHA
) || (arg2Rep
== GL_NONE
)))))) {
587 _mesa_error(ctx
, GL_INVALID_OPERATION
, "C/AFragmentOpATI(sec_interp)");
590 if (!check_arith_arg(curProg
, optype
, arg1
, arg1Rep
)) {
594 if (!check_arith_arg(curProg
, optype
, arg2
, arg2Rep
)) {
599 if (!check_arith_arg(curProg
, optype
, arg3
, arg3Rep
)) {
602 if ((arg1
>= GL_CON_0_ATI
) && (arg1
<= GL_CON_7_ATI
) &&
603 (arg2
>= GL_CON_0_ATI
) && (arg2
<= GL_CON_7_ATI
) &&
604 (arg3
>= GL_CON_0_ATI
) && (arg3
<= GL_CON_7_ATI
) &&
605 (arg1
!= arg2
) && (arg1
!= arg3
) && (arg2
!= arg3
)) {
606 _mesa_error(ctx
, GL_INVALID_OPERATION
, "C/AFragmentOpATI(3Consts)");
611 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
613 curI
->Opcode
[optype
] = op
;
614 curI
->SrcReg
[optype
][0].Index
= arg1
;
615 curI
->SrcReg
[optype
][0].argRep
= arg1Rep
;
616 curI
->SrcReg
[optype
][0].argMod
= arg1Mod
;
617 curI
->ArgCount
[optype
] = arg_count
;
620 curI
->SrcReg
[optype
][1].Index
= arg2
;
621 curI
->SrcReg
[optype
][1].argRep
= arg2Rep
;
622 curI
->SrcReg
[optype
][1].argMod
= arg2Mod
;
626 curI
->SrcReg
[optype
][2].Index
= arg3
;
627 curI
->SrcReg
[optype
][2].argRep
= arg3Rep
;
628 curI
->SrcReg
[optype
][2].argMod
= arg3Mod
;
631 curI
->DstReg
[optype
].Index
= dst
;
632 curI
->DstReg
[optype
].dstMod
= dstMod
;
633 curI
->DstReg
[optype
].dstMask
= dstMask
;
635 #if MESA_DEBUG_ATI_FS
636 debug_op(optype
, arg_count
, op
, dst
, dstMask
, dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, arg3
, arg3Rep
, arg3Mod
);
642 _mesa_ColorFragmentOp1ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
643 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
646 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 1, op
, dst
, dstMask
,
647 dstMod
, arg1
, arg1Rep
, arg1Mod
, 0, 0, 0, 0, 0, 0);
651 _mesa_ColorFragmentOp2ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
652 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
653 GLuint arg1Mod
, GLuint arg2
, GLuint arg2Rep
,
656 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 2, op
, dst
, dstMask
,
657 dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
,
662 _mesa_ColorFragmentOp3ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
663 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
664 GLuint arg1Mod
, GLuint arg2
, GLuint arg2Rep
,
665 GLuint arg2Mod
, GLuint arg3
, GLuint arg3Rep
,
668 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 3, op
, dst
, dstMask
,
669 dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
,
670 arg2Mod
, arg3
, arg3Rep
, arg3Mod
);
674 _mesa_AlphaFragmentOp1ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
675 GLuint arg1Rep
, GLuint arg1Mod
)
677 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 1, op
, dst
, 0, dstMod
,
678 arg1
, arg1Rep
, arg1Mod
, 0, 0, 0, 0, 0, 0);
682 _mesa_AlphaFragmentOp2ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
683 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
684 GLuint arg2Rep
, GLuint arg2Mod
)
686 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 2, op
, dst
, 0, dstMod
,
687 arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, 0, 0,
692 _mesa_AlphaFragmentOp3ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
693 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
694 GLuint arg2Rep
, GLuint arg2Mod
, GLuint arg3
,
695 GLuint arg3Rep
, GLuint arg3Mod
)
697 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 3, op
, dst
, 0, dstMod
,
698 arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, arg3
,
703 _mesa_SetFragmentShaderConstantATI(GLuint dst
, const GLfloat
* value
)
706 GET_CURRENT_CONTEXT(ctx
);
708 if ((dst
< GL_CON_0_ATI
) || (dst
> GL_CON_7_ATI
)) {
709 /* spec says nothing about what should happen here but we can't just segfault...*/
710 _mesa_error(ctx
, GL_INVALID_ENUM
, "glSetFragmentShaderConstantATI(dst)");
714 dstindex
= dst
- GL_CON_0_ATI
;
715 if (ctx
->ATIFragmentShader
.Compiling
) {
716 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
717 COPY_4V(curProg
->Constants
[dstindex
], value
);
718 curProg
->localConstDef
|= 1 << dstindex
;
721 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
722 COPY_4V(ctx
->ATIFragmentShader
.globalConstants
[dstindex
], value
);