~ubuntu-branches/ubuntu/quantal/mesa-glw/quantal

« back to all changes in this revision

Viewing changes to src/mesa/drivers/dri/s3v/s3v_texmem.c

  • Committer: Bazaar Package Importer
  • Author(s): Morten Kjeldgaard
  • Date: 2008-05-06 16:19:15 UTC
  • Revision ID: james.westby@ubuntu.com-20080506161915-uynz7nftmfixu6bq
Tags: upstream-7.0.3
ImportĀ upstreamĀ versionĀ 7.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Author: Max Lingua <sunmax@libero.it>
 
3
 */
 
4
 
 
5
#include <stdlib.h>
 
6
#include <stdio.h>
 
7
 
 
8
#include "glheader.h"
 
9
#include "macros.h"
 
10
#include "mtypes.h"
 
11
#include "simple_list.h"
 
12
#include "enums.h"
 
13
 
 
14
#include "mm.h"
 
15
#include "s3v_context.h"
 
16
#include "s3v_lock.h"
 
17
#include "s3v_tex.h"
 
18
 
 
19
void s3vSwapOutTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t);
 
20
void s3vUpdateTexLRU( s3vContextPtr vmesa, s3vTextureObjectPtr t );
 
21
 
 
22
 
 
23
void s3vDestroyTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t)
 
24
{
 
25
#if TEX_DEBUG_ON
 
26
   static unsigned int times=0;
 
27
   DEBUG_TEX(("*** s3vDestroyTexObj: #%i ***\n", ++times));
 
28
#endif
 
29
 
 
30
   if (!t) return;
 
31
 
 
32
/* FIXME: useful? */
 
33
#if _TEXFLUSH
 
34
        if (vmesa)
 
35
                DMAFLUSH();
 
36
#endif
 
37
 
 
38
   /* This is sad - need to sync *in case* we upload a texture
 
39
    * to this newly free memory...
 
40
    */
 
41
   if (t->MemBlock) {
 
42
      mmFreeMem(t->MemBlock);
 
43
      t->MemBlock = 0;
 
44
 
 
45
      if (vmesa && t->age > vmesa->dirtyAge)
 
46
             vmesa->dirtyAge = t->age;
 
47
   }
 
48
 
 
49
   if (t->globj)
 
50
      t->globj->DriverData = NULL;
 
51
 
 
52
   if (vmesa) {
 
53
      if (vmesa->CurrentTexObj[0] == t) {
 
54
                vmesa->CurrentTexObj[0] = 0;
 
55
                vmesa->dirty &= ~S3V_UPLOAD_TEX0;
 
56
      }
 
57
 
 
58
#if 0
 
59
      if (vmesa->CurrentTexObj[1] == t) {
 
60
         vmesa->CurrentTexObj[1] = 0;
 
61
         vmesa->dirty &= ~S3V_UPLOAD_TEX1;
 
62
      }
 
63
#endif
 
64
   }
 
65
 
 
66
   remove_from_list(t);
 
67
   FREE(t);
 
68
}
 
69
 
 
70
 
 
71
void s3vSwapOutTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t)
 
72
{
 
73
/*   int i; */
 
74
#if TEX_DEBUG_ON
 
75
   static unsigned int times=0;
 
76
   DEBUG_TEX(("*** s3vSwapOutTexObj: #%i ***\n", ++times));
 
77
#endif
 
78
 
 
79
   if (t->MemBlock) {
 
80
 
 
81
      mmFreeMem(t->MemBlock);
 
82
      t->MemBlock = 0;
 
83
 
 
84
      if (t->age > vmesa->dirtyAge)
 
85
         vmesa->dirtyAge = t->age;
 
86
   
 
87
      t->dirty_images = ~0; 
 
88
      move_to_tail(&(vmesa->SwappedOut), t);
 
89
   }
 
90
}
 
91
 
 
92
 
 
93
/* Upload an image from mesa's internal copy.
 
94
 */
 
95
 
 
96
static void s3vUploadTexLevel( s3vContextPtr vmesa, s3vTextureObjectPtr t,
 
97
                                int level )
 
