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
);