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 "main/colormac.h"
31 #include "main/context.h"
32 #include "main/enums.h"
33 #include "main/simple_list.h"
34 #include "main/imports.h"
35 #include "main/macros.h"
36 #include "main/texstore.h"
37 #include "main/teximage.h"
38 #include "main/texobj.h"
40 #include "mgacontext.h"
46 #include "swrast/swrast.h"
51 * Set the texture wrap modes.
52 * Currently \c GL_REPEAT, \c GL_CLAMP and \c GL_CLAMP_TO_EDGE are supported.
54 * \param t Texture object whose wrap modes are to be set
55 * \param swrap Wrap mode for the \a s texture coordinate
56 * \param twrap Wrap mode for the \a t texture coordinate
60 mgaSetTexWrapping( mgaTextureObjectPtr t
, GLenum swrap
, GLenum twrap
)
62 GLboolean is_clamp
= GL_FALSE
;
63 GLboolean is_clamp_to_edge
= GL_FALSE
;
65 t
->setup
.texctl
&= (TMC_clampu_MASK
& TMC_clampv_MASK
);
66 t
->setup
.texctl2
&= (TMC_borderen_MASK
);
72 t
->setup
.texctl
|= TMC_clampu_enable
;
75 case GL_CLAMP_TO_EDGE
:
76 t
->setup
.texctl
|= TMC_clampu_enable
;
77 is_clamp_to_edge
= GL_TRUE
;
80 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
87 t
->setup
.texctl
|= TMC_clampv_enable
;
90 case GL_CLAMP_TO_EDGE
:
91 t
->setup
.texctl
|= TMC_clampv_enable
;
92 is_clamp_to_edge
= GL_TRUE
;
95 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
99 t
->setup
.texctl2
|= TMC_borderen_enable
;
102 t
->border_fallback
= (is_clamp
&& is_clamp_to_edge
);
107 * Set the texture magnification and minification modes.
109 * \param t Texture whose filter modes are to be set
110 * \param minf Texture minification mode
111 * \param magf Texture magnification mode
115 mgaSetTexFilter( mgaTextureObjectPtr t
, GLenum minf
, GLenum magf
)
120 case GL_NEAREST
: val
= TF_minfilter_nrst
; break;
121 case GL_LINEAR
: val
= TF_minfilter_bilin
; break;
122 case GL_NEAREST_MIPMAP_NEAREST
: val
= TF_minfilter_mm1s
; break;
123 case GL_LINEAR_MIPMAP_NEAREST
: val
= TF_minfilter_mm4s
; break;
124 case GL_NEAREST_MIPMAP_LINEAR
: val
= TF_minfilter_mm2s
; break;
125 case GL_LINEAR_MIPMAP_LINEAR
: val
= TF_minfilter_mm8s
; break;
126 default: val
= TF_minfilter_nrst
; break;
130 case GL_NEAREST
: val
|= TF_magfilter_nrst
; break;
131 case GL_LINEAR
: val
|= TF_magfilter_bilin
; break;
132 default: val
|= TF_magfilter_nrst
; break;
135 /* See OpenGL 1.2 specification */
136 if (magf
== GL_LINEAR
&& (minf
== GL_NEAREST_MIPMAP_NEAREST
||
137 minf
== GL_NEAREST_MIPMAP_LINEAR
)) {
138 val
|= MGA_FIELD( TF_fthres
, 0x20 ); /* c = 0.5 */
140 val
|= MGA_FIELD( TF_fthres
, 0x10 ); /* c = 0 */
144 /* Mask off the bits for the fields we are setting. Remember, the MGA mask
145 * defines have 0s for the bits in the named fields. This is the opposite
146 * of most of the other drivers.
149 t
->setup
.texfilter
&= (TF_minfilter_MASK
&
152 t
->setup
.texfilter
|= val
;
155 static void mgaSetTexBorderColor(mgaTextureObjectPtr t
, const GLfloat color
[4])
158 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
159 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
160 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
161 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
162 t
->setup
.texbordercol
= PACK_COLOR_8888(c
[3], c
[0], c
[1], c
[2] );
167 mgaChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
168 GLenum format
, GLenum type
)
170 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
171 const GLboolean do32bpt
=
172 ( mmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
173 const GLboolean force16bpt
=
174 ( mmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
177 switch ( internalFormat
) {
180 case GL_COMPRESSED_RGBA
:
182 case GL_UNSIGNED_INT_10_10_10_2
:
183 case GL_UNSIGNED_INT_2_10_10_10_REV
:
184 return do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB1555
;
185 case GL_UNSIGNED_SHORT_4_4_4_4
:
186 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
187 return MESA_FORMAT_ARGB4444
;
188 case GL_UNSIGNED_SHORT_5_5_5_1
:
189 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
190 return MESA_FORMAT_ARGB1555
;
192 return do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
;
197 case GL_COMPRESSED_RGB
:
199 case GL_UNSIGNED_SHORT_4_4_4_4
:
200 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
201 return MESA_FORMAT_ARGB4444
;
202 case GL_UNSIGNED_SHORT_5_5_5_1
:
203 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
204 return MESA_FORMAT_ARGB1555
;
205 case GL_UNSIGNED_SHORT_5_6_5
:
206 case GL_UNSIGNED_SHORT_5_6_5_REV
:
207 return MESA_FORMAT_RGB565
;
209 return do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_RGB565
;
217 MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
;
221 return MESA_FORMAT_ARGB4444
;
224 return MESA_FORMAT_ARGB1555
;
230 return !force16bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_RGB565
;
235 return MESA_FORMAT_RGB565
;
242 case GL_COMPRESSED_ALPHA
:
243 /* FIXME: This will report incorrect component sizes... */
244 return MGA_IS_G400(mmesa
) ? MESA_FORMAT_AL88
: MESA_FORMAT_ARGB4444
;
252 case GL_COMPRESSED_LUMINANCE
:
253 /* FIXME: This will report incorrect component sizes... */
254 return MGA_IS_G400(mmesa
) ? MESA_FORMAT_AL88
: MESA_FORMAT_RGB565
;
257 case GL_LUMINANCE_ALPHA
:
258 case GL_LUMINANCE4_ALPHA4
:
259 case GL_LUMINANCE6_ALPHA2
:
260 case GL_LUMINANCE8_ALPHA8
:
261 case GL_LUMINANCE12_ALPHA4
:
262 case GL_LUMINANCE12_ALPHA12
:
263 case GL_LUMINANCE16_ALPHA16
:
264 case GL_COMPRESSED_LUMINANCE_ALPHA
:
265 /* FIXME: This will report incorrect component sizes... */
266 return MGA_IS_G400(mmesa
) ? MESA_FORMAT_AL88
: MESA_FORMAT_ARGB4444
;
273 case GL_COMPRESSED_INTENSITY
:
274 /* FIXME: This will report incorrect component sizes... */
275 return MGA_IS_G400(mmesa
) ? MESA_FORMAT_I8
: MESA_FORMAT_ARGB4444
;
278 if (MGA_IS_G400(mmesa
) &&
279 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
280 type
== GL_UNSIGNED_BYTE
))
281 return MESA_FORMAT_YCBCR
;
283 return MESA_FORMAT_YCBCR_REV
;
286 case GL_COLOR_INDEX1_EXT
:
287 case GL_COLOR_INDEX2_EXT
:
288 case GL_COLOR_INDEX4_EXT
:
289 case GL_COLOR_INDEX8_EXT
:
290 case GL_COLOR_INDEX12_EXT
:
291 case GL_COLOR_INDEX16_EXT
:
292 return MESA_FORMAT_CI8
;
295 _mesa_problem( ctx
, "unexpected texture format in %s", __FUNCTION__
);
296 return MESA_FORMAT_NONE
;
299 return MESA_FORMAT_NONE
; /* never get here */
306 * Allocate space for and load the mesa images into the texture memory block.
307 * This will happen before drawing with a new texture, or drawing with a
308 * texture after it was swapped out or teximaged again.
311 static mgaTextureObjectPtr
312 mgaAllocTexObj( struct gl_texture_object
*tObj
)
314 mgaTextureObjectPtr t
;
317 t
= CALLOC( sizeof( *t
) );
318 tObj
->DriverData
= t
;
320 /* Initialize non-image-dependent parts of the state:
324 t
->setup
.texctl
= TMC_takey_1
| TMC_tamask_0
;
325 t
->setup
.texctl2
= TMC_ckstransdis_enable
;
326 t
->setup
.texfilter
= TF_filteralpha_enable
| TF_uvoffset_OGL
;
328 t
->border_fallback
= GL_FALSE
;
329 t
->texenv_fallback
= GL_FALSE
;
331 make_empty_list( & t
->base
);
333 mgaSetTexWrapping( t
, tObj
->WrapS
, tObj
->WrapT
);
334 mgaSetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
335 mgaSetTexBorderColor( t
, tObj
->BorderColor
);
342 static void mgaTexEnv( GLcontext
*ctx
, GLenum target
,
343 GLenum pname
, const GLfloat
*param
)
345 GLuint unit
= ctx
->Texture
.CurrentUnit
;
346 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
347 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
350 case GL_TEXTURE_ENV_COLOR
: {
353 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
354 mmesa
->envcolor
[unit
] = PACK_COLOR_8888( c
[3], c
[0], c
[1], c
[2] );
361 static void mgaTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
362 GLint internalFormat
,
363 GLint width
, GLint height
, GLint border
,
364 GLenum format
, GLenum type
, const GLvoid
*pixels
,
365 const struct gl_pixelstore_attrib
*packing
,
366 struct gl_texture_object
*texObj
,
367 struct gl_texture_image
*texImage
)
369 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
372 driSwapOutTextureObject( t
);
375 t
= (driTextureObject
*) mgaAllocTexObj( texObj
);
377 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D" );
382 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
383 width
, height
, border
, format
, type
,
384 pixels
, packing
, texObj
, texImage
);
385 level
-= t
->firstLevel
;
387 t
->dirty_images
[0] |= (1UL << level
);
390 static void mgaTexSubImage2D( GLcontext
*ctx
,
393 GLint xoffset
, GLint yoffset
,
394 GLsizei width
, GLsizei height
,
395 GLenum format
, GLenum type
,
396 const GLvoid
*pixels
,
397 const struct gl_pixelstore_attrib
*packing
,
398 struct gl_texture_object
*texObj
,
399 struct gl_texture_image
*texImage
)
401 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
403 assert( t
); /* this _should_ be true */
405 driSwapOutTextureObject( t
);
408 t
= (driTextureObject
*) mgaAllocTexObj( texObj
);
410 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D" );
415 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
416 height
, format
, type
, pixels
, packing
, texObj
,
418 level
-= t
->firstLevel
;
420 t
->dirty_images
[0] |= (1UL << level
);
425 * Changes variables and flags for a state update, which will happen at the
426 * next UpdateTextureState
430 mgaTexParameter( GLcontext
*ctx
, GLenum target
,
431 struct gl_texture_object
*tObj
,
432 GLenum pname
, const GLfloat
*params
)
434 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
435 mgaTextureObjectPtr t
= (mgaTextureObjectPtr
) tObj
->DriverData
;
437 /* If we don't have a hardware texture, it will be automatically
438 * created with current state before it is used, so we don't have
442 (target
!= GL_TEXTURE_2D
&&
443 target
!= GL_TEXTURE_RECTANGLE_NV
) ) {
448 case GL_TEXTURE_MIN_FILTER
:
449 driSwapOutTextureObject( (driTextureObject
*) t
);
451 case GL_TEXTURE_MAG_FILTER
:
453 mgaSetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
456 case GL_TEXTURE_WRAP_S
:
457 case GL_TEXTURE_WRAP_T
:
459 mgaSetTexWrapping(t
,tObj
->WrapS
,tObj
->WrapT
);
462 case GL_TEXTURE_BORDER_COLOR
:
464 mgaSetTexBorderColor(t
, tObj
->BorderColor
);
467 case GL_TEXTURE_BASE_LEVEL
:
468 case GL_TEXTURE_MAX_LEVEL
:
469 case GL_TEXTURE_MIN_LOD
:
470 case GL_TEXTURE_MAX_LOD
:
471 /* This isn't the most efficient solution but there doesn't appear to
472 * be a nice alternative. Since there's no LOD clamping,
473 * we just have to rely on loading the right subset of mipmap levels
474 * to simulate a clamped LOD.
476 driSwapOutTextureObject( (driTextureObject
*) t
);
486 mgaBindTexture( GLcontext
*ctx
, GLenum target
,
487 struct gl_texture_object
*tObj
)
489 assert( (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_RECTANGLE_NV
) ||
490 (tObj
->DriverData
!= NULL
) );
495 mgaDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
497 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
498 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
502 FLUSH_BATCH( mmesa
);
505 driDestroyTextureObject( t
);
508 /* Free mipmap images and the texture object itself */
509 _mesa_delete_texture_object(ctx
, tObj
);
514 * Allocate a new texture object.
515 * Called via ctx->Driver.NewTextureObject.
516 * Note: this function will be called during context creation to
517 * allocate the default texture objects.
518 * Note: we could use containment here to 'derive' the driver-specific
519 * texture object from the core mesa gl_texture_object. Not done at this time.
521 static struct gl_texture_object
*
522 mgaNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
524 struct gl_texture_object
*obj
;
525 obj
= _mesa_new_texture_object(ctx
, name
, target
);
526 mgaAllocTexObj( obj
);
532 mgaInitTextureFuncs( struct dd_function_table
*functions
)
534 functions
->ChooseTextureFormat
= mgaChooseTextureFormat
;
535 functions
->TexImage2D
= mgaTexImage2D
;
536 functions
->TexSubImage2D
= mgaTexSubImage2D
;
537 functions
->BindTexture
= mgaBindTexture
;
538 functions
->NewTextureObject
= mgaNewTextureObject
;
539 functions
->DeleteTexture
= mgaDeleteTexture
;
540 functions
->IsTextureResident
= driIsTextureResident
;
541 functions
->TexEnv
= mgaTexEnv
;
542 functions
->TexParameter
= mgaTexParameter
;