98
{
 
99
        __DRIscreenPrivate *sPriv = vmesa->driScreen;
 
100
        const struct gl_texture_image *image = t->image[level].image;
 
101
        int i,j;
 
102
        int l2d;
 
103
        /* int offset = 0; */
 
104
        int words;
 
105
        GLuint* dest;
 
106
#if TEX_DEBUG_ON
 
107
        static unsigned int times=0;
 
108
#endif
 
109
        if ( !image ) return;
 
110
        if (image->Data == 0) return;
 
111
 
 
112
        DEBUG_TEX(("*** s3vUploadTexLevel: #%i ***\n", ++times));
 
113
        DEBUG_TEX(("level = %i\n", level));
 
114
 
 
115
        l2d = 5; /* 32bits per texel == 1<<5 */
 
116
/*
 
117
        if (level == 0) 
 
118
                ;
 
119
*/
 
120
        DEBUG_TEX(("t->image[%i].offset = 0x%x\n",
 
121
                level, t->image[level].offset));
 
122
                
 
123
        t->TextureBaseAddr[level] = (GLuint)(t->BufAddr + t->image[level].offset
 
124
                + _TEXALIGN) & (GLuint)(~_TEXALIGN);
 
125
        dest = (GLuint*)(sPriv->pFB + t->TextureBaseAddr[level]); 
 
126
 
 
127
        DEBUG_TEX(("sPriv->pFB = 0x%x\n", sPriv->pFB));
 
128
        DEBUG_TEX(("dest = 0x%x\n", dest));
 
129
        DEBUG_TEX(("dest - sPriv->pFB = 0x%x\n", ((int)dest - (int)sPriv->pFB)));
 
130
 
 
131
        /* NOTE: we implicitly suppose t->texelBytes == 2 */
 
132
 
 
133
        words = (image->Width * image->Height) >> 1;
 
134
 
 
135
        DEBUG_TEX(("\n\n"));
 
136
 
 
137
        switch (t->image[level].internalFormat) {
 
138
        case GL_RGB:
 
139
        case 3:
 
140
        {
 
141
                GLubyte *src = (GLubyte *)image->Data;
 
142
 
 
143
                DEBUG_TEX(("GL_RGB:\n"));
 
144
/*
 
145
                if (level == 0)
 
146
                        ;
 
147
*/
 
148
                /* The UGLY way, and SLOW : use DMA FIXME ! */
 
149
 
 
150
                for (i = 0; i < words; i++) {
 
151
                unsigned int data;
 
152
                /* data = PACK_COLOR_565(src[0],src[1],src[2]); */
 
153
                data = S3VIRGEPACKCOLOR555(src[0],src[1],src[2],255)
 
154
                        |(S3VIRGEPACKCOLOR555(src[3],src[4],src[5],255)<<16);
 
155
 
 
156
                *dest++ = data;
 
157
                /* src += 3; */
 
158
                src +=6;
 
159
        }
 
160
        }
 
161
        break;
 
162
 
 
163
        case GL_RGBA:
 
164
        case 4:
 
165
        {
 
166
                GLubyte *src = (GLubyte *)image->Data;
 
167
 
 
168
                DEBUG_TEX(("GL_RGBA:\n"));
 
169
/*
 
170
                if (level == 0)
 
171
                        ;
 
172
*/
 
173
                for (i = 0; i < words; i++) {           
 
174
                unsigned int data;
 
175
                
 
176
                /* data = PACK_COLOR_8888(src[0],src[1],src[2],src[3]); */
 
177
                data = S3VIRGEPACKCOLOR4444(src[0], src[1],src[2], src[3])
 
178
                | (S3VIRGEPACKCOLOR4444(src[4], src[5], src[6], src[7]) << 16);
 
179
                
 
180
                *dest++ = data;
 
181
                /* src += 4; */
 
182
                src += 8;
 
183
                }
 
184
        }
 
185
        break;
 
186
 
 
187
        case GL_LUMINANCE:
 
188
        {
 
189
                GLubyte *src = (GLubyte *)image->Data;
 
190
 
 
191
                DEBUG_TEX(("GL_LUMINANCE:\n"));
 
192
/*
 
193
                if (level == 0)
 
194
                        ;
 
195
*/
 
196
                for (i = 0; i < words; i++) {
 
197
                unsigned int data;
 
198
                
 
199
                /* data = PACK_COLOR_888(src[0],src[0],src[0]); */
 
200
                data = S3VIRGEPACKCOLOR4444(src[0],src[0],src[0],src[0])
 
201
                | (S3VIRGEPACKCOLOR4444(src[1],src[1],src[1],src[1]) << 16);
 
202
                 
 
203
                *dest++ = data;
 
204
                /* src ++; */
 
205
                src +=2;
 
206
                }
 
207
        }
 
208
        break;
 
209
 
 
210
        case GL_INTENSITY:
 
211
        {
 
212
                GLubyte *src = (GLubyte *)image->Data;
 
213
 
 
214
                DEBUG_TEX(("GL_INTENSITY:\n"));
 
215
/*      
 
216
                if (level == 0)
 
217
                        ;
 
218
*/
 
219
                for (i = 0; i < words; i++) {
 
220
                unsigned int data;
 
221
                
 
222
                /* data = PACK_COLOR_8888(src[0],src[0],src[0],src[0]); */
 
223
                data = S3VIRGEPACKCOLOR4444(src[0],src[0],src[0],src[0])
 
224
                | (S3VIRGEPACKCOLOR4444(src[1],src[1],src[1],src[1]) << 16);
 
225
 
 
226
                *dest++ = data; 
 
227
                /* src ++; */
 
228
                src += 2;
 
229
                }
 
230
        }
 
231
        break;
 
232
 
 
233
        case GL_LUMINANCE_ALPHA:
 
234
        {
 
235
                GLubyte *src = (GLubyte *)image->Data;
 
236
 
 
237
                DEBUG_TEX(("GL_LUMINANCE_ALPHA:\n"));
 
238
/*
 
239
                if (level == 0)
 
240
                        ;
 
241
*/
 
242
                for (i = 0; i < words; i++) {
 
243
                unsigned int data;
 
244
                
 
245
                /* data = PACK_COLOR_8888(src[0],src[0],src[0],src[1]); */
 
246
                data = S3VIRGEPACKCOLOR4444(src[0],src[0],src[0],src[1])
 
247
                | (S3VIRGEPACKCOLOR4444(src[2],src[2],src[2],src[3]) << 16);
 
248
                
 
249
                *dest++ = data;
 
250
                /* src += 2; */
 
251
                src += 4;
 
252
                }
 
253
        }
 
254
        break;
 
255
 
 
256
        case GL_ALPHA:
 
257
        {
 
258
                GLubyte *src = (GLubyte *)image->Data;
 
259
 
 
260
                DEBUG_TEX(("GL_ALPHA:\n"));
 
261
/*
 
262
                if (level == 0)
 
263
                        ;
 
264
*/
 
265
                for (i = 0; i < words; i++) {
 
266
                unsigned int data;
 
267
                
 
268
                /* data = PACK_COLOR_8888(255,255,255,src[0]); */
 
269
                data = S3VIRGEPACKCOLOR4444(255,255,255,src[0])
 
270
                | (S3VIRGEPACKCOLOR4444(255,255,255,src[1]) << 16);
 
271
                
 
272
                *dest++ = data;
 
273
                /* src += 1; */
 
274
                src += 2;
 
275
                }
 
276
        }
 
277
        break;
 
278
 
 
279
        /* TODO: Translate color indices *now*:
 
280
         */
 
281
        case GL_COLOR_INDEX:
 
282
        {
 
283
        
 
284
                GLubyte *dst = (GLubyte *)(t->BufAddr + t->image[level].offset);
 
285
                GLubyte *src = (GLubyte *)image->Data;
 
286
 
 
287
                DEBUG_TEX(("GL_COLOR_INDEX:\n"));
 
288
 
 
289
                for (j = 0 ; j < image->Height ; j++, dst += t->Pitch) {
 
290
                        for (i = 0 ; i < image->Width ; i++) {
 
291
                                dst[i] = src[0];
 
292
                                src += 1;
 
293
                        }
 
294
                }
 
295
        }
 
296
        break;
 
297
 
 
298
        default:
 
299
                fprintf(stderr, "Not supported texture format %s\n",
 
300
                        _mesa_lookup_enum_by_nr(image->_BaseFormat));
 
301
        }
 
302
 
 
303
        DEBUG_TEX(("words = %i\n\n", words));
 
304
}
 
