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;