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"
48 #include "swrast/swrast.h"
53 * Set the texture wrap modes.
54 * Currently \c GL_REPEAT, \c GL_CLAMP and \c GL_CLAMP_TO_EDGE are supported.
56 * \param t Texture object whose wrap modes are to be set
57 * \param swrap Wrap mode for the \a s texture coordinate
58 * \param twrap Wrap mode for the \a t texture coordinate
62 mgaSetTexWrapping( mgaTextureObjectPtr t
, GLenum swrap
, GLenum twrap
)
64 GLboolean is_clamp
= GL_FALSE
;
65 GLboolean is_clamp_to_edge
= GL_FALSE
;
67 t
->setup
.texctl
&= (TMC_clampu_MASK
& TMC_clampv_MASK
);
68 t
->setup
.texctl2
&= (TMC_borderen_MASK
);
74 t
->setup
.texctl
|= TMC_clampu_enable
;
77 case GL_CLAMP_TO_EDGE
:
78 t
->setup
.texctl
|= TMC_clampu_enable
;
79 is_clamp_to_edge
= GL_TRUE
;
82 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
89 t
->setup
.texctl
|= TMC_clampv_enable
;
92 case GL_CLAMP_TO_EDGE
:
93 t
->setup
.texctl
|= TMC_clampv_enable
;
94 is_clamp_to_edge
= GL_TRUE
;
97 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
101 t
->setup
.texctl2
|= TMC_borderen_enable
;
104 t
->border_fallback
= (is_clamp
&& is_clamp_to_edge
);
109 * Set the texture magnification and minification modes.
111 * \param t Texture whose filter modes are to be set
112 * \param minf Texture minification mode
113 * \param magf Texture magnification mode
117 mgaSetTexFilter( mgaTextureObjectPtr t
, GLenum minf
, GLenum magf
)
122 case GL_NEAREST
: val
= TF_minfilter_nrst
; break;
123 case GL_LINEAR
: val
= TF_minfilter_bilin
; break;
124 case GL_NEAREST_MIPMAP_NEAREST
: val
= TF_minfilter_mm1s
; break;
125 case GL_LINEAR_MIPMAP_NEAREST
: val
= TF_minfilter_mm4s
; break;
126 case GL_NEAREST_MIPMAP_LINEAR
: val
= TF_minfilter_mm2s
; break;
127 case GL_LINEAR_MIPMAP_LINEAR
: val
= TF_minfilter_mm8s
; break;
128 default: val
= TF_minfilter_nrst
; break;
132 case GL_NEAREST
: val
|= TF_magfilter_nrst
; break;
133 case GL_LINEAR
: val
|= TF_magfilter_bilin
; break;
134 default: val
|= TF_magfilter_nrst
; break;
137 /* See OpenGL 1.2 specification */
138 if (magf
== GL_LINEAR
&& (minf
== GL_NEAREST_MIPMAP_NEAREST
||
139 minf
== GL_NEAREST_MIPMAP_LINEAR
)) {
140 val
|= MGA_FIELD( TF_fthres
, 0x20 ); /* c = 0.5 */
142 val
|= MGA_FIELD( TF_fthres
, 0x10 ); /* c = 0 */
146 /* Mask off the bits for the fields we are setting. Remember, the MGA mask
147 * defines have 0s for the bits in the named fields. This is the opposite
148 * of most of the other drivers.
151 t
->setup
.texfilter
&= (TF_minfilter_MASK
&
154 t
->setup
.texfilter
|= val
;
157 static void mgaSetTexBorderColor(mgaTextureObjectPtr t
, GLubyte color
[4])
159 t
->setup
.texbordercol
= PACK_COLOR_8888(color
[3], color
[0],
160 color
[1], color
[2] );
164 static const struct gl_texture_format
*
165 mgaChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
166 GLenum format
, GLenum type
)
168 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
169 const GLboolean do32bpt
=
170 ( mmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
171 const GLboolean force16bpt
=
172 ( mmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
175 switch ( internalFormat
) {
178 case GL_COMPRESSED_RGBA
:
180 case GL_UNSIGNED_INT_10_10_10_2
:
181 case GL_UNSIGNED_INT_2_10_10_10_REV
:
182 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
183 case GL_UNSIGNED_SHORT_4_4_4_4
:
184 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
185 return &_mesa_texformat_argb4444
;
186 case GL_UNSIGNED_SHORT_5_5_5_1
:
187 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
188 return &_mesa_texformat_argb1555
;
190 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
195 case GL_COMPRESSED_RGB
:
197 case GL_UNSIGNED_SHORT_4_4_4_4
:
198 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
199 return &_mesa_texformat_argb4444
;
200 case GL_UNSIGNED_SHORT_5_5_5_1
:
201 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
202 return &_mesa_texformat_argb1555
;
203 case GL_UNSIGNED_SHORT_5_6_5
:
204 case GL_UNSIGNED_SHORT_5_6_5_REV
:
205 return &_mesa_texformat_rgb565
;
207 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
215 &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
219 return &_mesa_texformat_argb4444
;
222 return &_mesa_texformat_argb1555
;
228 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
233 return &_mesa_texformat_rgb565
;
240 case GL_COMPRESSED_ALPHA
:
241 /* FIXME: This will report incorrect component sizes... */
242 return MGA_IS_G400(mmesa
) ? &_mesa_texformat_al88
: &_mesa_texformat_argb4444
;
250 case GL_COMPRESSED_LUMINANCE
:
251 /* FIXME: This will report incorrect component sizes... */
252 return MGA_IS_G400(mmesa
) ? &_mesa_texformat_al88
: &_mesa_texformat_rgb565
;
255 case GL_LUMINANCE_ALPHA
:
256 case GL_LUMINANCE4_ALPHA4
:
257 case GL_LUMINANCE6_ALPHA2
:
258 case GL_LUMINANCE8_ALPHA8
:
259 case GL_LUMINANCE12_ALPHA4
:
260 case GL_LUMINANCE12_ALPHA12
:
261 case GL_LUMINANCE16_ALPHA16
:
262 case GL_COMPRESSED_LUMINANCE_ALPHA
:
263 /* FIXME: This will report incorrect component sizes... */
264 return MGA_IS_G400(mmesa
) ? &_mesa_texformat_al88
: &_mesa_texformat_argb4444
;
271 case GL_COMPRESSED_INTENSITY
:
272 /* FIXME: This will report incorrect component sizes... */
273 return MGA_IS_G400(mmesa
) ? &_mesa_texformat_i8
: &_mesa_texformat_argb4444
;
276 if (MGA_IS_G400(mmesa
) &&
277 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
278 type
== GL_UNSIGNED_BYTE
))
279 return &_mesa_texformat_ycbcr
;
281 return &_mesa_texformat_ycbcr_rev
;
284 case GL_COLOR_INDEX1_EXT
:
285 case GL_COLOR_INDEX2_EXT
:
286 case GL_COLOR_INDEX4_EXT
:
287 case GL_COLOR_INDEX8_EXT
:
288 case GL_COLOR_INDEX12_EXT
:
289 case GL_COLOR_INDEX16_EXT
:
290 return &_mesa_texformat_ci8
;
293 _mesa_problem( ctx
, "unexpected texture format in %s", __FUNCTION__
);
297 return NULL
; /* never get here */
304 * Allocate space for and load the mesa images into the texture memory block.
305 * This will happen before drawing with a new texture, or drawing with a
306 * texture after it was swapped out or teximaged again.
309 static mgaTextureObjectPtr
310 mgaAllocTexObj( struct gl_texture_object
*tObj
)
312 mgaTextureObjectPtr t
;
315 t
= CALLOC( sizeof( *t
) );
316 tObj
->DriverData
= t
;
318 /* Initialize non-image-dependent parts of the state:
322 t
->setup
.texctl
= TMC_takey_1
| TMC_tamask_0
;
323 t
->setup
.texctl2
= TMC_ckstransdis_enable
;
324 t
->setup
.texfilter
= TF_filteralpha_enable
| TF_uvoffset_OGL
;
326 t
->border_fallback
= GL_FALSE
;
327 t
->texenv_fallback
= GL_FALSE
;
329 make_empty_list( & t
->base
);
331 mgaSetTexWrapping( t
, tObj
->WrapS
, tObj
->WrapT
);
332 mgaSetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
333 mgaSetTexBorderColor( t
, tObj
->_BorderChan
);
340 static void mgaTexEnv( GLcontext
*ctx
, GLenum target
,
341 GLenum pname
, const GLfloat
*param
)
343 GLuint unit
= ctx
->Texture
.CurrentUnit
;
344 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
345 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
348 case GL_TEXTURE_ENV_COLOR
: {
351 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
352 mmesa
->envcolor
[unit
] = PACK_COLOR_8888( c
[3], c
[0], c
[1], c
[2] );
359 static void mgaTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
360 GLint internalFormat
,
361 GLint width
, GLint height
, GLint border
,
362 GLenum format
, GLenum type
, const GLvoid
*pixels
,
363 const struct gl_pixelstore_attrib
*packing
,
364 struct gl_texture_object
*texObj
,
365 struct gl_texture_image
*texImage
)
367 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
370 driSwapOutTextureObject( t
);
373 t
= (driTextureObject
*) mgaAllocTexObj( texObj
);
375 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D" );
380 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
381 width
, height
, border
, format
, type
,
382 pixels
, packing
, texObj
, texImage
);
383 level
-= t
->firstLevel
;
385 t
->dirty_images
[0] |= (1UL << level
);
388 static void mgaTexSubImage2D( GLcontext
*ctx
,
391 GLint xoffset
, GLint yoffset
,
392 GLsizei width
, GLsizei height
,
393 GLenum format
, GLenum type
,
394 const GLvoid
*pixels
,
395 const struct gl_pixelstore_attrib
*packing
,
396 struct gl_texture_object
*texObj
,
397 struct gl_texture_image
*texImage
)
399 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
401 assert( t
); /* this _should_ be true */
403 driSwapOutTextureObject( t
);
406 t
= (driTextureObject
*) mgaAllocTexObj( texObj
);
408 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D" );
413 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
414 height
, format
, type
, pixels
, packing
, texObj
,
416 level
-= t
->firstLevel
;
418 t
->dirty_images
[0] |= (1UL << level
);
423 * Changes variables and flags for a state update, which will happen at the
424 * next UpdateTextureState
428 mgaTexParameter( GLcontext
*ctx
, GLenum target
,
429 struct gl_texture_object
*tObj
,
430 GLenum pname
, const GLfloat
*params
)
432 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
433 mgaTextureObjectPtr t
= (mgaTextureObjectPtr
) tObj
->DriverData
;
435 /* If we don't have a hardware texture, it will be automatically
436 * created with current state before it is used, so we don't have
440 (target
!= GL_TEXTURE_2D
&&
441 target
!= GL_TEXTURE_RECTANGLE_NV
) ) {
446 case GL_TEXTURE_MIN_FILTER
:
447 driSwapOutTextureObject( (driTextureObject
*) t
);
449 case GL_TEXTURE_MAG_FILTER
:
451 mgaSetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
454 case GL_TEXTURE_WRAP_S
:
455 case GL_TEXTURE_WRAP_T
:
457 mgaSetTexWrapping(t
,tObj
->WrapS
,tObj
->WrapT
);
460 case GL_TEXTURE_BORDER_COLOR
:
462 mgaSetTexBorderColor(t
, tObj
->_BorderChan
);
465 case GL_TEXTURE_BASE_LEVEL
:
466 case GL_TEXTURE_MAX_LEVEL
:
467 case GL_TEXTURE_MIN_LOD
:
468 case GL_TEXTURE_MAX_LOD
:
469 /* This isn't the most efficient solution but there doesn't appear to
470 * be a nice alternative. Since there's no LOD clamping,
471 * we just have to rely on loading the right subset of mipmap levels
472 * to simulate a clamped LOD.
474 driSwapOutTextureObject( (driTextureObject
*) t
);
484 mgaBindTexture( GLcontext
*ctx
, GLenum target
,
485 struct gl_texture_object
*tObj
)
487 assert( (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_RECTANGLE_NV
) ||
488 (tObj
->DriverData
!= NULL
) );
493 mgaDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
495 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
496 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
500 FLUSH_BATCH( mmesa
);
503 driDestroyTextureObject( t
);
509 * Allocate a new texture object.
510 * Called via ctx->Driver.NewTextureObject.
511 * Note: this function will be called during context creation to
512 * allocate the default texture objects.
513 * Note: we could use containment here to 'derive' the driver-specific
514 * texture object from the core mesa gl_texture_object. Not done at this time.
516 static struct gl_texture_object
*
517 mgaNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
519 struct gl_texture_object
*obj
;
520 obj
= _mesa_new_texture_object(ctx
, name
, target
);
521 mgaAllocTexObj( obj
);
527 mgaInitTextureFuncs( struct dd_function_table
*functions
)
529 functions
->ChooseTextureFormat
= mgaChooseTextureFormat
;
530 functions
->TexImage2D
= mgaTexImage2D
;
531 functions
->TexSubImage2D
= mgaTexSubImage2D
;
532 functions
->BindTexture
= mgaBindTexture
;
533 functions
->NewTextureObject
= mgaNewTextureObject
;
534 functions
->DeleteTexture
= mgaDeleteTexture
;
535 functions
->IsTextureResident
= driIsTextureResident
;
536 functions
->TexEnv
= mgaTexEnv
;
537 functions
->TexParameter
= mgaTexParameter
;