~ubuntu-branches/ubuntu/precise/mesa-lts-quantal/precise-updates

« back to all changes in this revision

Viewing changes to src/mesa/main/atifragshader.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2012-11-30 20:58:34 UTC
  • Revision ID: package-import@ubuntu.com-20121130205834-gazuvne3fpwlf012
Tags: upstream-9.0
ImportĀ upstreamĀ versionĀ 9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "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/mfeatures.h"
 
30
#include "main/enums.h"
 
31
#include "main/mtypes.h"
 
32
#include "main/dispatch.h"
 
33
#include "main/atifragshader.h"
 
34
 
 
35
#if FEATURE_ATI_fragment_shader
 
36
 
 
37
#define MESA_DEBUG_ATI_FS 0
 
38
 
 
39
static struct ati_fragment_shader DummyShader;
 
40
 
 
41
 
 
42
void
 
43
_mesa_init_ati_fragment_shader_dispatch(struct _glapi_table *disp)
 
44
{
 
45
   SET_GenFragmentShadersATI(disp, _mesa_GenFragmentShadersATI);
 
46
   SET_BindFragmentShaderATI(disp, _mesa_BindFragmentShaderATI);
 
47
   SET_DeleteFragmentShaderATI(disp, _mesa_DeleteFragmentShaderATI);
 
48
   SET_BeginFragmentShaderATI(disp, _mesa_BeginFragmentShaderATI);
 
49
   SET_EndFragmentShaderATI(disp, _mesa_EndFragmentShaderATI);
 
50
   SET_PassTexCoordATI(disp, _mesa_PassTexCoordATI);
 
51
   SET_SampleMapATI(disp, _mesa_SampleMapATI);
 
52
   SET_ColorFragmentOp1ATI(disp, _mesa_ColorFragmentOp1ATI);
 
53
   SET_ColorFragmentOp2ATI(disp, _mesa_ColorFragmentOp2ATI);
 
54
   SET_ColorFragmentOp3ATI(disp, _mesa_ColorFragmentOp3ATI);
 
55
   SET_AlphaFragmentOp1ATI(disp, _mesa_AlphaFragmentOp1ATI);
 
56
   SET_AlphaFragmentOp2ATI(disp, _mesa_AlphaFragmentOp2ATI);
 
57
   SET_AlphaFragmentOp3ATI(disp, _mesa_AlphaFragmentOp3ATI);
 
58
   SET_SetFragmentShaderConstantATI(disp, _mesa_SetFragmentShaderConstantATI);
 
59
}
 
60
 
 
61
 
 
62
/**
 
63
 * Allocate and initialize a new ATI fragment shader object.
 
64
 */
 
65
struct ati_fragment_shader *
 
66
_mesa_new_ati_fragment_shader(struct gl_context *ctx, GLuint id)
 
67
{
 
68
   struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
 
69
   (void) ctx;
 
70
   if (s) {
 
71
      s->Id = id;
 
72
      s->RefCount = 1;
 
73
   }
 
74
   return s;
 
75
}
 
76
 
 
77
 
 
78
/**
 
79
 * Delete the given ati fragment shader
 
80
 */
 
81
void
 
82
_mesa_delete_ati_fragment_shader(struct gl_context *ctx, struct ati_fragment_shader *s)
 
83
{
 
84
   GLuint i;
 
85
   for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
 
86
      if (s->Instructions[i])
 
87
         free(s->Instructions[i]);
 
88
      if (s->SetupInst[i])
 
89
         free(s->SetupInst[i]);
 
90
   }
 
91
   free(s);
 
92
}
 
93
 
 
94
 
 
95
 
 
96
static void
 
97
new_arith_inst(struct ati_fragment_shader *prog)
 
98
{
 
99
/* set "default" instruction as not all may get defined.
 
100
   there is no specified way to express a nop with ati fragment shaders we use
 
101
   GL_NONE as the op enum and just set some params to 0 - so nothing to do here */
 
102
   prog->numArithInstr[prog->cur_pass >> 1]++;
 
103
}
 
104
 
 
105
static void
 
106
new_tex_inst(struct ati_fragment_shader *prog)
 
107
{
 
108
}
 
109
 
 
110
static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
 
111
{
 
112
   if (optype == curProg->last_optype) {
 
113
      curProg->last_optype = 1;
 
114
   }
 
115
}
 
116
 
 
117
#if MESA_DEBUG_ATI_FS
 
118
static char *
 
119
create_dst_mod_str(GLuint mod)
 
