fix _SOLO build problem
[mesa.git] / src / mesa / drivers / dri / mga / mgatex.c
1 /*
2 * Copyright 2000-2001 VA Linux Systems, Inc.
3 * All Rights Reserved.
4 *
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:
11 *
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
14 * Software.
15 *
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.
23 *
24 * Authors:
25 * Keith Whitwell <keith@tungstengraphics.com>
26 */
27 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatex.c,v 1.14 2002/10/30 12:51:36 alanh Exp $ */
28
29 #include "glheader.h"
30 #include "mm.h"
31 #include "mgacontext.h"
32 #include "mgatex.h"
33 #include "mgaregs.h"
34 #include "mgatris.h"
35 #include "mgaioctl.h"
36
37 #include "colormac.h"
38 #include "context.h"
39 #include "enums.h"
40 #include "simple_list.h"
41 #include "imports.h"
42 #include "macros.h"
43 #include "texformat.h"
44 #include "texstore.h"
45 #include "teximage.h"
46
47 #include "swrast/swrast.h"
48
49 #include "xmlpool.h"
50
51 /**
52 * Set the texture wrap modes.
53 * Currently \c GL_REPEAT, \c GL_CLAMP and \c GL_CLAMP_TO_EDGE are supported.
54 *
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
58 */
59
60 static void
61 mgaSetTexWrapping( mgaTextureObjectPtr t, GLenum swrap, GLenum twrap )
62 {
63 GLboolean is_clamp = GL_FALSE;
64 GLboolean is_clamp_to_edge = GL_FALSE;
65
66 t->setup.texctl &= (TMC_clampu_MASK & TMC_clampv_MASK);
67 t->setup.texctl2 &= (TMC_borderen_MASK);
68
69 switch( swrap ) {
70 case GL_REPEAT:
71 break;
72 case GL_CLAMP:
73 t->setup.texctl |= TMC_clampu_enable;
74 is_clamp = GL_TRUE;
75 break;
76 case GL_CLAMP_TO_EDGE:
77 t->setup.texctl |= TMC_clampu_enable;
78 is_clamp_to_edge = GL_TRUE;
79 break;
80 default:
81 _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
82 }
83
84 switch( twrap ) {
85 case GL_REPEAT:
86 break;
87 case GL_CLAMP:
88 t->setup.texctl |= TMC_clampv_enable;
89 is_clamp = GL_TRUE;
90 break;
91 case GL_CLAMP_TO_EDGE:
92 t->setup.texctl |= TMC_clampv_enable;
93 is_clamp_to_edge = GL_TRUE;
94 break;
95 default:
96 _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
97 }
98
99 if ( is_clamp ) {
100 t->setup.texctl2 |= TMC_borderen_enable;
101 }
102
103 t->border_fallback = (is_clamp && is_clamp_to_edge);
104 }
105
106
107 /**
108 * Set the texture magnification and minification modes.
109 *
110 * \param t Texture whose filter modes are to be set
111 * \param minf Texture minification mode
112 * \param magf Texture magnification mode
113 */
114
115 static void
116 mgaSetTexFilter( mgaTextureObjectPtr t, GLenum minf, GLenum magf )
117 {
118 GLuint val = 0;
119
120 switch (minf) {
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;
128 }
129
130 switch (magf) {
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;
134 }
135
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 */
140 } else {
141 val |= MGA_FIELD( TF_fthres, 0x10 ); /* c = 0 */
142 }
143
144
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.
148 */
149
150 t->setup.texfilter &= (TF_minfilter_MASK &
151 TF_magfilter_MASK &
152 TF_fthres_MASK);
153 t->setup.texfilter |= val;
154 }
155
156 static void mgaSetTexBorderColor(mgaTextureObjectPtr t, GLubyte color[4])
157 {
158 t->setup.texbordercol = PACK_COLOR_8888(color[3], color[0],
159 color[1], color[2] );
160 }
161
162
163 static const struct gl_texture_format *
164 mgaChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
165 GLenum format, GLenum type )
166 {
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 );
172 (void) format;
173
174 switch ( internalFormat ) {
175 case 4:
176 case GL_RGBA:
177 case GL_COMPRESSED_RGBA:
178 switch ( type ) {
179 case GL_UNSIGNED_INT_10_10_10_2:
180 case GL_UNSIGNED_INT_2_10_10_10_REV:
181 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555;
182 case GL_UNSIGNED_SHORT_4_4_4_4:
183 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
184 return &_mesa_texformat_argb4444;
185 case GL_UNSIGNED_SHORT_5_5_5_1:
186 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
187 return &_mesa_texformat_argb1555;
188 default:
189 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
190 }
191
192 case 3:
193 case GL_RGB:
194 case GL_COMPRESSED_RGB:
195 switch ( type ) {
196 case GL_UNSIGNED_SHORT_4_4_4_4:
197 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
198 return &_mesa_texformat_argb4444;
199 case GL_UNSIGNED_SHORT_5_5_5_1:
200 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
201 return &_mesa_texformat_argb1555;
202 case GL_UNSIGNED_SHORT_5_6_5:
203 case GL_UNSIGNED_SHORT_5_6_5_REV:
204 return &_mesa_texformat_rgb565;
205 default:
206 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
207 }
208
209 case GL_RGBA8:
210 case GL_RGB10_A2:
211 case GL_RGBA12:
212 case GL_RGBA16:
213 return !force16bpt ?
214 &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
215
216 case GL_RGBA4:
217 case GL_RGBA2:
218 return &_mesa_texformat_argb4444;
219
220 case GL_RGB5_A1:
221 return &_mesa_texformat_argb1555;
222
223 case GL_RGB8:
224 case GL_RGB10:
225 case GL_RGB12:
226 case GL_RGB16:
227 return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
228
229 case GL_RGB5:
230 case GL_RGB4:
231 case GL_R3_G3_B2:
232 return &_mesa_texformat_rgb565;
233
234 case GL_ALPHA:
235 case GL_ALPHA4:
236 case GL_ALPHA8:
237 case GL_ALPHA12:
238 case GL_ALPHA16:
239 case GL_COMPRESSED_ALPHA:
240 /* FIXME: This will report incorrect component sizes... */
241 return MGA_IS_G400(mmesa) ? &_mesa_texformat_al88 : &_mesa_texformat_argb4444;
242
243 case 1:
244 case GL_LUMINANCE:
245 case GL_LUMINANCE4:
246 case GL_LUMINANCE8:
247 case GL_LUMINANCE12:
248 case GL_LUMINANCE16:
249 case GL_COMPRESSED_LUMINANCE:
250 /* FIXME: This will report incorrect component sizes... */
251 return MGA_IS_G400(mmesa) ? &_mesa_texformat_al88 : &_mesa_texformat_rgb565;
252
253 case 2:
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_texformat_al88 : &_mesa_texformat_argb4444;
264
265 case GL_INTENSITY:
266 case GL_INTENSITY4:
267 case GL_INTENSITY8:
268 case GL_INTENSITY12:
269 case GL_INTENSITY16:
270 case GL_COMPRESSED_INTENSITY:
271 /* FIXME: This will report incorrect component sizes... */
272 return MGA_IS_G400(mmesa) ? &_mesa_texformat_i8 : &_mesa_texformat_argb4444;
273
274 case GL_YCBCR_MESA:
275 if (MGA_IS_G400(mmesa) &&
276 (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
277 type == GL_UNSIGNED_BYTE))
278 return &_mesa_texformat_ycbcr;
279 else
280 return &_mesa_texformat_ycbcr_rev;
281
282 case GL_COLOR_INDEX:
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_texformat_ci8;
290
291 default:
292 _mesa_problem( ctx, "unexpected texture format in %s", __FUNCTION__ );
293 return NULL;
294 }
295
296 return NULL; /* never get here */
297 }
298
299
300
301
302 /**
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.
306 */
307
308 static mgaTextureObjectPtr
309 mgaAllocTexObj( struct gl_texture_object *tObj )
310 {
311 mgaTextureObjectPtr t;
312
313
314 t = CALLOC( sizeof( *t ) );
315 tObj->DriverData = t;
316 if ( t != NULL ) {
317 /* Initialize non-image-dependent parts of the state:
318 */
319 t->base.tObj = tObj;
320
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;
324
325 t->border_fallback = GL_FALSE;
326 t->texenv_fallback = GL_FALSE;
327
328 make_empty_list( & t->base );
329
330 mgaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
331 mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
332 mgaSetTexBorderColor( t, tObj->_BorderChan );
333 }
334
335 return( t );
336 }
337
338
339 static void mgaDDTexEnv( GLcontext *ctx, GLenum target,
340 GLenum pname, const GLfloat *param )
341 {
342 GLuint unit = ctx->Texture.CurrentUnit;
343 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
344 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
345
346 switch( pname ) {
347 case GL_TEXTURE_ENV_COLOR: {
348 GLubyte c[4];
349
350 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
351 mmesa->envcolor[unit] = PACK_COLOR_8888( c[3], c[0], c[1], c[2] );
352 break;
353 }
354 }
355 }
356
357
358 static void mgaTexImage2D( GLcontext *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 )
365 {
366 driTextureObject * t = (driTextureObject *) texObj->DriverData;
367
368
369 if ( t != NULL ) {
370 driSwapOutTextureObject( t );
371 }
372 else {
373 t = (driTextureObject *) mgaAllocTexObj( texObj );
374 if ( t == NULL ) {
375 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" );
376 return;
377 }
378 }
379
380 _mesa_store_teximage2d( ctx, target, level, internalFormat,
381 width, height, border, format, type,
382 pixels, packing, texObj, texImage );
383 level -= t->firstLevel;
384 if (level >= 0)
385 t->dirty_images[0] |= (1UL << level);
386 }
387
388 static void mgaTexSubImage2D( GLcontext *ctx,
389 GLenum target,
390 GLint level,
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 )
398 {
399 driTextureObject * t = (driTextureObject *) texObj->DriverData;
400
401
402 assert( t != NULL ); /* this _should_ be true */
403 if ( t != NULL ) {
404 driSwapOutTextureObject( t );
405 }
406 else {
407 t = (driTextureObject *) mgaAllocTexObj( texObj );
408 if ( t == NULL ) {
409 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" );
410 return;
411 }
412 }
413
414 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
415 height, format, type, pixels, packing, texObj,
416 texImage);
417 level -= t->firstLevel;
418 if (level >= 0)
419 t->dirty_images[0] |= (1UL << level);
420 }
421
422
423 /**
424 * Changes variables and flags for a state update, which will happen at the
425 * next UpdateTextureState
426 */
427
428 static void
429 mgaDDTexParameter( GLcontext *ctx, GLenum target,
430 struct gl_texture_object *tObj,
431 GLenum pname, const GLfloat *params )
432 {
433 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
434 mgaTextureObjectPtr t;
435
436 t = (mgaTextureObjectPtr) tObj->DriverData;
437
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
440 * to do anything now
441 */
442
443 if ( (t == NULL) ||
444 (target != GL_TEXTURE_2D &&
445 target != GL_TEXTURE_RECTANGLE_NV) ) {
446 return;
447 }
448
449 switch (pname) {
450 case GL_TEXTURE_MIN_FILTER:
451 driSwapOutTextureObject( (driTextureObject *) t );
452 /* FALLTHROUGH */
453 case GL_TEXTURE_MAG_FILTER:
454 FLUSH_BATCH(mmesa);
455 mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
456 break;
457
458 case GL_TEXTURE_WRAP_S:
459 case GL_TEXTURE_WRAP_T:
460 FLUSH_BATCH(mmesa);
461 mgaSetTexWrapping(t,tObj->WrapS,tObj->WrapT);
462 break;
463
464 case GL_TEXTURE_BORDER_COLOR:
465 FLUSH_BATCH(mmesa);
466 mgaSetTexBorderColor(t, tObj->_BorderChan);
467 break;
468
469 case GL_TEXTURE_BASE_LEVEL:
470 case GL_TEXTURE_MAX_LEVEL:
471 case GL_TEXTURE_MIN_LOD:
472 case GL_TEXTURE_MAX_LOD:
473 /* This isn't the most efficient solution but there doesn't appear to
474 * be a nice alternative. Since there's no LOD clamping,
475 * we just have to rely on loading the right subset of mipmap levels
476 * to simulate a clamped LOD.
477 */
478 driSwapOutTextureObject( (driTextureObject *) t );
479 break;
480
481 default:
482 return;
483 }
484 }
485
486
487 static void
488 mgaDDBindTexture( GLcontext *ctx, GLenum target,
489 struct gl_texture_object *tObj )
490 {
491 if ( target == GL_TEXTURE_2D ||
492 target == GL_TEXTURE_RECTANGLE_NV ) {
493 if ( tObj->DriverData == NULL ) {
494 mgaAllocTexObj( tObj );
495 }
496 }
497 }
498
499
500 static void
501 mgaDDDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
502 {
503 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
504 driTextureObject * t = (driTextureObject *) tObj->DriverData;
505
506 if ( t ) {
507 if ( mmesa ) {
508 FLUSH_BATCH( mmesa );
509 }
510
511 driDestroyTextureObject( t );
512 }
513 }
514
515
516 void
517 mgaDDInitTextureFuncs( GLcontext *ctx )
518 {
519 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
520
521
522 ctx->Driver.ChooseTextureFormat = mgaChooseTextureFormat;
523 ctx->Driver.TexImage1D = _mesa_store_teximage1d;
524 ctx->Driver.TexImage2D = mgaTexImage2D;
525 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
526 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
527 ctx->Driver.TexSubImage2D = mgaTexSubImage2D;
528 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
529 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
530 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
531 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
532 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
533 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
534 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
535
536 ctx->Driver.BindTexture = mgaDDBindTexture;
537 ctx->Driver.CreateTexture = NULL; /* FIXME: Is this used??? */
538 ctx->Driver.DeleteTexture = mgaDDDeleteTexture;
539 ctx->Driver.IsTextureResident = driIsTextureResident;
540 ctx->Driver.PrioritizeTexture = NULL;
541 ctx->Driver.ActiveTexture = NULL;
542 ctx->Driver.UpdateTexturePalette = NULL;
543
544 ctx->Driver.TexEnv = mgaDDTexEnv;
545 ctx->Driver.TexParameter = mgaDDTexParameter;
546
547 driInitTextureObjects( ctx, & mmesa->swapped,
548 (DRI_TEXMGR_DO_TEXTURE_2D |
549 DRI_TEXMGR_DO_TEXTURE_RECT) );
550 }