Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4358 Serge 1
/**************************************************************************
2
 *
3
 * Copyright 2004 David Airlie
4
 * 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
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sub license, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
13
 *
14
 * The above copyright notice and this permission notice (including the
15
 * next paragraph) shall be included in all copies or substantial portions
16
 * of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
 * IN NO EVENT SHALL DAVID AIRLIE AND/OR ITS SUPPLIERS BE LIABLE FOR
22
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 **************************************************************************/
27
 
28
#include "main/glheader.h"
29
#include "main/atifragshader.h"
30
#include "main/macros.h"
31
#include "main/enums.h"
32
#include "tnl/t_context.h"
33
#include "program/program.h"
34
#include "r200_context.h"
35
#include "r200_ioctl.h"
36
#include "r200_tex.h"
37
 
38
#define SET_INST(inst, type) afs_cmd[((inst<<2) + (type<<1) + 1)]
39
#define SET_INST_2(inst, type) afs_cmd[((inst<<2) + (type<<1) + 2)]
40
 
41
static void r200SetFragShaderArg( GLuint *afs_cmd, GLuint opnum, GLuint optype,
42
				const struct atifragshader_src_register srcReg,
43
				GLuint argPos, GLuint *tfactor )
44
{
45
   const GLuint index = srcReg.Index;
46
   const GLuint srcmod = srcReg.argMod;
47
   const GLuint srcrep = srcReg.argRep;
48
   GLuint reg0 = 0;
49
   GLuint reg2 = 0;
50
   GLuint useOddSrc = 0;
51
 
52
   switch(srcrep) {
53
   case GL_RED:
54
      reg2 |= R200_TXC_REPL_RED << (R200_TXC_REPL_ARG_A_SHIFT + (2*argPos));
55
      if (optype)
56
	 useOddSrc = 1;
57
      break;
58
   case GL_GREEN:
59
      reg2 |= R200_TXC_REPL_GREEN << (R200_TXC_REPL_ARG_A_SHIFT + (2*argPos));
60
      if (optype)
61
	 useOddSrc = 1;
62
      break;
63
   case GL_BLUE:
64
      if (!optype)
65
	 reg2 |= R200_TXC_REPL_BLUE << (R200_TXC_REPL_ARG_A_SHIFT + (2*argPos));
66
      else
67
	 useOddSrc = 1;
68
      break;
69
   case GL_ALPHA:
70
      if (!optype)
71
	 useOddSrc = 1;
72
      break;
73
   }
74
 
75
   if (index >= GL_REG_0_ATI && index <= GL_REG_5_ATI)
76
      reg0 |= (((index - GL_REG_0_ATI)*2) + 10 + useOddSrc) << (5*argPos);
77
   else if (index >= GL_CON_0_ATI && index <= GL_CON_7_ATI) {
78
      if ((*tfactor == 0) || (index == *tfactor)) {
79
	 reg0 |= (R200_TXC_ARG_A_TFACTOR_COLOR + useOddSrc) << (5*argPos);
80
	 reg2 |= (index - GL_CON_0_ATI) << R200_TXC_TFACTOR_SEL_SHIFT;
81
	 *tfactor = index;
82
      }
83
      else {
84
	 reg0 |= (R200_TXC_ARG_A_TFACTOR1_COLOR + useOddSrc) << (5*argPos);
85
	 reg2 |= (index - GL_CON_0_ATI) << R200_TXC_TFACTOR1_SEL_SHIFT;
86
      }
87
   }
88
   else if (index == GL_PRIMARY_COLOR_EXT) {
89
      reg0 |= (R200_TXC_ARG_A_DIFFUSE_COLOR + useOddSrc) << (5*argPos);
90
   }
91
   else if (index == GL_SECONDARY_INTERPOLATOR_ATI) {
92
      reg0 |= (R200_TXC_ARG_A_SPECULAR_COLOR + useOddSrc) << (5*argPos);
93
   }
94
   /* GL_ZERO is a noop, for GL_ONE we set the complement */
95
   else if (index == GL_ONE) {
96
      reg0 |= R200_TXC_COMP_ARG_A << (4*argPos);
97
   }
98
 
99
   if (srcmod & GL_COMP_BIT_ATI)
100
      reg0 ^= R200_TXC_COMP_ARG_A << (4*argPos);
101
   if (srcmod & GL_BIAS_BIT_ATI)
102
      reg0 |= R200_TXC_BIAS_ARG_A << (4*argPos);
103
   if (srcmod & GL_2X_BIT_ATI)
104
      reg0 |= R200_TXC_SCALE_ARG_A << (4*argPos);
105
   if (srcmod & GL_NEGATE_BIT_ATI)
106
      reg0 ^= R200_TXC_NEG_ARG_A << (4*argPos);
107
 
108
   SET_INST(opnum, optype) |= reg0;
109
   SET_INST_2(opnum, optype) |= reg2;
110
}
111
 
