~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to src/mesa/drivers/dri/common/dri_bufmgr.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**************************************************************************
 
2
 * 
 
3
 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
 
4
 * All Rights Reserved.
 
5
 * 
 
6
 * Permission is hereby granted, free of charge, to any person obtaining a
 
7
 * copy of this software and associated documentation files (the
 
8
 * "Software"), to deal in the Software without restriction, including
 
9
 * without limitation the rights to use, copy, modify, merge, publish,
 
10
 * distribute, sub license, and/or sell copies of the Software, and to
 
11
 * permit persons to whom the Software is furnished to do so, subject to
 
12
 * the following conditions:
 
13
 * 
 
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 
17
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 
18
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
 
19
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
 
20
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 
21
 *
 
22
 * The above copyright notice and this permission notice (including the
 
23
 * next paragraph) shall be included in all copies or substantial portions
 
24
 * of the Software.
 
25
 * 
 
26
 * 
 
27
 **************************************************************************/
 
28
/*
 
29
 * Authors: Thomas Hellstrļæ½m <thomas-at-tungstengraphics-dot-com>
 
30
 *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
 
31
 */
 
32
 
 
33
#include <xf86drm.h>
 
34
#include <stdlib.h>
 
35
#include "glthread.h"
 
36
#include "errno.h"
 
37
#include "dri_bufmgr.h"
 
38
#include "string.h"
 
39
#include "imports.h"
 
40
#include "dri_bufpool.h"
 
41
 
 
42
_glthread_DECLARE_STATIC_MUTEX(bmMutex);
 
43
 
 
44
/*
 
45
 * TODO: Introduce fence pools in the same way as 
 
46
 * buffer object pools.
 
47
 */
 
48
 
 
49
 
 
50
 
 
51
typedef struct _DriFenceObject
 
52
{
 
53
   int fd;
 
54
   _glthread_Mutex mutex;
 
55
   int refCount;
 
56
   const char *name;
 
57
   drmFence fence;
 
58
} DriFenceObject;
 
59
 
 
60
typedef struct _DriBufferObject
 
61
{
 
62
   DriBufferPool *pool;
 
63
   _glthread_Mutex mutex;
 
64
   int refCount;
 
65
   const char *name;
 
66
   unsigned flags;
 
67
   unsigned hint;
 
68
   unsigned alignment;
 
69
   void *private;
 
70
} DriBufferObject;
 
71
 
 
72
 
 
73
void
 
74
bmError(int val, const char *file, const char *function, int line)
 
75
{
 
76
   _mesa_printf("Fatal video memory manager error \"%s\".\n"
 
77
                "Check kernel logs or set the LIBGL_DEBUG\n"
 
78
                "environment variable to \"verbose\" for more info.\n"
 
79
                "Detected in file %s, line %d, function %s.\n",
 
80
                strerror(-val), file, line, function);
 
81
#ifndef NDEBUG
 
82
   abort();
 
83
#else
 
84
   abort();
 
85
#endif
 
86
}
 
87
 
 
88
DriFenceObject *
 
89
driFenceBuffers(int fd, char *name, unsigned flags)
 
90
{
 
91
   DriFenceObject *fence = (DriFenceObject *) malloc(sizeof(*fence));
 
92
   int ret;
 
93
 
 
94
   if (!fence)
 
95
      BM_CKFATAL(-EINVAL);
 
96
 
 
97
   _glthread_LOCK_MUTEX(bmMutex);
 
98
   fence->refCount = 1;
 
99
   fence->name = name;
 
100
   fence->fd = fd;
 
101
   _glthread_INIT_MUTEX(fence->mutex);
 
102
   ret = drmFenceBuffers(fd, flags, &fence->fence);
 
103
   _glthread_UNLOCK_MUTEX(bmMutex);
 
104
   if (ret) {
 
105
      free(fence);
 
106
      BM_CKFATAL(ret);
 
107
   }
 
108
   return fence;
 
109
}
 
110
 
 
111
 
 
112
unsigned 
 
113
driFenceType(DriFenceObject * fence)
 
114
{
 
115
    unsigned ret;
 
116
 
 
117
    _glthread_LOCK_MUTEX(bmMutex);
 
118
    ret = fence->fence.flags;
 
119
    _glthread_UNLOCK_MUTEX(bmMutex);
 
120
    
 
121
    return ret;
 
122
}
 
123
 
 
124
 
 
125
DriFenceObject *
 
126
driFenceReference(DriFenceObject * fence)
 
127
{
 
128
   _glthread_LOCK_MUTEX(bmMutex);
 
129
   ++fence->refCount;
 
130
   _glthread_UNLOCK_MUTEX(bmMutex);
 
131
   return fence;
 
132
}
 
133
 
 
134
void
 
