~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/lib/GL/mesa/src/drv/i810/i810texmem.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * GLX Hardware Device Driver for Intel i810
 
3
 * Copyright (C) 1999 Keith Whitwell
 
4
 *
 
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:
 
11
 *
 
12
 * The above copyright notice and this permission notice shall be included
 
13
 * in all copies or substantial portions of the Software.
 
14
 *
 
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.
 
22
 *
 
23
 */
 
24
 
 
25
#include <stdlib.h>
 
26
#include <stdio.h>
 
27
 
 
28
#include "glheader.h"
 
29
#include "macros.h"
 
30
#include "mtypes.h"
 
31
#include "simple_list.h"
 
32
#include "enums.h"
 
33
 
 
34
#include "mm.h"
 
35
 
 
36
#include "i810screen.h"
 
37
#include "i810_dri.h"
 
38
 
 
39
#include "i810context.h"
 
40
#include "i810tex.h"
 
41
#include "i810state.h"
 
42
#include "i810ioctl.h"
 
43
 
 
44
 
 
45
void i810DestroyTexObj(i810ContextPtr imesa, i810TextureObjectPtr t)
 
46
{
 
47
   if (!t) return;
 
48
 
 
49
   /* This is sad - need to sync *in case* we upload a texture
 
50
    * to this newly free memory...
 
51
    */
 
52
   if (t->MemBlock) {
 
53
      mmFreeMem(t->MemBlock);
 
54
      t->MemBlock = 0;
 
55
 
 
56
      if (imesa && t->age > imesa->dirtyAge)
 
57
         imesa->dirtyAge = t->age;
 
58
   }
 
59
 
 
60
   if (t->globj)
 
61
      t->globj->DriverData = 0;
 
62
 
 
63
   if (imesa) {
 
64
      if (imesa->CurrentTexObj[0] == t) {
 
65
         imesa->CurrentTexObj[0] = 0;
 
66
         imesa->dirty &= ~I810_UPLOAD_TEX0;
 
67
      }
 
68
 
 
69
      if (imesa->CurrentTexObj[1] == t) {
 
70
         imesa->CurrentTexObj[1] = 0;
 
71
         imesa->dirty &= ~I810_UPLOAD_TEX1;
 
72
      }
 
73
   }
 
74
 
 
75
   remove_from_list(t);
 
76
   free(t);
 
77
}
 
78
 
 
79
 
 
80
void i810SwapOutTexObj(i810ContextPtr imesa, i810TextureObjectPtr t)
 
81
{
 
82
/*     fprintf(stderr, "%s\n", __FUNCTION__); */
 
83
 
 
84
   if (t->MemBlock) {
 
85
      mmFreeMem(t->MemBlock);
 
86
      t->MemBlock = 0;
 
87
 
 
88
      if (t->age > imesa->dirtyAge)
 
89
         imesa->dirtyAge = t->age;
 
90
   }
 
91
 
 
92
   t->dirty_images = ~0;
 
93
   move_to_tail(&(imesa->SwappedOut), t);
 
94
}
 
95
 
 
96
 
 
97
 
 
98
/* Upload an image from mesa's internal copy.
 
99
 */
 
100
static void i810UploadTexLevel( i810TextureObjectPtr t, int level )
 
101
{
 
102
   const struct gl_texture_image *image = t->image[level].image;
 
103
   int i,j;
 
104
 
 
105
   switch (t->image[level].internalFormat) {
 
106
   case GL_RGB:
 
107
   {
 
108
      GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
 
109
      GLubyte  *src = (GLubyte *)image->Data;
 
110
 
 
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] );
 
114
            src += 3;
 
115
         }
 
116
      }
 
117
   }
 
118
   break;
 
119
 
 
120
   case GL_RGBA:
 
121
   {
 
122
      GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
 
123
      GLubyte  *src = (GLubyte *)image->Data;
 
124
 
 
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] );
 
128
            src += 4;
 
129
         }
 
130
      }
 
131
   }
 
132
   break;
 
133
 
 
134
   case GL_LUMINANCE:
 
135
   {
 
136
      GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
 
137
      GLubyte  *src = (GLubyte *)image->Data;
 
138
 
 
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] );
 
142
            src ++;
 
143
         }
 
144
      }
 
145
   }
 
146
   break;
 