305
 
 
306
void s3vPrintLocalLRU( s3vContextPtr vmesa )
 
307
{
 
308
   s3vTextureObjectPtr t;
 
309
   int sz = 1 << (vmesa->s3vScreen->logTextureGranularity);
 
310
 
 
311
#if TEX_DEBUG_ON
 
312
   static unsigned int times=0;
 
313
   DEBUG_TEX(("*** s3vPrintLocalLRU: #%i ***\n", ++times));
 
314
#endif
 
315
 
 
316
   foreach( t, &vmesa->TexObjList ) {
 
317
      if (!t->globj)
 
318
         fprintf(stderr, "Placeholder %d at %x sz %x\n",
 
319
                    t->MemBlock->ofs / sz,
 
320
                    t->MemBlock->ofs,
 
321
                    t->MemBlock->size);
 
322
      else
 
323
         fprintf(stderr, "Texture at %x sz %x\n",
 
324
                    t->MemBlock->ofs,
 
325
                    t->MemBlock->size);
 
326
 
 
327
   }
 
328
}
 
329
 
 
330
void s3vPrintGlobalLRU( s3vContextPtr vmesa )
 
331
{
 
332
   int i, j;
 
333
   S3VTexRegionPtr list = vmesa->sarea->texList;
 
334
#if TEX_DEBUG_ON
 
335
   static unsigned int times=0;
 
336
   DEBUG_TEX(("*** s3vPrintGlobalLRU: #%i ***\n", ++times));
 
337
#endif
 
338
 
 
339
   for (i = 0, j = S3V_NR_TEX_REGIONS ; i < S3V_NR_TEX_REGIONS ; i++) {
 
340
      fprintf(stderr, "list[%d] age %d next %d prev %d\n",
 
341
              j, list[j].age, list[j].next, list[j].prev);
 
342
      j = list[j].next;
 
343
      if (j == S3V_NR_TEX_REGIONS) break;
 
344
   }
 
345
 
 
346
   if (j != S3V_NR_TEX_REGIONS)
 
347
      fprintf(stderr, "Loop detected in global LRU\n");
 
348
}
 