120
{
 
121
   static char ret_str[1024];
 
122
 
 
123
   memset(ret_str, 0, 1024);
 
124
   if (mod & GL_2X_BIT_ATI)
 
125
      strncat(ret_str, "|2X", 1024);
 
126
 
 
127
   if (mod & GL_4X_BIT_ATI)
 
128
      strncat(ret_str, "|4X", 1024);
 
129
 
 
130
   if (mod & GL_8X_BIT_ATI)
 
131
      strncat(ret_str, "|8X", 1024);
 
132
   if (mod & GL_HALF_BIT_ATI)
 
133
      strncat(ret_str, "|HA", 1024);
 
134
   if (mod & GL_QUARTER_BIT_ATI)
 
135
      strncat(ret_str, "|QU", 1024);
 
136
   if (mod & GL_EIGHTH_BIT_ATI)
 
137
      strncat(ret_str, "|EI", 1024);
 
138
 
 
139
   if (mod & GL_SATURATE_BIT_ATI)
 
140
      strncat(ret_str, "|SAT", 1024);
 
141
 
 
142
   if (strlen(ret_str) == 0)
 
143
      strncat(ret_str, "NONE", 1024);
 
144
   return ret_str;
 
145
}
 
146
 
 
147
static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI", 
 
148
                            "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
 
149
 
 
150
static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
 
151
                     GLuint dstMask, GLuint dstMod, GLuint arg1,
 
152
                     GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
 
153
                     GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
 
154
                     GLuint arg3Rep, GLuint arg3Mod)
 
155
{
 
156
  char *op_name;
 
157
 
 
158
  op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
 
159
  
 
160
  fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op),
 
161
              _mesa_lookup_enum_by_nr(dst));
 
162
  if (!optype)
 
163
    fprintf(stderr, ", %d", dstMask);
 
164
  
 
165
  fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
 
166
  
 
167
  fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1),
 
168
              _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod);
 
169
  if (arg_count>1)
 
170
    fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2),
 
171
              _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod);
 
172
  if (arg_count>2)
 
173
    fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3),
 
174
              _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod);
 
175
 
 
176
  fprintf(stderr,")\n");
 
177
 
 
178
}
 
179
#endif
 
180
 
 
181
static int check_arith_arg(struct ati_fragment_shader *curProg,
 
182
                        GLuint optype, GLuint arg, GLuint argRep)
 
183
{
 
184
   GET_CURRENT_CONTEXT(ctx);
 
185
 
 
186
   if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) &&
 
187
      ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) &&
 
188
      (arg != GL_ZERO) && (arg != GL_ONE) &&
 
189
      (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) {
 
190
      _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)");
 
191
      return 0;
 
192
   }
 
193
   if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
 
194
      ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
 
195
      _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
 
196
      return 0;
 
197
   }
 
198
   if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
 
199
      ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
 
200
      _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
 
201
      return 0;
 
202
   }
 
203
   if ((curProg->cur_pass == 1) &&
 
204
      ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
 
205
      curProg->interpinp1 = GL_TRUE;
 
206
   }
 
207
   return 1;
 
208
}
 
209
 
 
210
GLuint GLAPIENTRY
 
211
_mesa_GenFragmentShadersATI(GLuint range)
 
212
{
 
213
   GLuint first;
 
214
   GLuint i;
 
215
   GET_CURRENT_CONTEXT(ctx);
 
216
 
 
217
   if (range == 0) {
 
218
      _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)");
 
219
      return 0;
 
220
   }
 
221
 
 
222
   if (ctx->ATIFragmentShader.Compiling) {
 
223
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)");
 
224
      return 0;
 
225
   }
 
226
 
 
227
   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
 
228
   for (i = 0; i < range; i++) {
 
229
      _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
 
230
   }
 
231
 
 
232
   return first;
 
233
}
 
234
 
 
235
void GLAPIENTRY
 
236
_mesa_BindFragmentShaderATI(GLuint id)
 
