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