5 #include "main/glheader.h"
7 #include "main/macros.h"
8 #include "main/mtypes.h"
9 #include "main/simple_list.h"
10 #include "main/enums.h"
13 #include "glint_dri.h"
14 #include "gammacontext.h"
15 #include "gamma_lock.h"
17 void gammaDestroyTexObj(gammaContextPtr gmesa
, gammaTextureObjectPtr t
)
21 /* This is sad - need to sync *in case* we upload a texture
22 * to this newly free memory...
25 mmFreeMem(t
->MemBlock
);
28 if (gmesa
&& t
->age
> gmesa
->dirtyAge
)
29 gmesa
->dirtyAge
= t
->age
;
33 t
->globj
->DriverData
= 0;
36 if (gmesa
->CurrentTexObj
[0] == t
) {
37 gmesa
->CurrentTexObj
[0] = 0;
38 gmesa
->dirty
&= ~GAMMA_UPLOAD_TEX0
;
42 if (gmesa
->CurrentTexObj
[1] == t
) {
43 gmesa
->CurrentTexObj
[1] = 0;
44 gmesa
->dirty
&= ~GAMMA_UPLOAD_TEX1
;
54 void gammaSwapOutTexObj(gammaContextPtr gmesa
, gammaTextureObjectPtr t
)
56 /* fprintf(stderr, "%s\n", __FUNCTION__); */
59 mmFreeMem(t
->MemBlock
);
62 if (t
->age
> gmesa
->dirtyAge
)
63 gmesa
->dirtyAge
= t
->age
;
67 move_to_tail(&(gmesa
->SwappedOut
), t
);
72 /* Upload an image from mesa's internal copy.
74 static void gammaUploadTexLevel( gammaContextPtr gmesa
, gammaTextureObjectPtr t
, int level
)
76 const struct gl_texture_image
*image
= t
->image
[level
].image
;
84 /* fprintf(stderr, "%s\n", __FUNCTION__); */
86 l2d
= 5; /* 32bits per texel == 1<<5 */
89 t
->TextureAddressMode
&= ~(TAM_WidthMask
| TAM_HeightMask
);
90 t
->TextureAddressMode
|= (image
->WidthLog2
<< 9) |
91 (image
->HeightLog2
<< 13);
92 t
->TextureReadMode
&= ~(TRM_WidthMask
| TRM_HeightMask
|
93 TRM_DepthMask
| TRM_Border
|
95 t
->TextureReadMode
|= (image
->WidthLog2
<< 1) |
96 (image
->HeightLog2
<< 5) |
98 t
->TextureFormat
&= ~(TF_CompnentsMask
| TF_OneCompFmt_Mask
);
101 t
->TextureBaseAddr
[level
] = /* ??? */
102 (unsigned long)(t
->image
[level
].offset
+ t
->BufAddr
) << 5;
104 CALC_LOG2(depthLog2
, 1<<l2d
);
105 words
= (image
->Width
* image
->Height
) >> (5-depthLog2
);
107 CHECK_DMA_BUFFER(gmesa
, 3);
108 WRITE(gmesa
->buf
, LBWindowBase
, t
->TextureBaseAddr
[level
] >> 5);
109 WRITE(gmesa
->buf
, TextureCacheControl
, (TCC_Enable
| TCC_Invalidate
));
110 WRITE(gmesa
->buf
, WaitForCompletion
, 0);
111 FLUSH_DMA_BUFFER(gmesa
);
113 switch (t
->image
[level
].internalFormat
) {
117 GLubyte
*src
= (GLubyte
*)image
->Data
;
120 t
->TextureFormat
|= TF_Compnents_3
;
122 #if 0 /* This is the texture download code we SHOULD be using */
123 /* In the routines below, but this causes an DMA overrun - WHY ? */
124 while (offset
< words
) {
125 int count
= gmesa
->bufSize
;
128 if (count
> words
-offset
) count
= words
-offset
;
130 gmesa
->buf
->i
= GlintTextureDownloadOffsetTag
;
132 gmesa
->buf
->i
= offset
;
134 gmesa
->buf
->i
= (GlintTextureDataTag
| ((count
-1) << 16));
137 for (i
= 0; i
< count
; i
++) {
138 gmesa
->buf
->i
= PACK_COLOR_565(src
[0],src
[1],src
[2]);
143 gmesa
->bufCount
= count
+3; /* texture data + 3 values */
146 FLUSH_DMA_BUFFER(gmesa
);
149 /* The UGLY way, and SLOW !, but the above sometimes causes
150 * a DMA overrun error ??? FIXME ! */
152 CHECK_DMA_BUFFER(gmesa
, 1);
153 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
154 for (i
= 0; i
< words
; i
++) {
156 data
= PACK_COLOR_565(src
[0],src
[1],src
[2]);
157 CHECK_DMA_BUFFER(gmesa
, 1);
158 WRITE(gmesa
->buf
, TextureData
, data
);
161 FLUSH_DMA_BUFFER(gmesa
);
169 GLubyte
*src
= (GLubyte
*)image
->Data
;
172 t
->TextureFormat
|= TF_Compnents_4
;
174 /* The UGLY way, and SLOW !, but the above sometimes causes
175 * a DMA overrun error ??? FIXME ! */
176 CHECK_DMA_BUFFER(gmesa
, 1);
177 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
178 for (i
= 0; i
< words
; i
++) {
180 data
= PACK_COLOR_8888(src
[0],src
[1],src
[2],src
[3]);
181 CHECK_DMA_BUFFER(gmesa
, 1);
182 WRITE(gmesa
->buf
, TextureData
, data
);
185 FLUSH_DMA_BUFFER(gmesa
);
191 GLubyte
*src
= (GLubyte
*)image
->Data
;
194 t
->TextureFormat
|= TF_Compnents_1
| TF_OneCompFmt_Lum
;
196 /* The UGLY way, and SLOW !, but the above sometimes causes
197 * a DMA overrun error ??? FIXME ! */
198 CHECK_DMA_BUFFER(gmesa
, 1);
199 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
200 for (i
= 0; i
< words
; i
++) {
202 data
= PACK_COLOR_888(src
[0],src
[0],src
[0]);
203 CHECK_DMA_BUFFER(gmesa
, 1);
204 WRITE(gmesa
->buf
, TextureData
, data
);
207 FLUSH_DMA_BUFFER(gmesa
);
213 GLubyte
*src
= (GLubyte
*)image
->Data
;
216 t
->TextureFormat
|= TF_Compnents_1
| TF_OneCompFmt_Intensity
;
218 /* The UGLY way, and SLOW !, but the above sometimes causes
219 * a DMA overrun error ??? FIXME ! */
220 CHECK_DMA_BUFFER(gmesa
, 1);
221 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
222 for (i
= 0; i
< words
; i
++) {
224 data
= PACK_COLOR_8888(src
[0],src
[0],src
[0],src
[0]);
225 CHECK_DMA_BUFFER(gmesa
, 1);
226 WRITE(gmesa
->buf
, TextureData
, data
);
229 FLUSH_DMA_BUFFER(gmesa
);
233 case GL_LUMINANCE_ALPHA
:
235 GLubyte
*src
= (GLubyte
*)image
->Data
;
238 t
->TextureFormat
|= TF_Compnents_2
;
240 /* The UGLY way, and SLOW !, but the above sometimes causes
241 * a DMA overrun error ??? FIXME ! */
242 CHECK_DMA_BUFFER(gmesa
, 1);
243 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
244 for (i
= 0; i
< words
; i
++) {
246 data
= PACK_COLOR_8888(src
[0],src
[0],src
[0],src
[1]);
247 CHECK_DMA_BUFFER(gmesa
, 1);
248 WRITE(gmesa
->buf
, TextureData
, data
);
251 FLUSH_DMA_BUFFER(gmesa
);
257 GLubyte
*src
= (GLubyte
*)image
->Data
;
260 t
->TextureFormat
|= TF_Compnents_1
| TF_OneCompFmt_Alpha
;
262 /* The UGLY way, and SLOW !, but the above sometimes causes
263 * a DMA overrun error ??? FIXME ! */
264 CHECK_DMA_BUFFER(gmesa
, 1);
265 WRITE(gmesa
->buf
, TextureDownloadOffset
, 0);
266 for (i
= 0; i
< words
; i
++) {
268 data
= PACK_COLOR_8888(255,255,255,src
[0]);
269 CHECK_DMA_BUFFER(gmesa
, 1);
270 WRITE(gmesa
->buf
, TextureData
, data
);
273 FLUSH_DMA_BUFFER(gmesa
);
277 /* TODO: Translate color indices *now*:
281 GLubyte
*dst
= (GLubyte
*)(t
->BufAddr
+ t
->image
[level
].offset
);
282 GLubyte
*src
= (GLubyte
*)image
->Data
;
284 for (j
= 0 ; j
< image
->Height
; j
++, dst
+= t
->Pitch
) {
285 for (i
= 0 ; i
< image
->Width
; i
++) {
294 fprintf(stderr
, "Not supported texture format %s\n",
295 _mesa_lookup_enum_by_nr(image
->Format
));
298 CHECK_DMA_BUFFER(gmesa
, 2);
299 WRITE(gmesa
->buf
, WaitForCompletion
, 0);
300 WRITE(gmesa
->buf
, LBWindowBase
, gmesa
->LBWindowBase
);
303 void gammaPrintLocalLRU( gammaContextPtr gmesa
)
305 gammaTextureObjectPtr t
;
306 int sz
= 1 << (gmesa
->gammaScreen
->logTextureGranularity
);
308 foreach( t
, &gmesa
->TexObjList
) {
310 fprintf(stderr
, "Placeholder %d at %x sz %x\n",
311 t
->MemBlock
->ofs
/ sz
,
315 fprintf(stderr
, "Texture at %x sz %x\n",
322 void gammaPrintGlobalLRU( gammaContextPtr gmesa
)
325 GAMMATextureRegionPtr list
= gmesa
->sarea
->texList
;
327 for (i
= 0, j
= GAMMA_NR_TEX_REGIONS
; i
< GAMMA_NR_TEX_REGIONS
; i
++) {
328 fprintf(stderr
, "list[%d] age %d next %d prev %d\n",
329 j
, list
[j
].age
, list
[j
].next
, list
[j
].prev
);
331 if (j
== GAMMA_NR_TEX_REGIONS
) break;
334 if (j
!= GAMMA_NR_TEX_REGIONS
)
335 fprintf(stderr
, "Loop detected in global LRU\n");
339 void gammaResetGlobalLRU( gammaContextPtr gmesa
)
341 GAMMATextureRegionPtr list
= gmesa
->sarea
->texList
;
342 int sz
= 1 << gmesa
->gammaScreen
->logTextureGranularity
;
345 /* (Re)initialize the global circular LRU list. The last element
346 * in the array (GAMMA_NR_TEX_REGIONS) is the sentinal. Keeping it
347 * at the end of the array allows it to be addressed rationally
348 * when looking up objects at a particular location in texture
351 for (i
= 0 ; (i
+1) * sz
<= gmesa
->gammaScreen
->textureSize
; i
++) {
358 list
[0].prev
= GAMMA_NR_TEX_REGIONS
;
360 list
[i
].next
= GAMMA_NR_TEX_REGIONS
;
361 list
[GAMMA_NR_TEX_REGIONS
].prev
= i
;
362 list
[GAMMA_NR_TEX_REGIONS
].next
= 0;
363 gmesa
->sarea
->texAge
= 0;
367 void gammaUpdateTexLRU( gammaContextPtr gmesa
, gammaTextureObjectPtr t
)
370 int logsz
= gmesa
->gammaScreen
->logTextureGranularity
;
371 int start
= t
->MemBlock
->ofs
>> logsz
;
372 int end
= (t
->MemBlock
->ofs
+ t
->MemBlock
->size
- 1) >> logsz
;
373 GAMMATextureRegionPtr list
= gmesa
->sarea
->texList
;
375 gmesa
->texAge
= ++gmesa
->sarea
->texAge
;
377 /* Update our local LRU
379 move_to_head( &(gmesa
->TexObjList
), t
);
381 /* Update the global LRU
383 for (i
= start
; i
<= end
; i
++) {
386 list
[i
].age
= gmesa
->texAge
;
388 /* remove_from_list(i)
390 list
[(unsigned)list
[i
].next
].prev
= list
[i
].prev
;
391 list
[(unsigned)list
[i
].prev
].next
= list
[i
].next
;
393 /* insert_at_head(list, i)
395 list
[i
].prev
= GAMMA_NR_TEX_REGIONS
;
396 list
[i
].next
= list
[GAMMA_NR_TEX_REGIONS
].next
;
397 list
[(unsigned)list
[GAMMA_NR_TEX_REGIONS
].next
].prev
= i
;
398 list
[GAMMA_NR_TEX_REGIONS
].next
= i
;
403 /* Called for every shared texture region which has increased in age
404 * since we last held the lock.
406 * Figures out which of our textures have been ejected by other clients,
407 * and pushes a placeholder texture onto the LRU list to represent
408 * the other client's textures.
410 void gammaTexturesGone( gammaContextPtr gmesa
,
415 gammaTextureObjectPtr t
, tmp
;
417 foreach_s ( t
, tmp
, &gmesa
->TexObjList
) {
419 if (t
->MemBlock
->ofs
>= offset
+ size
||
420 t
->MemBlock
->ofs
+ t
->MemBlock
->size
<= offset
)
423 /* It overlaps - kick it off. Need to hold onto the currently bound
426 gammaSwapOutTexObj( gmesa
, t
);
430 t
= (gammaTextureObjectPtr
) calloc(1,sizeof(*t
));
433 t
->MemBlock
= mmAllocMem( gmesa
->texHeap
, size
, 0, offset
);
434 insert_at_head( &gmesa
->TexObjList
, t
);
437 /* Reload any lost textures referenced by current vertex buffer.
440 if (gmesa
->vertex_buffer
) {
443 fprintf(stderr
, "\n\nreload tex\n");
445 for (i
= 0 ; i
< gmesa
->statenr
; i
++) {
446 for (j
= 0 ; j
< 2 ; j
++) {
447 gammaTextureObjectPtr t
= gmesa
->state_tex
[j
][i
];
449 if (t
->MemBlock
== 0)
450 gammaUploadTexImages( gmesa
, t
);
455 /* Hard to do this with the lock held:
457 /* GAMMA_FIREVERTICES( gmesa ); */
466 /* This is called with the lock held. May have to eject our own and/or
467 * other client's texture objects to make room for the upload.
469 void gammaUploadTexImages( gammaContextPtr gmesa
, gammaTextureObjectPtr t
)
475 /* /fprintf(stderr, "%s\n", __FUNCTION__); */
477 LOCK_HARDWARE( gmesa
);
480 /* Do we need to eject LRU texture objects?
485 t
->MemBlock
= mmAllocMem( gmesa
->texHeap
, t
->totalSize
, 12, 0 );
489 if (gmesa
->TexObjList
.prev
== gmesa
->CurrentTexObj
[0] ||
490 gmesa
->TexObjList
.prev
== gmesa
->CurrentTexObj
[1]) {
491 fprintf(stderr
, "Hit bound texture in upload\n");
492 gammaPrintLocalLRU( gmesa
);
496 if (gmesa
->TexObjList
.prev
== &(gmesa
->TexObjList
)) {
497 fprintf(stderr
, "Failed to upload texture, sz %d\n", t
->totalSize
);
498 mmDumpMemInfo( gmesa
->texHeap
);
502 gammaSwapOutTexObj( gmesa
, gmesa
->TexObjList
.prev
);
505 ofs
= t
->MemBlock
->ofs
;
506 t
->BufAddr
= (char *)(unsigned long)(gmesa
->LBWindowBase
+ ofs
); /* ??? */
508 if (t
== gmesa
->CurrentTexObj
[0])
509 gmesa
->dirty
|= GAMMA_UPLOAD_TEX0
;
512 if (t
== gmesa
->CurrentTexObj
[1])
513 gmesa
->dirty
|= GAMMA_UPLOAD_TEX1
;
516 gammaUpdateTexLRU( gmesa
, t
);
520 if (gmesa
->dirtyAge
>= GET_DISPATCH_AGE(gmesa
))
521 gammaWaitAgeLocked( gmesa
, gmesa
->dirtyAge
);
524 numLevels
= t
->lastLevel
- t
->firstLevel
+ 1;
525 for (i
= 0 ; i
< numLevels
; i
++)
526 if (t
->dirty_images
& (1<<i
))
527 gammaUploadTexLevel( gmesa
, t
, i
);
532 UNLOCK_HARDWARE( gmesa
);