237
{
 
238
   GET_CURRENT_CONTEXT(ctx);
 
239
   struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
 
240
   struct ati_fragment_shader *newProg;
 
241
 
 
242
   if (ctx->ATIFragmentShader.Compiling) {
 
243
      _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
 
244
      return;
 
245
   }
 
246
 
 
247
   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
248
 
 
249
   if (curProg->Id == id) {
 
250
      return;
 
251
   }
 
252
 
 
253
   /* unbind current */
 
254
   if (curProg->Id != 0) {
 
255
      curProg->RefCount--;
 
256
      if (curProg->RefCount <= 0) {
 
257
         _mesa_HashRemove(ctx->Shared->ATIShaders, id);
 
258
      }
 
259
   }
 
260
 
 
261
   /* find new shader */
 
262
   if (id == 0) {
 
263
      newProg = ctx->Shared->DefaultFragmentShader;
 
264
   }
 
265
   else {
 
266
      newProg = (struct ati_fragment_shader *)
 
267
         _mesa_HashLookup(ctx->Shared->ATIShaders, id);
 
268
      if (!newProg || newProg == &DummyShader) {
 
269
         /* allocate a new program now */
 
270
         newProg = _mesa_new_ati_fragment_shader(ctx, id);
 
271
         if (!newProg) {
 
272
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
 
273
            return;
 
274
         }
 
275
         _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
 
276
      }
 
277
 
 
278
   }
 
279
 
 
280
   /* do actual bind */
 
281
   ctx->ATIFragmentShader.Current = newProg;
 
282
 
 
283
   ASSERT(ctx->ATIFragmentShader.Current);
 
284
   if (newProg)
 
285
      newProg->RefCount++;
 
286
 
 
287
   /*if (ctx->Driver.BindProgram)
 
288
      ctx->Driver.BindProgram(ctx, target, prog); */
 
289
}
 
290
 
 
291
void GLAPIENTRY
 
292
_mesa_DeleteFragmentShaderATI(GLuint id)
 
293
{
 
294
   GET_CURRENT_CONTEXT(ctx);
 
295
 
 
296
   if (ctx->ATIFragmentShader.Compiling) {
 
297
      _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
 
298
      return;
 
299
   }
 
300
 
 
301
   if (id != 0) {
 
302
      struct ati_fragment_shader *prog = (struct ati_fragment_shader *)
 
303
         _mesa_HashLookup(ctx->Shared->ATIShaders, id);
 
304
      if (prog == &DummyShader) {
 
305
         _mesa_HashRemove(ctx->Shared->ATIShaders, id);
 
306
      }
 
307
      else if (prog) {
 
308
         if (ctx->ATIFragmentShader.Current &&
 
309
             ctx->ATIFragmentShader.Current->Id == id) {
 
310
             FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
311
            _mesa_BindFragmentShaderATI(0);
 
312
         }
 
313
      }
 
314
 
 
315
      /* The ID is immediately available for re-use now */
 
316
      _mesa_HashRemove(ctx->Shared->ATIShaders, id);
 
317
      if (prog) {
 
318
         prog->RefCount--;
 
319
         if (prog->RefCount <= 0) {
 
320
            assert(prog != &DummyShader);
 
321
            free(prog);
 
322
         }
 
323
      }
 
324
   }
 
325
}
 
326
 
 
327
 
 
328
void GLAPIENTRY
 
329
_mesa_BeginFragmentShaderATI(void)
 
330
{
 
331
   GLint i;
 
332
   GET_CURRENT_CONTEXT(ctx);
 
333
 
 
334
   if (ctx->ATIFragmentShader.Compiling) {
 
335
      _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
 
336
      return;
 
337
   }
 
338
 
 
339
   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
340
 
 
341
   /* if the shader was already defined free instructions and get new ones
 
342
      (or, could use the same mem but would need to reinitialize) */
 
343
   /* no idea if it's allowed to redefine a shader */
 
344
   for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
 
345
         if (ctx->ATIFragmentShader.Current->Instructions[i])
 
346
            free(ctx->ATIFragmentShader.Current->Instructions[i]);
 
347
         if (ctx->ATIFragmentShader.Current->SetupInst[i])
 
348
            free(ctx->ATIFragmentShader.Current->SetupInst[i]);
 
349
   }
 
350
 
 
351
   /* malloc the instructions here - not sure if the best place but its
 
352
      a start */
 
353
   for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
 
354
      ctx->ATIFragmentShader.Current->Instructions[i] =
 
355
         (struct atifs_instruction *)
 
