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