4ed71777d39ed59478352549f8675bbef6da136b
[mesa.git] / src / mesa / drivers / dri / r300 / r300_tex.c
1 /*
2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
3
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29 /**
30 * \file
31 *
32 * \author 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_tex.h"
52
53 #include "xmlpool.h"
54
55
56 static unsigned int translate_wrap_mode(GLenum wrapmode)
57 {
58 switch(wrapmode) {
59 case GL_REPEAT: return R300_TX_REPEAT;
60 case GL_CLAMP: return R300_TX_CLAMP;
61 case GL_CLAMP_TO_EDGE: return R300_TX_CLAMP_TO_EDGE;
62 case GL_CLAMP_TO_BORDER: return R300_TX_CLAMP_TO_BORDER;
63 case GL_MIRRORED_REPEAT: return R300_TX_REPEAT | R300_TX_MIRRORED;
64 case GL_MIRROR_CLAMP_EXT: return R300_TX_CLAMP | R300_TX_MIRRORED;
65 case GL_MIRROR_CLAMP_TO_EDGE_EXT: return R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED;
66 case GL_MIRROR_CLAMP_TO_BORDER_EXT: return R300_TX_CLAMP_TO_BORDER | R300_TX_MIRRORED;
67 default:
68 _mesa_problem(NULL, "bad wrap mode in %s", __FUNCTION__);
69 return 0;
70 }
71 }
72
73
74 /**
75 * Update the cached hardware registers based on the current texture wrap modes.
76 *
77 * \param t Texture object whose wrap modes are to be set
78 */
79 static void r300UpdateTexWrap(r300TexObjPtr t)
80 {
81 struct gl_texture_object *tObj = t->base.tObj;
82
83 t->filter &=
84 ~(R300_TX_WRAP_S_MASK | R300_TX_WRAP_T_MASK | R300_TX_WRAP_R_MASK);
85
86 t->filter |= translate_wrap_mode(tObj->WrapS) << R300_TX_WRAP_S_SHIFT;
87
88 if (tObj->Target != GL_TEXTURE_1D) {
89 t->filter |= translate_wrap_mode(tObj->WrapT) << R300_TX_WRAP_T_SHIFT;
90
91 if (tObj->Target == GL_TEXTURE_3D)
92 t->filter |= translate_wrap_mode(tObj->WrapR) << R300_TX_WRAP_R_SHIFT;
93 }
94 }
95
96 static GLuint aniso_filter(GLfloat anisotropy)
97 {
98 if (anisotropy >= 16.0) {
99 return R300_TX_MAX_ANISO_16_TO_1;
100 } else if (anisotropy >= 8.0) {
101 return R300_TX_MAX_ANISO_8_TO_1;
102 } else if (anisotropy >= 4.0) {
103 return R300_TX_MAX_ANISO_4_TO_1;
104 } else if (anisotropy >= 2.0) {
105 return R300_TX_MAX_ANISO_2_TO_1;
106 } else {
107 return R300_TX_MAX_ANISO_1_TO_1;
108 }
109 }
110
111 /**
112 * Set the texture magnification and minification modes.
113 *
114 * \param t Texture whose filter modes are to be set
115 * \param minf Texture minification mode
116 * \param magf Texture magnification mode
117 * \param anisotropy Maximum anisotropy level
118 */
119 static void r300SetTexFilter(r300TexObjPtr t, GLenum minf, GLenum magf, GLfloat anisotropy)
120 {
121 t->filter &= ~(R300_TX_MIN_FILTER_MASK | R300_TX_MIN_FILTER_MIP_MASK | R300_TX_MAG_FILTER_MASK | R300_TX_MAX_ANISO_MASK);
122 t->filter_1 &= ~R300_EDGE_ANISO_EDGE_ONLY;
123
124 /* Note that EXT_texture_filter_anisotropic is extremely vague about
125 * how anisotropic filtering interacts with the "normal" filter modes.
126 * When anisotropic filtering is enabled, we override min and mag
127 * filter settings completely. This includes driconf's settings.
128 */
129 if (anisotropy >= 2.0 && (minf != GL_NEAREST) && (magf != GL_NEAREST)) {
130 t->filter |= R300_TX_MAG_FILTER_ANISO
131 | R300_TX_MIN_FILTER_ANISO
132 | R300_TX_MIN_FILTER_MIP_LINEAR
133 | aniso_filter(anisotropy);
134 if (RADEON_DEBUG & DEBUG_TEXTURE)
135 fprintf(stderr, "Using maximum anisotropy of %f\n", anisotropy);
136 return;
137 }
138
139 switch (minf) {
140 case GL_NEAREST:
141 t->filter |= R300_TX_MIN_FILTER_NEAREST;
142 break;
143 case GL_LINEAR:
144 t->filter |= R300_TX_MIN_FILTER_LINEAR;
145 break;
146 case GL_NEAREST_MIPMAP_NEAREST:
147 t->filter |= R300_TX_MIN_FILTER_NEAREST|R300_TX_MIN_FILTER_MIP_NEAREST;
148 break;
149 case GL_NEAREST_MIPMAP_LINEAR:
150 t->filter |= R300_TX_MIN_FILTER_NEAREST|R300_TX_MIN_FILTER_MIP_LINEAR;
151 break;
152 case GL_LINEAR_MIPMAP_NEAREST:
153 t->filter |= R300_TX_MIN_FILTER_LINEAR|R300_TX_MIN_FILTER_MIP_NEAREST;
154 break;
155 case GL_LINEAR_MIPMAP_LINEAR:
156 t->filter |= R300_TX_MIN_FILTER_LINEAR|R300_TX_MIN_FILTER_MIP_LINEAR;
157 break;
158 }
159
160 /* Note we don't have 3D mipmaps so only use the mag filter setting
161 * to set the 3D texture filter mode.
162 */
163 switch (magf) {
164 case GL_NEAREST:
165 t->filter |= R300_TX_MAG_FILTER_NEAREST;
166 break;
167 case GL_LINEAR:
168 t->filter |= R300_TX_MAG_FILTER_LINEAR;
169 break;
170 }
171 }
172
173 static void r300SetTexBorderColor(r300TexObjPtr t, GLubyte c[4])
174 {
175 t->pp_border_color = PACK_COLOR_8888(c[3], c[0], c[1], c[2]);
176 }
177
178 static void r300SetTexLodBias(r300TexObjPtr t, GLfloat bias)
179 {
180 GLuint b;
181 b = (unsigned int)fabsf(ceilf(bias*31));
182 if (signbit(bias)) {
183 b ^= 0x3ff; /* 10 bits */
184 }
185 b <<= 3;
186 b &= R300_LOD_BIAS_MASK;
187
188 t->filter_1 &= ~R300_LOD_BIAS_MASK;
189 t->filter_1 |= b;
190 }
191
192 /**
193 * Allocate space for and load the mesa images into the texture memory block.
194 * This will happen before drawing with a new texture, or drawing with a
195 * texture after it was swapped out or teximaged again.
196 */
197
198 static r300TexObjPtr r300AllocTexObj(struct gl_texture_object *texObj)
199 {
200 r300TexObjPtr t;
201
202 t = CALLOC_STRUCT(r300_tex_obj);
203 texObj->DriverData = t;
204 if (t != NULL) {
205 if (RADEON_DEBUG & DEBUG_TEXTURE) {
206 fprintf(stderr, "%s( %p, %p )\n", __FUNCTION__,
207 (void *)texObj, (void *)t);
208 }
209
210 /* Initialize non-image-dependent parts of the state:
211 */
212 t->base.tObj = texObj;
213 t->border_fallback = GL_FALSE;
214
215 make_empty_list(&t->base);
216
217 r300UpdateTexWrap(t);
218 r300SetTexFilter(t, texObj->MinFilter, texObj->MagFilter, texObj->MaxAnisotropy);
219 r300SetTexBorderColor(t, texObj->_BorderChan);
220 }
221
222 return t;
223 }
224
225 /* try to find a format which will only need a memcopy */
226 static const struct gl_texture_format *r300Choose8888TexFormat(GLenum srcFormat,
227 GLenum srcType)
228 {
229 const GLuint ui = 1;
230 const GLubyte littleEndian = *((const GLubyte *)&ui);
231
232 if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
233 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
234 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
235 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian)) {
236 return &_mesa_texformat_rgba8888;
237 } else if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
238 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
239 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
240 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian)) {
241 return &_mesa_texformat_rgba8888_rev;
242 } else if (srcFormat == GL_BGRA && ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
243 srcType == GL_UNSIGNED_INT_8_8_8_8)) {
244 return &_mesa_texformat_argb8888_rev;
245 } else if (srcFormat == GL_BGRA && ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
246 srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
247 return &_mesa_texformat_argb8888;
248 } else
249 return _dri_texformat_argb8888;
250 }
251
252 static const struct gl_texture_format *r300ChooseTextureFormat(GLcontext * ctx,
253 GLint
254 internalFormat,
255 GLenum format,
256 GLenum type)
257 {
258 r300ContextPtr rmesa = R300_CONTEXT(ctx);
259 const GLboolean do32bpt =
260 (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32);
261 const GLboolean force16bpt =
262 (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16);
263 (void)format;
264
265 #if 0
266 fprintf(stderr, "InternalFormat=%s(%d) type=%s format=%s\n",
267 _mesa_lookup_enum_by_nr(internalFormat), internalFormat,
268 _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format));
269 fprintf(stderr, "do32bpt=%d force16bpt=%d\n", do32bpt, force16bpt);
270 #endif
271
272 switch (internalFormat) {
273 case 4:
274 case GL_RGBA:
275 case GL_COMPRESSED_RGBA:
276 switch (type) {
277 case GL_UNSIGNED_INT_10_10_10_2:
278 case GL_UNSIGNED_INT_2_10_10_10_REV:
279 return do32bpt ? _dri_texformat_argb8888 :
280 _dri_texformat_argb1555;
281 case GL_UNSIGNED_SHORT_4_4_4_4:
282 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
283 return _dri_texformat_argb4444;
284 case GL_UNSIGNED_SHORT_5_5_5_1:
285 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
286 return _dri_texformat_argb1555;
287 default:
288 return do32bpt ? r300Choose8888TexFormat(format, type) :
289 _dri_texformat_argb4444;
290 }
291
292 case 3:
293 case GL_RGB:
294 case GL_COMPRESSED_RGB:
295 switch (type) {
296 case GL_UNSIGNED_SHORT_4_4_4_4:
297 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
298 return _dri_texformat_argb4444;
299 case GL_UNSIGNED_SHORT_5_5_5_1:
300 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
301 return _dri_texformat_argb1555;
302 case GL_UNSIGNED_SHORT_5_6_5:
303 case GL_UNSIGNED_SHORT_5_6_5_REV:
304 return _dri_texformat_rgb565;
305 default:
306 return do32bpt ? _dri_texformat_argb8888 :
307 _dri_texformat_rgb565;
308 }
309
310 case GL_RGBA8:
311 case GL_RGB10_A2:
312 case GL_RGBA12:
313 case GL_RGBA16:
314 return !force16bpt ?
315 r300Choose8888TexFormat(format,
316 type) : _dri_texformat_argb4444;
317
318 case GL_RGBA4:
319 case GL_RGBA2:
320 return _dri_texformat_argb4444;
321
322 case GL_RGB5_A1:
323 return _dri_texformat_argb1555;
324
325 case GL_RGB8:
326 case GL_RGB10:
327 case GL_RGB12:
328 case GL_RGB16:
329 return !force16bpt ? _dri_texformat_argb8888 :
330 _dri_texformat_rgb565;
331
332 case GL_RGB5:
333 case GL_RGB4:
334 case GL_R3_G3_B2:
335 return _dri_texformat_rgb565;
336
337 case GL_ALPHA:
338 case GL_ALPHA4:
339 case GL_ALPHA8:
340 case GL_ALPHA12:
341 case GL_ALPHA16:
342 case GL_COMPRESSED_ALPHA:
343 return _dri_texformat_a8;
344
345 case 1:
346 case GL_LUMINANCE:
347 case GL_LUMINANCE4:
348 case GL_LUMINANCE8:
349 case GL_LUMINANCE12:
350 case GL_LUMINANCE16:
351 case GL_COMPRESSED_LUMINANCE:
352 return _dri_texformat_l8;
353
354 case 2:
355 case GL_LUMINANCE_ALPHA:
356 case GL_LUMINANCE4_ALPHA4:
357 case GL_LUMINANCE6_ALPHA2:
358 case GL_LUMINANCE8_ALPHA8:
359 case GL_LUMINANCE12_ALPHA4:
360 case GL_LUMINANCE12_ALPHA12:
361 case GL_LUMINANCE16_ALPHA16:
362 case GL_COMPRESSED_LUMINANCE_ALPHA:
363 return _dri_texformat_al88;
364
365 case GL_INTENSITY:
366 case GL_INTENSITY4:
367 case GL_INTENSITY8:
368 case GL_INTENSITY12:
369 case GL_INTENSITY16:
370 case GL_COMPRESSED_INTENSITY:
371 return _dri_texformat_i8;
372
373 case GL_YCBCR_MESA:
374 if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
375 type == GL_UNSIGNED_BYTE)
376 return &_mesa_texformat_ycbcr;
377 else
378 return &_mesa_texformat_ycbcr_rev;
379
380 case GL_RGB_S3TC:
381 case GL_RGB4_S3TC:
382 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
383 return &_mesa_texformat_rgb_dxt1;
384
385 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
386 return &_mesa_texformat_rgba_dxt1;
387
388 case GL_RGBA_S3TC:
389 case GL_RGBA4_S3TC:
390 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
391 return &_mesa_texformat_rgba_dxt3;
392
393 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
394 return &_mesa_texformat_rgba_dxt5;
395
396 case GL_ALPHA16F_ARB:
397 return &_mesa_texformat_alpha_float16;
398 case GL_ALPHA32F_ARB:
399 return &_mesa_texformat_alpha_float32;
400 case GL_LUMINANCE16F_ARB:
401 return &_mesa_texformat_luminance_float16;
402 case GL_LUMINANCE32F_ARB:
403 return &_mesa_texformat_luminance_float32;
404 case GL_LUMINANCE_ALPHA16F_ARB:
405 return &_mesa_texformat_luminance_alpha_float16;
406 case GL_LUMINANCE_ALPHA32F_ARB:
407 return &_mesa_texformat_luminance_alpha_float32;
408 case GL_INTENSITY16F_ARB:
409 return &_mesa_texformat_intensity_float16;
410 case GL_INTENSITY32F_ARB:
411 return &_mesa_texformat_intensity_float32;
412 case GL_RGB16F_ARB:
413 return &_mesa_texformat_rgba_float16;
414 case GL_RGB32F_ARB:
415 return &_mesa_texformat_rgba_float32;
416 case GL_RGBA16F_ARB:
417 return &_mesa_texformat_rgba_float16;
418 case GL_RGBA32F_ARB:
419 return &_mesa_texformat_rgba_float32;
420
421 case GL_DEPTH_COMPONENT:
422 case GL_DEPTH_COMPONENT16:
423 case GL_DEPTH_COMPONENT24:
424 case GL_DEPTH_COMPONENT32:
425 #if 0
426 switch (type) {
427 case GL_UNSIGNED_BYTE:
428 case GL_UNSIGNED_SHORT:
429 return &_mesa_texformat_z16;
430 case GL_UNSIGNED_INT:
431 return &_mesa_texformat_z32;
432 case GL_UNSIGNED_INT_24_8_EXT:
433 default:
434 return &_mesa_texformat_z24_s8;
435 }
436 #else
437 return &_mesa_texformat_z16;
438 #endif
439
440 default:
441 _mesa_problem(ctx,
442 "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
443 (int)internalFormat);
444 return NULL;
445 }
446
447 return NULL; /* never get here */
448 }
449
450 static GLboolean
451 r300ValidateClientStorage(GLcontext * ctx, GLenum target,
452 GLint internalFormat,
453 GLint srcWidth, GLint srcHeight,
454 GLenum format, GLenum type, const void *pixels,
455 const struct gl_pixelstore_attrib *packing,
456 struct gl_texture_object *texObj,
457 struct gl_texture_image *texImage)
458 {
459 r300ContextPtr rmesa = R300_CONTEXT(ctx);
460
461 if (RADEON_DEBUG & DEBUG_TEXTURE)
462 fprintf(stderr, "intformat %s format %s type %s\n",
463 _mesa_lookup_enum_by_nr(internalFormat),
464 _mesa_lookup_enum_by_nr(format),
465 _mesa_lookup_enum_by_nr(type));
466
467 if (!ctx->Unpack.ClientStorage)
468 return 0;
469
470 if (ctx->_ImageTransferState ||
471 texImage->IsCompressed || texObj->GenerateMipmap)
472 return 0;
473
474 /* This list is incomplete, may be different on ppc???
475 */
476 switch (internalFormat) {
477 case GL_RGBA:
478 if (format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
479 texImage->TexFormat = _dri_texformat_argb8888;
480 } else
481 return 0;
482 break;
483
484 case GL_RGB:
485 if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
486 texImage->TexFormat = _dri_texformat_rgb565;
487 } else
488 return 0;
489 break;
490
491 case GL_YCBCR_MESA:
492 if (format == GL_YCBCR_MESA &&
493 type == GL_UNSIGNED_SHORT_8_8_REV_APPLE) {
494 texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
495 } else if (format == GL_YCBCR_MESA &&
496 (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
497 type == GL_UNSIGNED_BYTE)) {
498 texImage->TexFormat = &_mesa_texformat_ycbcr;
499 } else
500 return 0;
501 break;
502
503 default:
504 return 0;
505 }
506
507 /* Could deal with these packing issues, but currently don't:
508 */
509 if (packing->SkipPixels ||
510 packing->SkipRows || packing->SwapBytes || packing->LsbFirst) {
511 return 0;
512 }
513
514 GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
515 format, type);
516
517 if (RADEON_DEBUG & DEBUG_TEXTURE)
518 fprintf(stderr, "%s: srcRowStride %d/%x\n",
519 __FUNCTION__, srcRowStride, srcRowStride);
520
521 /* Could check this later in upload, pitch restrictions could be
522 * relaxed, but would need to store the image pitch somewhere,
523 * as packing details might change before image is uploaded:
524 */
525 if (!r300IsGartMemory(rmesa, pixels, srcHeight * srcRowStride)
526 || (srcRowStride & 63))
527 return 0;
528
529 /* Have validated that _mesa_transfer_teximage would be a straight
530 * memcpy at this point. NOTE: future calls to TexSubImage will
531 * overwrite the client data. This is explicitly mentioned in the
532 * extension spec.
533 */
534 texImage->Data = (void *)pixels;
535 texImage->IsClientData = GL_TRUE;
536 texImage->RowStride = srcRowStride / texImage->TexFormat->TexelBytes;
537
538 return 1;
539 }
540
541 static void r300TexImage1D(GLcontext * ctx, GLenum target, GLint level,
542 GLint internalFormat,
543 GLint width, GLint border,
544 GLenum format, GLenum type, const GLvoid * pixels,
545 const struct gl_pixelstore_attrib *packing,
546 struct gl_texture_object *texObj,
547 struct gl_texture_image *texImage)
548 {
549 driTextureObject *t = (driTextureObject *) texObj->DriverData;
550
551 if (t) {
552 driSwapOutTextureObject(t);
553 } else {
554 t = (driTextureObject *) r300AllocTexObj(texObj);
555 if (!t) {
556 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
557 return;
558 }
559 }
560
561 /* Note, this will call ChooseTextureFormat */
562 _mesa_store_teximage1d(ctx, target, level, internalFormat,
563 width, border, format, type, pixels,
564 &ctx->Unpack, texObj, texImage);
565
566 t->dirty_images[0] |= (1 << level);
567 }
568
569 static void r300TexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
570 GLint xoffset,
571 GLsizei width,
572 GLenum format, GLenum type,
573 const GLvoid * pixels,
574 const struct gl_pixelstore_attrib *packing,
575 struct gl_texture_object *texObj,
576 struct gl_texture_image *texImage)
577 {
578 driTextureObject *t = (driTextureObject *) texObj->DriverData;
579
580 assert(t); /* this _should_ be true */
581 if (t) {
582 driSwapOutTextureObject(t);
583 } else {
584 t = (driTextureObject *) r300AllocTexObj(texObj);
585 if (!t) {
586 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
587 return;
588 }
589 }
590
591 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
592 format, type, pixels, packing, texObj,
593 texImage);
594
595 t->dirty_images[0] |= (1 << level);
596 }
597
598 static void r300TexImage2D(GLcontext * ctx, GLenum target, GLint level,
599 GLint internalFormat,
600 GLint width, GLint height, GLint border,
601 GLenum format, GLenum type, const GLvoid * pixels,
602 const struct gl_pixelstore_attrib *packing,
603 struct gl_texture_object *texObj,
604 struct gl_texture_image *texImage)
605 {
606 driTextureObject *t = (driTextureObject *) texObj->DriverData;
607 GLuint face;
608
609 /* which cube face or ordinary 2D image */
610 switch (target) {
611 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
612 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
613 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
614 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
615 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
616 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
617 face =
618 (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
619 ASSERT(face < 6);
620 break;
621 default:
622 face = 0;
623 }
624
625 if (t != NULL) {
626 driSwapOutTextureObject(t);
627 } else {
628 t = (driTextureObject *) r300AllocTexObj(texObj);
629 if (!t) {
630 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
631 return;
632 }
633 }
634
635 texImage->IsClientData = GL_FALSE;
636
637 if (r300ValidateClientStorage(ctx, target,
638 internalFormat,
639 width, height,
640 format, type, pixels,
641 packing, texObj, texImage)) {
642 if (RADEON_DEBUG & DEBUG_TEXTURE)
643 fprintf(stderr, "%s: Using client storage\n",
644 __FUNCTION__);
645 } else {
646 if (RADEON_DEBUG & DEBUG_TEXTURE)
647 fprintf(stderr, "%s: Using normal storage\n",
648 __FUNCTION__);
649
650 /* Normal path: copy (to cached memory) and eventually upload
651 * via another copy to GART memory and then a blit... Could
652 * eliminate one copy by going straight to (permanent) GART.
653 *
654 * Note, this will call r300ChooseTextureFormat.
655 */
656 _mesa_store_teximage2d(ctx, target, level, internalFormat,
657 width, height, border, format, type,
658 pixels, &ctx->Unpack, texObj, texImage);
659
660 t->dirty_images[face] |= (1 << level);
661 }
662 }
663
664 static void r300TexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
665 GLint xoffset, GLint yoffset,
666 GLsizei width, GLsizei height,
667 GLenum format, GLenum type,
668 const GLvoid * pixels,
669 const struct gl_pixelstore_attrib *packing,
670 struct gl_texture_object *texObj,
671 struct gl_texture_image *texImage)
672 {
673 driTextureObject *t = (driTextureObject *) texObj->DriverData;
674 GLuint face;
675
676 /* which cube face or ordinary 2D image */
677 switch (target) {
678 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
679 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
680 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
681 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
682 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
683 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
684 face =
685 (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
686 ASSERT(face < 6);
687 break;
688 default:
689 face = 0;
690 }
691
692 assert(t); /* this _should_ be true */
693 if (t) {
694 driSwapOutTextureObject(t);
695 } else {
696 t = (driTextureObject *) r300AllocTexObj(texObj);
697 if (!t) {
698 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
699 return;
700 }
701 }
702
703 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
704 height, format, type, pixels, packing, texObj,
705 texImage);
706
707 t->dirty_images[face] |= (1 << level);
708 }
709
710 static void r300CompressedTexImage2D(GLcontext * ctx, GLenum target,
711 GLint level, GLint internalFormat,
712 GLint width, GLint height, GLint border,
713 GLsizei imageSize, const GLvoid * data,
714 struct gl_texture_object *texObj,
715 struct gl_texture_image *texImage)
716 {
717 driTextureObject *t = (driTextureObject *) texObj->DriverData;
718 GLuint face;
719
720 /* which cube face or ordinary 2D image */
721 switch (target) {
722 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
723 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
724 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
725 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
726 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
727 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
728 face =
729 (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
730 ASSERT(face < 6);
731 break;
732 default:
733 face = 0;
734 }
735
736 if (t != NULL) {
737 driSwapOutTextureObject(t);
738 } else {
739 t = (driTextureObject *) r300AllocTexObj(texObj);
740 if (!t) {
741 _mesa_error(ctx, GL_OUT_OF_MEMORY,
742 "glCompressedTexImage2D");
743 return;
744 }
745 }
746
747 texImage->IsClientData = GL_FALSE;
748
749 /* can't call this, different parameters. Would never evaluate to true anyway currently */
750 #if 0
751 if (r300ValidateClientStorage(ctx, target,
752 internalFormat,
753 width, height,
754 format, type, pixels,
755 packing, texObj, texImage)) {
756 if (RADEON_DEBUG & DEBUG_TEXTURE)
757 fprintf(stderr, "%s: Using client storage\n",
758 __FUNCTION__);
759 } else
760 #endif
761 {
762 if (RADEON_DEBUG & DEBUG_TEXTURE)
763 fprintf(stderr, "%s: Using normal storage\n",
764 __FUNCTION__);
765
766 /* Normal path: copy (to cached memory) and eventually upload
767 * via another copy to GART memory and then a blit... Could
768 * eliminate one copy by going straight to (permanent) GART.
769 *
770 * Note, this will call r300ChooseTextureFormat.
771 */
772 _mesa_store_compressed_teximage2d(ctx, target, level,
773 internalFormat, width, height,
774 border, imageSize, data,
775 texObj, texImage);
776
777 t->dirty_images[face] |= (1 << level);
778 }
779 }
780
781 static void r300CompressedTexSubImage2D(GLcontext * ctx, GLenum target,
782 GLint level, GLint xoffset,
783 GLint yoffset, GLsizei width,
784 GLsizei height, GLenum format,
785 GLsizei imageSize, const GLvoid * data,
786 struct gl_texture_object *texObj,
787 struct gl_texture_image *texImage)
788 {
789 driTextureObject *t = (driTextureObject *) texObj->DriverData;
790 GLuint face;
791
792 /* which cube face or ordinary 2D image */
793 switch (target) {
794 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
795 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
796 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
797 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
798 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
799 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
800 face =
801 (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
802 ASSERT(face < 6);
803 break;
804 default:
805 face = 0;
806 }
807
808 assert(t); /* this _should_ be true */
809 if (t) {
810 driSwapOutTextureObject(t);
811 } else {
812 t = (driTextureObject *) r300AllocTexObj(texObj);
813 if (!t) {
814 _mesa_error(ctx, GL_OUT_OF_MEMORY,
815 "glCompressedTexSubImage3D");
816 return;
817 }
818 }
819
820 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset,
821 yoffset, width, height, format,
822 imageSize, data, texObj, texImage);
823
824 t->dirty_images[face] |= (1 << level);
825 }
826
827 static void r300TexImage3D(GLcontext * ctx, GLenum target, GLint level,
828 GLint internalFormat,
829 GLint width, GLint height, GLint depth,
830 GLint border,
831 GLenum format, GLenum type, const GLvoid * pixels,
832 const struct gl_pixelstore_attrib *packing,
833 struct gl_texture_object *texObj,
834 struct gl_texture_image *texImage)
835 {
836 driTextureObject *t = (driTextureObject *) texObj->DriverData;
837
838 if (t) {
839 driSwapOutTextureObject(t);
840 } else {
841 t = (driTextureObject *) r300AllocTexObj(texObj);
842 if (!t) {
843 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
844 return;
845 }
846 }
847
848 texImage->IsClientData = GL_FALSE;
849
850 #if 0
851 if (r300ValidateClientStorage(ctx, target,
852 internalFormat,
853 width, height,
854 format, type, pixels,
855 packing, texObj, texImage)) {
856 if (RADEON_DEBUG & DEBUG_TEXTURE)
857 fprintf(stderr, "%s: Using client storage\n",
858 __FUNCTION__);
859 } else
860 #endif
861 {
862 if (RADEON_DEBUG & DEBUG_TEXTURE)
863 fprintf(stderr, "%s: Using normal storage\n",
864 __FUNCTION__);
865
866 /* Normal path: copy (to cached memory) and eventually upload
867 * via another copy to GART memory and then a blit... Could
868 * eliminate one copy by going straight to (permanent) GART.
869 *
870 * Note, this will call r300ChooseTextureFormat.
871 */
872 _mesa_store_teximage3d(ctx, target, level, internalFormat,
873 width, height, depth, border,
874 format, type, pixels,
875 &ctx->Unpack, texObj, texImage);
876
877 t->dirty_images[0] |= (1 << level);
878 }
879 }
880
881 static void
882 r300TexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
883 GLint xoffset, GLint yoffset, GLint zoffset,
884 GLsizei width, GLsizei height, GLsizei depth,
885 GLenum format, GLenum type,
886 const GLvoid * pixels,
887 const struct gl_pixelstore_attrib *packing,
888 struct gl_texture_object *texObj,
889 struct gl_texture_image *texImage)
890 {
891 driTextureObject *t = (driTextureObject *) texObj->DriverData;
892
893 /* fprintf(stderr, "%s\n", __FUNCTION__); */
894
895 assert(t); /* this _should_ be true */
896 if (t) {
897 driSwapOutTextureObject(t);
898 } else {
899 t = (driTextureObject *) r300AllocTexObj(texObj);
900 if (!t) {
901 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
902 return;
903 }
904 texObj->DriverData = t;
905 }
906
907 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
908 width, height, depth,
909 format, type, pixels, packing, texObj,
910 texImage);
911
912 t->dirty_images[0] |= (1 << level);
913 }
914
915 /* This feels like a prime target for code reuse, so I'm putting it here
916 * instead of inlining it in TexEnv. */
917 static GLenum r300TexUnitTarget(struct gl_texture_unit *unit) {
918 if (unit->_ReallyEnabled & (TEXTURE_RECT_BIT)) {
919 return GL_TEXTURE_RECTANGLE_NV;
920 } else if (unit->_ReallyEnabled & (TEXTURE_1D_BIT)) {
921 return GL_TEXTURE_1D;
922 } else if (unit->_ReallyEnabled & (TEXTURE_2D_BIT)) {
923 return GL_TEXTURE_2D;
924 } else if (unit->_ReallyEnabled & (TEXTURE_3D_BIT)) {
925 return GL_TEXTURE_3D;
926 } else if (unit->_ReallyEnabled & (TEXTURE_CUBE_BIT)) {
927 return GL_TEXTURE_CUBE_MAP;
928 }
929 if (unit->Enabled & (TEXTURE_RECT_BIT)) {
930 return GL_TEXTURE_RECTANGLE_NV;
931 } else if (unit->Enabled & (TEXTURE_1D_BIT)) {
932 return GL_TEXTURE_1D;
933 } else if (unit->Enabled & (TEXTURE_2D_BIT)) {
934 return GL_TEXTURE_2D;
935 } else if (unit->Enabled & (TEXTURE_3D_BIT)) {
936 return GL_TEXTURE_3D;
937 } else if (unit->Enabled & (TEXTURE_CUBE_BIT)) {
938 return GL_TEXTURE_CUBE_MAP;
939 }
940 return 0;
941 }
942
943 static void r300TexEnv(GLcontext * ctx, GLenum target,
944 GLenum pname, const GLfloat * param)
945 {
946 r300ContextPtr rmesa = R300_CONTEXT(ctx);
947 if (RADEON_DEBUG & DEBUG_STATE) {
948 fprintf(stderr, "%s( %s )\n",
949 __FUNCTION__, _mesa_lookup_enum_by_nr(pname));
950 }
951
952 /* This is incorrect: Need to maintain this data for each of
953 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
954 * between them according to _ReallyEnabled.
955 */
956 switch (pname) {
957 case GL_TEXTURE_LOD_BIAS_EXT: {
958 GLfloat bias, min;
959
960 /* The R300's LOD bias is a signed 2's complement value with a
961 * range of -16.0 <= bias < 16.0.
962 *
963 * NOTE: Add a small bias to the bias for conform mipsel.c test.
964 */
965 bias = *param + .01;
966 min = driQueryOptionb(&rmesa->radeon.optionCache,
967 "no_neg_lod_bias") ? 0.0 : -16.0;
968 bias = CLAMP(bias, min, 16.0);
969
970 /* There's probably a magic Mesa method for finding the REAL
971 * texture unit. I don't know it, though. */
972 if (!(ctx->Texture._EnabledUnits & (1 << ctx->Texture.CurrentUnit))) {
973 break;
974 }
975
976 /* Save our newly clamped LOD bias. */
977 ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias = bias;
978
979 break;
980 }
981
982 default:
983 return;
984 }
985 }
986
987 /**
988 * Changes variables and flags for a state update, which will happen at the
989 * next UpdateTextureState
990 */
991
992 static void r300TexParameter(GLcontext * ctx, GLenum target,
993 struct gl_texture_object *texObj,
994 GLenum pname, const GLfloat * params)
995 {
996 r300TexObjPtr t = (r300TexObjPtr) texObj->DriverData;
997
998 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
999 fprintf(stderr, "%s( %s )\n", __FUNCTION__,
1000 _mesa_lookup_enum_by_nr(pname));
1001 }
1002
1003 switch (pname) {
1004 case GL_TEXTURE_MIN_FILTER:
1005 case GL_TEXTURE_MAG_FILTER:
1006 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1007 r300SetTexFilter(t, texObj->MinFilter, texObj->MagFilter, texObj->MaxAnisotropy);
1008 break;
1009
1010 case GL_TEXTURE_WRAP_S:
1011 case GL_TEXTURE_WRAP_T:
1012 case GL_TEXTURE_WRAP_R:
1013 r300UpdateTexWrap(t);
1014 break;
1015
1016 case GL_TEXTURE_BORDER_COLOR:
1017 r300SetTexBorderColor(t, texObj->_BorderChan);
1018 break;
1019
1020 case GL_TEXTURE_BASE_LEVEL:
1021 case GL_TEXTURE_MAX_LEVEL:
1022 case GL_TEXTURE_MIN_LOD:
1023 case GL_TEXTURE_MAX_LOD:
1024 /* This isn't the most efficient solution but there doesn't appear to
1025 * be a nice alternative. Since there's no LOD clamping,
1026 * we just have to rely on loading the right subset of mipmap levels
1027 * to simulate a clamped LOD.
1028 */
1029 driSwapOutTextureObject((driTextureObject *) t);
1030 break;
1031
1032 case GL_DEPTH_TEXTURE_MODE:
1033 if (texObj->Image[0][texObj->BaseLevel]->TexFormat->BaseFormat
1034 == GL_DEPTH_COMPONENT) {
1035 r300SetDepthTexMode(texObj);
1036 break;
1037 } else {
1038 /* If the texture isn't a depth texture, changing this
1039 * state won't cause any changes to the hardware.
1040 * Don't force a flush of texture state.
1041 */
1042 return;
1043 }
1044
1045 default:
1046 return;
1047 }
1048 }
1049
1050 static void r300BindTexture(GLcontext * ctx, GLenum target,
1051 struct gl_texture_object *texObj)
1052 {
1053 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
1054 fprintf(stderr, "%s( %p ) unit=%d\n", __FUNCTION__,
1055 (void *)texObj, ctx->Texture.CurrentUnit);
1056 }
1057
1058 if ((target == GL_TEXTURE_1D)
1059 || (target == GL_TEXTURE_2D)
1060 || (target == GL_TEXTURE_3D)
1061 || (target == GL_TEXTURE_CUBE_MAP)
1062 || (target == GL_TEXTURE_RECTANGLE_NV)) {
1063 assert(texObj->DriverData != NULL);
1064 }
1065 }
1066
1067 static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
1068 {
1069 r300ContextPtr rmesa = R300_CONTEXT(ctx);
1070 driTextureObject *t = (driTextureObject *) texObj->DriverData;
1071
1072 if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
1073 fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__,
1074 (void *)texObj,
1075 _mesa_lookup_enum_by_nr(texObj->Target));
1076 }
1077
1078 if (t != NULL) {
1079 if (rmesa) {
1080 R300_FIREVERTICES(rmesa);
1081 }
1082
1083 driDestroyTextureObject(t);
1084 }
1085 /* Free mipmap images and the texture object itself */
1086 _mesa_delete_texture_object(ctx, texObj);
1087 }
1088
1089 /**
1090 * Allocate a new texture object.
1091 * Called via ctx->Driver.NewTextureObject.
1092 * Note: this function will be called during context creation to
1093 * allocate the default texture objects.
1094 * Note: we could use containment here to 'derive' the driver-specific
1095 * texture object from the core mesa gl_texture_object. Not done at this time.
1096 * Fixup MaxAnisotropy according to user preference.
1097 */
1098 static struct gl_texture_object *r300NewTextureObject(GLcontext * ctx,
1099 GLuint name,
1100 GLenum target)
1101 {
1102 r300ContextPtr rmesa = R300_CONTEXT(ctx);
1103 struct gl_texture_object *obj;
1104 obj = _mesa_new_texture_object(ctx, name, target);
1105 if (!obj)
1106 return NULL;
1107 obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
1108
1109 /* Attempt to fill LOD bias, if previously set.
1110 * Should start at 0.0, which won't affect the HW. */
1111 obj->LodBias = rmesa->LODBias;
1112
1113 r300AllocTexObj(obj);
1114 return obj;
1115 }
1116
1117 void r300InitTextureFuncs(struct dd_function_table *functions)
1118 {
1119 /* Note: we only plug in the functions we implement in the driver
1120 * since _mesa_init_driver_functions() was already called.
1121 */
1122 functions->ChooseTextureFormat = r300ChooseTextureFormat;
1123 functions->TexImage1D = r300TexImage1D;
1124 functions->TexImage2D = r300TexImage2D;
1125 functions->TexImage3D = r300TexImage3D;
1126 functions->TexSubImage1D = r300TexSubImage1D;
1127 functions->TexSubImage2D = r300TexSubImage2D;
1128 functions->TexSubImage3D = r300TexSubImage3D;
1129 functions->NewTextureObject = r300NewTextureObject;
1130 functions->BindTexture = r300BindTexture;
1131 functions->DeleteTexture = r300DeleteTexture;
1132 functions->IsTextureResident = driIsTextureResident;
1133
1134 functions->TexEnv = r300TexEnv;
1135 functions->TexParameter = r300TexParameter;
1136
1137 functions->CompressedTexImage2D = r300CompressedTexImage2D;
1138 functions->CompressedTexSubImage2D = r300CompressedTexSubImage2D;
1139
1140 driInitTextureFormats();
1141 }