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