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