1 /*
2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
3
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /*
31 * Authors:
32 * Keith Whitwell <keithw@vmware.com>
33 */
34
35 #include "main/glheader.h"
36 #include "main/imports.h"
37 #include "main/context.h"
38 #include "main/macros.h"
39 #include "main/teximage.h"
40 #include "main/texobj.h"
41 #include "main/enums.h"
42
43 #include "radeon_common.h"
44 #include "radeon_mipmap_tree.h"
45 #include "r200_context.h"
46 #include "r200_state.h"
47 #include "r200_ioctl.h"
48 #include "r200_swtcl.h"
49 #include "r200_tex.h"
50 #include "r200_tcl.h"
51
52 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
53 && (tx_table_be[f].format != 0xffffffff) )
54
55 /* ================================================================
56 * Texture combine functions
57 */
58
59 /* GL_ARB_texture_env_combine support
60 */
61
62 /* The color tables have combine functions for GL_SRC_COLOR,
63 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
64 */
65 static GLuint r200_register_color[][R200_MAX_TEXTURE_UNITS] =
66 {
67 {
68 R200_TXC_ARG_A_R0_COLOR,
69 R200_TXC_ARG_A_R1_COLOR,
70 R200_TXC_ARG_A_R2_COLOR,
71 R200_TXC_ARG_A_R3_COLOR,
72 R200_TXC_ARG_A_R4_COLOR,
73 R200_TXC_ARG_A_R5_COLOR
74 },
75 {
76 R200_TXC_ARG_A_R0_COLOR | R200_TXC_COMP_ARG_A,
77 R200_TXC_ARG_A_R1_COLOR | R200_TXC_COMP_ARG_A,
78 R200_TXC_ARG_A_R2_COLOR | R200_TXC_COMP_ARG_A,
79 R200_TXC_ARG_A_R3_COLOR | R200_TXC_COMP_ARG_A,
80 R200_TXC_ARG_A_R4_COLOR | R200_TXC_COMP_ARG_A,
81 R200_TXC_ARG_A_R5_COLOR | R200_TXC_COMP_ARG_A
82 },
83 {
84 R200_TXC_ARG_A_R0_ALPHA,
85 R200_TXC_ARG_A_R1_ALPHA,
86 R200_TXC_ARG_A_R2_ALPHA,
87 R200_TXC_ARG_A_R3_ALPHA,
88 R200_TXC_ARG_A_R4_ALPHA,
89 R200_TXC_ARG_A_R5_ALPHA
90 },
91 {
92 R200_TXC_ARG_A_R0_ALPHA | R200_TXC_COMP_ARG_A,
93 R200_TXC_ARG_A_R1_ALPHA | R200_TXC_COMP_ARG_A,
94 R200_TXC_ARG_A_R2_ALPHA | R200_TXC_COMP_ARG_A,
95 R200_TXC_ARG_A_R3_ALPHA | R200_TXC_COMP_ARG_A,
96 R200_TXC_ARG_A_R4_ALPHA | R200_TXC_COMP_ARG_A,
97 R200_TXC_ARG_A_R5_ALPHA | R200_TXC_COMP_ARG_A
98 },
99 };
100
101 static GLuint r200_tfactor_color[] =
102 {
103 R200_TXC_ARG_A_TFACTOR_COLOR,
104 R200_TXC_ARG_A_TFACTOR_COLOR | R200_TXC_COMP_ARG_A,
105 R200_TXC_ARG_A_TFACTOR_ALPHA,
106 R200_TXC_ARG_A_TFACTOR_ALPHA | R200_TXC_COMP_ARG_A
107 };
108
109 static GLuint r200_tfactor1_color[] =
110 {
111 R200_TXC_ARG_A_TFACTOR1_COLOR,
112 R200_TXC_ARG_A_TFACTOR1_COLOR | R200_TXC_COMP_ARG_A,
113 R200_TXC_ARG_A_TFACTOR1_ALPHA,
114 R200_TXC_ARG_A_TFACTOR1_ALPHA | R200_TXC_COMP_ARG_A
115 };
116
117 static GLuint r200_primary_color[] =
118 {
119 R200_TXC_ARG_A_DIFFUSE_COLOR,
120 R200_TXC_ARG_A_DIFFUSE_COLOR | R200_TXC_COMP_ARG_A,
121 R200_TXC_ARG_A_DIFFUSE_ALPHA,
122 R200_TXC_ARG_A_DIFFUSE_ALPHA | R200_TXC_COMP_ARG_A
123 };
124
125 /* GL_ZERO table - indices 0-3
126 * GL_ONE table - indices 1-4
127 */
128 static GLuint r200_zero_color[] =
129 {
130 R200_TXC_ARG_A_ZERO,
131 R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
132 R200_TXC_ARG_A_ZERO,
133 R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
134 R200_TXC_ARG_A_ZERO
135 };
136
137 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
138 */
139 static GLuint r200_register_alpha[][R200_MAX_TEXTURE_UNITS] =
140 {
141 {
142 R200_TXA_ARG_A_R0_ALPHA,
143 R200_TXA_ARG_A_R1_ALPHA,
144 R200_TXA_ARG_A_R2_ALPHA,
145 R200_TXA_ARG_A_R3_ALPHA,
146 R200_TXA_ARG_A_R4_ALPHA,
147 R200_TXA_ARG_A_R5_ALPHA
148 },
149 {
150 R200_TXA_ARG_A_R0_ALPHA | R200_TXA_COMP_ARG_A,
151 R200_TXA_ARG_A_R1_ALPHA | R200_TXA_COMP_ARG_A,
152 R200_TXA_ARG_A_R2_ALPHA | R200_TXA_COMP_ARG_A,
153 R200_TXA_ARG_A_R3_ALPHA | R200_TXA_COMP_ARG_A,
154 R200_TXA_ARG_A_R4_ALPHA | R200_TXA_COMP_ARG_A,
155 R200_TXA_ARG_A_R5_ALPHA | R200_TXA_COMP_ARG_A
156 },
157 };
158
159 static GLuint r200_tfactor_alpha[] =
160 {
161 R200_TXA_ARG_A_TFACTOR_ALPHA,
162 R200_TXA_ARG_A_TFACTOR_ALPHA | R200_TXA_COMP_ARG_A
163 };
164
165 static GLuint r200_tfactor1_alpha[] =
166 {
167 R200_TXA_ARG_A_TFACTOR1_ALPHA,
168 R200_TXA_ARG_A_TFACTOR1_ALPHA | R200_TXA_COMP_ARG_A
169 };
170
171 static GLuint r200_primary_alpha[] =
172 {
173 R200_TXA_ARG_A_DIFFUSE_ALPHA,
174 R200_TXA_ARG_A_DIFFUSE_ALPHA | R200_TXA_COMP_ARG_A
175 };
176
177 /* GL_ZERO table - indices 0-1
178 * GL_ONE table - indices 1-2
179 */
180 static GLuint r200_zero_alpha[] =
181 {
182 R200_TXA_ARG_A_ZERO,
183 R200_TXA_ARG_A_ZERO | R200_TXA_COMP_ARG_A,
184 R200_TXA_ARG_A_ZERO,
185 };
186
187
188 /* Extract the arg from slot A, shift it into the correct argument slot
189 * and set the corresponding complement bit.
190 */
191 #define R200_COLOR_ARG( n, arg ) \
192 do { \
193 color_combine |= \
194 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
195 << R200_TXC_ARG_##arg##_SHIFT); \
196 color_combine |= \
197 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
198 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
199 } while (0)
200
201 #define R200_ALPHA_ARG( n, arg ) \
202 do { \
203 alpha_combine |= \
204 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
205 << R200_TXA_ARG_##arg##_SHIFT); \
206 alpha_combine |= \
207 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
208 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
209 } while (0)
210
211
212 /* ================================================================
213 * Texture unit state management
214 */
215
r200UpdateTextureEnv(struct gl_context * ctx,int unit,int slot,GLuint replaceargs)216 static GLboolean r200UpdateTextureEnv( struct gl_context *ctx, int unit, int slot, GLuint replaceargs )
217 {
218 r200ContextPtr rmesa = R200_CONTEXT(ctx);
219 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
220 GLuint color_combine, alpha_combine;
221 GLuint color_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] &
222 ~(R200_TXC_SCALE_MASK | R200_TXC_OUTPUT_REG_MASK | R200_TXC_TFACTOR_SEL_MASK |
223 R200_TXC_TFACTOR1_SEL_MASK);
224 GLuint alpha_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] &
225 ~(R200_TXA_DOT_ALPHA | R200_TXA_SCALE_MASK | R200_TXA_OUTPUT_REG_MASK |
226 R200_TXA_TFACTOR_SEL_MASK | R200_TXA_TFACTOR1_SEL_MASK);
227
228 if ( R200_DEBUG & RADEON_TEXTURE ) {
229 fprintf( stderr, "%s( %p, %d )\n", __func__, (void *)ctx, unit );
230 }
231
232 /* Set the texture environment state. Isn't this nice and clean?
233 * The chip will automagically set the texture alpha to 0xff when
234 * the texture format does not include an alpha component. This
235 * reduces the amount of special-casing we have to do, alpha-only
236 * textures being a notable exception.
237 */
238
239 color_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXC_OUTPUT_REG_SHIFT) |
240 (unit << R200_TXC_TFACTOR_SEL_SHIFT) |
241 (replaceargs << R200_TXC_TFACTOR1_SEL_SHIFT);
242 alpha_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXA_OUTPUT_REG_SHIFT) |
243 (unit << R200_TXA_TFACTOR_SEL_SHIFT) |
244 (replaceargs << R200_TXA_TFACTOR1_SEL_SHIFT);
245
246 if ( !texUnit->_Current ) {
247 assert( unit == 0);
248 color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO
249 | R200_TXC_ARG_C_DIFFUSE_COLOR | R200_TXC_OP_MADD;
250 alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO
251 | R200_TXA_ARG_C_DIFFUSE_ALPHA | R200_TXA_OP_MADD;
252 }
253 else {
254 GLuint color_arg[3], alpha_arg[3];
255 GLuint i;
256 const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
257 const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
258 GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB;
259 GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA;
260
261
262 const GLint replaceoprgb =
263 ctx->Texture.Unit[replaceargs]._CurrentCombine->OperandRGB[0] - GL_SRC_COLOR;
264 const GLint replaceopa =
265 ctx->Texture.Unit[replaceargs]._CurrentCombine->OperandA[0] - GL_SRC_ALPHA;
266
267 /* Step 1:
268 * Extract the color and alpha combine function arguments.
269 */
270 for ( i = 0 ; i < numColorArgs ; i++ ) {
271 GLint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
272 const GLint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i];
273 assert(op >= 0);
274 assert(op <= 3);
275 switch ( srcRGBi ) {
276 case GL_TEXTURE:
277 color_arg[i] = r200_register_color[op][unit];
278 break;
279 case GL_CONSTANT:
280 color_arg[i] = r200_tfactor_color[op];
281 break;
282 case GL_PRIMARY_COLOR:
283 color_arg[i] = r200_primary_color[op];
284 break;
285 case GL_PREVIOUS:
286 if (replaceargs != unit) {
287 const GLint srcRGBreplace =
288 ctx->Texture.Unit[replaceargs]._CurrentCombine->SourceRGB[0];
289 if (op >= 2) {
290 op = op ^ replaceopa;
291 }
292 else {
293 op = op ^ replaceoprgb;
294 }
295 switch (srcRGBreplace) {
296 case GL_TEXTURE:
297 color_arg[i] = r200_register_color[op][replaceargs];
298 break;
299 case GL_CONSTANT:
300 color_arg[i] = r200_tfactor1_color[op];
301 break;
302 case GL_PRIMARY_COLOR:
303 color_arg[i] = r200_primary_color[op];
304 break;
305 case GL_PREVIOUS:
306 if (slot == 0)
307 color_arg[i] = r200_primary_color[op];
308 else
309 color_arg[i] = r200_register_color[op]
310 [rmesa->state.texture.unit[replaceargs - 1].outputreg];
311 break;
312 case GL_ZERO:
313 color_arg[i] = r200_zero_color[op];
314 break;
315 case GL_ONE:
316 color_arg[i] = r200_zero_color[op+1];
317 break;
318 case GL_TEXTURE0:
319 case GL_TEXTURE1:
320 case GL_TEXTURE2:
321 case GL_TEXTURE3:
322 case GL_TEXTURE4:
323 case GL_TEXTURE5:
324 color_arg[i] = r200_register_color[op][srcRGBreplace - GL_TEXTURE0];
325 break;
326 default:
327 return GL_FALSE;
328 }
329 }
330 else {
331 if (slot == 0)
332 color_arg[i] = r200_primary_color[op];
333 else
334 color_arg[i] = r200_register_color[op]
335 [rmesa->state.texture.unit[unit - 1].outputreg];
336 }
337 break;
338 case GL_ZERO:
339 color_arg[i] = r200_zero_color[op];
340 break;
341 case GL_ONE:
342 color_arg[i] = r200_zero_color[op+1];
343 break;
344 case GL_TEXTURE0:
345 case GL_TEXTURE1:
346 case GL_TEXTURE2:
347 case GL_TEXTURE3:
348 case GL_TEXTURE4:
349 case GL_TEXTURE5:
350 color_arg[i] = r200_register_color[op][srcRGBi - GL_TEXTURE0];
351 break;
352 default:
353 return GL_FALSE;
354 }
355 }
356
357 for ( i = 0 ; i < numAlphaArgs ; i++ ) {
358 GLint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
359 const GLint srcAi = texUnit->_CurrentCombine->SourceA[i];
360 assert(op >= 0);
361 assert(op <= 1);
362 switch ( srcAi ) {
363 case GL_TEXTURE:
364 alpha_arg[i] = r200_register_alpha[op][unit];
365 break;
366 case GL_CONSTANT:
367 alpha_arg[i] = r200_tfactor_alpha[op];
368 break;
369 case GL_PRIMARY_COLOR:
370 alpha_arg[i] = r200_primary_alpha[op];
371 break;
372 case GL_PREVIOUS:
373 if (replaceargs != unit) {
374 const GLint srcAreplace =
375 ctx->Texture.Unit[replaceargs]._CurrentCombine->SourceA[0];
376 op = op ^ replaceopa;
377 switch (srcAreplace) {
378 case GL_TEXTURE:
379 alpha_arg[i] = r200_register_alpha[op][replaceargs];
380 break;
381 case GL_CONSTANT:
382 alpha_arg[i] = r200_tfactor1_alpha[op];
383 break;
384 case GL_PRIMARY_COLOR:
385 alpha_arg[i] = r200_primary_alpha[op];
386 break;
387 case GL_PREVIOUS:
388 if (slot == 0)
389 alpha_arg[i] = r200_primary_alpha[op];
390 else
391 alpha_arg[i] = r200_register_alpha[op]
392 [rmesa->state.texture.unit[replaceargs - 1].outputreg];
393 break;
394 case GL_ZERO:
395 alpha_arg[i] = r200_zero_alpha[op];
396 break;
397 case GL_ONE:
398 alpha_arg[i] = r200_zero_alpha[op+1];
399 break;
400 case GL_TEXTURE0:
401 case GL_TEXTURE1:
402 case GL_TEXTURE2:
403 case GL_TEXTURE3:
404 case GL_TEXTURE4:
405 case GL_TEXTURE5:
406 alpha_arg[i] = r200_register_alpha[op][srcAreplace - GL_TEXTURE0];
407 break;
408 default:
409 return GL_FALSE;
410 }
411 }
412 else {
413 if (slot == 0)
414 alpha_arg[i] = r200_primary_alpha[op];
415 else
416 alpha_arg[i] = r200_register_alpha[op]
417 [rmesa->state.texture.unit[unit - 1].outputreg];
418 }
419 break;
420 case GL_ZERO:
421 alpha_arg[i] = r200_zero_alpha[op];
422 break;
423 case GL_ONE:
424 alpha_arg[i] = r200_zero_alpha[op+1];
425 break;
426 case GL_TEXTURE0:
427 case GL_TEXTURE1:
428 case GL_TEXTURE2:
429 case GL_TEXTURE3:
430 case GL_TEXTURE4:
431 case GL_TEXTURE5:
432 alpha_arg[i] = r200_register_alpha[op][srcAi - GL_TEXTURE0];
433 break;
434 default:
435 return GL_FALSE;
436 }
437 }
438
439 /* Step 2:
440 * Build up the color and alpha combine functions.
441 */
442 switch ( texUnit->_CurrentCombine->ModeRGB ) {
443 case GL_REPLACE:
444 color_combine = (R200_TXC_ARG_A_ZERO |
445 R200_TXC_ARG_B_ZERO |
446 R200_TXC_OP_MADD);
447 R200_COLOR_ARG( 0, C );
448 break;
449 case GL_MODULATE:
450 color_combine = (R200_TXC_ARG_C_ZERO |
451 R200_TXC_OP_MADD);
452 R200_COLOR_ARG( 0, A );
453 R200_COLOR_ARG( 1, B );
454 break;
455 case GL_ADD:
456 color_combine = (R200_TXC_ARG_B_ZERO |
457 R200_TXC_COMP_ARG_B |
458 R200_TXC_OP_MADD);
459 R200_COLOR_ARG( 0, A );
460 R200_COLOR_ARG( 1, C );
461 break;
462 case GL_ADD_SIGNED:
463 color_combine = (R200_TXC_ARG_B_ZERO |
464 R200_TXC_COMP_ARG_B |
465 R200_TXC_BIAS_ARG_C | /* new */
466 R200_TXC_OP_MADD); /* was ADDSIGNED */
467 R200_COLOR_ARG( 0, A );
468 R200_COLOR_ARG( 1, C );
469 break;
470 case GL_SUBTRACT:
471 color_combine = (R200_TXC_ARG_B_ZERO |
472 R200_TXC_COMP_ARG_B |
473 R200_TXC_NEG_ARG_C |
474 R200_TXC_OP_MADD);
475 R200_COLOR_ARG( 0, A );
476 R200_COLOR_ARG( 1, C );
477 break;
478 case GL_INTERPOLATE:
479 color_combine = (R200_TXC_OP_LERP);
480 R200_COLOR_ARG( 0, B );
481 R200_COLOR_ARG( 1, A );
482 R200_COLOR_ARG( 2, C );
483 break;
484
485 case GL_DOT3_RGB_EXT:
486 case GL_DOT3_RGBA_EXT:
487 /* The EXT version of the DOT3 extension does not support the
488 * scale factor, but the ARB version (and the version in OpenGL
489 * 1.3) does.
490 */
491 RGBshift = 0;
492 /* FALLTHROUGH */
493
494 case GL_DOT3_RGB:
495 case GL_DOT3_RGBA:
496 /* DOT3 works differently on R200 than on R100. On R100, just
497 * setting the DOT3 mode did everything for you. On R200, the
498 * driver has to enable the biasing and scale in the inputs to
499 * put them in the proper [-1,1] range. This is what the 4x and
500 * the -0.5 in the DOT3 spec do. The post-scale is then set
501 * normally.
502 */
503
504 color_combine = (R200_TXC_ARG_C_ZERO |
505 R200_TXC_OP_DOT3 |
506 R200_TXC_BIAS_ARG_A |
507 R200_TXC_BIAS_ARG_B |
508 R200_TXC_SCALE_ARG_A |
509 R200_TXC_SCALE_ARG_B);
510 R200_COLOR_ARG( 0, A );
511 R200_COLOR_ARG( 1, B );
512 break;
513
514 case GL_MODULATE_ADD_ATI:
515 color_combine = (R200_TXC_OP_MADD);
516 R200_COLOR_ARG( 0, A );
517 R200_COLOR_ARG( 1, C );
518 R200_COLOR_ARG( 2, B );
519 break;
520 case GL_MODULATE_SIGNED_ADD_ATI:
521 color_combine = (R200_TXC_BIAS_ARG_C | /* new */
522 R200_TXC_OP_MADD); /* was ADDSIGNED */
523 R200_COLOR_ARG( 0, A );
524 R200_COLOR_ARG( 1, C );
525 R200_COLOR_ARG( 2, B );
526 break;
527 case GL_MODULATE_SUBTRACT_ATI:
528 color_combine = (R200_TXC_NEG_ARG_C |
529 R200_TXC_OP_MADD);
530 R200_COLOR_ARG( 0, A );
531 R200_COLOR_ARG( 1, C );
532 R200_COLOR_ARG( 2, B );
533 break;
534 default:
535 return GL_FALSE;
536 }
537
538 switch ( texUnit->_CurrentCombine->ModeA ) {
539 case GL_REPLACE:
540 alpha_combine = (R200_TXA_ARG_A_ZERO |
541 R200_TXA_ARG_B_ZERO |
542 R200_TXA_OP_MADD);
543 R200_ALPHA_ARG( 0, C );
544 break;
545 case GL_MODULATE:
546 alpha_combine = (R200_TXA_ARG_C_ZERO |
547 R200_TXA_OP_MADD);
548 R200_ALPHA_ARG( 0, A );
549 R200_ALPHA_ARG( 1, B );
550 break;
551 case GL_ADD:
552 alpha_combine = (R200_TXA_ARG_B_ZERO |
553 R200_TXA_COMP_ARG_B |
554 R200_TXA_OP_MADD);
555 R200_ALPHA_ARG( 0, A );
556 R200_ALPHA_ARG( 1, C );
557 break;
558 case GL_ADD_SIGNED:
559 alpha_combine = (R200_TXA_ARG_B_ZERO |
560 R200_TXA_COMP_ARG_B |
561 R200_TXA_BIAS_ARG_C | /* new */
562 R200_TXA_OP_MADD); /* was ADDSIGNED */
563 R200_ALPHA_ARG( 0, A );
564 R200_ALPHA_ARG( 1, C );
565 break;
566 case GL_SUBTRACT:
567 alpha_combine = (R200_TXA_ARG_B_ZERO |
568 R200_TXA_COMP_ARG_B |
569 R200_TXA_NEG_ARG_C |
570 R200_TXA_OP_MADD);
571 R200_ALPHA_ARG( 0, A );
572 R200_ALPHA_ARG( 1, C );
573 break;
574 case GL_INTERPOLATE:
575 alpha_combine = (R200_TXA_OP_LERP);
576 R200_ALPHA_ARG( 0, B );
577 R200_ALPHA_ARG( 1, A );
578 R200_ALPHA_ARG( 2, C );
579 break;
580
581 case GL_MODULATE_ADD_ATI:
582 alpha_combine = (R200_TXA_OP_MADD);
583 R200_ALPHA_ARG( 0, A );
584 R200_ALPHA_ARG( 1, C );
585 R200_ALPHA_ARG( 2, B );
586 break;
587 case GL_MODULATE_SIGNED_ADD_ATI:
588 alpha_combine = (R200_TXA_BIAS_ARG_C | /* new */
589 R200_TXA_OP_MADD); /* was ADDSIGNED */
590 R200_ALPHA_ARG( 0, A );
591 R200_ALPHA_ARG( 1, C );
592 R200_ALPHA_ARG( 2, B );
593 break;
594 case GL_MODULATE_SUBTRACT_ATI:
595 alpha_combine = (R200_TXA_NEG_ARG_C |
596 R200_TXA_OP_MADD);
597 R200_ALPHA_ARG( 0, A );
598 R200_ALPHA_ARG( 1, C );
599 R200_ALPHA_ARG( 2, B );
600 break;
601 default:
602 return GL_FALSE;
603 }
604
605 if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT)
606 || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) {
607 alpha_scale |= R200_TXA_DOT_ALPHA;
608 Ashift = RGBshift;
609 }
610
611 /* Step 3:
612 * Apply the scale factor.
613 */
614 color_scale |= (RGBshift << R200_TXC_SCALE_SHIFT);
615 alpha_scale |= (Ashift << R200_TXA_SCALE_SHIFT);
616
617 /* All done!
618 */
619 }
620
621 if ( rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] != color_combine ||
622 rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] != alpha_combine ||
623 rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] != color_scale ||
624 rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] != alpha_scale) {
625 R200_STATECHANGE( rmesa, pix[slot] );
626 rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] = color_combine;
627 rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] = alpha_combine;
628 rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] = color_scale;
629 rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] = alpha_scale;
630 }
631
632 return GL_TRUE;
633 }
634
r200SetTexBuffer2(__DRIcontext * pDRICtx,GLint target,GLint texture_format,__DRIdrawable * dPriv)635 void r200SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint texture_format,
636 __DRIdrawable *dPriv)
637 {
638 struct gl_texture_object *texObj;
639 struct gl_texture_image *texImage;
640 struct radeon_renderbuffer *rb;
641 radeon_texture_image *rImage;
642 radeonContextPtr radeon;
643 struct radeon_framebuffer *rfb;
644 radeonTexObjPtr t;
645 uint32_t pitch_val;
646 mesa_format texFormat;
647
648 radeon = pDRICtx->driverPrivate;
649
650 rfb = dPriv->driverPrivate;
651 texObj = _mesa_get_current_tex_object(&radeon->glCtx, target);
652 texImage = _mesa_get_tex_image(&radeon->glCtx, texObj, target, 0);
653
654 rImage = get_radeon_texture_image(texImage);
655 t = radeon_tex_obj(texObj);
656 if (t == NULL) {
657 return;
658 }
659
660 radeon_update_renderbuffers(pDRICtx, dPriv, GL_TRUE);
661 rb = rfb->color_rb[0];
662 if (rb->bo == NULL) {
663 /* Failed to BO for the buffer */
664 return;
665 }
666
667 _mesa_lock_texture(&radeon->glCtx, texObj);
668 if (t->bo) {
669 radeon_bo_unref(t->bo);
670 t->bo = NULL;
671 }
672 if (rImage->bo) {
673 radeon_bo_unref(rImage->bo);
674 rImage->bo = NULL;
675 }
676
677 radeon_miptree_unreference(&t->mt);
678 radeon_miptree_unreference(&rImage->mt);
679
680 rImage->bo = rb->bo;
681 radeon_bo_ref(rImage->bo);
682 t->bo = rb->bo;
683 radeon_bo_ref(t->bo);
684 t->tile_bits = 0;
685 t->image_override = GL_TRUE;
686 t->override_offset = 0;
687 t->pp_txpitch &= (1 << 13) -1;
688 pitch_val = rb->pitch;
689 switch (rb->cpp) {
690 case 4:
691 if (texture_format == __DRI_TEXTURE_FORMAT_RGB) {
692 texFormat = MESA_FORMAT_BGR_UNORM8;
693 t->pp_txformat = tx_table_le[MESA_FORMAT_BGR_UNORM8].format;
694 }
695 else {
696 texFormat = MESA_FORMAT_B8G8R8A8_UNORM;
697 t->pp_txformat = tx_table_le[MESA_FORMAT_B8G8R8A8_UNORM].format;
698 }
699 t->pp_txfilter |= tx_table_le[MESA_FORMAT_B8G8R8A8_UNORM].filter;
700 break;
701 case 3:
702 default:
703 texFormat = MESA_FORMAT_BGR_UNORM8;
704 t->pp_txformat = tx_table_le[MESA_FORMAT_BGR_UNORM8].format;
705 t->pp_txfilter |= tx_table_le[MESA_FORMAT_BGR_UNORM8].filter;
706 break;
707 case 2:
708 texFormat = MESA_FORMAT_B5G6R5_UNORM;
709 t->pp_txformat = tx_table_le[MESA_FORMAT_B5G6R5_UNORM].format;
710 t->pp_txfilter |= tx_table_le[MESA_FORMAT_B5G6R5_UNORM].filter;
711 break;
712 }
713
714 _mesa_init_teximage_fields(&radeon->glCtx, texImage,
715 rb->base.Base.Width, rb->base.Base.Height,
716 1, 0,
717 rb->cpp, texFormat);
718 rImage->base.RowStride = rb->pitch / rb->cpp;
719
720
721 t->pp_txsize = ((rb->base.Base.Width - 1) << RADEON_TEX_USIZE_SHIFT)
722 | ((rb->base.Base.Height - 1) << RADEON_TEX_VSIZE_SHIFT);
723
724 if (target == GL_TEXTURE_RECTANGLE_NV) {
725 t->pp_txformat |= R200_TXFORMAT_NON_POWER2;
726 t->pp_txpitch = pitch_val;
727 t->pp_txpitch -= 32;
728 } else {
729 t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
730 R200_TXFORMAT_HEIGHT_MASK |
731 R200_TXFORMAT_CUBIC_MAP_ENABLE |
732 R200_TXFORMAT_F5_WIDTH_MASK |
733 R200_TXFORMAT_F5_HEIGHT_MASK);
734 t->pp_txformat |= ((texImage->WidthLog2 << R200_TXFORMAT_WIDTH_SHIFT) |
735 (texImage->HeightLog2 << R200_TXFORMAT_HEIGHT_SHIFT));
736 }
737
738 t->validated = GL_TRUE;
739 _mesa_unlock_texture(&radeon->glCtx, texObj);
740 return;
741 }
742
743
r200SetTexBuffer(__DRIcontext * pDRICtx,GLint target,__DRIdrawable * dPriv)744 void r200SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
745 {
746 r200SetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
747 }
748
749
750 #define REF_COLOR 1
751 #define REF_ALPHA 2
752
r200UpdateAllTexEnv(struct gl_context * ctx)753 static GLboolean r200UpdateAllTexEnv( struct gl_context *ctx )
754 {
755 r200ContextPtr rmesa = R200_CONTEXT(ctx);
756 GLint i, j, currslot;
757 GLint maxunitused = -1;
758 GLboolean texregfree[6] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
759 GLubyte stageref[7] = {0, 0, 0, 0, 0, 0, 0};
760 GLint nextunit[R200_MAX_TEXTURE_UNITS] = {0, 0, 0, 0, 0, 0};
761 GLint currentnext = -1;
762 GLboolean ok;
763
764 /* find highest used unit */
765 for ( j = 0; j < R200_MAX_TEXTURE_UNITS; j++) {
766 if (ctx->Texture.Unit[j]._Current) {
767 maxunitused = j;
768 }
769 }
770 stageref[maxunitused + 1] = REF_COLOR | REF_ALPHA;
771
772 for ( j = maxunitused; j >= 0; j-- ) {
773 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[j];
774
775 rmesa->state.texture.unit[j].outputreg = -1;
776
777 if (stageref[j + 1]) {
778
779 /* use the lowest available reg. That gets us automatically reg0 for the last stage.
780 need this even for disabled units, as it may get referenced due to the replace
781 optimization */
782 for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS; i++ ) {
783 if (texregfree[i]) {
784 rmesa->state.texture.unit[j].outputreg = i;
785 break;
786 }
787 }
788 if (rmesa->state.texture.unit[j].outputreg == -1) {
789 /* no more free regs we can use. Need a fallback :-( */
790 return GL_FALSE;
791 }
792
793 nextunit[j] = currentnext;
794
795 if (!texUnit->_Current) {
796 /* the not enabled stages are referenced "indirectly",
797 must not cut off the lower stages */
798 stageref[j] = REF_COLOR | REF_ALPHA;
799 continue;
800 }
801 currentnext = j;
802
803 const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
804 const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
805 const GLboolean isdot3rgba = (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ||
806 (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT);
807
808
809 /* check if we need the color part, special case for dot3_rgba
810 as if only the alpha part is referenced later on it still is using the color part */
811 if ((stageref[j + 1] & REF_COLOR) || isdot3rgba) {
812 for ( i = 0 ; i < numColorArgs ; i++ ) {
813 const GLuint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i];
814 const GLuint op = texUnit->_CurrentCombine->OperandRGB[i];
815 switch ( srcRGBi ) {
816 case GL_PREVIOUS:
817 /* op 0/1 are referencing color, op 2/3 alpha */
818 stageref[j] |= (op >> 1) + 1;
819 break;
820 case GL_TEXTURE:
821 texregfree[j] = GL_FALSE;
822 break;
823 case GL_TEXTURE0:
824 case GL_TEXTURE1:
825 case GL_TEXTURE2:
826 case GL_TEXTURE3:
827 case GL_TEXTURE4:
828 case GL_TEXTURE5:
829 texregfree[srcRGBi - GL_TEXTURE0] = GL_FALSE;
830 break;
831 default: /* don't care about other sources here */
832 break;
833 }
834 }
835 }
836
837 /* alpha args are ignored for dot3_rgba */
838 if ((stageref[j + 1] & REF_ALPHA) && !isdot3rgba) {
839
840 for ( i = 0 ; i < numAlphaArgs ; i++ ) {
841 const GLuint srcAi = texUnit->_CurrentCombine->SourceA[i];
842 switch ( srcAi ) {
843 case GL_PREVIOUS:
844 stageref[j] |= REF_ALPHA;
845 break;
846 case GL_TEXTURE:
847 texregfree[j] = GL_FALSE;
848 break;
849 case GL_TEXTURE0:
850 case GL_TEXTURE1:
851 case GL_TEXTURE2:
852 case GL_TEXTURE3:
853 case GL_TEXTURE4:
854 case GL_TEXTURE5:
855 texregfree[srcAi - GL_TEXTURE0] = GL_FALSE;
856 break;
857 default: /* don't care about other sources here */
858 break;
859 }
860 }
861 }
862 }
863 }
864
865 /* don't enable texture sampling for units if the result is not used */
866 for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) {
867 if (ctx->Texture.Unit[i]._Current && !texregfree[i])
868 rmesa->state.texture.unit[i].unitneeded = 1 << _mesa_tex_target_to_index(ctx, ctx->Texture.Unit[i]._Current->Target);
869 else rmesa->state.texture.unit[i].unitneeded = 0;
870 }
871
872 ok = GL_TRUE;
873 currslot = 0;
874 rmesa->state.envneeded = 1;
875
876 i = 0;
877 while ((i <= maxunitused) && (i >= 0)) {
878 /* only output instruction if the results are referenced */
879 if (ctx->Texture.Unit[i]._Current && stageref[i+1]) {
880 GLuint replaceunit = i;
881 /* try to optimize GL_REPLACE away (only one level deep though) */
882 if ( (ctx->Texture.Unit[i]._CurrentCombine->ModeRGB == GL_REPLACE) &&
883 (ctx->Texture.Unit[i]._CurrentCombine->ModeA == GL_REPLACE) &&
884 (ctx->Texture.Unit[i]._CurrentCombine->ScaleShiftRGB == 0) &&
885 (ctx->Texture.Unit[i]._CurrentCombine->ScaleShiftA == 0) &&
886 (nextunit[i] > 0) ) {
887 /* yippie! can optimize it away! */
888 replaceunit = i;
889 i = nextunit[i];
890 }
891
892 /* need env instruction slot */
893 rmesa->state.envneeded |= 1 << currslot;
894 ok = r200UpdateTextureEnv( ctx, i, currslot, replaceunit );
895 if (!ok) return GL_FALSE;
896 currslot++;
897 }
898 i = i + 1;
899 }
900
901 if (currslot == 0) {
902 /* need one stage at least */
903 rmesa->state.texture.unit[0].outputreg = 0;
904 ok = r200UpdateTextureEnv( ctx, 0, 0, 0 );
905 }
906
907 R200_STATECHANGE( rmesa, ctx );
908 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_BLEND_ENABLE_MASK | R200_MULTI_PASS_ENABLE);
909 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= rmesa->state.envneeded << R200_TEX_BLEND_0_ENABLE_SHIFT;
910
911 return ok;
912 }
913
914 #undef REF_COLOR
915 #undef REF_ALPHA
916
917
918 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
919 R200_MIN_FILTER_MASK | \
920 R200_MAG_FILTER_MASK | \
921 R200_MAX_ANISO_MASK | \
922 R200_YUV_TO_RGB | \
923 R200_YUV_TEMPERATURE_MASK | \
924 R200_CLAMP_S_MASK | \
925 R200_CLAMP_T_MASK | \
926 R200_BORDER_MODE_D3D )
927
928 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
929 R200_TXFORMAT_HEIGHT_MASK | \
930 R200_TXFORMAT_FORMAT_MASK | \
931 R200_TXFORMAT_F5_WIDTH_MASK | \
932 R200_TXFORMAT_F5_HEIGHT_MASK | \
933 R200_TXFORMAT_ALPHA_IN_MAP | \
934 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
935 R200_TXFORMAT_NON_POWER2)
936
937 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
938 R200_TEXCOORD_MASK | \
939 R200_MIN_MIP_LEVEL_MASK | \
940 R200_CLAMP_Q_MASK | \
941 R200_VOLUME_FILTER_MASK)
942
943
disable_tex_obj_state(r200ContextPtr rmesa,int unit)944 static void disable_tex_obj_state( r200ContextPtr rmesa,
945 int unit )
946 {
947
948 R200_STATECHANGE( rmesa, vtx );
949 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
950
951 R200_STATECHANGE( rmesa, ctx );
952 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_0_ENABLE << unit);
953 if (rmesa->radeon.TclFallback & (R200_TCL_FALLBACK_TEXGEN_0<<unit)) {
954 TCL_FALLBACK( &rmesa->radeon.glCtx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
955 }
956
957 /* Actually want to keep all units less than max active texture
958 * enabled, right? Fix this for >2 texunits.
959 */
960
961 {
962 GLuint tmp = rmesa->TexGenEnabled;
963
964 rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
965 rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
966 rmesa->TexGenNeedNormals[unit] = GL_FALSE;
967 rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
968
969 if (tmp != rmesa->TexGenEnabled) {
970 rmesa->recheck_texgen[unit] = GL_TRUE;
971 rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
972 }
973 }
974 }
import_tex_obj_state(r200ContextPtr rmesa,int unit,radeonTexObjPtr texobj)975 static void import_tex_obj_state( r200ContextPtr rmesa,
976 int unit,
977 radeonTexObjPtr texobj )
978 {
979 /* do not use RADEON_DB_STATE to avoid stale texture caches */
980 GLuint *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0];
981
982 R200_STATECHANGE( rmesa, tex[unit] );
983
984 cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
985 cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
986 cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
987 cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
988 cmd[TEX_PP_TXFORMAT_X] &= ~TEXOBJ_TXFORMAT_X_MASK;
989 cmd[TEX_PP_TXFORMAT_X] |= texobj->pp_txformat_x & TEXOBJ_TXFORMAT_X_MASK;
990 cmd[TEX_PP_TXSIZE] = texobj->pp_txsize; /* NPOT only! */
991 cmd[TEX_PP_TXPITCH] = texobj->pp_txpitch; /* NPOT only! */
992 cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
993
994 if (texobj->base.Target == GL_TEXTURE_CUBE_MAP) {
995 GLuint *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0];
996
997 R200_STATECHANGE( rmesa, cube[unit] );
998 cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
999 /* that value is submitted twice. could change cube atom
1000 to not include that command when new drm is used */
1001 cmd[TEX_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
1002 }
1003
1004 }
1005
set_texgen_matrix(r200ContextPtr rmesa,GLuint unit,const GLfloat * s_plane,const GLfloat * t_plane,const GLfloat * r_plane,const GLfloat * q_plane)1006 static void set_texgen_matrix( r200ContextPtr rmesa,
1007 GLuint unit,
1008 const GLfloat *s_plane,
1009 const GLfloat *t_plane,
1010 const GLfloat *r_plane,
1011 const GLfloat *q_plane )
1012 {
1013 GLfloat m[16];
1014
1015 m[0] = s_plane[0];
1016 m[4] = s_plane[1];
1017 m[8] = s_plane[2];
1018 m[12] = s_plane[3];
1019
1020 m[1] = t_plane[0];
1021 m[5] = t_plane[1];
1022 m[9] = t_plane[2];
1023 m[13] = t_plane[3];
1024
1025 m[2] = r_plane[0];
1026 m[6] = r_plane[1];
1027 m[10] = r_plane[2];
1028 m[14] = r_plane[3];
1029
1030 m[3] = q_plane[0];
1031 m[7] = q_plane[1];
1032 m[11] = q_plane[2];
1033 m[15] = q_plane[3];
1034
1035 _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m);
1036 _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) );
1037 rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;
1038 }
1039
1040
r200_need_dis_texgen(const GLbitfield texGenEnabled,const GLfloat * planeS,const GLfloat * planeT,const GLfloat * planeR,const GLfloat * planeQ)1041 static GLuint r200_need_dis_texgen(const GLbitfield texGenEnabled,
1042 const GLfloat *planeS,
1043 const GLfloat *planeT,
1044 const GLfloat *planeR,
1045 const GLfloat *planeQ)
1046 {
1047 GLuint needtgenable = 0;
1048
1049 if (!(texGenEnabled & S_BIT)) {
1050 if (((texGenEnabled & T_BIT) && planeT[0] != 0.0) ||
1051 ((texGenEnabled & R_BIT) && planeR[0] != 0.0) ||
1052 ((texGenEnabled & Q_BIT) && planeQ[0] != 0.0)) {
1053 needtgenable |= S_BIT;
1054 }
1055 }
1056 if (!(texGenEnabled & T_BIT)) {
1057 if (((texGenEnabled & S_BIT) && planeS[1] != 0.0) ||
1058 ((texGenEnabled & R_BIT) && planeR[1] != 0.0) ||
1059 ((texGenEnabled & Q_BIT) && planeQ[1] != 0.0)) {
1060 needtgenable |= T_BIT;
1061 }
1062 }
1063 if (!(texGenEnabled & R_BIT)) {
1064 if (((texGenEnabled & S_BIT) && planeS[2] != 0.0) ||
1065 ((texGenEnabled & T_BIT) && planeT[2] != 0.0) ||
1066 ((texGenEnabled & Q_BIT) && planeQ[2] != 0.0)) {
1067 needtgenable |= R_BIT;
1068 }
1069 }
1070 if (!(texGenEnabled & Q_BIT)) {
1071 if (((texGenEnabled & S_BIT) && planeS[3] != 0.0) ||
1072 ((texGenEnabled & T_BIT) && planeT[3] != 0.0) ||
1073 ((texGenEnabled & R_BIT) && planeR[3] != 0.0)) {
1074 needtgenable |= Q_BIT;
1075 }
1076 }
1077
1078 return needtgenable;
1079 }
1080
1081
1082 /*
1083 * Returns GL_FALSE if fallback required.
1084 */
r200_validate_texgen(struct gl_context * ctx,GLuint unit)1085 static GLboolean r200_validate_texgen( struct gl_context *ctx, GLuint unit )
1086 {
1087 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1088 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1089 GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4;
1090 GLuint tgi, tgcm;
1091 GLuint mode = 0;
1092 GLboolean mixed_fallback = GL_FALSE;
1093 static const GLfloat I[16] = {
1094 1, 0, 0, 0,
1095 0, 1, 0, 0,
1096 0, 0, 1, 0,
1097 0, 0, 0, 1 };
1098 static const GLfloat reflect[16] = {
1099 -1, 0, 0, 0,
1100 0, -1, 0, 0,
1101 0, 0, -1, 0,
1102 0, 0, 0, 1 };
1103
1104 rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
1105 rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
1106 rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
1107 rmesa->TexGenNeedNormals[unit] = GL_FALSE;
1108 tgi = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] & ~(R200_TEXGEN_INPUT_MASK <<
1109 inputshift);
1110 tgcm = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] & ~(R200_TEXGEN_COMP_MASK <<
1111 (unit * 4));
1112
1113 if (0)
1114 fprintf(stderr, "%s unit %d\n", __func__, unit);
1115
1116 if (texUnit->TexGenEnabled & S_BIT) {
1117 mode = texUnit->GenS.Mode;
1118 } else {
1119 tgcm |= R200_TEXGEN_COMP_S << (unit * 4);
1120 }
1121
1122 if (texUnit->TexGenEnabled & T_BIT) {
1123 if (texUnit->GenT.Mode != mode)
1124 mixed_fallback = GL_TRUE;
1125 } else {
1126 tgcm |= R200_TEXGEN_COMP_T << (unit * 4);
1127 }
1128 if (texUnit->TexGenEnabled & R_BIT) {
1129 if (texUnit->GenR.Mode != mode)
1130 mixed_fallback = GL_TRUE;
1131 } else {
1132 tgcm |= R200_TEXGEN_COMP_R << (unit * 4);
1133 }
1134
1135 if (texUnit->TexGenEnabled & Q_BIT) {
1136 if (texUnit->GenQ.Mode != mode)
1137 mixed_fallback = GL_TRUE;
1138 } else {
1139 tgcm |= R200_TEXGEN_COMP_Q << (unit * 4);
1140 }
1141
1142 if (mixed_fallback) {
1143 if (R200_DEBUG & RADEON_FALLBACKS)
1144 fprintf(stderr, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
1145 texUnit->TexGenEnabled, texUnit->GenS.Mode, texUnit->GenT.Mode,
1146 texUnit->GenR.Mode, texUnit->GenQ.Mode);
1147 return GL_FALSE;
1148 }
1149
1150 /* we CANNOT do mixed mode if the texgen mode requires a plane where the input
1151 is not enabled for texgen, since the planes are concatenated into texmat,
1152 and thus the input will come from texcoord rather than tex gen equation!
1153 Either fallback or just hope that those texcoords aren't really needed...
1154 Assuming the former will cause lots of unnecessary fallbacks, the latter will
1155 generate bogus results sometimes - it's pretty much impossible to really know
1156 when a fallback is needed, depends on texmat and what sort of texture is bound
1157 etc, - for now fallback if we're missing either S or T bits, there's a high
1158 probability we need the texcoords in that case.
1159 That's a lot of work for some obscure texgen mixed mode fixup - why oh why
1160 doesn't the chip just directly accept the plane parameters :-(. */
1161 switch (mode) {
1162 case GL_OBJECT_LINEAR: {
1163 GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled,
1164 texUnit->GenS.ObjectPlane,
1165 texUnit->GenT.ObjectPlane,
1166 texUnit->GenR.ObjectPlane,
1167 texUnit->GenQ.ObjectPlane );
1168 if (needtgenable & (S_BIT | T_BIT)) {
1169 if (R200_DEBUG & RADEON_FALLBACKS)
1170 fprintf(stderr, "fallback mixed texgen / obj plane, 0x%x\n",
1171 texUnit->TexGenEnabled);
1172 return GL_FALSE;
1173 }
1174 if (needtgenable & (R_BIT)) {
1175 tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4));
1176 }
1177 if (needtgenable & (Q_BIT)) {
1178 tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4));
1179 }
1180
1181 tgi |= R200_TEXGEN_INPUT_OBJ << inputshift;
1182 set_texgen_matrix( rmesa, unit,
1183 (texUnit->TexGenEnabled & S_BIT) ? texUnit->GenS.ObjectPlane : I,
1184 (texUnit->TexGenEnabled & T_BIT) ? texUnit->GenT.ObjectPlane : I + 4,
1185 (texUnit->TexGenEnabled & R_BIT) ? texUnit->GenR.ObjectPlane : I + 8,
1186 (texUnit->TexGenEnabled & Q_BIT) ? texUnit->GenQ.ObjectPlane : I + 12);
1187 }
1188 break;
1189
1190 case GL_EYE_LINEAR: {
1191 GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled,
1192 texUnit->GenS.EyePlane,
1193 texUnit->GenT.EyePlane,
1194 texUnit->GenR.EyePlane,
1195 texUnit->GenQ.EyePlane );
1196 if (needtgenable & (S_BIT | T_BIT)) {
1197 if (R200_DEBUG & RADEON_FALLBACKS)
1198 fprintf(stderr, "fallback mixed texgen / eye plane, 0x%x\n",
1199 texUnit->TexGenEnabled);
1200 return GL_FALSE;
1201 }
1202 if (needtgenable & (R_BIT)) {
1203 tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4));
1204 }
1205 if (needtgenable & (Q_BIT)) {
1206 tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4));
1207 }
1208 tgi |= R200_TEXGEN_INPUT_EYE << inputshift;
1209 set_texgen_matrix( rmesa, unit,
1210 (texUnit->TexGenEnabled & S_BIT) ? texUnit->GenS.EyePlane : I,
1211 (texUnit->TexGenEnabled & T_BIT) ? texUnit->GenT.EyePlane : I + 4,
1212 (texUnit->TexGenEnabled & R_BIT) ? texUnit->GenR.EyePlane : I + 8,
1213 (texUnit->TexGenEnabled & Q_BIT) ? texUnit->GenQ.EyePlane : I + 12);
1214 }
1215 break;
1216
1217 case GL_REFLECTION_MAP_NV:
1218 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1219 tgi |= R200_TEXGEN_INPUT_EYE_REFLECT << inputshift;
1220 /* pretty weird, must only negate when lighting is enabled? */
1221 if (ctx->Light.Enabled)
1222 set_texgen_matrix( rmesa, unit,
1223 (texUnit->TexGenEnabled & S_BIT) ? reflect : I,
1224 (texUnit->TexGenEnabled & T_BIT) ? reflect + 4 : I + 4,
1225 (texUnit->TexGenEnabled & R_BIT) ? reflect + 8 : I + 8,
1226 I + 12);
1227 break;
1228
1229 case GL_NORMAL_MAP_NV:
1230 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1231 tgi |= R200_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
1232 break;
1233
1234 case GL_SPHERE_MAP:
1235 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1236 tgi |= R200_TEXGEN_INPUT_SPHERE<<inputshift;
1237 break;
1238
1239 case 0:
1240 /* All texgen units were disabled, so just pass coords through. */
1241 tgi |= unit << inputshift;
1242 break;
1243
1244 default:
1245 /* Unsupported mode, fallback:
1246 */
1247 if (R200_DEBUG & RADEON_FALLBACKS)
1248 fprintf(stderr, "fallback unsupported texgen, %d\n",
1249 texUnit->GenS.Mode);
1250 return GL_FALSE;
1251 }
1252
1253 rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit;
1254 rmesa->TexGenCompSel |= R200_OUTPUT_TEX_0 << unit;
1255
1256 if (tgi != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] ||
1257 tgcm != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2])
1258 {
1259 R200_STATECHANGE(rmesa, tcg);
1260 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = tgi;
1261 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] = tgcm;
1262 }
1263
1264 return GL_TRUE;
1265 }
1266
set_re_cntl_d3d(struct gl_context * ctx,int unit,GLboolean use_d3d)1267 void set_re_cntl_d3d( struct gl_context *ctx, int unit, GLboolean use_d3d )
1268 {
1269 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1270
1271 GLuint re_cntl;
1272
1273 re_cntl = rmesa->hw.set.cmd[SET_RE_CNTL] & ~(R200_VTX_STQ0_D3D << (2 * unit));
1274 if (use_d3d)
1275 re_cntl |= R200_VTX_STQ0_D3D << (2 * unit);
1276
1277 if ( re_cntl != rmesa->hw.set.cmd[SET_RE_CNTL] ) {
1278 R200_STATECHANGE( rmesa, set );
1279 rmesa->hw.set.cmd[SET_RE_CNTL] = re_cntl;
1280 }
1281 }
1282
1283 /**
1284 * Compute the cached hardware register values for the given texture object.
1285 *
1286 * \param rmesa Context pointer
1287 * \param t the r300 texture object
1288 */
setup_hardware_state(r200ContextPtr rmesa,radeonTexObj * t)1289 static void setup_hardware_state(r200ContextPtr rmesa, radeonTexObj *t)
1290 {
1291 const struct gl_texture_image *firstImage = t->base.Image[0][t->minLod];
1292 GLint log2Width, log2Height, log2Depth, texelBytes;
1293 uint extra_size = 0;
1294
1295 if ( t->bo ) {
1296 return;
1297 }
1298
1299 log2Width = firstImage->WidthLog2;
1300 log2Height = firstImage->HeightLog2;
1301 log2Depth = firstImage->DepthLog2;
1302 texelBytes = _mesa_get_format_bytes(firstImage->TexFormat);
1303
1304 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
1305 "%s(%p, tex %p) log2(w %d, h %d, d %d), texelBytes %d. format %d\n",
1306 __func__, rmesa, t, log2Width, log2Height,
1307 log2Depth, texelBytes, firstImage->TexFormat);
1308
1309 if (!t->image_override) {
1310 if (VALID_FORMAT(firstImage->TexFormat)) {
1311 const struct tx_table *table = _mesa_little_endian() ? tx_table_le :
1312 tx_table_be;
1313
1314 t->pp_txformat &= ~(R200_TXFORMAT_FORMAT_MASK |
1315 R200_TXFORMAT_ALPHA_IN_MAP);
1316 t->pp_txfilter &= ~R200_YUV_TO_RGB;
1317
1318 t->pp_txformat |= table[ firstImage->TexFormat ].format;
1319 t->pp_txfilter |= table[ firstImage->TexFormat ].filter;
1320
1321
1322 } else {
1323 _mesa_problem(NULL, "unexpected texture format in %s",
1324 __func__);
1325 return;
1326 }
1327 }
1328
1329 t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK;
1330 t->pp_txfilter |= ((t->maxLod) << R200_MAX_MIP_LEVEL_SHIFT)
1331 & R200_MAX_MIP_LEVEL_MASK;
1332
1333 if ( t->pp_txfilter &
1334 (R200_MIN_FILTER_NEAREST_MIP_NEAREST
1335 | R200_MIN_FILTER_NEAREST_MIP_LINEAR
1336 | R200_MIN_FILTER_LINEAR_MIP_NEAREST
1337 | R200_MIN_FILTER_LINEAR_MIP_LINEAR
1338 | R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
1339 | R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR))
1340 extra_size = t->minLod;
1341
1342 t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
1343 R200_TXFORMAT_HEIGHT_MASK |
1344 R200_TXFORMAT_CUBIC_MAP_ENABLE |
1345 R200_TXFORMAT_F5_WIDTH_MASK |
1346 R200_TXFORMAT_F5_HEIGHT_MASK);
1347 t->pp_txformat |= (((log2Width + extra_size) << R200_TXFORMAT_WIDTH_SHIFT) |
1348 ((log2Height + extra_size)<< R200_TXFORMAT_HEIGHT_SHIFT));
1349
1350 t->tile_bits = 0;
1351
1352 t->pp_txformat_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK
1353 | R200_MIN_MIP_LEVEL_MASK);
1354
1355 t->pp_txformat_x |= (t->minLod << R200_MIN_MIP_LEVEL_SHIFT)
1356 & R200_MIN_MIP_LEVEL_MASK;
1357
1358 if (t->base.Target == GL_TEXTURE_3D) {
1359 t->pp_txformat_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT);
1360 t->pp_txformat_x |= R200_TEXCOORD_VOLUME;
1361
1362 }
1363 else if (t->base.Target == GL_TEXTURE_CUBE_MAP) {
1364 assert(log2Width == log2Height);
1365 t->pp_txformat |= ((log2Width << R200_TXFORMAT_F5_WIDTH_SHIFT) |
1366 (log2Height << R200_TXFORMAT_F5_HEIGHT_SHIFT) |
1367 /* don't think we need this bit, if it exists at all - fglrx does not set it */
1368 (R200_TXFORMAT_CUBIC_MAP_ENABLE));
1369 t->pp_txformat_x |= R200_TEXCOORD_CUBIC_ENV;
1370 t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) |
1371 (log2Height << R200_FACE_HEIGHT_1_SHIFT) |
1372 (log2Width << R200_FACE_WIDTH_2_SHIFT) |
1373 (log2Height << R200_FACE_HEIGHT_2_SHIFT) |
1374 (log2Width << R200_FACE_WIDTH_3_SHIFT) |
1375 (log2Height << R200_FACE_HEIGHT_3_SHIFT) |
1376 (log2Width << R200_FACE_WIDTH_4_SHIFT) |
1377 (log2Height << R200_FACE_HEIGHT_4_SHIFT));
1378 }
1379 else {
1380 /* If we don't in fact send enough texture coordinates, q will be 1,
1381 * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
1382 */
1383 t->pp_txformat_x |= R200_TEXCOORD_PROJ;
1384 }
1385 /* FIXME: NPOT sizes, is it correct really? */
1386 t->pp_txsize = (((firstImage->Width - 1) << R200_PP_TX_WIDTHMASK_SHIFT)
1387 | ((firstImage->Height - 1) << R200_PP_TX_HEIGHTMASK_SHIFT));
1388
1389 if ( !t->image_override ) {
1390 if (_mesa_is_format_compressed(firstImage->TexFormat))
1391 t->pp_txpitch = (firstImage->Width + 63) & ~(63);
1392 else
1393 t->pp_txpitch = ((firstImage->Width * texelBytes) + 63) & ~(63);
1394 t->pp_txpitch -= 32;
1395 }
1396
1397 if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) {
1398 t->pp_txformat |= R200_TXFORMAT_NON_POWER2;
1399 }
1400
1401 }
1402
r200_validate_texture(struct gl_context * ctx,struct gl_texture_object * texObj,int unit)1403 static GLboolean r200_validate_texture(struct gl_context *ctx, struct gl_texture_object *texObj, int unit)
1404 {
1405 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1406 radeonTexObj *t = radeon_tex_obj(texObj);
1407
1408 if (!radeon_validate_texture_miptree(ctx, _mesa_get_samplerobj(ctx, unit), texObj))
1409 return GL_FALSE;
1410
1411 r200_validate_texgen(ctx, unit);
1412 /* Configure the hardware registers (more precisely, the cached version
1413 * of the hardware registers). */
1414 setup_hardware_state(rmesa, t);
1415
1416 if (texObj->Target == GL_TEXTURE_RECTANGLE_NV ||
1417 texObj->Target == GL_TEXTURE_2D ||
1418 texObj->Target == GL_TEXTURE_1D)
1419 set_re_cntl_d3d( ctx, unit, GL_FALSE );
1420 else
1421 set_re_cntl_d3d( ctx, unit, GL_TRUE );
1422 R200_STATECHANGE( rmesa, ctx );
1423 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << unit;
1424
1425 R200_STATECHANGE( rmesa, vtx );
1426 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
1427 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3);
1428
1429 rmesa->recheck_texgen[unit] = GL_TRUE;
1430 r200TexUpdateParameters(ctx, unit);
1431 import_tex_obj_state( rmesa, unit, t );
1432
1433 if (rmesa->recheck_texgen[unit]) {
1434 GLboolean fallback = !r200_validate_texgen( ctx, unit );
1435 TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
1436 rmesa->recheck_texgen[unit] = 0;
1437 rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
1438 }
1439
1440 t->validated = GL_TRUE;
1441
1442 FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback );
1443
1444 return !t->border_fallback;
1445 }
1446
r200UpdateTextureUnit(struct gl_context * ctx,int unit)1447 static GLboolean r200UpdateTextureUnit(struct gl_context *ctx, int unit)
1448 {
1449 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1450 GLuint unitneeded = rmesa->state.texture.unit[unit].unitneeded;
1451
1452 if (!unitneeded) {
1453 /* disable the unit */
1454 disable_tex_obj_state(rmesa, unit);
1455 return GL_TRUE;
1456 }
1457
1458 if (!r200_validate_texture(ctx, ctx->Texture.Unit[unit]._Current, unit)) {
1459 _mesa_warning(ctx,
1460 "failed to validate texture for unit %d.\n",
1461 unit);
1462 rmesa->state.texture.unit[unit].texobj = NULL;
1463 return GL_FALSE;
1464 }
1465
1466 rmesa->state.texture.unit[unit].texobj = radeon_tex_obj(ctx->Texture.Unit[unit]._Current);
1467 return GL_TRUE;
1468 }
1469
1470
r200UpdateTextureState(struct gl_context * ctx)1471 void r200UpdateTextureState( struct gl_context *ctx )
1472 {
1473 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1474 GLboolean ok;
1475 GLuint dbg;
1476
1477 /* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or
1478 rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since
1479 we use these to determine if we want to emit the corresponding state
1480 atoms. */
1481 R200_NEWPRIM( rmesa );
1482
1483 if (ctx->ATIFragmentShader._Enabled) {
1484 GLuint i;
1485 for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) {
1486 if (ctx->Texture.Unit[i]._Current)
1487 rmesa->state.texture.unit[i].unitneeded = 1 << _mesa_tex_target_to_index(ctx, ctx->Texture.Unit[i]._Current->Target);
1488 else
1489 rmesa->state.texture.unit[i].unitneeded = 0;
1490 }
1491 ok = GL_TRUE;
1492 }
1493 else {
1494 ok = r200UpdateAllTexEnv( ctx );
1495 }
1496 if (ok) {
1497 ok = (r200UpdateTextureUnit( ctx, 0 ) &&
1498 r200UpdateTextureUnit( ctx, 1 ) &&
1499 r200UpdateTextureUnit( ctx, 2 ) &&
1500 r200UpdateTextureUnit( ctx, 3 ) &&
1501 r200UpdateTextureUnit( ctx, 4 ) &&
1502 r200UpdateTextureUnit( ctx, 5 ));
1503 }
1504
1505 if (ok && ctx->ATIFragmentShader._Enabled) {
1506 r200UpdateFragmentShader(ctx);
1507 }
1508
1509 FALLBACK( rmesa, R200_FALLBACK_TEXTURE, !ok );
1510
1511 if (rmesa->radeon.TclFallback)
1512 r200ChooseVertexState( ctx );
1513
1514
1515 if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200) {
1516
1517 /*
1518 * T0 hang workaround -------------
1519 * not needed for r200 derivatives
1520 */
1521 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_ENABLE_MASK) == R200_TEX_0_ENABLE &&
1522 (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) {
1523
1524 R200_STATECHANGE(rmesa, ctx);
1525 R200_STATECHANGE(rmesa, tex[1]);
1526 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE;
1527 if (!(rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_1_ENABLE))
1528 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1529 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= R200_TXFORMAT_LOOKUP_DISABLE;
1530 }
1531 else if (!ctx->ATIFragmentShader._Enabled) {
1532 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) &&
1533 (rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] & R200_TXFORMAT_LOOKUP_DISABLE)) {
1534 R200_STATECHANGE(rmesa, tex[1]);
1535 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~R200_TXFORMAT_LOOKUP_DISABLE;
1536 }
1537 }
1538 /* do the same workaround for the first pass of a fragment shader.
1539 * completely unknown if necessary / sufficient.
1540 */
1541 if ((rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_ENABLE_MASK) == R200_PPX_TEX_0_ENABLE &&
1542 (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) {
1543
1544 R200_STATECHANGE(rmesa, cst);
1545 R200_STATECHANGE(rmesa, tex[1]);
1546 rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_1_ENABLE;
1547 if (!(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE))
1548 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1549 rmesa->hw.tex[1].cmd[TEX_PP_TXMULTI_CTL] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE;
1550 }
1551
1552 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1553 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1554 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1555 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1556 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1557 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1558 R200_MIN_FILTER_LINEAR)) {
1559 R200_STATECHANGE(rmesa, ctx);
1560 R200_STATECHANGE(rmesa, tex[i+1]);
1561 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1562 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1563 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1564 }
1565 else {
1566 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1567 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1568 R200_STATECHANGE(rmesa, tex[i+1]);
1569 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1570 }
1571 }
1572 } */
1573
1574 /*
1575 * Texture cache LRU hang workaround -------------
1576 * not needed for r200 derivatives
1577 * hopefully this covers first pass of a shader as well
1578 */
1579
1580 /* While the cases below attempt to only enable the workaround in the
1581 * specific cases necessary, they were insufficient. See bugzilla #1519,
1582 * #729, #814. Tests with quake3 showed no impact on performance.
1583 */
1584 dbg = 0x6;
1585
1586 /*
1587 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1588 ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1589 0x04) == 0)) ||
1590 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1591 ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1592 0x04) == 0)) ||
1593 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1594 ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1595 0x04) == 0)))
1596 {
1597 dbg |= 0x02;
1598 }
1599
1600 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1601 ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1602 0x04) == 0)) ||
1603 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1604 ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1605 0x04) == 0)) ||
1606 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1607 ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1608 0x04) == 0)))
1609 {
1610 dbg |= 0x04;
1611 }*/
1612
1613 if (dbg != rmesa->hw.tam.cmd[TAM_DEBUG3]) {
1614 R200_STATECHANGE( rmesa, tam );
1615 rmesa->hw.tam.cmd[TAM_DEBUG3] = dbg;
1616 if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg);
1617 }
1618 }
1619 }
1620