blob: fb2fa4b95f9578cf863eddda64c5f03f023b989a [file] [log] [blame]
Dave Airlie7f752fe2004-12-19 03:06:59 +00001/**
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
Brian Paulbbd28712008-09-18 12:26:54 -060024#include "main/glheader.h"
25#include "main/context.h"
26#include "main/hash.h"
27#include "main/imports.h"
28#include "main/macros.h"
29#include "main/enums.h"
30#include "main/mtypes.h"
Dave Airlie7f752fe2004-12-19 03:06:59 +000031#include "atifragshader.h"
32
33#define MESA_DEBUG_ATI_FS 0
34
Brian Paul63d68302005-11-19 16:43:04 +000035static struct ati_fragment_shader DummyShader;
36
37
38/**
39 * Allocate and initialize a new ATI fragment shader object.
40 */
41struct ati_fragment_shader *
42_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id)
43{
44 struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
45 (void) ctx;
46 if (s) {
47 s->Id = id;
48 s->RefCount = 1;
49 }
50 return s;
51}
52
53
54/**
55 * Delete the given ati fragment shader
56 */
57void
58_mesa_delete_ati_fragment_shader(GLcontext *ctx, struct ati_fragment_shader *s)
59{
60 GLuint i;
61 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
62 if (s->Instructions[i])
63 _mesa_free(s->Instructions[i]);
64 if (s->SetupInst[i])
65 _mesa_free(s->SetupInst[i]);
66 }
67 _mesa_free(s);
68}
69
70
Dave Airlie7f752fe2004-12-19 03:06:59 +000071
72static void
Roland Scheideggerf519a772005-09-02 01:11:53 +000073new_arith_inst(struct ati_fragment_shader *prog)
Dave Airlie7f752fe2004-12-19 03:06:59 +000074{
Roland Scheideggerf519a772005-09-02 01:11:53 +000075/* set "default" instruction as not all may get defined.
76 there is no specified way to express a nop with ati fragment shaders we use
77 GL_NONE as the op enum and just set some params to 0 - so nothing to do here */
78 prog->numArithInstr[prog->cur_pass >> 1]++;
79}
80
81static void
82new_tex_inst(struct ati_fragment_shader *prog)
83{
84}
85
86static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
87{
88 if (optype == curProg->last_optype) {
89 curProg->last_optype = 1;
90 }
Dave Airlie7f752fe2004-12-19 03:06:59 +000091}
92
93#if MESA_DEBUG_ATI_FS
94static char *
95create_dst_mod_str(GLuint mod)
96{
97 static char ret_str[1024];
98
Kenneth Graunke26f8fad2010-02-18 23:51:00 -080099 memset(ret_str, 0, 1024);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000100 if (mod & GL_2X_BIT_ATI)
Kenneth Graunke8ff76242010-02-18 23:50:52 -0800101 strncat(ret_str, "|2X", 1024);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000102
103 if (mod & GL_4X_BIT_ATI)
Kenneth Graunke8ff76242010-02-18 23:50:52 -0800104 strncat(ret_str, "|4X", 1024);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000105
106 if (mod & GL_8X_BIT_ATI)
Kenneth Graunke8ff76242010-02-18 23:50:52 -0800107 strncat(ret_str, "|8X", 1024);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000108 if (mod & GL_HALF_BIT_ATI)
Kenneth Graunke8ff76242010-02-18 23:50:52 -0800109 strncat(ret_str, "|HA", 1024);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000110 if (mod & GL_QUARTER_BIT_ATI)
Kenneth Graunke8ff76242010-02-18 23:50:52 -0800111 strncat(ret_str, "|QU", 1024);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000112 if (mod & GL_EIGHTH_BIT_ATI)
Kenneth Graunke8ff76242010-02-18 23:50:52 -0800113 strncat(ret_str, "|EI", 1024);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000114
115 if (mod & GL_SATURATE_BIT_ATI)
Kenneth Graunke8ff76242010-02-18 23:50:52 -0800116 strncat(ret_str, "|SAT", 1024);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000117
Kenneth Graunke21d0c702010-02-18 23:50:55 -0800118 if (strlen(ret_str) == 0)
Kenneth Graunke8ff76242010-02-18 23:50:52 -0800119 strncat(ret_str, "NONE", 1024);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000120 return ret_str;
121}
122
123static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
124 "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
125
126static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
127 GLuint dstMask, GLuint dstMod, GLuint arg1,
128 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
129 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
130 GLuint arg3Rep, GLuint arg3Mod)
131{
132 char *op_name;
133
134 op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
135
136 fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op),
137 _mesa_lookup_enum_by_nr(dst));
138 if (!optype)
139 fprintf(stderr, ", %d", dstMask);
140
141 fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
142
143 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1),
144 _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod);
145 if (arg_count>1)
146 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2),
147 _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod);
148 if (arg_count>2)
149 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3),
150 _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod);
151
152 fprintf(stderr,")\n");
153
154}
155#endif
156
Roland Scheideggerf519a772005-09-02 01:11:53 +0000157static int check_arith_arg(struct ati_fragment_shader *curProg,
158 GLuint optype, GLuint arg, GLuint argRep)
159{
160 GET_CURRENT_CONTEXT(ctx);
161
162 if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) &&
163 ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) &&
164 (arg != GL_ZERO) && (arg != GL_ONE) &&
165 (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) {
166 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)");
167 return 0;
168 }
169 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
170 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
171 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
172 return 0;
173 }
174 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
175 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
176 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
177 return 0;
178 }
179 if ((curProg->cur_pass == 1) &&
180 ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
181 curProg->interpinp1 = GL_TRUE;
182 }
183 return 1;
184}
185
Dave Airlie7f752fe2004-12-19 03:06:59 +0000186GLuint GLAPIENTRY
187_mesa_GenFragmentShadersATI(GLuint range)
188{
189 GLuint first;
190 GLuint i;
191 GET_CURRENT_CONTEXT(ctx);
192
Roland Scheideggerf519a772005-09-02 01:11:53 +0000193 if (range == 0) {
194 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)");
195 return 0;
196 }
197
198 if (ctx->ATIFragmentShader.Compiling) {
199 _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)");
200 return 0;
201 }
202
Brian Paul63d68302005-11-19 16:43:04 +0000203 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000204 for (i = 0; i < range; i++) {
Brian Paul63d68302005-11-19 16:43:04 +0000205 _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000206 }
207
208 return first;
209}
210
211void GLAPIENTRY
212_mesa_BindFragmentShaderATI(GLuint id)
213{
Dave Airlie7f752fe2004-12-19 03:06:59 +0000214 GET_CURRENT_CONTEXT(ctx);
215 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Brian Paul63d68302005-11-19 16:43:04 +0000216 struct ati_fragment_shader *newProg;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000217
Roland Scheideggerf519a772005-09-02 01:11:53 +0000218 if (ctx->ATIFragmentShader.Compiling) {
219 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
220 return;
221 }
222
Dave Airlie7f752fe2004-12-19 03:06:59 +0000223 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
224
Brian Paul63d68302005-11-19 16:43:04 +0000225 if (curProg->Id == id) {
Dave Airlie7f752fe2004-12-19 03:06:59 +0000226 return;
227 }
228
Brian Paul63d68302005-11-19 16:43:04 +0000229 /* unbind current */
230 if (curProg->Id != 0) {
231 curProg->RefCount--;
232 if (curProg->RefCount <= 0) {
233 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000234 }
235 }
236
Brian Paul63d68302005-11-19 16:43:04 +0000237 /* find new shader */
Dave Airlie7f752fe2004-12-19 03:06:59 +0000238 if (id == 0) {
Brian Paul63d68302005-11-19 16:43:04 +0000239 newProg = ctx->Shared->DefaultFragmentShader;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000240 }
241 else {
Brian Paul63d68302005-11-19 16:43:04 +0000242 newProg = (struct ati_fragment_shader *)
243 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
244 if (!newProg || newProg == &DummyShader) {
Dave Airlie7f752fe2004-12-19 03:06:59 +0000245 /* allocate a new program now */
Brian Paul63d68302005-11-19 16:43:04 +0000246 newProg = _mesa_new_ati_fragment_shader(ctx, id);
247 if (!newProg) {
Dave Airlie7f752fe2004-12-19 03:06:59 +0000248 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
249 return;
250 }
Brian Paul63d68302005-11-19 16:43:04 +0000251 _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000252 }
253
254 }
255
256 /* do actual bind */
Brian Paul63d68302005-11-19 16:43:04 +0000257 ctx->ATIFragmentShader.Current = newProg;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000258
259 ASSERT(ctx->ATIFragmentShader.Current);
Brian Paul63d68302005-11-19 16:43:04 +0000260 if (newProg)
261 newProg->RefCount++;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000262
263 /*if (ctx->Driver.BindProgram)
264 ctx->Driver.BindProgram(ctx, target, prog); */
265}
266
267void GLAPIENTRY
268_mesa_DeleteFragmentShaderATI(GLuint id)
269{
270 GET_CURRENT_CONTEXT(ctx);
271
Roland Scheideggerf519a772005-09-02 01:11:53 +0000272 if (ctx->ATIFragmentShader.Compiling) {
273 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
274 return;
275 }
276
Dave Airlie7f752fe2004-12-19 03:06:59 +0000277 if (id != 0) {
Brian Paul63d68302005-11-19 16:43:04 +0000278 struct ati_fragment_shader *prog = (struct ati_fragment_shader *)
279 _mesa_HashLookup(ctx->Shared->ATIShaders, id);
280 if (prog == &DummyShader) {
281 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000282 }
283 else if (prog) {
284 if (ctx->ATIFragmentShader.Current &&
Brian Paul63d68302005-11-19 16:43:04 +0000285 ctx->ATIFragmentShader.Current->Id == id) {
Roland Scheideggerce335072005-09-08 00:12:57 +0000286 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000287 _mesa_BindFragmentShaderATI(0);
288 }
289 }
Brian Paul63d68302005-11-19 16:43:04 +0000290
Brian Paulea2943e2005-01-20 04:02:02 +0000291 /* The ID is immediately available for re-use now */
Brian Paul63d68302005-11-19 16:43:04 +0000292 _mesa_HashRemove(ctx->Shared->ATIShaders, id);
Eric Anholtb08ed4f2009-12-22 12:38:11 -0800293 if (prog) {
294 prog->RefCount--;
295 if (prog->RefCount <= 0) {
296 _mesa_free(prog);
297 }
Brian Paulea2943e2005-01-20 04:02:02 +0000298 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000299 }
300}
301
Brian Paul63d68302005-11-19 16:43:04 +0000302
Dave Airlie7f752fe2004-12-19 03:06:59 +0000303void GLAPIENTRY
304_mesa_BeginFragmentShaderATI(void)
305{
Roland Scheideggerf519a772005-09-02 01:11:53 +0000306 GLint i;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000307 GET_CURRENT_CONTEXT(ctx);
308
Roland Scheideggerf519a772005-09-02 01:11:53 +0000309 if (ctx->ATIFragmentShader.Compiling) {
310 _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
311 return;
312 }
313
Roland Scheideggerce335072005-09-08 00:12:57 +0000314 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
315
Roland Scheideggerf519a772005-09-02 01:11:53 +0000316 /* if the shader was already defined free instructions and get new ones
317 (or, could use the same mem but would need to reinitialize) */
318 /* no idea if it's allowed to redefine a shader */
319 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
320 if (ctx->ATIFragmentShader.Current->Instructions[i])
321 _mesa_free(ctx->ATIFragmentShader.Current->Instructions[i]);
322 if (ctx->ATIFragmentShader.Current->SetupInst[i])
323 _mesa_free(ctx->ATIFragmentShader.Current->SetupInst[i]);
324 }
325
Dave Airlie7f752fe2004-12-19 03:06:59 +0000326 /* malloc the instructions here - not sure if the best place but its
327 a start */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000328 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
329 ctx->ATIFragmentShader.Current->Instructions[i] =
330 (struct atifs_instruction *)
331 _mesa_calloc(sizeof(struct atifs_instruction) *
332 (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
333 ctx->ATIFragmentShader.Current->SetupInst[i] =
334 (struct atifs_setupinst *)
335 _mesa_calloc(sizeof(struct atifs_setupinst) *
336 (MAX_NUM_FRAGMENT_REGISTERS_ATI));
337 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000338
Roland Scheideggerf519a772005-09-02 01:11:53 +0000339/* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
Brian Paul63d68302005-11-19 16:43:04 +0000340 ctx->ATIFragmentShader.Current->LocalConstDef = 0;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000341 ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
342 ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
343 ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
344 ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
345 ctx->ATIFragmentShader.Current->NumPasses = 0;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000346 ctx->ATIFragmentShader.Current->cur_pass = 0;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000347 ctx->ATIFragmentShader.Current->last_optype = 0;
348 ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
349 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
350 ctx->ATIFragmentShader.Current->swizzlerq = 0;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000351 ctx->ATIFragmentShader.Compiling = 1;
352}
353
354void GLAPIENTRY
355_mesa_EndFragmentShaderATI(void)
356{
357 GET_CURRENT_CONTEXT(ctx);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000358 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000359#if MESA_DEBUG_ATI_FS
360 GLint i, j;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000361#endif
362
Roland Scheideggerf519a772005-09-02 01:11:53 +0000363 if (!ctx->ATIFragmentShader.Compiling) {
364 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
365 return;
366 }
367 if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
368 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
369 /* according to spec, DON'T return here */
370 }
371
372 match_pair_inst(curProg, 0);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000373 ctx->ATIFragmentShader.Compiling = 0;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000374 ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
375 if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
376 (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
377 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
378 }
379 if (ctx->ATIFragmentShader.Current->cur_pass > 1)
380 ctx->ATIFragmentShader.Current->NumPasses = 2;
Brian Paul4ac9c802010-02-04 16:49:35 -0700381 else
382 ctx->ATIFragmentShader.Current->NumPasses = 1;
383
384 ctx->ATIFragmentShader.Current->cur_pass = 0;
385
Dave Airlie7f752fe2004-12-19 03:06:59 +0000386#if MESA_DEBUG_ATI_FS
Roland Scheideggerf519a772005-09-02 01:11:53 +0000387 for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
388 for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
389 GLuint op = curProg->SetupInst[j][i].Opcode;
390 const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0";
391 GLuint src = curProg->SetupInst[j][i].src;
392 GLuint swizzle = curProg->SetupInst[j][i].swizzle;
393 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
394 swizzle);
395 }
396 for (i = 0; i < curProg->numArithInstr[j]; i++) {
397 GLuint op0 = curProg->Instructions[j][i].Opcode[0];
398 GLuint op1 = curProg->Instructions[j][i].Opcode[1];
399 const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0";
400 const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0";
401 GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
402 GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
403 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
Dave Airlie7f752fe2004-12-19 03:06:59 +0000404 op1, op1_enum, count1);
Roland Scheideggerf519a772005-09-02 01:11:53 +0000405 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000406 }
407#endif
Brian Paul4ac9c802010-02-04 16:49:35 -0700408
409 if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, NULL)) {
410 ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
411 /* XXX is this the right error? */
412 _mesa_error(ctx, GL_INVALID_OPERATION,
413 "glEndFragmentShaderATI(driver rejected shader)");
414 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000415}
416
417void GLAPIENTRY
418_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
419{
420 GET_CURRENT_CONTEXT(ctx);
421 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000422 struct atifs_setupinst *curI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000423
Roland Scheideggerf519a772005-09-02 01:11:53 +0000424 if (!ctx->ATIFragmentShader.Compiling) {
425 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
426 return;
427 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000428
Roland Scheideggerf519a772005-09-02 01:11:53 +0000429 if (curProg->cur_pass == 1) {
430 match_pair_inst(curProg, 0);
431 curProg->cur_pass = 2;
432 }
433 if ((curProg->cur_pass > 2) ||
434 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
435 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
436 return;
437 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000438 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
439 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000440 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
441 return;
442 }
443 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000444 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
445 ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000446 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
447 return;
448 }
449 if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
450 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
451 return;
452 }
Brian872d1792007-08-07 21:42:34 +0100453 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000454 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
455 return;
456 }
457 if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
458 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
459 return;
460 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000461 if (coord <= GL_TEXTURE7_ARB) {
462 GLuint tmp = coord - GL_TEXTURE0_ARB;
463 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
464 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000465 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
466 return;
467 } else {
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000468 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
Roland Scheideggerf519a772005-09-02 01:11:53 +0000469 }
470 }
471
472 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
473 new_tex_inst(curProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000474
475 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000476 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
Dave Airlie7f752fe2004-12-19 03:06:59 +0000477
Roland Scheideggerf519a772005-09-02 01:11:53 +0000478 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
479 curI->src = coord;
480 curI->swizzle = swizzle;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000481
482#if MESA_DEBUG_ATI_FS
483 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
484 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
485 _mesa_lookup_enum_by_nr(swizzle));
486#endif
487}
488
489void GLAPIENTRY
490_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
491{
492 GET_CURRENT_CONTEXT(ctx);
493 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000494 struct atifs_setupinst *curI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000495
Roland Scheideggerf519a772005-09-02 01:11:53 +0000496 if (!ctx->ATIFragmentShader.Compiling) {
497 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
498 return;
499 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000500
Roland Scheideggerf519a772005-09-02 01:11:53 +0000501 if (curProg->cur_pass == 1) {
502 match_pair_inst(curProg, 0);
503 curProg->cur_pass = 2;
504 }
505 if ((curProg->cur_pass > 2) ||
506 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
507 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
508 return;
509 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000510 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
511 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000512 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
513 return;
514 }
515 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000516 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
517 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000518 /* is this texture5 or texture7? spec is a bit unclear there */
519 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
520 return;
521 }
522 if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
523 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
524 return;
525 }
Brian872d1792007-08-07 21:42:34 +0100526 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000527 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
528 return;
529 }
530 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
531 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
532 return;
533 }
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000534 if (interp <= GL_TEXTURE7_ARB) {
535 GLuint tmp = interp - GL_TEXTURE0_ARB;
536 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
537 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
Roland Scheideggerf519a772005-09-02 01:11:53 +0000538 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
539 return;
540 } else {
Roland Scheideggerf4ff4d32005-09-08 13:41:54 +0000541 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
Roland Scheideggerf519a772005-09-02 01:11:53 +0000542 }
543 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000544
Roland Scheideggerf519a772005-09-02 01:11:53 +0000545 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
546 new_tex_inst(curProg);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000547
Dave Airlie7f752fe2004-12-19 03:06:59 +0000548 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000549 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
Dave Airlie7f752fe2004-12-19 03:06:59 +0000550
Roland Scheideggerf519a772005-09-02 01:11:53 +0000551 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
552 curI->src = interp;
553 curI->swizzle = swizzle;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000554
555#if MESA_DEBUG_ATI_FS
556 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
557 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
558 _mesa_lookup_enum_by_nr(swizzle));
559#endif
560}
561
562static void
563_mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
564 GLuint dstMask, GLuint dstMod, GLuint arg1,
565 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
566 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
567 GLuint arg3Rep, GLuint arg3Mod)
568{
569 GET_CURRENT_CONTEXT(ctx);
570 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
571 GLint ci;
572 struct atifs_instruction *curI;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000573 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000574
Roland Scheideggerf519a772005-09-02 01:11:53 +0000575 if (!ctx->ATIFragmentShader.Compiling) {
576 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
577 return;
578 }
Dave Airlie3aa69b32005-01-30 06:24:30 +0000579
Roland Scheideggerf519a772005-09-02 01:11:53 +0000580 if (curProg->cur_pass==0)
581 curProg->cur_pass=1;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000582
Roland Scheideggerf519a772005-09-02 01:11:53 +0000583 else if (curProg->cur_pass==2)
584 curProg->cur_pass=3;
585
586 /* decide whether this is a new instruction or not ... all color instructions are new,
587 and alpha instructions might also be new if there was no preceding color inst */
588 if ((optype == 0) || (curProg->last_optype == optype)) {
589 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
590 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
591 return;
592 }
593 /* easier to do that here slight side effect invalid instr will still be inserted as nops */
594 match_pair_inst(curProg, optype);
595 new_arith_inst(curProg);
596 }
597 curProg->last_optype = optype;
598 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000599
600 /* add the instructions */
Roland Scheideggerf519a772005-09-02 01:11:53 +0000601 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
602
603 /* error checking */
604 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
605 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
606 return;
607 }
608 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
609 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
610 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
611 (modtemp != GL_EIGHTH_BIT_ATI)) {
612 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
613 return;
614 }
615 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
616 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
617 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
618 return;
619 }
620 if (optype == 1) {
621 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
622 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
623 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
624 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
625 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
626 return;
627 }
628 }
629 if ((op == GL_DOT4_ATI) &&
630 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
631 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
632 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
633 }
634
635 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
636 return;
637 }
638 if (arg2) {
639 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
640 return;
641 }
642 }
643 if (arg3) {
644 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
645 return;
646 }
647 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
648 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
649 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
650 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
651 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
652 return;
653 }
654 }
655
656 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
Dave Airlie7f752fe2004-12-19 03:06:59 +0000657
658 curI->Opcode[optype] = op;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000659 curI->SrcReg[optype][0].Index = arg1;
660 curI->SrcReg[optype][0].argRep = arg1Rep;
661 curI->SrcReg[optype][0].argMod = arg1Mod;
662 curI->ArgCount[optype] = arg_count;
663
664 if (arg2) {
665 curI->SrcReg[optype][1].Index = arg2;
666 curI->SrcReg[optype][1].argRep = arg2Rep;
667 curI->SrcReg[optype][1].argMod = arg2Mod;
668 }
669
670 if (arg3) {
671 curI->SrcReg[optype][2].Index = arg3;
672 curI->SrcReg[optype][2].argRep = arg3Rep;
673 curI->SrcReg[optype][2].argMod = arg3Mod;
674 }
675
676 curI->DstReg[optype].Index = dst;
677 curI->DstReg[optype].dstMod = dstMod;
678 curI->DstReg[optype].dstMask = dstMask;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000679
Dave Airlie7f752fe2004-12-19 03:06:59 +0000680#if MESA_DEBUG_ATI_FS
681 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
682#endif
683
684}
685
686void GLAPIENTRY
687_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
688 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
689 GLuint arg1Mod)
690{
691 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
692 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
693}
694
695void GLAPIENTRY
696_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
697 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
698 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
699 GLuint arg2Mod)
700{
701 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
702 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
703 arg2Mod, 0, 0, 0);
704}
705
706void GLAPIENTRY
707_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
708 GLuint dstMod, GLuint arg1, GLuint arg1Rep,
709 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
710 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
711 GLuint arg3Mod)
712{
713 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
714 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
715 arg2Mod, arg3, arg3Rep, arg3Mod);
716}
717
718void GLAPIENTRY
719_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
720 GLuint arg1Rep, GLuint arg1Mod)
721{
722 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
723 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
724}
725
726void GLAPIENTRY
727_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
728 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
729 GLuint arg2Rep, GLuint arg2Mod)
730{
731 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
732 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
733 0);
734}
735
736void GLAPIENTRY
737_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
738 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
739 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
740 GLuint arg3Rep, GLuint arg3Mod)
741{
742 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
743 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
744 arg3Rep, arg3Mod);
745}
746
747void GLAPIENTRY
748_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
749{
Karl Schultze81cbd82005-09-05 13:45:23 +0000750 GLuint dstindex;
Dave Airlie7f752fe2004-12-19 03:06:59 +0000751 GET_CURRENT_CONTEXT(ctx);
Dave Airlie7f752fe2004-12-19 03:06:59 +0000752
Roland Scheideggerf519a772005-09-02 01:11:53 +0000753 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
754 /* spec says nothing about what should happen here but we can't just segfault...*/
755 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
756 return;
757 }
758
Karl Schultze81cbd82005-09-05 13:45:23 +0000759 dstindex = dst - GL_CON_0_ATI;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000760 if (ctx->ATIFragmentShader.Compiling) {
761 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
762 COPY_4V(curProg->Constants[dstindex], value);
Brian Paul63d68302005-11-19 16:43:04 +0000763 curProg->LocalConstDef |= 1 << dstindex;
Roland Scheideggerf519a772005-09-02 01:11:53 +0000764 }
765 else {
Roland Scheideggerce335072005-09-08 00:12:57 +0000766 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian Paul63d68302005-11-19 16:43:04 +0000767 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
Roland Scheideggerf519a772005-09-02 01:11:53 +0000768 }
Dave Airlie7f752fe2004-12-19 03:06:59 +0000769}