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);
188 if (!prog
->DeletePending
) {
189 prog
->DeletePending
= GL_TRUE
;
192 if (prog
->RefCount
<= 0) {
193 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
194 ctx
->Driver
.DeleteProgram(ctx
, prog
);
200 _mesa_BeginFragmentShaderATI(void)
202 GET_CURRENT_CONTEXT(ctx
);
204 /* malloc the instructions here - not sure if the best place but its
206 ctx
->ATIFragmentShader
.Current
->Instructions
=
207 (struct atifs_instruction
*)
208 _mesa_calloc(sizeof(struct atifs_instruction
) * MAX_NUM_PASSES_ATI
*
209 MAX_NUM_INSTRUCTIONS_PER_PASS_ATI
* 2);
211 ctx
->ATIFragmentShader
.Current
->cur_pass
= 0;
212 ctx
->ATIFragmentShader
.Compiling
= 1;
216 _mesa_EndFragmentShaderATI(void)
218 GET_CURRENT_CONTEXT(ctx
);
219 #if MESA_DEBUG_ATI_FS
220 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
224 ctx
->ATIFragmentShader
.Compiling
= 0;
226 #if MESA_DEBUG_ATI_FS
227 for (i
= 0; i
< curProg
->Base
.NumInstructions
; i
++) {
228 GLuint op0
= curProg
->Instructions
[i
].Opcode
[0];
229 GLuint op1
= curProg
->Instructions
[i
].Opcode
[1];
230 const char *op0_enum
= op0
> 5 ? _mesa_lookup_enum_by_nr(op0
) : "0";
231 const char *op1_enum
= op1
> 5 ? _mesa_lookup_enum_by_nr(op1
) : "0";
232 GLuint count0
= curProg
->Instructions
[i
].ArgCount
[0];
233 GLuint count1
= curProg
->Instructions
[i
].ArgCount
[1];
235 fprintf(stderr
, "%2d %04X %s %d %04X %s %d\n", i
, op0
, op0_enum
, count0
,
236 op1
, op1_enum
, count1
);
242 _mesa_PassTexCoordATI(GLuint dst
, GLuint coord
, GLenum swizzle
)
244 GET_CURRENT_CONTEXT(ctx
);
245 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
247 struct atifs_instruction
*curI
;
250 ci
= curProg
->Base
.NumInstructions
- 1;
252 if ((swizzle != GL_SWIZZLE_STR_ATI) ||
253 (swizzle != GL_SWIZZLE_STQ_ATI) ||
254 (swizzle != GL_SWIZZLE_STR_DR_ATI) ||
255 (swizzle != GL_SWIZZLE_STQ_DQ_ATI))
258 /* add the instructions */
259 curI
= &curProg
->Instructions
[ci
];
261 curI
->Opcode
[0] = ATI_FRAGMENT_SHADER_PASS_OP
;
262 curI
->DstReg
[0].Index
= dst
;
263 curI
->SrcReg
[0][0].Index
= coord
;
264 curI
->DstReg
[0].Swizzle
= swizzle
;
266 #if MESA_DEBUG_ATI_FS
267 _mesa_debug(ctx
, "%s(%s, %s, %s)\n", __FUNCTION__
,
268 _mesa_lookup_enum_by_nr(dst
), _mesa_lookup_enum_by_nr(coord
),
269 _mesa_lookup_enum_by_nr(swizzle
));
274 _mesa_SampleMapATI(GLuint dst
, GLuint interp
, GLenum swizzle
)
276 GET_CURRENT_CONTEXT(ctx
);
277 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
279 struct atifs_instruction
*curI
;
283 ci
= curProg
->Base
.NumInstructions
- 1;
284 /* add the instructions */
285 curI
= &curProg
->Instructions
[ci
];
287 curI
->Opcode
[0] = ATI_FRAGMENT_SHADER_SAMPLE_OP
;
288 curI
->DstReg
[0].Index
= dst
;
289 curI
->DstReg
[0].Swizzle
= swizzle
;
291 curI
->SrcReg
[0][0].Index
= interp
;
293 #if MESA_DEBUG_ATI_FS
294 _mesa_debug(ctx
, "%s(%s, %s, %s)\n", __FUNCTION__
,
295 _mesa_lookup_enum_by_nr(dst
), _mesa_lookup_enum_by_nr(interp
),
296 _mesa_lookup_enum_by_nr(swizzle
));
301 _mesa_FragmentOpXATI(GLint optype
, GLuint arg_count
, GLenum op
, GLuint dst
,
302 GLuint dstMask
, GLuint dstMod
, GLuint arg1
,
303 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
304 GLuint arg2Rep
, GLuint arg2Mod
, GLuint arg3
,
305 GLuint arg3Rep
, GLuint arg3Mod
)
307 GET_CURRENT_CONTEXT(ctx
);
308 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
310 struct atifs_instruction
*curI
;
312 /* decide whether this is a new instruction or not ... all color instructions are new */
316 ci
= curProg
->Base
.NumInstructions
- 1;
318 /* add the instructions */
319 curI
= &curProg
->Instructions
[ci
];
321 curI
->Opcode
[optype
] = op
;
323 curI
->SrcReg
[optype
][0].Index
= arg1
;
324 curI
->SrcReg
[optype
][0].argRep
= arg1Rep
;
325 curI
->SrcReg
[optype
][0].argMod
= arg1Mod
;
326 curI
->ArgCount
[optype
] = arg_count
;
329 curI
->SrcReg
[optype
][1].Index
= arg2
;
330 curI
->SrcReg
[optype
][1].argRep
= arg2Rep
;
331 curI
->SrcReg
[optype
][1].argMod
= arg2Mod
;
335 curI
->SrcReg
[optype
][2].Index
= arg3
;
336 curI
->SrcReg
[optype
][2].argRep
= arg3Rep
;
337 curI
->SrcReg
[optype
][2].argMod
= arg3Mod
;
340 curI
->DstReg
[optype
].Index
= dst
;
341 curI
->DstReg
[optype
].dstMod
= dstMod
;
342 curI
->DstReg
[optype
].dstMask
= dstMask
;
344 #if MESA_DEBUG_ATI_FS
345 debug_op(optype
, arg_count
, op
, dst
, dstMask
, dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, arg3
, arg3Rep
, arg3Mod
);
351 _mesa_ColorFragmentOp1ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
352 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
355 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 1, op
, dst
, dstMask
,
356 dstMod
, arg1
, arg1Rep
, arg1Mod
, 0, 0, 0, 0, 0, 0);
360 _mesa_ColorFragmentOp2ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
361 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
362 GLuint arg1Mod
, GLuint arg2
, GLuint arg2Rep
,
365 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 2, op
, dst
, dstMask
,
366 dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
,
371 _mesa_ColorFragmentOp3ATI(GLenum op
, GLuint dst
, GLuint dstMask
,
372 GLuint dstMod
, GLuint arg1
, GLuint arg1Rep
,
373 GLuint arg1Mod
, GLuint arg2
, GLuint arg2Rep
,
374 GLuint arg2Mod
, GLuint arg3
, GLuint arg3Rep
,
377 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP
, 3, op
, dst
, dstMask
,
378 dstMod
, arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
,
379 arg2Mod
, arg3
, arg3Rep
, arg3Mod
);
383 _mesa_AlphaFragmentOp1ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
384 GLuint arg1Rep
, GLuint arg1Mod
)
386 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 1, op
, dst
, 0, dstMod
,
387 arg1
, arg1Rep
, arg1Mod
, 0, 0, 0, 0, 0, 0);
391 _mesa_AlphaFragmentOp2ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
392 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
393 GLuint arg2Rep
, GLuint arg2Mod
)
395 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 2, op
, dst
, 0, dstMod
,
396 arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, 0, 0,
401 _mesa_AlphaFragmentOp3ATI(GLenum op
, GLuint dst
, GLuint dstMod
, GLuint arg1
,
402 GLuint arg1Rep
, GLuint arg1Mod
, GLuint arg2
,
403 GLuint arg2Rep
, GLuint arg2Mod
, GLuint arg3
,
404 GLuint arg3Rep
, GLuint arg3Mod
)
406 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP
, 3, op
, dst
, 0, dstMod
,
407 arg1
, arg1Rep
, arg1Mod
, arg2
, arg2Rep
, arg2Mod
, arg3
,
412 _mesa_SetFragmentShaderConstantATI(GLuint dst
, const GLfloat
* value
)
414 GET_CURRENT_CONTEXT(ctx
);
415 GLuint dstindex
= dst
- GL_CON_0_ATI
;
416 struct ati_fragment_shader
*curProg
= ctx
->ATIFragmentShader
.Current
;
418 COPY_4V(curProg
->Constants
[dstindex
], value
);