i965: fix bugs in projective texture coordinates
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_tex.c
1 /*
2 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
3 VA Linux Systems Inc., Fremont, California.
4
5 All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice (including the
16 next paragraph) shall be included in all copies or substantial
17 portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
23 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28 /*
29 * Authors:
30 * Gareth Hughes <gareth@valinux.com>
31 * Brian Paul <brianp@valinux.com>
32 */
33
34 #include "main/glheader.h"
35 #include "main/imports.h"
36 #include "main/colormac.h"
37 #include "main/context.h"
38 #include "main/enums.h"
39 #include "main/image.h"
40 #include "main/simple_list.h"
41 #include "main/texformat.h"
42 #include "main/texstore.h"
43 #include "main/teximage.h"
44 #include "main/texobj.h"
45
46 #include "radeon_context.h"
47 #include "radeon_state.h"
48 #include "radeon_ioctl.h"
49 #include "radeon_swtcl.h"
50 #include "radeon_tex.h"
51
52 #include "xmlpool.h"
53
54
55
56 /**
57 * Set the texture wrap modes.
58 *
59 * \param t Texture object whose wrap modes are to be set
60 * \param swrap Wrap mode for the \a s texture coordinate
61 * \param twrap Wrap mode for the \a t texture coordinate
62 */
63
64 static void radeonSetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap )
65 {
66 GLboolean is_clamp = GL_FALSE;
67 GLboolean is_clamp_to_border = GL_FALSE;
68
69 t->pp_txfilter &= ~(RADEON_CLAMP_S_MASK | RADEON_CLAMP_T_MASK | RADEON_BORDER_MODE_D3D);
70
71 switch ( swrap ) {
72 case GL_REPEAT:
73 t->pp_txfilter |= RADEON_CLAMP_S_WRAP;
74 break;
75 case GL_CLAMP:
76 t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_GL;
77 is_clamp = GL_TRUE;
78 break;
79 case GL_CLAMP_TO_EDGE:
80 t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST;
81 break;
82 case GL_CLAMP_TO_BORDER:
83 t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_GL;
84 is_clamp_to_border = GL_TRUE;
85 break;
86 case GL_MIRRORED_REPEAT:
87 t->pp_txfilter |= RADEON_CLAMP_S_MIRROR;
88 break;
89 case GL_MIRROR_CLAMP_EXT:
90 t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_GL;
91 is_clamp = GL_TRUE;
92 break;
93 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
94 t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_LAST;
95 break;
96 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
97 t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_GL;
98 is_clamp_to_border = GL_TRUE;
99 break;
100 default:
101 _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
102 }
103
104 switch ( twrap ) {
105 case GL_REPEAT:
106 t->pp_txfilter |= RADEON_CLAMP_T_WRAP;
107 break;
108 case GL_CLAMP:
109 t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_GL;
110 is_clamp = GL_TRUE;
111 break;
112 case GL_CLAMP_TO_EDGE:
113 t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST;
114 break;
115 case GL_CLAMP_TO_BORDER:
116 t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_GL;
117 is_clamp_to_border = GL_TRUE;
118 break;
119 case GL_MIRRORED_REPEAT:
120 t->pp_txfilter |= RADEON_CLAMP_T_MIRROR;
121 break;
122 case GL_MIRROR_CLAMP_EXT:
123 t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_GL;
124 is_clamp = GL_TRUE;
125 break;
126 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
127 t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_LAST;
128 break;
129 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
130 t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_GL;
131 is_clamp_to_border = GL_TRUE;
132 break;
133 default:
134 _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
135 }
136
137 if ( is_clamp_to_border ) {
138 t->pp_txfilter |= RADEON_BORDER_MODE_D3D;
139 }
140
141 t->border_fallback = (is_clamp && is_clamp_to_border);
142 }
143
144 static void radeonSetTexMaxAnisotropy( radeonTexObjPtr t, GLfloat max )
145 {
146 t->pp_txfilter &= ~RADEON_MAX_ANISO_MASK;
147
148 if ( max == 1.0 ) {
149 t->pp_txfilter |= RADEON_MAX_ANISO_1_TO_1;
150 } else if ( max <= 2.0 ) {
151 t->pp_txfilter |= RADEON_MAX_ANISO_2_TO_1;
152 } else if ( max <= 4.0 ) {
153 t->pp_txfilter |= RADEON_MAX_ANISO_4_TO_1;
154 } else if ( max <= 8.0 ) {
155 t->pp_txfilter |= RADEON_MAX_ANISO_8_TO_1;
156 } else {
157 t->pp_txfilter |= RADEON_MAX_ANISO_16_TO_1;
158 }
159 }
160
161 /**
162 * Set the texture magnification and minification modes.
163 *
164 * \param t Texture whose filter modes are to be set
165 * \param minf Texture minification mode
166 * \param magf Texture magnification mode
167 */
168
169 static void radeonSetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf )
170 {
171 GLuint anisotropy = (t->pp_txfilter & RADEON_MAX_ANISO_MASK);
172
173 t->pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK);
174
175 /* r100 chips can't handle mipmaps/aniso for cubemap/volume textures */
176 if ( t->base.tObj->Target == GL_TEXTURE_CUBE_MAP ) {
177 switch ( minf ) {
178 case GL_NEAREST:
179 case GL_NEAREST_MIPMAP_NEAREST:
180 case GL_NEAREST_MIPMAP_LINEAR:
181 t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST;
182 break;
183 case GL_LINEAR:
184 case GL_LINEAR_MIPMAP_NEAREST:
185 case GL_LINEAR_MIPMAP_LINEAR:
186 t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR;
187 break;
188 default:
189 break;
190 }
191 }
192 else if ( anisotropy == RADEON_MAX_ANISO_1_TO_1 ) {
193 switch ( minf ) {
194 case GL_NEAREST:
195 t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST;
196 break;
197 case GL_LINEAR:
198 t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR;
199 break;
200 case GL_NEAREST_MIPMAP_NEAREST:
201 t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST;
202 break;
203 case GL_NEAREST_MIPMAP_LINEAR:
204 t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST;
205 break;
206 case GL_LINEAR_MIPMAP_NEAREST:
207 t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR;
208 break;
209 case GL_LINEAR_MIPMAP_LINEAR:
210 t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR;
211 break;
212 }
213 } else {
214 switch ( minf ) {
215 case GL_NEAREST:
216 t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST;
217 break;
218 case GL_LINEAR:
219 t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_LINEAR;
220 break;
221 case GL_NEAREST_MIPMAP_NEAREST:
222 case GL_LINEAR_MIPMAP_NEAREST:
223 t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
224 break;
225 case GL_NEAREST_MIPMAP_LINEAR:
226 case GL_LINEAR_MIPMAP_LINEAR:
227 t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR;
228 break;
229 }
230 }
231
232 switch ( magf ) {
233 case GL_NEAREST:
234 t->pp_txfilter |= RADEON_MAG_FILTER_NEAREST;
235 break;
236 case GL_LINEAR:
237 t->pp_txfilter |= RADEON_MAG_FILTER_LINEAR;
238 break;
239 }
240 }
241
242 static void radeonSetTexBorderColor( radeonTexObjPtr t, const GLfloat color[4] )
243 {
244 GLubyte c[4];
245 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
246 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
247 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
248 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
249 t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
250 }
251
252
253 /**
254 * Allocate space for and load the mesa images into the texture memory block.
255 * This will happen before drawing with a new texture, or drawing with a
256 * texture after it was swapped out or teximaged again.
257 */
258
259 static radeonTexObjPtr radeonAllocTexObj( struct gl_texture_object *texObj )
260 {
261 radeonTexObjPtr t;
262
263 t = CALLOC_STRUCT( radeon_tex_obj );
264 texObj->DriverData = t;
265 if ( t != NULL ) {
266 if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
267 fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, (void *)texObj, (void *)t );
268 }
269
270 /* Initialize non-image-dependent parts of the state:
271 */
272 t->base.tObj = texObj;
273 t->border_fallback = GL_FALSE;
274
275 t->pp_txfilter = RADEON_BORDER_MODE_OGL;
276 t->pp_txformat = (RADEON_TXFORMAT_ENDIAN_NO_SWAP |
277 RADEON_TXFORMAT_PERSPECTIVE_ENABLE);
278
279 make_empty_list( & t->base );
280
281 radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
282 radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
283 radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
284 radeonSetTexBorderColor( t, texObj->BorderColor );
285 }
286
287 return t;
288 }
289
290
291 static const struct gl_texture_format *
292 radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
293 GLenum format, GLenum type )
294 {
295 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
296 const GLboolean do32bpt =
297 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
298 const GLboolean force16bpt =
299 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
300 (void) format;
301
302 switch ( internalFormat ) {
303 case 4:
304 case GL_RGBA:
305 case GL_COMPRESSED_RGBA:
306 switch ( type ) {
307 case GL_UNSIGNED_INT_10_10_10_2:
308 case GL_UNSIGNED_INT_2_10_10_10_REV:
309 return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_argb1555;
310 case GL_UNSIGNED_SHORT_4_4_4_4:
311 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
312 return _dri_texformat_argb4444;
313 case GL_UNSIGNED_SHORT_5_5_5_1:
314 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
315 return _dri_texformat_argb1555;
316 default:
317 return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_argb4444;
318 }
319
320 case 3:
321 case GL_RGB:
322 case GL_COMPRESSED_RGB:
323 switch ( type ) {
324 case GL_UNSIGNED_SHORT_4_4_4_4:
325 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
326 return _dri_texformat_argb4444;
327 case GL_UNSIGNED_SHORT_5_5_5_1:
328 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
329 return _dri_texformat_argb1555;
330 case GL_UNSIGNED_SHORT_5_6_5:
331 case GL_UNSIGNED_SHORT_5_6_5_REV:
332 return _dri_texformat_rgb565;
333 default:
334 return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
335 }
336
337 case GL_RGBA8:
338 case GL_RGB10_A2:
339 case GL_RGBA12:
340 case GL_RGBA16:
341 return !force16bpt ?
342 _dri_texformat_argb8888 : _dri_texformat_argb4444;
343
344 case GL_RGBA4:
345 case GL_RGBA2:
346 return _dri_texformat_argb4444;
347
348 case GL_RGB5_A1:
349 return _dri_texformat_argb1555;
350
351 case GL_RGB8:
352 case GL_RGB10:
353 case GL_RGB12:
354 case GL_RGB16:
355 return !force16bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
356
357 case GL_RGB5:
358 case GL_RGB4:
359 case GL_R3_G3_B2:
360 return _dri_texformat_rgb565;
361
362 case GL_ALPHA:
363 case GL_ALPHA4:
364 case GL_ALPHA8:
365 case GL_ALPHA12:
366 case GL_ALPHA16:
367 case GL_COMPRESSED_ALPHA:
368 return _dri_texformat_a8;
369
370 case 1:
371 case GL_LUMINANCE:
372 case GL_LUMINANCE4:
373 case GL_LUMINANCE8:
374 case GL_LUMINANCE12:
375 case GL_LUMINANCE16:
376 case GL_COMPRESSED_LUMINANCE:
377 return _dri_texformat_l8;
378
379 case 2:
380 case GL_LUMINANCE_ALPHA:
381 case GL_LUMINANCE4_ALPHA4:
382 case GL_LUMINANCE6_ALPHA2:
383 case GL_LUMINANCE8_ALPHA8:
384 case GL_LUMINANCE12_ALPHA4:
385 case GL_LUMINANCE12_ALPHA12:
386 case GL_LUMINANCE16_ALPHA16:
387 case GL_COMPRESSED_LUMINANCE_ALPHA:
388 return _dri_texformat_al88;
389
390 case GL_INTENSITY:
391 case GL_INTENSITY4:
392 case GL_INTENSITY8:
393 case GL_INTENSITY12:
394 case GL_INTENSITY16:
395 case GL_COMPRESSED_INTENSITY:
396 return _dri_texformat_i8;
397
398 case GL_YCBCR_MESA:
399 if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
400 type == GL_UNSIGNED_BYTE)
401 return &_mesa_texformat_ycbcr;
402 else
403 return &_mesa_texformat_ycbcr_rev;
404
405 case GL_RGB_S3TC:
406 case GL_RGB4_S3TC:
407 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
408 return &_mesa_texformat_rgb_dxt1;
409
410 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
411 return &_mesa_texformat_rgba_dxt1;
412
413 case GL_RGBA_S3TC:
414 case GL_RGBA4_S3TC:
415 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
416 return &_mesa_texformat_rgba_dxt3;
417
418 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
419 return &_mesa_texformat_rgba_dxt5;
420
421 default:
422 _mesa_problem(ctx, "unexpected texture format in %s", __FUNCTION__);
423 return NULL;
424 }
425
426 return NULL; /* never get here */
427 }
428
429
430 static void radeonTexImage1D( GLcontext *ctx, GLenum target, GLint level,
431 GLint internalFormat,
432 GLint width, GLint border,
433 GLenum format, GLenum type, const GLvoid *pixels,
434 const struct gl_pixelstore_attrib *packing,
435 struct gl_texture_object *texObj,
436 struct gl_texture_image *texImage )
437 {
438 driTextureObject * t = (driTextureObject *) texObj->DriverData;
439
440 if ( t ) {
441 driSwapOutTextureObject( t );
442 }
443 else {
444 t = (driTextureObject *) radeonAllocTexObj( texObj );
445 if (!t) {
446 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
447 return;
448 }
449 }
450
451 /* Note, this will call ChooseTextureFormat */
452 _mesa_store_teximage1d(ctx, target, level, internalFormat,
453 width, border, format, type, pixels,
454 &ctx->Unpack, texObj, texImage);
455
456 t->dirty_images[0] |= (1 << level);
457 }
458
459
460 static void radeonTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
461 GLint xoffset,
462 GLsizei width,
463 GLenum format, GLenum type,
464 const GLvoid *pixels,
465 const struct gl_pixelstore_attrib *packing,
466 struct gl_texture_object *texObj,
467 struct gl_texture_image *texImage )
468 {
469 driTextureObject * t = (driTextureObject *) texObj->DriverData;
470
471 assert( t ); /* this _should_ be true */
472 if ( t ) {
473 driSwapOutTextureObject( t );
474 }
475 else {
476 t = (driTextureObject *) radeonAllocTexObj( texObj );
477 if (!t) {
478 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
479 return;
480 }
481 }
482
483 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
484 format, type, pixels, packing, texObj,
485 texImage);
486
487 t->dirty_images[0] |= (1 << level);
488 }
489
490
491 static void radeonTexImage2D( GLcontext *ctx, GLenum target, GLint level,
492 GLint internalFormat,
493 GLint width, GLint height, GLint border,
494 GLenum format, GLenum type, const GLvoid *pixels,
495 const struct gl_pixelstore_attrib *packing,
496 struct gl_texture_object *texObj,
497 struct gl_texture_image *texImage )
498 {
499 driTextureObject * t = (driTextureObject *) texObj->DriverData;
500 GLuint face;
501
502 /* which cube face or ordinary 2D image */
503 switch (target) {
504 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
505 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
506 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
507 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
508 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
509 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
510 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
511 ASSERT(face < 6);
512 break;
513 default:
514 face = 0;
515 }
516
517 if ( t != NULL ) {
518 driSwapOutTextureObject( t );
519 }
520 else {
521 t = (driTextureObject *) radeonAllocTexObj( texObj );
522 if (!t) {
523 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
524 return;
525 }
526 }
527
528 /* Note, this will call ChooseTextureFormat */
529 _mesa_store_teximage2d(ctx, target, level, internalFormat,
530 width, height, border, format, type, pixels,
531 &ctx->Unpack, texObj, texImage);
532
533 t->dirty_images[face] |= (1 << level);
534 }
535
536
537 static void radeonTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
538 GLint xoffset, GLint yoffset,
539 GLsizei width, GLsizei height,
540 GLenum format, GLenum type,
541 const GLvoid *pixels,
542 const struct gl_pixelstore_attrib *packing,
543 struct gl_texture_object *texObj,
544 struct gl_texture_image *texImage )
545 {
546 driTextureObject * t = (driTextureObject *) texObj->DriverData;
547 GLuint face;
548
549 /* which cube face or ordinary 2D image */
550 switch (target) {
551 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
552 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
553 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
554 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
555 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
556 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
557 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
558 ASSERT(face < 6);
559 break;
560 default:
561 face = 0;
562 }
563
564 assert( t ); /* this _should_ be true */
565 if ( t ) {
566 driSwapOutTextureObject( t );
567 }
568 else {
569 t = (driTextureObject *) radeonAllocTexObj( texObj );
570 if (!t) {
571 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
572 return;
573 }
574 }
575
576 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
577 height, format, type, pixels, packing, texObj,
578 texImage);
579
580 t->dirty_images[face] |= (1 << level);
581 }
582
583 static void radeonCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
584 GLint internalFormat,
585 GLint width, GLint height, GLint border,
586 GLsizei imageSize, const GLvoid *data,
587 struct gl_texture_object *texObj,
588 struct gl_texture_image *texImage )
589 {
590 driTextureObject * t = (driTextureObject *) texObj->DriverData;
591 GLuint face;
592
593 /* which cube face or ordinary 2D image */
594 switch (target) {
595 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
596 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
597 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
598 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
599 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
600 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
601 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
602 ASSERT(face < 6);
603 break;
604 default:
605 face = 0;
606 }
607
608 if ( t != NULL ) {
609 driSwapOutTextureObject( t );
610 }
611 else {
612 t = (driTextureObject *) radeonAllocTexObj( texObj );
613 if (!t) {
614 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
615 return;
616 }
617 }
618
619 /* Note, this will call ChooseTextureFormat */
620 _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
621 height, border, imageSize, data, texObj, texImage);
622
623 t->dirty_images[face] |= (1 << level);
624 }
625
626
627 static void radeonCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
628 GLint xoffset, GLint yoffset,
629 GLsizei width, GLsizei height,
630 GLenum format,
631 GLsizei imageSize, const GLvoid *data,
632 struct gl_texture_object *texObj,
633 struct gl_texture_image *texImage )
634 {
635 driTextureObject * t = (driTextureObject *) texObj->DriverData;
636 GLuint face;
637
638
639 /* which cube face or ordinary 2D image */
640 switch (target) {
641 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
642 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
643 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
644 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
645 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
646 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
647 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
648 ASSERT(face < 6);
649 break;
650 default:
651 face = 0;
652 }
653
654 assert( t ); /* this _should_ be true */
655 if ( t ) {
656 driSwapOutTextureObject( t );
657 }
658 else {
659 t = (driTextureObject *) radeonAllocTexObj( texObj );
660 if (!t) {
661 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
662 return;
663 }
664 }
665
666 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
667 height, format, imageSize, data, texObj, texImage);
668
669 t->dirty_images[face] |= (1 << level);
670 }
671
672 #define SCALED_FLOAT_TO_BYTE( x, scale ) \
673 (((GLuint)((255.0F / scale) * (x))) / 2)
674
675 static void radeonTexEnv( GLcontext *ctx, GLenum target,
676 GLenum pname, const GLfloat *param )
677 {
678 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
679 GLuint unit = ctx->Texture.CurrentUnit;
680 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
681
682 if ( RADEON_DEBUG & DEBUG_STATE ) {
683 fprintf( stderr, "%s( %s )\n",
684 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
685 }
686
687 switch ( pname ) {
688 case GL_TEXTURE_ENV_COLOR: {
689 GLubyte c[4];
690 GLuint envColor;
691 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
692 envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
693 if ( rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] != envColor ) {
694 RADEON_STATECHANGE( rmesa, tex[unit] );
695 rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] = envColor;
696 }
697 break;
698 }
699
700 case GL_TEXTURE_LOD_BIAS_EXT: {
701 GLfloat bias, min;
702 GLuint b;
703
704 /* The Radeon's LOD bias is a signed 2's complement value with a
705 * range of -1.0 <= bias < 4.0. We break this into two linear
706 * functions, one mapping [-1.0,0.0] to [-128,0] and one mapping
707 * [0.0,4.0] to [0,127].
708 */
709 min = driQueryOptionb (&rmesa->optionCache, "no_neg_lod_bias") ?
710 0.0 : -1.0;
711 bias = CLAMP( *param, min, 4.0 );
712 if ( bias == 0 ) {
713 b = 0;
714 } else if ( bias > 0 ) {
715 b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 4.0 )) << RADEON_LOD_BIAS_SHIFT;
716 } else {
717 b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 1.0 )) << RADEON_LOD_BIAS_SHIFT;
718 }
719 if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] & RADEON_LOD_BIAS_MASK) != b ) {
720 RADEON_STATECHANGE( rmesa, tex[unit] );
721 rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] &= ~RADEON_LOD_BIAS_MASK;
722 rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] |= (b & RADEON_LOD_BIAS_MASK);
723 }
724 break;
725 }
726
727 default:
728 return;
729 }
730 }
731
732
733 /**
734 * Changes variables and flags for a state update, which will happen at the
735 * next UpdateTextureState
736 */
737
738 static void radeonTexParameter( GLcontext *ctx, GLenum target,
739 struct gl_texture_object *texObj,
740 GLenum pname, const GLfloat *params )
741 {
742 radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
743
744 if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
745 fprintf( stderr, "%s( %s )\n", __FUNCTION__,
746 _mesa_lookup_enum_by_nr( pname ) );
747 }
748
749 switch ( pname ) {
750 case GL_TEXTURE_MIN_FILTER:
751 case GL_TEXTURE_MAG_FILTER:
752 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
753 radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
754 radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
755 break;
756
757 case GL_TEXTURE_WRAP_S:
758 case GL_TEXTURE_WRAP_T:
759 radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
760 break;
761
762 case GL_TEXTURE_BORDER_COLOR:
763 radeonSetTexBorderColor( t, texObj->BorderColor );
764 break;
765
766 case GL_TEXTURE_BASE_LEVEL:
767 case GL_TEXTURE_MAX_LEVEL:
768 case GL_TEXTURE_MIN_LOD:
769 case GL_TEXTURE_MAX_LOD:
770 /* This isn't the most efficient solution but there doesn't appear to
771 * be a nice alternative. Since there's no LOD clamping,
772 * we just have to rely on loading the right subset of mipmap levels
773 * to simulate a clamped LOD.
774 */
775 driSwapOutTextureObject( (driTextureObject *) t );
776 break;
777
778 default:
779 return;
780 }
781
782 /* Mark this texobj as dirty (one bit per tex unit)
783 */
784 t->dirty_state = TEX_ALL;
785 }
786
787
788 static void radeonBindTexture( GLcontext *ctx, GLenum target,
789 struct gl_texture_object *texObj )
790 {
791 if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
792 fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, (void *)texObj,
793 ctx->Texture.CurrentUnit );
794 }
795
796 assert( (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D &&
797 target != GL_TEXTURE_RECTANGLE_NV && target != GL_TEXTURE_CUBE_MAP) ||
798 (texObj->DriverData != NULL) );
799 }
800
801
802 static void radeonDeleteTexture( GLcontext *ctx,
803 struct gl_texture_object *texObj )
804 {
805 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
806 driTextureObject * t = (driTextureObject *) texObj->DriverData;
807
808 if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
809 fprintf( stderr, "%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj,
810 _mesa_lookup_enum_by_nr( texObj->Target ) );
811 }
812
813 if ( t != NULL ) {
814 if ( rmesa ) {
815 RADEON_FIREVERTICES( rmesa );
816 }
817
818 driDestroyTextureObject( t );
819 }
820
821 /* Free mipmap images and the texture object itself */
822 _mesa_delete_texture_object(ctx, texObj);
823 }
824
825 /* Need:
826 * - Same GEN_MODE for all active bits
827 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
828 * - STRQ presumably all supported (matrix means incoming R values
829 * can end up in STQ, this has implications for vertex support,
830 * presumably ok if maos is used, though?)
831 *
832 * Basically impossible to do this on the fly - just collect some
833 * basic info & do the checks from ValidateState().
834 */
835 static void radeonTexGen( GLcontext *ctx,
836 GLenum coord,
837 GLenum pname,
838 const GLfloat *params )
839 {
840 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
841 GLuint unit = ctx->Texture.CurrentUnit;
842 rmesa->recheck_texgen[unit] = GL_TRUE;
843 }
844
845 /**
846 * Allocate a new texture object.
847 * Called via ctx->Driver.NewTextureObject.
848 * Note: we could use containment here to 'derive' the driver-specific
849 * texture object from the core mesa gl_texture_object. Not done at this time.
850 */
851 static struct gl_texture_object *
852 radeonNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
853 {
854 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
855 struct gl_texture_object *obj;
856 obj = _mesa_new_texture_object(ctx, name, target);
857 if (!obj)
858 return NULL;
859 obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
860 radeonAllocTexObj( obj );
861 return obj;
862 }
863
864
865 void radeonInitTextureFuncs( struct dd_function_table *functions )
866 {
867 functions->ChooseTextureFormat = radeonChooseTextureFormat;
868 functions->TexImage1D = radeonTexImage1D;
869 functions->TexImage2D = radeonTexImage2D;
870 functions->TexSubImage1D = radeonTexSubImage1D;
871 functions->TexSubImage2D = radeonTexSubImage2D;
872
873 functions->NewTextureObject = radeonNewTextureObject;
874 functions->BindTexture = radeonBindTexture;
875 functions->DeleteTexture = radeonDeleteTexture;
876 functions->IsTextureResident = driIsTextureResident;
877
878 functions->TexEnv = radeonTexEnv;
879 functions->TexParameter = radeonTexParameter;
880 functions->TexGen = radeonTexGen;
881
882 functions->CompressedTexImage2D = radeonCompressedTexImage2D;
883 functions->CompressedTexSubImage2D = radeonCompressedTexSubImage2D;
884
885 driInitTextureFormats();
886 }