1 /* $XFree86: xc/lib/GL/mesa/src/drv/gamma/gamma_texmem.c,v 1.5 2002/11/05 17:46:07 tsi Exp $ */
10 #include "simple_list.h"
14 #include "glint_dri.h"
15 #include "gamma_context.h"
16 #include "gamma_lock.h"
18 void gammaDestroyTexObj(gammaContextPtr gmesa
, gammaTextureObjectPtr t
)
22 /* This is sad - need to sync *in case* we upload a texture
23 * to this newly free memory...
26 mmFreeMem(t
->MemBlock
);
29 if (gmesa
&& t
->age
> gmesa
->dirtyAge
)
30 gmesa
->dirtyAge
= t
->age
;
34 t
->globj
->DriverData
= 0;
37 if (gmesa
->CurrentTexObj
[0] == t
) {
38 gmesa
->CurrentTexObj
[0] = 0;
39 gmesa
->dirty
&= ~GAMMA_UPLOAD_TEX0
;
43 if (gmesa
->CurrentTexObj
[1] == t
) {
44 gmesa
->CurrentTexObj
[1] = 0;
45 gmesa
->dirty
&= ~GAMMA_UPLOAD_TEX1
;
55 void gammaSwapOutTexObj(gammaContextPtr gmesa
, gammaTextureObjectPtr t
)
57 /* fprintf(stderr, "%s\n", __FUNCTION__); */
60 mmFreeMem(t
->MemBlock
);
63 if (t
->age
> gmesa
->dirtyAge
)
64 gmesa
->dirtyAge
= t
->age
;
68 move_to_tail(&(gmesa
->SwappedOut
), t
);
73 /* Upload an image from mesa's internal copy.
75 static void gammaUploadTexLevel( gammaContextPtr gmesa
, gammaTextureObjectPtr t
, int level
)
77 const struct gl_texture_image
*image
= t
->image
[level
].image
;
85 /* fprintf(stderr, "%s\n", __FUNCTION__); */
87 l2d
= 5; /* 32bits per texel == 1<<5 */
90 t
->TextureAddressMode
&= ~(TAM_WidthMask
| TAM_HeightMask
);
91 t
->TextureAddressMode
|= (image
->WidthLog2
<< 9) |
92 (image
->HeightLog2
<< 13);
93 t
->TextureReadMode
&= ~(TRM_WidthMask
| TRM_HeightMask
|
94 TRM_DepthMask
| TRM_Border
|
96 t
->TextureReadMode
|= (image
->WidthLog2
<< 1) |
97 (image
->HeightLog2
<< 5) |
99 t
->TextureFormat
&= ~(TF_CompnentsMask
| TF_OneCompFmt_Mask
);
102 t
->TextureBaseAddr
[level
] = /* ??? */
103 (unsigned long)(t
->image
[level
].offset
+ t
->BufAddr
) << 5;
105 CALC_LOG2(depthLog2
, 1<<l2d
);
106 words
= (image
->Width
* image
->Height
) >> (5-depthLog2
);
108 CHECK_DMA_BUFFER(gmesa
, 3);
109 WRITE(gmesa
->buf
, LBWindowBase
, t
->TextureBaseAddr
[level
] >> 5);
110 WRITE(gmesa
->buf
, TextureCacheControl
, (TCC_Enable
| TCC_Invalidate
));
111 WRITE(gmesa
->buf
, WaitForCompletion
, 0);
112 FLUSH_DMA_BUFFER(gmesa
);
114 switch (t
->image
[level
].internalFormat
) {
118 GLubyte
*src
= (GLubyte
*)image
->Data
;
121 t
->TextureFormat
|= TF_Compnents_3
;
123 #if 0 /* This is the texture download code we SHOULD be using */
124 /* In the routines below, but this causes an DMA overrun - WHY ? */
125 while (offset
< words
) {
126 int count
= gmesa
->bufSize
;
129 if (count
> words
-offset
) count
= words
-offset
;
131 gmesa
->buf
->i
= GlintTextureDownloadOffsetTag
;
133 gmesa
->buf
->i
= offset
;
135 gmesa
->buf
->i
= (GlintTextureDataTag
| ((count
-1) << 16));
138 for (i
= 0; i
< count
; i
++) {
139 gmesa
->buf
->i
= PACK_COLOR_565(src
[0],src
[1],src
[2]);
144 gmesa
->bufCount
= count
+3; /* texture data + 3 values */
147 FLUSH_DMA_BUFFER(gmesa
);
150 /* The UGLY way, and SLOW !, but the above sometimes causes
151 * a DMA overrun error ??? FIXME ! */
153 CHECK_DMA_BUFFER(gmesa
, 1);
154 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
155 for (i
= 0; i
< words
; i
++) {
157 data
= PACK_COLOR_565(src
[0],src
[1],src
[2]);
158 CHECK_DMA_BUFFER(gmesa
, 1);
159 WRITE(gmesa
->buf
, TextureData
, data
);
162 FLUSH_DMA_BUFFER(gmesa
);
170 GLubyte
*src
= (GLubyte
*)image
->Data
;
173 t
->TextureFormat
|= TF_Compnents_4
;
175 /* The UGLY way, and SLOW !, but the above sometimes causes
176 * a DMA overrun error ??? FIXME ! */
177 CHECK_DMA_BUFFER(gmesa
, 1);
178 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
179 for (i
= 0; i
< words
; i
++) {
181 data
= PACK_COLOR_8888(src
[0],src
[1],src
[2],src
[3]);
182 CHECK_DMA_BUFFER(gmesa
, 1);
183 WRITE(gmesa
->buf
, TextureData
, data
);
186 FLUSH_DMA_BUFFER(gmesa
);
192 GLubyte
*src
= (GLubyte
*)image
->Data
;
195 t
->TextureFormat
|= TF_Compnents_1
| TF_OneCompFmt_Lum
;
197 /* The UGLY way, and SLOW !, but the above sometimes causes
198 * a DMA overrun error ??? FIXME ! */
199 CHECK_DMA_BUFFER(gmesa
, 1);
200 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
201 for (i
= 0; i
< words
; i
++) {
203 data
= PACK_COLOR_888(src
[0],src
[0],src
[0]);
204 CHECK_DMA_BUFFER(gmesa
, 1);
205 WRITE(gmesa
->buf
, TextureData
, data
);
208 FLUSH_DMA_BUFFER(gmesa
);
214 GLubyte
*src
= (GLubyte
*)image
->Data
;
217 t
->TextureFormat
|= TF_Compnents_1
| TF_OneCompFmt_Intensity
;
219 /* The UGLY way, and SLOW !, but the above sometimes causes
220 * a DMA overrun error ??? FIXME ! */
221 CHECK_DMA_BUFFER(gmesa
, 1);
222 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
223 for (i
= 0; i
< words
; i
++) {
225 data
= PACK_COLOR_8888(src
[0],src
[0],src
[0],src
[0]);
226 CHECK_DMA_BUFFER(gmesa
, 1);
227 WRITE(gmesa
->buf
, TextureData
, data
);
230 FLUSH_DMA_BUFFER(gmesa
);
234 case GL_LUMINANCE_ALPHA
:
236 GLubyte
*src
= (GLubyte
*)image
->Data
;
239 t
->TextureFormat
|= TF_Compnents_2
;
241 /* The UGLY way, and SLOW !, but the above sometimes causes
242 * a DMA overrun error ??? FIXME ! */
243 CHECK_DMA_BUFFER(gmesa
, 1);
244 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
245 for (i
= 0; i
< words
; i
++) {
247 data
= PACK_COLOR_8888(src
[0],src
[0],src
[0],src
[1]);
248 CHECK_DMA_BUFFER(gmesa
, 1);
249 WRITE(gmesa
->buf
, TextureData
, data
);
252 FLUSH_DMA_BUFFER(gmesa
);
258 GLubyte
*src
= (GLubyte
*)image
->Data
;
261 t
->TextureFormat
|= TF_Compnents_1
| TF_OneCompFmt_Alpha
;
263 /* The UGLY way, and SLOW !, but the above sometimes causes
264 * a DMA overrun error ??? FIXME ! */
265 CHECK_DMA_BUFFER(gmesa
, 1);
266 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
267 for (i
= 0; i
< words
; i
++) {
269 data
= PACK_COLOR_8888(255,255,255,src
[0]);
270 CHECK_DMA_BUFFER(gmesa
, 1);
271 WRITE(gmesa
->buf
, TextureData
, data
);
274 FLUSH_DMA_BUFFER(gmesa
);
278 /* TODO: Translate color indices *now*:
282 GLubyte
*dst
= (GLubyte
*)(t
->BufAddr
+ t
->image
[level
].offset
);
283 GLubyte
*src
= (GLubyte
*)image
->Data
;
285 for (j
= 0 ; j
< image
->Height
; j
++, dst
+= t
->Pitch
) {
286 for (i
= 0 ; i
< image
->Width
; i
++) {
295 fprintf(stderr
, "Not supported texture format %s\n",
296 _mesa_lookup_enum_by_nr(image
->Format
));
299 CHECK_DMA_BUFFER(gmesa
, 2);
300 WRITE(gmesa
->buf
, WaitForCompletion
, 0);
301 WRITE(gmesa
->buf
, LBWindowBase
, gmesa
->LBWindowBase
);
304 void gammaPrintLocalLRU( gammaContextPtr gmesa
)
306 gammaTextureObjectPtr t
;
307 int sz
= 1 << (gmesa
->gammaScreen
->logTextureGranularity
);
309 foreach( t
, &gmesa
->TexObjList
) {
311 fprintf(stderr
, "Placeholder %d at %x sz %x\n",
312 t
->MemBlock
->ofs
/ sz
,
316 fprintf(stderr
, "Texture at %x sz %x\n",
323 void gammaPrintGlobalLRU( gammaContextPtr gmesa
)
326 GAMMATextureRegionPtr list
= gmesa
->sarea
->texList
;
328 for (i
= 0, j
= GAMMA_NR_TEX_REGIONS
; i
< GAMMA_NR_TEX_REGIONS
; i
++) {
329 fprintf(stderr
, "list[%d] age %d next %d prev %d\n",
330 j
, list
[j
].age
, list
[j
].next
, list
[j
].prev
);
332 if (j
== GAMMA_NR_TEX_REGIONS
) break;
335 if (j
!= GAMMA_NR_TEX_REGIONS
)
336 fprintf(stderr
, "Loop detected in global LRU\n");
340 void gammaResetGlobalLRU( gammaContextPtr gmesa
)
342 GAMMATextureRegionPtr list
= gmesa
->sarea
->texList
;
343 int sz
= 1 << gmesa
->gammaScreen
->logTextureGranularity
;
346 /* (Re)initialize the global circular LRU list. The last element
347 * in the array (GAMMA_NR_TEX_REGIONS) is the sentinal. Keeping it
348 * at the end of the array allows it to be addressed rationally
349 * when looking up objects at a particular location in texture
352 for (i
= 0 ; (i
+1) * sz
<= gmesa
->gammaScreen
->textureSize
; i
++) {
359 list
[0].prev
= GAMMA_NR_TEX_REGIONS
;
361 list
[i
].next
= GAMMA_NR_TEX_REGIONS
;
362 list
[GAMMA_NR_TEX_REGIONS
].prev
= i
;
363 list
[GAMMA_NR_TEX_REGIONS
].next
= 0;
364 gmesa
->sarea
->texAge
= 0;
368 void gammaUpdateTexLRU( gammaContextPtr gmesa
, gammaTextureObjectPtr t
)
371 int logsz
= gmesa
->gammaScreen
->logTextureGranularity
;
372 int start
= t
->MemBlock
->ofs
>> logsz
;
373 int end
= (t
->MemBlock
->ofs
+ t
->MemBlock
->size
- 1) >> logsz
;
374 GAMMATextureRegionPtr list
= gmesa
->sarea
->texList
;
376 gmesa
->texAge
= ++gmesa
->sarea
->texAge
;
378 /* Update our local LRU
380 move_to_head( &(gmesa
->TexObjList
), t
);
382 /* Update the global LRU
384 for (i
= start
; i
<= end
; i
++) {
387 list
[i
].age
= gmesa
->texAge
;
389 /* remove_from_list(i)
391 list
[(unsigned)list
[i
].next
].prev
= list
[i
].prev
;
392 list
[(unsigned)list
[i
].prev
].next
= list
[i
].next
;
394 /* insert_at_head(list, i)
396 list
[i
].prev
= GAMMA_NR_TEX_REGIONS
;
397 list
[i
].next
= list
[GAMMA_NR_TEX_REGIONS
].next
;
398 list
[(unsigned)list
[GAMMA_NR_TEX_REGIONS
].next
].prev
= i
;
399 list
[GAMMA_NR_TEX_REGIONS
].next
= i
;
404 /* Called for every shared texture region which has increased in age
405 * since we last held the lock.
407 * Figures out which of our textures have been ejected by other clients,
408 * and pushes a placeholder texture onto the LRU list to represent
409 * the other client's textures.
411 void gammaTexturesGone( gammaContextPtr gmesa
,
416 gammaTextureObjectPtr t
, tmp
;
418 foreach_s ( t
, tmp
, &gmesa
->TexObjList
) {
420 if (t
->MemBlock
->ofs
>= offset
+ size
||
421 t
->MemBlock
->ofs
+ t
->MemBlock
->size
<= offset
)
424 /* It overlaps - kick it off. Need to hold onto the currently bound
427 gammaSwapOutTexObj( gmesa
, t
);
431 t
= (gammaTextureObjectPtr
) calloc(1,sizeof(*t
));
434 t
->MemBlock
= mmAllocMem( gmesa
->texHeap
, size
, 0, offset
);
435 insert_at_head( &gmesa
->TexObjList
, t
);
438 /* Reload any lost textures referenced by current vertex buffer.
441 if (gmesa
->vertex_buffer
) {
444 fprintf(stderr
, "\n\nreload tex\n");
446 for (i
= 0 ; i
< gmesa
->statenr
; i
++) {
447 for (j
= 0 ; j
< 2 ; j
++) {
448 gammaTextureObjectPtr t
= gmesa
->state_tex
[j
][i
];
450 if (t
->MemBlock
== 0)
451 gammaUploadTexImages( gmesa
, t
);
456 /* Hard to do this with the lock held:
458 /* GAMMA_FIREVERTICES( gmesa ); */
467 /* This is called with the lock held. May have to eject our own and/or
468 * other client's texture objects to make room for the upload.
470 void gammaUploadTexImages( gammaContextPtr gmesa
, gammaTextureObjectPtr t
)
476 /* /fprintf(stderr, "%s\n", __FUNCTION__); */
478 LOCK_HARDWARE( gmesa
);
481 /* Do we need to eject LRU texture objects?
486 t
->MemBlock
= mmAllocMem( gmesa
->texHeap
, t
->totalSize
, 12, 0 );
490 if (gmesa
->TexObjList
.prev
== gmesa
->CurrentTexObj
[0] ||
491 gmesa
->TexObjList
.prev
== gmesa
->CurrentTexObj
[1]) {
492 fprintf(stderr
, "Hit bound texture in upload\n");
493 gammaPrintLocalLRU( gmesa
);
497 if (gmesa
->TexObjList
.prev
== &(gmesa
->TexObjList
)) {
498 fprintf(stderr
, "Failed to upload texture, sz %d\n", t
->totalSize
);
499 mmDumpMemInfo( gmesa
->texHeap
);
503 gammaSwapOutTexObj( gmesa
, gmesa
->TexObjList
.prev
);
506 ofs
= t
->MemBlock
->ofs
;
507 t
->BufAddr
= (char *)(unsigned long)(gmesa
->LBWindowBase
+ ofs
); /* ??? */
509 if (t
== gmesa
->CurrentTexObj
[0])
510 gmesa
->dirty
|= GAMMA_UPLOAD_TEX0
;
513 if (t
== gmesa
->CurrentTexObj
[1])
514 gmesa
->dirty
|= GAMMA_UPLOAD_TEX1
;
517 gammaUpdateTexLRU( gmesa
, t
);
521 if (gmesa
->dirtyAge
>= GET_DISPATCH_AGE(gmesa
))
522 gammaWaitAgeLocked( gmesa
, gmesa
->dirtyAge
);
525 numLevels
= t
->lastLevel
- t
->firstLevel
+ 1;
526 for (i
= 0 ; i
< numLevels
; i
++)
527 if (t
->dirty_images
& (1<<i
))
528 gammaUploadTexLevel( gmesa
, t
, i
);
533 UNLOCK_HARDWARE( gmesa
);