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