Merge commit 'origin/gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / unichrome / via_tex.c
1 /*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #include <stdlib.h>
27 #include <stdio.h>
28
29 #include "main/glheader.h"
30 #include "main/macros.h"
31 #include "main/mtypes.h"
32 #include "main/enums.h"
33 #include "main/colortab.h"
34 #include "main/convolve.h"
35 #include "main/context.h"
36 #include "main/mipmap.h"
37 #include "main/simple_list.h"
38 #include "main/texcompress.h"
39 #include "main/texformat.h"
40 #include "main/texobj.h"
41 #include "main/texstore.h"
42
43 #include "main/mm.h"
44 #include "via_context.h"
45 #include "via_fb.h"
46 #include "via_tex.h"
47 #include "via_state.h"
48 #include "via_ioctl.h"
49 #include "via_3d_reg.h"
50
51 static const struct gl_texture_format *
52 viaChooseTexFormat( GLcontext *ctx, GLint internalFormat,
53 GLenum format, GLenum type )
54 {
55 struct via_context *vmesa = VIA_CONTEXT(ctx);
56 const GLboolean do32bpt = ( vmesa->viaScreen->bitsPerPixel == 32
57 /* && vmesa->viaScreen->textureSize > 4*1024*1024 */
58 );
59
60
61 switch ( internalFormat ) {
62 case 4:
63 case GL_RGBA:
64 case GL_COMPRESSED_RGBA:
65 if ( format == GL_BGRA ) {
66 if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ||
67 type == GL_UNSIGNED_BYTE ) {
68 return &_mesa_texformat_argb8888;
69 }
70 else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
71 return &_mesa_texformat_argb4444;
72 }
73 else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
74 return &_mesa_texformat_argb1555;
75 }
76 }
77 else if ( type == GL_UNSIGNED_BYTE ||
78 type == GL_UNSIGNED_INT_8_8_8_8_REV ||
79 type == GL_UNSIGNED_INT_8_8_8_8 ) {
80 return &_mesa_texformat_argb8888;
81 }
82 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
83
84 case 3:
85 case GL_RGB:
86 case GL_COMPRESSED_RGB:
87 if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
88 return &_mesa_texformat_rgb565;
89 }
90 else if ( type == GL_UNSIGNED_BYTE ) {
91 return &_mesa_texformat_argb8888;
92 }
93 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
94
95 case GL_RGBA8:
96 case GL_RGB10_A2:
97 case GL_RGBA12:
98 case GL_RGBA16:
99 return &_mesa_texformat_argb8888;
100
101 case GL_RGBA4:
102 case GL_RGBA2:
103 return &_mesa_texformat_argb4444;
104
105 case GL_RGB5_A1:
106 return &_mesa_texformat_argb1555;
107
108 case GL_RGB8:
109 case GL_RGB10:
110 case GL_RGB12:
111 case GL_RGB16:
112 return &_mesa_texformat_argb8888;
113
114 case GL_RGB5:
115 case GL_RGB4:
116 case GL_R3_G3_B2:
117 return &_mesa_texformat_rgb565;
118
119 case GL_ALPHA:
120 case GL_ALPHA4:
121 case GL_ALPHA8:
122 case GL_ALPHA12:
123 case GL_ALPHA16:
124 case GL_COMPRESSED_ALPHA:
125 return &_mesa_texformat_a8;
126
127 case 1:
128 case GL_LUMINANCE:
129 case GL_LUMINANCE4:
130 case GL_LUMINANCE8:
131 case GL_LUMINANCE12:
132 case GL_LUMINANCE16:
133 case GL_COMPRESSED_LUMINANCE:
134 return &_mesa_texformat_l8;
135
136 case 2:
137 case GL_LUMINANCE_ALPHA:
138 case GL_LUMINANCE4_ALPHA4:
139 case GL_LUMINANCE6_ALPHA2:
140 case GL_LUMINANCE8_ALPHA8:
141 case GL_LUMINANCE12_ALPHA4:
142 case GL_LUMINANCE12_ALPHA12:
143 case GL_LUMINANCE16_ALPHA16:
144 case GL_COMPRESSED_LUMINANCE_ALPHA:
145 return &_mesa_texformat_al88;
146
147 case GL_INTENSITY:
148 case GL_INTENSITY4:
149 case GL_INTENSITY8:
150 case GL_INTENSITY12:
151 case GL_INTENSITY16:
152 case GL_COMPRESSED_INTENSITY:
153 return &_mesa_texformat_i8;
154
155 case GL_YCBCR_MESA:
156 if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
157 type == GL_UNSIGNED_BYTE)
158 return &_mesa_texformat_ycbcr;
159 else
160 return &_mesa_texformat_ycbcr_rev;
161
162 case GL_COMPRESSED_RGB_FXT1_3DFX:
163 return &_mesa_texformat_rgb_fxt1;
164 case GL_COMPRESSED_RGBA_FXT1_3DFX:
165 return &_mesa_texformat_rgba_fxt1;
166
167 case GL_RGB_S3TC:
168 case GL_RGB4_S3TC:
169 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
170 return &_mesa_texformat_rgb_dxt1;
171
172 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
173 return &_mesa_texformat_rgba_dxt1;
174
175 case GL_RGBA_S3TC:
176 case GL_RGBA4_S3TC:
177 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
178 return &_mesa_texformat_rgba_dxt3;
179
180 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
181 return &_mesa_texformat_rgba_dxt5;
182
183 case GL_COLOR_INDEX:
184 case GL_COLOR_INDEX1_EXT:
185 case GL_COLOR_INDEX2_EXT:
186 case GL_COLOR_INDEX4_EXT:
187 case GL_COLOR_INDEX8_EXT:
188 case GL_COLOR_INDEX12_EXT:
189 case GL_COLOR_INDEX16_EXT:
190 return &_mesa_texformat_ci8;
191
192 default:
193 fprintf(stderr, "unexpected texture format %s in %s\n",
194 _mesa_lookup_enum_by_nr(internalFormat),
195 __FUNCTION__);
196 return NULL;
197 }
198
199 return NULL; /* never get here */
200 }
201
202 static int logbase2(int n)
203 {
204 GLint i = 1;
205 GLint log2 = 0;
206
207 while (n > i) {
208 i *= 2;
209 log2++;
210 }
211
212 return log2;
213 }
214
215 static const char *get_memtype_name( GLint memType )
216 {
217 static const char *names[] = {
218 "VIA_MEM_VIDEO",
219 "VIA_MEM_AGP",
220 "VIA_MEM_SYSTEM",
221 "VIA_MEM_MIXED",
222 "VIA_MEM_UNKNOWN"
223 };
224
225 return names[memType];
226 }
227
228
229 static GLboolean viaMoveTexBuffers( struct via_context *vmesa,
230 struct via_tex_buffer **buffers,
231 GLuint nr,
232 GLint newMemType )
233 {
234 struct via_tex_buffer *newTexBuf[VIA_MAX_TEXLEVELS];
235 GLint i;
236
237 if (VIA_DEBUG & DEBUG_TEXTURE)
238 fprintf(stderr, "%s to %s\n",
239 __FUNCTION__,
240 get_memtype_name(newMemType));
241
242 memset(newTexBuf, 0, sizeof(newTexBuf));
243
244 /* First do all the allocations (or fail):
245 */
246 for (i = 0; i < nr; i++) {
247 if (buffers[i]->memType != newMemType) {
248
249 /* Don't allow uploads in a thrash state. Should try and
250 * catch this earlier.
251 */
252 if (vmesa->thrashing && newMemType != VIA_MEM_SYSTEM)
253 goto cleanup;
254
255 newTexBuf[i] = via_alloc_texture(vmesa,
256 buffers[i]->size,
257 newMemType);
258 if (!newTexBuf[i])
259 goto cleanup;
260 }
261 }
262
263
264 /* Now copy all the image data and free the old texture memory.
265 */
266 for (i = 0; i < nr; i++) {
267 if (newTexBuf[i]) {
268 memcpy(newTexBuf[i]->bufAddr,
269 buffers[i]->bufAddr,
270 buffers[i]->size);
271
272 newTexBuf[i]->image = buffers[i]->image;
273 newTexBuf[i]->image->texMem = newTexBuf[i];
274 newTexBuf[i]->image->image.Data = newTexBuf[i]->bufAddr;
275 via_free_texture(vmesa, buffers[i]);
276 }
277 }
278
279 if (VIA_DEBUG & DEBUG_TEXTURE)
280 fprintf(stderr, "%s - success\n", __FUNCTION__);
281
282 return GL_TRUE;
283
284 cleanup:
285 /* Release any allocations made prior to failure:
286 */
287 if (VIA_DEBUG & DEBUG_TEXTURE)
288 fprintf(stderr, "%s - failed\n", __FUNCTION__);
289
290 for (i = 0; i < nr; i++) {
291 if (newTexBuf[i]) {
292 via_free_texture(vmesa, newTexBuf[i]);
293 }
294 }
295
296 return GL_FALSE;
297 }
298
299
300 static GLboolean viaMoveTexObject( struct via_context *vmesa,
301 struct via_texture_object *viaObj,
302 GLint newMemType )
303 {
304 struct via_texture_image **viaImage =
305 (struct via_texture_image **)&viaObj->obj.Image[0][0];
306 struct via_tex_buffer *buffers[VIA_MAX_TEXLEVELS];
307 GLuint i, nr = 0;
308
309 for (i = viaObj->firstLevel; i <= viaObj->lastLevel; i++)
310 buffers[nr++] = viaImage[i]->texMem;
311
312 if (viaMoveTexBuffers( vmesa, &buffers[0], nr, newMemType )) {
313 viaObj->memType = newMemType;
314 return GL_TRUE;
315 }
316
317 return GL_FALSE;
318 }
319
320
321
322 static GLboolean viaSwapInTexObject( struct via_context *vmesa,
323 struct via_texture_object *viaObj )
324 {
325 const struct via_texture_image *baseImage =
326 (struct via_texture_image *)viaObj->obj.Image[0][viaObj->obj.BaseLevel];
327
328 if (VIA_DEBUG & DEBUG_TEXTURE)
329 fprintf(stderr, "%s\n", __FUNCTION__);
330
331 if (baseImage->texMem->memType != VIA_MEM_SYSTEM)
332 return viaMoveTexObject( vmesa, viaObj, baseImage->texMem->memType );
333
334 return (viaMoveTexObject( vmesa, viaObj, VIA_MEM_AGP ) ||
335 viaMoveTexObject( vmesa, viaObj, VIA_MEM_VIDEO ));
336 }
337
338
339 /* This seems crude, but it asks a fairly pertinent question and gives
340 * an accurate answer:
341 */
342 static GLboolean viaIsTexMemLow( struct via_context *vmesa,
343 GLuint heap )
344 {
345 struct via_tex_buffer *buf = via_alloc_texture(vmesa, 512 * 1024, heap );
346 if (!buf)
347 return GL_TRUE;
348
349 via_free_texture(vmesa, buf);
350 return GL_FALSE;
351 }
352
353
354 /* Speculatively move texture images which haven't been used in a
355 * while back to system memory.
356 *
357 * TODO: only do this when texture memory is low.
358 *
359 * TODO: use dma.
360 *
361 * TODO: keep the fb/agp version hanging around and use the local
362 * version as backing store, so re-upload might be avoided.
363 *
364 * TODO: do this properly in the kernel...
365 */
366 GLboolean viaSwapOutWork( struct via_context *vmesa )
367 {
368 struct via_tex_buffer *s, *tmp;
369 GLuint done = 0;
370 GLuint heap, target;
371
372 if (VIA_DEBUG & DEBUG_TEXTURE)
373 fprintf(stderr, "%s VID %d AGP %d SYS %d\n", __FUNCTION__,
374 vmesa->total_alloc[VIA_MEM_VIDEO],
375 vmesa->total_alloc[VIA_MEM_AGP],
376 vmesa->total_alloc[VIA_MEM_SYSTEM]);
377
378
379 for (heap = VIA_MEM_VIDEO; heap <= VIA_MEM_AGP; heap++) {
380 GLuint nr = 0, sz = 0;
381
382 if (vmesa->thrashing) {
383 if (VIA_DEBUG & DEBUG_TEXTURE)
384 fprintf(stderr, "Heap %d: trash flag\n", heap);
385 target = 1*1024*1024;
386 }
387 else if (viaIsTexMemLow(vmesa, heap)) {
388 if (VIA_DEBUG & DEBUG_TEXTURE)
389 fprintf(stderr, "Heap %d: low memory\n", heap);
390 target = 64*1024;
391 }
392 else {
393 if (VIA_DEBUG & DEBUG_TEXTURE)
394 fprintf(stderr, "Heap %d: nothing to do\n", heap);
395 continue;
396 }
397
398 foreach_s( s, tmp, &vmesa->tex_image_list[heap] ) {
399 if (s->lastUsed < vmesa->lastSwap[1]) {
400 struct via_texture_object *viaObj =
401 (struct via_texture_object *) s->image->image.TexObject;
402
403 if (VIA_DEBUG & DEBUG_TEXTURE)
404 fprintf(stderr,
405 "back copy tex sz %d, lastUsed %d lastSwap %d\n",
406 s->size, s->lastUsed, vmesa->lastSwap[1]);
407
408 if (viaMoveTexBuffers( vmesa, &s, 1, VIA_MEM_SYSTEM )) {
409 viaObj->memType = VIA_MEM_MIXED;
410 done += s->size;
411 }
412 else {
413 if (VIA_DEBUG & DEBUG_TEXTURE)
414 fprintf(stderr, "Failed to back copy texture!\n");
415 sz += s->size;
416 }
417 }
418 else {
419 nr ++;
420 sz += s->size;
421 }
422
423 if (done > target) {
424 vmesa->thrashing = GL_FALSE; /* might not get set otherwise? */
425 return GL_TRUE;
426 }
427 }
428
429 assert(sz == vmesa->total_alloc[heap]);
430
431 if (VIA_DEBUG & DEBUG_TEXTURE)
432 fprintf(stderr, "Heap %d: nr %d tot sz %d\n", heap, nr, sz);
433 }
434
435
436 return done != 0;
437 }
438
439
440
441 /* Basically, just collect the image dimensions and addresses for each
442 * image and update the texture object state accordingly.
443 */
444 static GLboolean viaSetTexImages(GLcontext *ctx,
445 struct gl_texture_object *texObj)
446 {
447 struct via_context *vmesa = VIA_CONTEXT(ctx);
448 struct via_texture_object *viaObj = (struct via_texture_object *)texObj;
449 const struct via_texture_image *baseImage =
450 (struct via_texture_image *)texObj->Image[0][texObj->BaseLevel];
451 GLint firstLevel, lastLevel, numLevels;
452 GLuint texFormat;
453 GLint w, h, p;
454 GLint i, j = 0, k = 0, l = 0, m = 0;
455 GLuint texBase;
456 GLuint basH = 0;
457 GLuint widthExp = 0;
458 GLuint heightExp = 0;
459
460 switch (baseImage->image.TexFormat->MesaFormat) {
461 case MESA_FORMAT_ARGB8888:
462 texFormat = HC_HTXnFM_ARGB8888;
463 break;
464 case MESA_FORMAT_ARGB4444:
465 texFormat = HC_HTXnFM_ARGB4444;
466 break;
467 case MESA_FORMAT_RGB565:
468 texFormat = HC_HTXnFM_RGB565;
469 break;
470 case MESA_FORMAT_ARGB1555:
471 texFormat = HC_HTXnFM_ARGB1555;
472 break;
473 case MESA_FORMAT_RGB888:
474 texFormat = HC_HTXnFM_ARGB0888;
475 break;
476 case MESA_FORMAT_L8:
477 texFormat = HC_HTXnFM_L8;
478 break;
479 case MESA_FORMAT_I8:
480 texFormat = HC_HTXnFM_T8;
481 break;
482 case MESA_FORMAT_CI8:
483 texFormat = HC_HTXnFM_Index8;
484 break;
485 case MESA_FORMAT_AL88:
486 texFormat = HC_HTXnFM_AL88;
487 break;
488 case MESA_FORMAT_A8:
489 texFormat = HC_HTXnFM_A8;
490 break;
491 default:
492 _mesa_problem(vmesa->glCtx, "Bad texture format in viaSetTexImages");
493 return GL_FALSE;
494 }
495
496 /* Compute which mipmap levels we really want to send to the hardware.
497 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
498 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
499 * Yes, this looks overly complicated, but it's all needed.
500 */
501 if (texObj->MinFilter == GL_LINEAR || texObj->MinFilter == GL_NEAREST) {
502 firstLevel = lastLevel = texObj->BaseLevel;
503 }
504 else {
505 firstLevel = texObj->BaseLevel + (GLint)(texObj->MinLod + 0.5);
506 firstLevel = MAX2(firstLevel, texObj->BaseLevel);
507 lastLevel = texObj->BaseLevel + (GLint)(texObj->MaxLod + 0.5);
508 lastLevel = MAX2(lastLevel, texObj->BaseLevel);
509 lastLevel = MIN2(lastLevel, texObj->BaseLevel + baseImage->image.MaxLog2);
510 lastLevel = MIN2(lastLevel, texObj->MaxLevel);
511 lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
512 }
513
514 numLevels = lastLevel - firstLevel + 1;
515
516 /* The hardware supports only 10 mipmap levels; ignore higher levels.
517 */
518 if ((numLevels > 10) && (ctx->Const.MaxTextureLevels > 10)) {
519 lastLevel -= numLevels - 10;
520 numLevels = 10;
521 }
522
523 /* save these values, check if they effect the residency of the
524 * texture:
525 */
526 if (viaObj->firstLevel != firstLevel ||
527 viaObj->lastLevel != lastLevel) {
528 viaObj->firstLevel = firstLevel;
529 viaObj->lastLevel = lastLevel;
530 viaObj->memType = VIA_MEM_MIXED;
531 }
532
533 if (VIA_DEBUG & DEBUG_TEXTURE & 0)
534 fprintf(stderr, "%s, current memType: %s\n",
535 __FUNCTION__,
536 get_memtype_name(viaObj->memType));
537
538
539 if (viaObj->memType == VIA_MEM_MIXED ||
540 viaObj->memType == VIA_MEM_SYSTEM) {
541 if (!viaSwapInTexObject(vmesa, viaObj)) {
542 if (VIA_DEBUG & DEBUG_TEXTURE)
543 if (!vmesa->thrashing)
544 fprintf(stderr, "Thrashing flag set for frame %d\n",
545 vmesa->swap_count);
546 vmesa->thrashing = GL_TRUE;
547 return GL_FALSE;
548 }
549 }
550
551 if (viaObj->memType == VIA_MEM_AGP)
552 viaObj->regTexFM = (HC_SubA_HTXnFM << 24) | HC_HTXnLoc_AGP | texFormat;
553 else
554 viaObj->regTexFM = (HC_SubA_HTXnFM << 24) | HC_HTXnLoc_Local | texFormat;
555
556
557 for (i = 0; i < numLevels; i++) {
558 struct via_texture_image *viaImage =
559 (struct via_texture_image *)texObj->Image[0][firstLevel + i];
560
561 w = viaImage->image.WidthLog2;
562 h = viaImage->image.HeightLog2;
563 p = viaImage->pitchLog2;
564
565 assert(viaImage->texMem->memType == viaObj->memType);
566
567 texBase = viaImage->texMem->texBase;
568 if (!texBase) {
569 if (VIA_DEBUG & DEBUG_TEXTURE)
570 fprintf(stderr, "%s: no texBase[%d]\n", __FUNCTION__, i);
571 return GL_FALSE;
572 }
573
574 /* Image has to remain resident until the coming fence is retired.
575 */
576 move_to_head( &vmesa->tex_image_list[viaImage->texMem->memType],
577 viaImage->texMem );
578 viaImage->texMem->lastUsed = vmesa->lastBreadcrumbWrite;
579
580
581 viaObj->regTexBaseAndPitch[i].baseL =
582 ((HC_SubA_HTXnL0BasL + i) << 24) | (texBase & 0xFFFFFF);
583
584 viaObj->regTexBaseAndPitch[i].pitchLog2 =
585 ((HC_SubA_HTXnL0Pit + i) << 24) | (p << 20);
586
587
588 /* The base high bytes for each 3 levels are packed
589 * together into one register:
590 */
591 j = i / 3;
592 k = 3 - (i % 3);
593 basH |= ((texBase & 0xFF000000) >> (k << 3));
594 if (k == 1) {
595 viaObj->regTexBaseH[j] = ((j + HC_SubA_HTXnL012BasH) << 24) | basH;
596 basH = 0;
597 }
598
599 /* Likewise, sets of 6 log2width and log2height values are
600 * packed into individual registers:
601 */
602 l = i / 6;
603 m = i % 6;
604 widthExp |= (((GLuint)w & 0xF) << (m << 2));
605 heightExp |= (((GLuint)h & 0xF) << (m << 2));
606 if (m == 5) {
607 viaObj->regTexWidthLog2[l] =
608 (l + HC_SubA_HTXnL0_5WE) << 24 | widthExp;
609 viaObj->regTexHeightLog2[l] =
610 (l + HC_SubA_HTXnL0_5HE) << 24 | heightExp;
611 widthExp = 0;
612 heightExp = 0;
613 }
614 if (w) w--;
615 if (h) h--;
616 if (p) p--;
617 }
618
619 if (k != 1) {
620 viaObj->regTexBaseH[j] = ((j + HC_SubA_HTXnL012BasH) << 24) | basH;
621 }
622 if (m != 5) {
623 viaObj->regTexWidthLog2[l] = (l + HC_SubA_HTXnL0_5WE) << 24 | widthExp;
624 viaObj->regTexHeightLog2[l] = (l + HC_SubA_HTXnL0_5HE) << 24 | heightExp;
625 }
626
627 return GL_TRUE;
628 }
629
630
631 GLboolean viaUpdateTextureState( GLcontext *ctx )
632 {
633 struct gl_texture_unit *texUnit = ctx->Texture.Unit;
634 GLuint i;
635
636 for (i = 0; i < 2; i++) {
637 if (texUnit[i]._ReallyEnabled == TEXTURE_2D_BIT ||
638 texUnit[i]._ReallyEnabled == TEXTURE_1D_BIT) {
639
640 if (!viaSetTexImages(ctx, texUnit[i]._Current))
641 return GL_FALSE;
642 }
643 else if (texUnit[i]._ReallyEnabled) {
644 return GL_FALSE;
645 }
646 }
647
648 return GL_TRUE;
649 }
650
651
652
653
654
655
656
657
658 static void viaTexImage(GLcontext *ctx,
659 GLint dims,
660 GLenum target, GLint level,
661 GLint internalFormat,
662 GLint width, GLint height, GLint border,
663 GLenum format, GLenum type, const void *pixels,
664 const struct gl_pixelstore_attrib *packing,
665 struct gl_texture_object *texObj,
666 struct gl_texture_image *texImage)
667 {
668 struct via_context *vmesa = VIA_CONTEXT(ctx);
669 GLint postConvWidth = width;
670 GLint postConvHeight = height;
671 GLint texelBytes, sizeInBytes;
672 struct via_texture_object *viaObj = (struct via_texture_object *)texObj;
673 struct via_texture_image *viaImage = (struct via_texture_image *)texImage;
674 int heaps[3], nheaps, i;
675
676 if (!is_empty_list(&vmesa->freed_tex_buffers)) {
677 viaCheckBreadcrumb(vmesa, 0);
678 via_release_pending_textures(vmesa);
679 }
680
681 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
682 _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
683 &postConvHeight);
684 }
685
686 /* choose the texture format */
687 texImage->TexFormat = viaChooseTexFormat(ctx, internalFormat,
688 format, type);
689
690 assert(texImage->TexFormat);
691
692 if (dims == 1) {
693 texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
694 texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
695 }
696 else {
697 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
698 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
699 }
700 texelBytes = texImage->TexFormat->TexelBytes;
701
702 if (texelBytes == 0) {
703 /* compressed format */
704 texImage->IsCompressed = GL_TRUE;
705 texImage->CompressedSize =
706 ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
707 texImage->Height, texImage->Depth,
708 texImage->TexFormat->MesaFormat);
709 }
710
711 /* Minimum pitch of 32 bytes */
712 if (postConvWidth * texelBytes < 32) {
713 postConvWidth = 32 / texelBytes;
714 texImage->RowStride = postConvWidth;
715 }
716
717 assert(texImage->RowStride == postConvWidth);
718 viaImage->pitchLog2 = logbase2(postConvWidth * texelBytes);
719
720 /* allocate memory */
721 if (texImage->IsCompressed)
722 sizeInBytes = texImage->CompressedSize;
723 else
724 sizeInBytes = postConvWidth * postConvHeight * texelBytes;
725
726
727 /* Attempt to allocate texture memory directly, otherwise use main
728 * memory and this texture will always be a fallback. FIXME!
729 *
730 * TODO: make room in agp if this fails.
731 * TODO: use fb ram for textures as well.
732 */
733
734
735 switch (viaObj->memType) {
736 case VIA_MEM_UNKNOWN:
737 heaps[0] = VIA_MEM_AGP;
738 heaps[1] = VIA_MEM_VIDEO;
739 heaps[2] = VIA_MEM_SYSTEM;
740 nheaps = 3;
741 break;
742 case VIA_MEM_AGP:
743 case VIA_MEM_VIDEO:
744 heaps[0] = viaObj->memType;
745 heaps[1] = VIA_MEM_SYSTEM;
746 nheaps = 2;
747 break;
748 case VIA_MEM_MIXED:
749 case VIA_MEM_SYSTEM:
750 default:
751 heaps[0] = VIA_MEM_SYSTEM;
752 nheaps = 1;
753 break;
754 }
755
756 for (i = 0; i < nheaps && !viaImage->texMem; i++) {
757 if (VIA_DEBUG & DEBUG_TEXTURE)
758 fprintf(stderr, "try %s (obj %s)\n", get_memtype_name(heaps[i]),
759 get_memtype_name(viaObj->memType));
760 viaImage->texMem = via_alloc_texture(vmesa, sizeInBytes, heaps[i]);
761 }
762
763 if (!viaImage->texMem) {
764 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
765 return;
766 }
767
768 if (VIA_DEBUG & DEBUG_TEXTURE)
769 fprintf(stderr, "upload %d bytes to %s\n", sizeInBytes,
770 get_memtype_name(viaImage->texMem->memType));
771
772 viaImage->texMem->image = viaImage;
773 texImage->Data = viaImage->texMem->bufAddr;
774
775 if (viaObj->memType == VIA_MEM_UNKNOWN)
776 viaObj->memType = viaImage->texMem->memType;
777 else if (viaObj->memType != viaImage->texMem->memType)
778 viaObj->memType = VIA_MEM_MIXED;
779
780 if (VIA_DEBUG & DEBUG_TEXTURE)
781 fprintf(stderr, "%s, obj %s, image : %s\n",
782 __FUNCTION__,
783 get_memtype_name(viaObj->memType),
784 get_memtype_name(viaImage->texMem->memType));
785
786 vmesa->clearTexCache = 1;
787
788 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
789 format, type,
790 pixels, packing, "glTexImage");
791 if (!pixels) {
792 /* Note: we check for a NULL image pointer here, _after_ we allocated
793 * memory for the texture. That's what the GL spec calls for.
794 */
795 return;
796 }
797 else {
798 GLint dstRowStride;
799 GLboolean success;
800 if (texImage->IsCompressed) {
801 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
802 }
803 else {
804 dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes;
805 }
806 ASSERT(texImage->TexFormat->StoreImage);
807 success = texImage->TexFormat->StoreImage(ctx, dims,
808 texImage->_BaseFormat,
809 texImage->TexFormat,
810 texImage->Data,
811 0, 0, 0, /* dstX/Y/Zoffset */
812 dstRowStride,
813 texImage->ImageOffsets,
814 width, height, 1,
815 format, type, pixels, packing);
816 if (!success) {
817 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
818 }
819 }
820
821 /* GL_SGIS_generate_mipmap */
822 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
823 _mesa_generate_mipmap(ctx, target, texObj);
824 }
825
826 _mesa_unmap_teximage_pbo(ctx, packing);
827 }
828
829 static void viaTexImage2D(GLcontext *ctx,
830 GLenum target, GLint level,
831 GLint internalFormat,
832 GLint width, GLint height, GLint border,
833 GLenum format, GLenum type, const void *pixels,
834 const struct gl_pixelstore_attrib *packing,
835 struct gl_texture_object *texObj,
836 struct gl_texture_image *texImage)
837 {
838 viaTexImage( ctx, 2, target, level,
839 internalFormat, width, height, border,
840 format, type, pixels,
841 packing, texObj, texImage );
842 }
843
844 static void viaTexSubImage2D(GLcontext *ctx,
845 GLenum target,
846 GLint level,
847 GLint xoffset, GLint yoffset,
848 GLsizei width, GLsizei height,
849 GLenum format, GLenum type,
850 const GLvoid *pixels,
851 const struct gl_pixelstore_attrib *packing,
852 struct gl_texture_object *texObj,
853 struct gl_texture_image *texImage)
854 {
855 struct via_context *vmesa = VIA_CONTEXT(ctx);
856
857 viaWaitIdle(vmesa, GL_TRUE);
858 vmesa->clearTexCache = 1;
859
860 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
861 height, format, type, pixels, packing, texObj,
862 texImage);
863 }
864
865 static void viaTexImage1D(GLcontext *ctx,
866 GLenum target, GLint level,
867 GLint internalFormat,
868 GLint width, GLint border,
869 GLenum format, GLenum type, const void *pixels,
870 const struct gl_pixelstore_attrib *packing,
871 struct gl_texture_object *texObj,
872 struct gl_texture_image *texImage)
873 {
874 viaTexImage( ctx, 1, target, level,
875 internalFormat, width, 1, border,
876 format, type, pixels,
877 packing, texObj, texImage );
878 }
879
880 static void viaTexSubImage1D(GLcontext *ctx,
881 GLenum target,
882 GLint level,
883 GLint xoffset,
884 GLsizei width,
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 struct via_context *vmesa = VIA_CONTEXT(ctx);
892
893 viaWaitIdle(vmesa, GL_TRUE);
894 vmesa->clearTexCache = 1;
895
896 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
897 format, type, pixels, packing, texObj,
898 texImage);
899 }
900
901
902
903 static GLboolean viaIsTextureResident(GLcontext *ctx,
904 struct gl_texture_object *texObj)
905 {
906 struct via_texture_object *viaObj =
907 (struct via_texture_object *)texObj;
908
909 return (viaObj->memType == VIA_MEM_AGP ||
910 viaObj->memType == VIA_MEM_VIDEO);
911 }
912
913
914
915 static struct gl_texture_image *viaNewTextureImage( GLcontext *ctx )
916 {
917 (void) ctx;
918 return (struct gl_texture_image *)CALLOC_STRUCT(via_texture_image);
919 }
920
921
922 static struct gl_texture_object *viaNewTextureObject( GLcontext *ctx,
923 GLuint name,
924 GLenum target )
925 {
926 struct via_texture_object *obj = CALLOC_STRUCT(via_texture_object);
927
928 _mesa_initialize_texture_object(&obj->obj, name, target);
929 (void) ctx;
930
931 obj->memType = VIA_MEM_UNKNOWN;
932
933 return &obj->obj;
934 }
935
936
937 static void viaFreeTextureImageData( GLcontext *ctx,
938 struct gl_texture_image *texImage )
939 {
940 struct via_context *vmesa = VIA_CONTEXT(ctx);
941 struct via_texture_image *image = (struct via_texture_image *)texImage;
942
943 if (image->texMem) {
944 via_free_texture(vmesa, image->texMem);
945 image->texMem = NULL;
946 }
947
948 texImage->Data = NULL;
949 }
950
951
952
953
954 void viaInitTextureFuncs(struct dd_function_table * functions)
955 {
956 functions->ChooseTextureFormat = viaChooseTexFormat;
957 functions->TexImage1D = viaTexImage1D;
958 functions->TexImage2D = viaTexImage2D;
959 functions->TexSubImage1D = viaTexSubImage1D;
960 functions->TexSubImage2D = viaTexSubImage2D;
961
962 functions->NewTextureObject = viaNewTextureObject;
963 functions->NewTextureImage = viaNewTextureImage;
964 functions->DeleteTexture = _mesa_delete_texture_object;
965 functions->FreeTexImageData = viaFreeTextureImageData;
966
967 #if 0 && defined( USE_SSE_ASM )
968 /*
969 * XXX this code is disabled for now because the via_sse_memcpy()
970 * routine causes segfaults with flightgear.
971 * See Mesa3d-dev mail list messages from 7/15/2005 for details.
972 * Note that this function is currently disabled in via_tris.c too.
973 */
974 if (getenv("VIA_NO_SSE"))
975 functions->TextureMemCpy = _mesa_memcpy;
976 else
977 functions->TextureMemCpy = via_sse_memcpy;
978 #else
979 functions->TextureMemCpy = _mesa_memcpy;
980 #endif
981
982 functions->UpdateTexturePalette = 0;
983 functions->IsTextureResident = viaIsTextureResident;
984 }
985
986