112
static GLuint dstmask_table[8] =
113
{
114
   R200_TXC_OUTPUT_MASK_RGB,
115
   R200_TXC_OUTPUT_MASK_R,
116
   R200_TXC_OUTPUT_MASK_G,
117
   R200_TXC_OUTPUT_MASK_RG,
118
   R200_TXC_OUTPUT_MASK_B,
119
   R200_TXC_OUTPUT_MASK_RB,
120
   R200_TXC_OUTPUT_MASK_GB,
121
   R200_TXC_OUTPUT_MASK_RGB
122
};
123
 
124
static void r200UpdateFSArith( struct gl_context *ctx )
125
{
126
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
127
   GLuint *afs_cmd;
128
   const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
129
   GLuint pass;
130
 
131
   R200_STATECHANGE( rmesa, afs[0] );
132
   R200_STATECHANGE( rmesa, afs[1] );
133
 
134
   if (shader->NumPasses < 2) {
135
      afs_cmd = (GLuint *) rmesa->hw.afs[1].cmd;
136
   }
137
   else {
138
      afs_cmd = (GLuint *) rmesa->hw.afs[0].cmd;
139
   }
140
   for (pass = 0; pass < shader->NumPasses; pass++) {
141
      GLuint opnum = 0;
142
      GLuint pc;
143
      for (pc = 0; pc < shader->numArithInstr[pass]; pc++) {
144
         GLuint optype;
145
	 struct atifs_instruction *inst = &shader->Instructions[pass][pc];
146
 
147
	 SET_INST(opnum, 0) = 0;
148
	 SET_INST_2(opnum, 0) = 0;
149
	 SET_INST(opnum, 1) = 0;
150
	 SET_INST_2(opnum, 1) = 0;
151
 
152
	 for (optype = 0; optype < 2; optype++) {
153
	    GLuint tfactor = 0;
154
 
155
	    if (inst->Opcode[optype]) {
156
	       switch (inst->Opcode[optype]) {
157
	       /* these are all MADD in disguise
158
		  MADD is A * B + C
159
		  so for GL_ADD use arg B/C and make A complement 0
160
		  for GL_SUB use arg B/C, negate C and make A complement 0
161
		  for GL_MOV use arg C
162
		  for GL_MUL use arg A
163
		  for GL_MAD all good */
164
	       case GL_SUB_ATI:
165
		  /* negate C */
166
		  SET_INST(opnum, optype) |= R200_TXC_NEG_ARG_C;
167
		  /* fallthrough */
168
	       case GL_ADD_ATI:
169
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
170
					inst->SrcReg[optype][0], 1, &tfactor);
171
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
172
					inst->SrcReg[optype][1], 2, &tfactor);
173
		  /* A = complement 0 */
174
		  SET_INST(opnum, optype) |= R200_TXC_COMP_ARG_A;
175
		  SET_INST(opnum, optype) |= R200_TXC_OP_MADD;
176
		  break;
177
	       case GL_MOV_ATI:
178
		  /* put arg0 in C */
179
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
180
					inst->SrcReg[optype][0], 2, &tfactor);
181
		  SET_INST(opnum, optype) |= R200_TXC_OP_MADD;
182
		  break;
183
	       case GL_MAD_ATI:
184
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
185
					inst->SrcReg[optype][2], 2, &tfactor);
186
		  /* fallthrough */
187
	       case GL_MUL_ATI:
188
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
189
					inst->SrcReg[optype][0], 0, &tfactor);
190
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
191
					inst->SrcReg[optype][1], 1, &tfactor);
192
		  SET_INST(opnum, optype) |= R200_TXC_OP_MADD;
193
		  break;
194
	       case GL_LERP_ATI:
