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
;
70 /* user-space buffer: */
78 bmError(int val
, const char *file
, const char *function
, int line
)
80 _mesa_printf("Fatal video memory manager error \"%s\".\n"
81 "Check kernel logs or set the LIBGL_DEBUG\n"
82 "environment variable to \"verbose\" for more info.\n"
83 "Detected in file %s, line %d, function %s.\n",
84 strerror(-val
), file
, line
, function
);
93 driFenceBuffers(int fd
, char *name
, unsigned flags
)
95 DriFenceObject
*fence
= (DriFenceObject
*) malloc(sizeof(*fence
));
101 _glthread_LOCK_MUTEX(bmMutex
);
105 _glthread_INIT_MUTEX(fence
->mutex
);
106 ret
= drmFenceBuffers(fd
, flags
, &fence
->fence
);
107 _glthread_UNLOCK_MUTEX(bmMutex
);
117 driFenceType(DriFenceObject
* fence
)
121 _glthread_LOCK_MUTEX(bmMutex
);
122 ret
= fence
->fence
.flags
;
123 _glthread_UNLOCK_MUTEX(bmMutex
);
130 driFenceReference(DriFenceObject
* fence
)
132 _glthread_LOCK_MUTEX(bmMutex
);
134 _glthread_UNLOCK_MUTEX(bmMutex
);
139 driFenceUnReference(DriFenceObject
* fence
)
144 _glthread_LOCK_MUTEX(bmMutex
);
145 if (--fence
->refCount
== 0) {
146 drmFenceDestroy(fence
->fd
, &fence
->fence
);
149 _glthread_UNLOCK_MUTEX(bmMutex
);
153 driFenceFinish(DriFenceObject
* fence
, unsigned type
, int lazy
)
156 unsigned flags
= (lazy
) ? DRM_FENCE_FLAG_WAIT_LAZY
: 0;
158 _glthread_LOCK_MUTEX(fence
->mutex
);
159 ret
= drmFenceWait(fence
->fd
, flags
, &fence
->fence
, type
);
160 _glthread_UNLOCK_MUTEX(fence
->mutex
);
165 driFenceSignaled(DriFenceObject
* fence
, unsigned type
)
173 _glthread_LOCK_MUTEX(fence
->mutex
);
174 ret
= drmFenceSignaled(fence
->fd
, &fence
->fence
, type
, &signaled
);
175 _glthread_UNLOCK_MUTEX(fence
->mutex
);
182 driBOKernel(struct _DriBufferObject
*buf
)
186 assert(buf
->private != NULL
);
187 ret
= buf
->pool
->kernel(buf
->pool
, buf
->private);
195 driBOWaitIdle(struct _DriBufferObject
*buf
, int lazy
)
197 struct _DriBufferPool
*pool
;
200 _glthread_LOCK_MUTEX(buf
->mutex
);
203 _glthread_UNLOCK_MUTEX(buf
->mutex
);
205 assert(priv
!= NULL
);
206 BM_CKFATAL(buf
->pool
->waitIdle(pool
, priv
, lazy
));
210 driBOMap(struct _DriBufferObject
*buf
, unsigned flags
, unsigned hint
)
212 if (buf
->userBuffer
) {
213 return buf
->userData
;
218 assert(buf
->private != NULL
);
220 _glthread_LOCK_MUTEX(buf
->mutex
);
221 BM_CKFATAL(buf
->pool
->map(buf
->pool
, buf
->private, flags
, hint
, &virtual));
222 _glthread_UNLOCK_MUTEX(buf
->mutex
);
228 driBOUnmap(struct _DriBufferObject
*buf
)
230 if (!buf
->userBuffer
) {
231 assert(buf
->private != NULL
);
233 buf
->pool
->unmap(buf
->pool
, buf
->private);
238 driBOOffset(struct _DriBufferObject
*buf
)
242 assert(buf
->private != NULL
);
244 _glthread_LOCK_MUTEX(buf
->mutex
);
245 ret
= buf
->pool
->offset(buf
->pool
, buf
->private);
246 _glthread_UNLOCK_MUTEX(buf
->mutex
);
251 driBOFlags(struct _DriBufferObject
*buf
)
255 assert(buf
->private != NULL
);
257 _glthread_LOCK_MUTEX(buf
->mutex
);
258 ret
= buf
->pool
->flags(buf
->pool
, buf
->private);
259 _glthread_UNLOCK_MUTEX(buf
->mutex
);
263 struct _DriBufferObject
*
264 driBOReference(struct _DriBufferObject
*buf
)
266 _glthread_LOCK_MUTEX(bmMutex
);
267 if (++buf
->refCount
== 1) {
270 _glthread_UNLOCK_MUTEX(bmMutex
);
275 driBOUnReference(struct _DriBufferObject
*buf
)
282 _glthread_LOCK_MUTEX(bmMutex
);
283 tmp
= --buf
->refCount
;
284 _glthread_UNLOCK_MUTEX(bmMutex
);
287 buf
->pool
->destroy(buf
->pool
, buf
->private);
293 driBOData(struct _DriBufferObject
*buf
,
294 unsigned size
, const void *data
, unsigned flags
)
298 struct _DriBufferPool
*pool
;
300 assert(!buf
->userBuffer
); /* XXX just do a memcpy? */
302 _glthread_LOCK_MUTEX(buf
->mutex
);
305 _mesa_error(NULL
, GL_INVALID_OPERATION
,
306 "driBOData called on invalid buffer\n");
309 newBuffer
= !buf
->private || (pool
->size(pool
, buf
->private) < size
) ||
310 pool
->map(pool
, buf
->private, DRM_BO_FLAG_WRITE
,
311 DRM_BO_HINT_DONT_BLOCK
, &virtual);
315 pool
->destroy(pool
, buf
->private);
318 buf
->private = pool
->create(pool
, size
, flags
, DRM_BO_HINT_DONT_FENCE
,
322 BM_CKFATAL(pool
->map(pool
, buf
->private,
324 DRM_BO_HINT_DONT_BLOCK
, &virtual));
328 memcpy(virtual, data
, size
);
330 BM_CKFATAL(pool
->unmap(pool
, buf
->private));
331 _glthread_UNLOCK_MUTEX(buf
->mutex
);
335 driBOSubData(struct _DriBufferObject
*buf
,
336 unsigned long offset
, unsigned long size
, const void *data
)
340 assert(!buf
->userBuffer
); /* XXX just do a memcpy? */
342 _glthread_LOCK_MUTEX(buf
->mutex
);
344 BM_CKFATAL(buf
->pool
->map(buf
->pool
, buf
->private,
345 DRM_BO_FLAG_WRITE
, 0, &virtual));
346 memcpy((unsigned char *) virtual + offset
, data
, size
);
347 BM_CKFATAL(buf
->pool
->unmap(buf
->pool
, buf
->private));
349 _glthread_UNLOCK_MUTEX(buf
->mutex
);
353 driBOGetSubData(struct _DriBufferObject
*buf
,
354 unsigned long offset
, unsigned long size
, void *data
)
358 assert(!buf
->userBuffer
); /* XXX just do a memcpy? */
360 _glthread_LOCK_MUTEX(buf
->mutex
);
362 BM_CKFATAL(buf
->pool
->map(buf
->pool
, buf
->private,
363 DRM_BO_FLAG_READ
, 0, &virtual));
364 memcpy(data
, (unsigned char *) virtual + offset
, size
);
365 BM_CKFATAL(buf
->pool
->unmap(buf
->pool
, buf
->private));
367 _glthread_UNLOCK_MUTEX(buf
->mutex
);
371 driBOSetStatic(struct _DriBufferObject
*buf
,
372 unsigned long offset
,
373 unsigned long size
, void *virtual, unsigned flags
)
375 assert(!buf
->userBuffer
); /* XXX what to do? */
377 _glthread_LOCK_MUTEX(buf
->mutex
);
378 if (buf
->private != NULL
) {
379 _mesa_error(NULL
, GL_INVALID_OPERATION
,
380 "Invalid buffer for setStatic\n");
383 if (buf
->pool
->setstatic
== NULL
) {
384 _mesa_error(NULL
, GL_INVALID_OPERATION
,
385 "Invalid buffer pool for setStatic\n");
392 buf
->private = buf
->pool
->setstatic(buf
->pool
, offset
, size
,
395 _mesa_error(NULL
, GL_OUT_OF_MEMORY
,
396 "Invalid buffer pool for setStatic\n");
399 _glthread_UNLOCK_MUTEX(buf
->mutex
);
405 driGenBuffers(struct _DriBufferPool
*pool
,
408 struct _DriBufferObject
*buffers
[],
409 unsigned alignment
, unsigned flags
, unsigned hint
)
411 struct _DriBufferObject
*buf
;
414 flags
= (flags
) ? flags
: DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_MEM_VRAM
|
415 DRM_BO_FLAG_MEM_LOCAL
| DRM_BO_FLAG_READ
| DRM_BO_FLAG_WRITE
;
418 for (i
= 0; i
< n
; ++i
) {
419 buf
= (struct _DriBufferObject
*) calloc(1, sizeof(*buf
));
423 _glthread_INIT_MUTEX(buf
->mutex
);
424 _glthread_LOCK_MUTEX(buf
->mutex
);
425 _glthread_LOCK_MUTEX(bmMutex
);
427 _glthread_UNLOCK_MUTEX(bmMutex
);
431 buf
->alignment
= alignment
;
433 _glthread_UNLOCK_MUTEX(buf
->mutex
);
439 driGenUserBuffer(struct _DriBufferPool
*pool
,
441 struct _DriBufferObject
**buffers
,
442 void *ptr
, unsigned bytes
)
444 const unsigned alignment
= 1, flags
= 0, hint
= 0;
446 driGenBuffers(pool
, name
, 1, buffers
, alignment
, flags
, hint
);
448 (*buffers
)->userBuffer
= 1;
449 (*buffers
)->userData
= ptr
;
450 (*buffers
)->userSize
= bytes
;
455 driDeleteBuffers(unsigned n
, struct _DriBufferObject
*buffers
[])
459 for (i
= 0; i
< n
; ++i
) {
460 driBOUnReference(buffers
[i
]);
466 driInitBufMgr(int fd
)
473 driBOCreateList(int target
, drmBOList
* list
)
475 _glthread_LOCK_MUTEX(bmMutex
);
476 BM_CKFATAL(drmBOCreateList(target
, list
));
477 _glthread_UNLOCK_MUTEX(bmMutex
);
481 driBOResetList(drmBOList
* list
)
483 _glthread_LOCK_MUTEX(bmMutex
);
484 BM_CKFATAL(drmBOResetList(list
));
485 _glthread_UNLOCK_MUTEX(bmMutex
);
489 driBOAddListItem(drmBOList
* list
, struct _DriBufferObject
*buf
,
490 unsigned flags
, unsigned mask
)
494 _glthread_LOCK_MUTEX(buf
->mutex
);
495 _glthread_LOCK_MUTEX(bmMutex
);
496 BM_CKFATAL(drmAddValidateItem(list
, driBOKernel(buf
),
497 flags
, mask
, &newItem
));
498 _glthread_UNLOCK_MUTEX(bmMutex
);
501 * Tell userspace pools to validate the buffer. This should be a
502 * noop if the pool is already validated.
503 * FIXME: We should have a list for this as well.
506 if (buf
->pool
->validate
) {
507 BM_CKFATAL(buf
->pool
->validate(buf
->pool
, buf
->private));
510 _glthread_UNLOCK_MUTEX(buf
->mutex
);
514 driBOFence(struct _DriBufferObject
*buf
, struct _DriFenceObject
*fence
)
516 _glthread_LOCK_MUTEX(buf
->mutex
);
517 BM_CKFATAL(buf
->pool
->fence(buf
->pool
, buf
->private, fence
));
518 _glthread_UNLOCK_MUTEX(buf
->mutex
);
523 driBOValidateList(int fd
, drmBOList
* list
)
525 _glthread_LOCK_MUTEX(bmMutex
);
526 BM_CKFATAL(drmBOValidateList(fd
, list
));
527 _glthread_UNLOCK_MUTEX(bmMutex
);
531 driPoolTakeDown(struct _DriBufferPool
*pool
)
533 pool
->takeDown(pool
);