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