2
* GLX Hardware Device Driver for Intel i810
3
* Copyright (C) 1999 Keith Whitwell
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
12
* The above copyright notice and this permission notice shall be included
13
* in all copies or substantial portions of the Software.
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
19
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
#include "simple_list.h"
36
#include "i810screen.h"
39
#include "i810context.h"
41
#include "i810state.h"
42
#include "i810ioctl.h"
45
void i810DestroyTexObj(i810ContextPtr imesa, i810TextureObjectPtr t)
49
/* This is sad - need to sync *in case* we upload a texture
50
* to this newly free memory...
53
mmFreeMem(t->MemBlock);
56
if (imesa && t->age > imesa->dirtyAge)
57
imesa->dirtyAge = t->age;
61
t->globj->DriverData = 0;
64
if (imesa->CurrentTexObj[0] == t) {
65
imesa->CurrentTexObj[0] = 0;
66
imesa->dirty &= ~I810_UPLOAD_TEX0;
69
if (imesa->CurrentTexObj[1] == t) {
70
imesa->CurrentTexObj[1] = 0;
71
imesa->dirty &= ~I810_UPLOAD_TEX1;
80
void i810SwapOutTexObj(i810ContextPtr imesa, i810TextureObjectPtr t)
82
/* fprintf(stderr, "%s\n", __FUNCTION__); */
85
mmFreeMem(t->MemBlock);
88
if (t->age > imesa->dirtyAge)
89
imesa->dirtyAge = t->age;
93
move_to_tail(&(imesa->SwappedOut), t);
98
/* Upload an image from mesa's internal copy.
100
static void i810UploadTexLevel( i810TextureObjectPtr t, int level )
102
const struct gl_texture_image *image = t->image[level].image;
105
switch (t->image[level].internalFormat) {
108
GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
109
GLubyte *src = (GLubyte *)image->Data;
111
for (j = 0 ; j < image->Height ; j++, dst += (t->Pitch/2)) {
112
for (i = 0 ; i < image->Width ; i++) {
113
dst[i] = PACK_COLOR_565( src[0], src[1], src[2] );
122
GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
123
GLubyte *src = (GLubyte *)image->Data;
125
for (j = 0 ; j < image->Height ; j++, dst += (t->Pitch/2)) {
126
for (i = 0 ; i < image->Width ; i++) {
127
dst[i] = PACK_COLOR_4444( src[3], src[0], src[1], src[2] );
136
GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
137
GLubyte *src = (GLubyte *)image->Data;
139
for (j = 0 ; j < image->Height ; j++, dst += (t->Pitch/2)) {
140
for (i = 0 ; i < image->Width ; i++) {
141
dst[i] = PACK_COLOR_565( src[0], src[0], src[0] );
150
GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
151
GLubyte *src = (GLubyte *)image->Data;
154
for (j = 0 ; j < image->Height ; j++, dst += (t->Pitch/2)) {
155
for (i = 0 ; i < image->Width ; i++) {
156
dst[i] = PACK_COLOR_4444( src[0], src[0], src[0], src[0] );
163
case GL_LUMINANCE_ALPHA:
165
GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
166
GLubyte *src = (GLubyte *)image->Data;
168
for (j = 0 ; j < image->Height ; j++, dst += (t->Pitch/2)) {
169
for (i = 0 ; i < image->Width ; i++) {
170
dst[i] = PACK_COLOR_4444( src[1], src[0], src[0], src[0] );
179
GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
180
GLubyte *src = (GLubyte *)image->Data;
182
for (j = 0 ; j < image->Height ; j++, dst += (t->Pitch/2)) {
183
for (i = 0 ; i < image->Width ; i++) {
184
dst[i] = PACK_COLOR_4444( src[0], 255, 255, 255 );
191
/* TODO: Translate color indices *now*:
195
GLubyte *dst = (GLubyte *)(t->BufAddr + t->image[level].offset);
196
GLubyte *src = (GLubyte *)image->Data;
198
for (j = 0 ; j < image->Height ; j++, dst += t->Pitch) {
199
for (i = 0 ; i < image->Width ; i++) {
208
fprintf(stderr, "Not supported texture format %s\n",
209
_mesa_lookup_enum_by_nr(image->Format));
215
void i810PrintLocalLRU( i810ContextPtr imesa )
217
i810TextureObjectPtr t;
218
int sz = 1 << (imesa->i810Screen->logTextureGranularity);
220
foreach( t, &imesa->TexObjList ) {
222
fprintf(stderr, "Placeholder %d at %x sz %x\n",
223
t->MemBlock->ofs / sz,
227
fprintf(stderr, "Texture at %x sz %x\n",
234
void i810PrintGlobalLRU( i810ContextPtr imesa )
237
I810TexRegionRec *list = imesa->sarea->texList;
239
for (i = 0, j = I810_NR_TEX_REGIONS ; i < I810_NR_TEX_REGIONS ; i++) {
240
fprintf(stderr, "list[%d] age %d next %d prev %d\n",
241
j, list[j].age, list[j].next, list[j].prev);
243
if (j == I810_NR_TEX_REGIONS) break;
246
if (j != I810_NR_TEX_REGIONS)
247
fprintf(stderr, "Loop detected in global LRU\n");
251
void i810ResetGlobalLRU( i810ContextPtr imesa )
253
I810TexRegionRec *list = imesa->sarea->texList;
254
int sz = 1 << imesa->i810Screen->logTextureGranularity;
257
/* (Re)initialize the global circular LRU list. The last element
258
* in the array (I810_NR_TEX_REGIONS) is the sentinal. Keeping it
259
* at the end of the array allows it to be addressed rationally
260
* when looking up objects at a particular location in texture
263
for (i = 0 ; (i+1) * sz <= imesa->i810Screen->textureSize ; i++) {
270
list[0].prev = I810_NR_TEX_REGIONS;
272
list[i].next = I810_NR_TEX_REGIONS;
273
list[I810_NR_TEX_REGIONS].prev = i;
274
list[I810_NR_TEX_REGIONS].next = 0;
275
imesa->sarea->texAge = 0;
279
void i810UpdateTexLRU( i810ContextPtr imesa, i810TextureObjectPtr t )
282
int logsz = imesa->i810Screen->logTextureGranularity;
283
int start = t->MemBlock->ofs >> logsz;
284
int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz;
285
I810TexRegionRec *list = imesa->sarea->texList;
287
imesa->texAge = ++imesa->sarea->texAge;
289
/* Update our local LRU
291
move_to_head( &(imesa->TexObjList), t );
293
/* Update the global LRU
295
for (i = start ; i <= end ; i++) {
298
list[i].age = imesa->texAge;
300
/* remove_from_list(i)
302
list[(unsigned)list[i].next].prev = list[i].prev;
303
list[(unsigned)list[i].prev].next = list[i].next;
305
/* insert_at_head(list, i)
307
list[i].prev = I810_NR_TEX_REGIONS;
308
list[i].next = list[I810_NR_TEX_REGIONS].next;
309
list[(unsigned)list[I810_NR_TEX_REGIONS].next].prev = i;
310
list[I810_NR_TEX_REGIONS].next = i;
315
/* Called for every shared texture region which has increased in age
316
* since we last held the lock.
318
* Figures out which of our textures have been ejected by other clients,
319
* and pushes a placeholder texture onto the LRU list to represent
320
* the other client's textures.
322
void i810TexturesGone( i810ContextPtr imesa,
327
i810TextureObjectPtr t, tmp;
329
foreach_s ( t, tmp, &imesa->TexObjList ) {
331
if (t->MemBlock->ofs >= offset + size ||
332
t->MemBlock->ofs + t->MemBlock->size <= offset)
335
/* It overlaps - kick it off. Need to hold onto the currently bound
338
i810SwapOutTexObj( imesa, t );
342
t = (i810TextureObjectPtr) calloc(1,sizeof(*t));
345
t->MemBlock = mmAllocMem( imesa->texHeap, size, 0, offset);
346
insert_at_head( &imesa->TexObjList, t );
354
/* This is called with the lock held. May have to eject our own and/or
355
* other client's texture objects to make room for the upload.
357
void i810UploadTexImages( i810ContextPtr imesa, i810TextureObjectPtr t )
363
LOCK_HARDWARE( imesa );
365
/* Do we need to eject LRU texture objects?
370
t->MemBlock = mmAllocMem( imesa->texHeap, t->totalSize, 12, 0 );
374
if (imesa->TexObjList.prev == imesa->CurrentTexObj[0] ||
375
imesa->TexObjList.prev == imesa->CurrentTexObj[1]) {
376
fprintf(stderr, "Hit bound texture in upload\n");
377
i810PrintLocalLRU( imesa );
381
if (imesa->TexObjList.prev == &(imesa->TexObjList)) {
382
fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize);
383
mmDumpMemInfo( imesa->texHeap );
387
i810SwapOutTexObj( imesa, imesa->TexObjList.prev );
390
ofs = t->MemBlock->ofs;
391
t->BufAddr = imesa->i810Screen->tex.map + ofs;
392
t->Setup[I810_TEXREG_MI3] = imesa->i810Screen->textureOffset + ofs;
394
if (t == imesa->CurrentTexObj[0])
395
I810_STATECHANGE(imesa, I810_UPLOAD_TEX0);
397
if (t == imesa->CurrentTexObj[1])
398
I810_STATECHANGE(imesa, I810_UPLOAD_TEX1);
400
i810UpdateTexLRU( imesa, t );
403
if (imesa->dirtyAge >= GET_DISPATCH_AGE(imesa))
404
i810WaitAgeLocked( imesa, imesa->dirtyAge );
406
numLevels = t->lastLevel - t->firstLevel + 1;
407
for (i = 0 ; i < numLevels ; i++)
408
if (t->dirty_images & (1<<i))
409
i810UploadTexLevel( t, i );
413
UNLOCK_HARDWARE( imesa );