349
 
 
350
 
 
351
void s3vResetGlobalLRU( s3vContextPtr vmesa )
 
352
{
 
353
   S3VTexRegionPtr list = vmesa->sarea->texList;
 
354
   int sz = 1 << vmesa->s3vScreen->logTextureGranularity;
 
355
   int i;
 
356
 
 
357
#if TEX_DEBUG_ON
 
358
   static unsigned int times=0;
 
359
   DEBUG_TEX(("*** s3vResetGlobalLRU: #%i ***\n", ++times));
 
360
#endif
 
361
 
 
362
   /* (Re)initialize the global circular LRU list.  The last element
 
363
    * in the array (S3V_NR_TEX_REGIONS) is the sentinal.  Keeping it
 
364
    * at the end of the array allows it to be addressed rationally
 
365
    * when looking up objects at a particular location in texture
 
366
    * memory.
 
367
    */
 
368
   for (i = 0 ; (i+1) * sz <= vmesa->s3vScreen->textureSize ; i++) {
 
369
      list[i].prev = i-1;
 
370
      list[i].next = i+1;
 
371
      list[i].age = 0;
 
372
   }
 
373
 
 
374
   i--;
 
375
   list[0].prev = S3V_NR_TEX_REGIONS;
 
376
   list[i].prev = i-1;
 
377
   list[i].next = S3V_NR_TEX_REGIONS;
 
378
   list[S3V_NR_TEX_REGIONS].prev = i;
 
379
   list[S3V_NR_TEX_REGIONS].next = 0;
 
380
   vmesa->sarea->texAge = 0;
 
381
}
 
382
 
 
383
 
 
384
void s3vUpdateTexLRU( s3vContextPtr vmesa, s3vTextureObjectPtr t )
 
