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;
235 #if MESA_DEBUG_ATI_FS
236 for (i
= 0; i
< curProg
->Base
.NumInstructions
; i
++) {
237 GLuint op0
= curProg
->Instructions
[i
].Opcode
[0];
238 GLuint op1
= curProg
->Instructions
[i
].Opcode
[1];
239 const char *op0_enum
= op0
> 5 ? _mesa_lookup_enum_by_nr(op0
) : "0";
240 const char *op1_enum
= op1
> 5 ? _mesa_lookup_enum_by_nr(op1
) : "0";
241 GLuint count0
= curProg
->Instructions
[i
].ArgCount
[0];
242 GLuint count1
= curProg
->Instructions
[i
].ArgCount
[1];
244 fprintf(stderr
, "%2d %04X %s %d %04X %s %d\n", i
, op0
, op0_enum
, count0
,
245 op1
, op1_enum
, count1
);
251 _mesa_PassTexCoordATI(GLuint dst
, GLuint coord
, GLenum swizzle
)
253 GET_CURRENT_CONTEXT(ctx
);
254 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
256 struct atifs_instruction
*curI
;
259 ci
= curProg
->Base
.NumInstructions
- 1;
261 if ((swizzle != GL_SWIZZLE_STR_ATI) ||
262 (swizzle != GL_SWIZZLE_STQ_ATI) ||
263 (swizzle != GL_SWIZZLE_STR_DR_ATI) ||
264 (swizzle != GL_SWIZZLE_STQ_DQ_ATI))
267 /* add the instructions */
268 curI
= &curProg
->Instructions
[ci
];
270 curI
->Opcode
[0] = ATI_FRAGMENT_SHADER_PASS_OP
;
271 curI
->DstReg
[0].Index
= dst
;
272 curI
->SrcReg
[0][0].Index
= coord
;
273 curI
->DstReg
[0].Swizzle
= swizzle
;
275 #if MESA_DEBUG_ATI_FS
276 _mesa_debug(ctx
, "%s(%s, %s, %s)\n", __FUNCTION__
,
277 _mesa_lookup_enum_by_nr(dst
), _mesa_lookup_enum_by_nr(coord
),
278 _mesa_lookup_enum_by_nr(swizzle
));
283 _mesa_SampleMapATI(GLuint dst
, GLuint interp
, GLenum swizzle
)
285 GET_CURRENT_CONTEXT(ctx
);
286 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
288 struct atifs_instruction
*curI
;
292 ci
= curProg
->Base
.NumInstructions
- 1;
293 /* add the instructions */
294 curI
= &curProg
->Instructions
[ci
];
296 curI
->Opcode
[0] = ATI_FRAGMENT_SHADER_SAMPLE_OP
;
297 curI
->DstReg
[0].Index
= dst
;
298 curI
->DstReg
[0].Swizzle
= swizzle
;
300 curI
->SrcReg
[0][0].Index
= interp
;
302 #if MESA_DEBUG_ATI_FS
303 _mesa_debug(ctx
, "%s(%s, %s, %s)\n", __FUNCTION__
,
304 _mesa_lookup_enum_by_nr(dst
), _mesa_lookup_enum_by_nr(interp
),
305 _mesa_lookup_enum_by_nr(swizzle
));
310 _mesa_FragmentOpXATI(GLint optype
, GLuint arg_count
, GLenum op
, GLuint dst
,
311 GLuint dstMask
, GLuint dstMod
, GLuint arg1
,
312 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
313 GLuint arg2Rep
, GLuint arg2Mod
, GLuint arg3
,
314 GLuint arg3Rep
, GLuint arg3Mod
)
316 GET_CURRENT_CONTEXT(ctx
);
317 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
319 struct atifs_instruction
*curI
;
321 /* decide whether this is a new instruction or not ... all color instructions are new */
325 ci
= curProg
->Base
.NumInstructions
- 1;
327 /* add the instructions */
328 curI
= &curProg
->Instructions
[ci
];
330 curI
->Opcode
[optype
] = op
;
332 curI
->SrcReg
[optype
][0].Index
= arg1
;
333 curI
->SrcReg
[optype
][0].argRep
= arg1Rep
;
334 curI
->SrcReg
[optype
][0].argMod
= arg1Mod
;
335 curI
->ArgCount
[optype
] = arg_count
;
338 curI
->SrcReg
[optype
][1].Index
= arg2
;
339 curI
->SrcReg
[optype
][1].argRep
= arg2Rep
;
340 curI
->SrcReg
[optype
][1].argMod
= arg2Mod
;
344 curI
->SrcReg
[optype
][2].Index
= arg3
;
345 curI
->SrcReg
[optype
][2].argRep
= arg3Rep
;
346 curI
->SrcReg
[optype
][2].argMod
= arg3Mod
;
349 curI
->DstReg
[optype
].Index
= dst
;
350 curI
->DstReg
[optype
].dstMod
= dstMod
;
351 curI
->DstReg
[optype
].dstMask
= dstMask
;
353 #if MESA_DEBUG_ATI_FS
354 debug_op(optype
, arg_count
, op
, dst
, dstMask
, dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, arg3
, arg3Rep
, arg3Mod
);
360 _mesa_ColorFragmentOp1ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
361 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
364 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 1, op
, dst
, dstMask
,
365 dstMod
, arg1
, arg1Rep
, arg1Mod
, 0, 0, 0, 0, 0, 0);
369 _mesa_ColorFragmentOp2ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
370 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
371 GLuint arg1Mod
, GLuint arg2
, GLuint arg2Rep
,
374 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 2, op
, dst
, dstMask
,
375 dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
,
380 _mesa_ColorFragmentOp3ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
381 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
382 GLuint arg1Mod
, GLuint arg2
, GLuint arg2Rep
,
383 GLuint arg2Mod
, GLuint arg3
, GLuint arg3Rep
,
386 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 3, op
, dst
, dstMask
,
387 dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
,
388 arg2Mod
, arg3
, arg3Rep
, arg3Mod
);
392 _mesa_AlphaFragmentOp1ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
393 GLuint arg1Rep
, GLuint arg1Mod
)
395 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 1, op
, dst
, 0, dstMod
,
396 arg1
, arg1Rep
, arg1Mod
, 0, 0, 0, 0, 0, 0);
400 _mesa_AlphaFragmentOp2ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
401 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
402 GLuint arg2Rep
, GLuint arg2Mod
)
404 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 2, op
, dst
, 0, dstMod
,
405 arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, 0, 0,
410 _mesa_AlphaFragmentOp3ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
411 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
412 GLuint arg2Rep
, GLuint arg2Mod
, GLuint arg3
,
413 GLuint arg3Rep
, GLuint arg3Mod
)
415 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 3, op
, dst
, 0, dstMod
,
416 arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, arg3
,
421 _mesa_SetFragmentShaderConstantATI(GLuint dst
, const GLfloat
* value
)
423 GET_CURRENT_CONTEXT(ctx
);
424 GLuint dstindex
= dst
- GL_CON_0_ATI
;
425 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
427 COPY_4V(curProg
->Constants
[dstindex
], value
);