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>
37 #include "dri_bufpool.h"
38 #include "dri_bufmgr.h"
39 #include "intel_screen.h"
44 struct _BPool
*parent
;
45 struct _DriFenceObject
*fence
;
53 _glthread_Mutex mutex
;
54 unsigned long bufSize
;
59 unsigned checkDelayed
;
61 drmMMListHead delayed
;
70 createBPool(int fd
, unsigned long bufSize
, unsigned numBufs
, unsigned flags
,
71 unsigned checkDelayed
)
73 BPool
*p
= (BPool
*) malloc(sizeof(*p
));
80 p
->bufs
= (BBuf
*) malloc(numBufs
* sizeof(*p
->bufs
));
86 DRMINITLISTHEAD(&p
->free
);
87 DRMINITLISTHEAD(&p
->head
);
88 DRMINITLISTHEAD(&p
->delayed
);
94 p
->checkDelayed
= checkDelayed
;
96 _glthread_INIT_MUTEX(p
->mutex
);
98 if (drmBOCreate(fd
, 0, numBufs
* bufSize
, 0, NULL
, drm_bo_type_dc
,
99 flags
, 0, &p
->kernelBO
)) {
104 if (drmBOMap(fd
, &p
->kernelBO
, DRM_BO_FLAG_READ
| DRM_BO_FLAG_WRITE
, 0,
106 drmBODestroy(fd
, &p
->kernelBO
);
113 * We unmap the buffer so that we can validate it later. Note that this is
114 * just a synchronizing operation. The buffer will have a virtual mapping
115 * until it is destroyed.
118 drmBOUnmap(fd
, &p
->kernelBO
);
121 for (i
= 0; i
< numBufs
; ++i
) {
124 buf
->start
= i
* bufSize
;
127 DRMLISTADDTAIL(&buf
->head
, &p
->free
);
136 pool_checkFree(BPool
* p
, int wait
)
138 drmMMListHead
*list
, *prev
;
143 list
= p
->delayed
.next
;
145 if (p
->numDelayed
> 3) {
146 for (i
= 0; i
< p
->numDelayed
; i
+= 3) {
152 for (; list
!= &p
->delayed
; list
= prev
, prev
= list
->prev
) {
154 buf
= DRMLISTENTRY(BBuf
, list
, head
);
158 driFenceFinish(buf
->fence
, DRM_FENCE_TYPE_EXE
, 1);
162 signaled
= driFenceSignaled(buf
->fence
, DRM_FENCE_TYPE_EXE
);
169 driFenceUnReference(buf
->fence
);
173 DRMLISTADD(list
, &p
->free
);
179 pool_create(struct _DriBufferPool
*pool
,
180 unsigned long size
, unsigned flags
, unsigned hint
,
183 BPool
*p
= (BPool
*) pool
->data
;
187 if (alignment
&& (alignment
!= 4096))
190 _glthread_LOCK_MUTEX(p
->mutex
);
193 pool_checkFree(p
, GL_TRUE
);
195 if (p
->numFree
== 0) {
196 fprintf(stderr
, "Out of fixed size buffer objects\n");
202 if (item
== &p
->free
) {
203 fprintf(stderr
, "Fixed size buffer pool corruption\n");
209 _glthread_UNLOCK_MUTEX(p
->mutex
);
210 return (void *) DRMLISTENTRY(BBuf
, item
, head
);
215 pool_destroy(struct _DriBufferPool
*pool
, void *private)
217 BBuf
*buf
= (BBuf
*) private;
218 BPool
*p
= buf
->parent
;
220 _glthread_LOCK_MUTEX(p
->mutex
);
223 DRMLISTADDTAIL(&buf
->head
, &p
->delayed
);
228 DRMLISTADD(&buf
->head
, &p
->free
);
232 if ((p
->numDelayed
% p
->checkDelayed
) == 0)
233 pool_checkFree(p
, 0);
235 _glthread_UNLOCK_MUTEX(p
->mutex
);
241 pool_map(struct _DriBufferPool
*pool
, void *private, unsigned flags
,
242 int hint
, void **virtual)
245 BBuf
*buf
= (BBuf
*) private;
246 BPool
*p
= buf
->parent
;
248 _glthread_LOCK_MUTEX(p
->mutex
);
251 * Currently Mesa doesn't have any condition variables to resolve this
252 * cleanly in a multithreading environment.
253 * We bail out instead.
257 fprintf(stderr
, "Trying to map already mapped buffer object\n");
262 if (buf
->unfenced
&& !(hint
& DRM_BO_HINT_ALLOW_UNFENCED_MAP
)) {
263 fprintf(stderr
, "Trying to map an unfenced buffer object 0x%08x"
264 " 0x%08x %d\n", hint
, flags
, buf
->start
);
271 _glthread_UNLOCK_MUTEX(p
->mutex
);
275 buf
->mapped
= GL_TRUE
;
276 *virtual = (unsigned char *) p
->virtual + buf
->start
;
277 _glthread_UNLOCK_MUTEX(p
->mutex
);
282 pool_waitIdle(struct _DriBufferPool
*pool
, void *private, int lazy
)
284 BBuf
*buf
= (BBuf
*) private;
285 driFenceFinish(buf
->fence
, 0, lazy
);
290 pool_unmap(struct _DriBufferPool
*pool
, void *private)
292 BBuf
*buf
= (BBuf
*) private;
299 pool_offset(struct _DriBufferPool
*pool
, void *private)
301 BBuf
*buf
= (BBuf
*) private;
302 BPool
*p
= buf
->parent
;
304 return p
->kernelBO
.offset
+ buf
->start
;
308 pool_flags(struct _DriBufferPool
*pool
, void *private)
310 BPool
*p
= (BPool
*) pool
->data
;
312 return p
->kernelBO
.flags
;
316 pool_size(struct _DriBufferPool
*pool
, void *private)
318 BPool
*p
= (BPool
*) pool
->data
;
325 pool_fence(struct _DriBufferPool
*pool
, void *private,
326 struct _DriFenceObject
*fence
)
328 BBuf
*buf
= (BBuf
*) private;
329 BPool
*p
= buf
->parent
;
331 _glthread_LOCK_MUTEX(p
->mutex
);
333 driFenceUnReference(buf
->fence
);
337 driFenceReference(buf
->fence
);
338 _glthread_UNLOCK_MUTEX(p
->mutex
);
344 pool_kernel(struct _DriBufferPool
*pool
, void *private)
346 BBuf
*buf
= (BBuf
*) private;
347 BPool
*p
= buf
->parent
;
353 pool_validate(struct _DriBufferPool
*pool
, void *private)
355 BBuf
*buf
= (BBuf
*) private;
356 BPool
*p
= buf
->parent
;
357 _glthread_LOCK_MUTEX(p
->mutex
);
358 buf
->unfenced
= GL_TRUE
;
359 _glthread_UNLOCK_MUTEX(p
->mutex
);
364 pool_takedown(struct _DriBufferPool
*pool
)
366 BPool
*p
= (BPool
*) pool
->data
;
369 * Wait on outstanding fences.
372 _glthread_LOCK_MUTEX(p
->mutex
);
373 while ((p
->numFree
< p
->numTot
) && p
->numDelayed
) {
374 _glthread_UNLOCK_MUTEX(p
->mutex
);
376 pool_checkFree(p
, GL_TRUE
);
377 _glthread_LOCK_MUTEX(p
->mutex
);
380 drmBODestroy(pool
->fd
, &p
->kernelBO
);
382 _glthread_UNLOCK_MUTEX(p
->mutex
);
388 struct _DriBufferPool
*
389 driBatchPoolInit(int fd
, unsigned flags
,
390 unsigned long bufSize
,
391 unsigned numBufs
, unsigned checkDelayed
)
393 struct _DriBufferPool
*pool
;
395 pool
= (struct _DriBufferPool
*) malloc(sizeof(*pool
));
399 pool
->data
= createBPool(fd
, bufSize
, numBufs
, flags
, checkDelayed
);
404 pool
->map
= &pool_map
;
405 pool
->unmap
= &pool_unmap
;
406 pool
->destroy
= &pool_destroy
;
407 pool
->offset
= &pool_offset
;
408 pool
->flags
= &pool_flags
;
409 pool
->size
= &pool_size
;
410 pool
->create
= &pool_create
;
411 pool
->fence
= &pool_fence
;
412 pool
->kernel
= &pool_kernel
;
413 pool
->validate
= &pool_validate
;
414 pool
->waitIdle
= &pool_waitIdle
;
415 pool
->setstatic
= NULL
;
416 pool
->takeDown
= &pool_takedown
;