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 | }>><>><> |