135
driFenceUnReference(DriFenceObject * fence)
 
136
{
 
137
   if (!fence)
 
138
      return;
 
139
 
 
140
   _glthread_LOCK_MUTEX(bmMutex);
 
141
   if (--fence->refCount == 0) {
 
142
      drmFenceDestroy(fence->fd, &fence->fence);
 
143
      free(fence);
 
144
   }
 
145
   _glthread_UNLOCK_MUTEX(bmMutex);
 
146
}
 
147
 
 
148
void
 
149
driFenceFinish(DriFenceObject * fence, unsigned type, int lazy)
 
150
{
 
151
   int ret;
 
152
   unsigned flags = (lazy) ? DRM_FENCE_FLAG_WAIT_LAZY : 0;
 
153
 
 
154
   _glthread_LOCK_MUTEX(fence->mutex);
 
155
   ret = drmFenceWait(fence->fd, flags, &fence->fence, type);
 
156
   _glthread_UNLOCK_MUTEX(fence->mutex);
 
157
   BM_CKFATAL(ret);
 
158
}
 
159
 
 
160
int
 
161
driFenceSignaled(DriFenceObject * fence, unsigned type)
 
162
{
 
163
   int signaled;
 
164
   int ret;
 
165
 
 
166
   if (fence == NULL)
 
167
      return GL_TRUE;
 
168
 
 
169
   _glthread_LOCK_MUTEX(fence->mutex);
 
170
   ret = drmFenceSignaled(fence->fd, &fence->fence, type, &signaled);
 
171
   _glthread_UNLOCK_MUTEX(fence->mutex);
 
172
   BM_CKFATAL(ret);
 
173
   return signaled;
 
174
}
 
175
 
 
176
 
 
177
extern drmBO *
 
178
driBOKernel(struct _DriBufferObject *buf)
 
179
{
 
180
   drmBO *ret;
 
181
 
 
182
   assert(buf->private != NULL);
 
183
   ret = buf->pool->kernel(buf->pool, buf->private);
 
184
   if (!ret)
 
185
      BM_CKFATAL(-EINVAL);
 
186
 
 
187
   return ret;
 
188
}
 
189
 
 
190
void
 
191
driBOWaitIdle(struct _DriBufferObject *buf, int lazy)
 
192
{
 
193
   assert(buf->private != NULL);
 
194
 
 
195
   _glthread_LOCK_MUTEX(buf->mutex);
 
196
   BM_CKFATAL(buf->pool->waitIdle(buf->pool, buf->private, lazy));
 
197
   _glthread_UNLOCK_MUTEX(buf->mutex);
 
198
}
 
199
 
 
200
void *
 
201
driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint)
 
202
{
 
203
   void *virtual;
 
204
 
 
205
   assert(buf->private != NULL);
 
206
 
 
207
   _glthread_LOCK_MUTEX(buf->mutex);
 
208
   BM_CKFATAL(buf->pool->map(buf->pool, buf->private, flags, hint, &virtual));
 
209
   _glthread_UNLOCK_MUTEX(buf->mutex);
 
210
   return virtual;
 
211
}
 
212
 
 
213
void
 
214
driBOUnmap(struct _DriBufferObject *buf)
 
215
{
 
216
   assert(buf->private != NULL);
 
217
 
 
218
   buf->pool->unmap(buf->pool, buf->private);
 
219
}
 
220
 
 
221
unsigned long
 
222
driBOOffset(struct _DriBufferObject *buf)
 
223
{
 
224
   unsigned long ret;
 
225
 
 
226
   assert(buf->private != NULL);
 
227
 
 
228
   _glthread_LOCK_MUTEX(buf->mutex);
 
229
   ret = buf->pool->offset(buf->pool, buf->private);
 
230
   _glthread_UNLOCK_MUTEX(buf->mutex);
 
231
   return ret;
 
232
}
 
233
 
 
234
unsigned
 
235
driBOFlags(struct _DriBufferObject *buf)
 
236
{
 
237
   unsigned ret;
 
238
 
 
239
   assert(buf->private != NULL);
 
240
 
 
241
   _glthread_LOCK_MUTEX(buf->mutex);
 
242
   ret = buf->pool->flags(buf->pool, buf->private);
 
243
   _glthread_UNLOCK_MUTEX(buf->mutex);
 
244
   return ret;
 
245
}
 
246
 
 
247
struct _DriBufferObject *
 
248
driBOReference(struct _DriBufferObject *buf)
 
249
{
 
250
   _glthread_LOCK_MUTEX(bmMutex);
 
251
   if (++buf->refCount == 1) {
 
252
      BM_CKFATAL(-EINVAL);
 
253
   }
 
254
   _glthread_UNLOCK_MUTEX(bmMutex);
 
255
   return buf;
 
256
}
 
