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
41static 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
112static GLuint dstmask_table[9] =
113{
114   /* first slot never used, GL_NONE translated to RGB by mesa and you can't get a 0 dstmask. */
115   R200_TXC_OUTPUT_MASK_RGB,
116   R200_TXC_OUTPUT_MASK_R,
117   R200_TXC_OUTPUT_MASK_G,
118   R200_TXC_OUTPUT_MASK_RG,
119   R200_TXC_OUTPUT_MASK_B,
120   R200_TXC_OUTPUT_MASK_RB,
121   R200_TXC_OUTPUT_MASK_GB,
122   R200_TXC_OUTPUT_MASK_RGB,
123   R200_TXC_OUTPUT_MASK_RGB, /* alpha ops */
124};
125
126static void r200UpdateFSArith( struct gl_context *ctx )
127{
128   r200ContextPtr rmesa = R200_CONTEXT(ctx);
129   GLuint *afs_cmd;
130   const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
131   GLuint pass;
132
133   R200_STATECHANGE( rmesa, afs[0] );
134   R200_STATECHANGE( rmesa, afs[1] );
135
136   if (shader->NumPasses < 2) {
137      afs_cmd = (GLuint *) rmesa->hw.afs[1].cmd;
138   }
139   else {
140      afs_cmd = (GLuint *) rmesa->hw.afs[0].cmd;
141   }
142   for (pass = 0; pass < shader->NumPasses; pass++) {
143      GLuint opnum = 0;
144      GLuint pc;
145      for (pc = 0; pc < shader->numArithInstr[pass]; pc++) {
146         GLuint optype;
147	 struct atifs_instruction *inst = &shader->Instructions[pass][pc];
148
149	 SET_INST(opnum, 0) = 0;
150	 SET_INST_2(opnum, 0) = 0;
151	 SET_INST(opnum, 1) = 0;
152	 SET_INST_2(opnum, 1) = 0;
153
154	 for (optype = 0; optype < 2; optype++) {
155	    GLuint tfactor = 0;
156
157	    if (inst->Opcode[optype]) {
158	       switch (inst->Opcode[optype]) {
159	       /* these are all MADD in disguise
160		  MADD is A * B + C
161		  so for GL_ADD use arg B/C and make A complement 0
162		  for GL_SUB use arg B/C, negate C and make A complement 0
163		  for GL_MOV use arg C
164		  for GL_MUL use arg A
165		  for GL_MAD all good */
166	       case GL_SUB_ATI:
167		  /* negate C */
168		  SET_INST(opnum, optype) |= R200_TXC_NEG_ARG_C;
169		  FALLTHROUGH;
170	       case GL_ADD_ATI:
171		  r200SetFragShaderArg(afs_cmd, opnum, optype,
172					inst->SrcReg[optype][0], 1, &tfactor);
173		  r200SetFragShaderArg(afs_cmd, opnum, optype,
174					inst->SrcReg[optype][1], 2, &tfactor);
175		  /* A = complement 0 */
176		  SET_INST(opnum, optype) |= R200_TXC_COMP_ARG_A;
177		  SET_INST(opnum, optype) |= R200_TXC_OP_MADD;
178		  break;
179	       case GL_MOV_ATI:
180		  /* put arg0 in C */
181		  r200SetFragShaderArg(afs_cmd, opnum, optype,
182					inst->SrcReg[optype][0], 2, &tfactor);
183		  SET_INST(opnum, optype) |= R200_TXC_OP_MADD;
184		  break;
185	       case GL_MAD_ATI:
186		  r200SetFragShaderArg(afs_cmd, opnum, optype,
187					inst->SrcReg[optype][2], 2, &tfactor);
188		  FALLTHROUGH;
189	       case GL_MUL_ATI:
190		  r200SetFragShaderArg(afs_cmd, opnum, optype,
191					inst->SrcReg[optype][0], 0, &tfactor);
192		  r200SetFragShaderArg(afs_cmd, opnum, optype,
193					inst->SrcReg[optype][1], 1, &tfactor);
194		  SET_INST(opnum, optype) |= R200_TXC_OP_MADD;
195		  break;
196	       case GL_LERP_ATI:
197		  /* arg order is not native chip order, swap A and C */
198		  r200SetFragShaderArg(afs_cmd, opnum, optype,
199					inst->SrcReg[optype][0], 2, &tfactor);
200		  r200SetFragShaderArg(afs_cmd, opnum, optype,
201					inst->SrcReg[optype][1], 1, &tfactor);
202		  r200SetFragShaderArg(afs_cmd, opnum, optype,
203					inst->SrcReg[optype][2], 0, &tfactor);
204		  SET_INST(opnum, optype) |= R200_TXC_OP_LERP;
205		  break;
206	       case GL_CND_ATI:
207		  r200SetFragShaderArg(afs_cmd, opnum, optype,
208					inst->SrcReg[optype][0], 0, &tfactor);
209		  r200SetFragShaderArg(afs_cmd, opnum, optype,
210					inst->SrcReg[optype][1], 1, &tfactor);
211		  r200SetFragShaderArg(afs_cmd, opnum, optype,
212					inst->SrcReg[optype][2], 2, &tfactor);
213		  SET_INST(opnum, optype) |= R200_TXC_OP_CONDITIONAL;
214		  break;
215	       case GL_CND0_ATI:
216		  r200SetFragShaderArg(afs_cmd, opnum, optype,
217					inst->SrcReg[optype][0], 0, &tfactor);
218		  r200SetFragShaderArg(afs_cmd, opnum, optype,
219					inst->SrcReg[optype][1], 1, &tfactor);
220		  r200SetFragShaderArg(afs_cmd, opnum, optype,
221					inst->SrcReg[optype][2], 2, &tfactor);
222		  SET_INST(opnum, optype) |= R200_TXC_OP_CND0;
223		  break;
224		  /* cannot specify dot ops as alpha ops directly */
225	       case GL_DOT2_ADD_ATI:
226		  if (optype)
227		     SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA;
228		  else {
229		     r200SetFragShaderArg(afs_cmd, opnum, 0,
230					inst->SrcReg[0][0], 0, &tfactor);
231		     r200SetFragShaderArg(afs_cmd, opnum, 0,
232					inst->SrcReg[0][1], 1, &tfactor);
233		     r200SetFragShaderArg(afs_cmd, opnum, 0,
234					inst->SrcReg[0][2], 2, &tfactor);
235		     SET_INST(opnum, 0) |= R200_TXC_OP_DOT2_ADD;
236		  }
237		  break;
238	       case GL_DOT3_ATI:
239		  if (optype)
240		     SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA;
241		  else {
242		     r200SetFragShaderArg(afs_cmd, opnum, 0,
243					inst->SrcReg[0][0], 0, &tfactor);
244		     r200SetFragShaderArg(afs_cmd, opnum, 0,
245					inst->SrcReg[0][1], 1, &tfactor);
246		     SET_INST(opnum, 0) |= R200_TXC_OP_DOT3;
247		  }
248		  break;
249	       case GL_DOT4_ATI:
250	       /* experimental verification: for dot4 setup of alpha args is needed
251		  (dstmod is ignored, though, so dot2/dot3 should be safe)
252		  the hardware apparently does R1*R2 + G1*G2 + B1*B2 + A3*A4
253		  but the API doesn't allow it */
254		  if (optype)
255		     SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA;
256		  else {
257		     r200SetFragShaderArg(afs_cmd, opnum, 0,
258					inst->SrcReg[0][0], 0, &tfactor);
259		     r200SetFragShaderArg(afs_cmd, opnum, 0,
260					inst->SrcReg[0][1], 1, &tfactor);
261		     r200SetFragShaderArg(afs_cmd, opnum, 1,
262					inst->SrcReg[0][0], 0, &tfactor);
263		     r200SetFragShaderArg(afs_cmd, opnum, 1,
264					inst->SrcReg[0][1], 1, &tfactor);
265		     SET_INST(opnum, optype) |= R200_TXC_OP_DOT4;
266		  }
267		  break;
268	       }
269	    }
270
271	    /* destination */
272	    if (inst->DstReg[optype].Index) {
273	       GLuint dstreg = inst->DstReg[optype].Index - GL_REG_0_ATI;
274	       GLuint dstmask = inst->DstReg[optype].dstMask;
275	       GLuint sat = inst->DstReg[optype].dstMod & GL_SATURATE_BIT_ATI;
276	       GLuint dstmod = inst->DstReg[optype].dstMod;
277
278	       dstmod &= ~GL_SATURATE_BIT_ATI;
279
280	       SET_INST_2(opnum, optype) |= (dstreg + 1) << R200_TXC_OUTPUT_REG_SHIFT;
281	       SET_INST_2(opnum, optype) |= dstmask_table[dstmask];
282
283		/* fglrx does clamp the last instructions to 0_1 it seems */
284		/* this won't necessarily catch the last instruction
285		   which writes to reg0 */
286	       if (sat || (pc == (shader->numArithInstr[pass] - 1) &&
287			((pass == 1) || (shader->NumPasses == 1))))
288		  SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_0_1;
289	       else
290		/*should we clamp or not? spec is vague, I would suppose yes but fglrx doesn't */
291		  SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_8_8;
292/*		  SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_WRAP;*/
293	       switch(dstmod) {
294	       case GL_2X_BIT_ATI:
295		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_2X;
296		  break;
297	       case GL_4X_BIT_ATI:
298		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_4X;
299		  break;
300	       case GL_8X_BIT_ATI:
301		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_8X;
302		  break;
303	       case GL_HALF_BIT_ATI:
304		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV2;
305		  break;
306	       case GL_QUARTER_BIT_ATI:
307		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV4;
308		  break;
309	       case GL_EIGHTH_BIT_ATI:
310		  SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV8;
311		  break;
312	       default:
313		  break;
314	       }
315	    }
316	 }
317/*	 fprintf(stderr, "pass %d nr %d inst 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
318		pass, opnum, SET_INST(opnum, 0), SET_INST_2(opnum, 0),
319		SET_INST(opnum, 1), SET_INST_2(opnum, 1));*/
320         opnum++;
321      }
322      afs_cmd = (GLuint *) rmesa->hw.afs[1].cmd;
323   }
324   rmesa->afs_loaded = ctx->ATIFragmentShader.Current;
325}
326
327static void r200UpdateFSRouting( struct gl_context *ctx ) {
328   r200ContextPtr rmesa = R200_CONTEXT(ctx);
329   const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
330   GLuint reg;
331
332   R200_STATECHANGE( rmesa, ctx );
333   R200_STATECHANGE( rmesa, cst );
334
335   for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
336      if (shader->swizzlerq & (1 << (2 * reg)))
337	 /* r coord */
338	 set_re_cntl_d3d( ctx, reg, 1);
339	 /* q coord */
340      else set_re_cntl_d3d( ctx, reg, 0);
341   }
342
343   rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_MULTI_PASS_ENABLE |
344				       R200_TEX_BLEND_ENABLE_MASK |
345				       R200_TEX_ENABLE_MASK);
346   rmesa->hw.cst.cmd[CST_PP_CNTL_X] &= ~(R200_PPX_PFS_INST_ENABLE_MASK |
347					 R200_PPX_TEX_ENABLE_MASK |
348					 R200_PPX_OUTPUT_REG_MASK);
349
350   /* first pass registers use slots 8 - 15
351      but single pass shaders use slots 0 - 7 */
352   if (shader->NumPasses < 2) {
353      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->numArithInstr[0] == 8 ?
354	 0xff << (R200_TEX_BLEND_0_ENABLE_SHIFT - 1) :
355	 (0xff >> (8 - shader->numArithInstr[0])) << R200_TEX_BLEND_0_ENABLE_SHIFT;
356   } else {
357      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_MULTI_PASS_ENABLE;
358      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->numArithInstr[1] == 8 ?
359	 0xff << (R200_TEX_BLEND_0_ENABLE_SHIFT - 1) :
360	 (0xff >> (8 - shader->numArithInstr[1])) << R200_TEX_BLEND_0_ENABLE_SHIFT;
361      rmesa->hw.cst.cmd[CST_PP_CNTL_X] |=
362	 (0xff >> (8 - shader->numArithInstr[0])) << R200_PPX_FPS_INST0_ENABLE_SHIFT;
363   }
364
365   if (shader->NumPasses < 2) {
366      for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
367         struct gl_texture_object *texObj = ctx->Texture.Unit[reg]._Current;
368         R200_STATECHANGE( rmesa, tex[reg] );
369	 rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = 0;
370	 if (shader->SetupInst[0][reg].Opcode) {
371	    GLuint txformat = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT]
372		& ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
373	    GLuint txformat_x = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] & ~R200_TEXCOORD_MASK;
374	    txformat |= (shader->SetupInst[0][reg].src - GL_TEXTURE0_ARB)
375		<< R200_TXFORMAT_ST_ROUTE_SHIFT;
376	    /* fix up texcoords for proj/non-proj 2d (3d and cube are not defined when
377	       using projection so don't have to worry there).
378	       When passing coords, need R200_TEXCOORD_VOLUME, otherwise loose a coord */
379	    /* FIXME: someone might rely on default tex coords r/q, which we unfortunately
380	       don't provide (we have the same problem without shaders) */
381	    if (shader->SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
382	       txformat |= R200_TXFORMAT_LOOKUP_DISABLE;
383	       if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
384		  shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
385		  txformat_x |= R200_TEXCOORD_VOLUME;
386	       }
387	       else {
388		  txformat_x |= R200_TEXCOORD_PROJ;
389	       }
390	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
391	    }
392	    else if (texObj && texObj->Target == GL_TEXTURE_3D) {
393	       txformat_x |= R200_TEXCOORD_VOLUME;
394	    }
395	    else if (texObj && texObj->Target == GL_TEXTURE_CUBE_MAP) {
396	       txformat_x |= R200_TEXCOORD_CUBIC_ENV;
397	    }
398	    else if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
399	       shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
400	       txformat_x |= R200_TEXCOORD_NONPROJ;
401	    }
402	    else {
403	       txformat_x |= R200_TEXCOORD_PROJ;
404	    }
405	    rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] = txformat;
406	    rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] = txformat_x;
407	    /* enabling texturing when unit isn't correctly configured may not be safe */
408	    if (texObj)
409	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
410	 }
411      }
412
413   } else {
414      /* setup 1st pass */
415      for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
416	 struct gl_texture_object *texObj = ctx->Texture.Unit[reg]._Current;
417	 R200_STATECHANGE( rmesa, tex[reg] );
418	 GLuint txformat_multi = 0;
419	 if (shader->SetupInst[0][reg].Opcode) {
420	    txformat_multi |= (shader->SetupInst[0][reg].src - GL_TEXTURE0_ARB)
421		<< R200_PASS1_ST_ROUTE_SHIFT;
422	    if (shader->SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
423	       txformat_multi |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE;
424	       if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
425		  shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
426		  txformat_multi |= R200_PASS1_TEXCOORD_VOLUME;
427	       }
428	       else {
429		  txformat_multi |= R200_PASS1_TEXCOORD_PROJ;
430	       }
431	       rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_0_ENABLE << reg;
432	    }
433	    else if (texObj && texObj->Target == GL_TEXTURE_3D) {
434	       txformat_multi |= R200_PASS1_TEXCOORD_VOLUME;
435	    }
436	    else if (texObj && texObj->Target == GL_TEXTURE_CUBE_MAP) {
437	       txformat_multi |= R200_PASS1_TEXCOORD_CUBIC_ENV;
438	    }
439	    else if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI ||
440		  shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
441		  txformat_multi |= R200_PASS1_TEXCOORD_NONPROJ;
442	    }
443	    else {
444	       txformat_multi |= R200_PASS1_TEXCOORD_PROJ;
445	    }
446	    if (texObj)
447	       rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_0_ENABLE << reg;
448	 }
449         rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = txformat_multi;
450      }
451
452      /* setup 2nd pass */
453      for (reg=0; reg < R200_MAX_TEXTURE_UNITS; reg++) {
454	 struct gl_texture_object *texObj = ctx->Texture.Unit[reg]._Current;
455	 if (shader->SetupInst[1][reg].Opcode) {
456	    GLuint coord = shader->SetupInst[1][reg].src;
457	    GLuint txformat = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT]
458		& ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
459	    GLuint txformat_x = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] & ~R200_TEXCOORD_MASK;
460	    R200_STATECHANGE( rmesa, tex[reg] );
461	    if (shader->SetupInst[1][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
462	       txformat |= R200_TXFORMAT_LOOKUP_DISABLE;
463	       txformat_x |= R200_TEXCOORD_VOLUME;
464	       if (shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI ||
465		  shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
466	          txformat_x |= R200_TEXCOORD_VOLUME;
467	       }
468	       else {
469		  txformat_x |= R200_TEXCOORD_PROJ;
470	       }
471	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
472	    }
473	    else if (texObj && texObj->Target == GL_TEXTURE_3D) {
474	       txformat_x |= R200_TEXCOORD_VOLUME;
475	    }
476	    else if (texObj && texObj->Target == GL_TEXTURE_CUBE_MAP) {
477	       txformat_x |= R200_TEXCOORD_CUBIC_ENV;
478	    }
479	    else if (shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI ||
480	       shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) {
481	       txformat_x |= R200_TEXCOORD_NONPROJ;
482	    }
483	    else {
484	       txformat_x |= R200_TEXCOORD_PROJ;
485	    }
486	    if (coord >= GL_REG_0_ATI) {
487	       GLuint txformat_multi = rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL];
488	       txformat_multi |= (coord - GL_REG_0_ATI + 2) << R200_PASS2_COORDS_REG_SHIFT;
489	       rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = txformat_multi;
490	       rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= 1 <<
491		  (R200_PPX_OUTPUT_REG_0_SHIFT + coord - GL_REG_0_ATI);
492	    } else {
493	       txformat |= (coord - GL_TEXTURE0_ARB) << R200_TXFORMAT_ST_ROUTE_SHIFT;
494	    }
495	    rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] = txformat_x;
496	    rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] = txformat;
497	    if (texObj)
498	       rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
499	 }
500      }
501   }
502}
503
504static void r200UpdateFSConstants( struct gl_context *ctx )
505{
506   r200ContextPtr rmesa = R200_CONTEXT(ctx);
507   const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
508   GLuint i;
509
510   /* update constants */
511   R200_STATECHANGE(rmesa, atf);
512   for (i = 0; i < 8; i++)
513   {
514      GLubyte con_byte[4];
515      if ((shader->LocalConstDef >> i) & 1) {
516	 CLAMPED_FLOAT_TO_UBYTE(con_byte[0], shader->Constants[i][0]);
517	 CLAMPED_FLOAT_TO_UBYTE(con_byte[1], shader->Constants[i][1]);
518	 CLAMPED_FLOAT_TO_UBYTE(con_byte[2], shader->Constants[i][2]);
519	 CLAMPED_FLOAT_TO_UBYTE(con_byte[3], shader->Constants[i][3]);
520      }
521      else {
522	 CLAMPED_FLOAT_TO_UBYTE(con_byte[0], ctx->ATIFragmentShader.GlobalConstants[i][0]);
523	 CLAMPED_FLOAT_TO_UBYTE(con_byte[1], ctx->ATIFragmentShader.GlobalConstants[i][1]);
524	 CLAMPED_FLOAT_TO_UBYTE(con_byte[2], ctx->ATIFragmentShader.GlobalConstants[i][2]);
525	 CLAMPED_FLOAT_TO_UBYTE(con_byte[3], ctx->ATIFragmentShader.GlobalConstants[i][3]);
526      }
527      rmesa->hw.atf.cmd[ATF_TFACTOR_0 + i] = radeonPackColor (
528	 4, con_byte[0], con_byte[1], con_byte[2], con_byte[3] );
529   }
530}
531
532/* update routing, constants and arithmetic
533 * constants need to be updated always (globals can change, no separate notification)
534 * routing needs to be updated always too (non-shader code will overwrite state, plus
535 * some of the routing depends on what sort of texture is bound)
536 * for both of them, we need to update anyway because of disabling/enabling ati_fs which
537 * we'd need to track otherwise
538 * arithmetic is only updated if current shader changes (and probably the data should be
539 * stored in some DriverData object attached to the mesa atifs object, i.e. binding a
540 * shader wouldn't force us to "recompile" the shader).
541 */
542void r200UpdateFragmentShader( struct gl_context *ctx )
543{
544   r200ContextPtr rmesa = R200_CONTEXT(ctx);
545
546   r200UpdateFSConstants( ctx );
547   r200UpdateFSRouting( ctx );
548   if (rmesa->afs_loaded != ctx->ATIFragmentShader.Current)
549      r200UpdateFSArith( ctx );
550}
551