62f3dcfeef2ce84ca9d613e38dfd20cb2870a40c
[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_NEAREST_MIP_LINEAR;
224 break;
225 case GL_LINEAR_MIPMAP_NEAREST:
226 t->filter |= R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST;
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 case GL_RGB_S3TC:
437 case GL_RGB4_S3TC:
438 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
439 return &_mesa_texformat_rgb_dxt1;
440
441 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
442 return &_mesa_texformat_rgba_dxt1;
443
444 case GL_RGBA_S3TC:
445 case GL_RGBA4_S3TC:
446 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
447 return &_mesa_texformat_rgba_dxt3;
448
449 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
450 return &_mesa_texformat_rgba_dxt5;
451
452 default:
453 _mesa_problem(ctx,
454 "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
455 (int)internalFormat);
456 return NULL;
457 }
458
459 return NULL; /* never get here */
460 }
461
462 static GLboolean
463 r300ValidateClientStorage(GLcontext * ctx, GLenum target,
464 GLint internalFormat,
465 GLint srcWidth, GLint srcHeight,
466 GLenum format, GLenum type, const void *pixels,
467 const struct gl_pixelstore_attrib *packing,
468 struct gl_texture_object *texObj,
469 struct gl_texture_image *texImage)
470 {
471 r300ContextPtr rmesa = R300_CONTEXT(ctx);
472
473 if (0)
474 fprintf(stderr, "intformat %s format %s type %s\n",
475 _mesa_lookup_enum_by_nr(internalFormat),
476 _mesa_lookup_enum_by_nr(format),
477 _mesa_lookup_enum_by_nr(type));
478
479 if (!ctx->Unpack.ClientStorage)
480 return 0;
481
482 if (ctx->_ImageTransferState ||
483 texImage->IsCompressed || texObj->GenerateMipmap)
484 return 0;
485
486 /* This list is incomplete, may be different on ppc???
487 */
488 switch (internalFormat) {
489 case GL_RGBA:
490 if (format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
491 texImage->TexFormat = _dri_texformat_argb8888;
492 } else
493 return 0;
494 break;
495
496 case GL_RGB:
497 if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
498 texImage->TexFormat = _dri_texformat_rgb565;
499 } else
500 return 0;
501 break;
502
503 case GL_YCBCR_MESA:
504 if (format == GL_YCBCR_MESA &&
505 type == GL_UNSIGNED_SHORT_8_8_REV_APPLE) {
506 texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
507 } else if (format == GL_YCBCR_MESA &&
508 (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
509 type == GL_UNSIGNED_BYTE)) {
510 texImage->TexFormat = &_mesa_texformat_ycbcr;
511 } else
512 return 0;
513 break;
514
515 default:
516 return 0;
517 }
518
519 /* Could deal with these packing issues, but currently don't:
520 */
521 if (packing->SkipPixels ||
522 packing->SkipRows || packing->SwapBytes || packing->LsbFirst) {
523 return 0;
524 }
525
526 {
527 GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
528 format, type);
529
530 if (0)
531 fprintf(stderr, "%s: srcRowStride %d/%x\n",
532 __FUNCTION__, srcRowStride, srcRowStride);
533
534 /* Could check this later in upload, pitch restrictions could be
535 * relaxed, but would need to store the image pitch somewhere,
536 * as packing details might change before image is uploaded:
537 */
538 if (!r300IsGartMemory(rmesa, pixels, srcHeight * srcRowStride)
539 || (srcRowStride & 63))
540 return 0;
541
542 /* Have validated that _mesa_transfer_teximage would be a straight
543 * memcpy at this point. NOTE: future calls to TexSubImage will
544 * overwrite the client data. This is explicitly mentioned in the
545 * extension spec.
546 */
547 texImage->Data = (void *)pixels;
548 texImage->IsClientData = GL_TRUE;
549 texImage->RowStride =
550 srcRowStride / texImage->TexFormat->TexelBytes;
551
552 return 1;
553 }
554 }
555
556 static void r300TexImage1D(GLcontext * ctx, GLenum target, GLint level,
557 GLint internalFormat,
558 GLint width, GLint border,
559 GLenum format, GLenum type, const GLvoid * pixels,
560 const struct gl_pixelstore_attrib *packing,
561 struct gl_texture_object *texObj,
562 struct gl_texture_image *texImage)
563 {
564 driTextureObject *t = (driTextureObject *) texObj->DriverData;
565
566 if (t) {
567 driSwapOutTextureObject(t);
568 } else {
569 t = (driTextureObject *) r300AllocTexObj(texObj);
570 if (!t) {
571 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
572 return;
573 }
574 }
575
576 /* Note, this will call ChooseTextureFormat */
577 _mesa_store_teximage1d(ctx, target, level, internalFormat,
578 width, border, format, type, pixels,
579 &ctx->Unpack, texObj, texImage);
580
581 t->dirty_images[0] |= (1 << level);
582 }
583
584 static void r300TexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
585 GLint xoffset,
586 GLsizei width,
587 GLenum format, GLenum type,
588 const GLvoid * pixels,
589 const struct gl_pixelstore_attrib *packing,
590 struct gl_texture_object *texObj,
591 struct gl_texture_image *texImage)
592 {
593 driTextureObject *t = (driTextureObject *) texObj->DriverData;
594
595 assert(t); /* this _should_ be true */
596 if (t) {
597 driSwapOutTextureObject(t);
598 } else {
599 t = (driTextureObject *) r300AllocTexObj(texObj);
600 if (!t) {
601 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
602 return;
603 }
604 }
605
606 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
607 format, type, pixels, packing, texObj,
608 texImage);
609
610 t->dirty_images[0] |= (1 << level);
611 }
612
613 static void r300TexImage2D(GLcontext * ctx, GLenum target, GLint level,
614 GLint internalFormat,
615 GLint width, GLint height, GLint border,
616 GLenum format, GLenum type, const GLvoid * pixels,
617 const struct gl_pixelstore_attrib *packing,
618 struct gl_texture_object *texObj,
619 struct gl_texture_image *texImage)
620 {
621 driTextureObject *t = (driTextureObject *) texObj->DriverData;
622 GLuint face;
623
624 /* which cube face or ordinary 2D image */
625 switch (target) {
626 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
627 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
628 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
629 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
630 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
631 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
632 face =
633 (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
634 ASSERT(face < 6);
635 break;
636 default:
637 face = 0;
638 }
639
640 if (t != NULL) {
641 driSwapOutTextureObject(t);
642 } else {
643 t = (driTextureObject *) r300AllocTexObj(texObj);
644 if (!t) {
645 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
646 return;
647 }
648 }
649
650 texImage->IsClientData = GL_FALSE;
651
652 if (r300ValidateClientStorage(ctx, target,
653 internalFormat,
654 width, height,
655 format, type, pixels,
656 packing, texObj, texImage)) {
657 if (RADEON_DEBUG & DEBUG_TEXTURE)
658 fprintf(stderr, "%s: Using client storage\n",
659 __FUNCTION__);
660 } else {
661 if (RADEON_DEBUG & DEBUG_TEXTURE)
662 fprintf(stderr, "%s: Using normal storage\n",
663 __FUNCTION__);
664
665 /* Normal path: copy (to cached memory) and eventually upload
666 * via another copy to GART memory and then a blit... Could
667 * eliminate one copy by going straight to (permanent) GART.
668 *
669 * Note, this will call r300ChooseTextureFormat.
670 */
671 _mesa_store_teximage2d(ctx, target, level, internalFormat,
672 width, height, border, format, type,
673 pixels, &ctx->Unpack, texObj, texImage);
674
675 t->dirty_images[face] |= (1 << level);
676 }
677 }
678
679 static void r300TexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
680 GLint xoffset, GLint yoffset,
681 GLsizei width, GLsizei height,
682 GLenum format, GLenum type,
683 const GLvoid * pixels,
684 const struct gl_pixelstore_attrib *packing,
685 struct gl_texture_object *texObj,
686 struct gl_texture_image *texImage)
687 {
688 driTextureObject *t = (driTextureObject *) texObj->DriverData;
689 GLuint face;
690
691 /* which cube face or ordinary 2D image */
692 switch (target) {
693 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
694 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
695 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
696 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
697 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
698 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
699 face =
700 (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
701 ASSERT(face < 6);
702 break;
703 default:
704 face = 0;
705 }
706
707 assert(t); /* this _should_ be true */
708 if (t) {
709 driSwapOutTextureObject(t);
710 } else {
711 t = (driTextureObject *) r300AllocTexObj(texObj);
712 if (!t) {
713 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
714 return;
715 }
716 }
717
718 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
719 height, format, type, pixels, packing, texObj,
720 texImage);
721
722 t->dirty_images[face] |= (1 << level);
723 }
724
725 static void r300CompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
726 GLint internalFormat,
727 GLint width, GLint height, GLint border,
728 GLsizei imageSize, const GLvoid *data,
729 struct gl_texture_object *texObj,
730 struct gl_texture_image *texImage )
731 {
732 driTextureObject * t = (driTextureObject *) texObj->DriverData;
733 GLuint face;
734
735 /* which cube face or ordinary 2D image */
736 switch (target) {
737 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
738 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
739 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
740 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
741 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
742 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
743 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
744 ASSERT(face < 6);
745 break;
746 default:
747 face = 0;
748 }
749
750 if ( t != NULL ) {
751 driSwapOutTextureObject( t );
752 }
753 else {
754 t = (driTextureObject *) r300AllocTexObj( texObj );
755 if (!t) {
756 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
757 return;
758 }
759 }
760
761 texImage->IsClientData = GL_FALSE;
762 /* can't call this, different parameters. Would never evaluate to true anyway currently
763 if (r300ValidateClientStorage( ctx, target,
764 internalFormat,
765 width, height,
766 format, type, pixels,
767 packing, texObj, texImage)) {
768 if (RADEON_DEBUG & DEBUG_TEXTURE)
769 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
770 }
771 else */{
772 if (RADEON_DEBUG & DEBUG_TEXTURE)
773 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
774
775 /* Normal path: copy (to cached memory) and eventually upload
776 * via another copy to GART memory and then a blit... Could
777 * eliminate one copy by going straight to (permanent) GART.
778 *
779 * Note, this will call r300ChooseTextureFormat.
780 */
781 _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
782 height, border, imageSize, data, texObj, texImage);
783
784 t->dirty_images[face] |= (1 << level);
785 }
786 }
787
788
789 static void r300CompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
790 GLint xoffset, GLint yoffset,
791 GLsizei width, GLsizei height,
792 GLenum format,
793 GLsizei imageSize, const GLvoid *data,
794 struct gl_texture_object *texObj,
795 struct gl_texture_image *texImage )
796 {
797 driTextureObject * t = (driTextureObject *) texObj->DriverData;
798 GLuint face;
799
800
801 /* which cube face or ordinary 2D image */
802 switch (target) {
803 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
804 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
805 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
806 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
807 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
808 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
809 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
810 ASSERT(face < 6);
811 break;
812 default:
813 face = 0;
814 }
815
816 assert( t ); /* this _should_ be true */
817 if ( t ) {
818 driSwapOutTextureObject( t );
819 }
820 else {
821 t = (driTextureObject *) r300AllocTexObj( texObj );
822 if (!t) {
823 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage3D");
824 return;
825 }
826 }
827
828 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
829 height, format, imageSize, data, texObj, texImage);
830
831 t->dirty_images[face] |= (1 << level);
832 }
833
834 #if ENABLE_HW_3D_TEXTURE
835 static void r300TexImage3D(GLcontext * ctx, GLenum target, GLint level,
836 GLint internalFormat,
837 GLint width, GLint height, GLint depth,
838 GLint border,
839 GLenum format, GLenum type, const GLvoid * pixels,
840 const struct gl_pixelstore_attrib *packing,
841 struct gl_texture_object *texObj,
842 struct gl_texture_image *texImage)
843 {
844 driTextureObject *t = (driTextureObject *) texObj->DriverData;
845
846 if (t) {
847 driSwapOutTextureObject(t);
848 } else {
849 t = (driTextureObject *) r300AllocTexObj(texObj);
850 if (!t) {
851 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
852 return;
853 }
854 }
855
856 texImage->IsClientData = GL_FALSE;
857
858 #if 0
859 if (r300ValidateClientStorage(ctx, target,
860 internalFormat,
861 width, height,
862 format, type, pixels,
863 packing, texObj, texImage)) {
864 if (RADEON_DEBUG & DEBUG_TEXTURE)
865 fprintf(stderr, "%s: Using client storage\n",
866 __FUNCTION__);
867 } else
868 #endif
869 {
870 if (RADEON_DEBUG & DEBUG_TEXTURE)
871 fprintf(stderr, "%s: Using normal storage\n",
872 __FUNCTION__);
873
874 /* Normal path: copy (to cached memory) and eventually upload
875 * via another copy to GART memory and then a blit... Could
876 * eliminate one copy by going straight to (permanent) GART.
877 *
878 * Note, this will call r300ChooseTextureFormat.
879 */
880 _mesa_store_teximage3d(ctx, target, level, internalFormat,
881 width, height, depth, border,
882 format, type, pixels,
883 &ctx->Unpack, texObj, texImage);
884
885 t->dirty_images[0] |= (1 << level);
886 }
887 }
888 #endif
889
890 #if ENABLE_HW_3D_TEXTURE
891 static void
892 r300TexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
893 GLint xoffset, GLint yoffset, GLint zoffset,
894 GLsizei width, GLsizei height, GLsizei depth,
895 GLenum format, GLenum type,
896 const GLvoid * pixels,
897 const struct gl_pixelstore_attrib *packing,
898 struct gl_texture_object *texObj,
899 struct gl_texture_image *texImage)
900 {
901 driTextureObject *t = (driTextureObject *) texObj->DriverData;
902
903 /* fprintf(stderr, "%s\n", __FUNCTION__); */
904
905 assert(t); /* this _should_ be true */
906 if (t) {
907 driSwapOutTextureObject(t);
908 } else {
909 t = (driTextureObject *) r300AllocTexObj(texObj);
910 if (!t) {
911 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
912 return;
913 }
914 texObj->DriverData = t;
915 }
916
917 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
918 width, height, depth,
919 format, type, pixels, packing, texObj,
920 texImage);
921
922 t->dirty_images[0] |= (1 << level);
923 }
924 #endif
925
926 static void r300TexEnv(GLcontext * ctx, GLenum target,
927 GLenum pname, const GLfloat * param)
928 {
929 r300ContextPtr rmesa = R300_CONTEXT(ctx);
930 GLuint unit = ctx->Texture.CurrentUnit;
931
932 if (RADEON_DEBUG & DEBUG_STATE) {
933 fprintf(stderr, "%s( %s )\n",
934 __FUNCTION__, _mesa_lookup_enum_by_nr(pname));
935 }
936
937 /* This is incorrect: Need to maintain this data for each of
938 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
939 * between them according to _ReallyEnabled.
940 */
941 switch (pname) {
942 case GL_TEXTURE_ENV_COLOR:{
943 WARN_ONCE("I am broken - Fixme !\n");
944 /*
945 GLubyte c[4];
946 GLuint envColor;
947 UNCLAMPED_FLOAT_TO_RGBA_CHAN(c, texUnit->EnvColor);
948 envColor = radeonPackColor(4, c[0], c[1], c[2], c[3]);
949 if (rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor) {
950 R200_STATECHANGE(rmesa, tf);
951 rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] =
952 envColor;
953 }*/
954 break;
955 }
956
957 case GL_TEXTURE_LOD_BIAS_EXT:{
958 GLfloat bias, min;
959 GLuint b;
960
961 /* The R300's LOD bias is a signed 2's complement value with a
962 * range of -16.0 <= bias < 16.0.
963 *
964 * NOTE: Add a small bias to the bias for conform mipsel.c test.
965 */
966 bias = *param + .01;
967 min =
968 driQueryOptionb(&rmesa->radeon.optionCache,
969 "no_neg_lod_bias") ? 0.0 : -16.0;
970 bias = CLAMP(bias, min, 16.0);
971
972 /* 0.0 - 16.0 == 0x0 - 0x1000 */
973 /* 0.0 - -16.0 == 0x1001 - 0x1fff */
974 b = 0x1000 / 16.0 * bias;
975 b &= R300_LOD_BIAS_MASK;
976
977 if(b != (rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] & R300_LOD_BIAS_MASK)){
978 R300_STATECHANGE(rmesa, tex.unknown1);
979 rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] &= ~R300_LOD_BIAS_MASK;
980 rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] |= b;
981 }
982 break;
983 }
984
985 default:
986 return;
987 }
988 }
989
990 /**
991 * Changes variables and flags for a state update, which will happen at the
992 * next UpdateTextureState
993 */
994
995 static void r300TexParameter(GLcontext * ctx, GLenum target,
996 struct gl_texture_object *texObj,
997 GLenum pname, const GLfloat * params)
998 {
999 r300TexObjPtr t = (r300TexObjPtr) texObj->DriverData;
1000
1001 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
1002 fprintf(stderr, "%s( %s )\n", __FUNCTION__,
1003 _mesa_lookup_enum_by_nr(pname));
1004 }
1005
1006 switch (pname) {
1007 case GL_TEXTURE_MIN_FILTER:
1008 case GL_TEXTURE_MAG_FILTER:
1009 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1010 r300SetTexMaxAnisotropy(t, texObj->MaxAnisotropy);
1011 r300SetTexFilter(t, texObj->MinFilter, texObj->MagFilter);
1012 break;
1013
1014 case GL_TEXTURE_WRAP_S:
1015 case GL_TEXTURE_WRAP_T:
1016 case GL_TEXTURE_WRAP_R:
1017 r300SetTexWrap(t, texObj->WrapS, texObj->WrapT, texObj->WrapR);
1018 break;
1019
1020 case GL_TEXTURE_BORDER_COLOR:
1021 r300SetTexBorderColor(t, texObj->_BorderChan);
1022 break;
1023
1024 case GL_TEXTURE_BASE_LEVEL:
1025 case GL_TEXTURE_MAX_LEVEL:
1026 case GL_TEXTURE_MIN_LOD:
1027 case GL_TEXTURE_MAX_LOD:
1028 /* This isn't the most efficient solution but there doesn't appear to
1029 * be a nice alternative. Since there's no LOD clamping,
1030 * we just have to rely on loading the right subset of mipmap levels
1031 * to simulate a clamped LOD.
1032 */
1033 driSwapOutTextureObject((driTextureObject *) t);
1034 break;
1035
1036 default:
1037 return;
1038 }
1039
1040 /* Mark this texobj as dirty (one bit per tex unit)
1041 */
1042 t->dirty_state = TEX_ALL;
1043 }
1044
1045 static void r300BindTexture(GLcontext * ctx, GLenum target,
1046 struct gl_texture_object *texObj)
1047 {
1048 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
1049 fprintf(stderr, "%s( %p ) unit=%d\n", __FUNCTION__,
1050 (void *)texObj, ctx->Texture.CurrentUnit);
1051 }
1052
1053 if ((target == GL_TEXTURE_1D)
1054 || (target == GL_TEXTURE_2D)
1055 #if ENABLE_HW_3D_TEXTURE
1056 || (target == GL_TEXTURE_3D)
1057 #endif
1058 || (target == GL_TEXTURE_CUBE_MAP)
1059 || (target == GL_TEXTURE_RECTANGLE_NV)) {
1060 assert(texObj->DriverData != NULL);
1061 }
1062 }
1063
1064 static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
1065 {
1066 r300ContextPtr rmesa = R300_CONTEXT(ctx);
1067 driTextureObject *t = (driTextureObject *) texObj->DriverData;
1068
1069 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
1070 fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__,
1071 (void *)texObj,
1072 _mesa_lookup_enum_by_nr(texObj->Target));
1073 }
1074
1075 if (t != NULL) {
1076 if (rmesa) {
1077 R300_FIREVERTICES(rmesa);
1078 }
1079
1080 driDestroyTextureObject(t);
1081 }
1082 /* Free mipmap images and the texture object itself */
1083 _mesa_delete_texture_object(ctx, texObj);
1084 }
1085
1086 /**
1087 * Allocate a new texture object.
1088 * Called via ctx->Driver.NewTextureObject.
1089 * Note: this function will be called during context creation to
1090 * allocate the default texture objects.
1091 * Note: we could use containment here to 'derive' the driver-specific
1092 * texture object from the core mesa gl_texture_object. Not done at this time.
1093 * Fixup MaxAnisotropy according to user preference.
1094 */
1095 static struct gl_texture_object *r300NewTextureObject(GLcontext * ctx,
1096 GLuint name,
1097 GLenum target)
1098 {
1099 r300ContextPtr rmesa = R300_CONTEXT(ctx);
1100 struct gl_texture_object *obj;
1101 obj = _mesa_new_texture_object(ctx, name, target);
1102 if (!obj)
1103 return NULL;
1104 obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
1105
1106 r300AllocTexObj(obj);
1107 return obj;
1108 }
1109
1110 void r300InitTextureFuncs(struct dd_function_table *functions)
1111 {
1112 /* Note: we only plug in the functions we implement in the driver
1113 * since _mesa_init_driver_functions() was already called.
1114 */
1115 functions->ChooseTextureFormat = r300ChooseTextureFormat;
1116 functions->TexImage1D = r300TexImage1D;
1117 functions->TexImage2D = r300TexImage2D;
1118 #if ENABLE_HW_3D_TEXTURE
1119 functions->TexImage3D = r300TexImage3D;
1120 #else
1121 functions->TexImage3D = _mesa_store_teximage3d;
1122 #endif
1123 functions->TexSubImage1D = r300TexSubImage1D;
1124 functions->TexSubImage2D = r300TexSubImage2D;
1125 #if ENABLE_HW_3D_TEXTURE
1126 functions->TexSubImage3D = r300TexSubImage3D;
1127 #else
1128 functions->TexSubImage3D = _mesa_store_texsubimage3d;
1129 #endif
1130 functions->NewTextureObject = r300NewTextureObject;
1131 functions->BindTexture = r300BindTexture;
1132 functions->DeleteTexture = r300DeleteTexture;
1133 functions->IsTextureResident = driIsTextureResident;
1134
1135 functions->TexEnv = r300TexEnv;
1136 functions->TexParameter = r300TexParameter;
1137
1138 functions->CompressedTexImage2D = r300CompressedTexImage2D;
1139 functions->CompressedTexSubImage2D = r300CompressedTexSubImage2D;
1140
1141 driInitTextureFormats();
1142
1143 #if 0
1144 /* moved or obsolete code */
1145 r300ContextPtr rmesa = R300_CONTEXT(ctx);
1146 driInitTextureObjects(ctx, &rmesa->swapped,
1147 DRI_TEXMGR_DO_TEXTURE_1D
1148 | DRI_TEXMGR_DO_TEXTURE_2D);
1149
1150 /* Hack: r300NewTextureObject is not yet installed when the
1151 * default textures are created. Therefore set MaxAnisotropy of the
1152 * default 2D texture now. */
1153 ctx->Shared->Default2D->MaxAnisotropy =
1154 driQueryOptionf(&rmesa->optionCache, "def_max_anisotropy");
1155 #endif
1156 }