2
* Author: Max Lingua <sunmax@libero.it>
11
#include "simple_list.h"
15
#include "s3v_context.h"
19
void s3vSwapOutTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t);
20
void s3vUpdateTexLRU( s3vContextPtr vmesa, s3vTextureObjectPtr t );
23
void s3vDestroyTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t)
26
static unsigned int times=0;
27
DEBUG_TEX(("*** s3vDestroyTexObj: #%i ***\n", ++times));
38
/* This is sad - need to sync *in case* we upload a texture
39
* to this newly free memory...
42
mmFreeMem(t->MemBlock);
45
if (vmesa && t->age > vmesa->dirtyAge)
46
vmesa->dirtyAge = t->age;
50
t->globj->DriverData = NULL;
53
if (vmesa->CurrentTexObj[0] == t) {
54
vmesa->CurrentTexObj[0] = 0;
55
vmesa->dirty &= ~S3V_UPLOAD_TEX0;
59
if (vmesa->CurrentTexObj[1] == t) {
60
vmesa->CurrentTexObj[1] = 0;
61
vmesa->dirty &= ~S3V_UPLOAD_TEX1;
71
void s3vSwapOutTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t)
75
static unsigned int times=0;
76
DEBUG_TEX(("*** s3vSwapOutTexObj: #%i ***\n", ++times));
81
mmFreeMem(t->MemBlock);
84
if (t->age > vmesa->dirtyAge)
85
vmesa->dirtyAge = t->age;
88
move_to_tail(&(vmesa->SwappedOut), t);
93
/* Upload an image from mesa's internal copy.
96
static void s3vUploadTexLevel( s3vContextPtr vmesa, s3vTextureObjectPtr t,
99
__DRIscreenPrivate *sPriv = vmesa->driScreen;
100
const struct gl_texture_image *image = t->image[level].image;
103
/* int offset = 0; */
107
static unsigned int times=0;
109
if ( !image ) return;
110
if (image->Data == 0) return;
112
DEBUG_TEX(("*** s3vUploadTexLevel: #%i ***\n", ++times));
113
DEBUG_TEX(("level = %i\n", level));
115
l2d = 5; /* 32bits per texel == 1<<5 */
120
DEBUG_TEX(("t->image[%i].offset = 0x%x\n",
121
level, t->image[level].offset));
123
t->TextureBaseAddr[level] = (GLuint)(t->BufAddr + t->image[level].offset
124
+ _TEXALIGN) & (GLuint)(~_TEXALIGN);
125
dest = (GLuint*)(sPriv->pFB + t->TextureBaseAddr[level]);
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)));
131
/* NOTE: we implicitly suppose t->texelBytes == 2 */
133
words = (image->Width * image->Height) >> 1;
137
switch (t->image[level].internalFormat) {
141
GLubyte *src = (GLubyte *)image->Data;
143
DEBUG_TEX(("GL_RGB:\n"));
148
/* The UGLY way, and SLOW : use DMA FIXME ! */
150
for (i = 0; i < words; i++) {
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);
166
GLubyte *src = (GLubyte *)image->Data;
168
DEBUG_TEX(("GL_RGBA:\n"));
173
for (i = 0; i < words; i++) {
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);
189
GLubyte *src = (GLubyte *)image->Data;
191
DEBUG_TEX(("GL_LUMINANCE:\n"));
196
for (i = 0; i < words; i++) {
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);
212
GLubyte *src = (GLubyte *)image->Data;
214
DEBUG_TEX(("GL_INTENSITY:\n"));
219
for (i = 0; i < words; i++) {
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);
233
case GL_LUMINANCE_ALPHA:
235
GLubyte *src = (GLubyte *)image->Data;
237
DEBUG_TEX(("GL_LUMINANCE_ALPHA:\n"));
242
for (i = 0; i < words; i++) {
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);
258
GLubyte *src = (GLubyte *)image->Data;
260
DEBUG_TEX(("GL_ALPHA:\n"));
265
for (i = 0; i < words; i++) {
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);
279
/* TODO: Translate color indices *now*:
284
GLubyte *dst = (GLubyte *)(t->BufAddr + t->image[level].offset);
285
GLubyte *src = (GLubyte *)image->Data;
287
DEBUG_TEX(("GL_COLOR_INDEX:\n"));
289
for (j = 0 ; j < image->Height ; j++, dst += t->Pitch) {
290
for (i = 0 ; i < image->Width ; i++) {
299
fprintf(stderr, "Not supported texture format %s\n",
300
_mesa_lookup_enum_by_nr(image->_BaseFormat));
303
DEBUG_TEX(("words = %i\n\n", words));
306
void s3vPrintLocalLRU( s3vContextPtr vmesa )
308
s3vTextureObjectPtr t;
309
int sz = 1 << (vmesa->s3vScreen->logTextureGranularity);
312
static unsigned int times=0;
313
DEBUG_TEX(("*** s3vPrintLocalLRU: #%i ***\n", ++times));
316
foreach( t, &vmesa->TexObjList ) {
318
fprintf(stderr, "Placeholder %d at %x sz %x\n",
319
t->MemBlock->ofs / sz,
323
fprintf(stderr, "Texture at %x sz %x\n",
330
void s3vPrintGlobalLRU( s3vContextPtr vmesa )
333
S3VTexRegionPtr list = vmesa->sarea->texList;
335
static unsigned int times=0;
336
DEBUG_TEX(("*** s3vPrintGlobalLRU: #%i ***\n", ++times));
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);
343
if (j == S3V_NR_TEX_REGIONS) break;
346
if (j != S3V_NR_TEX_REGIONS)
347
fprintf(stderr, "Loop detected in global LRU\n");
351
void s3vResetGlobalLRU( s3vContextPtr vmesa )
353
S3VTexRegionPtr list = vmesa->sarea->texList;
354
int sz = 1 << vmesa->s3vScreen->logTextureGranularity;
358
static unsigned int times=0;
359
DEBUG_TEX(("*** s3vResetGlobalLRU: #%i ***\n", ++times));
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
368
for (i = 0 ; (i+1) * sz <= vmesa->s3vScreen->textureSize ; i++) {
375
list[0].prev = S3V_NR_TEX_REGIONS;
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;
384
void s3vUpdateTexLRU( s3vContextPtr vmesa, s3vTextureObjectPtr t )
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;
395
static unsigned int times=0;
396
DEBUG_TEX(("*** s3vUpdateTexLRU: #%i ***\n", ++times));
399
vmesa->texAge = ++vmesa->sarea->texAge;
401
/* Update our local LRU
403
move_to_head( &(vmesa->TexObjList), t );
405
/* Update the global LRU
408
for (i = start ; i <= end ; i++) {
411
list[i].age = vmesa->texAge;
413
/* remove_from_list(i)
415
list[(unsigned)list[i].next].prev = list[i].prev;
416
list[(unsigned)list[i].prev].next = list[i].next;
418
/* insert_at_head(list, i)
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;
429
/* Called for every shared texture region which has increased in age
430
* since we last held the lock.
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.
436
void s3vTexturesGone( s3vContextPtr vmesa,
441
s3vTextureObjectPtr t, tmp;
443
static unsigned int times=0;
444
DEBUG_TEX(("*** s3vTexturesGone: #%i ***\n", ++times));
447
foreach_s ( t, tmp, &vmesa->TexObjList ) {
449
if (t->MemBlock->ofs >= offset + size ||
450
t->MemBlock->ofs + t->MemBlock->size <= offset)
453
/* It overlaps - kick it off. Need to hold onto the currently bound
456
s3vSwapOutTexObj( vmesa, t );
460
t = (s3vTextureObjectPtr) calloc(1,sizeof(*t));
463
t->MemBlock = mmAllocMem( vmesa->texHeap, size, 0, offset);
464
insert_at_head( &vmesa->TexObjList, t );
467
/* Reload any lost textures referenced by current vertex buffer.
470
if (vmesa->vertex_buffer) {
473
fprintf(stderr, "\n\nreload tex\n");
475
for (i = 0 ; i < vmesa->statenr ; i++) {
476
for (j = 0 ; j < 2 ; j++) {
477
s3vTextureObjectPtr t = vmesa->state_tex[j][i];
479
if (t->MemBlock == 0)
480
s3vUploadTexImages( vmesa, t );
485
/* Hard to do this with the lock held:
487
/* S3V_FIREVERTICES( vmesa ); */
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.
496
void s3vUploadTexImages( s3vContextPtr vmesa, s3vTextureObjectPtr t )
502
static unsigned int times=0;
503
static unsigned int try=0;
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));
510
/* Do we need to eject LRU texture objects?
517
DEBUG_TEX(("trying to alloc mem for tex (try %i)\n", ++try));
519
t->MemBlock = mmAllocMem( vmesa->texHeap, t->totalSize, 12, 0 );
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 ); */
531
if (vmesa->TexObjList.prev == &(vmesa->TexObjList)) {
532
/* fprintf(stderr, "Failed to upload texture, sz %d\n",
534
mmDumpMemInfo( vmesa->texHeap ); */
538
DEBUG_TEX(("swapping out: %p\n", vmesa->TexObjList.prev));
539
s3vSwapOutTexObj( vmesa, vmesa->TexObjList.prev );
542
ofs = t->MemBlock->ofs;
544
t->BufAddr = vmesa->s3vScreen->texOffset + ofs;
546
DEBUG_TEX(("ofs = 0x%x\n", ofs));
547
DEBUG_TEX(("t->BufAddr = 0x%x\n", t->BufAddr));
549
/* FIXME: check if we need it */
551
if (t == vmesa->CurrentTexObj[0]) {
552
vmesa->dirty |= S3V_UPLOAD_TEX0;
553
vmesa->restore_primitive = -1;
558
if (t == vmesa->CurrentTexObj[1])
559
vmesa->dirty |= S3V_UPLOAD_TEX1;
562
s3vUpdateTexLRU( vmesa, t );
566
if (vmesa->dirtyAge >= GET_DISPATCH_AGE(vmesa))
567
s3vWaitAgeLocked( vmesa, vmesa->dirtyAge );
571
S3V_SIMPLE_FLUSH_LOCK(vmesa);
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 );
580
S3V_SIMPLE_UNLOCK(vmesa);