385
{
 
386
/*
 
387
   int i;
 
388
   int logsz = vmesa->s3vScreen->logTextureGranularity;
 
389
   int start = t->MemBlock->ofs >> logsz;
 
390
   int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz;
 
391
   S3VTexRegionPtr list = vmesa->sarea->texList;
 
392
*/
 
393
 
 
394
#if TEX_DEBUG_ON
 
395
   static unsigned int times=0;
 
396
   DEBUG_TEX(("*** s3vUpdateTexLRU: #%i ***\n", ++times));
 
397
#endif
 
398
 
 
399
   vmesa->texAge = ++vmesa->sarea->texAge;
 
400
 
 
401
   /* Update our local LRU
 
402
    */
 
403
   move_to_head( &(vmesa->TexObjList), t );
 
404
 
 
405
   /* Update the global LRU
 
406
    */
 
407
#if 0
 
408
   for (i = start ; i <= end ; i++) {
 
409
 
 
410
      list[i].in_use = 1;
 
411
      list[i].age = vmesa->texAge;
 
412
 
 
413
      /* remove_from_list(i)
 
414
       */
 
415
      list[(unsigned)list[i].next].prev = list[i].prev;
 
416
      list[(unsigned)list[i].prev].next = list[i].next;
 
417
 
 
418
      /* insert_at_head(list, i)
 
419
       */
 
420
      list[i].prev = S3V_NR_TEX_REGIONS;
 
421
      list[i].next = list[S3V_NR_TEX_REGIONS].next;
 
422
      list[(unsigned)list[S3V_NR_TEX_REGIONS].next].prev = i;
 
423
      list[S3V_NR_TEX_REGIONS].next = i;
 
424
   }
 
425
#endif
 
426
}
 
427
 
 
428
 
 
429
/* Called for every shared texture region which has increased in age
 
430
 * since we last held the lock.
 
431
 *
 
432
 * Figures out which of our textures have been ejected by other clients,
 
433
 * and pushes a placeholder texture onto the LRU list to represent
 
434
 * the other client's textures.
 
435
 */
 
436
void s3vTexturesGone( s3vContextPtr vmesa,
 
437
                       GLuint offset,
 
438
                       GLuint size,
 
439
                       GLuint in_use )
 
440
{
 
441
   s3vTextureObjectPtr t, tmp;
 
442
#if TEX_DEBUG_ON
 
443
   static unsigned int times=0;
 
444
   DEBUG_TEX(("*** s3vTexturesGone: #%i ***\n", ++times));
 
445
#endif
 
446
 
 
447
   foreach_s ( t, tmp, &vmesa->TexObjList ) {
 
448
 
 
449
      if (t->MemBlock->ofs >= offset + size ||
 
450
          t->MemBlock->ofs + t->MemBlock->size <= offset)
 
451
         continue;
 
452
 
 
453
      /* It overlaps - kick it off.  Need to hold onto the currently bound
 
454
       * objects, however.
 
455
       */
 
456
          s3vSwapOutTexObj( vmesa, t );
 
457
   }
 
458
 
 
459
   if (in_use) {
 
460
                   t = (s3vTextureObjectPtr) calloc(1,sizeof(*t));
 
461
                   if (!t) return;
 
462
 
 
463
                   t->MemBlock = mmAllocMem( vmesa->texHeap, size, 0, offset);
 
464
                   insert_at_head( &vmesa->TexObjList, t );
 
465
   }
 
466
 
 
467
   /* Reload any lost textures referenced by current vertex buffer.
 
468
        */
 
469
#if 0
 
470
   if (vmesa->vertex_buffer) {
 
471
                   int i, j;
 
472
 
 
473
                   fprintf(stderr, "\n\nreload tex\n");
 
474
 
 
475
                   for (i = 0 ; i < vmesa->statenr ; i++) {
 
476
                                   for (j = 0 ; j < 2 ; j++) {
 
477
                                                   s3vTextureObjectPtr t = vmesa->state_tex[j][i];
 
478
                                                   if (t) {
 
479
                                                                   if (t->MemBlock == 0)
 
480
                                                                                   s3vUploadTexImages( vmesa, t );
 
481
                                                   }
 
482
                                   }
 
483
                   }
 
484
 
 
485
                   /* Hard to do this with the lock held:
 
486
                        */
 
487
                   /*        S3V_FIREVERTICES( vmesa ); */
 
488
   }
 
489
#endif
 
490
}
 
