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