2
* \file atifragshader.c
4
* Copyright (C) 2004 David Airlie All Rights Reserved.
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:
13
* The above copyright notice and this permission notice shall be included
14
* in all copies or substantial portions of the Software.
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.
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 "atifragshader.h"
33
#define MESA_DEBUG_ATI_FS 0
35
static struct ati_fragment_shader DummyShader;
39
* Allocate and initialize a new ATI fragment shader object.
41
struct ati_fragment_shader *
42
_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id)
44
struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
55
* Delete the given ati fragment shader
58
_mesa_delete_ati_fragment_shader(GLcontext *ctx, struct ati_fragment_shader *s)
61
for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
62
if (s->Instructions[i])
63
free(s->Instructions[i]);
65
free(s->SetupInst[i]);
73
new_arith_inst(struct ati_fragment_shader *prog)
75
/* 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]++;
82
new_tex_inst(struct ati_fragment_shader *prog)
86
static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
88
if (optype == curProg->last_optype) {
89
curProg->last_optype = 1;
95
create_dst_mod_str(GLuint mod)
97
static char ret_str[1024];
99
memset(ret_str, 0, 1024);
100
if (mod & GL_2X_BIT_ATI)
101
strncat(ret_str, "|2X", 1024);
103
if (mod & GL_4X_BIT_ATI)
104
strncat(ret_str, "|4X", 1024);
106
if (mod & GL_8X_BIT_ATI)
107
strncat(ret_str, "|8X", 1024);
108
if (mod & GL_HALF_BIT_ATI)
109
strncat(ret_str, "|HA", 1024);
110
if (mod & GL_QUARTER_BIT_ATI)
111
strncat(ret_str, "|QU", 1024);
112
if (mod & GL_EIGHTH_BIT_ATI)
113
strncat(ret_str, "|EI", 1024);
115
if (mod & GL_SATURATE_BIT_ATI)
116
strncat(ret_str, "|SAT", 1024);
118
if (strlen(ret_str) == 0)
119
strncat(ret_str, "NONE", 1024);
123
static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
124
"AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
126
static 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)
134
op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
136
fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op),
137
_mesa_lookup_enum_by_nr(dst));
139
fprintf(stderr, ", %d", dstMask);
141
fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
143
fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1),
144
_mesa_lookup_enum_by_nr(arg1Rep), arg1Mod);
146
fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2),
147
_mesa_lookup_enum_by_nr(arg2Rep), arg2Mod);
149
fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3),
150
_mesa_lookup_enum_by_nr(arg3Rep), arg3Mod);
152
fprintf(stderr,")\n");
157
static int check_arith_arg(struct ati_fragment_shader *curProg,
158
GLuint optype, GLuint arg, GLuint argRep)
160
GET_CURRENT_CONTEXT(ctx);
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)");
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)");
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)");
179
if ((curProg->cur_pass == 1) &&
180
((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
181
curProg->interpinp1 = GL_TRUE;
187
_mesa_GenFragmentShadersATI(GLuint range)
191
GET_CURRENT_CONTEXT(ctx);
194
_mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)");
198
if (ctx->ATIFragmentShader.Compiling) {
199
_mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)");
203
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
204
for (i = 0; i < range; i++) {
205
_mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
212
_mesa_BindFragmentShaderATI(GLuint id)
214
GET_CURRENT_CONTEXT(ctx);
215
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
216
struct ati_fragment_shader *newProg;
218
if (ctx->ATIFragmentShader.Compiling) {
219
_mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
223
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
225
if (curProg->Id == id) {
230
if (curProg->Id != 0) {
232
if (curProg->RefCount <= 0) {
233
_mesa_HashRemove(ctx->Shared->ATIShaders, id);
237
/* find new shader */
239
newProg = ctx->Shared->DefaultFragmentShader;
242
newProg = (struct ati_fragment_shader *)
243
_mesa_HashLookup(ctx->Shared->ATIShaders, id);
244
if (!newProg || newProg == &DummyShader) {
245
/* allocate a new program now */
246
newProg = _mesa_new_ati_fragment_shader(ctx, id);
248
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
251
_mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
257
ctx->ATIFragmentShader.Current = newProg;
259
ASSERT(ctx->ATIFragmentShader.Current);
263
/*if (ctx->Driver.BindProgram)
264
ctx->Driver.BindProgram(ctx, target, prog); */
268
_mesa_DeleteFragmentShaderATI(GLuint id)
270
GET_CURRENT_CONTEXT(ctx);
272
if (ctx->ATIFragmentShader.Compiling) {
273
_mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
278
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);
284
if (ctx->ATIFragmentShader.Current &&
285
ctx->ATIFragmentShader.Current->Id == id) {
286
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
287
_mesa_BindFragmentShaderATI(0);
291
/* The ID is immediately available for re-use now */
292
_mesa_HashRemove(ctx->Shared->ATIShaders, id);
295
if (prog->RefCount <= 0) {
304
_mesa_BeginFragmentShaderATI(void)
307
GET_CURRENT_CONTEXT(ctx);
309
if (ctx->ATIFragmentShader.Compiling) {
310
_mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
314
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
316
/* 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
free(ctx->ATIFragmentShader.Current->Instructions[i]);
322
if (ctx->ATIFragmentShader.Current->SetupInst[i])
323
free(ctx->ATIFragmentShader.Current->SetupInst[i]);
326
/* malloc the instructions here - not sure if the best place but its
328
for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
329
ctx->ATIFragmentShader.Current->Instructions[i] =
330
(struct atifs_instruction *)
331
calloc(1, sizeof(struct atifs_instruction) *
332
(MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
333
ctx->ATIFragmentShader.Current->SetupInst[i] =
334
(struct atifs_setupinst *)
335
calloc(1, sizeof(struct atifs_setupinst) *
336
(MAX_NUM_FRAGMENT_REGISTERS_ATI));
339
/* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
340
ctx->ATIFragmentShader.Current->LocalConstDef = 0;
341
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;
346
ctx->ATIFragmentShader.Current->cur_pass = 0;
347
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;
351
ctx->ATIFragmentShader.Compiling = 1;
355
_mesa_EndFragmentShaderATI(void)
357
GET_CURRENT_CONTEXT(ctx);
358
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
359
#if MESA_DEBUG_ATI_FS
363
if (!ctx->ATIFragmentShader.Compiling) {
364
_mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
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 */
372
match_pair_inst(curProg, 0);
373
ctx->ATIFragmentShader.Compiling = 0;
374
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)");
379
if (ctx->ATIFragmentShader.Current->cur_pass > 1)
380
ctx->ATIFragmentShader.Current->NumPasses = 2;
382
ctx->ATIFragmentShader.Current->NumPasses = 1;
384
ctx->ATIFragmentShader.Current->cur_pass = 0;
386
#if MESA_DEBUG_ATI_FS
387
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,
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,
404
op1, op1_enum, count1);
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)");
418
_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
420
GET_CURRENT_CONTEXT(ctx);
421
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
422
struct atifs_setupinst *curI;
424
if (!ctx->ATIFragmentShader.Compiling) {
425
_mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
429
if (curProg->cur_pass == 1) {
430
match_pair_inst(curProg, 0);
431
curProg->cur_pass = 2;
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)");
438
if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
439
((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
440
_mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
443
if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
444
((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
445
((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
446
_mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
449
if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
450
_mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
453
if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
454
_mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
457
if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
458
_mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
461
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))) {
465
_mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
468
curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
472
curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
473
new_tex_inst(curProg);
475
/* add the instructions */
476
curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
478
curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
480
curI->swizzle = swizzle;
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));
490
_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
492
GET_CURRENT_CONTEXT(ctx);
493
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
494
struct atifs_setupinst *curI;
496
if (!ctx->ATIFragmentShader.Compiling) {
497
_mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
501
if (curProg->cur_pass == 1) {
502
match_pair_inst(curProg, 0);
503
curProg->cur_pass = 2;
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)");
510
if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
511
((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
512
_mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
515
if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
516
((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
517
((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
518
/* is this texture5 or texture7? spec is a bit unclear there */
519
_mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
522
if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
523
_mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
526
if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
527
_mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
530
if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
531
_mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
534
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))) {
538
_mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
541
curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
545
curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
546
new_tex_inst(curProg);
548
/* add the instructions */
549
curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
551
curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
553
curI->swizzle = swizzle;
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));
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)
569
GET_CURRENT_CONTEXT(ctx);
570
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
572
struct atifs_instruction *curI;
573
GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
575
if (!ctx->ATIFragmentShader.Compiling) {
576
_mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
580
if (curProg->cur_pass==0)
583
else if (curProg->cur_pass==2)
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)");
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);
597
curProg->last_optype = optype;
598
ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
600
/* add the instructions */
601
curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
604
if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
605
_mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
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);
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)");
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)");
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)");
635
if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
639
if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
644
if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
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)");
656
/* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
658
curI->Opcode[optype] = op;
659
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;
665
curI->SrcReg[optype][1].Index = arg2;
666
curI->SrcReg[optype][1].argRep = arg2Rep;
667
curI->SrcReg[optype][1].argMod = arg2Mod;
671
curI->SrcReg[optype][2].Index = arg3;
672
curI->SrcReg[optype][2].argRep = arg3Rep;
673
curI->SrcReg[optype][2].argMod = arg3Mod;
676
curI->DstReg[optype].Index = dst;
677
curI->DstReg[optype].dstMod = dstMod;
678
curI->DstReg[optype].dstMask = dstMask;
680
#if MESA_DEBUG_ATI_FS
681
debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
687
_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
688
GLuint dstMod, GLuint arg1, GLuint arg1Rep,
691
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
692
dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
696
_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
697
GLuint dstMod, GLuint arg1, GLuint arg1Rep,
698
GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
701
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
702
dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
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,
713
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
714
dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
715
arg2Mod, arg3, arg3Rep, arg3Mod);
719
_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
720
GLuint arg1Rep, GLuint arg1Mod)
722
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
723
arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
727
_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
728
GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
729
GLuint arg2Rep, GLuint arg2Mod)
731
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
732
arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
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)
742
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
743
arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
748
_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
751
GET_CURRENT_CONTEXT(ctx);
753
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)");
759
dstindex = dst - GL_CON_0_ATI;
760
if (ctx->ATIFragmentShader.Compiling) {
761
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
762
COPY_4V(curProg->Constants[dstindex], value);
763
curProg->LocalConstDef |= 1 << dstindex;
766
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
767
COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);