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