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