Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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