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