195
		  /* arg order is not native chip order, swap A and C */
196
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
197
					inst->SrcReg[optype][0], 2, &tfactor);
198
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
199
					inst->SrcReg[optype][1], 1, &tfactor);
200
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
201
					inst->SrcReg[optype][2], 0, &tfactor);
202
		  SET_INST(opnum, optype) |= R200_TXC_OP_LERP;
203
		  break;
204
	       case GL_CND_ATI:
205
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
206
					inst->SrcReg[optype][0], 0, &tfactor);
207
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
208
					inst->SrcReg[optype][1], 1, &tfactor);
209
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
210
					inst->SrcReg[optype][2], 2, &tfactor);
211
		  SET_INST(opnum, optype) |= R200_TXC_OP_CONDITIONAL;
212
		  break;
213
	       case GL_CND0_ATI:
214
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
215
					inst->SrcReg[optype][0], 0, &tfactor);
216
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
217
					inst->SrcReg[optype][1], 1, &tfactor);
218
		  r200SetFragShaderArg(afs_cmd, opnum, optype,
219
					inst->SrcReg[optype][2], 2, &tfactor);
220
		  SET_INST(opnum, optype) |= R200_TXC_OP_CND0;
221
		  break;
222
		  /* cannot specify dot ops as alpha ops directly */
223
	       case GL_DOT2_ADD_ATI:
224
		  if (optype)
225
		     SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA;
226
		  else {
227
		     r200SetFragShaderArg(afs_cmd, opnum, 0,
228
					inst->SrcReg[0][0], 0, &tfactor);
229
		     r200SetFragShaderArg(afs_cmd, opnum, 0,
230
					inst->SrcReg[0][1], 1, &tfactor);
231
		     r200SetFragShaderArg(afs_cmd, opnum, 0,
232
					inst->SrcReg[0][2], 2, &tfactor);
233
		     SET_INST(opnum, 0) |= R200_TXC_OP_DOT2_ADD;
234
		  }
235
		  break;
236
	       case GL_DOT3_ATI:
237
		  if (optype)
238
		     SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA;
239
		  else {
240
		     r200SetFragShaderArg(afs_cmd, opnum, 0,
241
					inst->SrcReg[0][0], 0, &tfactor);
242
		     r200SetFragShaderArg(afs_cmd, opnum, 0,
243
					inst->SrcReg[0][1], 1, &tfactor);
244
		     SET_INST(opnum, 0) |= R200_TXC_OP_DOT3;
245
		  }
246
		  break;
247
	       case GL_DOT4_ATI:
248
	       /* experimental verification: for dot4 setup of alpha args is needed
249
		  (dstmod is ignored, though, so dot2/dot3 should be safe)
250
		  the hardware apparently does R1*R2 + G1*G2 + B1*B2 + A3*A4
251
		  but the API doesn't allow it */
252
		  if (optype)
253
		     SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA;
254
		  else {
255
		     r200SetFragShaderArg(afs_cmd, opnum, 0,
256
					inst->SrcReg[0][0], 0, &tfactor);
257
		     r200SetFragShaderArg(afs_cmd, opnum, 0,
258
					inst->SrcReg[0][1], 1, &tfactor);
259
		     r200SetFragShaderArg(afs_cmd, opnum, 1,
260
					inst->SrcReg[0][0], 0, &tfactor);
261
		     r200SetFragShaderArg(afs_cmd, opnum, 1,
262
					inst->SrcReg[0][1], 1, &tfactor);
263
		     SET_INST(opnum, optype) |= R200_TXC_OP_DOT4;
264
		  }
265
		  break;
266
	       }
267
	    }
268
 
269
	    /* destination */
