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 0
189 if (!prog->DeletePending) {
190 prog->DeletePending = GL_TRUE;
191 prog->RefCount--;
192 }
193 if (prog->RefCount <= 0) {
194 _mesa_HashRemove(ctx->Shared->Programs, id);
195 ctx->Driver.DeleteProgram(ctx, prog);
196 }
197 #else
198 /* The ID is immediately available for re-use now */
199 _mesa_HashRemove(ctx->Shared->Programs, id);
200 prog->RefCount--;
201 if (prog->RefCount <= 0) {
202 ctx->Driver.DeleteProgram(ctx, prog);
203 }
204 #endif
205 }
206 }
207
208 void GLAPIENTRY
209 _mesa_BeginFragmentShaderATI(void)
210 {
211 GET_CURRENT_CONTEXT(ctx);
212
213 /* malloc the instructions here - not sure if the best place but its
214 a start */
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);
219
220 ctx->ATIFragmentShader.Current->cur_pass = 0;
221 ctx->ATIFragmentShader.Compiling = 1;
222 }
223
224 void GLAPIENTRY
225 _mesa_EndFragmentShaderATI(void)
226 {
227 GET_CURRENT_CONTEXT(ctx);
228 #if MESA_DEBUG_ATI_FS
229 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
230 GLint i;
231 #endif
232
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];
244
245 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
246 op1, op1_enum, count1);
247 }
248 #endif
249 }
250
251 void GLAPIENTRY
252 _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
253 {
254 GET_CURRENT_CONTEXT(ctx);
255 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
256 GLint ci;
257 struct atifs_instruction *curI;
258
259 if (ctx->ATIFragmentShader.Current->cur_pass==1)
260 ctx->ATIFragmentShader.Current->cur_pass=2;
261
262 new_inst(curProg);
263 ci = curProg->Base.NumInstructions - 1;
264 /* some validation
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))
269 */
270
271 /* add the instructions */
272 curI = &curProg->Instructions[ci];
273
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;
278
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));
283 #endif
284 }
285
286 void GLAPIENTRY
287 _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
288 {
289 GET_CURRENT_CONTEXT(ctx);
290 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
291 GLint ci;
292 struct atifs_instruction *curI;
293
294 if (ctx->ATIFragmentShader.Current->cur_pass==1)
295 ctx->ATIFragmentShader.Current->cur_pass=2;
296
297
298 new_inst(curProg);
299
300 ci = curProg->Base.NumInstructions - 1;
301 /* add the instructions */
302 curI = &curProg->Instructions[ci];
303
304 curI->Opcode[0] = ATI_FRAGMENT_SHADER_SAMPLE_OP;
305 curI->DstReg[0].Index = dst;
306 curI->DstReg[0].Swizzle = swizzle;
307
308 curI->SrcReg[0][0].Index = interp;
309
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));
314 #endif
315 }
316
317 static void
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)
323 {
324 GET_CURRENT_CONTEXT(ctx);
325 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
326 GLint ci;
327 struct atifs_instruction *curI;
328
329 if (ctx->ATIFragmentShader.Current->cur_pass==0)
330 ctx->ATIFragmentShader.Current->cur_pass=1;
331
332 /* decide whether this is a new instruction or not ... all color instructions are new */
333 if (optype == 0)
334 new_inst(curProg);
335
336 ci = curProg->Base.NumInstructions - 1;
337
338 /* add the instructions */
339 curI = &curProg->Instructions[ci];
340
341 curI->Opcode[optype] = op;
342
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;
347
348 if (arg2) {
349 curI->SrcReg[optype][1].Index = arg2;
350 curI->SrcReg[optype][1].argRep = arg2Rep;
351 curI->SrcReg[optype][1].argMod = arg2Mod;
352 }
353
354 if (arg3) {
355 curI->SrcReg[optype][2].Index = arg3;
356 curI->SrcReg[optype][2].argRep = arg3Rep;
357 curI->SrcReg[optype][2].argMod = arg3Mod;
358 }
359
360 curI->DstReg[optype].Index = dst;
361 curI->DstReg[optype].dstMod = dstMod;
362 curI->DstReg[optype].dstMask = dstMask;
363
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);
366 #endif
367
368 }
369
370 void GLAPIENTRY
371 _mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
372 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
373 GLuint arg1Mod)
374 {
375 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
376 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
377 }
378
379 void GLAPIENTRY
380 _mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
381 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
382 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
383 GLuint arg2Mod)
384 {
385 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
386 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
387 arg2Mod, 0, 0, 0);
388 }
389
390 void GLAPIENTRY
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,
395 GLuint arg3Mod)
396 {
397 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
398 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
399 arg2Mod, arg3, arg3Rep, arg3Mod);
400 }
401
402 void GLAPIENTRY
403 _mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
404 GLuint arg1Rep, GLuint arg1Mod)
405 {
406 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
407 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
408 }
409
410 void GLAPIENTRY
411 _mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
412 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
413 GLuint arg2Rep, GLuint arg2Mod)
414 {
415 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
416 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
417 0);
418 }
419
420 void GLAPIENTRY
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)
425 {
426 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
427 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
428 arg3Rep, arg3Mod);
429 }
430
431 void GLAPIENTRY
432 _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
433 {
434 GET_CURRENT_CONTEXT(ctx);
435 GLuint dstindex = dst - GL_CON_0_ATI;
436 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
437
438 COPY_4V(curProg->Constants[dstindex], value);
439 }