147
 
 
148
   case GL_INTENSITY:
 
149
   {
 
150
      GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
 
151
      GLubyte  *src = (GLubyte *)image->Data;
 
152
      int i;
 
153
 
 
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] );
 
157
            src ++;
 
158
         }
 
159
      }
 
160
   }
 
161
   break;
 
162
 
 
163
   case GL_LUMINANCE_ALPHA:
 
164
   {
 
165
      GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
 
166
      GLubyte  *src = (GLubyte *)image->Data;
 
167
 
 
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] );
 
171
            src += 2;
 
172
         }
 
173
      }
 
174
   }
 
175
   break;
 
176
 
 
177
   case GL_ALPHA:
 
178
   {
 
179
      GLushort *dst = (GLushort *)(t->BufAddr + t->image[level].offset);
 
180
      GLubyte  *src = (GLubyte *)image->Data;
 
181
 
 
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 );
 
185
            src += 1;
 
186
         }
 
187
      }
 
188
   }
 
189
   break;
 
190
 
 
191
   /* TODO: Translate color indices *now*:
 
192
    */
 
193
   case GL_COLOR_INDEX:
 
194
      {
 
195
         GLubyte *dst = (GLubyte *)(t->BufAddr + t->image[level].offset);
 
196
         GLubyte *src = (GLubyte *)image->Data;
 
197
 
 
198
         for (j = 0 ; j < image->Height ; j++, dst += t->Pitch) {
 
199
            for (i = 0 ; i < image->Width ; i++) {
 
200
               dst[i] = src[0];
 
201
               src += 1;
 
202
            }
 
203
         }
 
204
      }
 
205
   break;
 
206
 
 
207
   default:
 
208
      fprintf(stderr, "Not supported texture format %s\n",
 
209
              _mesa_lookup_enum_by_nr(image->Format));
 
210
   }
 
211
}
 
212
 
 
213
 
 
214
 
 
215
void i810PrintLocalLRU( i810ContextPtr imesa )
 
216
{
 
217
   i810TextureObjectPtr t;
 
218
   int sz = 1 << (imesa->i810Screen->logTextureGranularity);
 
219
 
 
220
   foreach( t, &imesa->TexObjList ) {
 
221
      if (!t->globj)
 
222
         fprintf(stderr, "Placeholder %d at %x sz %x\n",
 
223
                 t->MemBlock->ofs / sz,
 
224
                 t->MemBlock->ofs,
 
225
                 t->MemBlock->size);
 
226
      else
 
227
         fprintf(stderr, "Texture at %x sz %x\n",
 
228
                 t->MemBlock->ofs,
 
229
                 t->MemBlock->size);
 
230
 
 
231
   }
 
232
}
 
233
 
 
234
void i810PrintGlobalLRU( i810ContextPtr imesa )
 
235
{
 
236
   int i, j;
 
237
   I810TexRegionRec *list = imesa->sarea->texList;
 
238
 
 
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);
 
242
      j = list[j].next;
 
243
      if (j == I810_NR_TEX_REGIONS) break;
 
244
   }
 
245
 
 
246
   if (j != I810_NR_TEX_REGIONS)
 
247
      fprintf(stderr, "Loop detected in global LRU\n");
 
248
}
 
249
 
 
250
 
 
251
void i810ResetGlobalLRU( i810ContextPtr imesa )
 
252
{
 
253
   I810TexRegionRec *list = imesa->sarea->texList;
 
254
   int sz = 1 << imesa->i810Screen->logTextureGranularity;
 
255
   int i;
 
256
 
 
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
 
261
    * memory.
 
262
    */
 
263
   for (i = 0 ; (i+1) * sz <= imesa->i810Screen->textureSize ; i++) {
 
264
      list[i].prev = i-1;
 
265
      list[i].next = i+1;
 
266
      list[i].age = 0;
 
267
   }
 
268
 
 
269
   i--;
 
270
   list[0].prev = I810_NR_TEX_REGIONS;
 
271
   list[i].prev = i-1;
 
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;
 
276
}
 
277
 
 
278
 
 
279
void i810UpdateTexLRU( i810ContextPtr imesa, i810TextureObjectPtr t )
 
