2 * Copyright 2000-2001 VA Linux Systems, Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
25 * Keith Whitwell <keith@tungstengraphics.com>
27 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatex.c,v 1.14 2002/10/30 12:51:36 alanh Exp $ */
31 #include "mgacontext.h"
40 #include "simple_list.h"
43 #include "texformat.h"
47 #include "swrast/swrast.h"
50 * Set the texture wrap modes.
51 * Currently \c GL_REPEAT, \c GL_CLAMP and \c GL_CLAMP_TO_EDGE are supported.
53 * \param t Texture object whose wrap modes are to be set
54 * \param swrap Wrap mode for the \a s texture coordinate
55 * \param twrap Wrap mode for the \a t texture coordinate
59 mgaSetTexWrapping( mgaTextureObjectPtr t
, GLenum swrap
, GLenum twrap
)
61 GLboolean is_clamp
= GL_FALSE
;
62 GLboolean is_clamp_to_edge
= GL_FALSE
;
64 t
->setup
.texctl
&= (TMC_clampu_MASK
& TMC_clampv_MASK
);
65 t
->setup
.texctl2
&= (TMC_borderen_MASK
);
71 t
->setup
.texctl
|= TMC_clampu_enable
;
74 case GL_CLAMP_TO_EDGE
:
75 t
->setup
.texctl
|= TMC_clampu_enable
;
76 is_clamp_to_edge
= GL_TRUE
;
79 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
86 t
->setup
.texctl
|= TMC_clampv_enable
;
89 case GL_CLAMP_TO_EDGE
:
90 t
->setup
.texctl
|= TMC_clampv_enable
;
91 is_clamp_to_edge
= GL_TRUE
;
94 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
98 t
->setup
.texctl2
|= TMC_borderen_enable
;
101 t
->border_fallback
= (is_clamp
&& is_clamp_to_edge
);
106 * Set the texture magnification and minification modes.
108 * \param t Texture whose filter modes are to be set
109 * \param minf Texture minification mode
110 * \param magf Texture magnification mode
114 mgaSetTexFilter( mgaTextureObjectPtr t
, GLenum minf
, GLenum magf
)
119 case GL_NEAREST
: val
= TF_minfilter_nrst
; break;
120 case GL_LINEAR
: val
= TF_minfilter_bilin
; break;
121 case GL_NEAREST_MIPMAP_NEAREST
: val
= TF_minfilter_mm1s
; break;
122 case GL_LINEAR_MIPMAP_NEAREST
: val
= TF_minfilter_mm4s
; break;
123 case GL_NEAREST_MIPMAP_LINEAR
: val
= TF_minfilter_mm2s
; break;
124 case GL_LINEAR_MIPMAP_LINEAR
: val
= TF_minfilter_mm8s
; break;
125 default: val
= TF_minfilter_nrst
; break;
129 case GL_NEAREST
: val
|= TF_magfilter_nrst
; break;
130 case GL_LINEAR
: val
|= TF_magfilter_bilin
; break;
131 default: val
|= TF_magfilter_nrst
; break;
134 /* See OpenGL 1.2 specification */
135 if (magf
== GL_LINEAR
&& (minf
== GL_NEAREST_MIPMAP_NEAREST
||
136 minf
== GL_NEAREST_MIPMAP_LINEAR
)) {
137 val
|= (0x20 << TF_fthres_SHIFT
); /* c = 0.5 */
139 val
|= (0x10 << TF_fthres_SHIFT
); /* c = 0 */
143 /* Mask off the bits for the fields we are setting. Remember, the MGA mask
144 * defines have 0s for the bits in the named fields. This is the opposite
145 * of most of the other drivers.
148 t
->setup
.texfilter
&= (TF_minfilter_MASK
&
151 t
->setup
.texfilter
|= val
;
154 static void mgaSetTexBorderColor(mgaTextureObjectPtr t
, GLubyte color
[4])
156 t
->setup
.texbordercol
= PACK_COLOR_8888(color
[3], color
[0],
157 color
[1], color
[2] );
161 static const struct gl_texture_format
*
162 mgaChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
163 GLenum format
, GLenum type
)
165 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
166 const GLboolean do32bpt
= mmesa
->default32BitTextures
;
168 switch ( internalFormat
) {
171 case GL_COMPRESSED_RGBA
:
172 if ( format
== GL_BGRA
) {
173 if ( type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
174 return &_mesa_texformat_argb8888
;
176 else if ( type
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
177 return &_mesa_texformat_argb4444
;
179 else if ( type
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
180 return &_mesa_texformat_argb1555
;
183 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
187 case GL_COMPRESSED_RGB
:
188 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
189 return &_mesa_texformat_rgb565
;
191 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
197 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
201 return &_mesa_texformat_argb4444
;
204 return &_mesa_texformat_argb1555
;
210 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
215 return &_mesa_texformat_rgb565
;
222 case GL_COMPRESSED_ALPHA
:
223 /* FIXME: This will report incorrect component sizes... */
224 return &_mesa_texformat_argb4444
;
232 case GL_COMPRESSED_LUMINANCE
:
233 /* FIXME: This will report incorrect component sizes... */
234 return &_mesa_texformat_rgb565
;
237 case GL_LUMINANCE_ALPHA
:
238 case GL_LUMINANCE4_ALPHA4
:
239 case GL_LUMINANCE6_ALPHA2
:
240 case GL_LUMINANCE8_ALPHA8
:
241 case GL_LUMINANCE12_ALPHA4
:
242 case GL_LUMINANCE12_ALPHA12
:
243 case GL_LUMINANCE16_ALPHA16
:
244 case GL_COMPRESSED_LUMINANCE_ALPHA
:
245 /* FIXME: This will report incorrect component sizes... */
246 return &_mesa_texformat_argb4444
;
253 case GL_COMPRESSED_INTENSITY
:
254 /* FIXME: This will report incorrect component sizes... */
255 return &_mesa_texformat_argb4444
;
258 if (MGA_IS_G400(mmesa
) &&
259 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
260 type
== GL_UNSIGNED_BYTE
))
261 return &_mesa_texformat_ycbcr
;
263 return &_mesa_texformat_ycbcr_rev
;
266 case GL_COLOR_INDEX1_EXT
:
267 case GL_COLOR_INDEX2_EXT
:
268 case GL_COLOR_INDEX4_EXT
:
269 case GL_COLOR_INDEX8_EXT
:
270 case GL_COLOR_INDEX12_EXT
:
271 case GL_COLOR_INDEX16_EXT
:
272 return &_mesa_texformat_ci8
;
275 _mesa_problem( ctx
, "unexpected texture format in %s", __FUNCTION__
);
279 return NULL
; /* never get here */
286 * Allocate space for and load the mesa images into the texture memory block.
287 * This will happen before drawing with a new texture, or drawing with a
288 * texture after it was swapped out or teximaged again.
291 static mgaTextureObjectPtr
292 mgaAllocTexObj( struct gl_texture_object
*tObj
)
294 mgaTextureObjectPtr t
;
297 t
= CALLOC( sizeof( *t
) );
298 tObj
->DriverData
= t
;
300 /* Initialize non-image-dependent parts of the state:
304 t
->setup
.texctl
= TMC_takey_1
| TMC_tamask_0
;
305 t
->setup
.texctl2
= TMC_ckstransdis_enable
;
306 t
->setup
.texfilter
= (TF_minfilter_nrst
308 | TF_filteralpha_enable
311 t
->border_fallback
= GL_FALSE
;
313 make_empty_list( & t
->base
);
315 mgaSetTexWrapping( t
, tObj
->WrapS
, tObj
->WrapT
);
316 mgaSetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
317 mgaSetTexBorderColor( t
, tObj
->_BorderChan
);
324 static void mgaDDTexEnv( GLcontext
*ctx
, GLenum target
,
325 GLenum pname
, const GLfloat
*param
)
327 GLuint unit
= ctx
->Texture
.CurrentUnit
;
328 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
329 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
333 case GL_TEXTURE_ENV_COLOR
: {
337 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
338 envColor
= mgaPackColor( mmesa
->mgaScreen
->cpp
, c
[0], c
[1], c
[2], c
[3] );
339 mmesa
->envcolor
= PACK_COLOR_8888( c
[3], c
[0], c
[1], c
[2] );
341 if (mmesa
->setup
.fcol
!= envColor
) {
343 mmesa
->setup
.fcol
= envColor
;
344 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
346 mmesa
->blend_flags
&= ~MGA_BLEND_ENV_COLOR
;
348 /* Actually just require all four components to be
349 * equal. This permits a single-pass GL_BLEND.
351 * More complex multitexture/multipass fallbacks
352 * for blend can be done later.
354 if (mmesa
->envcolor
!= 0x0 && mmesa
->envcolor
!= 0xffffffff)
355 mmesa
->blend_flags
|= MGA_BLEND_ENV_COLOR
;
363 static void mgaTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
364 GLint internalFormat
,
365 GLint width
, GLint height
, GLint border
,
366 GLenum format
, GLenum type
, const GLvoid
*pixels
,
367 const struct gl_pixelstore_attrib
*packing
,
368 struct gl_texture_object
*texObj
,
369 struct gl_texture_image
*texImage
)
371 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
375 driSwapOutTextureObject( t
);
378 t
= (driTextureObject
*) mgaAllocTexObj( texObj
);
380 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D" );
385 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
386 width
, height
, border
, format
, type
,
387 pixels
, packing
, texObj
, texImage
);
388 level
-= t
->firstLevel
;
390 t
->dirty_images
[0] |= (1UL << level
);
393 static void mgaTexSubImage2D( GLcontext
*ctx
,
396 GLint xoffset
, GLint yoffset
,
397 GLsizei width
, GLsizei height
,
398 GLenum format
, GLenum type
,
399 const GLvoid
*pixels
,
400 const struct gl_pixelstore_attrib
*packing
,
401 struct gl_texture_object
*texObj
,
402 struct gl_texture_image
*texImage
)
404 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
407 assert( t
!= NULL
); /* this _should_ be true */
409 driSwapOutTextureObject( t
);
412 t
= (driTextureObject
*) mgaAllocTexObj( texObj
);
414 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D" );
419 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
420 height
, format
, type
, pixels
, packing
, texObj
,
422 level
-= t
->firstLevel
;
424 t
->dirty_images
[0] |= (1UL << level
);
429 * Changes variables and flags for a state update, which will happen at the
430 * next UpdateTextureState
434 mgaDDTexParameter( GLcontext
*ctx
, GLenum target
,
435 struct gl_texture_object
*tObj
,
436 GLenum pname
, const GLfloat
*params
)
438 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
439 mgaTextureObjectPtr t
;
441 t
= (mgaTextureObjectPtr
) tObj
->DriverData
;
443 /* If we don't have a hardware texture, it will be automatically
444 * created with current state before it is used, so we don't have
449 || (target
!= GL_TEXTURE_2D
) ) {
454 case GL_TEXTURE_MIN_FILTER
:
455 driSwapOutTextureObject( (driTextureObject
*) t
);
457 case GL_TEXTURE_MAG_FILTER
:
459 mgaSetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
462 case GL_TEXTURE_WRAP_S
:
463 case GL_TEXTURE_WRAP_T
:
465 mgaSetTexWrapping(t
,tObj
->WrapS
,tObj
->WrapT
);
468 case GL_TEXTURE_BORDER_COLOR
:
470 mgaSetTexBorderColor(t
, tObj
->_BorderChan
);
473 case GL_TEXTURE_BASE_LEVEL
:
474 case GL_TEXTURE_MAX_LEVEL
:
475 case GL_TEXTURE_MIN_LOD
:
476 case GL_TEXTURE_MAX_LOD
:
477 /* This isn't the most efficient solution but there doesn't appear to
478 * be a nice alternative. Since there's no LOD clamping,
479 * we just have to rely on loading the right subset of mipmap levels
480 * to simulate a clamped LOD.
482 driSwapOutTextureObject( (driTextureObject
*) t
);
492 mgaDDBindTexture( GLcontext
*ctx
, GLenum target
,
493 struct gl_texture_object
*tObj
)
495 if ( target
== GL_TEXTURE_2D
) {
496 if ( tObj
->DriverData
== NULL
) {
497 mgaAllocTexObj( tObj
);
504 mgaDDDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
506 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
507 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
511 FLUSH_BATCH( mmesa
);
514 driDestroyTextureObject( t
);
520 mgaDDInitTextureFuncs( GLcontext
*ctx
)
522 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
525 ctx
->Driver
.ChooseTextureFormat
= mgaChooseTextureFormat
;
526 ctx
->Driver
.TexImage1D
= _mesa_store_teximage1d
;
527 ctx
->Driver
.TexImage2D
= mgaTexImage2D
;
528 ctx
->Driver
.TexImage3D
= _mesa_store_teximage3d
;
529 ctx
->Driver
.TexSubImage1D
= _mesa_store_texsubimage1d
;
530 ctx
->Driver
.TexSubImage2D
= mgaTexSubImage2D
;
531 ctx
->Driver
.TexSubImage3D
= _mesa_store_texsubimage3d
;
532 ctx
->Driver
.CopyTexImage1D
= _swrast_copy_teximage1d
;
533 ctx
->Driver
.CopyTexImage2D
= _swrast_copy_teximage2d
;
534 ctx
->Driver
.CopyTexSubImage1D
= _swrast_copy_texsubimage1d
;
535 ctx
->Driver
.CopyTexSubImage2D
= _swrast_copy_texsubimage2d
;
536 ctx
->Driver
.CopyTexSubImage3D
= _swrast_copy_texsubimage3d
;
537 ctx
->Driver
.TestProxyTexImage
= _mesa_test_proxy_teximage
;
539 ctx
->Driver
.BindTexture
= mgaDDBindTexture
;
540 ctx
->Driver
.CreateTexture
= NULL
; /* FIXME: Is this used??? */
541 ctx
->Driver
.DeleteTexture
= mgaDDDeleteTexture
;
542 ctx
->Driver
.IsTextureResident
= driIsTextureResident
;
543 ctx
->Driver
.PrioritizeTexture
= NULL
;
544 ctx
->Driver
.ActiveTexture
= NULL
;
545 ctx
->Driver
.UpdateTexturePalette
= NULL
;
547 ctx
->Driver
.TexEnv
= mgaDDTexEnv
;
548 ctx
->Driver
.TexParameter
= mgaDDTexParameter
;
550 driInitTextureObjects( ctx
, & mmesa
->swapped
, DRI_TEXMGR_DO_TEXTURE_2D
);