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
r200SetFragShaderArg(GLuint * afs_cmd,GLuint opnum,GLuint optype,const struct atifragshader_src_register srcReg,GLuint argPos,GLuint * tfactor)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
r200UpdateFSArith(struct gl_context * ctx)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
r200UpdateFSRouting(struct gl_context * ctx)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 struct gl_texture_object *texObj = ctx->Texture.Unit[reg]._Current;
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 (texObj && texObj->Target == GL_TEXTURE_3D) {
391 txformat_x |= R200_TEXCOORD_VOLUME;
392 }
393 else if (texObj && texObj->Target == GL_TEXTURE_CUBE_MAP) {
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 (texObj)
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 struct gl_texture_object *texObj = ctx->Texture.Unit[reg]._Current;
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 (texObj && texObj->Target == GL_TEXTURE_3D) {
432 txformat_multi |= R200_PASS1_TEXCOORD_VOLUME;
433 }
434 else if (texObj && texObj->Target == GL_TEXTURE_CUBE_MAP) {
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 (texObj)
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 struct gl_texture_object *texObj = ctx->Texture.Unit[reg]._Current;
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 (texObj && texObj->Target == GL_TEXTURE_3D) {
472 txformat_x |= R200_TEXCOORD_VOLUME;
473 }
474 else if (texObj && texObj->Target == GL_TEXTURE_CUBE_MAP) {
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 (texObj)
496 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg;
497 }
498 }
499 }
500 }
501
r200UpdateFSConstants(struct gl_context * ctx)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 */
r200UpdateFragmentShader(struct gl_context * ctx)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 }
549