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