1
/**************************************************************************
3
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
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:
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.
22
* The above copyright notice and this permission notice (including the
23
* next paragraph) shall be included in all copies or substantial portions
27
**************************************************************************/
29
* Authors: Thomas Hellstrļæ½m <thomas-at-tungstengraphics-dot-com>
30
* Keith Whitwell <keithw-at-tungstengraphics-dot-com>
37
#include "dri_bufmgr.h"
40
#include "dri_bufpool.h"
42
_glthread_DECLARE_STATIC_MUTEX(bmMutex);
45
* TODO: Introduce fence pools in the same way as
46
* buffer object pools.
51
typedef struct _DriFenceObject
54
_glthread_Mutex mutex;
60
typedef struct _DriBufferObject
63
_glthread_Mutex mutex;
74
bmError(int val, const char *file, const char *function, int line)
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);
89
driFenceBuffers(int fd, char *name, unsigned flags)
91
DriFenceObject *fence = (DriFenceObject *) malloc(sizeof(*fence));
97
_glthread_LOCK_MUTEX(bmMutex);
101
_glthread_INIT_MUTEX(fence->mutex);
102
ret = drmFenceBuffers(fd, flags, &fence->fence);
103
_glthread_UNLOCK_MUTEX(bmMutex);
113
driFenceType(DriFenceObject * fence)
117
_glthread_LOCK_MUTEX(bmMutex);
118
ret = fence->fence.flags;
119
_glthread_UNLOCK_MUTEX(bmMutex);
126
driFenceReference(DriFenceObject * fence)
128
_glthread_LOCK_MUTEX(bmMutex);
130
_glthread_UNLOCK_MUTEX(bmMutex);
135
driFenceUnReference(DriFenceObject * fence)
140
_glthread_LOCK_MUTEX(bmMutex);
141
if (--fence->refCount == 0) {
142
drmFenceDestroy(fence->fd, &fence->fence);
145
_glthread_UNLOCK_MUTEX(bmMutex);
149
driFenceFinish(DriFenceObject * fence, unsigned type, int lazy)
152
unsigned flags = (lazy) ? DRM_FENCE_FLAG_WAIT_LAZY : 0;
154
_glthread_LOCK_MUTEX(fence->mutex);
155
ret = drmFenceWait(fence->fd, flags, &fence->fence, type);
156
_glthread_UNLOCK_MUTEX(fence->mutex);
161
driFenceSignaled(DriFenceObject * fence, unsigned type)
169
_glthread_LOCK_MUTEX(fence->mutex);
170
ret = drmFenceSignaled(fence->fd, &fence->fence, type, &signaled);
171
_glthread_UNLOCK_MUTEX(fence->mutex);
178
driBOKernel(struct _DriBufferObject *buf)
182
assert(buf->private != NULL);
183
ret = buf->pool->kernel(buf->pool, buf->private);
191
driBOWaitIdle(struct _DriBufferObject *buf, int lazy)
193
assert(buf->private != NULL);
195
_glthread_LOCK_MUTEX(buf->mutex);
196
BM_CKFATAL(buf->pool->waitIdle(buf->pool, buf->private, lazy));
197
_glthread_UNLOCK_MUTEX(buf->mutex);
201
driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint)
205
assert(buf->private != NULL);
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);
214
driBOUnmap(struct _DriBufferObject *buf)
216
assert(buf->private != NULL);
218
buf->pool->unmap(buf->pool, buf->private);
222
driBOOffset(struct _DriBufferObject *buf)
226
assert(buf->private != NULL);
228
_glthread_LOCK_MUTEX(buf->mutex);
229
ret = buf->pool->offset(buf->pool, buf->private);
230
_glthread_UNLOCK_MUTEX(buf->mutex);
235
driBOFlags(struct _DriBufferObject *buf)
239
assert(buf->private != NULL);
241
_glthread_LOCK_MUTEX(buf->mutex);
242
ret = buf->pool->flags(buf->pool, buf->private);
243
_glthread_UNLOCK_MUTEX(buf->mutex);
247
struct _DriBufferObject *
248
driBOReference(struct _DriBufferObject *buf)
250
_glthread_LOCK_MUTEX(bmMutex);
251
if (++buf->refCount == 1) {
254
_glthread_UNLOCK_MUTEX(bmMutex);
259
driBOUnReference(struct _DriBufferObject *buf)
266
_glthread_LOCK_MUTEX(bmMutex);
267
tmp = --buf->refCount;
268
_glthread_UNLOCK_MUTEX(bmMutex);
270
buf->pool->destroy(buf->pool, buf->private);
276
driBOData(struct _DriBufferObject *buf,
277
unsigned size, const void *data, unsigned flags)
281
struct _DriBufferPool *pool;
283
_glthread_LOCK_MUTEX(buf->mutex);
286
_mesa_error(NULL, GL_INVALID_OPERATION,
287
"driBOData called on invalid buffer\n");
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);
296
pool->destroy(pool, buf->private);
299
buf->private = pool->create(pool, size, flags, 0, buf->alignment);
302
BM_CKFATAL(pool->map(pool, buf->private,
304
DRM_BO_HINT_DONT_BLOCK, &virtual));
308
memcpy(virtual, data, size);
310
BM_CKFATAL(pool->unmap(pool, buf->private));
311
_glthread_UNLOCK_MUTEX(buf->mutex);
315
driBOSubData(struct _DriBufferObject *buf,
316
unsigned long offset, unsigned long size, const void *data)
320
_glthread_LOCK_MUTEX(buf->mutex);
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));
327
_glthread_UNLOCK_MUTEX(buf->mutex);
331
driBOGetSubData(struct _DriBufferObject *buf,
332
unsigned long offset, unsigned long size, void *data)
336
_glthread_LOCK_MUTEX(buf->mutex);
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));
343
_glthread_UNLOCK_MUTEX(buf->mutex);
347
driBOSetStatic(struct _DriBufferObject *buf,
348
unsigned long offset,
349
unsigned long size, void *virtual, unsigned flags)
351
_glthread_LOCK_MUTEX(buf->mutex);
352
if (buf->private != NULL) {
353
_mesa_error(NULL, GL_INVALID_OPERATION,
354
"Invalid buffer for setStatic\n");
357
if (buf->pool->setstatic == NULL) {
358
_mesa_error(NULL, GL_INVALID_OPERATION,
359
"Invalid buffer pool for setStatic\n");
366
buf->private = buf->pool->setstatic(buf->pool, offset, size,
369
_mesa_error(NULL, GL_OUT_OF_MEMORY,
370
"Invalid buffer pool for setStatic\n");
373
_glthread_UNLOCK_MUTEX(buf->mutex);
379
driGenBuffers(struct _DriBufferPool *pool,
382
struct _DriBufferObject *buffers[],
383
unsigned alignment, unsigned flags, unsigned hint)
385
struct _DriBufferObject *buf;
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;
392
for (i = 0; i < n; ++i) {
393
buf = (struct _DriBufferObject *) calloc(1, sizeof(*buf));
397
_glthread_INIT_MUTEX(buf->mutex);
398
_glthread_LOCK_MUTEX(buf->mutex);
399
_glthread_LOCK_MUTEX(bmMutex);
401
_glthread_UNLOCK_MUTEX(bmMutex);
405
buf->alignment = alignment;
407
_glthread_UNLOCK_MUTEX(buf->mutex);
413
driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[])
417
for (i = 0; i < n; ++i) {
418
driBOUnReference(buffers[i]);
424
driInitBufMgr(int fd)
431
driBOCreateList(int target, drmBOList * list)
433
_glthread_LOCK_MUTEX(bmMutex);
434
BM_CKFATAL(drmBOCreateList(20, list));
435
_glthread_UNLOCK_MUTEX(bmMutex);
439
driBOResetList(drmBOList * list)
441
_glthread_LOCK_MUTEX(bmMutex);
442
BM_CKFATAL(drmBOResetList(list));
443
_glthread_UNLOCK_MUTEX(bmMutex);
447
driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf,
448
unsigned flags, unsigned mask)
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);
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.
464
if (buf->pool->validate) {
465
BM_CKFATAL(buf->pool->validate(buf->pool, buf->private));
468
_glthread_UNLOCK_MUTEX(buf->mutex);
472
driBOFence(struct _DriBufferObject *buf, struct _DriFenceObject *fence)
474
_glthread_LOCK_MUTEX(buf->mutex);
475
BM_CKFATAL(buf->pool->fence(buf->pool, buf->private, fence));
476
_glthread_UNLOCK_MUTEX(buf->mutex);
481
driBOValidateList(int fd, drmBOList * list)
483
_glthread_LOCK_MUTEX(bmMutex);
484
BM_CKFATAL(drmBOValidateList(fd, list));
485
_glthread_UNLOCK_MUTEX(bmMutex);
489
driPoolTakeDown(struct _DriBufferPool *pool)
491
pool->takeDown(pool);