270
	    if (inst->DstReg[optype].Index) {
271
	       GLuint dstreg = inst->DstReg[optype].Index - GL_REG_0_ATI;
272
	       GLuint dstmask = inst->DstReg[optype].dstMask;
273
	       GLuint sat = inst->DstReg[optype].dstMod & GL_SATURATE_BIT_ATI;
274
	       GLuint dstmod = inst->DstReg[optype].dstMod;
275
 
276
	       dstmod &= ~GL_SATURATE_BIT_ATI;
277
 
278
	       SET_INST_2(opnum, optype) |= (dstreg + 1) << R200_TXC_OUTPUT_REG_SHIFT;
279
	       SET_INST_2(opnum, optype) |= dstmask_table[dstmask];
280
 
281
		/* fglrx does clamp the last instructions to 0_1 it seems */
282
		/* this won't necessarily catch the last instruction
283
		   which writes to reg0 */
284
	       if (sat || (pc == (shader->numArithInstr[pass] - 1) &&
285
			((pass == 1) || (shader->NumPasses == 1))))
286
		  SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_0_1;
287
	       else
288
		/*should we clamp or not? spec is vague, I would suppose yes but fglrx doesn't */
289
		  SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_8_8;
290
/*		  SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_WRAP;*/
291
	       switch(dstmod) {
292
	       case GL_2X_BIT_ATI:
293
		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_2X;
294
		  break;
295
	       case GL_4X_BIT_ATI:
296
		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_4X;
297
		  break;
298
	       case GL_8X_BIT_ATI:
299
		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_8X;
300
		  break;
301
	       case GL_HALF_BIT_ATI:
302
		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV2;
303
		  break;
304
	       case GL_QUARTER_BIT_ATI:
305
		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV4;
306
		  break;
307
	       case GL_EIGHTH_BIT_ATI:
308
		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV8;
309
		  break;
310
	       default:
311
		  break;
312
	       }
313
	    }
314
	 }
315
/*	 fprintf(stderr, "pass %d nr %d inst 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
316
		pass, opnum, SET_INST(opnum, 0), SET_INST_2(opnum, 0),
317
		SET_INST(opnum, 1), SET_INST_2(opnum, 1));*/
318
         opnum++;
319
      }
320
      afs_cmd = (GLuint *) rmesa->hw.afs[1].cmd;
321
   }
322
   rmesa->afs_loaded = ctx->ATIFragmentShader.Current;
323
}
324
 
325
static void r200UpdateFSRouting( struct gl_context *ctx ) {
326
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
327
   const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
328
   GLuint reg;
329
 
330
   R200_STATECHANGE( rmesa, ctx );
331
   R200_STATECHANGE( rmesa, cst );
332
 
333
   for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
334
      if (shader->swizzlerq & (1 << (2 * reg)))
335
	 /* r coord */
336
	 set_re_cntl_d3d( ctx, reg, 1);
337
	 /* q coord */
338
      else set_re_cntl_d3d( ctx, reg, 0);
339
   }
340
 
341
   rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_MULTI_PASS_ENABLE |
342
				       R200_TEX_BLEND_ENABLE_MASK |
343
				       R200_TEX_ENABLE_MASK);
344
   rmesa->hw.cst.cmd[CST_PP_CNTL_X] &= ~(R200_PPX_PFS_INST_ENABLE_MASK |
345
					 R200_PPX_TEX_ENABLE_MASK |
346
					 R200_PPX_OUTPUT_REG_MASK);
347
 
348
   /* first pass registers use slots 8 - 15
349
      but single pass shaders use slots 0 - 7 */
350
   if (shader->NumPasses < 2) {
351
      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->numArithInstr[0] == 8 ?
352
	 0xff << (R200_TEX_BLEND_0_ENABLE_SHIFT - 1) :
353
	 (0xff >> (8 - shader->numArithInstr[0])) << R200_TEX_BLEND_0_ENABLE_SHIFT;
354
   } else {
355
      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_MULTI_PASS_ENABLE;
356
      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->numArithInstr[1] == 8 ?
357
	 0xff << (R200_TEX_BLEND_0_ENABLE_SHIFT - 1) :
358
	 (0xff >> (8 - shader->numArithInstr[1])) << R200_TEX_BLEND_0_ENABLE_SHIFT;
359
      rmesa->hw.cst.cmd[CST_PP_CNTL_X] |=
360
	 (0xff >> (8 - shader->numArithInstr[0])) << R200_PPX_FPS_INST0_ENABLE_SHIFT;
361
   }
362
 
363
   if (shader->NumPasses < 2) {
364
      for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
365
	 GLbitfield targetbit = ctx->Texture.Unit[reg]._ReallyEnabled;
366
         R200_STATECHANGE( rmesa, tex[reg] );
367
	 rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = 0;
368
	 if (shader->SetupInst[0][reg].Opcode) {
369
	    GLuint txformat = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT]
370
		& ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
371
	    GLuint txformat_x = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] & ~R200_TEXCOORD_MASK;
