merge unichrome changes from branch
[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
695 /* Minimum pitch of 32 bytes */
696 if (postConvWidth * texelBytes < 32) {
697 postConvWidth = 32 / texelBytes;
698 texImage->RowStride = postConvWidth;
699 }
700
701 assert(texImage->RowStride == postConvWidth);
702 viaImage->pitchLog2 = logbase2(postConvWidth * texelBytes);
703
704 /* allocate memory */
705 if (texImage->IsCompressed)
706 sizeInBytes = texImage->CompressedSize;
707 else
708 sizeInBytes = postConvWidth * postConvHeight * texelBytes;
709
710
711 /* Attempt to allocate texture memory directly, otherwise use main
712 * memory and this texture will always be a fallback. FIXME!
713 *
714 * TODO: make room in agp if this fails.
715 * TODO: use fb ram for textures as well.
716 */
717
718
719 switch (viaObj->memType) {
720 case VIA_MEM_UNKNOWN:
721 heaps[0] = VIA_MEM_AGP;
722 heaps[1] = VIA_MEM_VIDEO;
723 heaps[2] = VIA_MEM_SYSTEM;
724 nheaps = 3;
725 break;
726 case VIA_MEM_AGP:
727 case VIA_MEM_VIDEO:
728 heaps[0] = viaObj->memType;
729 heaps[1] = VIA_MEM_SYSTEM;
730 nheaps = 2;
731 break;
732 case VIA_MEM_MIXED:
733 case VIA_MEM_SYSTEM:
734 default:
735 heaps[0] = VIA_MEM_SYSTEM;
736 nheaps = 1;
737 break;
738 }
739
740 for (i = 0; i < nheaps && !viaImage->texMem; i++) {
741 if (VIA_DEBUG & DEBUG_TEXTURE)
742 fprintf(stderr, "try %s (obj %s)\n", get_memtype_name(heaps[i]),
743 get_memtype_name(viaObj->memType));
744 viaImage->texMem = via_alloc_texture(vmesa, sizeInBytes, heaps[i]);
745 }
746
747 if (!viaImage->texMem) {
748 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
749 return;
750 }
751
752 if (VIA_DEBUG & DEBUG_TEXTURE)
753 fprintf(stderr, "upload %d bytes to %s\n", sizeInBytes,
754 get_memtype_name(viaImage->texMem->memType));
755
756 viaImage->texMem->image = viaImage;
757 texImage->Data = viaImage->texMem->bufAddr;
758
759 if (viaObj->memType == VIA_MEM_UNKNOWN)
760 viaObj->memType = viaImage->texMem->memType;
761 else if (viaObj->memType != viaImage->texMem->memType)
762 viaObj->memType = VIA_MEM_MIXED;
763
764 if (VIA_DEBUG & DEBUG_TEXTURE)
765 fprintf(stderr, "%s, obj %s, image : %s\n",
766 __FUNCTION__,
767 get_memtype_name(viaObj->memType),
768 get_memtype_name(viaImage->texMem->memType));
769
770 vmesa->clearTexCache = 1;
771
772 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
773 format, type,
774 pixels, packing, "glTexImage");
775 if (!pixels) {
776 /* Note: we check for a NULL image pointer here, _after_ we allocated
777 * memory for the texture. That's what the GL spec calls for.
778 */
779 return;
780 }
781 else {
782 GLint dstRowStride, dstImageStride = 0;
783 GLboolean success;
784 if (texImage->IsCompressed) {
785 dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,width);
786 }
787 else {
788 dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes;
789 }
790 ASSERT(texImage->TexFormat->StoreImage);
791 success = texImage->TexFormat->StoreImage(ctx, dims, texImage->Format,
792 texImage->TexFormat,
793 texImage->Data,
794 0, 0, 0, /* dstX/Y/Zoffset */
795 dstRowStride, dstImageStride,
796 width, height, 1,
797 format, type, pixels, packing);
798 if (!success) {
799 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
800 }
801 }
802
803 /* GL_SGIS_generate_mipmap */
804 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
805 _mesa_generate_mipmap(ctx, target,
806 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
807 texObj);
808 }
809
810 _mesa_unmap_teximage_pbo(ctx, packing);
811 }
812
813 static void viaTexImage2D(GLcontext *ctx,
814 GLenum target, GLint level,
815 GLint internalFormat,
816 GLint width, GLint height, GLint border,
817 GLenum format, GLenum type, const void *pixels,
818 const struct gl_pixelstore_attrib *packing,
819 struct gl_texture_object *texObj,
820 struct gl_texture_image *texImage)
821 {
822 viaTexImage( ctx, 2, target, level,
823 internalFormat, width, height, border,
824 format, type, pixels,
825 packing, texObj, texImage );
826 }
827
828 static void viaTexSubImage2D(GLcontext *ctx,
829 GLenum target,
830 GLint level,
831 GLint xoffset, GLint yoffset,
832 GLsizei width, GLsizei height,
833 GLenum format, GLenum type,
834 const GLvoid *pixels,
835 const struct gl_pixelstore_attrib *packing,
836 struct gl_texture_object *texObj,
837 struct gl_texture_image *texImage)
838 {
839 struct via_context *vmesa = VIA_CONTEXT(ctx);
840
841 VIA_FLUSH_DMA(vmesa);
842 vmesa->clearTexCache = 1;
843
844 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
845 height, format, type, pixels, packing, texObj,
846 texImage);
847 }
848
849 static void viaTexImage1D(GLcontext *ctx,
850 GLenum target, GLint level,
851 GLint internalFormat,
852 GLint width, GLint border,
853 GLenum format, GLenum type, const void *pixels,
854 const struct gl_pixelstore_attrib *packing,
855 struct gl_texture_object *texObj,
856 struct gl_texture_image *texImage)
857 {
858 viaTexImage( ctx, 1, target, level,
859 internalFormat, width, 1, border,
860 format, type, pixels,
861 packing, texObj, texImage );
862 }
863
864 static void viaTexSubImage1D(GLcontext *ctx,
865 GLenum target,
866 GLint level,
867 GLint xoffset,
868 GLsizei width,
869 GLenum format, GLenum type,
870 const GLvoid *pixels,
871 const struct gl_pixelstore_attrib *packing,
872 struct gl_texture_object *texObj,
873 struct gl_texture_image *texImage)
874 {
875 struct via_context *vmesa = VIA_CONTEXT(ctx);
876
877 VIA_FLUSH_DMA(vmesa);
878 vmesa->clearTexCache = 1;
879
880 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
881 format, type, pixels, packing, texObj,
882 texImage);
883 }
884
885
886
887 static GLboolean viaIsTextureResident(GLcontext *ctx,
888 struct gl_texture_object *texObj)
889 {
890 struct via_texture_object *viaObj =
891 (struct via_texture_object *)texObj;
892
893 return (viaObj->memType == VIA_MEM_AGP ||
894 viaObj->memType == VIA_MEM_VIDEO);
895 }
896
897
898
899 static struct gl_texture_image *viaNewTextureImage( GLcontext *ctx )
900 {
901 (void) ctx;
902 return (struct gl_texture_image *)CALLOC_STRUCT(via_texture_image);
903 }
904
905
906 static struct gl_texture_object *viaNewTextureObject( GLcontext *ctx,
907 GLuint name,
908 GLenum target )
909 {
910 struct via_texture_object *obj = CALLOC_STRUCT(via_texture_object);
911
912 _mesa_initialize_texture_object(&obj->obj, name, target);
913 (void) ctx;
914
915 obj->memType = VIA_MEM_UNKNOWN;
916
917 return &obj->obj;
918 }
919
920
921 static void viaFreeTextureImageData( GLcontext *ctx,
922 struct gl_texture_image *texImage )
923 {
924 struct via_context *vmesa = VIA_CONTEXT(ctx);
925 struct via_texture_image *image = (struct via_texture_image *)texImage;
926
927 if (image->texMem) {
928 via_free_texture(vmesa, image->texMem);
929 image->texMem = NULL;
930 }
931
932 texImage->Data = NULL;
933 }
934
935
936
937
938 void viaInitTextureFuncs(struct dd_function_table * functions)
939 {
940 functions->ChooseTextureFormat = viaChooseTexFormat;
941 functions->TexImage1D = viaTexImage1D;
942 functions->TexImage2D = viaTexImage2D;
943 functions->TexSubImage1D = viaTexSubImage1D;
944 functions->TexSubImage2D = viaTexSubImage2D;
945
946 functions->NewTextureObject = viaNewTextureObject;
947 functions->NewTextureImage = viaNewTextureImage;
948 functions->DeleteTexture = _mesa_delete_texture_object;
949 functions->FreeTexImageData = viaFreeTextureImageData;
950
951 functions->UpdateTexturePalette = 0;
952 functions->IsTextureResident = viaIsTextureResident;
953 }
954
955