257
 
 
258
void
 
259
driBOUnReference(struct _DriBufferObject *buf)
 
260
{
 
261
   int tmp;
 
262
 
 
263
   if (!buf)
 
264
      return;
 
265
 
 
266
   _glthread_LOCK_MUTEX(bmMutex);
 
267
   tmp = --buf->refCount;
 
268
   _glthread_UNLOCK_MUTEX(bmMutex);
 
269
   if (!tmp) {
 
270
      buf->pool->destroy(buf->pool, buf->private);
 
271
      free(buf);
 
272
   }
 
273
}
 
274
 
 
275
void
 
276
driBOData(struct _DriBufferObject *buf,
 
277
          unsigned size, const void *data, unsigned flags)
 
278
{
 
279
   void *virtual;
 
280
   int newBuffer;
 
281
   struct _DriBufferPool *pool;
 
282
 
 
283
   _glthread_LOCK_MUTEX(buf->mutex);
 
284
   pool = buf->pool;
 
285
   if (!pool->create) {
 
286
      _mesa_error(NULL, GL_INVALID_OPERATION,
 
287
                  "driBOData called on invalid buffer\n");
 
288
      BM_CKFATAL(-EINVAL);
 
289
   }
 
290
   newBuffer = !buf->private || (pool->size(pool, buf->private) < size) ||
 
291
      pool->map(pool, buf->private, DRM_BO_FLAG_WRITE,
 
292
                DRM_BO_HINT_DONT_BLOCK, &virtual);
 
293
 
 
294
   if (newBuffer) {
 
295
      if (buf->private)
 
296
         pool->destroy(pool, buf->private);
 
297
      if (!flags)
 
298
         flags = buf->flags;
 
299
      buf->private = pool->create(pool, size, flags, 0, buf->alignment);
 
300
      if (!buf->private)
 
301
         BM_CKFATAL(-ENOMEM);
 
302
      BM_CKFATAL(pool->map(pool, buf->private,
 
303
                           DRM_BO_FLAG_WRITE,
 
304
                           DRM_BO_HINT_DONT_BLOCK, &virtual));
 
305
   }
 
306
 
 
307
   if (data != NULL)
 
308
      memcpy(virtual, data, size);
 
309
 
 
310
   BM_CKFATAL(pool->unmap(pool, buf->private));
 
311
   _glthread_UNLOCK_MUTEX(buf->mutex);
 
312
}
 
313
 
 
314
void
 
315
driBOSubData(struct _DriBufferObject *buf,
 
316
             unsigned long offset, unsigned long size, const void *data)
 
317
{
 
318
   void *virtual;
 
319
 
 
320
   _glthread_LOCK_MUTEX(buf->mutex);
 
321
   if (size && data) {
 
322
      BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
 
323
                                DRM_BO_FLAG_WRITE, 0, &virtual));
 
324
      memcpy((unsigned char *) virtual + offset, data, size);
 
325
      BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
 
326
   }
 
327
   _glthread_UNLOCK_MUTEX(buf->mutex);
 
328
}
 
329
 
 
330
void
 
331
driBOGetSubData(struct _DriBufferObject *buf,
 
332
                unsigned long offset, unsigned long size, void *data)
 
333
{
 
334
   void *virtual;
 
335
 
 
336
   _glthread_LOCK_MUTEX(buf->mutex);
 
337
   if (size && data) {
 
338
      BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
 
339
                                DRM_BO_FLAG_READ, 0, &virtual));
 
340
      memcpy(data, (unsigned char *) virtual + offset, size);
 
341
      BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
 
342
   }
 
343
   _glthread_UNLOCK_MUTEX(buf->mutex);
 
344
}
 
345
 
 
346
void
 
347
driBOSetStatic(struct _DriBufferObject *buf,
 
348
               unsigned long offset,
 
349
               unsigned long size, void *virtual, unsigned flags)
 
350
{
 
351
   _glthread_LOCK_MUTEX(buf->mutex);
 
352
   if (buf->private != NULL) {
 
353
      _mesa_error(NULL, GL_INVALID_OPERATION,
 
354
                  "Invalid buffer for setStatic\n");
 
355
      BM_CKFATAL(-EINVAL);
 
356
   }
 
357
   if (buf->pool->setstatic == NULL) {
 
358
      _mesa_error(NULL, GL_INVALID_OPERATION,
 
359
                  "Invalid buffer pool for setStatic\n");
 
360
      BM_CKFATAL(-EINVAL);
 
361
   }
 
362
 
 
363
   if (!flags)
 
364
      flags = buf->flags;
 
365
 
 
366
   buf->private = buf->pool->setstatic(buf->pool, offset, size,
 
367
                                       virtual, flags);
 
368
   if (!buf->private) {
 
369
      _mesa_error(NULL, GL_OUT_OF_MEMORY,
 
370
                  "Invalid buffer pool for setStatic\n");
 
371
      BM_CKFATAL(-ENOMEM);
 
372
   }
 
373
   _glthread_UNLOCK_MUTEX(buf->mutex);
 
374
}
 