372
	    txformat |= (shader->SetupInst[0][reg].src - GL_TEXTURE0_ARB)
373
		<< R200_TXFORMAT_ST_ROUTE_SHIFT;
374
	    /* fix up texcoords for proj/non-proj 2d (3d and cube are not defined when
375
	       using projection so don't have to worry there).
376
	       When passing coords, need R200_TEXCOORD_VOLUME, otherwise loose a coord */
377
	    /* FIXME: someone might rely on default tex coords r/q, which we unfortunately
378
	       don't provide (we have the same problem without shaders) */
379
	    if (shader->SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
380
	       txformat |= R200_TXFORMAT_LOOKUP_DISABLE;
381
	       if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
382
		  shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
383
		  txformat_x |= R200_TEXCOORD_VOLUME;
384
	       }
385
	       else {
386
		  txformat_x |= R200_TEXCOORD_PROJ;
387
	       }
388
	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
389
	    }
390
	    else if (targetbit == TEXTURE_3D_BIT) {
391
	       txformat_x |= R200_TEXCOORD_VOLUME;
392
	    }
393
	    else if (targetbit == TEXTURE_CUBE_BIT) {
394
	       txformat_x |= R200_TEXCOORD_CUBIC_ENV;
395
	    }
396
	    else if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
397
	       shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
398
	       txformat_x |= R200_TEXCOORD_NONPROJ;
399
	    }
400
	    else {
401
	       txformat_x |= R200_TEXCOORD_PROJ;
402
	    }
403
	    rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] = txformat;
404
	    rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] = txformat_x;
405
	    /* enabling texturing when unit isn't correctly configured may not be safe */
406
	    if (targetbit)
407
	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
408
	 }
409
      }
410
 
411
   } else {
412
      /* setup 1st pass */
413
      for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
414
	 GLbitfield targetbit = ctx->Texture.Unit[reg]._ReallyEnabled;
415
	 R200_STATECHANGE( rmesa, tex[reg] );
416
	 GLuint txformat_multi = 0;
417
	 if (shader->SetupInst[0][reg].Opcode) {
418
	    txformat_multi |= (shader->SetupInst[0][reg].src - GL_TEXTURE0_ARB)
419
		<< R200_PASS1_ST_ROUTE_SHIFT;
420
	    if (shader->SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
421
	       txformat_multi |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE;
422
	       if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
423
		  shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
424
		  txformat_multi |= R200_PASS1_TEXCOORD_VOLUME;
425
	       }
426
	       else {
427
		  txformat_multi |= R200_PASS1_TEXCOORD_PROJ;
428
	       }
429
	       rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_0_ENABLE << reg;
430
	    }
431
	    else if (targetbit == TEXTURE_3D_BIT) {
432
	       txformat_multi |= R200_PASS1_TEXCOORD_VOLUME;
433
	    }
434
	    else if (targetbit == TEXTURE_CUBE_BIT) {
435
	       txformat_multi |= R200_PASS1_TEXCOORD_CUBIC_ENV;
436
	    }
437
	    else if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
438
		  shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
439
		  txformat_multi |= R200_PASS1_TEXCOORD_NONPROJ;
440
	    }
441
	    else {
442
	       txformat_multi |= R200_PASS1_TEXCOORD_PROJ;
443
	    }
444
	    if (targetbit)
445
	       rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_0_ENABLE << reg;
446
	 }
447
         rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = txformat_multi;
448
      }
449
 
450
      /* setup 2nd pass */
451
      for (reg=0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
452
	 GLbitfield targetbit = ctx->Texture.Unit[reg]._ReallyEnabled;
453
	 if (shader->SetupInst[1][reg].Opcode) {
454
	    GLuint coord = shader->SetupInst[1][reg].src;
455
	    GLuint txformat = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT]
456
		& ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
457
	    GLuint txformat_x = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] & ~R200_TEXCOORD_MASK;
458
	    R200_STATECHANGE( rmesa, tex[reg] );
