2 * Author: Max Lingua <sunmax@libero.it>
8 #include "main/glheader.h"
9 #include "main/macros.h"
10 #include "main/mtypes.h"
11 #include "main/simple_list.h"
12 #include "main/enums.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
);