356
         calloc(1, sizeof(struct atifs_instruction) *
 
357
                   (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
 
358
      ctx->ATIFragmentShader.Current->SetupInst[i] =
 
359
         (struct atifs_setupinst *)
 
360
         calloc(1, sizeof(struct atifs_setupinst) *
 
361
                   (MAX_NUM_FRAGMENT_REGISTERS_ATI));
 
362
   }
 
363
 
 
364
/* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
 
365
   ctx->ATIFragmentShader.Current->LocalConstDef = 0;
 
366
   ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
 
367
   ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
 
368
   ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
 
369
   ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
 
370
   ctx->ATIFragmentShader.Current->NumPasses = 0;
 
371
   ctx->ATIFragmentShader.Current->cur_pass = 0;
 
372
   ctx->ATIFragmentShader.Current->last_optype = 0;
 
373
   ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
 
374
   ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
 
375
   ctx->ATIFragmentShader.Current->swizzlerq = 0;
 
376
   ctx->ATIFragmentShader.Compiling = 1;
 
377
}
 
378
 
 
379
void GLAPIENTRY
 
380
_mesa_EndFragmentShaderATI(void)
 
381
{
 
382
   GET_CURRENT_CONTEXT(ctx);
 
383
   struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
 
384
#if MESA_DEBUG_ATI_FS
 
385
   GLint i, j;
 
386
#endif
 
387
 
 
388
   if (!ctx->ATIFragmentShader.Compiling) {
 
389
      _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
 
390
      return;
 
391
   }
 
392
   if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
 
393
      _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
 
394
   /* according to spec, DON'T return here */
 
395
   }
 
396
 
 
397
   match_pair_inst(curProg, 0);
 
398
   ctx->ATIFragmentShader.Compiling = 0;
 
399
   ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
 
400
   if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
 
401
      (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
 
402
      _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
 
403
   }
 
404
   if (ctx->ATIFragmentShader.Current->cur_pass > 1)
 
405
      ctx->ATIFragmentShader.Current->NumPasses = 2;
 
406
   else
 
407
      ctx->ATIFragmentShader.Current->NumPasses = 1;
 
408
 
 
409
   ctx->ATIFragmentShader.Current->cur_pass = 0;
 
410
 
 
411
#if MESA_DEBUG_ATI_FS
 
412
   for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
 
413
      for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
 
414
         GLuint op = curProg->SetupInst[j][i].Opcode;
 
415
         const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0";
 
416
         GLuint src = curProg->SetupInst[j][i].src;
 
417
         GLuint swizzle = curProg->SetupInst[j][i].swizzle;
 
418
         fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
 
419
              swizzle);
 
420
      }
 
421
      for (i = 0; i < curProg->numArithInstr[j]; i++) {
 
422
         GLuint op0 = curProg->Instructions[j][i].Opcode[0];
 
423
         GLuint op1 = curProg->Instructions[j][i].Opcode[1];
 
424
         const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0";
 
425
         const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0";
 
426
         GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
 
427
         GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
 
428
         fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
 
429
              op1, op1_enum, count1);
 
430
      }
 
431
   }
 
432
#endif
 
433
 
 
434
   if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, NULL)) {
 
435
      ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
 
436
      /* XXX is this the right error? */
 
437
      _mesa_error(ctx, GL_INVALID_OPERATION,
 
438
                  "glEndFragmentShaderATI(driver rejected shader)");
 
439
   }
 
440
}
 
441
 
 
442
void GLAPIENTRY
 
443
_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
 
444
{
 
445
   GET_CURRENT_CONTEXT(ctx);
 
446
   struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
 
447
   struct atifs_setupinst *curI;
 
448
 
 
449
   if (!ctx->ATIFragmentShader.Compiling) {
 
450
      _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
 
451
      return;
 
452
   }
 
453
 
 
454
   if (curProg->cur_pass == 1) {
 
455
      match_pair_inst(curProg, 0);
 
456
      curProg->cur_pass = 2;
 
457
   }
 
458
   if ((curProg->cur_pass > 2) ||
 
459
      ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
 
460
      _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
 
461
      return;
 
462
   }
 
463
   if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
 
464
      ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
 
465
      _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
 
466
      return;
 
467
   }
 
468
   if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
 
469
       ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
 
470
       ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
 
471
      _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
 
472
      return;
 
473
   }
 
474
   if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
 
475
      _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
 
476
      return;
 
477
   }
 
478
   if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
 
479
      _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
 
480
      return;
 
481
   }
 
482
   if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
 
483
      _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
 
484
      return;
 
485
   }
 
486
   if (coord <= GL_TEXTURE7_ARB) {
 
487
      GLuint tmp = coord - GL_TEXTURE0_ARB;
 
488
      if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
 
489
           (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
 
490
         _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
 
491
         return;
 
492
      } else {
 
493
         curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
 
494
      }
 
495
   }
 
496
 
 
497
   curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
 
498
   new_tex_inst(curProg);
 
499
 
 
500
   /* add the instructions */
 
501
   curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
 
502
 
 
503
   curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
 
