Merge branch 'origin'
[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 /* try to find a format which will only need a memcopy */
301 static const struct gl_texture_format *r300Choose8888TexFormat( GLenum srcFormat,
302 GLenum srcType )
303 {
304 const GLuint ui = 1;
305 const GLubyte littleEndian = *((const GLubyte *) &ui);
306
307 if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
308 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
309 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
310 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian)) {
311 return &_mesa_texformat_rgba8888;
312 }
313 else if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
314 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
315 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
316 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian)) {
317 return &_mesa_texformat_rgba8888_rev;
318 }
319 else if (srcFormat == GL_BGRA &&
320 ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
321 srcType == GL_UNSIGNED_INT_8_8_8_8)) {
322 return &_mesa_texformat_argb8888_rev;
323 }
324 else if (srcFormat == GL_BGRA &&
325 ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
326 srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
327 return &_mesa_texformat_argb8888;
328 }
329 else return _dri_texformat_argb8888;
330 }
331
332 static const struct gl_texture_format *r300ChooseTextureFormat(GLcontext * ctx,
333 GLint
334 internalFormat,
335 GLenum format,
336 GLenum type)
337 {
338 r300ContextPtr rmesa = R300_CONTEXT(ctx);
339 const GLboolean do32bpt =
340 (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32);
341 const GLboolean force16bpt =
342 (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16);
343 (void)format;
344
345 #if 0
346 fprintf(stderr, "InternalFormat=%s(%d) type=%s format=%s\n",
347 _mesa_lookup_enum_by_nr(internalFormat), internalFormat,
348 _mesa_lookup_enum_by_nr(type),
349 _mesa_lookup_enum_by_nr(format));
350 fprintf(stderr, "do32bpt=%d force16bpt=%d\n",
351 do32bpt, force16bpt);
352 #endif
353
354 switch (internalFormat) {
355 case 4:
356 case GL_RGBA:
357 case GL_COMPRESSED_RGBA:
358 switch (type) {
359 case GL_UNSIGNED_INT_10_10_10_2:
360 case GL_UNSIGNED_INT_2_10_10_10_REV:
361 return do32bpt ? _dri_texformat_argb8888 :
362 _dri_texformat_argb1555;
363 case GL_UNSIGNED_SHORT_4_4_4_4:
364 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
365 return _dri_texformat_argb4444;
366 case GL_UNSIGNED_SHORT_5_5_5_1:
367 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
368 return _dri_texformat_argb1555;
369 default:
370 return do32bpt ? r300Choose8888TexFormat(format, type) :
371 _dri_texformat_argb4444;
372 }
373
374 case 3:
375 case GL_RGB:
376 case GL_COMPRESSED_RGB:
377 switch (type) {
378 case GL_UNSIGNED_SHORT_4_4_4_4:
379 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
380 return _dri_texformat_argb4444;
381 case GL_UNSIGNED_SHORT_5_5_5_1:
382 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
383 return _dri_texformat_argb1555;
384 case GL_UNSIGNED_SHORT_5_6_5:
385 case GL_UNSIGNED_SHORT_5_6_5_REV:
386 return _dri_texformat_rgb565;
387 default:
388 return do32bpt ? _dri_texformat_argb8888 :
389 _dri_texformat_rgb565;
390 }
391
392 case GL_RGBA8:
393 case GL_RGB10_A2:
394 case GL_RGBA12:
395 case GL_RGBA16:
396 return !force16bpt ?
397 r300Choose8888TexFormat(format, type) : _dri_texformat_argb4444;
398
399 case GL_RGBA4:
400 case GL_RGBA2:
401 return _dri_texformat_argb4444;
402
403 case GL_RGB5_A1:
404 return _dri_texformat_argb1555;
405
406 case GL_RGB8:
407 case GL_RGB10:
408 case GL_RGB12:
409 case GL_RGB16:
410 return !force16bpt ? _dri_texformat_argb8888 :
411 _dri_texformat_rgb565;
412
413 case GL_RGB5:
414 case GL_RGB4:
415 case GL_R3_G3_B2:
416 return _dri_texformat_rgb565;
417
418 case GL_ALPHA:
419 case GL_ALPHA4:
420 case GL_ALPHA8:
421 case GL_ALPHA12:
422 case GL_ALPHA16:
423 case GL_COMPRESSED_ALPHA:
424 return _dri_texformat_a8;
425
426 case 1:
427 case GL_LUMINANCE:
428 case GL_LUMINANCE4:
429 case GL_LUMINANCE8:
430 case GL_LUMINANCE12:
431 case GL_LUMINANCE16:
432 case GL_COMPRESSED_LUMINANCE:
433 return _dri_texformat_l8;
434
435 case 2:
436 case GL_LUMINANCE_ALPHA:
437 case GL_LUMINANCE4_ALPHA4:
438 case GL_LUMINANCE6_ALPHA2:
439 case GL_LUMINANCE8_ALPHA8:
440 case GL_LUMINANCE12_ALPHA4:
441 case GL_LUMINANCE12_ALPHA12:
442 case GL_LUMINANCE16_ALPHA16:
443 case GL_COMPRESSED_LUMINANCE_ALPHA:
444 return _dri_texformat_al88;
445
446 case GL_INTENSITY:
447 case GL_INTENSITY4:
448 case GL_INTENSITY8:
449 case GL_INTENSITY12:
450 case GL_INTENSITY16:
451 case GL_COMPRESSED_INTENSITY:
452 return _dri_texformat_i8;
453
454 case GL_YCBCR_MESA:
455 if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
456 type == GL_UNSIGNED_BYTE)
457 return &_mesa_texformat_ycbcr;
458 else
459 return &_mesa_texformat_ycbcr_rev;
460
461 case GL_RGB_S3TC:
462 case GL_RGB4_S3TC:
463 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
464 return &_mesa_texformat_rgb_dxt1;
465
466 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
467 return &_mesa_texformat_rgba_dxt1;
468
469 case GL_RGBA_S3TC:
470 case GL_RGBA4_S3TC:
471 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
472 return &_mesa_texformat_rgba_dxt3;
473
474 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
475 return &_mesa_texformat_rgba_dxt5;
476
477 case GL_ALPHA16F_ARB:
478 return &_mesa_texformat_alpha_float16;
479 case GL_ALPHA32F_ARB:
480 return &_mesa_texformat_alpha_float32;
481 case GL_LUMINANCE16F_ARB:
482 return &_mesa_texformat_luminance_float16;
483 case GL_LUMINANCE32F_ARB:
484 return &_mesa_texformat_luminance_float32;
485 case GL_LUMINANCE_ALPHA16F_ARB:
486 return &_mesa_texformat_luminance_alpha_float16;
487 case GL_LUMINANCE_ALPHA32F_ARB:
488 return &_mesa_texformat_luminance_alpha_float32;
489 case GL_INTENSITY16F_ARB:
490 return &_mesa_texformat_intensity_float16;
491 case GL_INTENSITY32F_ARB:
492 return &_mesa_texformat_intensity_float32;
493 case GL_RGB16F_ARB:
494 return &_mesa_texformat_rgba_float16;
495 case GL_RGB32F_ARB:
496 return &_mesa_texformat_rgba_float32;
497 case GL_RGBA16F_ARB:
498 return &_mesa_texformat_rgba_float16;
499 case GL_RGBA32F_ARB:
500 return &_mesa_texformat_rgba_float32;
501
502 default:
503 _mesa_problem(ctx,
504 "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
505 (int)internalFormat);
506 return NULL;
507 }
508
509 return NULL; /* never get here */
510 }
511
512 static GLboolean
513 r300ValidateClientStorage(GLcontext * ctx, GLenum target,
514 GLint internalFormat,
515 GLint srcWidth, GLint srcHeight,
516 GLenum format, GLenum type, const void *pixels,
517 const struct gl_pixelstore_attrib *packing,
518 struct gl_texture_object *texObj,
519 struct gl_texture_image *texImage)
520 {
521 r300ContextPtr rmesa = R300_CONTEXT(ctx);
522
523 if (0)
524 fprintf(stderr, "intformat %s format %s type %s\n",
525 _mesa_lookup_enum_by_nr(internalFormat),
526 _mesa_lookup_enum_by_nr(format),
527 _mesa_lookup_enum_by_nr(type));
528
529 if (!ctx->Unpack.ClientStorage)
530 return 0;
531
532 if (ctx->_ImageTransferState ||
533 texImage->IsCompressed || texObj->GenerateMipmap)
534 return 0;
535
536 /* This list is incomplete, may be different on ppc???
537 */
538 switch (internalFormat) {
539 case GL_RGBA:
540 if (format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
541 texImage->TexFormat = _dri_texformat_argb8888;
542 } else
543 return 0;
544 break;
545
546 case GL_RGB:
547 if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
548 texImage->TexFormat = _dri_texformat_rgb565;
549 } else
550 return 0;
551 break;
552
553 case GL_YCBCR_MESA:
554 if (format == GL_YCBCR_MESA &&
555 type == GL_UNSIGNED_SHORT_8_8_REV_APPLE) {
556 texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
557 } else if (format == GL_YCBCR_MESA &&
558 (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
559 type == GL_UNSIGNED_BYTE)) {
560 texImage->TexFormat = &_mesa_texformat_ycbcr;
561 } else
562 return 0;
563 break;
564
565 default:
566 return 0;
567 }
568
569 /* Could deal with these packing issues, but currently don't:
570 */
571 if (packing->SkipPixels ||
572 packing->SkipRows || packing->SwapBytes || packing->LsbFirst) {
573 return 0;
574 }
575
576 {
577 GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
578 format, type);
579
580 if (0)
581 fprintf(stderr, "%s: srcRowStride %d/%x\n",
582 __FUNCTION__, srcRowStride, srcRowStride);
583
584 /* Could check this later in upload, pitch restrictions could be
585 * relaxed, but would need to store the image pitch somewhere,
586 * as packing details might change before image is uploaded:
587 */
588 if (!r300IsGartMemory(rmesa, pixels, srcHeight * srcRowStride)
589 || (srcRowStride & 63))
590 return 0;
591
592 /* Have validated that _mesa_transfer_teximage would be a straight
593 * memcpy at this point. NOTE: future calls to TexSubImage will
594 * overwrite the client data. This is explicitly mentioned in the
595 * extension spec.
596 */
597 texImage->Data = (void *)pixels;
598 texImage->IsClientData = GL_TRUE;
599 texImage->RowStride =
600 srcRowStride / texImage->TexFormat->TexelBytes;
601
602 return 1;
603 }
604 }
605
606 static void r300TexImage1D(GLcontext * ctx, GLenum target, GLint level,
607 GLint internalFormat,
608 GLint width, 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
616 if (t) {
617 driSwapOutTextureObject(t);
618 } else {
619 t = (driTextureObject *) r300AllocTexObj(texObj);
620 if (!t) {
621 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
622 return;
623 }
624 }
625
626 /* Note, this will call ChooseTextureFormat */
627 _mesa_store_teximage1d(ctx, target, level, internalFormat,
628 width, border, format, type, pixels,
629 &ctx->Unpack, texObj, texImage);
630
631 t->dirty_images[0] |= (1 << level);
632 }
633
634 static void r300TexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
635 GLint xoffset,
636 GLsizei width,
637 GLenum format, GLenum type,
638 const GLvoid * pixels,
639 const struct gl_pixelstore_attrib *packing,
640 struct gl_texture_object *texObj,
641 struct gl_texture_image *texImage)
642 {
643 driTextureObject *t = (driTextureObject *) texObj->DriverData;
644
645 assert(t); /* this _should_ be true */
646 if (t) {
647 driSwapOutTextureObject(t);
648 } else {
649 t = (driTextureObject *) r300AllocTexObj(texObj);
650 if (!t) {
651 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
652 return;
653 }
654 }
655
656 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
657 format, type, pixels, packing, texObj,
658 texImage);
659
660 t->dirty_images[0] |= (1 << level);
661 }
662
663 static void r300TexImage2D(GLcontext * ctx, GLenum target, GLint level,
664 GLint internalFormat,
665 GLint width, GLint height, GLint border,
666 GLenum format, GLenum type, const GLvoid * pixels,
667 const struct gl_pixelstore_attrib *packing,
668 struct gl_texture_object *texObj,
669 struct gl_texture_image *texImage)
670 {
671 driTextureObject *t = (driTextureObject *) texObj->DriverData;
672 GLuint face;
673
674 /* which cube face or ordinary 2D image */
675 switch (target) {
676 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
677 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
678 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
679 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
680 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
681 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
682 face =
683 (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
684 ASSERT(face < 6);
685 break;
686 default:
687 face = 0;
688 }
689
690 if (t != NULL) {
691 driSwapOutTextureObject(t);
692 } else {
693 t = (driTextureObject *) r300AllocTexObj(texObj);
694 if (!t) {
695 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
696 return;
697 }
698 }
699
700 texImage->IsClientData = GL_FALSE;
701
702 if (r300ValidateClientStorage(ctx, target,
703 internalFormat,
704 width, height,
705 format, type, pixels,
706 packing, texObj, texImage)) {
707 if (RADEON_DEBUG & DEBUG_TEXTURE)
708 fprintf(stderr, "%s: Using client storage\n",
709 __FUNCTION__);
710 } else {
711 if (RADEON_DEBUG & DEBUG_TEXTURE)
712 fprintf(stderr, "%s: Using normal storage\n",
713 __FUNCTION__);
714
715 /* Normal path: copy (to cached memory) and eventually upload
716 * via another copy to GART memory and then a blit... Could
717 * eliminate one copy by going straight to (permanent) GART.
718 *
719 * Note, this will call r300ChooseTextureFormat.
720 */
721 _mesa_store_teximage2d(ctx, target, level, internalFormat,
722 width, height, border, format, type,
723 pixels, &ctx->Unpack, texObj, texImage);
724
725 t->dirty_images[face] |= (1 << level);
726 }
727 }
728
729 static void r300TexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
730 GLint xoffset, GLint yoffset,
731 GLsizei width, GLsizei height,
732 GLenum format, GLenum type,
733 const GLvoid * pixels,
734 const struct gl_pixelstore_attrib *packing,
735 struct gl_texture_object *texObj,
736 struct gl_texture_image *texImage)
737 {
738 driTextureObject *t = (driTextureObject *) texObj->DriverData;
739 GLuint face;
740
741 /* which cube face or ordinary 2D image */
742 switch (target) {
743 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
744 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
745 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
746 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
747 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
748 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
749 face =
750 (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
751 ASSERT(face < 6);
752 break;
753 default:
754 face = 0;
755 }
756
757 assert(t); /* this _should_ be true */
758 if (t) {
759 driSwapOutTextureObject(t);
760 } else {
761 t = (driTextureObject *) r300AllocTexObj(texObj);
762 if (!t) {
763 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
764 return;
765 }
766 }
767
768 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
769 height, format, type, pixels, packing, texObj,
770 texImage);
771
772 t->dirty_images[face] |= (1 << level);
773 }
774
775 static void r300CompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
776 GLint internalFormat,
777 GLint width, GLint height, GLint border,
778 GLsizei imageSize, const GLvoid *data,
779 struct gl_texture_object *texObj,
780 struct gl_texture_image *texImage )
781 {
782 driTextureObject * t = (driTextureObject *) texObj->DriverData;
783 GLuint face;
784
785 /* which cube face or ordinary 2D image */
786 switch (target) {
787 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
788 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
789 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
790 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
791 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
792 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
793 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
794 ASSERT(face < 6);
795 break;
796 default:
797 face = 0;
798 }
799
800 if ( t != NULL ) {
801 driSwapOutTextureObject( t );
802 }
803 else {
804 t = (driTextureObject *) r300AllocTexObj( texObj );
805 if (!t) {
806 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
807 return;
808 }
809 }
810
811 texImage->IsClientData = GL_FALSE;
812 /* can't call this, different parameters. Would never evaluate to true anyway currently
813 if (r300ValidateClientStorage( ctx, target,
814 internalFormat,
815 width, height,
816 format, type, pixels,
817 packing, texObj, texImage)) {
818 if (RADEON_DEBUG & DEBUG_TEXTURE)
819 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
820 }
821 else */{
822 if (RADEON_DEBUG & DEBUG_TEXTURE)
823 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
824
825 /* Normal path: copy (to cached memory) and eventually upload
826 * via another copy to GART memory and then a blit... Could
827 * eliminate one copy by going straight to (permanent) GART.
828 *
829 * Note, this will call r300ChooseTextureFormat.
830 */
831 _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
832 height, border, imageSize, data, texObj, texImage);
833
834 t->dirty_images[face] |= (1 << level);
835 }
836 }
837
838
839 static void r300CompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
840 GLint xoffset, GLint yoffset,
841 GLsizei width, GLsizei height,
842 GLenum format,
843 GLsizei imageSize, const GLvoid *data,
844 struct gl_texture_object *texObj,
845 struct gl_texture_image *texImage )
846 {
847 driTextureObject * t = (driTextureObject *) texObj->DriverData;
848 GLuint face;
849
850
851 /* which cube face or ordinary 2D image */
852 switch (target) {
853 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
854 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
855 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
856 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
857 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
858 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
859 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
860 ASSERT(face < 6);
861 break;
862 default:
863 face = 0;
864 }
865
866 assert( t ); /* this _should_ be true */
867 if ( t ) {
868 driSwapOutTextureObject( t );
869 }
870 else {
871 t = (driTextureObject *) r300AllocTexObj( texObj );
872 if (!t) {
873 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage3D");
874 return;
875 }
876 }
877
878 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
879 height, format, imageSize, data, texObj, texImage);
880
881 t->dirty_images[face] |= (1 << level);
882 }
883
884 #if ENABLE_HW_3D_TEXTURE
885 static void r300TexImage3D(GLcontext * ctx, GLenum target, GLint level,
886 GLint internalFormat,
887 GLint width, GLint height, GLint depth,
888 GLint border,
889 GLenum format, GLenum type, 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 if (t) {
897 driSwapOutTextureObject(t);
898 } else {
899 t = (driTextureObject *) r300AllocTexObj(texObj);
900 if (!t) {
901 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
902 return;
903 }
904 }
905
906 texImage->IsClientData = GL_FALSE;
907
908 #if 0
909 if (r300ValidateClientStorage(ctx, target,
910 internalFormat,
911 width, height,
912 format, type, pixels,
913 packing, texObj, texImage)) {
914 if (RADEON_DEBUG & DEBUG_TEXTURE)
915 fprintf(stderr, "%s: Using client storage\n",
916 __FUNCTION__);
917 } else
918 #endif
919 {
920 if (RADEON_DEBUG & DEBUG_TEXTURE)
921 fprintf(stderr, "%s: Using normal storage\n",
922 __FUNCTION__);
923
924 /* Normal path: copy (to cached memory) and eventually upload
925 * via another copy to GART memory and then a blit... Could
926 * eliminate one copy by going straight to (permanent) GART.
927 *
928 * Note, this will call r300ChooseTextureFormat.
929 */
930 _mesa_store_teximage3d(ctx, target, level, internalFormat,
931 width, height, depth, border,
932 format, type, pixels,
933 &ctx->Unpack, texObj, texImage);
934
935 t->dirty_images[0] |= (1 << level);
936 }
937 }
938 #endif
939
940 #if ENABLE_HW_3D_TEXTURE
941 static void
942 r300TexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
943 GLint xoffset, GLint yoffset, GLint zoffset,
944 GLsizei width, GLsizei height, GLsizei depth,
945 GLenum format, GLenum type,
946 const GLvoid * pixels,
947 const struct gl_pixelstore_attrib *packing,
948 struct gl_texture_object *texObj,
949 struct gl_texture_image *texImage)
950 {
951 driTextureObject *t = (driTextureObject *) texObj->DriverData;
952
953 /* fprintf(stderr, "%s\n", __FUNCTION__); */
954
955 assert(t); /* this _should_ be true */
956 if (t) {
957 driSwapOutTextureObject(t);
958 } else {
959 t = (driTextureObject *) r300AllocTexObj(texObj);
960 if (!t) {
961 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
962 return;
963 }
964 texObj->DriverData = t;
965 }
966
967 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
968 width, height, depth,
969 format, type, pixels, packing, texObj,
970 texImage);
971
972 t->dirty_images[0] |= (1 << level);
973 }
974 #endif
975
976 static void r300TexEnv(GLcontext * ctx, GLenum target,
977 GLenum pname, const GLfloat * param)
978 {
979 if (RADEON_DEBUG & DEBUG_STATE) {
980 fprintf(stderr, "%s( %s )\n",
981 __FUNCTION__, _mesa_lookup_enum_by_nr(pname));
982 }
983
984 /* This is incorrect: Need to maintain this data for each of
985 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
986 * between them according to _ReallyEnabled.
987 */
988 switch (pname) {
989 case GL_TEXTURE_LOD_BIAS_EXT:{
990 #if 0 /* Needs to be relocated in order to make sure we got the right tmu */
991 GLfloat bias, min;
992 GLuint b;
993
994 /* The R300's LOD bias is a signed 2's complement value with a
995 * range of -16.0 <= bias < 16.0.
996 *
997 * NOTE: Add a small bias to the bias for conform mipsel.c test.
998 */
999 bias = *param + .01;
1000 min =
1001 driQueryOptionb(&rmesa->radeon.optionCache,
1002 "no_neg_lod_bias") ? 0.0 : -16.0;
1003 bias = CLAMP(bias, min, 16.0);
1004
1005 /* 0.0 - 16.0 == 0x0 - 0x1000 */
1006 /* 0.0 - -16.0 == 0x1001 - 0x1fff */
1007 b = 0x1000 / 16.0 * bias;
1008 b &= R300_LOD_BIAS_MASK;
1009
1010 if(b != (rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] & R300_LOD_BIAS_MASK)){
1011 R300_STATECHANGE(rmesa, tex.unknown1);
1012 rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] &= ~R300_LOD_BIAS_MASK;
1013 rmesa->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+unit] |= b;
1014 }
1015 #endif
1016 break;
1017 }
1018
1019 default:
1020 return;
1021 }
1022 }
1023
1024 /**
1025 * Changes variables and flags for a state update, which will happen at the
1026 * next UpdateTextureState
1027 */
1028
1029 static void r300TexParameter(GLcontext * ctx, GLenum target,
1030 struct gl_texture_object *texObj,
1031 GLenum pname, const GLfloat * params)
1032 {
1033 r300TexObjPtr t = (r300TexObjPtr) texObj->DriverData;
1034
1035 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
1036 fprintf(stderr, "%s( %s )\n", __FUNCTION__,
1037 _mesa_lookup_enum_by_nr(pname));
1038 }
1039
1040 switch (pname) {
1041 case GL_TEXTURE_MIN_FILTER:
1042 case GL_TEXTURE_MAG_FILTER:
1043 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1044 r300SetTexMaxAnisotropy(t, texObj->MaxAnisotropy);
1045 r300SetTexFilter(t, texObj->MinFilter, texObj->MagFilter);
1046 break;
1047
1048 case GL_TEXTURE_WRAP_S:
1049 case GL_TEXTURE_WRAP_T:
1050 case GL_TEXTURE_WRAP_R:
1051 r300SetTexWrap(t, texObj->WrapS, texObj->WrapT, texObj->WrapR);
1052 break;
1053
1054 case GL_TEXTURE_BORDER_COLOR:
1055 r300SetTexBorderColor(t, texObj->_BorderChan);
1056 break;
1057
1058 case GL_TEXTURE_BASE_LEVEL:
1059 case GL_TEXTURE_MAX_LEVEL:
1060 case GL_TEXTURE_MIN_LOD:
1061 case GL_TEXTURE_MAX_LOD:
1062 /* This isn't the most efficient solution but there doesn't appear to
1063 * be a nice alternative. Since there's no LOD clamping,
1064 * we just have to rely on loading the right subset of mipmap levels
1065 * to simulate a clamped LOD.
1066 */
1067 driSwapOutTextureObject((driTextureObject *) t);
1068 break;
1069
1070 default:
1071 return;
1072 }
1073
1074 /* Mark this texobj as dirty (one bit per tex unit)
1075 */
1076 t->dirty_state = TEX_ALL;
1077 }
1078
1079 static void r300BindTexture(GLcontext * ctx, GLenum target,
1080 struct gl_texture_object *texObj)
1081 {
1082 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
1083 fprintf(stderr, "%s( %p ) unit=%d\n", __FUNCTION__,
1084 (void *)texObj, ctx->Texture.CurrentUnit);
1085 }
1086
1087 if ((target == GL_TEXTURE_1D)
1088 || (target == GL_TEXTURE_2D)
1089 #if ENABLE_HW_3D_TEXTURE
1090 || (target == GL_TEXTURE_3D)
1091 #endif
1092 || (target == GL_TEXTURE_CUBE_MAP)
1093 || (target == GL_TEXTURE_RECTANGLE_NV)) {
1094 assert(texObj->DriverData != NULL);
1095 }
1096 }
1097
1098 static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
1099 {
1100 r300ContextPtr rmesa = R300_CONTEXT(ctx);
1101 driTextureObject *t = (driTextureObject *) texObj->DriverData;
1102
1103 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
1104 fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__,
1105 (void *)texObj,
1106 _mesa_lookup_enum_by_nr(texObj->Target));
1107 }
1108
1109 if (t != NULL) {
1110 if (rmesa) {
1111 R300_FIREVERTICES(rmesa);
1112 }
1113
1114 driDestroyTextureObject(t);
1115 }
1116 /* Free mipmap images and the texture object itself */
1117 _mesa_delete_texture_object(ctx, texObj);
1118 }
1119
1120 /**
1121 * Allocate a new texture object.
1122 * Called via ctx->Driver.NewTextureObject.
1123 * Note: this function will be called during context creation to
1124 * allocate the default texture objects.
1125 * Note: we could use containment here to 'derive' the driver-specific
1126 * texture object from the core mesa gl_texture_object. Not done at this time.
1127 * Fixup MaxAnisotropy according to user preference.
1128 */
1129 static struct gl_texture_object *r300NewTextureObject(GLcontext * ctx,
1130 GLuint name,
1131 GLenum target)
1132 {
1133 r300ContextPtr rmesa = R300_CONTEXT(ctx);
1134 struct gl_texture_object *obj;
1135 obj = _mesa_new_texture_object(ctx, name, target);
1136 if (!obj)
1137 return NULL;
1138 obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
1139
1140 r300AllocTexObj(obj);
1141 return obj;
1142 }
1143
1144
1145 void r300InitTextureFuncs(struct dd_function_table *functions)
1146 {
1147 /* Note: we only plug in the functions we implement in the driver
1148 * since _mesa_init_driver_functions() was already called.
1149 */
1150 functions->ChooseTextureFormat = r300ChooseTextureFormat;
1151 functions->TexImage1D = r300TexImage1D;
1152 functions->TexImage2D = r300TexImage2D;
1153 #if ENABLE_HW_3D_TEXTURE
1154 functions->TexImage3D = r300TexImage3D;
1155 #else
1156 functions->TexImage3D = _mesa_store_teximage3d;
1157 #endif
1158 functions->TexSubImage1D = r300TexSubImage1D;
1159 functions->TexSubImage2D = r300TexSubImage2D;
1160 #if ENABLE_HW_3D_TEXTURE
1161 functions->TexSubImage3D = r300TexSubImage3D;
1162 #else
1163 functions->TexSubImage3D = _mesa_store_texsubimage3d;
1164 #endif
1165 functions->NewTextureObject = r300NewTextureObject;
1166 functions->BindTexture = r300BindTexture;
1167 functions->DeleteTexture = r300DeleteTexture;
1168 functions->IsTextureResident = driIsTextureResident;
1169
1170 functions->TexEnv = r300TexEnv;
1171 functions->TexParameter = r300TexParameter;
1172
1173 functions->CompressedTexImage2D = r300CompressedTexImage2D;
1174 functions->CompressedTexSubImage2D = r300CompressedTexSubImage2D;
1175
1176 driInitTextureFormats();
1177
1178 #if 0
1179 /* moved or obsolete code */
1180 r300ContextPtr rmesa = R300_CONTEXT(ctx);
1181 driInitTextureObjects(ctx, &rmesa->swapped,
1182 DRI_TEXMGR_DO_TEXTURE_1D
1183 | DRI_TEXMGR_DO_TEXTURE_2D);
1184
1185 /* Hack: r300NewTextureObject is not yet installed when the
1186 * default textures are created. Therefore set MaxAnisotropy of the
1187 * default 2D texture now. */
1188 ctx->Shared->Default2D->MaxAnisotropy =
1189 driQueryOptionf(&rmesa->optionCache, "def_max_anisotropy");
1190 #endif
1191 }