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>
28 #include "main/glheader.h"
30 #include "mgacontext.h"
36 #include "main/colormac.h"
37 #include "main/context.h"
38 #include "main/enums.h"
39 #include "main/simple_list.h"
40 #include "main/imports.h"
41 #include "main/macros.h"
42 #include "main/texformat.h"
43 #include "main/texstore.h"
44 #include "main/teximage.h"
45 #include "main/texobj.h"
47 #include "swrast/swrast.h"
52 * Set the texture wrap modes.
53 * Currently \c GL_REPEAT, \c GL_CLAMP and \c GL_CLAMP_TO_EDGE are supported.
55 * \param t Texture object whose wrap modes are to be set
56 * \param swrap Wrap mode for the \a s texture coordinate
57 * \param twrap Wrap mode for the \a t texture coordinate
61 mgaSetTexWrapping( mgaTextureObjectPtr t
, GLenum swrap
, GLenum twrap
)
63 GLboolean is_clamp
= GL_FALSE
;
64 GLboolean is_clamp_to_edge
= GL_FALSE
;
66 t
->setup
.texctl
&= (TMC_clampu_MASK
& TMC_clampv_MASK
);
67 t
->setup
.texctl2
&= (TMC_borderen_MASK
);
73 t
->setup
.texctl
|= TMC_clampu_enable
;
76 case GL_CLAMP_TO_EDGE
:
77 t
->setup
.texctl
|= TMC_clampu_enable
;
78 is_clamp_to_edge
= GL_TRUE
;
81 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
88 t
->setup
.texctl
|= TMC_clampv_enable
;
91 case GL_CLAMP_TO_EDGE
:
92 t
->setup
.texctl
|= TMC_clampv_enable
;
93 is_clamp_to_edge
= GL_TRUE
;
96 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
100 t
->setup
.texctl2
|= TMC_borderen_enable
;
103 t
->border_fallback
= (is_clamp
&& is_clamp_to_edge
);
108 * Set the texture magnification and minification modes.
110 * \param t Texture whose filter modes are to be set
111 * \param minf Texture minification mode
112 * \param magf Texture magnification mode
116 mgaSetTexFilter( mgaTextureObjectPtr t
, GLenum minf
, GLenum magf
)
121 case GL_NEAREST
: val
= TF_minfilter_nrst
; break;
122 case GL_LINEAR
: val
= TF_minfilter_bilin
; break;
123 case GL_NEAREST_MIPMAP_NEAREST
: val
= TF_minfilter_mm1s
; break;
124 case GL_LINEAR_MIPMAP_NEAREST
: val
= TF_minfilter_mm4s
; break;
125 case GL_NEAREST_MIPMAP_LINEAR
: val
= TF_minfilter_mm2s
; break;
126 case GL_LINEAR_MIPMAP_LINEAR
: val
= TF_minfilter_mm8s
; break;
127 default: val
= TF_minfilter_nrst
; break;
131 case GL_NEAREST
: val
|= TF_magfilter_nrst
; break;
132 case GL_LINEAR
: val
|= TF_magfilter_bilin
; break;
133 default: val
|= TF_magfilter_nrst
; break;
136 /* See OpenGL 1.2 specification */
137 if (magf
== GL_LINEAR
&& (minf
== GL_NEAREST_MIPMAP_NEAREST
||
138 minf
== GL_NEAREST_MIPMAP_LINEAR
)) {
139 val
|= MGA_FIELD( TF_fthres
, 0x20 ); /* c = 0.5 */
141 val
|= MGA_FIELD( TF_fthres
, 0x10 ); /* c = 0 */
145 /* Mask off the bits for the fields we are setting. Remember, the MGA mask
146 * defines have 0s for the bits in the named fields. This is the opposite
147 * of most of the other drivers.
150 t
->setup
.texfilter
&= (TF_minfilter_MASK
&
153 t
->setup
.texfilter
|= val
;
156 static void mgaSetTexBorderColor(mgaTextureObjectPtr t
, const GLfloat color
[4])
159 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
160 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
161 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
162 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
163 t
->setup
.texbordercol
= PACK_COLOR_8888(c
[3], c
[0], c
[1], c
[2] );
167 static const struct gl_texture_format
*
168 mgaChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
169 GLenum format
, GLenum type
)
171 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
172 const GLboolean do32bpt
=
173 ( mmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
174 const GLboolean force16bpt
=
175 ( mmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
178 switch ( internalFormat
) {
181 case GL_COMPRESSED_RGBA
:
183 case GL_UNSIGNED_INT_10_10_10_2
:
184 case GL_UNSIGNED_INT_2_10_10_10_REV
:
185 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
186 case GL_UNSIGNED_SHORT_4_4_4_4
:
187 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
188 return &_mesa_texformat_argb4444
;
189 case GL_UNSIGNED_SHORT_5_5_5_1
:
190 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
191 return &_mesa_texformat_argb1555
;
193 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
198 case GL_COMPRESSED_RGB
:
200 case GL_UNSIGNED_SHORT_4_4_4_4
:
201 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
202 return &_mesa_texformat_argb4444
;
203 case GL_UNSIGNED_SHORT_5_5_5_1
:
204 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
205 return &_mesa_texformat_argb1555
;
206 case GL_UNSIGNED_SHORT_5_6_5
:
207 case GL_UNSIGNED_SHORT_5_6_5_REV
:
208 return &_mesa_texformat_rgb565
;
210 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
218 &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
222 return &_mesa_texformat_argb4444
;
225 return &_mesa_texformat_argb1555
;
231 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
236 return &_mesa_texformat_rgb565
;
243 case GL_COMPRESSED_ALPHA
:
244 /* FIXME: This will report incorrect component sizes... */
245 return MGA_IS_G400(mmesa
) ? &_mesa_texformat_al88
: &_mesa_texformat_argb4444
;
253 case GL_COMPRESSED_LUMINANCE
:
254 /* FIXME: This will report incorrect component sizes... */
255 return MGA_IS_G400(mmesa
) ? &_mesa_texformat_al88
: &_mesa_texformat_rgb565
;
258 case GL_LUMINANCE_ALPHA
:
259 case GL_LUMINANCE4_ALPHA4
:
260 case GL_LUMINANCE6_ALPHA2
:
261 case GL_LUMINANCE8_ALPHA8
:
262 case GL_LUMINANCE12_ALPHA4
:
263 case GL_LUMINANCE12_ALPHA12
:
264 case GL_LUMINANCE16_ALPHA16
:
265 case GL_COMPRESSED_LUMINANCE_ALPHA
:
266 /* FIXME: This will report incorrect component sizes... */
267 return MGA_IS_G400(mmesa
) ? &_mesa_texformat_al88
: &_mesa_texformat_argb4444
;
274 case GL_COMPRESSED_INTENSITY
:
275 /* FIXME: This will report incorrect component sizes... */
276 return MGA_IS_G400(mmesa
) ? &_mesa_texformat_i8
: &_mesa_texformat_argb4444
;
279 if (MGA_IS_G400(mmesa
) &&
280 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
281 type
== GL_UNSIGNED_BYTE
))
282 return &_mesa_texformat_ycbcr
;
284 return &_mesa_texformat_ycbcr_rev
;
287 case GL_COLOR_INDEX1_EXT
:
288 case GL_COLOR_INDEX2_EXT
:
289 case GL_COLOR_INDEX4_EXT
:
290 case GL_COLOR_INDEX8_EXT
:
291 case GL_COLOR_INDEX12_EXT
:
292 case GL_COLOR_INDEX16_EXT
:
293 return &_mesa_texformat_ci8
;
296 _mesa_problem( ctx
, "unexpected texture format in %s", __FUNCTION__
);
300 return NULL
; /* never get here */
307 * Allocate space for and load the mesa images into the texture memory block.
308 * This will happen before drawing with a new texture, or drawing with a
309 * texture after it was swapped out or teximaged again.
312 static mgaTextureObjectPtr
313 mgaAllocTexObj( struct gl_texture_object
*tObj
)
315 mgaTextureObjectPtr t
;
318 t
= CALLOC( sizeof( *t
) );
319 tObj
->DriverData
= t
;
321 /* Initialize non-image-dependent parts of the state:
325 t
->setup
.texctl
= TMC_takey_1
| TMC_tamask_0
;
326 t
->setup
.texctl2
= TMC_ckstransdis_enable
;
327 t
->setup
.texfilter
= TF_filteralpha_enable
| TF_uvoffset_OGL
;
329 t
->border_fallback
= GL_FALSE
;
330 t
->texenv_fallback
= GL_FALSE
;
332 make_empty_list( & t
->base
);
334 mgaSetTexWrapping( t
, tObj
->WrapS
, tObj
->WrapT
);
335 mgaSetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
336 mgaSetTexBorderColor( t
, tObj
->BorderColor
);
343 static void mgaTexEnv( GLcontext
*ctx
, GLenum target
,
344 GLenum pname
, const GLfloat
*param
)
346 GLuint unit
= ctx
->Texture
.CurrentUnit
;
347 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
348 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
351 case GL_TEXTURE_ENV_COLOR
: {
354 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
355 mmesa
->envcolor
[unit
] = PACK_COLOR_8888( c
[3], c
[0], c
[1], c
[2] );
362 static void mgaTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
363 GLint internalFormat
,
364 GLint width
, GLint height
, GLint border
,
365 GLenum format
, GLenum type
, const GLvoid
*pixels
,
366 const struct gl_pixelstore_attrib
*packing
,
367 struct gl_texture_object
*texObj
,
368 struct gl_texture_image
*texImage
)
370 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
373 driSwapOutTextureObject( t
);
376 t
= (driTextureObject
*) mgaAllocTexObj( texObj
);
378 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D" );
383 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
384 width
, height
, border
, format
, type
,
385 pixels
, packing
, texObj
, texImage
);
386 level
-= t
->firstLevel
;
388 t
->dirty_images
[0] |= (1UL << level
);
391 static void mgaTexSubImage2D( GLcontext
*ctx
,
394 GLint xoffset
, GLint yoffset
,
395 GLsizei width
, GLsizei height
,
396 GLenum format
, GLenum type
,
397 const GLvoid
*pixels
,
398 const struct gl_pixelstore_attrib
*packing
,
399 struct gl_texture_object
*texObj
,
400 struct gl_texture_image
*texImage
)
402 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
404 assert( t
); /* this _should_ be true */
406 driSwapOutTextureObject( t
);
409 t
= (driTextureObject
*) mgaAllocTexObj( texObj
);
411 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D" );
416 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
417 height
, format
, type
, pixels
, packing
, texObj
,
419 level
-= t
->firstLevel
;
421 t
->dirty_images
[0] |= (1UL << level
);
426 * Changes variables and flags for a state update, which will happen at the
427 * next UpdateTextureState
431 mgaTexParameter( GLcontext
*ctx
, GLenum target
,
432 struct gl_texture_object
*tObj
,
433 GLenum pname
, const GLfloat
*params
)
435 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
436 mgaTextureObjectPtr t
= (mgaTextureObjectPtr
) tObj
->DriverData
;
438 /* If we don't have a hardware texture, it will be automatically
439 * created with current state before it is used, so we don't have
443 (target
!= GL_TEXTURE_2D
&&
444 target
!= GL_TEXTURE_RECTANGLE_NV
) ) {
449 case GL_TEXTURE_MIN_FILTER
:
450 driSwapOutTextureObject( (driTextureObject
*) t
);
452 case GL_TEXTURE_MAG_FILTER
:
454 mgaSetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
457 case GL_TEXTURE_WRAP_S
:
458 case GL_TEXTURE_WRAP_T
:
460 mgaSetTexWrapping(t
,tObj
->WrapS
,tObj
->WrapT
);
463 case GL_TEXTURE_BORDER_COLOR
:
465 mgaSetTexBorderColor(t
, tObj
->BorderColor
);
468 case GL_TEXTURE_BASE_LEVEL
:
469 case GL_TEXTURE_MAX_LEVEL
:
470 case GL_TEXTURE_MIN_LOD
:
471 case GL_TEXTURE_MAX_LOD
:
472 /* This isn't the most efficient solution but there doesn't appear to
473 * be a nice alternative. Since there's no LOD clamping,
474 * we just have to rely on loading the right subset of mipmap levels
475 * to simulate a clamped LOD.
477 driSwapOutTextureObject( (driTextureObject
*) t
);
487 mgaBindTexture( GLcontext
*ctx
, GLenum target
,
488 struct gl_texture_object
*tObj
)
490 assert( (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_RECTANGLE_NV
) ||
491 (tObj
->DriverData
!= NULL
) );
496 mgaDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
498 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
499 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
503 FLUSH_BATCH( mmesa
);
506 driDestroyTextureObject( t
);
509 /* Free mipmap images and the texture object itself */
510 _mesa_delete_texture_object(ctx
, tObj
);
515 * Allocate a new texture object.
516 * Called via ctx->Driver.NewTextureObject.
517 * Note: this function will be called during context creation to
518 * allocate the default texture objects.
519 * Note: we could use containment here to 'derive' the driver-specific
520 * texture object from the core mesa gl_texture_object. Not done at this time.
522 static struct gl_texture_object
*
523 mgaNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
525 struct gl_texture_object
*obj
;
526 obj
= _mesa_new_texture_object(ctx
, name
, target
);
527 mgaAllocTexObj( obj
);
533 mgaInitTextureFuncs( struct dd_function_table
*functions
)
535 functions
->ChooseTextureFormat
= mgaChooseTextureFormat
;
536 functions
->TexImage2D
= mgaTexImage2D
;
537 functions
->TexSubImage2D
= mgaTexSubImage2D
;
538 functions
->BindTexture
= mgaBindTexture
;
539 functions
->NewTextureObject
= mgaNewTextureObject
;
540 functions
->DeleteTexture
= mgaDeleteTexture
;
541 functions
->IsTextureResident
= driIsTextureResident
;
542 functions
->TexEnv
= mgaTexEnv
;
543 functions
->TexParameter
= mgaTexParameter
;