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/mfeatures.h"
30
#include "main/enums.h"
31
#include "main/mtypes.h"
32
#include "main/dispatch.h"
33
#include "main/atifragshader.h"
35
#if FEATURE_ATI_fragment_shader
37
#define MESA_DEBUG_ATI_FS 0
39
static struct ati_fragment_shader DummyShader;
43
_mesa_init_ati_fragment_shader_dispatch(struct _glapi_table *disp)
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);
63
* Allocate and initialize a new ATI fragment shader object.
65
struct ati_fragment_shader *
66
_mesa_new_ati_fragment_shader(struct gl_context *ctx, GLuint id)
68
struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
79
* Delete the given ati fragment shader
82
_mesa_delete_ati_fragment_shader(struct gl_context *ctx, struct ati_fragment_shader *s)
85
for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
86
if (s->Instructions[i])
87
free(s->Instructions[i]);
89
free(s->SetupInst[i]);
97
new_arith_inst(struct ati_fragment_shader *prog)
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]++;
106
new_tex_inst(struct ati_fragment_shader *prog)
110
static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
112
if (optype == curProg->last_optype) {
113
curProg->last_optype = 1;
117
#if MESA_DEBUG_ATI_FS
119
create_dst_mod_str(GLuint mod)
121
static char ret_str[1024];
123
memset(ret_str, 0, 1024);
124
if (mod & GL_2X_BIT_ATI)
125
strncat(ret_str, "|2X", 1024);
127
if (mod & GL_4X_BIT_ATI)
128
strncat(ret_str, "|4X", 1024);
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);
139
if (mod & GL_SATURATE_BIT_ATI)
140
strncat(ret_str, "|SAT", 1024);
142
if (strlen(ret_str) == 0)
143
strncat(ret_str, "NONE", 1024);
147
static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
148
"AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
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)
158
op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
160
fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op),
161
_mesa_lookup_enum_by_nr(dst));
163
fprintf(stderr, ", %d", dstMask);
165
fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
167
fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1),
168
_mesa_lookup_enum_by_nr(arg1Rep), arg1Mod);
170
fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2),
171
_mesa_lookup_enum_by_nr(arg2Rep), arg2Mod);
173
fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3),
174
_mesa_lookup_enum_by_nr(arg3Rep), arg3Mod);
176
fprintf(stderr,")\n");
181
static int check_arith_arg(struct ati_fragment_shader *curProg,
182
GLuint optype, GLuint arg, GLuint argRep)
184
GET_CURRENT_CONTEXT(ctx);
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)");
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)");
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)");
203
if ((curProg->cur_pass == 1) &&
204
((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
205
curProg->interpinp1 = GL_TRUE;
211
_mesa_GenFragmentShadersATI(GLuint range)
215
GET_CURRENT_CONTEXT(ctx);
218
_mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)");
222
if (ctx->ATIFragmentShader.Compiling) {
223
_mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)");
227
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
228
for (i = 0; i < range; i++) {
229
_mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
236
_mesa_BindFragmentShaderATI(GLuint id)
238
GET_CURRENT_CONTEXT(ctx);
239
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
240
struct ati_fragment_shader *newProg;
242
if (ctx->ATIFragmentShader.Compiling) {
243
_mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
247
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
249
if (curProg->Id == id) {
254
if (curProg->Id != 0) {
256
if (curProg->RefCount <= 0) {
257
_mesa_HashRemove(ctx->Shared->ATIShaders, id);
261
/* find new shader */
263
newProg = ctx->Shared->DefaultFragmentShader;
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);
272
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
275
_mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
281
ctx->ATIFragmentShader.Current = newProg;
283
ASSERT(ctx->ATIFragmentShader.Current);
287
/*if (ctx->Driver.BindProgram)
288
ctx->Driver.BindProgram(ctx, target, prog); */
292
_mesa_DeleteFragmentShaderATI(GLuint id)
294
GET_CURRENT_CONTEXT(ctx);
296
if (ctx->ATIFragmentShader.Compiling) {
297
_mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
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);
308
if (ctx->ATIFragmentShader.Current &&
309
ctx->ATIFragmentShader.Current->Id == id) {
310
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
311
_mesa_BindFragmentShaderATI(0);
315
/* The ID is immediately available for re-use now */
316
_mesa_HashRemove(ctx->Shared->ATIShaders, id);
319
if (prog->RefCount <= 0) {
320
assert(prog != &DummyShader);
329
_mesa_BeginFragmentShaderATI(void)
332
GET_CURRENT_CONTEXT(ctx);
334
if (ctx->ATIFragmentShader.Compiling) {
335
_mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
339
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
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]);
351
/* malloc the instructions here - not sure if the best place but its
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));
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;
380
_mesa_EndFragmentShaderATI(void)
382
GET_CURRENT_CONTEXT(ctx);
383
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
384
#if MESA_DEBUG_ATI_FS
388
if (!ctx->ATIFragmentShader.Compiling) {
389
_mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
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 */
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)");
404
if (ctx->ATIFragmentShader.Current->cur_pass > 1)
405
ctx->ATIFragmentShader.Current->NumPasses = 2;
407
ctx->ATIFragmentShader.Current->NumPasses = 1;
409
ctx->ATIFragmentShader.Current->cur_pass = 0;
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,
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);
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)");
443
_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
445
GET_CURRENT_CONTEXT(ctx);
446
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
447
struct atifs_setupinst *curI;
449
if (!ctx->ATIFragmentShader.Compiling) {
450
_mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
454
if (curProg->cur_pass == 1) {
455
match_pair_inst(curProg, 0);
456
curProg->cur_pass = 2;
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)");
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)");
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)");
474
if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
475
_mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
478
if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
479
_mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
482
if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
483
_mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
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)");
493
curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
497
curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
498
new_tex_inst(curProg);
500
/* add the instructions */
501
curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
503
curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
505
curI->swizzle = swizzle;
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));
515
_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
517
GET_CURRENT_CONTEXT(ctx);
518
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
519
struct atifs_setupinst *curI;
521
if (!ctx->ATIFragmentShader.Compiling) {
522
_mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
526
if (curProg->cur_pass == 1) {
527
match_pair_inst(curProg, 0);
528
curProg->cur_pass = 2;
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)");
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)");
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)");
547
if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
548
_mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
551
if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
552
_mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
555
if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
556
_mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
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)");
566
curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
570
curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
571
new_tex_inst(curProg);
573
/* add the instructions */
574
curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
576
curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
578
curI->swizzle = swizzle;
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));
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)
594
GET_CURRENT_CONTEXT(ctx);
595
struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
597
struct atifs_instruction *curI;
598
GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
600
if (!ctx->ATIFragmentShader.Compiling) {
601
_mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
605
if (curProg->cur_pass==0)
608
else if (curProg->cur_pass==2)
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)");
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);
622
curProg->last_optype = optype;
623
ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
625
/* add the instructions */
626
curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
629
if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
630
_mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
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);
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)");
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)");
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)");
660
if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
664
if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
669
if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
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)");
681
/* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
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;
690
curI->SrcReg[optype][1].Index = arg2;
691
curI->SrcReg[optype][1].argRep = arg2Rep;
692
curI->SrcReg[optype][1].argMod = arg2Mod;
696
curI->SrcReg[optype][2].Index = arg3;
697
curI->SrcReg[optype][2].argRep = arg3Rep;
698
curI->SrcReg[optype][2].argMod = arg3Mod;
701
curI->DstReg[optype].Index = dst;
702
curI->DstReg[optype].dstMod = dstMod;
703
curI->DstReg[optype].dstMask = dstMask;
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);
712
_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
713
GLuint dstMod, GLuint arg1, GLuint arg1Rep,
716
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
717
dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
721
_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
722
GLuint dstMod, GLuint arg1, GLuint arg1Rep,
723
GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
726
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
727
dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
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,
738
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
739
dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
740
arg2Mod, arg3, arg3Rep, arg3Mod);
744
_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
745
GLuint arg1Rep, GLuint arg1Mod)
747
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
748
arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
752
_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
753
GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
754
GLuint arg2Rep, GLuint arg2Mod)
756
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
757
arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
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)
767
_mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
768
arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
773
_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
776
GET_CURRENT_CONTEXT(ctx);
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)");
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;
791
FLUSH_VERTICES(ctx, _NEW_PROGRAM);
792
COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
796
#endif /* FEATURE_ATI_fragment_shader */