1 /* -*- mode: c; c-basic-offset: 3 -*- */
3 * Copyright 2000 Gareth Hughes
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Gareth Hughes <gareth@valinux.com>
28 * Leif Delgass <ldelgass@retinalburn.net>
29 * José Fonseca <j_r_fonseca@yahoo.co.uk>
32 #include "main/glheader.h"
33 #include "main/imports.h"
34 #include "main/context.h"
35 #include "main/macros.h"
36 #include "main/texformat.h"
38 #include "mach64_context.h"
39 #include "mach64_ioctl.h"
40 #include "mach64_state.h"
41 #include "mach64_vb.h"
42 #include "mach64_tris.h"
43 #include "mach64_tex.h"
45 static void mach64SetTexImages( mach64ContextPtr mmesa
,
46 const struct gl_texture_object
*tObj
)
48 mach64TexObjPtr t
= (mach64TexObjPtr
) tObj
->DriverData
;
49 struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
55 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
)
56 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, tObj
);
58 switch (baseImage
->TexFormat
->MesaFormat
) {
59 case MESA_FORMAT_ARGB8888
:
60 t
->textureFormat
= MACH64_DATATYPE_ARGB8888
;
62 case MESA_FORMAT_ARGB4444
:
63 t
->textureFormat
= MACH64_DATATYPE_ARGB4444
;
65 case MESA_FORMAT_RGB565
:
66 t
->textureFormat
= MACH64_DATATYPE_RGB565
;
68 case MESA_FORMAT_ARGB1555
:
69 t
->textureFormat
= MACH64_DATATYPE_ARGB1555
;
71 case MESA_FORMAT_RGB332
:
72 t
->textureFormat
= MACH64_DATATYPE_RGB332
;
74 case MESA_FORMAT_RGB888
:
75 t
->textureFormat
= MACH64_DATATYPE_RGB8
;
78 t
->textureFormat
= MACH64_DATATYPE_CI8
;
80 case MESA_FORMAT_YCBCR
:
81 t
->textureFormat
= MACH64_DATATYPE_YVYU422
;
83 case MESA_FORMAT_YCBCR_REV
:
84 t
->textureFormat
= MACH64_DATATYPE_VYUY422
;
87 _mesa_problem(mmesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
90 totalSize
= ( baseImage
->Height
*
92 baseImage
->TexFormat
->TexelBytes
);
94 totalSize
= (totalSize
+ 31) & ~31;
96 t
->base
.totalSize
= totalSize
;
97 t
->base
.firstLevel
= tObj
->BaseLevel
;
98 t
->base
.lastLevel
= tObj
->BaseLevel
;
100 /* Set the texture format */
101 if ( ( baseImage
->_BaseFormat
== GL_RGBA
) ||
102 ( baseImage
->_BaseFormat
== GL_ALPHA
) ||
103 ( baseImage
->_BaseFormat
== GL_LUMINANCE_ALPHA
) ) {
109 t
->widthLog2
= baseImage
->WidthLog2
;
110 t
->heightLog2
= baseImage
->HeightLog2
;
111 t
->maxLog2
= baseImage
->MaxLog2
;
114 static void mach64UpdateTextureEnv( GLcontext
*ctx
, int unit
)
116 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
117 GLint source
= mmesa
->tmu_source
[unit
];
118 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
119 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
120 const GLenum format
= tObj
->Image
[0][tObj
->BaseLevel
]->_BaseFormat
;
121 GLuint s
= mmesa
->setup
.scale_3d_cntl
;
123 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
124 fprintf( stderr
, "%s( %p, %d )\n",
125 __FUNCTION__
, ctx
, unit
);
128 /* REPLACE MODULATE DECAL GL_BLEND
130 * ALPHA C = Cf C = Cf undef C = Cf
131 * A = At A = AfAt A = AfAt
133 * LUMINANCE C = Ct C = CfCt undef C = Cf(1-Ct)+CcCt
134 * A = Af A = Af A = Af
136 * LUMINANCE_ALPHA C = Ct C = CfCt undef C = Cf(1-Ct)+CcCt
137 * A = At A = AfAt A = AfAt
139 * INTENSITY C = Ct C = CfCt undef C = Cf(1-Ct)+CcCt
140 * A = At A = AfAt A = Af(1-At)+AcAt
142 * RGB C = Ct C = CfCt C = Ct C = Cf(1-Ct)+CcCt
143 * A = Af A = Af A = Af A = Af
145 * RGBA C = Ct C = CfCt C = Cf(1-At)+CtAt C = Cf(1-Ct)+CcCt
146 * A = At A = AfAt A = Af A = AfAt
151 s
&= ~MACH64_TEX_LIGHT_FCN_MASK
;
153 /* Set the texture environment state
154 * Need to verify these are working correctly, but the
155 * texenv Mesa demo seems to work.
157 switch ( texUnit
->EnvMode
) {
161 case GL_LUMINANCE_ALPHA
:
163 /* Not compliant - can't get At */
164 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
165 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
168 s
|= MACH64_TEX_LIGHT_FCN_REPLACE
;
174 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
175 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
179 /* These should be compliant */
180 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
182 case GL_LUMINANCE_ALPHA
:
184 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
185 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
188 /* Should fallback when blending enabled for complete compliance */
189 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
192 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
198 s
|= MACH64_TEX_LIGHT_FCN_ALPHA_DECAL
;
201 s
|= MACH64_TEX_LIGHT_FCN_REPLACE
;
204 case GL_LUMINANCE_ALPHA
:
205 /* undefined - disable texturing, pass fragment unmodified */
206 /* Also, pass fragment alpha instead of texture alpha */
207 s
&= ~MACH64_TEX_MAP_AEN
;
208 s
|= MACH64_TEXTURE_DISABLE
;
209 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
213 /* undefined - disable texturing, pass fragment unmodified */
214 s
|= MACH64_TEXTURE_DISABLE
;
215 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
218 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
222 /* GL_BLEND not supported by RagePRO, use software */
223 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
224 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
228 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
229 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
232 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
235 if ( mmesa
->setup
.scale_3d_cntl
!= s
) {
236 mmesa
->setup
.scale_3d_cntl
= s
;
237 mmesa
->dirty
|= MACH64_UPLOAD_SCALE_3D_CNTL
;
241 /* blend = 0, modulate = 1 - initialize to blend */
242 mmesa
->setup
.tex_cntl
&= ~MACH64_COMP_COMBINE_MODULATE
;
243 /* Set the texture composite function for multitexturing*/
244 switch ( texUnit
->EnvMode
) {
246 /* GL_BLEND not supported by RagePRO, use software */
247 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
248 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
251 /* Should fallback when blending enabled for complete compliance */
252 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
257 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
259 default: /* not supported by RagePRO */
260 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
261 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
268 case GL_LUMINANCE_ALPHA
:
270 /* undefined, disable compositing and pass fragment unmodified */
271 mmesa
->setup
.tex_cntl
&= ~MACH64_TEXTURE_COMPOSITE
;
273 default: /* not supported by RagePRO */
274 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
275 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
280 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
281 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
284 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
290 static void mach64UpdateTextureUnit( GLcontext
*ctx
, int unit
)
292 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
293 int source
= mmesa
->tmu_source
[unit
];
294 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
295 const struct gl_texture_object
*tObj
= ctx
->Texture
.Unit
[source
]._Current
;
296 mach64TexObjPtr t
= tObj
->DriverData
;
297 GLuint d
= mmesa
->setup
.dp_pix_width
;
298 GLuint s
= mmesa
->setup
.scale_3d_cntl
;
300 assert(unit
== 0 || unit
== 1); /* only two tex units */
302 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
303 fprintf( stderr
, "%s( %p, %d ) enabled=0x%x 0x%x\n",
304 __FUNCTION__
, ctx
, unit
, ctx
->Texture
.Unit
[0]._ReallyEnabled
,
305 ctx
->Texture
.Unit
[1]._ReallyEnabled
);
308 if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
310 assert(t
); /* should have driver tex data by now */
312 /* Fallback if there's a texture border */
313 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 ) {
314 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
318 /* Upload teximages */
319 if (t
->base
.dirty_images
[0]) {
320 mach64SetTexImages( mmesa
, tObj
);
321 mmesa
->dirty
|= (MACH64_UPLOAD_TEX0IMAGE
<< unit
);
324 /* Bind to the given texture unit */
325 mmesa
->CurrentTexObj
[unit
] = t
;
326 t
->base
.bound
|= (1 << unit
);
328 if ( t
->base
.memBlock
)
329 driUpdateTextureLRU( (driTextureObject
*) t
); /* XXX: should be locked! */
333 d
&= ~MACH64_SCALE_PIX_WIDTH_MASK
;
334 d
|= (t
->textureFormat
<< 28);
336 s
&= ~(MACH64_TEXTURE_DISABLE
|
337 MACH64_TEX_CACHE_SPLIT
|
338 MACH64_TEX_BLEND_FCN_MASK
|
341 if ( mmesa
->multitex
) {
342 s
|= MACH64_TEX_BLEND_FCN_TRILINEAR
| MACH64_TEX_CACHE_SPLIT
;
343 } else if ( t
->BilinearMin
) {
344 s
|= MACH64_TEX_BLEND_FCN_LINEAR
;
346 s
|= MACH64_TEX_BLEND_FCN_NEAREST
;
348 if ( t
->BilinearMag
) {
349 s
|= MACH64_BILINEAR_TEX_EN
;
351 s
&= ~MACH64_BILINEAR_TEX_EN
;
355 s
|= MACH64_TEX_MAP_AEN
;
358 mmesa
->setup
.tex_cntl
&= ~(MACH64_TEXTURE_CLAMP_S
|
359 MACH64_TEXTURE_CLAMP_T
|
360 MACH64_SECONDARY_STW
);
363 mmesa
->setup
.tex_cntl
|= MACH64_TEXTURE_CLAMP_S
;
366 mmesa
->setup
.tex_cntl
|= MACH64_TEXTURE_CLAMP_T
;
369 mmesa
->setup
.tex_size_pitch
|= ((t
->widthLog2
<< 0) |
371 (t
->heightLog2
<< 8));
374 /* Enable texture mapping mode */
375 s
&= ~MACH64_TEXTURE_DISABLE
;
377 d
&= ~MACH64_COMPOSITE_PIX_WIDTH_MASK
;
378 d
|= (t
->textureFormat
<< 4);
380 mmesa
->setup
.tex_cntl
&= ~(MACH64_COMP_ALPHA
|
381 MACH64_SEC_TEX_CLAMP_S
|
382 MACH64_SEC_TEX_CLAMP_T
);
383 mmesa
->setup
.tex_cntl
|= (MACH64_TEXTURE_COMPOSITE
|
384 MACH64_SECONDARY_STW
);
386 if ( t
->BilinearMin
) {
387 mmesa
->setup
.tex_cntl
|= MACH64_COMP_BLEND_BILINEAR
;
389 mmesa
->setup
.tex_cntl
&= ~MACH64_COMP_BLEND_BILINEAR
;
391 if ( t
->BilinearMag
) {
392 mmesa
->setup
.tex_cntl
|= MACH64_COMP_FILTER_BILINEAR
;
394 mmesa
->setup
.tex_cntl
&= ~MACH64_COMP_FILTER_BILINEAR
;
398 mmesa
->setup
.tex_cntl
|= MACH64_COMP_ALPHA
;
401 mmesa
->setup
.tex_cntl
|= MACH64_SEC_TEX_CLAMP_S
;
404 mmesa
->setup
.tex_cntl
|= MACH64_SEC_TEX_CLAMP_T
;
407 mmesa
->setup
.tex_size_pitch
|= ((t
->widthLog2
<< 16) |
409 (t
->heightLog2
<< 24));
412 if ( mmesa
->setup
.scale_3d_cntl
!= s
) {
413 mmesa
->setup
.scale_3d_cntl
= s
;
414 mmesa
->dirty
|= MACH64_UPLOAD_SCALE_3D_CNTL
;
417 if ( mmesa
->setup
.dp_pix_width
!= d
) {
418 mmesa
->setup
.dp_pix_width
= d
;
419 mmesa
->dirty
|= MACH64_UPLOAD_DP_PIX_WIDTH
;
422 else if (texUnit
->_ReallyEnabled
) {
423 /* 3D or cube map texture enabled - fallback */
424 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
427 /* texture unit disabled */
432 /* Update the hardware texture state */
433 void mach64UpdateTextureState( GLcontext
*ctx
)
435 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
437 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
438 fprintf( stderr
, "%s( %p ) en=0x%x 0x%x\n",
439 __FUNCTION__
, ctx
, ctx
->Texture
.Unit
[0]._ReallyEnabled
,
440 ctx
->Texture
.Unit
[1]._ReallyEnabled
);
443 /* Clear any texturing fallbacks */
444 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_FALSE
);
446 /* Unbind any currently bound textures */
447 if ( mmesa
->CurrentTexObj
[0] ) mmesa
->CurrentTexObj
[0]->base
.bound
= 0;
448 if ( mmesa
->CurrentTexObj
[1] ) mmesa
->CurrentTexObj
[1]->base
.bound
= 0;
449 mmesa
->CurrentTexObj
[0] = NULL
;
450 mmesa
->CurrentTexObj
[1] = NULL
;
452 /* Disable all texturing until it is known to be good */
453 mmesa
->setup
.scale_3d_cntl
|= MACH64_TEXTURE_DISABLE
;
454 mmesa
->setup
.scale_3d_cntl
&= ~MACH64_TEX_MAP_AEN
;
455 mmesa
->setup
.tex_cntl
&= ~MACH64_TEXTURE_COMPOSITE
;
457 mmesa
->setup
.tex_size_pitch
= 0x00000000;
459 mmesa
->tmu_source
[0] = 0;
460 mmesa
->tmu_source
[1] = 1;
463 if (ctx
->Texture
._EnabledUnits
& 0x2) {
465 if (ctx
->Texture
._EnabledUnits
& 0x1) {
466 /* units 0 and 1 enabled */
468 mach64UpdateTextureUnit( ctx
, 0 );
469 mach64UpdateTextureEnv( ctx
, 0 );
470 mach64UpdateTextureUnit( ctx
, 1 );
471 mach64UpdateTextureEnv( ctx
, 1 );
473 mmesa
->tmu_source
[0] = 1;
474 mmesa
->tmu_source
[1] = 0;
475 mach64UpdateTextureUnit( ctx
, 0 );
476 mach64UpdateTextureEnv( ctx
, 0 );
478 } else if (ctx
->Texture
._EnabledUnits
& 0x1) {
479 /* only unit 0 enabled */
480 mach64UpdateTextureUnit( ctx
, 0 );
481 mach64UpdateTextureEnv( ctx
, 0 );
484 mmesa
->dirty
|= (MACH64_UPLOAD_SCALE_3D_CNTL
|
485 MACH64_UPLOAD_TEXTURE
);
489 /* Due to the way we must program texture state into the Rage Pro,
490 * we must leave these calculations to the absolute last minute.
492 void mach64EmitTexStateLocked( mach64ContextPtr mmesa
,
496 drm_mach64_sarea_t
*sarea
= mmesa
->sarea
;
497 drm_mach64_context_regs_t
*regs
= &(mmesa
->setup
);
499 /* for multitex, both textures must be local or AGP */
501 assert(t0
->heap
== t1
->heap
);
504 if (t0
->heap
== MACH64_CARD_HEAP
) {
505 #if ENABLE_PERF_BOXES
506 mmesa
->c_texsrc_card
++;
508 mmesa
->setup
.tex_cntl
&= ~MACH64_TEX_SRC_AGP
;
510 #if ENABLE_PERF_BOXES
511 mmesa
->c_texsrc_agp
++;
513 mmesa
->setup
.tex_cntl
|= MACH64_TEX_SRC_AGP
;
515 mmesa
->setup
.tex_offset
= t0
->bufAddr
;
519 mmesa
->setup
.secondary_tex_off
= t1
->bufAddr
;
522 memcpy( &sarea
->context_state
.tex_size_pitch
, ®s
->tex_size_pitch
,
523 MACH64_NR_TEXTURE_REGS
* sizeof(GLuint
) );