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"
48 * Set the texture wrap modes.
49 * Currently \c GL_REPEAT, \c GL_CLAMP and \c GL_CLAMP_TO_EDGE are supported.
51 * \param t Texture object whose wrap modes are to be set
52 * \param swrap Wrap mode for the \a s texture coordinate
53 * \param twrap Wrap mode for the \a t texture coordinate
57 mgaSetTexWrapping( mgaTextureObjectPtr t
, GLenum swrap
, GLenum twrap
)
59 GLboolean is_clamp
= GL_FALSE
;
60 GLboolean is_clamp_to_edge
= GL_FALSE
;
62 t
->setup
.texctl
&= (TMC_clampu_MASK
& TMC_clampv_MASK
);
63 t
->setup
.texctl2
&= (TMC_borderen_MASK
);
69 t
->setup
.texctl
|= TMC_clampu_enable
;
72 case GL_CLAMP_TO_EDGE
:
73 t
->setup
.texctl
|= TMC_clampu_enable
;
74 is_clamp_to_edge
= GL_TRUE
;
77 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
84 t
->setup
.texctl
|= TMC_clampv_enable
;
87 case GL_CLAMP_TO_EDGE
:
88 t
->setup
.texctl
|= TMC_clampv_enable
;
89 is_clamp_to_edge
= GL_TRUE
;
92 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
96 t
->setup
.texctl2
|= TMC_borderen_enable
;
99 t
->border_fallback
= (is_clamp
&& is_clamp_to_edge
);
104 * Set the texture magnification and minification modes.
106 * \param t Texture whose filter modes are to be set
107 * \param minf Texture minification mode
108 * \param magf Texture magnification mode
112 mgaSetTexFilter( mgaTextureObjectPtr t
, GLenum minf
, GLenum magf
)
117 case GL_NEAREST
: val
= TF_minfilter_nrst
; break;
118 case GL_LINEAR
: val
= TF_minfilter_bilin
; break;
119 case GL_NEAREST_MIPMAP_NEAREST
: val
= TF_minfilter_mm1s
; break;
120 case GL_LINEAR_MIPMAP_NEAREST
: val
= TF_minfilter_mm4s
; break;
121 case GL_NEAREST_MIPMAP_LINEAR
: val
= TF_minfilter_mm2s
; break;
122 case GL_LINEAR_MIPMAP_LINEAR
: val
= TF_minfilter_mm8s
; break;
123 default: val
= TF_minfilter_nrst
; break;
127 case GL_NEAREST
: val
|= TF_magfilter_nrst
; break;
128 case GL_LINEAR
: val
|= TF_magfilter_bilin
; break;
129 default: val
|= TF_magfilter_nrst
; break;
132 /* See OpenGL 1.2 specification */
133 if (magf
== GL_LINEAR
&& (minf
== GL_NEAREST_MIPMAP_NEAREST
||
134 minf
== GL_NEAREST_MIPMAP_LINEAR
)) {
135 val
|= MGA_FIELD( TF_fthres
, 0x20 ); /* c = 0.5 */
137 val
|= MGA_FIELD( TF_fthres
, 0x10 ); /* c = 0 */
141 /* Mask off the bits for the fields we are setting. Remember, the MGA mask
142 * defines have 0s for the bits in the named fields. This is the opposite
143 * of most of the other drivers.
146 t
->setup
.texfilter
&= (TF_minfilter_MASK
&
149 t
->setup
.texfilter
|= val
;
152 static void mgaSetTexBorderColor(mgaTextureObjectPtr t
, const GLfloat color
[4])
155 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
156 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
157 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
158 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
159 t
->setup
.texbordercol
= PACK_COLOR_8888(c
[3], c
[0], c
[1], c
[2] );
164 mgaChooseTextureFormat( struct gl_context
*ctx
, GLint internalFormat
,
165 GLenum format
, GLenum type
)
167 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
168 const GLboolean do32bpt
=
169 ( mmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
170 const GLboolean force16bpt
=
171 ( mmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
174 switch ( internalFormat
) {
177 case GL_COMPRESSED_RGBA
:
179 case GL_UNSIGNED_INT_10_10_10_2
:
180 case GL_UNSIGNED_INT_2_10_10_10_REV
:
181 return do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB1555
;
182 case GL_UNSIGNED_SHORT_4_4_4_4
:
183 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
184 return MESA_FORMAT_ARGB4444
;
185 case GL_UNSIGNED_SHORT_5_5_5_1
:
186 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
187 return MESA_FORMAT_ARGB1555
;
189 return do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
;
194 case GL_COMPRESSED_RGB
:
196 case GL_UNSIGNED_SHORT_4_4_4_4
:
197 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
198 return MESA_FORMAT_ARGB4444
;
199 case GL_UNSIGNED_SHORT_5_5_5_1
:
200 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
201 return MESA_FORMAT_ARGB1555
;
202 case GL_UNSIGNED_SHORT_5_6_5
:
203 case GL_UNSIGNED_SHORT_5_6_5_REV
:
204 return MESA_FORMAT_RGB565
;
206 return do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_RGB565
;
214 MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
;
218 return MESA_FORMAT_ARGB4444
;
221 return MESA_FORMAT_ARGB1555
;
227 return !force16bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_RGB565
;
232 return MESA_FORMAT_RGB565
;
239 case GL_COMPRESSED_ALPHA
:
240 /* FIXME: This will report incorrect component sizes... */
241 return MGA_IS_G400(mmesa
) ? MESA_FORMAT_AL88
: MESA_FORMAT_ARGB4444
;
249 case GL_COMPRESSED_LUMINANCE
:
250 /* FIXME: This will report incorrect component sizes... */
251 return MGA_IS_G400(mmesa
) ? MESA_FORMAT_AL88
: MESA_FORMAT_RGB565
;
254 case GL_LUMINANCE_ALPHA
:
255 case GL_LUMINANCE4_ALPHA4
:
256 case GL_LUMINANCE6_ALPHA2
:
257 case GL_LUMINANCE8_ALPHA8
:
258 case GL_LUMINANCE12_ALPHA4
:
259 case GL_LUMINANCE12_ALPHA12
:
260 case GL_LUMINANCE16_ALPHA16
:
261 case GL_COMPRESSED_LUMINANCE_ALPHA
:
262 /* FIXME: This will report incorrect component sizes... */
263 return MGA_IS_G400(mmesa
) ? MESA_FORMAT_AL88
: MESA_FORMAT_ARGB4444
;
270 case GL_COMPRESSED_INTENSITY
:
271 /* FIXME: This will report incorrect component sizes... */
272 return MGA_IS_G400(mmesa
) ? MESA_FORMAT_I8
: MESA_FORMAT_ARGB4444
;
275 if (MGA_IS_G400(mmesa
) &&
276 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
277 type
== GL_UNSIGNED_BYTE
))
278 return MESA_FORMAT_YCBCR
;
280 return MESA_FORMAT_YCBCR_REV
;
283 case GL_COLOR_INDEX1_EXT
:
284 case GL_COLOR_INDEX2_EXT
:
285 case GL_COLOR_INDEX4_EXT
:
286 case GL_COLOR_INDEX8_EXT
:
287 case GL_COLOR_INDEX12_EXT
:
288 case GL_COLOR_INDEX16_EXT
:
289 return MESA_FORMAT_CI8
;
292 _mesa_problem( ctx
, "unexpected texture format in %s", __FUNCTION__
);
293 return MESA_FORMAT_NONE
;
296 return MESA_FORMAT_NONE
; /* never get here */
303 * Allocate space for and load the mesa images into the texture memory block.
304 * This will happen before drawing with a new texture, or drawing with a
305 * texture after it was swapped out or teximaged again.
308 static mgaTextureObjectPtr
309 mgaAllocTexObj( struct gl_texture_object
*tObj
)
311 mgaTextureObjectPtr t
;
314 t
= CALLOC( sizeof( *t
) );
315 tObj
->DriverData
= t
;
317 /* Initialize non-image-dependent parts of the state:
321 t
->setup
.texctl
= TMC_takey_1
| TMC_tamask_0
;
322 t
->setup
.texctl2
= TMC_ckstransdis_enable
;
323 t
->setup
.texfilter
= TF_filteralpha_enable
| TF_uvoffset_OGL
;
325 t
->border_fallback
= GL_FALSE
;
326 t
->texenv_fallback
= GL_FALSE
;
328 make_empty_list( & t
->base
);
330 mgaSetTexWrapping( t
, tObj
->Sampler
.WrapS
, tObj
->Sampler
.WrapT
);
331 mgaSetTexFilter( t
, tObj
->Sampler
.MinFilter
, tObj
->Sampler
.MagFilter
);
332 mgaSetTexBorderColor( t
, tObj
->Sampler
.BorderColor
.f
);
339 static void mgaTexEnv( struct gl_context
*ctx
, GLenum target
,
340 GLenum pname
, const GLfloat
*param
)
342 GLuint unit
= ctx
->Texture
.CurrentUnit
;
343 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
344 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
347 case GL_TEXTURE_ENV_COLOR
: {
350 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
351 mmesa
->envcolor
[unit
] = PACK_COLOR_8888( c
[3], c
[0], c
[1], c
[2] );
358 static void mgaTexImage2D( struct gl_context
*ctx
, GLenum target
, GLint level
,
359 GLint internalFormat
,
360 GLint width
, GLint height
, GLint border
,
361 GLenum format
, GLenum type
, const GLvoid
*pixels
,
362 const struct gl_pixelstore_attrib
*packing
,
363 struct gl_texture_object
*texObj
,
364 struct gl_texture_image
*texImage
)
366 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
369 driSwapOutTextureObject( t
);
372 t
= (driTextureObject
*) mgaAllocTexObj( texObj
);
374 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D" );
379 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
380 width
, height
, border
, format
, type
,
381 pixels
, packing
, texObj
, texImage
);
382 level
-= t
->firstLevel
;
384 t
->dirty_images
[0] |= (1UL << level
);
387 static void mgaTexSubImage2D( struct gl_context
*ctx
,
390 GLint xoffset
, GLint yoffset
,
391 GLsizei width
, GLsizei height
,
392 GLenum format
, GLenum type
,
393 const GLvoid
*pixels
,
394 const struct gl_pixelstore_attrib
*packing
,
395 struct gl_texture_object
*texObj
,
396 struct gl_texture_image
*texImage
)
398 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
400 assert( t
); /* this _should_ be true */
402 driSwapOutTextureObject( t
);
405 t
= (driTextureObject
*) mgaAllocTexObj( texObj
);
407 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D" );
412 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
413 height
, format
, type
, pixels
, packing
, texObj
,
415 level
-= t
->firstLevel
;
417 t
->dirty_images
[0] |= (1UL << level
);
422 * Changes variables and flags for a state update, which will happen at the
423 * next UpdateTextureState
427 mgaTexParameter( struct gl_context
*ctx
, GLenum target
,
428 struct gl_texture_object
*tObj
,
429 GLenum pname
, const GLfloat
*params
)
431 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
432 mgaTextureObjectPtr t
= (mgaTextureObjectPtr
) tObj
->DriverData
;
434 /* If we don't have a hardware texture, it will be automatically
435 * created with current state before it is used, so we don't have
439 (target
!= GL_TEXTURE_2D
&&
440 target
!= GL_TEXTURE_RECTANGLE_NV
) ) {
445 case GL_TEXTURE_MIN_FILTER
:
446 driSwapOutTextureObject( (driTextureObject
*) t
);
448 case GL_TEXTURE_MAG_FILTER
:
450 mgaSetTexFilter( t
, tObj
->Sampler
.MinFilter
, tObj
->Sampler
.MagFilter
);
453 case GL_TEXTURE_WRAP_S
:
454 case GL_TEXTURE_WRAP_T
:
456 mgaSetTexWrapping(t
,tObj
->Sampler
.WrapS
,tObj
->Sampler
.WrapT
);
459 case GL_TEXTURE_BORDER_COLOR
:
461 mgaSetTexBorderColor(t
, tObj
->Sampler
.BorderColor
.f
);
464 case GL_TEXTURE_BASE_LEVEL
:
465 case GL_TEXTURE_MAX_LEVEL
:
466 case GL_TEXTURE_MIN_LOD
:
467 case GL_TEXTURE_MAX_LOD
:
468 /* This isn't the most efficient solution but there doesn't appear to
469 * be a nice alternative. Since there's no LOD clamping,
470 * we just have to rely on loading the right subset of mipmap levels
471 * to simulate a clamped LOD.
473 driSwapOutTextureObject( (driTextureObject
*) t
);
483 mgaBindTexture( struct gl_context
*ctx
, GLenum target
,
484 struct gl_texture_object
*tObj
)
486 assert( (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_RECTANGLE_NV
) ||
487 (tObj
->DriverData
!= NULL
) );
492 mgaDeleteTexture( struct gl_context
*ctx
, struct gl_texture_object
*tObj
)
494 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
495 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
499 FLUSH_BATCH( mmesa
);
502 driDestroyTextureObject( t
);
505 /* Free mipmap images and the texture object itself */
506 _mesa_delete_texture_object(ctx
, tObj
);
511 * Allocate a new texture object.
512 * Called via ctx->Driver.NewTextureObject.
513 * Note: this function will be called during context creation to
514 * allocate the default texture objects.
515 * Note: we could use containment here to 'derive' the driver-specific
516 * texture object from the core mesa gl_texture_object. Not done at this time.
518 static struct gl_texture_object
*
519 mgaNewTextureObject( struct gl_context
*ctx
, GLuint name
, GLenum target
)
521 struct gl_texture_object
*obj
;
522 obj
= _mesa_new_texture_object(ctx
, name
, target
);
523 mgaAllocTexObj( obj
);
529 mgaInitTextureFuncs( struct dd_function_table
*functions
)
531 functions
->ChooseTextureFormat
= mgaChooseTextureFormat
;
532 functions
->TexImage2D
= mgaTexImage2D
;
533 functions
->TexSubImage2D
= mgaTexSubImage2D
;
534 functions
->BindTexture
= mgaBindTexture
;
535 functions
->NewTextureObject
= mgaNewTextureObject
;
536 functions
->DeleteTexture
= mgaDeleteTexture
;
537 functions
->IsTextureResident
= driIsTextureResident
;
538 functions
->TexEnv
= mgaTexEnv
;
539 functions
->TexParameter
= mgaTexParameter
;