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_inst(struct ati_fragment_shader
*prog
)
40 prog
->Base
.NumInstructions
++;
45 create_dst_mod_str(GLuint mod
)
47 static char ret_str
[1024];
49 _mesa_memset(ret_str
, 0, 1024);
50 if (mod
& GL_2X_BIT_ATI
)
51 _mesa_strncat(ret_str
, "|2X", 1024);
53 if (mod
& GL_4X_BIT_ATI
)
54 _mesa_strncat(ret_str
, "|4X", 1024);
56 if (mod
& GL_8X_BIT_ATI
)
57 _mesa_strncat(ret_str
, "|8X", 1024);
58 if (mod
& GL_HALF_BIT_ATI
)
59 _mesa_strncat(ret_str
, "|HA", 1024);
60 if (mod
& GL_QUARTER_BIT_ATI
)
61 _mesa_strncat(ret_str
, "|QU", 1024);
62 if (mod
& GL_EIGHTH_BIT_ATI
)
63 _mesa_strncat(ret_str
, "|EI", 1024);
65 if (mod
& GL_SATURATE_BIT_ATI
)
66 _mesa_strncat(ret_str
, "|SAT", 1024);
68 if (_mesa_strlen(ret_str
) == 0)
69 _mesa_strncat(ret_str
, "NONE", 1024);
73 static char *atifs_ops
[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
74 "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
76 static void debug_op(GLint optype
, GLuint arg_count
, GLenum op
, GLuint dst
,
77 GLuint dstMask
, GLuint dstMod
, GLuint arg1
,
78 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
79 GLuint arg2Rep
, GLuint arg2Mod
, GLuint arg3
,
80 GLuint arg3Rep
, GLuint arg3Mod
)
84 op_name
= atifs_ops
[(arg_count
-1)+(optype
?3:0)];
86 fprintf(stderr
, "%s(%s, %s", op_name
, _mesa_lookup_enum_by_nr(op
),
87 _mesa_lookup_enum_by_nr(dst
));
89 fprintf(stderr
, ", %d", dstMask
);
91 fprintf(stderr
, ", %s", create_dst_mod_str(dstMod
));
93 fprintf(stderr
, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1
),
94 _mesa_lookup_enum_by_nr(arg1Rep
), arg1Mod
);
96 fprintf(stderr
, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2
),
97 _mesa_lookup_enum_by_nr(arg2Rep
), arg2Mod
);
99 fprintf(stderr
, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3
),
100 _mesa_lookup_enum_by_nr(arg3Rep
), arg3Mod
);
102 fprintf(stderr
,")\n");
108 _mesa_GenFragmentShadersATI(GLuint range
)
112 GET_CURRENT_CONTEXT(ctx
);
114 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, range
);
115 for (i
= 0; i
< range
; i
++) {
116 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, &_mesa_DummyProgram
);
123 _mesa_BindFragmentShaderATI(GLuint id
)
125 struct program
*prog
;
126 GET_CURRENT_CONTEXT(ctx
);
127 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
129 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
131 if (curProg
->Base
.Id
== id
) {
135 if (curProg
->Base
.Id
!= 0) {
136 curProg
->Base
.RefCount
--;
137 if (curProg
->Base
.RefCount
<= 0) {
138 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
144 prog
= ctx
->Shared
->DefaultFragmentShader
;
147 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
148 if (!prog
|| prog
== &_mesa_DummyProgram
) {
149 /* allocate a new program now */
150 prog
= ctx
->Driver
.NewProgram(ctx
, GL_FRAGMENT_SHADER_ATI
, id
);
152 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindFragmentShaderATI");
155 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, prog
);
161 ctx
->ATIFragmentShader
.Current
= (struct ati_fragment_shader
*) prog
;
163 ASSERT(ctx
->ATIFragmentShader
.Current
);
167 /*if (ctx->Driver.BindProgram)
168 ctx->Driver.BindProgram(ctx, target, prog); */
172 _mesa_DeleteFragmentShaderATI(GLuint id
)
174 GET_CURRENT_CONTEXT(ctx
);
177 struct program
*prog
= (struct program
*)
178 _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
179 if (prog
== &_mesa_DummyProgram
) {
180 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
183 if (ctx
->ATIFragmentShader
.Current
&&
184 ctx
->ATIFragmentShader
.Current
->Base
.Id
== id
) {
185 _mesa_BindFragmentShaderATI(0);
189 if (!prog
->DeletePending
) {
190 prog
->DeletePending
= GL_TRUE
;
193 if (prog
->RefCount
<= 0) {
194 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
195 ctx
->Driver
.DeleteProgram(ctx
, prog
);
198 /* The ID is immediately available for re-use now */
199 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
201 if (prog
->RefCount
<= 0) {
202 ctx
->Driver
.DeleteProgram(ctx
, prog
);
209 _mesa_BeginFragmentShaderATI(void)
211 GET_CURRENT_CONTEXT(ctx
);
213 /* malloc the instructions here - not sure if the best place but its
215 ctx
->ATIFragmentShader
.Current
->Instructions
=
216 (struct atifs_instruction
*)
217 _mesa_calloc(sizeof(struct atifs_instruction
) * MAX_NUM_PASSES_ATI
*
218 MAX_NUM_INSTRUCTIONS_PER_PASS_ATI
* 2);
220 ctx
->ATIFragmentShader
.Current
->cur_pass
= 0;
221 ctx
->ATIFragmentShader
.Compiling
= 1;
225 _mesa_EndFragmentShaderATI(void)
227 GET_CURRENT_CONTEXT(ctx
);
228 #if MESA_DEBUG_ATI_FS
229 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
233 ctx
->ATIFragmentShader
.Compiling
= 0;
234 ctx
->ATIFragmentShader
.Current
->NumPasses
= ctx
->ATIFragmentShader
.Current
->cur_pass
;
235 ctx
->ATIFragmentShader
.Current
->cur_pass
=0;
236 #if MESA_DEBUG_ATI_FS
237 for (i
= 0; i
< curProg
->Base
.NumInstructions
; i
++) {
238 GLuint op0
= curProg
->Instructions
[i
].Opcode
[0];
239 GLuint op1
= curProg
->Instructions
[i
].Opcode
[1];
240 const char *op0_enum
= op0
> 5 ? _mesa_lookup_enum_by_nr(op0
) : "0";
241 const char *op1_enum
= op1
> 5 ? _mesa_lookup_enum_by_nr(op1
) : "0";
242 GLuint count0
= curProg
->Instructions
[i
].ArgCount
[0];
243 GLuint count1
= curProg
->Instructions
[i
].ArgCount
[1];
245 fprintf(stderr
, "%2d %04X %s %d %04X %s %d\n", i
, op0
, op0_enum
, count0
,
246 op1
, op1_enum
, count1
);
252 _mesa_PassTexCoordATI(GLuint dst
, GLuint coord
, GLenum swizzle
)
254 GET_CURRENT_CONTEXT(ctx
);
255 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
257 struct atifs_instruction
*curI
;
259 if (ctx
->ATIFragmentShader
.Current
->cur_pass
==1)
260 ctx
->ATIFragmentShader
.Current
->cur_pass
=2;
263 ci
= curProg
->Base
.NumInstructions
- 1;
265 if ((swizzle != GL_SWIZZLE_STR_ATI) ||
266 (swizzle != GL_SWIZZLE_STQ_ATI) ||
267 (swizzle != GL_SWIZZLE_STR_DR_ATI) ||
268 (swizzle != GL_SWIZZLE_STQ_DQ_ATI))
271 /* add the instructions */
272 curI
= &curProg
->Instructions
[ci
];
274 curI
->Opcode
[0] = ATI_FRAGMENT_SHADER_PASS_OP
;
275 curI
->DstReg
[0].Index
= dst
;
276 curI
->SrcReg
[0][0].Index
= coord
;
277 curI
->DstReg
[0].Swizzle
= swizzle
;
279 #if MESA_DEBUG_ATI_FS
280 _mesa_debug(ctx
, "%s(%s, %s, %s)\n", __FUNCTION__
,
281 _mesa_lookup_enum_by_nr(dst
), _mesa_lookup_enum_by_nr(coord
),
282 _mesa_lookup_enum_by_nr(swizzle
));
287 _mesa_SampleMapATI(GLuint dst
, GLuint interp
, GLenum swizzle
)
289 GET_CURRENT_CONTEXT(ctx
);
290 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
292 struct atifs_instruction
*curI
;
294 if (ctx
->ATIFragmentShader
.Current
->cur_pass
==1)
295 ctx
->ATIFragmentShader
.Current
->cur_pass
=2;
300 ci
= curProg
->Base
.NumInstructions
- 1;
301 /* add the instructions */
302 curI
= &curProg
->Instructions
[ci
];
304 curI
->Opcode
[0] = ATI_FRAGMENT_SHADER_SAMPLE_OP
;
305 curI
->DstReg
[0].Index
= dst
;
306 curI
->DstReg
[0].Swizzle
= swizzle
;
308 curI
->SrcReg
[0][0].Index
= interp
;
310 #if MESA_DEBUG_ATI_FS
311 _mesa_debug(ctx
, "%s(%s, %s, %s)\n", __FUNCTION__
,
312 _mesa_lookup_enum_by_nr(dst
), _mesa_lookup_enum_by_nr(interp
),
313 _mesa_lookup_enum_by_nr(swizzle
));
318 _mesa_FragmentOpXATI(GLint optype
, GLuint arg_count
, GLenum op
, GLuint dst
,
319 GLuint dstMask
, GLuint dstMod
, GLuint arg1
,
320 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
321 GLuint arg2Rep
, GLuint arg2Mod
, GLuint arg3
,
322 GLuint arg3Rep
, GLuint arg3Mod
)
324 GET_CURRENT_CONTEXT(ctx
);
325 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
327 struct atifs_instruction
*curI
;
329 if (ctx
->ATIFragmentShader
.Current
->cur_pass
==0)
330 ctx
->ATIFragmentShader
.Current
->cur_pass
=1;
332 /* decide whether this is a new instruction or not ... all color instructions are new */
336 ci
= curProg
->Base
.NumInstructions
- 1;
338 /* add the instructions */
339 curI
= &curProg
->Instructions
[ci
];
341 curI
->Opcode
[optype
] = op
;
343 curI
->SrcReg
[optype
][0].Index
= arg1
;
344 curI
->SrcReg
[optype
][0].argRep
= arg1Rep
;
345 curI
->SrcReg
[optype
][0].argMod
= arg1Mod
;
346 curI
->ArgCount
[optype
] = arg_count
;
349 curI
->SrcReg
[optype
][1].Index
= arg2
;
350 curI
->SrcReg
[optype
][1].argRep
= arg2Rep
;
351 curI
->SrcReg
[optype
][1].argMod
= arg2Mod
;
355 curI
->SrcReg
[optype
][2].Index
= arg3
;
356 curI
->SrcReg
[optype
][2].argRep
= arg3Rep
;
357 curI
->SrcReg
[optype
][2].argMod
= arg3Mod
;
360 curI
->DstReg
[optype
].Index
= dst
;
361 curI
->DstReg
[optype
].dstMod
= dstMod
;
362 curI
->DstReg
[optype
].dstMask
= dstMask
;
364 #if MESA_DEBUG_ATI_FS
365 debug_op(optype
, arg_count
, op
, dst
, dstMask
, dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, arg3
, arg3Rep
, arg3Mod
);
371 _mesa_ColorFragmentOp1ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
372 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
375 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 1, op
, dst
, dstMask
,
376 dstMod
, arg1
, arg1Rep
, arg1Mod
, 0, 0, 0, 0, 0, 0);
380 _mesa_ColorFragmentOp2ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
381 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
382 GLuint arg1Mod
, GLuint arg2
, GLuint arg2Rep
,
385 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 2, op
, dst
, dstMask
,
386 dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
,
391 _mesa_ColorFragmentOp3ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
392 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
393 GLuint arg1Mod
, GLuint arg2
, GLuint arg2Rep
,
394 GLuint arg2Mod
, GLuint arg3
, GLuint arg3Rep
,
397 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 3, op
, dst
, dstMask
,
398 dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
,
399 arg2Mod
, arg3
, arg3Rep
, arg3Mod
);
403 _mesa_AlphaFragmentOp1ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
404 GLuint arg1Rep
, GLuint arg1Mod
)
406 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 1, op
, dst
, 0, dstMod
,
407 arg1
, arg1Rep
, arg1Mod
, 0, 0, 0, 0, 0, 0);
411 _mesa_AlphaFragmentOp2ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
412 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
413 GLuint arg2Rep
, GLuint arg2Mod
)
415 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 2, op
, dst
, 0, dstMod
,
416 arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, 0, 0,
421 _mesa_AlphaFragmentOp3ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
422 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
423 GLuint arg2Rep
, GLuint arg2Mod
, GLuint arg3
,
424 GLuint arg3Rep
, GLuint arg3Mod
)
426 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 3, op
, dst
, 0, dstMod
,
427 arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, arg3
,
432 _mesa_SetFragmentShaderConstantATI(GLuint dst
, const GLfloat
* value
)
434 GET_CURRENT_CONTEXT(ctx
);
435 GLuint dstindex
= dst
- GL_CON_0_ATI
;
436 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
438 COPY_4V(curProg
->Constants
[dstindex
], value
);