GC a bit of dead code I noticed while looking at texwrap.
[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 unsigned long hw_swrap=0, hw_twrap=0, hw_qwrap=0;
68
69 t->filter &=
70 ~(R300_TX_WRAP_S_MASK | R300_TX_WRAP_T_MASK | R300_TX_WRAP_Q_MASK);
71
72 switch (swrap) {
73 case GL_REPEAT:
74 hw_swrap |= R300_TX_REPEAT;
75 break;
76 case GL_CLAMP:
77 hw_swrap |= R300_TX_CLAMP;
78 break;
79 case GL_CLAMP_TO_EDGE:
80 hw_swrap |= R300_TX_CLAMP_TO_EDGE;
81 break;
82 case GL_CLAMP_TO_BORDER:
83 hw_swrap |= R300_TX_CLAMP_TO_BORDER;
84 break;
85 case GL_MIRRORED_REPEAT:
86 hw_swrap |= R300_TX_REPEAT | R300_TX_MIRRORED;
87 break;
88 case GL_MIRROR_CLAMP_EXT:
89 hw_swrap |= R300_TX_CLAMP | R300_TX_MIRRORED;
90 break;
91 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
92 hw_swrap |= R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED;
93 break;
94 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
95 hw_swrap |= R300_TX_CLAMP_TO_BORDER | R300_TX_MIRRORED;
96 break;
97 default:
98 _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
99 }
100
101 switch (twrap) {
102 case GL_REPEAT:
103 hw_twrap |= R300_TX_REPEAT;
104 break;
105 case GL_CLAMP:
106 hw_twrap |= R300_TX_CLAMP;
107 break;
108 case GL_CLAMP_TO_EDGE:
109 hw_twrap |= R300_TX_CLAMP_TO_EDGE;
110 break;
111 case GL_CLAMP_TO_BORDER:
112 hw_twrap |= R300_TX_CLAMP_TO_BORDER;
113 break;
114 case GL_MIRRORED_REPEAT:
115 hw_twrap |= R300_TX_REPEAT | R300_TX_MIRRORED;
116 break;
117 case GL_MIRROR_CLAMP_EXT:
118 hw_twrap |= R300_TX_CLAMP | R300_TX_MIRRORED;
119 break;
120 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
121 hw_twrap |= R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED;
122 break;
123 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
124 hw_twrap |= R300_TX_CLAMP_TO_BORDER | R300_TX_MIRRORED;
125 break;
126 default:
127 _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
128 }
129
130 switch (rwrap) {
131 case GL_REPEAT:
132 hw_qwrap |= R300_TX_REPEAT;
133 break;
134 case GL_CLAMP:
135 hw_qwrap |= R300_TX_CLAMP;
136 break;
137 case GL_CLAMP_TO_EDGE:
138 hw_qwrap |= R300_TX_CLAMP_TO_EDGE;
139 break;
140 case GL_CLAMP_TO_BORDER:
141 hw_qwrap |= R300_TX_CLAMP_TO_BORDER;
142 break;
143 case GL_MIRRORED_REPEAT:
144 hw_qwrap |= R300_TX_REPEAT | R300_TX_MIRRORED;
145 break;
146 case GL_MIRROR_CLAMP_EXT:
147 hw_qwrap |= R300_TX_CLAMP | R300_TX_MIRRORED;
148 break;
149 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
150 hw_qwrap |= R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED;
151 break;
152 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
153 hw_qwrap |= R300_TX_CLAMP_TO_BORDER | R300_TX_MIRRORED;
154 break;
155 default:
156 _mesa_problem(NULL, "bad R wrap mode in %s", __FUNCTION__);
157 }
158
159 t->filter |= hw_swrap << R300_TX_WRAP_S_SHIFT;
160 t->filter |= hw_twrap << R300_TX_WRAP_T_SHIFT;
161 t->filter |= hw_qwrap << R300_TX_WRAP_Q_SHIFT;
162
163 #if 0
164 t->format_x &= ~R200_CLAMP_Q_MASK;
165 t->border_fallback = (is_clamp && is_clamp_to_border);
166 #endif
167 }
168
169 static void r300SetTexMaxAnisotropy(r300TexObjPtr t, GLfloat max)
170 {
171
172 t->filter &= ~R300_TX_MAX_ANISO_MASK;
173
174 if (max <= 1.0) {
175 t->filter |= R300_TX_MAX_ANISO_1_TO_1;
176 } else if (max <= 2.0) {
177 t->filter |= R300_TX_MAX_ANISO_2_TO_1;
178 } else if (max <= 4.0) {
179 t->filter |= R300_TX_MAX_ANISO_4_TO_1;
180 } else if (max <= 8.0) {
181 t->filter |= R300_TX_MAX_ANISO_8_TO_1;
182 } else {
183 t->filter |= R300_TX_MAX_ANISO_16_TO_1;
184 }
185 }
186
187 /**
188 * Set the texture magnification and minification modes.
189 *
190 * \param t Texture whose filter modes are to be set
191 * \param minf Texture minification mode
192 * \param magf Texture magnification mode
193 */
194
195 static void r300SetTexFilter(r300TexObjPtr t, GLenum minf, GLenum magf)
196 {
197 GLuint anisotropy = (t->filter & R300_TX_MAX_ANISO_MASK);
198
199 t->filter &= ~(R300_TX_MIN_FILTER_MASK | R300_TX_MAG_FILTER_MASK);
200 #if 0
201 //t->format_x &= ~R200_VOLUME_FILTER_MASK;
202 #endif
203
204 if (anisotropy == R300_TX_MAX_ANISO_1_TO_1) {
205 switch (minf) {
206 case GL_NEAREST:
207 t->filter |= R300_TX_MIN_FILTER_NEAREST;
208 break;
209 case GL_LINEAR:
210 t->filter |= R300_TX_MIN_FILTER_LINEAR;
211 break;
212 case GL_NEAREST_MIPMAP_NEAREST:
213 t->filter |= R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST;
214 break;
215 case GL_NEAREST_MIPMAP_LINEAR:
216 t->filter |= R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR;
217 break;
218 case GL_LINEAR_MIPMAP_NEAREST:
219 t->filter |= R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST;
220 break;
221 case GL_LINEAR_MIPMAP_LINEAR:
222 t->filter |= R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR;
223 break;
224 }
225 } else {
226 switch (minf) {
227 case GL_NEAREST:
228 t->filter |= R300_TX_MIN_FILTER_ANISO_NEAREST;
229 break;
230 case GL_LINEAR:
231 t->filter |= R300_TX_MIN_FILTER_ANISO_LINEAR;
232 break;
233 case GL_NEAREST_MIPMAP_NEAREST:
234 case GL_LINEAR_MIPMAP_NEAREST:
235 t->filter |=
236 R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
237 break;
238 case GL_NEAREST_MIPMAP_LINEAR:
239 case GL_LINEAR_MIPMAP_LINEAR:
240 t->filter |=
241 R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR;
242 break;
243 }
244 }
245
246 /* Note we don't have 3D mipmaps so only use the mag filter setting
247 * to set the 3D texture filter mode.
248 */
249 switch (magf) {
250 case GL_NEAREST:
251 t->filter |= R300_TX_MAG_FILTER_NEAREST;
252 /*t->format_x |= R200_VOLUME_FILTER_NEAREST;*/
253 break;
254 case GL_LINEAR:
255 t->filter |= R300_TX_MAG_FILTER_LINEAR;
256 /*t->format_x |= R200_VOLUME_FILTER_LINEAR;*/
257 break;
258 }
259 }
260
261 static void r300SetTexBorderColor(r300TexObjPtr t, GLubyte c[4])
262 {
263 t->pp_border_color = r300PackColor(4, c[0], c[1], c[2], c[3]);
264 }
265
266 /**
267 * Allocate space for and load the mesa images into the texture memory block.
268 * This will happen before drawing with a new texture, or drawing with a
269 * texture after it was swapped out or teximaged again.
270 */
271
272 static r300TexObjPtr r300AllocTexObj(struct gl_texture_object *texObj)
273 {
274 r300TexObjPtr t;
275
276 t = CALLOC_STRUCT(r300_tex_obj);
277 texObj->DriverData = t;
278 if (t != NULL) {
279 if (RADEON_DEBUG & DEBUG_TEXTURE) {
280 fprintf(stderr, "%s( %p, %p )\n", __FUNCTION__,
281 (void *)texObj, (void *)t);
282 }
283
284 /* Initialize non-image-dependent parts of the state:
285 */
286 t->base.tObj = texObj;
287 t->border_fallback = GL_FALSE;
288
289 make_empty_list(&t->base);
290
291 r300SetTexWrap(t, texObj->WrapS, texObj->WrapT, texObj->WrapR);
292 r300SetTexMaxAnisotropy(t, texObj->MaxAnisotropy);
293 r300SetTexFilter(t, texObj->MinFilter, texObj->MagFilter);
294 r300SetTexBorderColor(t, texObj->_BorderChan);
295 }
296
297 return t;
298 }
299
300 static const struct gl_texture_format *r300ChooseTextureFormat(GLcontext * ctx,
301 GLint
302 internalFormat,
303 GLenum format,
304 GLenum type)
305 {
306 r300ContextPtr rmesa = R300_CONTEXT(ctx);
307 const GLboolean do32bpt =
308 (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32);
309 const GLboolean force16bpt =
310 (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16);
311 (void)format;
312
313 #if 0
314 fprintf(stderr, "InternalFormat=%s(%d) type=%s format=%s\n",
315 _mesa_lookup_enum_by_nr(internalFormat), internalFormat,
316 _mesa_lookup_enum_by_nr(type),
317 _mesa_lookup_enum_by_nr(format));
318 fprintf(stderr, "do32bpt=%d force16bpt=%d\n",
319 do32bpt, force16bpt);
320 #endif
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 case GL_RGB_S3TC:
430 case GL_RGB4_S3TC:
431 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
432 return &_mesa_texformat_rgb_dxt1;
433
434 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
435 return &_mesa_texformat_rgba_dxt1;
436
437 case GL_RGBA_S3TC:
438 case GL_RGBA4_S3TC:
439 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
440 return &_mesa_texformat_rgba_dxt3;
441
442 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
443 return &_mesa_texformat_rgba_dxt5;
444
445 default:
446 _mesa_problem(ctx,
447 "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
448 (int)internalFormat);
449 return NULL;
450 }
451
452 return NULL; /* never get here */
453 }
454
455 static GLboolean
456 r300ValidateClientStorage(GLcontext * ctx, GLenum target,
457 GLint internalFormat,
458 GLint srcWidth, GLint srcHeight,
459 GLenum format, GLenum type, const void *pixels,
460 const struct gl_pixelstore_attrib *packing,
461 struct gl_texture_object *texObj,
462 struct gl_texture_image *texImage)
463 {
464 r300ContextPtr rmesa = R300_CONTEXT(ctx);
465
466 if (0)
467 fprintf(stderr, "intformat %s format %s type %s\n",
468 _mesa_lookup_enum_by_nr(internalFormat),
469 _mesa_lookup_enum_by_nr(format),
470 _mesa_lookup_enum_by_nr(type));
471
472 if (!ctx->Unpack.ClientStorage)
473 return 0;
474
475 if (ctx->_ImageTransferState ||
476 texImage->IsCompressed || texObj->GenerateMipmap)
477 return 0;
478
479 /* This list is incomplete, may be different on ppc???
480 */
481 switch (internalFormat) {
482 case GL_RGBA:
483 if (format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
484 texImage->TexFormat = _dri_texformat_argb8888;
485 } else
486 return 0;
487 break;
488
489 case GL_RGB:
490 if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
491 texImage->TexFormat = _dri_texformat_rgb565;
492 } else
493 return 0;
494 break;
495
496 case GL_YCBCR_MESA:
497 if (format == GL_YCBCR_MESA &&
498 type == GL_UNSIGNED_SHORT_8_8_REV_APPLE) {
499 texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
500 } else if (format == GL_YCBCR_MESA &&
501 (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
502 type == GL_UNSIGNED_BYTE)) {
503 texImage->TexFormat = &_mesa_texformat_ycbcr;
504 } else
505 return 0;
506 break;
507
508 default:
509 return 0;
510 }
511
512 /* Could deal with these packing issues, but currently don't:
513 */
514 if (packing->SkipPixels ||
515 packing->SkipRows || packing->SwapBytes || packing->LsbFirst) {
516 return 0;
517 }
518
519 {
520 GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
521 format, type);
522
523 if (0)
524 fprintf(stderr, "%s: srcRowStride %d/%x\n",
525 __FUNCTION__, srcRowStride, srcRowStride);
526
527 /* Could check this later in upload, pitch restrictions could be
528 * relaxed, but would need to store the image pitch somewhere,
529 * as packing details might change before image is uploaded:
530 */
531 if (!r300IsGartMemory(rmesa, pixels, srcHeight * srcRowStride)
532 || (srcRowStride & 63))
533 return 0;
534
535 /* Have validated that _mesa_transfer_teximage would be a straight
536 * memcpy at this point. NOTE: future calls to TexSubImage will
537 * overwrite the client data. This is explicitly mentioned in the
538 * extension spec.
539 */
540 texImage->Data = (void *)pixels;
541 texImage->IsClientData = GL_TRUE;
542 texImage->RowStride =
543 srcRowStride / texImage->TexFormat->TexelBytes;
544
545 return 1;
546 }
547 }
548
549 static void r300TexImage1D(GLcontext * ctx, GLenum target, GLint level,
550 GLint internalFormat,
551 GLint width, GLint border,
552 GLenum format, GLenum type, const GLvoid * pixels,
553 const struct gl_pixelstore_attrib *packing,
554 struct gl_texture_object *texObj,
555 struct gl_texture_image *texImage)
556 {
557 driTextureObject *t = (driTextureObject *) texObj->DriverData;
558
559 if (t) {
560 driSwapOutTextureObject(t);
561 } else {
562 t = (driTextureObject *) r300AllocTexObj(texObj);
563 if (!t) {
564 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
565 return;
566 }
567 }
568
569 /* Note, this will call ChooseTextureFormat */
570 _mesa_store_teximage1d(ctx, target, level, internalFormat,
571 width, border, format, type, pixels,
572 &ctx->Unpack, texObj, texImage);
573
574 t->dirty_images[0] |= (1 << level);
575 }
576
577 static void r300TexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
578 GLint xoffset,
579 GLsizei width,
580 GLenum format, GLenum type,
581 const GLvoid * pixels,
582 const struct gl_pixelstore_attrib *packing,
583 struct gl_texture_object *texObj,
584 struct gl_texture_image *texImage)
585 {
586 driTextureObject *t = (driTextureObject *) texObj->DriverData;
587
588 assert(t); /* this _should_ be true */
589 if (t) {
590 driSwapOutTextureObject(t);
591 } else {
592 t = (driTextureObject *) r300AllocTexObj(texObj);
593 if (!t) {
594 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
595 return;
596 }
597 }
598
599 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
600 format, type, pixels, packing, texObj,
601 texImage);
602
603 t->dirty_images[0] |= (1 << level);
604 }
605
606 static void r300TexImage2D(GLcontext * ctx, GLenum target, GLint level,
607 GLint internalFormat,
608 GLint width, GLint height, GLint border,
609 GLenum format, GLenum type, const GLvoid * pixels,
610 const struct gl_pixelstore_attrib *packing,
611 struct gl_texture_object *texObj,
612 struct gl_texture_image *texImage)
613 {
614 driTextureObject *t = (driTextureObject *) texObj->DriverData;
615 GLuint face;
616
617 /* which cube face or ordinary 2D image */
618 switch (target) {
619 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
620 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
621 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
622 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
623 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
624 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
625 face =
626 (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
627 ASSERT(face < 6);
628 break;
629 default:
630 face = 0;
631 }
632
633 if (t != NULL) {
634 driSwapOutTextureObject(t);
635 } else {
636 t = (driTextureObject *) r300AllocTexObj(texObj);
637 if (!t) {
638 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
639 return;
640 }
641 }
642
643 texImage->IsClientData = GL_FALSE;
644
645 if (r300ValidateClientStorage(ctx, target,
646 internalFormat,
647 width, height,
648 format, type, pixels,
649 packing, texObj, texImage)) {
650 if (RADEON_DEBUG & DEBUG_TEXTURE)
651 fprintf(stderr, "%s: Using client storage\n",
652 __FUNCTION__);
653 } else {
654 if (RADEON_DEBUG & DEBUG_TEXTURE)
655 fprintf(stderr, "%s: Using normal storage\n",
656 __FUNCTION__);
657
658 /* Normal path: copy (to cached memory) and eventually upload
659 * via another copy to GART memory and then a blit... Could
660 * eliminate one copy by going straight to (permanent) GART.
661 *
662 * Note, this will call r300ChooseTextureFormat.
663 */
664 _mesa_store_teximage2d(ctx, target, level, internalFormat,
665 width, height, border, format, type,
666 pixels, &ctx->Unpack, texObj, texImage);
667
668 t->dirty_images[face] |= (1 << level);
669 }
670 }
671
672 static void r300TexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
673 GLint xoffset, GLint yoffset,
674 GLsizei width, GLsizei height,
675 GLenum format, GLenum type,
676 const GLvoid * pixels,
677 const struct gl_pixelstore_attrib *packing,
678 struct gl_texture_object *texObj,
679 struct gl_texture_image *texImage)
680 {
681 driTextureObject *t = (driTextureObject *) texObj->DriverData;
682 GLuint face;
683
684 /* which cube face or ordinary 2D image */
685 switch (target) {
686 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
687 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
688 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
689 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
690 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
691 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
692 face =
693 (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
694 ASSERT(face < 6);
695 break;
696 default:
697 face = 0;
698 }
699
700 assert(t); /* this _should_ be true */
701 if (t) {
702 driSwapOutTextureObject(t);
703 } else {
704 t = (driTextureObject *) r300AllocTexObj(texObj);
705 if (!t) {
706 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
707 return;
708 }
709 }
710
711 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
712 height, format, type, pixels, packing, texObj,
713 texImage);
714
715 t->dirty_images[face] |= (1 << level);
716 }
717
718 static void r300CompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
719 GLint internalFormat,
720 GLint width, GLint height, GLint border,
721 GLsizei imageSize, const GLvoid *data,
722 struct gl_texture_object *texObj,
723 struct gl_texture_image *texImage )
724 {
725 driTextureObject * t = (driTextureObject *) texObj->DriverData;
726 GLuint face;
727
728 /* which cube face or ordinary 2D image */
729 switch (target) {
730 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
731 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
732 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
733 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
734 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
735 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
736 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
737 ASSERT(face < 6);
738 break;
739 default:
740 face = 0;
741 }
742
743 if ( t != NULL ) {
744 driSwapOutTextureObject( t );
745 }
746 else {
747 t = (driTextureObject *) r300AllocTexObj( texObj );
748 if (!t) {
749 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
750 return;
751 }
752 }
753
754 texImage->IsClientData = GL_FALSE;
755 /* can't call this, different parameters. Would never evaluate to true anyway currently
756 if (r300ValidateClientStorage( ctx, target,
757 internalFormat,
758 width, height,
759 format, type, pixels,
760 packing, texObj, texImage)) {
761 if (RADEON_DEBUG & DEBUG_TEXTURE)
762 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
763 }
764 else */{
765 if (RADEON_DEBUG & DEBUG_TEXTURE)
766 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
767
768 /* Normal path: copy (to cached memory) and eventually upload
769 * via another copy to GART memory and then a blit... Could
770 * eliminate one copy by going straight to (permanent) GART.
771 *
772 * Note, this will call r300ChooseTextureFormat.
773 */
774 _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
775 height, border, imageSize, data, texObj, texImage);
776
777 t->dirty_images[face] |= (1 << level);
778 }
779 }
780
781
782 static void r300CompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
783 GLint xoffset, GLint yoffset,
784 GLsizei width, GLsizei height,
785 GLenum format,
786 GLsizei imageSize, const GLvoid *data,
787 struct gl_texture_object *texObj,
788 struct gl_texture_image *texImage )
789 {
790 driTextureObject * t = (driTextureObject *) texObj->DriverData;
791 GLuint face;
792
793
794 /* which cube face or ordinary 2D image */
795 switch (target) {
796 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
797 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
798 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
799 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
800 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
801 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
802 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
803 ASSERT(face < 6);
804 break;
805 default:
806 face = 0;
807 }
808
809 assert( t ); /* this _should_ be true */
810 if ( t ) {
811 driSwapOutTextureObject( t );
812 }
813 else {
814 t = (driTextureObject *) r300AllocTexObj( texObj );
815 if (!t) {
816 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage3D");
817 return;
818 }
819 }
820
821 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
822 height, format, imageSize, data, texObj, texImage);
823
824 t->dirty_images[face] |= (1 << level);
825 }
826
827 #if ENABLE_HW_3D_TEXTURE
828 static void r300TexImage3D(GLcontext * ctx, GLenum target, GLint level,
829 GLint internalFormat,
830 GLint width, GLint height, GLint depth,
831 GLint border,
832 GLenum format, GLenum type, const GLvoid * pixels,
833 const struct gl_pixelstore_attrib *packing,
834 struct gl_texture_object *texObj,
835 struct gl_texture_image *texImage)
836 {
837 driTextureObject *t = (driTextureObject *) texObj->DriverData;
838
839 if (t) {
840 driSwapOutTextureObject(t);
841 } else {
842 t = (driTextureObject *) r300AllocTexObj(texObj);
843 if (!t) {
844 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
845 return;
846 }
847 }
848
849 texImage->IsClientData = GL_FALSE;
850
851 #if 0
852 if (r300ValidateClientStorage(ctx, target,
853 internalFormat,
854 width, height,
855 format, type, pixels,
856 packing, texObj, texImage)) {
857 if (RADEON_DEBUG & DEBUG_TEXTURE)
858 fprintf(stderr, "%s: Using client storage\n",
859 __FUNCTION__);
860 } else
861 #endif
862 {
863 if (RADEON_DEBUG & DEBUG_TEXTURE)
864 fprintf(stderr, "%s: Using normal storage\n",
865 __FUNCTION__);
866
867 /* Normal path: copy (to cached memory) and eventually upload
868 * via another copy to GART memory and then a blit... Could
869 * eliminate one copy by going straight to (permanent) GART.
870 *
871 * Note, this will call r300ChooseTextureFormat.
872 */
873 _mesa_store_teximage3d(ctx, target, level, internalFormat,
874 width, height, depth, border,
875 format, type, pixels,
876 &ctx->Unpack, texObj, texImage);
877
878 t->dirty_images[0] |= (1 << level);
879 }
880 }
881 #endif
882
883 #if ENABLE_HW_3D_TEXTURE
884 static void
885 r300TexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
886 GLint xoffset, GLint yoffset, GLint zoffset,
887 GLsizei width, GLsizei height, GLsizei depth,
888 GLenum format, GLenum type,
889 const GLvoid * pixels,
890 const struct gl_pixelstore_attrib *packing,
891 struct gl_texture_object *texObj,
892 struct gl_texture_image *texImage)
893 {
894 driTextureObject *t = (driTextureObject *) texObj->DriverData;
895
896 /* fprintf(stderr, "%s\n", __FUNCTION__); */
897
898 assert(t); /* this _should_ be true */
899 if (t) {
900 driSwapOutTextureObject(t);
901 } else {
902 t = (driTextureObject *) r300AllocTexObj(texObj);
903 if (!t) {
904 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
905 return;
906 }
907 texObj->DriverData = t;
908 }
909
910 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
911 width, height, depth,
912 format, type, pixels, packing, texObj,
913 texImage);
914
915 t->dirty_images[0] |= (1 << level);
916 }
917 #endif
918
919 static void r300TexEnv(GLcontext * ctx, GLenum target,
920 GLenum pname, const GLfloat * param)
921 {
922 r300ContextPtr rmesa = R300_CONTEXT(ctx);
923 GLuint unit = ctx->Texture.CurrentUnit;
924
925 if (RADEON_DEBUG & DEBUG_STATE) {
926 fprintf(stderr, "%s( %s )\n",
927 __FUNCTION__, _mesa_lookup_enum_by_nr(pname));
928 }
929
930 /* This is incorrect: Need to maintain this data for each of
931 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
932 * between them according to _ReallyEnabled.
933 */
934 switch (pname) {
935 case GL_TEXTURE_ENV_COLOR:{
936 WARN_ONCE("I am broken - Fixme !\n");
937 /*
938 GLubyte c[4];
939 GLuint envColor;
940 UNCLAMPED_FLOAT_TO_RGBA_CHAN(c, texUnit->EnvColor);
941 envColor = radeonPackColor(4, c[0], c[1], c[2], c[3]);
942 if (rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor) {
943 R200_STATECHANGE(rmesa, tf);
944 rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] =
945 envColor;
946 }*/
947 break;
948 }
949
950 case GL_TEXTURE_LOD_BIAS_EXT:{
951 GLfloat bias, min;
952 GLuint b;
953
954 /* The R300's LOD bias is a signed 2's complement value with a
955 * range of -16.0 <= bias < 16.0.
956 *
957 * NOTE: Add a small bias to the bias for conform mipsel.c test.
958 */
959 bias = *param + .01;
960 min =
961 driQueryOptionb(&rmesa->radeon.optionCache,
962 "no_neg_lod_bias") ? 0.0 : -16.0;
963 bias = CLAMP(bias, min, 16.0);
964
965 /* 0.0 - 16.0 == 0x0 - 0x1000 */
966 /* 0.0 - -16.0 == 0x1001 - 0x1fff */
967 b = 0x1000 / 16.0 * bias;
968 b &= R300_LOD_BIAS_MASK;
969
970 if(b != (rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] & R300_LOD_BIAS_MASK)){
971 R300_STATECHANGE(rmesa, tex.unknown1);
972 rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] &= ~R300_LOD_BIAS_MASK;
973 rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] |= b;
974 }
975 break;
976 }
977
978 default:
979 return;
980 }
981 }
982
983 /**
984 * Changes variables and flags for a state update, which will happen at the
985 * next UpdateTextureState
986 */
987
988 static void r300TexParameter(GLcontext * ctx, GLenum target,
989 struct gl_texture_object *texObj,
990 GLenum pname, const GLfloat * params)
991 {
992 r300TexObjPtr t = (r300TexObjPtr) texObj->DriverData;
993
994 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
995 fprintf(stderr, "%s( %s )\n", __FUNCTION__,
996 _mesa_lookup_enum_by_nr(pname));
997 }
998
999 switch (pname) {
1000 case GL_TEXTURE_MIN_FILTER:
1001 case GL_TEXTURE_MAG_FILTER:
1002 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1003 r300SetTexMaxAnisotropy(t, texObj->MaxAnisotropy);
1004 r300SetTexFilter(t, texObj->MinFilter, texObj->MagFilter);
1005 break;
1006
1007 case GL_TEXTURE_WRAP_S:
1008 case GL_TEXTURE_WRAP_T:
1009 case GL_TEXTURE_WRAP_R:
1010 r300SetTexWrap(t, texObj->WrapS, texObj->WrapT, texObj->WrapR);
1011 break;
1012
1013 case GL_TEXTURE_BORDER_COLOR:
1014 r300SetTexBorderColor(t, texObj->_BorderChan);
1015 break;
1016
1017 case GL_TEXTURE_BASE_LEVEL:
1018 case GL_TEXTURE_MAX_LEVEL:
1019 case GL_TEXTURE_MIN_LOD:
1020 case GL_TEXTURE_MAX_LOD:
1021 /* This isn't the most efficient solution but there doesn't appear to
1022 * be a nice alternative. Since there's no LOD clamping,
1023 * we just have to rely on loading the right subset of mipmap levels
1024 * to simulate a clamped LOD.
1025 */
1026 driSwapOutTextureObject((driTextureObject *) t);
1027 break;
1028
1029 default:
1030 return;
1031 }
1032
1033 /* Mark this texobj as dirty (one bit per tex unit)
1034 */
1035 t->dirty_state = TEX_ALL;
1036 }
1037
1038 static void r300BindTexture(GLcontext * ctx, GLenum target,
1039 struct gl_texture_object *texObj)
1040 {
1041 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
1042 fprintf(stderr, "%s( %p ) unit=%d\n", __FUNCTION__,
1043 (void *)texObj, ctx->Texture.CurrentUnit);
1044 }
1045
1046 if ((target == GL_TEXTURE_1D)
1047 || (target == GL_TEXTURE_2D)
1048 #if ENABLE_HW_3D_TEXTURE
1049 || (target == GL_TEXTURE_3D)
1050 #endif
1051 || (target == GL_TEXTURE_CUBE_MAP)
1052 || (target == GL_TEXTURE_RECTANGLE_NV)) {
1053 assert(texObj->DriverData != NULL);
1054 }
1055 }
1056
1057 static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
1058 {
1059 r300ContextPtr rmesa = R300_CONTEXT(ctx);
1060 driTextureObject *t = (driTextureObject *) texObj->DriverData;
1061
1062 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
1063 fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__,
1064 (void *)texObj,
1065 _mesa_lookup_enum_by_nr(texObj->Target));
1066 }
1067
1068 if (t != NULL) {
1069 if (rmesa) {
1070 R300_FIREVERTICES(rmesa);
1071 }
1072
1073 driDestroyTextureObject(t);
1074 }
1075 /* Free mipmap images and the texture object itself */
1076 _mesa_delete_texture_object(ctx, texObj);
1077 }
1078
1079 /**
1080 * Allocate a new texture object.
1081 * Called via ctx->Driver.NewTextureObject.
1082 * Note: this function will be called during context creation to
1083 * allocate the default texture objects.
1084 * Note: we could use containment here to 'derive' the driver-specific
1085 * texture object from the core mesa gl_texture_object. Not done at this time.
1086 * Fixup MaxAnisotropy according to user preference.
1087 */
1088 static struct gl_texture_object *r300NewTextureObject(GLcontext * ctx,
1089 GLuint name,
1090 GLenum target)
1091 {
1092 r300ContextPtr rmesa = R300_CONTEXT(ctx);
1093 struct gl_texture_object *obj;
1094 obj = _mesa_new_texture_object(ctx, name, target);
1095 if (!obj)
1096 return NULL;
1097 obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
1098
1099 r300AllocTexObj(obj);
1100 return obj;
1101 }
1102
1103 void r300InitTextureFuncs(struct dd_function_table *functions)
1104 {
1105 /* Note: we only plug in the functions we implement in the driver
1106 * since _mesa_init_driver_functions() was already called.
1107 */
1108 functions->ChooseTextureFormat = r300ChooseTextureFormat;
1109 functions->TexImage1D = r300TexImage1D;
1110 functions->TexImage2D = r300TexImage2D;
1111 #if ENABLE_HW_3D_TEXTURE
1112 functions->TexImage3D = r300TexImage3D;
1113 #else
1114 functions->TexImage3D = _mesa_store_teximage3d;
1115 #endif
1116 functions->TexSubImage1D = r300TexSubImage1D;
1117 functions->TexSubImage2D = r300TexSubImage2D;
1118 #if ENABLE_HW_3D_TEXTURE
1119 functions->TexSubImage3D = r300TexSubImage3D;
1120 #else
1121 functions->TexSubImage3D = _mesa_store_texsubimage3d;
1122 #endif
1123 functions->NewTextureObject = r300NewTextureObject;
1124 functions->BindTexture = r300BindTexture;
1125 functions->DeleteTexture = r300DeleteTexture;
1126 functions->IsTextureResident = driIsTextureResident;
1127
1128 functions->TexEnv = r300TexEnv;
1129 functions->TexParameter = r300TexParameter;
1130
1131 functions->CompressedTexImage2D = r300CompressedTexImage2D;
1132 functions->CompressedTexSubImage2D = r300CompressedTexSubImage2D;
1133
1134 driInitTextureFormats();
1135
1136 #if 0
1137 /* moved or obsolete code */
1138 r300ContextPtr rmesa = R300_CONTEXT(ctx);
1139 driInitTextureObjects(ctx, &rmesa->swapped,
1140 DRI_TEXMGR_DO_TEXTURE_1D
1141 | DRI_TEXMGR_DO_TEXTURE_2D);
1142
1143 /* Hack: r300NewTextureObject is not yet installed when the
1144 * default textures are created. Therefore set MaxAnisotropy of the
1145 * default 2D texture now. */
1146 ctx->Shared->Default2D->MaxAnisotropy =
1147 driQueryOptionf(&rmesa->optionCache, "def_max_anisotropy");
1148 #endif
1149 }