cosmetic changes
[mesa.git] / src / mesa / shader / atifragshader.c
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 "glheader.h"
25 #include "context.h"
26 #include "hash.h"
27 #include "imports.h"
28 #include "macros.h"
29 #include "enums.h"
30 #include "mtypes.h"
31 #include "atifragshader.h"
32
33 #define MESA_DEBUG_ATI_FS 0
34
35 extern struct program _mesa_DummyProgram;
36
37 static void
38 new_inst(struct ati_fragment_shader *prog)
39 {
40 prog->Base.NumInstructions++;
41 }
42
43 #if MESA_DEBUG_ATI_FS
44 static char *
45 create_dst_mod_str(GLuint mod)
46 {
47 static char ret_str[1024];
48
49 _mesa_memset(ret_str, 0, 1024);
50 if (mod & GL_2X_BIT_ATI)
51 _mesa_strncat(ret_str, "|2X", 1024);
52
53 if (mod & GL_4X_BIT_ATI)
54 _mesa_strncat(ret_str, "|4X", 1024);
55
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);
64
65 if (mod & GL_SATURATE_BIT_ATI)
66 _mesa_strncat(ret_str, "|SAT", 1024);
67
68 if (_mesa_strlen(ret_str) == 0)
69 _mesa_strncat(ret_str, "NONE", 1024);
70 return ret_str;
71 }
72
73 static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
74 "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
75
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)
81 {
82 char *op_name;
83
84 op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
85
86 fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op),
87 _mesa_lookup_enum_by_nr(dst));
88 if (!optype)
89 fprintf(stderr, ", %d", dstMask);
90
91 fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
92
93 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1),
94 _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod);
95 if (arg_count>1)
96 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2),
97 _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod);
98 if (arg_count>2)
99 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3),
100 _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod);
101
102 fprintf(stderr,")\n");
103
104 }
105 #endif
106
107 GLuint GLAPIENTRY
108 _mesa_GenFragmentShadersATI(GLuint range)
109 {
110 GLuint first;
111 GLuint i;
112 GET_CURRENT_CONTEXT(ctx);
113
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);
117 }
118
119 return first;
120 }
121
122 void GLAPIENTRY
123 _mesa_BindFragmentShaderATI(GLuint id)
124 {
125 struct program *prog;
126 GET_CURRENT_CONTEXT(ctx);
127 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
128
129 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
130
131 if (curProg->Base.Id == id) {
132 return;
133 }
134
135 if (curProg->Base.Id != 0) {
136 curProg->Base.RefCount--;
137 if (curProg->Base.RefCount <= 0) {
138 _mesa_HashRemove(ctx->Shared->Programs, id);
139 }
140 }
141
142 /* Go bind */
143 if (id == 0) {
144 prog = ctx->Shared->DefaultFragmentShader;
145 }
146 else {
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);
151 if (!prog) {
152 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
153 return;
154 }
155 _mesa_HashInsert(ctx->Shared->Programs, id, prog);
156 }
157
158 }
159
160 /* do actual bind */
161 ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) prog;
162
163 ASSERT(ctx->ATIFragmentShader.Current);
164 if (prog)
165 prog->RefCount++;
166
167 /*if (ctx->Driver.BindProgram)
168 ctx->Driver.BindProgram(ctx, target, prog); */
169 }
170
171 void GLAPIENTRY
172 _mesa_DeleteFragmentShaderATI(GLuint id)
173 {
174 GET_CURRENT_CONTEXT(ctx);
175
176 if (id != 0) {
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);
181 }
182 else if (prog) {
183 if (ctx->ATIFragmentShader.Current &&
184 ctx->ATIFragmentShader.Current->Base.Id == id) {
185 _mesa_BindFragmentShaderATI(0);
186 }
187 }
188 if (!prog->DeletePending) {
189 prog->DeletePending = GL_TRUE;
190 prog->RefCount--;
191 }
192 if (prog->RefCount <= 0) {
193 _mesa_HashRemove(ctx->Shared->Programs, id);
194 ctx->Driver.DeleteProgram(ctx, prog);
195 }
196 }
197 }
198
199 void GLAPIENTRY
200 _mesa_BeginFragmentShaderATI(void)
201 {
202 GET_CURRENT_CONTEXT(ctx);
203
204 /* malloc the instructions here - not sure if the best place but its
205 a start */
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);
210
211 ctx->ATIFragmentShader.Current->cur_pass = 0;
212 ctx->ATIFragmentShader.Compiling = 1;
213 }
214
215 void GLAPIENTRY
216 _mesa_EndFragmentShaderATI(void)
217 {
218 GET_CURRENT_CONTEXT(ctx);
219 #if MESA_DEBUG_ATI_FS
220 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
221 GLint i;
222 #endif
223
224 ctx->ATIFragmentShader.Compiling = 0;
225
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];
234
235 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
236 op1, op1_enum, count1);
237 }
238 #endif
239 }
240
241 void GLAPIENTRY
242 _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
243 {
244 GET_CURRENT_CONTEXT(ctx);
245 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
246 GLint ci;
247 struct atifs_instruction *curI;
248
249 new_inst(curProg);
250 ci = curProg->Base.NumInstructions - 1;
251 /* some validation
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))
256 */
257
258 /* add the instructions */
259 curI = &curProg->Instructions[ci];
260
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;
265
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));
270 #endif
271 }
272
273 void GLAPIENTRY
274 _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
275 {
276 GET_CURRENT_CONTEXT(ctx);
277 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
278 GLint ci;
279 struct atifs_instruction *curI;
280
281 new_inst(curProg);
282
283 ci = curProg->Base.NumInstructions - 1;
284 /* add the instructions */
285 curI = &curProg->Instructions[ci];
286
287 curI->Opcode[0] = ATI_FRAGMENT_SHADER_SAMPLE_OP;
288 curI->DstReg[0].Index = dst;
289 curI->DstReg[0].Swizzle = swizzle;
290
291 curI->SrcReg[0][0].Index = interp;
292
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));
297 #endif
298 }
299
300 static void
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)
306 {
307 GET_CURRENT_CONTEXT(ctx);
308 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
309 GLint ci;
310 struct atifs_instruction *curI;
311
312 /* decide whether this is a new instruction or not ... all color instructions are new */
313 if (optype == 0)
314 new_inst(curProg);
315
316 ci = curProg->Base.NumInstructions - 1;
317
318 /* add the instructions */
319 curI = &curProg->Instructions[ci];
320
321 curI->Opcode[optype] = op;
322
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;
327
328 if (arg2) {
329 curI->SrcReg[optype][1].Index = arg2;
330 curI->SrcReg[optype][1].argRep = arg2Rep;
331 curI->SrcReg[optype][1].argMod = arg2Mod;
332 }
333
334 if (arg3) {
335 curI->SrcReg[optype][2].Index = arg3;
336 curI->SrcReg[optype][2].argRep = arg3Rep;
337 curI->SrcReg[optype][2].argMod = arg3Mod;
338 }
339
340 curI->DstReg[optype].Index = dst;
341 curI->DstReg[optype].dstMod = dstMod;
342 curI->DstReg[optype].dstMask = dstMask;
343
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);
346 #endif
347
348 }
349
350 void GLAPIENTRY
351 _mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
352 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
353 GLuint arg1Mod)
354 {
355 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
356 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
357 }
358
359 void GLAPIENTRY
360 _mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
361 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
362 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
363 GLuint arg2Mod)
364 {
365 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
366 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
367 arg2Mod, 0, 0, 0);
368 }
369
370 void GLAPIENTRY
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,
375 GLuint arg3Mod)
376 {
377 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
378 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
379 arg2Mod, arg3, arg3Rep, arg3Mod);
380 }
381
382 void GLAPIENTRY
383 _mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
384 GLuint arg1Rep, GLuint arg1Mod)
385 {
386 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
387 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
388 }
389
390 void GLAPIENTRY
391 _mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
392 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
393 GLuint arg2Rep, GLuint arg2Mod)
394 {
395 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
396 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
397 0);
398 }
399
400 void GLAPIENTRY
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)
405 {
406 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
407 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
408 arg3Rep, arg3Mod);
409 }
410
411 void GLAPIENTRY
412 _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
413 {
414 GET_CURRENT_CONTEXT(ctx);
415 GLuint dstindex = dst - GL_CON_0_ATI;
416 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
417
418 COPY_4V(curProg->Constants[dstindex], value);
419 }