1 /**************************************************************************
3 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Gareth Hughes <gareth@valinux.com>
31 * Kevin E. Martin <martin@valinux.com>
32 * Brian Paul <brianp@valinux.com>
35 #include "main/glheader.h"
36 #include "main/imports.h"
37 #include "main/context.h"
38 #include "main/macros.h"
40 #include "r128_context.h"
41 #include "r128_ioctl.h"
42 #include "r128_tris.h"
46 static void r128SetTexImages( r128ContextPtr rmesa
,
47 const struct gl_texture_object
*tObj
)
49 r128TexObjPtr t
= (r128TexObjPtr
) tObj
->DriverData
;
50 struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
51 int log2Pitch
, log2Height
, log2Size
, log2MinSize
;
54 GLint firstLevel
, lastLevel
;
59 if ( R128_DEBUG
& DEBUG_VERBOSE_API
)
60 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *) tObj
);
62 switch (baseImage
->TexFormat
) {
63 case MESA_FORMAT_ARGB8888
:
64 case MESA_FORMAT_ARGB8888_REV
:
65 t
->textureFormat
= R128_DATATYPE_ARGB8888
;
67 case MESA_FORMAT_ARGB4444
:
68 case MESA_FORMAT_ARGB4444_REV
:
69 t
->textureFormat
= R128_DATATYPE_ARGB4444
;
71 case MESA_FORMAT_RGB565
:
72 case MESA_FORMAT_RGB565_REV
:
73 t
->textureFormat
= R128_DATATYPE_RGB565
;
75 case MESA_FORMAT_RGB332
:
76 t
->textureFormat
= R128_DATATYPE_RGB8
;
79 t
->textureFormat
= R128_DATATYPE_CI8
;
81 case MESA_FORMAT_YCBCR
:
82 t
->textureFormat
= R128_DATATYPE_YVYU422
;
84 case MESA_FORMAT_YCBCR_REV
:
85 t
->textureFormat
= R128_DATATYPE_VYUY422
;
88 _mesa_problem(rmesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
91 /* Compute which mipmap levels we really want to send to the hardware.
94 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
95 firstLevel
= t
->base
.firstLevel
;
96 lastLevel
= t
->base
.lastLevel
;
98 log2Pitch
= tObj
->Image
[0][firstLevel
]->WidthLog2
;
99 log2Height
= tObj
->Image
[0][firstLevel
]->HeightLog2
;
100 log2Size
= MAX2(log2Pitch
, log2Height
);
101 log2MinSize
= log2Size
;
103 t
->base
.dirty_images
[0] = 0;
105 for ( i
= firstLevel
; i
<= lastLevel
; i
++ ) {
106 const struct gl_texture_image
*texImage
;
108 texImage
= tObj
->Image
[0][i
];
109 if ( !texImage
|| !texImage
->Data
) {
114 log2MinSize
= texImage
->MaxLog2
;
116 t
->image
[i
- firstLevel
].offset
= totalSize
;
117 t
->image
[i
- firstLevel
].width
= tObj
->Image
[0][i
]->Width
;
118 t
->image
[i
- firstLevel
].height
= tObj
->Image
[0][i
]->Height
;
120 t
->base
.dirty_images
[0] |= (1 << i
);
122 totalSize
+= (tObj
->Image
[0][i
]->Height
*
123 tObj
->Image
[0][i
]->Width
*
124 _mesa_get_format_bytes(tObj
->Image
[0][i
]->TexFormat
));
126 /* Offsets must be 32-byte aligned for host data blits and tiling */
127 totalSize
= (totalSize
+ 31) & ~31;
130 t
->base
.totalSize
= totalSize
;
131 t
->base
.firstLevel
= firstLevel
;
132 t
->base
.lastLevel
= lastLevel
;
134 /* Set the texture format */
135 t
->setup
.tex_cntl
&= ~(0xf << 16);
136 t
->setup
.tex_cntl
|= t
->textureFormat
;
138 t
->setup
.tex_combine_cntl
= 0x00000000; /* XXX is this right? */
140 t
->setup
.tex_size_pitch
= ((log2Pitch
<< R128_TEX_PITCH_SHIFT
) |
141 (log2Size
<< R128_TEX_SIZE_SHIFT
) |
142 (log2Height
<< R128_TEX_HEIGHT_SHIFT
) |
143 (log2MinSize
<< R128_TEX_MIN_SIZE_SHIFT
));
145 for ( i
= 0 ; i
< R128_MAX_TEXTURE_LEVELS
; i
++ ) {
146 t
->setup
.tex_offset
[i
] = 0x00000000;
149 if (firstLevel
== lastLevel
)
150 t
->setup
.tex_cntl
|= R128_MIP_MAP_DISABLE
;
152 t
->setup
.tex_cntl
&= ~R128_MIP_MAP_DISABLE
;
154 /* FYI: r128UploadTexImages( rmesa, t ); used to be called here */
158 /* ================================================================
159 * Texture combine functions
162 #define COLOR_COMB_DISABLE (R128_COMB_DIS | \
163 R128_COLOR_FACTOR_TEX)
164 #define COLOR_COMB_COPY_INPUT (R128_COMB_COPY_INP | \
165 R128_COLOR_FACTOR_TEX)
166 #define COLOR_COMB_MODULATE (R128_COMB_MODULATE | \
167 R128_COLOR_FACTOR_TEX)
168 #define COLOR_COMB_MODULATE_NTEX (R128_COMB_MODULATE | \
169 R128_COLOR_FACTOR_NTEX)
170 #define COLOR_COMB_ADD (R128_COMB_ADD | \
171 R128_COLOR_FACTOR_TEX)
172 #define COLOR_COMB_BLEND_TEX (R128_COMB_BLEND_TEXTURE | \
173 R128_COLOR_FACTOR_TEX)
174 /* Rage 128 Pro/M3 only! */
175 #define COLOR_COMB_BLEND_COLOR (R128_COMB_MODULATE2X | \
176 R128_COMB_FCN_MSB | \
177 R128_COLOR_FACTOR_CONST_COLOR)
179 #define ALPHA_COMB_DISABLE (R128_COMB_ALPHA_DIS | \
180 R128_ALPHA_FACTOR_TEX_ALPHA)
181 #define ALPHA_COMB_COPY_INPUT (R128_COMB_ALPHA_COPY_INP | \
182 R128_ALPHA_FACTOR_TEX_ALPHA)
183 #define ALPHA_COMB_MODULATE (R128_COMB_ALPHA_MODULATE | \
184 R128_ALPHA_FACTOR_TEX_ALPHA)
185 #define ALPHA_COMB_MODULATE_NTEX (R128_COMB_ALPHA_MODULATE | \
186 R128_ALPHA_FACTOR_NTEX_ALPHA)
187 #define ALPHA_COMB_ADD (R128_COMB_ALPHA_ADD | \
188 R128_ALPHA_FACTOR_TEX_ALPHA)
190 #define INPUT_INTERP (R128_INPUT_FACTOR_INT_COLOR | \
191 R128_INP_FACTOR_A_INT_ALPHA)
192 #define INPUT_PREVIOUS (R128_INPUT_FACTOR_PREV_COLOR | \
193 R128_INP_FACTOR_A_PREV_ALPHA)
195 static GLboolean
r128UpdateTextureEnv( GLcontext
*ctx
, int unit
)
197 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
198 GLint source
= rmesa
->tmu_source
[unit
];
199 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
200 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
201 const GLenum format
= tObj
->Image
[0][tObj
->BaseLevel
]->_BaseFormat
;
204 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
205 fprintf( stderr
, "%s( %p, %d )\n",
206 __FUNCTION__
, (void *) ctx
, unit
);
210 combine
= INPUT_INTERP
;
212 combine
= INPUT_PREVIOUS
;
215 /* Set the texture environment state */
216 switch ( texUnit
->EnvMode
) {
220 case GL_LUMINANCE_ALPHA
:
222 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
223 ALPHA_COMB_DISABLE
); /* A = At */
227 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
228 ALPHA_COMB_COPY_INPUT
); /* A = Af */
231 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
232 ALPHA_COMB_DISABLE
); /* A = At */
243 case GL_LUMINANCE_ALPHA
:
245 combine
|= (COLOR_COMB_MODULATE
| /* C = CfCt */
246 ALPHA_COMB_MODULATE
); /* A = AfAt */
250 combine
|= (COLOR_COMB_MODULATE
| /* C = CfCt */
251 ALPHA_COMB_COPY_INPUT
); /* A = Af */
254 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
255 ALPHA_COMB_MODULATE
); /* A = AfAt */
266 combine
|= (COLOR_COMB_BLEND_TEX
| /* C = Cf(1-At)+CtAt */
267 ALPHA_COMB_COPY_INPUT
); /* A = Af */
270 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
271 ALPHA_COMB_COPY_INPUT
); /* A = Af */
275 case GL_LUMINANCE_ALPHA
:
277 /* Undefined behaviour - just copy the incoming fragment */
278 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = undefined */
279 ALPHA_COMB_COPY_INPUT
); /* A = undefined */
288 /* Rage 128 Pro and M3 can handle GL_BLEND texturing.
290 if ( !R128_IS_PLAIN( rmesa
) ) {
291 /* XXX this hasn't been fully tested, I don't have a Pro card. -BP */
294 case GL_LUMINANCE_ALPHA
:
295 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-Ct)+CcCt */
296 ALPHA_COMB_MODULATE
); /* A = AfAt */
301 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-Ct)+CcCt */
302 ALPHA_COMB_COPY_INPUT
); /* A = Af */
306 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
307 ALPHA_COMB_MODULATE
); /* A = AfAt */
311 /* GH: We could be smarter about this... */
312 switch ( rmesa
->env_color
& 0xff000000 ) {
314 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-It)+CcIt */
315 ALPHA_COMB_MODULATE_NTEX
); /* A = Af(1-It) */
317 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
318 ALPHA_COMB_MODULATE
); /* A = fallback */
330 /* Rage 128 has to fake some cases of GL_BLEND, otherwise fallback
331 * to software rendering.
333 if ( rmesa
->blend_flags
) {
338 case GL_LUMINANCE_ALPHA
:
339 switch ( rmesa
->env_color
& 0x00ffffff ) {
341 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
342 ALPHA_COMB_MODULATE
); /* A = AfAt */
345 /* This isn't right - BP */
348 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
349 ALPHA_COMB_MODULATE
); /* A = AfAt */
351 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
352 ALPHA_COMB_COPY_INPUT
); /* A = Af */
357 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
358 ALPHA_COMB_MODULATE
); /* A = fallback */
364 switch ( rmesa
->env_color
& 0x00ffffff ) {
366 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
367 ALPHA_COMB_COPY_INPUT
); /* A = Af */
370 /* This isn't right - BP */
373 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
374 ALPHA_COMB_COPY_INPUT
); /* A = Af */
376 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
377 ALPHA_COMB_COPY_INPUT
); /* A = Af */
382 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
383 ALPHA_COMB_COPY_INPUT
); /* A = fallback */
389 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
390 ALPHA_COMB_MODULATE
); /* A = AfAt */
392 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
393 ALPHA_COMB_COPY_INPUT
); /* A = Af */
397 switch ( rmesa
->env_color
& 0x00ffffff ) {
399 combine
|= COLOR_COMB_MODULATE_NTEX
; /* C = Cf(1-It) */
402 /* This isn't right - BP */
405 combine
|= COLOR_COMB_MODULATE_NTEX
; /* C = Cf(1-It) */
407 combine
|= COLOR_COMB_ADD
; /* C = Cf+It */
412 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
413 ALPHA_COMB_MODULATE
); /* A = fallback */
416 switch ( rmesa
->env_color
& 0xff000000 ) {
418 combine
|= ALPHA_COMB_MODULATE_NTEX
; /* A = Af(1-It) */
421 /* This isn't right - BP */
424 combine
|= ALPHA_COMB_MODULATE_NTEX
; /* A = Af(1-It) */
426 combine
|= ALPHA_COMB_ADD
; /* A = Af+It */
431 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
432 ALPHA_COMB_MODULATE
); /* A = fallback */
445 case GL_LUMINANCE_ALPHA
:
446 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
447 ALPHA_COMB_MODULATE
); /* A = AfAt */
451 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
452 ALPHA_COMB_COPY_INPUT
); /* A = Af */
455 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
456 ALPHA_COMB_MODULATE
); /* A = AfAt */
459 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
460 ALPHA_COMB_ADD
); /* A = Af+At */
472 if ( rmesa
->tex_combine
[unit
] != combine
) {
473 rmesa
->tex_combine
[unit
] = combine
;
474 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
479 static void disable_tex( GLcontext
*ctx
, int unit
)
481 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
483 FLUSH_BATCH( rmesa
);
485 if ( rmesa
->CurrentTexObj
[unit
] ) {
486 rmesa
->CurrentTexObj
[unit
]->base
.bound
&= ~(1 << unit
);
487 rmesa
->CurrentTexObj
[unit
] = NULL
;
490 rmesa
->setup
.tex_cntl_c
&= ~(R128_TEXMAP_ENABLE
<< unit
);
491 rmesa
->setup
.tex_size_pitch_c
&= ~(R128_TEX_SIZE_PITCH_MASK
<<
492 (R128_SEC_TEX_SIZE_PITCH_SHIFT
* unit
));
493 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
495 /* If either texture unit is disabled, then multitexturing is not
499 rmesa
->blend_flags
&= ~R128_BLEND_MULTITEX
;
502 static GLboolean
enable_tex_2d( GLcontext
*ctx
, int unit
)
504 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
505 const int source
= rmesa
->tmu_source
[unit
];
506 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
507 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
508 r128TexObjPtr t
= (r128TexObjPtr
) tObj
->DriverData
;
510 /* Need to load the 2d images associated with this unit.
512 if ( t
->base
.dirty_images
[0] ) {
513 /* FIXME: For Radeon, RADEON_FIREVERTICES is called here. Should
514 * FIXME: something similar be done for R128?
516 /* FLUSH_BATCH( rmesa ); */
518 r128SetTexImages( rmesa
, tObj
);
519 r128UploadTexImages( rmesa
, t
);
520 if ( !t
->base
.memBlock
)
527 static GLboolean
update_tex_common( GLcontext
*ctx
, int unit
)
529 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
530 const int source
= rmesa
->tmu_source
[unit
];
531 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
532 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
533 r128TexObjPtr t
= (r128TexObjPtr
) tObj
->DriverData
;
536 /* Fallback if there's a texture border */
537 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 ) {
542 /* Update state if this is a different texture object to last
545 if ( rmesa
->CurrentTexObj
[unit
] != t
) {
546 if ( rmesa
->CurrentTexObj
[unit
] != NULL
) {
547 /* The old texture is no longer bound to this texture unit.
551 rmesa
->CurrentTexObj
[unit
]->base
.bound
&=
555 rmesa
->CurrentTexObj
[unit
] = t
;
556 t
->base
.bound
|= (1UL << unit
);
557 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
559 driUpdateTextureLRU( (driTextureObject
*) t
); /* XXX: should be locked! */
562 /* FIXME: We need to update the texture unit if any texture parameters have
563 * changed, but this texture was already bound. This could be changed to
564 * work like the Radeon driver where the texture object has it's own
567 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
570 rmesa
->setup
.tex_size_pitch_c
&= ~(R128_TEX_SIZE_PITCH_MASK
<<
571 (R128_SEC_TEX_SIZE_PITCH_SHIFT
* unit
));
574 rmesa
->setup
.tex_cntl_c
|= R128_TEXMAP_ENABLE
;
575 rmesa
->setup
.tex_size_pitch_c
|= t
->setup
.tex_size_pitch
<< 0;
576 rmesa
->setup
.scale_3d_cntl
&= ~R128_TEX_CACHE_SPLIT
;
577 t
->setup
.tex_cntl
&= ~R128_SEC_SELECT_SEC_ST
;
580 rmesa
->setup
.tex_cntl_c
|= R128_SEC_TEXMAP_ENABLE
;
581 rmesa
->setup
.tex_size_pitch_c
|= t
->setup
.tex_size_pitch
<< 16;
582 rmesa
->setup
.scale_3d_cntl
|= R128_TEX_CACHE_SPLIT
;
583 t
->setup
.tex_cntl
|= R128_SEC_SELECT_SEC_ST
;
585 /* If the second TMU is enabled, then multitexturing is happening.
587 if ( R128_IS_PLAIN( rmesa
) )
588 rmesa
->blend_flags
|= R128_BLEND_MULTITEX
;
591 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
594 /* FIXME: The Radeon has some cached state so that it can avoid calling
595 * FIXME: UpdateTextureEnv in some cases. Is that possible here?
597 return r128UpdateTextureEnv( ctx
, unit
);
600 static GLboolean
updateTextureUnit( GLcontext
*ctx
, int unit
)
602 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
603 const int source
= rmesa
->tmu_source
[unit
];
604 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
607 if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
608 return (enable_tex_2d( ctx
, unit
) &&
609 update_tex_common( ctx
, unit
));
611 else if ( texUnit
->_ReallyEnabled
) {
615 disable_tex( ctx
, unit
);
621 void r128UpdateTextureState( GLcontext
*ctx
)
623 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
627 /* This works around a quirk with the R128 hardware. If only OpenGL
628 * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used. The
629 * hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
632 rmesa
->tmu_source
[0] = 0;
633 rmesa
->tmu_source
[1] = 1;
635 if ((ctx
->Texture
._EnabledUnits
& 0x03) == 0x02) {
636 /* only texture 1 enabled */
637 rmesa
->tmu_source
[0] = 1;
638 rmesa
->tmu_source
[1] = 0;
641 ok
= (updateTextureUnit( ctx
, 0 ) &&
642 updateTextureUnit( ctx
, 1 ));
644 FALLBACK( rmesa
, R128_FALLBACK_TEXTURE
, !ok
);