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