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>
33 * XXX NOTE: there are no intel dependencies in this file.
34 * Rename to dri_batchpool.c?
42 #include "pipe/p_compiler.h"
43 #include "pipe/p_thread.h"
45 #include "dri_bufpool.h"
46 #include "dri_bufmgr.h"
47 #include "intel_batchpool.h"
53 struct _BPool
*parent
;
54 struct _DriFenceObject
*fence
;
62 _glthread_Mutex mutex
;
63 unsigned long bufSize
;
68 unsigned checkDelayed
;
70 drmMMListHead delayed
;
79 createBPool(int fd
, unsigned long bufSize
, unsigned numBufs
, unsigned flags
,
80 unsigned checkDelayed
)
82 BPool
*p
= (BPool
*) malloc(sizeof(*p
));
89 p
->bufs
= (BBuf
*) malloc(numBufs
* sizeof(*p
->bufs
));
95 DRMINITLISTHEAD(&p
->free
);
96 DRMINITLISTHEAD(&p
->head
);
97 DRMINITLISTHEAD(&p
->delayed
);
100 p
->numFree
= numBufs
;
101 p
->bufSize
= bufSize
;
103 p
->checkDelayed
= checkDelayed
;
105 _glthread_INIT_MUTEX(p
->mutex
);
107 if (drmBOCreate(fd
, 0, numBufs
* bufSize
, 0, NULL
, drm_bo_type_dc
,
108 flags
, DRM_BO_HINT_DONT_FENCE
, &p
->kernelBO
)) {
113 if (drmBOMap(fd
, &p
->kernelBO
, DRM_BO_FLAG_READ
| DRM_BO_FLAG_WRITE
, 0,
115 drmBODestroy(fd
, &p
->kernelBO
);
122 * We unmap the buffer so that we can validate it later. Note that this is
123 * just a synchronizing operation. The buffer will have a virtual mapping
124 * until it is destroyed.
127 drmBOUnmap(fd
, &p
->kernelBO
);
130 for (i
= 0; i
< numBufs
; ++i
) {
133 buf
->start
= i
* bufSize
;
136 DRMLISTADDTAIL(&buf
->head
, &p
->free
);
145 pool_checkFree(BPool
* p
, int wait
)
147 drmMMListHead
*list
, *prev
;
152 list
= p
->delayed
.next
;
154 if (p
->numDelayed
> 3) {
155 for (i
= 0; i
< p
->numDelayed
; i
+= 3) {
161 for (; list
!= &p
->delayed
; list
= prev
, prev
= list
->prev
) {
163 buf
= DRMLISTENTRY(BBuf
, list
, head
);
167 driFenceFinish(buf
->fence
, DRM_FENCE_TYPE_EXE
, 1);
171 signaled
= driFenceSignaled(buf
->fence
, DRM_FENCE_TYPE_EXE
);
178 driFenceUnReference(buf
->fence
);
182 DRMLISTADD(list
, &p
->free
);
188 pool_create(struct _DriBufferPool
*pool
,
189 unsigned long size
, unsigned flags
, unsigned hint
,
192 BPool
*p
= (BPool
*) pool
->data
;
196 if (alignment
&& (alignment
!= 4096))
199 _glthread_LOCK_MUTEX(p
->mutex
);
202 pool_checkFree(p
, TRUE
);
204 if (p
->numFree
== 0) {
205 fprintf(stderr
, "Out of fixed size buffer objects\n");
211 if (item
== &p
->free
) {
212 fprintf(stderr
, "Fixed size buffer pool corruption\n");
218 _glthread_UNLOCK_MUTEX(p
->mutex
);
219 return (void *) DRMLISTENTRY(BBuf
, item
, head
);
224 pool_destroy(struct _DriBufferPool
*pool
, void *private)
226 BBuf
*buf
= (BBuf
*) private;
227 BPool
*p
= buf
->parent
;
229 _glthread_LOCK_MUTEX(p
->mutex
);
232 DRMLISTADDTAIL(&buf
->head
, &p
->delayed
);
237 DRMLISTADD(&buf
->head
, &p
->free
);
241 if ((p
->numDelayed
% p
->checkDelayed
) == 0)
242 pool_checkFree(p
, 0);
244 _glthread_UNLOCK_MUTEX(p
->mutex
);
250 pool_map(struct _DriBufferPool
*pool
, void *private, unsigned flags
,
251 int hint
, void **virtual)
254 BBuf
*buf
= (BBuf
*) private;
255 BPool
*p
= buf
->parent
;
257 _glthread_LOCK_MUTEX(p
->mutex
);
260 * Currently Mesa doesn't have any condition variables to resolve this
261 * cleanly in a multithreading environment.
262 * We bail out instead.
266 fprintf(stderr
, "Trying to map already mapped buffer object\n");
271 if (buf
->unfenced
&& !(hint
& DRM_BO_HINT_ALLOW_UNFENCED_MAP
)) {
272 fprintf(stderr
, "Trying to map an unfenced buffer object 0x%08x"
273 " 0x%08x %d\n", hint
, flags
, buf
->start
);
280 _glthread_UNLOCK_MUTEX(p
->mutex
);
285 *virtual = (unsigned char *) p
->virtual + buf
->start
;
286 _glthread_UNLOCK_MUTEX(p
->mutex
);
291 pool_waitIdle(struct _DriBufferPool
*pool
, void *private, int lazy
)
293 BBuf
*buf
= (BBuf
*) private;
294 driFenceFinish(buf
->fence
, 0x0, lazy
);
299 pool_unmap(struct _DriBufferPool
*pool
, void *private)
301 BBuf
*buf
= (BBuf
*) private;
308 pool_offset(struct _DriBufferPool
*pool
, void *private)
310 BBuf
*buf
= (BBuf
*) private;
311 BPool
*p
= buf
->parent
;
313 return p
->kernelBO
.offset
+ buf
->start
;
317 pool_flags(struct _DriBufferPool
*pool
, void *private)
319 BPool
*p
= (BPool
*) pool
->data
;
321 return p
->kernelBO
.flags
;
325 pool_size(struct _DriBufferPool
*pool
, void *private)
327 BPool
*p
= (BPool
*) pool
->data
;
334 pool_fence(struct _DriBufferPool
*pool
, void *private,
335 struct _DriFenceObject
*fence
)
337 BBuf
*buf
= (BBuf
*) private;
338 BPool
*p
= buf
->parent
;
340 _glthread_LOCK_MUTEX(p
->mutex
);
342 driFenceUnReference(buf
->fence
);
346 driFenceReference(buf
->fence
);
347 _glthread_UNLOCK_MUTEX(p
->mutex
);
353 pool_kernel(struct _DriBufferPool
*pool
, void *private)
355 BBuf
*buf
= (BBuf
*) private;
356 BPool
*p
= buf
->parent
;
362 pool_validate(struct _DriBufferPool
*pool
, void *private)
364 BBuf
*buf
= (BBuf
*) private;
365 BPool
*p
= buf
->parent
;
366 _glthread_LOCK_MUTEX(p
->mutex
);
367 buf
->unfenced
= TRUE
;
368 _glthread_UNLOCK_MUTEX(p
->mutex
);
373 pool_takedown(struct _DriBufferPool
*pool
)
375 BPool
*p
= (BPool
*) pool
->data
;
378 * Wait on outstanding fences.
381 _glthread_LOCK_MUTEX(p
->mutex
);
382 while ((p
->numFree
< p
->numTot
) && p
->numDelayed
) {
383 _glthread_UNLOCK_MUTEX(p
->mutex
);
385 pool_checkFree(p
, TRUE
);
386 _glthread_LOCK_MUTEX(p
->mutex
);
389 drmBODestroy(pool
->fd
, &p
->kernelBO
);
391 _glthread_UNLOCK_MUTEX(p
->mutex
);
397 struct _DriBufferPool
*
398 driBatchPoolInit(int fd
, unsigned flags
,
399 unsigned long bufSize
,
400 unsigned numBufs
, unsigned checkDelayed
)
402 struct _DriBufferPool
*pool
;
404 pool
= (struct _DriBufferPool
*) malloc(sizeof(*pool
));
408 pool
->data
= createBPool(fd
, bufSize
, numBufs
, flags
, checkDelayed
);
413 pool
->map
= &pool_map
;
414 pool
->unmap
= &pool_unmap
;
415 pool
->destroy
= &pool_destroy
;
416 pool
->offset
= &pool_offset
;
417 pool
->flags
= &pool_flags
;
418 pool
->size
= &pool_size
;
419 pool
->create
= &pool_create
;
420 pool
->fence
= &pool_fence
;
421 pool
->kernel
= &pool_kernel
;
422 pool
->validate
= &pool_validate
;
423 pool
->waitIdle
= &pool_waitIdle
;
424 pool
->setstatic
= NULL
;
425 pool
->takeDown
= &pool_takedown
;