504
   curI->src = coord;
 
505
   curI->swizzle = swizzle;
 
506
 
 
507
#if MESA_DEBUG_ATI_FS
 
508
   _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
 
509
               _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
 
510
               _mesa_lookup_enum_by_nr(swizzle));
 
511
#endif
 
512
}
 
513
 
 
514
void GLAPIENTRY
 
515
_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
 
516
{
 
517
   GET_CURRENT_CONTEXT(ctx);
 
518
   struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
 
519
   struct atifs_setupinst *curI;
 
520
 
 
521
   if (!ctx->ATIFragmentShader.Compiling) {
 
522
      _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
 
523
      return;
 
524
   }
 
525
 
 
526
   if (curProg->cur_pass == 1) {
 
527
      match_pair_inst(curProg, 0);
 
528
      curProg->cur_pass = 2;
 
529
   }
 
530
   if ((curProg->cur_pass > 2) ||
 
531
      ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
 
532
      _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
 
533
      return;
 
534
   }
 
535
   if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
 
536
      ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
 
537
      _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
 
538
      return;
 
539
   }
 
540
   if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
 
541
       ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
 
542
       ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
 
543
   /* is this texture5 or texture7? spec is a bit unclear there */
 
544
      _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
 
545
      return;
 
546
   }
 
547
   if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
 
548
      _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
 
549
      return;
 
550
   }
 
551
   if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
 
552
      _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
 
553
      return;
 
554
   }
 
555
   if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
 
556
      _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
 
557
      return;
 
558
   }
 
559
   if (interp <= GL_TEXTURE7_ARB) {
 
560
      GLuint tmp = interp - GL_TEXTURE0_ARB;
 
561
      if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
 
562
           (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
 
563
         _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
 
564
         return;
 
565
      } else {
 
566
         curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
 
567
      }
 
568
   }
 
569
 
 
570
   curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
 
571
   new_tex_inst(curProg);
 
572
 
 
573
   /* add the instructions */
 
574
   curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
 
575
 
 
576
   curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
 
577
   curI->src = interp;
 
578
   curI->swizzle = swizzle;
 
579
 
 
580
#if MESA_DEBUG_ATI_FS
 
581
   _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
 
582
               _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
 
583
               _mesa_lookup_enum_by_nr(swizzle));
 
584
#endif
 
585
}
 
586
 
 
587
static void
 
588
_mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
 
589
                     GLuint dstMask, GLuint dstMod, GLuint arg1,
 
590
                     GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
 
591
                     GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
 
592
                     GLuint arg3Rep, GLuint arg3Mod)
 
593
{
 
594
   GET_CURRENT_CONTEXT(ctx);
 
595
   struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
 
596
   GLint ci;
 
597
   struct atifs_instruction *curI;
 
598
   GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
 
599
 
 
600
   if (!ctx->ATIFragmentShader.Compiling) {
 
601
      _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
 
602
      return;
 
603
   }
 
604
 
 
605
   if (curProg->cur_pass==0)
 
606
      curProg->cur_pass=1;
 
607
 
 
608
   else if (curProg->cur_pass==2)
 
609
      curProg->cur_pass=3;
 
610
 
 
611
   /* decide whether this is a new instruction or not ... all color instructions are new,
 
612
      and alpha instructions might also be new if there was no preceding color inst */
 
613
   if ((optype == 0) || (curProg->last_optype == optype)) {
 
614
      if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
 
615
         _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
 
616
         return;
 
617
      }
 
618
      /* easier to do that here slight side effect invalid instr will still be inserted as nops */
 
619
      match_pair_inst(curProg, optype);
 
620
      new_arith_inst(curProg);
 
621
   }
 
622
   curProg->last_optype = optype;
 
623
   ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
 
624
 
 
625
   /* add the instructions */
 
626
   curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
 
627
 
 
628
   /* error checking */
 
629
   if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
 
630
      _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
 
631
      return;
 
632
   }
 
633
   if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
 
634
      (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
 
635
      (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
 
636
      (modtemp != GL_EIGHTH_BIT_ATI)) {
 
637
      _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
 
638
      return;
 
639
   }
 
640
   /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
 
641
   if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
 
642
      _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
 
643
      return;
 
644
   }
 
645
   if (optype == 1) {
 
646
      if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
 
647
         ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
 
648
         ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
 
649
         ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
 
650
         _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
 
651
         return;
 
652
      }
 
653
   }
 