280
{
 
281
   int i;
 
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;
 
286
 
 
287
   imesa->texAge = ++imesa->sarea->texAge;
 
288
 
 
289
   /* Update our local LRU
 
290
    */
 
291
   move_to_head( &(imesa->TexObjList), t );
 
292
 
 
293
   /* Update the global LRU
 
294
    */
 
295
   for (i = start ; i <= end ; i++) {
 
296
 
 
297
      list[i].in_use = 1;
 
298
      list[i].age = imesa->texAge;
 
299
 
 
300
      /* remove_from_list(i)
 
301
       */
 
302
      list[(unsigned)list[i].next].prev = list[i].prev;
 
303
      list[(unsigned)list[i].prev].next = list[i].next;
 
304
 
 
305
      /* insert_at_head(list, i)
 
306
       */
 
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;
 
311
   }
 
312
}
 
313
 
 
314
 
 
315
/* Called for every shared texture region which has increased in age
 
316
 * since we last held the lock.
 
317
 *
 
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.
 
321
 */
 
322
void i810TexturesGone( i810ContextPtr imesa,
 
323
                       GLuint offset,
 
324
                       GLuint size,
 
325
                       GLuint in_use )
 
326
{
 
327
   i810TextureObjectPtr t, tmp;
 
328
 
 
329
   foreach_s ( t, tmp, &imesa->TexObjList ) {
 
330
 
 
331
      if (t->MemBlock->ofs >= offset + size ||
 
332
          t->MemBlock->ofs + t->MemBlock->size <= offset)
 
333
         continue;
 
334
 
 
335
      /* It overlaps - kick it off.  Need to hold onto the currently bound
 
336
       * objects, however.
 
337
       */
 
338
      i810SwapOutTexObj( imesa, t );
 
339
   }
 
340
 
 
341
   if (in_use) {
 
342
      t = (i810TextureObjectPtr) calloc(1,sizeof(*t));
 
343
      if (!t) return;
 
344
 
 
345
      t->MemBlock = mmAllocMem( imesa->texHeap, size, 0, offset);
 
346
      insert_at_head( &imesa->TexObjList, t );
 
347
   }
 
348
}
 
349
 
 
350
 
 
351
 
 
352
 
 
353
 
 
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.
 
356
 */
 
357
void i810UploadTexImages( i810ContextPtr imesa, i810TextureObjectPtr t )
 
358
{
 
359
   int i;
 
360
   int ofs;
 
361
   int numLevels;
 
362
 
 
363
   LOCK_HARDWARE( imesa );
 
364
 
 
365
   /* Do we need to eject LRU texture objects?
 
366
    */
 
367
   if (!t->MemBlock) {
 
368
      while (1)
 
369
      {
 
370
         t->MemBlock = mmAllocMem( imesa->texHeap, t->totalSize, 12, 0 );
 
371
         if (t->MemBlock)
 
372
            break;
 
373
 
 
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 );
 
378
            return;
 
379
         }
 
380
 
 
381
         if (imesa->TexObjList.prev == &(imesa->TexObjList)) {
 
382
            fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize);
 
383
            mmDumpMemInfo( imesa->texHeap );
 
384
            return;
 
385
         }
 
386
 
 
387
         i810SwapOutTexObj( imesa, imesa->TexObjList.prev );
 
388
      }
 
389
 
 
390
      ofs = t->MemBlock->ofs;
 
391
      t->BufAddr = imesa->i810Screen->tex.map + ofs;
 
392
      t->Setup[I810_TEXREG_MI3] = imesa->i810Screen->textureOffset + ofs;
 
393
 
 
394
      if (t == imesa->CurrentTexObj[0])
 
395
         I810_STATECHANGE(imesa, I810_UPLOAD_TEX0);
 
396
 
 
397
      if (t == imesa->CurrentTexObj[1])
 
398
         I810_STATECHANGE(imesa, I810_UPLOAD_TEX1);
 
399
 
 
400
      i810UpdateTexLRU( imesa, t );
 
401
   }
 
402
 
 
403
   if (imesa->dirtyAge >= GET_DISPATCH_AGE(imesa))
 
404
      i810WaitAgeLocked( imesa, imesa->dirtyAge );
 
405
 
 
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 );
 
410
 
 
411
   t->dirty_images = 0;
 
412
 
 
413
   UNLOCK_HARDWARE( imesa );
 
414
}