remove bogus assertion in DeleteTexture() function
[mesa.git] / src / mesa / drivers / dri / r128 / r128_tex.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.14 2002/11/05 17:46:08 tsi Exp $ */
2 /**************************************************************************
3
4 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
5 Cedar Park, Texas.
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Gareth Hughes <gareth@valinux.com>
32 * Kevin E. Martin <martin@valinux.com>
33 * Brian Paul <brianp@valinux.com>
34 */
35
36 #include "r128_context.h"
37 #include "r128_state.h"
38 #include "r128_ioctl.h"
39 #include "r128_vb.h"
40 #include "r128_tris.h"
41 #include "r128_tex.h"
42 #include "r128_texobj.h"
43
44 #include "context.h"
45 #include "macros.h"
46 #include "simple_list.h"
47 #include "enums.h"
48 #include "texstore.h"
49 #include "texformat.h"
50 #include "teximage.h"
51 #include "imports.h"
52 #include "colormac.h"
53 #include "texobj.h"
54
55 #include "xmlpool.h"
56
57 #define TEX_0 1
58 #define TEX_1 2
59
60
61 /**
62 * Set the texture wrap modes. Currently \c GL_REPEAT, \c GL_CLAMP,
63 * \c GL_CLAMP_TO_EDGE, and \c GL_MIRRORED_REPEAT are supported.
64 *
65 * \param t Texture object whose wrap modes are to be set
66 * \param swrap Wrap mode for the \a s texture coordinate
67 * \param twrap Wrap mode for the \a t texture coordinate
68 */
69 static void r128SetTexWrap( r128TexObjPtr t, GLenum swrap, GLenum twrap )
70 {
71 t->setup.tex_cntl &= ~(R128_TEX_CLAMP_S_MASK | R128_TEX_CLAMP_T_MASK);
72
73 switch ( swrap ) {
74 case GL_CLAMP:
75 t->setup.tex_cntl |= R128_TEX_CLAMP_S_BORDER_COLOR;
76 break;
77 case GL_CLAMP_TO_EDGE:
78 t->setup.tex_cntl |= R128_TEX_CLAMP_S_CLAMP;
79 break;
80 case GL_REPEAT:
81 t->setup.tex_cntl |= R128_TEX_CLAMP_S_WRAP;
82 break;
83 case GL_MIRRORED_REPEAT:
84 t->setup.tex_cntl |= R128_TEX_CLAMP_S_MIRROR;
85 break;
86 }
87
88 switch ( twrap ) {
89 case GL_CLAMP:
90 t->setup.tex_cntl |= R128_TEX_CLAMP_T_BORDER_COLOR;
91 break;
92 case GL_CLAMP_TO_EDGE:
93 t->setup.tex_cntl |= R128_TEX_CLAMP_T_CLAMP;
94 break;
95 case GL_REPEAT:
96 t->setup.tex_cntl |= R128_TEX_CLAMP_T_WRAP;
97 break;
98 case GL_MIRRORED_REPEAT:
99 t->setup.tex_cntl |= R128_TEX_CLAMP_T_MIRROR;
100 break;
101 }
102 }
103
104 static void r128SetTexFilter( r128TexObjPtr t, GLenum minf, GLenum magf )
105 {
106 t->setup.tex_cntl &= ~(R128_MIN_BLEND_MASK | R128_MAG_BLEND_MASK);
107
108 switch ( minf ) {
109 case GL_NEAREST:
110 t->setup.tex_cntl |= R128_MIN_BLEND_NEAREST;
111 break;
112 case GL_LINEAR:
113 t->setup.tex_cntl |= R128_MIN_BLEND_LINEAR;
114 break;
115 case GL_NEAREST_MIPMAP_NEAREST:
116 t->setup.tex_cntl |= R128_MIN_BLEND_MIPNEAREST;
117 break;
118 case GL_LINEAR_MIPMAP_NEAREST:
119 t->setup.tex_cntl |= R128_MIN_BLEND_MIPLINEAR;
120 break;
121 case GL_NEAREST_MIPMAP_LINEAR:
122 t->setup.tex_cntl |= R128_MIN_BLEND_LINEARMIPNEAREST;
123 break;
124 case GL_LINEAR_MIPMAP_LINEAR:
125 t->setup.tex_cntl |= R128_MIN_BLEND_LINEARMIPLINEAR;
126 break;
127 }
128
129 switch ( magf ) {
130 case GL_NEAREST:
131 t->setup.tex_cntl |= R128_MAG_BLEND_NEAREST;
132 break;
133 case GL_LINEAR:
134 t->setup.tex_cntl |= R128_MAG_BLEND_LINEAR;
135 break;
136 }
137 }
138
139 static void r128SetTexBorderColor( r128TexObjPtr t, GLubyte c[4] )
140 {
141 t->setup.tex_border_color = r128PackColor( 4, c[0], c[1], c[2], c[3] );
142 }
143
144
145 static r128TexObjPtr r128AllocTexObj( struct gl_texture_object *texObj )
146 {
147 r128TexObjPtr t;
148
149 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
150 fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj );
151 }
152
153 t = (r128TexObjPtr) CALLOC_STRUCT( r128_tex_obj );
154 texObj->DriverData = t;
155 if ( t != NULL ) {
156
157 /* Initialize non-image-dependent parts of the state:
158 */
159 t->base.tObj = texObj;
160
161 /* FIXME Something here to set initial values for other parts of
162 * FIXME t->setup?
163 */
164
165 make_empty_list( (driTextureObject *) t );
166
167 r128SetTexWrap( t, texObj->WrapS, texObj->WrapT );
168 r128SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
169 r128SetTexBorderColor( t, texObj->_BorderChan );
170 }
171
172 return t;
173 }
174
175
176 /* Called by the _mesa_store_teximage[123]d() functions. */
177 static const struct gl_texture_format *
178 r128ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
179 GLenum format, GLenum type )
180 {
181 r128ContextPtr rmesa = R128_CONTEXT(ctx);
182 const GLboolean do32bpt =
183 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
184 const GLboolean force16bpt =
185 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
186 (void) format;
187 (void) type;
188
189 switch ( internalFormat ) {
190 /* non-sized formats with alpha */
191 case GL_INTENSITY:
192 case GL_COMPRESSED_INTENSITY:
193 case GL_ALPHA:
194 case GL_COMPRESSED_ALPHA:
195 case 2:
196 case GL_LUMINANCE_ALPHA:
197 case GL_COMPRESSED_LUMINANCE_ALPHA:
198 case 4:
199 case GL_RGBA:
200 case GL_COMPRESSED_RGBA:
201 if (do32bpt)
202 return &_mesa_texformat_argb8888;
203 else
204 return &_mesa_texformat_argb4444;
205
206 /* 16-bit formats with alpha */
207 case GL_INTENSITY4:
208 case GL_ALPHA4:
209 case GL_LUMINANCE4_ALPHA4:
210 case GL_RGBA2:
211 case GL_RGBA4:
212 return &_mesa_texformat_argb4444;
213
214 /* 32-bit formats with alpha */
215 case GL_INTENSITY8:
216 case GL_INTENSITY12:
217 case GL_INTENSITY16:
218 case GL_ALPHA8:
219 case GL_ALPHA12:
220 case GL_ALPHA16:
221 case GL_LUMINANCE6_ALPHA2:
222 case GL_LUMINANCE8_ALPHA8:
223 case GL_LUMINANCE12_ALPHA4:
224 case GL_LUMINANCE12_ALPHA12:
225 case GL_LUMINANCE16_ALPHA16:
226 case GL_RGB5_A1:
227 case GL_RGBA8:
228 case GL_RGB10_A2:
229 case GL_RGBA12:
230 case GL_RGBA16:
231 if (!force16bpt)
232 return &_mesa_texformat_argb8888;
233 else
234 return &_mesa_texformat_argb4444;
235
236 /* non-sized formats without alpha */
237 case 1:
238 case GL_LUMINANCE:
239 case GL_COMPRESSED_LUMINANCE:
240 case 3:
241 case GL_RGB:
242 case GL_COMPRESSED_RGB:
243 if (do32bpt)
244 return &_mesa_texformat_argb8888;
245 else
246 return &_mesa_texformat_rgb565;
247
248 /* 16-bit formats without alpha */
249 case GL_LUMINANCE4:
250 case GL_R3_G3_B2:
251 case GL_RGB4:
252 case GL_RGB5:
253 return &_mesa_texformat_rgb565;
254
255 /* 32-bit formats without alpha */
256 case GL_LUMINANCE8:
257 case GL_LUMINANCE12:
258 case GL_LUMINANCE16:
259 case GL_RGB8:
260 case GL_RGB10:
261 case GL_RGB12:
262 case GL_RGB16:
263 if (!force16bpt)
264 return &_mesa_texformat_argb8888;
265 else
266 return &_mesa_texformat_rgb565;
267
268 /* color-indexed formats */
269 case GL_COLOR_INDEX:
270 case GL_COLOR_INDEX1_EXT:
271 case GL_COLOR_INDEX2_EXT:
272 case GL_COLOR_INDEX4_EXT:
273 case GL_COLOR_INDEX8_EXT:
274 case GL_COLOR_INDEX12_EXT:
275 case GL_COLOR_INDEX16_EXT:
276 return &_mesa_texformat_ci8;
277
278 case GL_YCBCR_MESA:
279 if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
280 type == GL_UNSIGNED_BYTE)
281 return &_mesa_texformat_ycbcr;
282 else
283 return &_mesa_texformat_ycbcr_rev;
284
285 default:
286 _mesa_problem( ctx, "unexpected format in %s", __FUNCTION__ );
287 return NULL;
288 }
289 }
290
291
292 static void r128TexImage1D( GLcontext *ctx, GLenum target, GLint level,
293 GLint internalFormat,
294 GLint width, GLint border,
295 GLenum format, GLenum type, const GLvoid *pixels,
296 const struct gl_pixelstore_attrib *packing,
297 struct gl_texture_object *texObj,
298 struct gl_texture_image *texImage )
299 {
300 driTextureObject * t = (driTextureObject *) texObj->DriverData;
301
302 if ( t ) {
303 driSwapOutTextureObject( t );
304 }
305 else {
306 t = (driTextureObject *) r128AllocTexObj(texObj);
307 if (!t) {
308 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
309 return;
310 }
311 }
312
313 /* Note, this will call r128ChooseTextureFormat */
314 _mesa_store_teximage1d( ctx, target, level, internalFormat,
315 width, border, format, type,
316 pixels, packing, texObj, texImage );
317
318 t->dirty_images[0] |= (1 << level);
319 }
320
321
322 static void r128TexSubImage1D( GLcontext *ctx,
323 GLenum target,
324 GLint level,
325 GLint xoffset,
326 GLsizei width,
327 GLenum format, GLenum type,
328 const GLvoid *pixels,
329 const struct gl_pixelstore_attrib *packing,
330 struct gl_texture_object *texObj,
331 struct gl_texture_image *texImage )
332 {
333 driTextureObject * t = (driTextureObject *) texObj->DriverData;
334
335 assert( t ); /* this _should_ be true */
336 if ( t ) {
337 driSwapOutTextureObject( t );
338 }
339 else {
340 t = (driTextureObject *) r128AllocTexObj(texObj);
341 if (!t) {
342 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
343 return;
344 }
345 }
346
347 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
348 format, type, pixels, packing, texObj,
349 texImage);
350
351 t->dirty_images[0] |= (1 << level);
352 }
353
354
355 static void r128TexImage2D( GLcontext *ctx, GLenum target, GLint level,
356 GLint internalFormat,
357 GLint width, GLint height, GLint border,
358 GLenum format, GLenum type, const GLvoid *pixels,
359 const struct gl_pixelstore_attrib *packing,
360 struct gl_texture_object *texObj,
361 struct gl_texture_image *texImage )
362 {
363 driTextureObject * t = (driTextureObject *) texObj->DriverData;
364
365 if ( t ) {
366 driSwapOutTextureObject( (driTextureObject *) t );
367 }
368 else {
369 t = (driTextureObject *) r128AllocTexObj(texObj);
370 if (!t) {
371 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
372 return;
373 }
374 }
375
376 /* Note, this will call r128ChooseTextureFormat */
377 _mesa_store_teximage2d(ctx, target, level, internalFormat,
378 width, height, border, format, type, pixels,
379 &ctx->Unpack, texObj, texImage);
380
381 t->dirty_images[0] |= (1 << level);
382 }
383
384
385 static void r128TexSubImage2D( GLcontext *ctx,
386 GLenum target,
387 GLint level,
388 GLint xoffset, GLint yoffset,
389 GLsizei width, GLsizei height,
390 GLenum format, GLenum type,
391 const GLvoid *pixels,
392 const struct gl_pixelstore_attrib *packing,
393 struct gl_texture_object *texObj,
394 struct gl_texture_image *texImage )
395 {
396 driTextureObject * t = (driTextureObject *) texObj->DriverData;
397
398 assert( t ); /* this _should_ be true */
399 if ( t ) {
400 driSwapOutTextureObject( t );
401 }
402 else {
403 t = (driTextureObject *) r128AllocTexObj(texObj);
404 if (!t) {
405 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
406 return;
407 }
408 }
409
410 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
411 height, format, type, pixels, packing, texObj,
412 texImage);
413 t->dirty_images[0] |= (1 << level);
414 }
415
416
417 static void r128TexEnv( GLcontext *ctx, GLenum target,
418 GLenum pname, const GLfloat *param )
419 {
420 r128ContextPtr rmesa = R128_CONTEXT(ctx);
421 struct gl_texture_unit *texUnit;
422 GLubyte c[4];
423
424 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
425 fprintf( stderr, "%s( %s )\n",
426 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
427 }
428
429 switch ( pname ) {
430 case GL_TEXTURE_ENV_MODE:
431 FLUSH_BATCH( rmesa );
432 rmesa->new_state |= R128_NEW_ALPHA;
433 break;
434
435 case GL_TEXTURE_ENV_COLOR:
436 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
437 CLAMPED_FLOAT_TO_UBYTE( c[0], texUnit->EnvColor[0] );
438 CLAMPED_FLOAT_TO_UBYTE( c[1], texUnit->EnvColor[1] );
439 CLAMPED_FLOAT_TO_UBYTE( c[2], texUnit->EnvColor[2] );
440 CLAMPED_FLOAT_TO_UBYTE( c[3], texUnit->EnvColor[3] );
441 rmesa->env_color = r128PackColor( 4, c[0], c[1], c[2], c[3] );
442 if ( rmesa->setup.constant_color_c != rmesa->env_color ) {
443 FLUSH_BATCH( rmesa );
444 rmesa->setup.constant_color_c = rmesa->env_color;
445
446 /* More complex multitexture/multipass fallbacks for GL_BLEND
447 * can be done later, but this allows a single pass GL_BLEND
448 * in some cases (ie. Performer town demo). This is only
449 * applicable to the regular Rage 128, as the Pro and M3 can
450 * handle true single-pass GL_BLEND texturing.
451 */
452 rmesa->blend_flags &= ~R128_BLEND_ENV_COLOR;
453 if ( R128_IS_PLAIN( rmesa ) &&
454 rmesa->env_color != 0x00000000 &&
455 rmesa->env_color != 0xff000000 &&
456 rmesa->env_color != 0x00ffffff &&
457 rmesa->env_color != 0xffffffff ) {
458 rmesa->blend_flags |= R128_BLEND_ENV_COLOR;
459 }
460 }
461 break;
462
463 case GL_TEXTURE_LOD_BIAS:
464 {
465 CARD32 t = rmesa->setup.tex_cntl_c;
466 GLint bias;
467 CARD32 b;
468
469 /* GTH: This isn't exactly correct, but gives good results up to a
470 * certain point. It is better than completely ignoring the LOD
471 * bias. Unfortunately there isn't much range in the bias, the
472 * spec mentions strides that vary between 0.5 and 2.0 but these
473 * numbers don't seem to relate the the GL LOD bias value at all.
474 */
475 if ( param[0] >= 1.0 ) {
476 bias = -128;
477 } else if ( param[0] >= 0.5 ) {
478 bias = -64;
479 } else if ( param[0] >= 0.25 ) {
480 bias = 0;
481 } else if ( param[0] >= 0.0 ) {
482 bias = 63;
483 } else {
484 bias = 127;
485 }
486
487 b = (CARD32)bias & 0xff;
488 t &= ~R128_LOD_BIAS_MASK;
489 t |= (b << R128_LOD_BIAS_SHIFT);
490
491 if ( rmesa->setup.tex_cntl_c != t ) {
492 FLUSH_BATCH( rmesa );
493 rmesa->setup.tex_cntl_c = t;
494 rmesa->dirty |= R128_UPLOAD_CONTEXT;
495 }
496 }
497 break;
498
499 default:
500 return;
501 }
502 }
503
504
505 static void r128TexParameter( GLcontext *ctx, GLenum target,
506 struct gl_texture_object *tObj,
507 GLenum pname, const GLfloat *params )
508 {
509 r128ContextPtr rmesa = R128_CONTEXT(ctx);
510 r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData;
511
512 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
513 fprintf( stderr, "%s( %s )\n",
514 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
515 }
516
517 if ( ( target != GL_TEXTURE_2D ) && ( target != GL_TEXTURE_1D ) )
518 return;
519
520 switch ( pname ) {
521 case GL_TEXTURE_MIN_FILTER:
522 case GL_TEXTURE_MAG_FILTER:
523 if ( t->base.bound ) FLUSH_BATCH( rmesa );
524 r128SetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
525 break;
526
527 case GL_TEXTURE_WRAP_S:
528 case GL_TEXTURE_WRAP_T:
529 if ( t->base.bound ) FLUSH_BATCH( rmesa );
530 r128SetTexWrap( t, tObj->WrapS, tObj->WrapT );
531 break;
532
533 case GL_TEXTURE_BORDER_COLOR:
534 if ( t->base.bound ) FLUSH_BATCH( rmesa );
535 r128SetTexBorderColor( t, tObj->_BorderChan );
536 break;
537
538 case GL_TEXTURE_BASE_LEVEL:
539 case GL_TEXTURE_MAX_LEVEL:
540 case GL_TEXTURE_MIN_LOD:
541 case GL_TEXTURE_MAX_LOD:
542 /* This isn't the most efficient solution but there doesn't appear to
543 * be a nice alternative for R128. Since there's no LOD clamping,
544 * we just have to rely on loading the right subset of mipmap levels
545 * to simulate a clamped LOD.
546 */
547 if ( t->base.bound ) FLUSH_BATCH( rmesa );
548 driSwapOutTextureObject( (driTextureObject *) t );
549 break;
550
551 default:
552 return;
553 }
554 }
555
556 static void r128BindTexture( GLcontext *ctx, GLenum target,
557 struct gl_texture_object *tObj )
558 {
559 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
560 fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, tObj,
561 ctx->Texture.CurrentUnit );
562 }
563
564 assert( (target != GL_TEXTURE_2D && target != GL_TEXTURE_1D) ||
565 (tObj->DriverData != NULL) );
566 }
567
568
569 static void r128DeleteTexture( GLcontext *ctx,
570 struct gl_texture_object *tObj )
571 {
572 r128ContextPtr rmesa = R128_CONTEXT(ctx);
573 driTextureObject * t = (driTextureObject *) tObj->DriverData;
574
575 if ( t ) {
576 if ( t->bound && rmesa ) {
577 FLUSH_BATCH( rmesa );
578 }
579
580 driDestroyTextureObject( t );
581 }
582 /* Free mipmap images and the texture object itself */
583 _mesa_delete_texture_object(ctx, tObj);
584 }
585
586 /**
587 * Allocate a new texture object.
588 * Called via ctx->Driver.NewTextureObject.
589 * Note: we could use containment here to 'derive' the driver-specific
590 * texture object from the core mesa gl_texture_object. Not done at this time.
591 */
592 static struct gl_texture_object *
593 r128NewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
594 {
595 struct gl_texture_object *obj;
596 obj = _mesa_new_texture_object(ctx, name, target);
597 r128AllocTexObj( obj );
598 return obj;
599 }
600
601 void r128InitTextureFuncs( struct dd_function_table *functions )
602 {
603 functions->TexEnv = r128TexEnv;
604 functions->ChooseTextureFormat = r128ChooseTextureFormat;
605 functions->TexImage1D = r128TexImage1D;
606 functions->TexSubImage1D = r128TexSubImage1D;
607 functions->TexImage2D = r128TexImage2D;
608 functions->TexSubImage2D = r128TexSubImage2D;
609 functions->TexParameter = r128TexParameter;
610 functions->BindTexture = r128BindTexture;
611 functions->NewTextureObject = r128NewTextureObject;
612 functions->DeleteTexture = r128DeleteTexture;
613 functions->IsTextureResident = driIsTextureResident;
614 }
615