654
   if ((op == GL_DOT4_ATI) &&
 
655
      (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
 
656
      (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
 
657
      _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
 
658
   }
 
659
 
 
660
   if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
 
661
      return;
 
662
   }
 
663
   if (arg2) {
 
664
      if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
 
665
         return;
 
666
      }
 
667
   }
 
668
   if (arg3) {
 
669
      if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
 
670
         return;
 
671
      }
 
672
      if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
 
673
          (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
 
674
          (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
 
675
          (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
 
676
         _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
 
677
         return;
 
678
      }
 
679
   }
 
680
 
 
681
   /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
 
682
 
 
683
   curI->Opcode[optype] = op;
 
684
   curI->SrcReg[optype][0].Index = arg1;
 
685
   curI->SrcReg[optype][0].argRep = arg1Rep;
 
686
   curI->SrcReg[optype][0].argMod = arg1Mod;
 
687
   curI->ArgCount[optype] = arg_count;
 
688
 
 
689
   if (arg2) {
 
690
      curI->SrcReg[optype][1].Index = arg2;
 
691
      curI->SrcReg[optype][1].argRep = arg2Rep;
 
692
      curI->SrcReg[optype][1].argMod = arg2Mod;
 
693
   }
 
694
 
 
695
   if (arg3) {
 
696
      curI->SrcReg[optype][2].Index = arg3;
 
697
      curI->SrcReg[optype][2].argRep = arg3Rep;
 
698
      curI->SrcReg[optype][2].argMod = arg3Mod;
 
699
   }
 
700
 
 
701
   curI->DstReg[optype].Index = dst;
 
702
   curI->DstReg[optype].dstMod = dstMod;
 
703
   curI->DstReg[optype].dstMask = dstMask;
 
704
 
 
705
#if MESA_DEBUG_ATI_FS
 
706
   debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
 
707
#endif
 
708
 
 
709
}
 
710
 
 
711
void GLAPIENTRY
 
712
_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
 
713
                          GLuint dstMod, GLuint arg1, GLuint arg1Rep,
 
714
                          GLuint arg1Mod)
 
715
{
 
716
   _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
 
717
                        dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
 
718
}
 
719
 
 
720
void GLAPIENTRY
 
721
_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
 
722
                          GLuint dstMod, GLuint arg1, GLuint arg1Rep,
 
723
                          GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
 
724
                          GLuint arg2Mod)
 
725
{
 
726
   _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
 
727
                        dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
 
728
                        arg2Mod, 0, 0, 0);
 
729
}
 
730
 
 
731
void GLAPIENTRY
 
732
_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
 
733
                          GLuint dstMod, GLuint arg1, GLuint arg1Rep,
 
734
                          GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
 
735
                          GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
 
736
                          GLuint arg3Mod)
 
737
{
 
738
   _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
 
739
                        dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
 
740
                        arg2Mod, arg3, arg3Rep, arg3Mod);
 
741
}
 
742
 
 
743
void GLAPIENTRY
 
744
_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
 
745
                          GLuint arg1Rep, GLuint arg1Mod)
 
746
{
 
747
   _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
 
748
                        arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
 
749
}
 
750
 
 
751
void GLAPIENTRY
 
752
_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
 
753
                          GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
 
754
                          GLuint arg2Rep, GLuint arg2Mod)
 
755
{
 
756
   _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
 
757
                        arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
 
758
                        0);
 
759
}
 
760
 
 
761
void GLAPIENTRY
 
762
_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
 
763
                          GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
 
764
                          GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
 
765
                          GLuint arg3Rep, GLuint arg3Mod)
 
766
{
 
767
   _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
 
768
                        arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
 
769
                        arg3Rep, arg3Mod);
 
770
}
 
771
 
 
772
void GLAPIENTRY
 
773
_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
 
774
{
 
775
   GLuint dstindex;
 
776
   GET_CURRENT_CONTEXT(ctx);
 
777
 
 
778
   if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
 
779
      /* spec says nothing about what should happen here but we can't just segfault...*/
 
780
      _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
 
781
      return;
 
782
   }
 
783
 
 
784
   dstindex = dst - GL_CON_0_ATI;
 
785
   if (ctx->ATIFragmentShader.Compiling) {
 
786
      struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
 
787
      COPY_4V(curProg->Constants[dstindex], value);
 
788
      curProg->LocalConstDef |= 1 << dstindex;
 
789
   }
 
790
   else {
 
791
      FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
792
      COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
 
793
   }
 
794
}
 
795
 
 
796
#endif /* FEATURE_ATI_fragment_shader */