491
 
 
492
 
 
493
/* This is called with the lock held.  May have to eject our own and/or
 
494
 * other client's texture objects to make room for the upload.
 
495
 */
 
496
void s3vUploadTexImages( s3vContextPtr vmesa, s3vTextureObjectPtr t )
 
497
{
 
498
        int i;
 
499
        int ofs;
 
500
        int numLevels;
 
501
#if TEX_DEBUG_ON
 
502
        static unsigned int times=0;
 
503
        static unsigned int try=0;
 
504
 
 
505
        DEBUG_TEX(("*** s3vUploadTexImages: #%i ***\n", ++times));
 
506
        DEBUG_TEX(("vmesa->texHeap = 0x%x; t->totalSize = %i\n",
 
507
                (unsigned int)vmesa->texHeap, t->totalSize));
 
508
#endif
 
509
 
 
510
        /* Do we need to eject LRU texture objects?
 
511
         */
 
512
        if (!t->MemBlock) {
 
513
 
 
514
                while (1)
 
515
                {
 
516
                        /* int try = 0; */
 
517
                        DEBUG_TEX(("trying to alloc mem for tex (try %i)\n", ++try));
 
518
 
 
519
                        t->MemBlock = mmAllocMem( vmesa->texHeap, t->totalSize, 12, 0 );
 
520
 
 
521
                        if (t->MemBlock)
 
522
                                break;
 
523
 
 
524
                        if (vmesa->TexObjList.prev == vmesa->CurrentTexObj[0]) {
 
525
/*                          || vmesa->TexObjList.prev == vmesa->CurrentTexObj[1]) {
 
526
                                fprintf(stderr, "Hit bound texture in upload\n");
 
527
                                s3vPrintLocalLRU( vmesa ); */
 
528
                                return;
 
529
                        }
 
530
 
 
531
                        if (vmesa->TexObjList.prev == &(vmesa->TexObjList)) {
 
532
/*                              fprintf(stderr, "Failed to upload texture, sz %d\n",
 
533
                                        t->totalSize);
 
534
                                mmDumpMemInfo( vmesa->texHeap ); */
 
535
                                return;
 
536
                        }
 
537
 
 
538
                        DEBUG_TEX(("swapping out: %p\n", vmesa->TexObjList.prev));
 
539
                        s3vSwapOutTexObj( vmesa, vmesa->TexObjList.prev );
 
540
                }
 
541
 
 
542
        ofs = t->MemBlock->ofs;
 
543
 
 
544
        t->BufAddr = vmesa->s3vScreen->texOffset + ofs;
 
545
 
 
546
        DEBUG_TEX(("ofs = 0x%x\n", ofs));
 
547
        DEBUG_TEX(("t->BufAddr = 0x%x\n", t->BufAddr));
 
548
 
 
549
/* FIXME: check if we need it */
 
550
#if 0
 
551
        if (t == vmesa->CurrentTexObj[0]) {
 
552
                vmesa->dirty |= S3V_UPLOAD_TEX0; 
 
553
                vmesa->restore_primitive = -1; 
 
554
        }
 
555
#endif
 
556
 
 
557
#if 0
 
558
        if (t == vmesa->CurrentTexObj[1])
 
559
                vmesa->dirty |= S3V_UPLOAD_TEX1;
 
560
#endif
 
561
 
 
562
        s3vUpdateTexLRU( vmesa, t );
 
563
        }
 
564
 
 
565
#if 0
 
566
        if (vmesa->dirtyAge >= GET_DISPATCH_AGE(vmesa))
 
567
                s3vWaitAgeLocked( vmesa, vmesa->dirtyAge );
 
568
#endif
 
569
 
 
570
#if _TEXLOCK
 
571
        S3V_SIMPLE_FLUSH_LOCK(vmesa);
 
572
#endif
 
573
        numLevels = t->lastLevel - t->firstLevel + 1;
 
574
        for (i = 0 ; i < numLevels ; i++)
 
575
                if (t->dirty_images & (1<<i))
 
576
                        s3vUploadTexLevel( vmesa, t, i );
 
577
 
 
578
        t->dirty_images = 0;
 
579
#if _TEXLOCK
 
580
        S3V_SIMPLE_UNLOCK(vmesa);
 
581
#endif
 
582
}