375
 
 
376
 
 
377
 
 
378
void
 
379
driGenBuffers(struct _DriBufferPool *pool,
 
380
              const char *name,
 
381
              unsigned n,
 
382
              struct _DriBufferObject *buffers[],
 
383
              unsigned alignment, unsigned flags, unsigned hint)
 
384
{
 
385
   struct _DriBufferObject *buf;
 
386
   int i;
 
387
 
 
388
   flags = (flags) ? flags : DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM |
 
389
      DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE;
 
390
 
 
391
 
 
392
   for (i = 0; i < n; ++i) {
 
393
      buf = (struct _DriBufferObject *) calloc(1, sizeof(*buf));
 
394
      if (!buf)
 
395
         BM_CKFATAL(-ENOMEM);
 
396
 
 
397
      _glthread_INIT_MUTEX(buf->mutex);
 
398
      _glthread_LOCK_MUTEX(buf->mutex);
 
399
      _glthread_LOCK_MUTEX(bmMutex);
 
400
      buf->refCount = 1;
 
401
      _glthread_UNLOCK_MUTEX(bmMutex);
 
402
      buf->flags = flags;
 
403
      buf->hint = hint;
 
404
      buf->name = name;
 
405
      buf->alignment = alignment;
 
406
      buf->pool = pool;
 
407
      _glthread_UNLOCK_MUTEX(buf->mutex);
 
408
      buffers[i] = buf;
 
409
   }
 
410
}
 
411
 
 
412
void
 
413
driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[])
 
414
{
 
415
   int i;
 
416
 
 
417
   for (i = 0; i < n; ++i) {
 
418
      driBOUnReference(buffers[i]);
 
419
   }
 
420
}
 
421
 
 
422
 
 
423
void
 
424
driInitBufMgr(int fd)
 
425
{
 
426
   ;
 
427
}
 
428
 
 
429
 
 
430
void
 
431
driBOCreateList(int target, drmBOList * list)
 
432
{
 
433
   _glthread_LOCK_MUTEX(bmMutex);
 
434
   BM_CKFATAL(drmBOCreateList(20, list));
 
435
   _glthread_UNLOCK_MUTEX(bmMutex);
 
436
}
 
437
 
 
438
void
 
439
driBOResetList(drmBOList * list)
 
440
{
 
441
   _glthread_LOCK_MUTEX(bmMutex);
 
442
   BM_CKFATAL(drmBOResetList(list));
 
443
   _glthread_UNLOCK_MUTEX(bmMutex);
 
444
}
 
445
 
 
446
void
 
447
driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf,
 
448
                 unsigned flags, unsigned mask)
 
449
{
 
450
   int newItem;
 
451
 
 
452
   _glthread_LOCK_MUTEX(buf->mutex);
 
453
   _glthread_LOCK_MUTEX(bmMutex);
 
454
   BM_CKFATAL(drmAddValidateItem(list, driBOKernel(buf),
 
455
                                 flags, mask, &newItem));
 
456
   _glthread_UNLOCK_MUTEX(bmMutex);
 
457
 
 
458
   /*
 
459
    * Tell userspace pools to validate the buffer. This should be a 
 
460
    * noop if the pool is already validated.
 
461
    * FIXME: We should have a list for this as well.
 
462
    */
 
463
 
 
464
   if (buf->pool->validate) {
 
465
      BM_CKFATAL(buf->pool->validate(buf->pool, buf->private));
 
466
   }
 
467
 
 
468
   _glthread_UNLOCK_MUTEX(buf->mutex);
 
469
}
 
470
 
 
471
void
 
472
driBOFence(struct _DriBufferObject *buf, struct _DriFenceObject *fence)
 
473
{
 
474
   _glthread_LOCK_MUTEX(buf->mutex);
 
475
   BM_CKFATAL(buf->pool->fence(buf->pool, buf->private, fence));
 
476
   _glthread_UNLOCK_MUTEX(buf->mutex);
 
477
 
 
478
}
 
479
 
 
480
void
 
481
driBOValidateList(int fd, drmBOList * list)
 
482
{
 
483
   _glthread_LOCK_MUTEX(bmMutex);
 
484
   BM_CKFATAL(drmBOValidateList(fd, list));
 
485
   _glthread_UNLOCK_MUTEX(bmMutex);
 
486
}
 
487
 
 
488
void
 
489
driPoolTakeDown(struct _DriBufferPool *pool)
 
490
{
 
491
   pool->takeDown(pool);
 
492
 
 
493
}