Fix dumb mistake from a previous commit. __driCreateScreen is now
[mesa.git] / src / mesa / drivers / dri / r200 / r200_tex.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_tex.c,v 1.2 2002/11/05 17:46:08 tsi Exp $ */
2 /*
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 */
29
30 /*
31 * Authors:
32 * Keith Whitwell <keith@tungstengraphics.com>
33 */
34
35 #include "glheader.h"
36 #include "imports.h"
37 #include "colormac.h"
38 #include "context.h"
39 #include "enums.h"
40 #include "image.h"
41 #include "simple_list.h"
42 #include "texformat.h"
43 #include "texstore.h"
44 #include "texmem.h"
45 #include "teximage.h"
46 #include "texobj.h"
47
48 #include "r200_context.h"
49 #include "r200_state.h"
50 #include "r200_ioctl.h"
51 #include "r200_swtcl.h"
52 #include "r200_tex.h"
53
54 #include "xmlpool.h"
55
56
57
58 /**
59 * Set the texture wrap modes.
60 *
61 * \param t Texture object whose wrap modes are to be set
62 * \param swrap Wrap mode for the \a s texture coordinate
63 * \param twrap Wrap mode for the \a t texture coordinate
64 */
65
66 static void r200SetTexWrap( r200TexObjPtr t, GLenum swrap, GLenum twrap, GLenum rwrap )
67 {
68 GLboolean is_clamp = GL_FALSE;
69 GLboolean is_clamp_to_border = GL_FALSE;
70
71 t->pp_txfilter &= ~(R200_CLAMP_S_MASK | R200_CLAMP_T_MASK | R200_BORDER_MODE_D3D);
72
73 switch ( swrap ) {
74 case GL_REPEAT:
75 t->pp_txfilter |= R200_CLAMP_S_WRAP;
76 break;
77 case GL_CLAMP:
78 t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL;
79 is_clamp = GL_TRUE;
80 break;
81 case GL_CLAMP_TO_EDGE:
82 t->pp_txfilter |= R200_CLAMP_S_CLAMP_LAST;
83 break;
84 case GL_CLAMP_TO_BORDER:
85 t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL;
86 is_clamp_to_border = GL_TRUE;
87 break;
88 case GL_MIRRORED_REPEAT:
89 t->pp_txfilter |= R200_CLAMP_S_MIRROR;
90 break;
91 case GL_MIRROR_CLAMP_EXT:
92 t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_GL;
93 is_clamp = GL_TRUE;
94 break;
95 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
96 t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_LAST;
97 break;
98 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
99 t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_GL;
100 is_clamp_to_border = GL_TRUE;
101 break;
102 default:
103 _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
104 }
105
106 switch ( twrap ) {
107 case GL_REPEAT:
108 t->pp_txfilter |= R200_CLAMP_T_WRAP;
109 break;
110 case GL_CLAMP:
111 t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL;
112 is_clamp = GL_TRUE;
113 break;
114 case GL_CLAMP_TO_EDGE:
115 t->pp_txfilter |= R200_CLAMP_T_CLAMP_LAST;
116 break;
117 case GL_CLAMP_TO_BORDER:
118 t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL | R200_BORDER_MODE_D3D;
119 is_clamp_to_border = GL_TRUE;
120 break;
121 case GL_MIRRORED_REPEAT:
122 t->pp_txfilter |= R200_CLAMP_T_MIRROR;
123 break;
124 case GL_MIRROR_CLAMP_EXT:
125 t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_GL;
126 is_clamp = GL_TRUE;
127 break;
128 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
129 t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_LAST;
130 break;
131 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
132 t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_GL;
133 is_clamp_to_border = GL_TRUE;
134 break;
135 default:
136 _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
137 }
138
139 t->pp_txformat_x &= ~R200_CLAMP_Q_MASK;
140
141 switch ( rwrap ) {
142 case GL_REPEAT:
143 t->pp_txformat_x |= R200_CLAMP_Q_WRAP;
144 break;
145 case GL_CLAMP:
146 t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL;
147 is_clamp = GL_TRUE;
148 break;
149 case GL_CLAMP_TO_EDGE:
150 t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_LAST;
151 break;
152 case GL_CLAMP_TO_BORDER:
153 t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL;
154 is_clamp_to_border = GL_TRUE;
155 break;
156 case GL_MIRRORED_REPEAT:
157 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR;
158 break;
159 case GL_MIRROR_CLAMP_EXT:
160 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_GL;
161 is_clamp = GL_TRUE;
162 break;
163 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
164 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_LAST;
165 break;
166 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
167 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_GL;
168 is_clamp_to_border = GL_TRUE;
169 break;
170 default:
171 _mesa_problem(NULL, "bad R wrap mode in %s", __FUNCTION__);
172 }
173
174 if ( is_clamp_to_border ) {
175 t->pp_txfilter |= R200_BORDER_MODE_D3D;
176 }
177
178 t->border_fallback = (is_clamp && is_clamp_to_border);
179 }
180
181 static void r200SetTexMaxAnisotropy( r200TexObjPtr t, GLfloat max )
182 {
183 t->pp_txfilter &= ~R200_MAX_ANISO_MASK;
184
185 if ( max == 1.0 ) {
186 t->pp_txfilter |= R200_MAX_ANISO_1_TO_1;
187 } else if ( max <= 2.0 ) {
188 t->pp_txfilter |= R200_MAX_ANISO_2_TO_1;
189 } else if ( max <= 4.0 ) {
190 t->pp_txfilter |= R200_MAX_ANISO_4_TO_1;
191 } else if ( max <= 8.0 ) {
192 t->pp_txfilter |= R200_MAX_ANISO_8_TO_1;
193 } else {
194 t->pp_txfilter |= R200_MAX_ANISO_16_TO_1;
195 }
196 }
197
198 /**
199 * Set the texture magnification and minification modes.
200 *
201 * \param t Texture whose filter modes are to be set
202 * \param minf Texture minification mode
203 * \param magf Texture magnification mode
204 */
205
206 static void r200SetTexFilter( r200TexObjPtr t, GLenum minf, GLenum magf )
207 {
208 GLuint anisotropy = (t->pp_txfilter & R200_MAX_ANISO_MASK);
209
210 t->pp_txfilter &= ~(R200_MIN_FILTER_MASK | R200_MAG_FILTER_MASK);
211 t->pp_txformat_x &= ~R200_VOLUME_FILTER_MASK;
212
213 if ( anisotropy == R200_MAX_ANISO_1_TO_1 ) {
214 switch ( minf ) {
215 case GL_NEAREST:
216 t->pp_txfilter |= R200_MIN_FILTER_NEAREST;
217 break;
218 case GL_LINEAR:
219 t->pp_txfilter |= R200_MIN_FILTER_LINEAR;
220 break;
221 case GL_NEAREST_MIPMAP_NEAREST:
222 t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_NEAREST;
223 break;
224 case GL_NEAREST_MIPMAP_LINEAR:
225 t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_NEAREST;
226 break;
227 case GL_LINEAR_MIPMAP_NEAREST:
228 t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_LINEAR;
229 break;
230 case GL_LINEAR_MIPMAP_LINEAR:
231 t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_LINEAR;
232 break;
233 }
234 } else {
235 switch ( minf ) {
236 case GL_NEAREST:
237 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST;
238 break;
239 case GL_LINEAR:
240 t->pp_txfilter |= R200_MIN_FILTER_ANISO_LINEAR;
241 break;
242 case GL_NEAREST_MIPMAP_NEAREST:
243 case GL_LINEAR_MIPMAP_NEAREST:
244 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
245 break;
246 case GL_NEAREST_MIPMAP_LINEAR:
247 case GL_LINEAR_MIPMAP_LINEAR:
248 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR;
249 break;
250 }
251 }
252
253 /* Note we don't have 3D mipmaps so only use the mag filter setting
254 * to set the 3D texture filter mode.
255 */
256 switch ( magf ) {
257 case GL_NEAREST:
258 t->pp_txfilter |= R200_MAG_FILTER_NEAREST;
259 t->pp_txformat_x |= R200_VOLUME_FILTER_NEAREST;
260 break;
261 case GL_LINEAR:
262 t->pp_txfilter |= R200_MAG_FILTER_LINEAR;
263 t->pp_txformat_x |= R200_VOLUME_FILTER_LINEAR;
264 break;
265 }
266 }
267
268 static void r200SetTexBorderColor( r200TexObjPtr t, GLubyte c[4] )
269 {
270 t->pp_border_color = r200PackColor( 4, c[0], c[1], c[2], c[3] );
271 }
272
273
274 /**
275 * Allocate space for and load the mesa images into the texture memory block.
276 * This will happen before drawing with a new texture, or drawing with a
277 * texture after it was swapped out or teximaged again.
278 */
279
280 static r200TexObjPtr r200AllocTexObj( struct gl_texture_object *texObj )
281 {
282 r200TexObjPtr t;
283
284 t = CALLOC_STRUCT( r200_tex_obj );
285 texObj->DriverData = t;
286 if ( t != NULL ) {
287 if ( R200_DEBUG & DEBUG_TEXTURE ) {
288 fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, (void *)texObj,
289 (void *)t );
290 }
291
292 /* Initialize non-image-dependent parts of the state:
293 */
294 t->base.tObj = texObj;
295 t->border_fallback = GL_FALSE;
296
297 make_empty_list( & t->base );
298
299 r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
300 r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
301 r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
302 r200SetTexBorderColor( t, texObj->_BorderChan );
303 }
304
305 return t;
306 }
307
308
309 static const struct gl_texture_format *
310 r200ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
311 GLenum format, GLenum type )
312 {
313 r200ContextPtr rmesa = R200_CONTEXT(ctx);
314 const GLboolean do32bpt =
315 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
316 const GLboolean force16bpt =
317 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
318 (void) format;
319
320 switch ( internalFormat ) {
321 case 4:
322 case GL_RGBA:
323 case GL_COMPRESSED_RGBA:
324 switch ( type ) {
325 case GL_UNSIGNED_INT_10_10_10_2:
326 case GL_UNSIGNED_INT_2_10_10_10_REV:
327 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555;
328 case GL_UNSIGNED_SHORT_4_4_4_4:
329 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
330 return &_mesa_texformat_argb4444;
331 case GL_UNSIGNED_SHORT_5_5_5_1:
332 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
333 return &_mesa_texformat_argb1555;
334 default:
335 return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444;
336 }
337
338 case 3:
339 case GL_RGB:
340 case GL_COMPRESSED_RGB:
341 switch ( type ) {
342 case GL_UNSIGNED_SHORT_4_4_4_4:
343 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
344 return &_mesa_texformat_argb4444;
345 case GL_UNSIGNED_SHORT_5_5_5_1:
346 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
347 return &_mesa_texformat_argb1555;
348 case GL_UNSIGNED_SHORT_5_6_5:
349 case GL_UNSIGNED_SHORT_5_6_5_REV:
350 return &_mesa_texformat_rgb565;
351 default:
352 return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565;
353 }
354
355 case GL_RGBA8:
356 case GL_RGB10_A2:
357 case GL_RGBA12:
358 case GL_RGBA16:
359 return !force16bpt ?
360 &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444;
361
362 case GL_RGBA4:
363 case GL_RGBA2:
364 return &_mesa_texformat_argb4444;
365
366 case GL_RGB5_A1:
367 return &_mesa_texformat_argb1555;
368
369 case GL_RGB8:
370 case GL_RGB10:
371 case GL_RGB12:
372 case GL_RGB16:
373 return !force16bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565;
374
375 case GL_RGB5:
376 case GL_RGB4:
377 case GL_R3_G3_B2:
378 return &_mesa_texformat_rgb565;
379
380 case GL_ALPHA:
381 case GL_ALPHA4:
382 case GL_ALPHA8:
383 case GL_ALPHA12:
384 case GL_ALPHA16:
385 case GL_COMPRESSED_ALPHA:
386 return &_mesa_texformat_al88;
387
388 case 1:
389 case GL_LUMINANCE:
390 case GL_LUMINANCE4:
391 case GL_LUMINANCE8:
392 case GL_LUMINANCE12:
393 case GL_LUMINANCE16:
394 case GL_COMPRESSED_LUMINANCE:
395 return &_mesa_texformat_al88;
396
397 case 2:
398 case GL_LUMINANCE_ALPHA:
399 case GL_LUMINANCE4_ALPHA4:
400 case GL_LUMINANCE6_ALPHA2:
401 case GL_LUMINANCE8_ALPHA8:
402 case GL_LUMINANCE12_ALPHA4:
403 case GL_LUMINANCE12_ALPHA12:
404 case GL_LUMINANCE16_ALPHA16:
405 case GL_COMPRESSED_LUMINANCE_ALPHA:
406 return &_mesa_texformat_al88;
407
408 case GL_INTENSITY:
409 case GL_INTENSITY4:
410 case GL_INTENSITY8:
411 case GL_INTENSITY12:
412 case GL_INTENSITY16:
413 case GL_COMPRESSED_INTENSITY:
414 /* At the moment, glean & conform both fail using the i8 internal
415 * format.
416 */
417 return &_mesa_texformat_al88;
418 /* return &_mesa_texformat_i8; */
419
420 case GL_YCBCR_MESA:
421 if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
422 type == GL_UNSIGNED_BYTE)
423 return &_mesa_texformat_ycbcr;
424 else
425 return &_mesa_texformat_ycbcr_rev;
426
427 default:
428 _mesa_problem(ctx, "unexpected texture format in %s", __FUNCTION__);
429 return NULL;
430 }
431
432 return NULL; /* never get here */
433 }
434
435
436 static GLboolean
437 r200ValidateClientStorage( GLcontext *ctx, GLenum target,
438 GLint internalFormat,
439 GLint srcWidth, GLint srcHeight,
440 GLenum format, GLenum type, const void *pixels,
441 const struct gl_pixelstore_attrib *packing,
442 struct gl_texture_object *texObj,
443 struct gl_texture_image *texImage)
444
445 {
446 r200ContextPtr rmesa = R200_CONTEXT(ctx);
447
448 if (0)
449 fprintf(stderr, "intformat %s format %s type %s\n",
450 _mesa_lookup_enum_by_nr( internalFormat ),
451 _mesa_lookup_enum_by_nr( format ),
452 _mesa_lookup_enum_by_nr( type ));
453
454 if (!ctx->Unpack.ClientStorage)
455 return 0;
456
457 if (ctx->_ImageTransferState ||
458 texImage->IsCompressed ||
459 texObj->GenerateMipmap)
460 return 0;
461
462
463 /* This list is incomplete, may be different on ppc???
464 */
465 switch ( internalFormat ) {
466 case GL_RGBA:
467 if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
468 texImage->TexFormat = &_mesa_texformat_argb8888;
469 }
470 else
471 return 0;
472 break;
473
474 case GL_RGB:
475 if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
476 texImage->TexFormat = &_mesa_texformat_rgb565;
477 }
478 else
479 return 0;
480 break;
481
482 case GL_YCBCR_MESA:
483 if ( format == GL_YCBCR_MESA &&
484 type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
485 texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
486 }
487 else if ( format == GL_YCBCR_MESA &&
488 (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
489 type == GL_UNSIGNED_BYTE)) {
490 texImage->TexFormat = &_mesa_texformat_ycbcr;
491 }
492 else
493 return 0;
494 break;
495
496 default:
497 return 0;
498 }
499
500 /* Could deal with these packing issues, but currently don't:
501 */
502 if (packing->SkipPixels ||
503 packing->SkipRows ||
504 packing->SwapBytes ||
505 packing->LsbFirst) {
506 return 0;
507 }
508
509 {
510 GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
511 format, type);
512
513
514 if (0)
515 fprintf(stderr, "%s: srcRowStride %d/%x\n",
516 __FUNCTION__, srcRowStride, srcRowStride);
517
518 /* Could check this later in upload, pitch restrictions could be
519 * relaxed, but would need to store the image pitch somewhere,
520 * as packing details might change before image is uploaded:
521 */
522 if (!r200IsGartMemory( rmesa, pixels, srcHeight * srcRowStride ) ||
523 (srcRowStride & 63))
524 return 0;
525
526
527 /* Have validated that _mesa_transfer_teximage would be a straight
528 * memcpy at this point. NOTE: future calls to TexSubImage will
529 * overwrite the client data. This is explicitly mentioned in the
530 * extension spec.
531 */
532 texImage->Data = (void *)pixels;
533 texImage->IsClientData = GL_TRUE;
534 texImage->RowStride = srcRowStride / texImage->TexFormat->TexelBytes;
535
536 return 1;
537 }
538 }
539
540
541 static void r200TexImage1D( GLcontext *ctx, GLenum target, GLint level,
542 GLint internalFormat,
543 GLint width, GLint border,
544 GLenum format, GLenum type, const GLvoid *pixels,
545 const struct gl_pixelstore_attrib *packing,
546 struct gl_texture_object *texObj,
547 struct gl_texture_image *texImage )
548 {
549 driTextureObject * t = (driTextureObject *) texObj->DriverData;
550
551 if ( t ) {
552 driSwapOutTextureObject( t );
553 }
554 else {
555 t = (driTextureObject *) r200AllocTexObj( texObj );
556 if (!t) {
557 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
558 return;
559 }
560 }
561
562 /* Note, this will call ChooseTextureFormat */
563 _mesa_store_teximage1d(ctx, target, level, internalFormat,
564 width, border, format, type, pixels,
565 &ctx->Unpack, texObj, texImage);
566
567 t->dirty_images[0] |= (1 << level);
568 }
569
570
571 static void r200TexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
572 GLint xoffset,
573 GLsizei width,
574 GLenum format, GLenum type,
575 const GLvoid *pixels,
576 const struct gl_pixelstore_attrib *packing,
577 struct gl_texture_object *texObj,
578 struct gl_texture_image *texImage )
579 {
580 driTextureObject * t = (driTextureObject *) texObj->DriverData;
581
582 assert( t ); /* this _should_ be true */
583 if ( t ) {
584 driSwapOutTextureObject( t );
585 }
586 else {
587 t = (driTextureObject *) r200AllocTexObj( texObj );
588 if (!t) {
589 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
590 return;
591 }
592 }
593
594 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
595 format, type, pixels, packing, texObj,
596 texImage);
597
598 t->dirty_images[0] |= (1 << level);
599 }
600
601
602 static void r200TexImage2D( GLcontext *ctx, GLenum target, GLint level,
603 GLint internalFormat,
604 GLint width, GLint height, GLint border,
605 GLenum format, GLenum type, const GLvoid *pixels,
606 const struct gl_pixelstore_attrib *packing,
607 struct gl_texture_object *texObj,
608 struct gl_texture_image *texImage )
609 {
610 driTextureObject * t = (driTextureObject *) texObj->DriverData;
611 GLuint face;
612
613 /* which cube face or ordinary 2D image */
614 switch (target) {
615 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
616 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
617 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
618 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
619 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
620 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
621 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
622 ASSERT(face < 6);
623 break;
624 default:
625 face = 0;
626 }
627
628 if ( t != NULL ) {
629 driSwapOutTextureObject( t );
630 }
631 else {
632 t = (driTextureObject *) r200AllocTexObj( texObj );
633 if (!t) {
634 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
635 return;
636 }
637 }
638
639 texImage->IsClientData = GL_FALSE;
640
641 if (r200ValidateClientStorage( ctx, target,
642 internalFormat,
643 width, height,
644 format, type, pixels,
645 packing, texObj, texImage)) {
646 if (R200_DEBUG & DEBUG_TEXTURE)
647 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
648 }
649 else {
650 if (R200_DEBUG & DEBUG_TEXTURE)
651 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
652
653 /* Normal path: copy (to cached memory) and eventually upload
654 * via another copy to GART memory and then a blit... Could
655 * eliminate one copy by going straight to (permanent) GART.
656 *
657 * Note, this will call r200ChooseTextureFormat.
658 */
659 _mesa_store_teximage2d(ctx, target, level, internalFormat,
660 width, height, border, format, type, pixels,
661 &ctx->Unpack, texObj, texImage);
662
663 t->dirty_images[face] |= (1 << level);
664 }
665 }
666
667
668 static void r200TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
669 GLint xoffset, GLint yoffset,
670 GLsizei width, GLsizei height,
671 GLenum format, GLenum type,
672 const GLvoid *pixels,
673 const struct gl_pixelstore_attrib *packing,
674 struct gl_texture_object *texObj,
675 struct gl_texture_image *texImage )
676 {
677 driTextureObject * t = (driTextureObject *) texObj->DriverData;
678 GLuint face;
679
680 /* which cube face or ordinary 2D image */
681 switch (target) {
682 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
683 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
684 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
685 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
686 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
687 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
688 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
689 ASSERT(face < 6);
690 break;
691 default:
692 face = 0;
693 }
694
695 assert( t ); /* this _should_ be true */
696 if ( t ) {
697 driSwapOutTextureObject( t );
698 }
699 else {
700 t = (driTextureObject *) r200AllocTexObj( texObj );
701 if (!t) {
702 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
703 return;
704 }
705 }
706
707 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
708 height, format, type, pixels, packing, texObj,
709 texImage);
710
711 t->dirty_images[face] |= (1 << level);
712 }
713
714
715 #if ENABLE_HW_3D_TEXTURE
716 static void r200TexImage3D( GLcontext *ctx, GLenum target, GLint level,
717 GLint internalFormat,
718 GLint width, GLint height, GLint depth,
719 GLint border,
720 GLenum format, GLenum type, const GLvoid *pixels,
721 const struct gl_pixelstore_attrib *packing,
722 struct gl_texture_object *texObj,
723 struct gl_texture_image *texImage )
724 {
725 driTextureObject * t = (driTextureObject *) texObj->DriverData;
726
727 if ( t ) {
728 driSwapOutTextureObject( t );
729 }
730 else {
731 t = r200AllocTexObj( texObj );
732 if (!t) {
733 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
734 return;
735 }
736 }
737
738 texImage->IsClientData = GL_FALSE;
739
740 #if 0
741 if (r200ValidateClientStorage( ctx, target,
742 internalFormat,
743 width, height,
744 format, type, pixels,
745 packing, texObj, texImage)) {
746 if (R200_DEBUG & DEBUG_TEXTURE)
747 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
748 }
749 else
750 #endif
751 {
752 if (R200_DEBUG & DEBUG_TEXTURE)
753 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
754
755 /* Normal path: copy (to cached memory) and eventually upload
756 * via another copy to GART memory and then a blit... Could
757 * eliminate one copy by going straight to (permanent) GART.
758 *
759 * Note, this will call r200ChooseTextureFormat.
760 */
761 _mesa_store_teximage3d(ctx, target, level, internalFormat,
762 width, height, depth, border,
763 format, type, pixels,
764 &ctx->Unpack, texObj, texImage);
765
766 t->dirty_images[0] |= (1 << level);
767 }
768 }
769 #endif
770
771
772 #if ENABLE_HW_3D_TEXTURE
773 static void
774 r200TexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
775 GLint xoffset, GLint yoffset, GLint zoffset,
776 GLsizei width, GLsizei height, GLsizei depth,
777 GLenum format, GLenum type,
778 const GLvoid *pixels,
779 const struct gl_pixelstore_attrib *packing,
780 struct gl_texture_object *texObj,
781 struct gl_texture_image *texImage )
782 {
783 driTextureObject * t = (driTextureObject *) texObj->DriverData;
784
785 /* fprintf(stderr, "%s\n", __FUNCTION__); */
786
787 assert( t ); /* this _should_ be true */
788 if ( t ) {
789 driSwapOutTextureObject( t );
790 }
791 else {
792 t = r200AllocTexObj(texObj);
793 if (!t) {
794 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
795 return;
796 }
797 texObj->DriverData = t;
798 }
799
800 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
801 width, height, depth,
802 format, type, pixels, packing, texObj, texImage);
803
804 t->dirty_images[0] |= (1 << level);
805 }
806 #endif
807
808
809
810 static void r200TexEnv( GLcontext *ctx, GLenum target,
811 GLenum pname, const GLfloat *param )
812 {
813 r200ContextPtr rmesa = R200_CONTEXT(ctx);
814 GLuint unit = ctx->Texture.CurrentUnit;
815 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
816
817 if ( R200_DEBUG & DEBUG_STATE ) {
818 fprintf( stderr, "%s( %s )\n",
819 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
820 }
821
822 /* This is incorrect: Need to maintain this data for each of
823 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
824 * between them according to _ReallyEnabled.
825 */
826 switch ( pname ) {
827 case GL_TEXTURE_ENV_COLOR: {
828 GLubyte c[4];
829 GLuint envColor;
830 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
831 envColor = r200PackColor( 4, c[0], c[1], c[2], c[3] );
832 if ( rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor ) {
833 R200_STATECHANGE( rmesa, tf );
834 rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] = envColor;
835 }
836 break;
837 }
838
839 case GL_TEXTURE_LOD_BIAS_EXT: {
840 GLfloat bias, min;
841 GLuint b;
842 const int fixed_one = 0x8000000;
843
844 /* The R200's LOD bias is a signed 2's complement value with a
845 * range of -16.0 <= bias < 16.0.
846 *
847 * NOTE: Add a small bias to the bias for conform mipsel.c test.
848 */
849 bias = *param + .01;
850 min = driQueryOptionb (&rmesa->optionCache, "no_neg_lod_bias") ?
851 0.0 : -16.0;
852 bias = CLAMP( bias, min, 16.0 );
853 b = (int)(bias * fixed_one) & R200_LOD_BIAS_MASK;
854
855 if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] & R200_LOD_BIAS_MASK) != b ) {
856 R200_STATECHANGE( rmesa, tex[unit] );
857 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] &= ~R200_LOD_BIAS_MASK;
858 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] |= b;
859 }
860 break;
861 }
862
863 default:
864 return;
865 }
866 }
867
868
869 /**
870 * Changes variables and flags for a state update, which will happen at the
871 * next UpdateTextureState
872 */
873
874 static void r200TexParameter( GLcontext *ctx, GLenum target,
875 struct gl_texture_object *texObj,
876 GLenum pname, const GLfloat *params )
877 {
878 r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
879
880 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
881 fprintf( stderr, "%s( %s )\n", __FUNCTION__,
882 _mesa_lookup_enum_by_nr( pname ) );
883 }
884
885 switch ( pname ) {
886 case GL_TEXTURE_MIN_FILTER:
887 case GL_TEXTURE_MAG_FILTER:
888 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
889 r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
890 r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
891 break;
892
893 case GL_TEXTURE_WRAP_S:
894 case GL_TEXTURE_WRAP_T:
895 case GL_TEXTURE_WRAP_R:
896 r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
897 break;
898
899 case GL_TEXTURE_BORDER_COLOR:
900 r200SetTexBorderColor( t, texObj->_BorderChan );
901 break;
902
903 case GL_TEXTURE_BASE_LEVEL:
904 case GL_TEXTURE_MAX_LEVEL:
905 case GL_TEXTURE_MIN_LOD:
906 case GL_TEXTURE_MAX_LOD:
907 /* This isn't the most efficient solution but there doesn't appear to
908 * be a nice alternative. Since there's no LOD clamping,
909 * we just have to rely on loading the right subset of mipmap levels
910 * to simulate a clamped LOD.
911 */
912 driSwapOutTextureObject( (driTextureObject *) t );
913 break;
914
915 default:
916 return;
917 }
918
919 /* Mark this texobj as dirty (one bit per tex unit)
920 */
921 t->dirty_state = TEX_ALL;
922 }
923
924
925
926 static void r200BindTexture( GLcontext *ctx, GLenum target,
927 struct gl_texture_object *texObj )
928 {
929 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
930 fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, (void *)texObj,
931 ctx->Texture.CurrentUnit );
932 }
933
934 if ( (target == GL_TEXTURE_1D)
935 || (target == GL_TEXTURE_2D)
936 #if ENABLE_HW_3D_TEXTURE
937 || (target == GL_TEXTURE_3D)
938 #endif
939 || (target == GL_TEXTURE_CUBE_MAP)
940 || (target == GL_TEXTURE_RECTANGLE_NV) ) {
941 assert( texObj->DriverData != NULL );
942 }
943 }
944
945
946 static void r200DeleteTexture( GLcontext *ctx,
947 struct gl_texture_object *texObj )
948 {
949 r200ContextPtr rmesa = R200_CONTEXT(ctx);
950 driTextureObject * t = (driTextureObject *) texObj->DriverData;
951
952 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
953 fprintf( stderr, "%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj,
954 _mesa_lookup_enum_by_nr( texObj->Target ) );
955 }
956
957 if ( t != NULL ) {
958 if ( rmesa ) {
959 R200_FIREVERTICES( rmesa );
960 }
961
962 driDestroyTextureObject( t );
963 }
964 /* Free mipmap images and the texture object itself */
965 _mesa_delete_texture_object(ctx, texObj);
966 }
967
968 /* Need:
969 * - Same GEN_MODE for all active bits
970 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
971 * - STRQ presumably all supported (matrix means incoming R values
972 * can end up in STQ, this has implications for vertex support,
973 * presumably ok if maos is used, though?)
974 *
975 * Basically impossible to do this on the fly - just collect some
976 * basic info & do the checks from ValidateState().
977 */
978 static void r200TexGen( GLcontext *ctx,
979 GLenum coord,
980 GLenum pname,
981 const GLfloat *params )
982 {
983 r200ContextPtr rmesa = R200_CONTEXT(ctx);
984 GLuint unit = ctx->Texture.CurrentUnit;
985 rmesa->recheck_texgen[unit] = GL_TRUE;
986 }
987
988
989 /**
990 * Allocate a new texture object.
991 * Called via ctx->Driver.NewTextureObject.
992 * Note: this function will be called during context creation to
993 * allocate the default texture objects.
994 * Note: we could use containment here to 'derive' the driver-specific
995 * texture object from the core mesa gl_texture_object. Not done at this time.
996 * Fixup MaxAnisotropy according to user preference.
997 */
998 static struct gl_texture_object *
999 r200NewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
1000 {
1001 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1002 struct gl_texture_object *obj;
1003 obj = _mesa_new_texture_object(ctx, name, target);
1004 if (!obj)
1005 return NULL;
1006 obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
1007 r200AllocTexObj( obj );
1008 return obj;
1009 }
1010
1011
1012 void r200InitTextureFuncs( struct dd_function_table *functions )
1013 {
1014 /* Note: we only plug in the functions we implement in the driver
1015 * since _mesa_init_driver_functions() was already called.
1016 */
1017 functions->ChooseTextureFormat = r200ChooseTextureFormat;
1018 functions->TexImage1D = r200TexImage1D;
1019 functions->TexImage2D = r200TexImage2D;
1020 #if ENABLE_HW_3D_TEXTURE
1021 functions->TexImage3D = r200TexImage3D;
1022 #else
1023 functions->TexImage3D = _mesa_store_teximage3d;
1024 #endif
1025 functions->TexSubImage1D = r200TexSubImage1D;
1026 functions->TexSubImage2D = r200TexSubImage2D;
1027 #if ENABLE_HW_3D_TEXTURE
1028 functions->TexSubImage3D = r200TexSubImage3D;
1029 #else
1030 functions->TexSubImage3D = _mesa_store_texsubimage3d;
1031 #endif
1032 functions->NewTextureObject = r200NewTextureObject;
1033 functions->BindTexture = r200BindTexture;
1034 functions->DeleteTexture = r200DeleteTexture;
1035 functions->IsTextureResident = driIsTextureResident;
1036
1037 functions->TexEnv = r200TexEnv;
1038 functions->TexParameter = r200TexParameter;
1039 functions->TexGen = r200TexGen;
1040
1041 #if 000
1042 /* moved or obsolete code */
1043 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1044 driInitTextureObjects( ctx, & rmesa->swapped,
1045 DRI_TEXMGR_DO_TEXTURE_1D
1046 | DRI_TEXMGR_DO_TEXTURE_2D );
1047
1048 /* Hack: r200NewTextureObject is not yet installed when the
1049 * default textures are created. Therefore set MaxAnisotropy of the
1050 * default 2D texture now. */
1051 ctx->Shared->Default2D->MaxAnisotropy = driQueryOptionf (&rmesa->optionCache,
1052 "def_max_anisotropy");
1053 #endif
1054 }