459
	    if (shader->SetupInst[1][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
460
	       txformat |= R200_TXFORMAT_LOOKUP_DISABLE;
461
	       txformat_x |= R200_TEXCOORD_VOLUME;
462
	       if (shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI ||
463
		  shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
464
	          txformat_x |= R200_TEXCOORD_VOLUME;
465
	       }
466
	       else {
467
		  txformat_x |= R200_TEXCOORD_PROJ;
468
	       }
469
	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
470
	    }
471
	    else if (targetbit == TEXTURE_3D_BIT) {
472
	       txformat_x |= R200_TEXCOORD_VOLUME;
473
	    }
474
	    else if (targetbit == TEXTURE_CUBE_BIT) {
475
	       txformat_x |= R200_TEXCOORD_CUBIC_ENV;
476
	    }
477
	    else if (shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI ||
478
	       shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
479
	       txformat_x |= R200_TEXCOORD_NONPROJ;
480
	    }
481
	    else {
482
	       txformat_x |= R200_TEXCOORD_PROJ;
483
	    }
484
	    if (coord >= GL_REG_0_ATI) {
485
	       GLuint txformat_multi = rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL];
486
	       txformat_multi |= (coord - GL_REG_0_ATI + 2) << R200_PASS2_COORDS_REG_SHIFT;
487
	       rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = txformat_multi;
488
	       rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= 1 <<
489
		  (R200_PPX_OUTPUT_REG_0_SHIFT + coord - GL_REG_0_ATI);
490
	    } else {
491
	       txformat |= (coord - GL_TEXTURE0_ARB) << R200_TXFORMAT_ST_ROUTE_SHIFT;
492
	    }
493
	    rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] = txformat_x;
494
	    rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] = txformat;
495
	    if (targetbit)
496
	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
497
	 }
498
      }
499
   }
500
}
501
 
502
static void r200UpdateFSConstants( struct gl_context *ctx )
503
{
504
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
505
   const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
506
   GLuint i;
507
 
508
   /* update constants */
509
   R200_STATECHANGE(rmesa, atf);
510
   for (i = 0; i < 8; i++)
511
   {
512
      GLubyte con_byte[4];
513
      if ((shader->LocalConstDef >> i) & 1) {
514
	 CLAMPED_FLOAT_TO_UBYTE(con_byte[0], shader->Constants[i][0]);
515
	 CLAMPED_FLOAT_TO_UBYTE(con_byte[1], shader->Constants[i][1]);
516
	 CLAMPED_FLOAT_TO_UBYTE(con_byte[2], shader->Constants[i][2]);
517
	 CLAMPED_FLOAT_TO_UBYTE(con_byte[3], shader->Constants[i][3]);
518
      }
519
      else {
520
	 CLAMPED_FLOAT_TO_UBYTE(con_byte[0], ctx->ATIFragmentShader.GlobalConstants[i][0]);
521
	 CLAMPED_FLOAT_TO_UBYTE(con_byte[1], ctx->ATIFragmentShader.GlobalConstants[i][1]);
522
	 CLAMPED_FLOAT_TO_UBYTE(con_byte[2], ctx->ATIFragmentShader.GlobalConstants[i][2]);
523
	 CLAMPED_FLOAT_TO_UBYTE(con_byte[3], ctx->ATIFragmentShader.GlobalConstants[i][3]);
524
      }
525
      rmesa->hw.atf.cmd[ATF_TFACTOR_0 + i] = radeonPackColor (
526
	 4, con_byte[0], con_byte[1], con_byte[2], con_byte[3] );
527
   }
528
}
529
 
530
/* update routing, constants and arithmetic
531
 * constants need to be updated always (globals can change, no separate notification)
532
 * routing needs to be updated always too (non-shader code will overwrite state, plus
533
 * some of the routing depends on what sort of texture is bound)
534
 * for both of them, we need to update anyway because of disabling/enabling ati_fs which
535
 * we'd need to track otherwise
536
 * arithmetic is only updated if current shader changes (and probably the data should be
537
 * stored in some DriverData object attached to the mesa atifs object, i.e. binding a
538
 * shader wouldn't force us to "recompile" the shader).
539
 */
540
void r200UpdateFragmentShader( struct gl_context *ctx )
541
{
542
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
543
 
544
   r200UpdateFSConstants( ctx );
545
   r200UpdateFSRouting( ctx );
546
   if (rmesa->afs_loaded != ctx->ATIFragmentShader.Current)
547
      r200UpdateFSArith( ctx );
548
}