1 /**************************************************************************
3 * Copyright © 2007 Intel Corporation
4 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 * The above copyright notice and this permission notice (including the
24 * next paragraph) shall be included in all copies or substantial portions
28 **************************************************************************/
30 * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
31 * Keith Whitwell <keithw-at-tungstengraphics-dot-com>
32 * Eric Anholt <eric@anholt.net>
41 #include "dri_bufmgr.h"
45 typedef struct _dri_bufmgr_ttm
{
49 _glthread_Mutex mutex
;
50 unsigned int fence_type
;
51 unsigned int fence_type_flush
;
54 typedef struct _dri_bo_ttm
{
57 int refcount
; /* Protected by bufmgr->mutex */
61 typedef struct _dri_fence_ttm
65 int refcount
; /* Protected by bufmgr->mutex */
66 /** Fence type from when the fence was created, used for later waits */
74 driFenceSignaled(DriFenceObject
* fence
, unsigned type
)
82 _glthread_LOCK_MUTEX(fence
->mutex
);
83 ret
= drmFenceSignaled(bufmgr_ttm
->fd
, &fence
->fence
, type
, &signaled
);
84 _glthread_UNLOCK_MUTEX(fence
->mutex
);
91 dri_ttm_alloc(dri_bufmgr
*bufmgr
, const char *name
,
92 unsigned long size
, unsigned int alignment
, unsigned int flags
,
95 dri_bufmgr_ttm
*ttm_bufmgr
;
97 unsigned int pageSize
= getpagesize();
100 ttm_bufmgr
= (dri_bufmgr_ttm
*)bufmgr
;
102 ttm_buf
= malloc(sizeof(*ttm_buf
));
106 ret
= drmBOCreate(ttm_bufmgr
->fd
, 0, size
, alignment
/ pageSize
,
107 NULL
, drm_bo_type_dc
,
108 flags
, hint
, &ttm_buf
->drm_bo
);
113 ttm_buf
->bo
.size
= ttm_buf
->drm_bo
.size
;
114 ttm_buf
->bo
.offset
= ttm_buf
->drm_bo
.offset
;
115 ttm_buf
->bo
.virtual = NULL
;
116 ttm_buf
->bo
.bufmgr
= bufmgr
;
117 ttm_buf
->refcount
= 1;
123 dri_ttm_alloc_static(dri_bufmgr
*bufmgr
, const char *name
,
124 unsigned long offset
, unsigned long size
, void *virtual,
125 unsigned int flags
, unsigned int hint
)
127 dri_bufmgr_ttm
*ttm_bufmgr
;
131 ttm_bufmgr
= (dri_bufmgr_ttm
*)bufmgr
;
133 ttm_buf
= malloc(sizeof(*ttm_buf
));
137 ret
= drmBOCreate(ttm_bufmgr
->fd
, offset
, size
, 0,
138 NULL
, drm_bo_type_fake
,
139 flags
, 0, &ttm_buf
->drm_bo
);
144 ttm_buf
->bo
.size
= ttm_buf
->drm_bo
.size
;
145 ttm_buf
->bo
.offset
= ttm_buf
->drm_bo
.offset
;
146 ttm_buf
->bo
.virtual = virtual;
147 ttm_buf
->bo
.bufmgr
= bufmgr
;
148 ttm_buf
->refcount
= 1;
154 dri_ttm_bo_reference(dri_bo
*buf
)
156 dri_bufmgr_ttm
*bufmgr_ttm
= (dri_bufmgr_ttm
*)buf
->bufmgr
;
157 dri_bo_ttm
*ttm_buf
= (dri_bo_ttm
*)buf
;
159 _glthread_LOCK_MUTEX(bufmgr_ttm
->mutex
);
161 _glthread_UNLOCK_MUTEX(bufmgr_ttm
->mutex
);
165 dri_ttm_bo_unreference(dri_bo
*buf
)
167 dri_bufmgr_ttm
*bufmgr_ttm
= (dri_bufmgr_ttm
*)buf
->bufmgr
;
168 dri_bo_ttm
*ttm_buf
= (dri_bo_ttm
*)buf
;
173 _glthread_LOCK_MUTEX(bufmgr_ttm
->mutex
);
174 if (--ttm_buf
->refcount
== 0) {
175 drmBOUnReference(bufmgr_ttm
->fd
, &ttm_buf
->drm_bo
);
176 _glthread_UNLOCK_MUTEX(bufmgr_ttm
->mutex
);
180 _glthread_UNLOCK_MUTEX(bufmgr_ttm
->mutex
);
184 dri_ttm_bo_map(dri_bo
*buf
, GLboolean write_enable
)
186 dri_bufmgr_ttm
*bufmgr_ttm
;
187 dri_bo_ttm
*ttm_buf
= (dri_bo_ttm
*)buf
;
190 bufmgr_ttm
= (dri_bufmgr_ttm
*)buf
->bufmgr
;
192 flags
= DRM_BO_FLAG_READ
;
194 flags
|= DRM_BO_FLAG_WRITE
;
196 return drmBOMap(bufmgr_ttm
->fd
, &ttm_buf
->drm_bo
, flags
, 0, &buf
->virtual);
200 dri_ttm_bo_unmap(dri_bo
*buf
)
202 dri_bufmgr_ttm
*bufmgr_ttm
;
203 dri_bo_ttm
*ttm_buf
= (dri_bo_ttm
*)buf
;
208 bufmgr_ttm
= (dri_bufmgr_ttm
*)buf
->bufmgr
;
212 return drmBOUnmap(bufmgr_ttm
->fd
, &ttm_buf
->drm_bo
);
216 dri_ttm_validate(dri_bo
*buf
, unsigned int flags
)
218 dri_bufmgr_ttm
*bufmgr_ttm
;
219 dri_bo_ttm
*ttm_buf
= (dri_bo_ttm
*)buf
;
223 /* XXX: Sanity-check whether we've already validated this one under
224 * different flags. See drmAddValidateItem().
227 bufmgr_ttm
= (dri_bufmgr_ttm
*)buf
->bufmgr
;
229 /* Calculate the appropriate mask to pass to the DRM. There appears to be
230 * be a direct relationship to flags, so it's unnecessary to have it passed
233 mask
= DRM_BO_MASK_MEM
;
234 mask
|= flags
& (DRM_BO_FLAG_READ
| DRM_BO_FLAG_WRITE
| DRM_BO_FLAG_EXE
);
236 err
= drmBOValidate(bufmgr_ttm
->fd
, &ttm_buf
->drm_bo
, flags
, mask
, 0);
239 /* XXX: add to fence list for sanity checking */
246 dri_ttm_fence_validated(dri_bufmgr
*bufmgr
, const char *name
,
249 dri_fence_ttm
*fence_ttm
= malloc(sizeof(*fence_ttm
));
250 dri_bufmgr_ttm
*bufmgr_ttm
= (dri_bufmgr_ttm
*)bufmgr
;
258 type
= bufmgr_ttm
->fence_type_flush
;
260 type
= bufmgr_ttm
->fence_type
;
262 fence_ttm
->refcount
= 1;
263 fence_ttm
->name
= name
;
264 fence_ttm
->type
= type
;
265 fence_ttm
->fence
.bufmgr
= bufmgr
;
266 ret
= drmFenceBuffers(bufmgr_ttm
->fd
, type
, &fence_ttm
->drm_fence
);
271 return &fence_ttm
->fence
;
275 dri_ttm_fence_reference(dri_fence
*fence
)
277 dri_fence_ttm
*fence_ttm
= (dri_fence_ttm
*)fence
;
278 dri_bufmgr_ttm
*bufmgr_ttm
= (dri_bufmgr_ttm
*)fence
->bufmgr
;
280 _glthread_LOCK_MUTEX(bufmgr_ttm
->mutex
);
281 ++fence_ttm
->refcount
;
282 _glthread_UNLOCK_MUTEX(bufmgr_ttm
->mutex
);
286 dri_ttm_fence_unreference(dri_fence
*fence
)
288 dri_fence_ttm
*fence_ttm
= (dri_fence_ttm
*)fence
;
289 dri_bufmgr_ttm
*bufmgr_ttm
= (dri_bufmgr_ttm
*)fence
->bufmgr
;
294 _glthread_LOCK_MUTEX(bufmgr_ttm
->mutex
);
295 if (--fence_ttm
->refcount
== 0) {
296 drmFenceDestroy(bufmgr_ttm
->fd
, &fence_ttm
->drm_fence
);
297 _glthread_UNLOCK_MUTEX(bufmgr_ttm
->mutex
);
301 _glthread_UNLOCK_MUTEX(bufmgr_ttm
->mutex
);
305 dri_ttm_fence_wait(dri_fence
*fence
)
307 dri_fence_ttm
*fence_ttm
= (dri_fence_ttm
*)fence
;
308 dri_bufmgr_ttm
*bufmgr_ttm
= (dri_bufmgr_ttm
*)fence
->bufmgr
;
311 _glthread_LOCK_MUTEX(bufmgr_ttm
->mutex
);
312 ret
= drmFenceWait(bufmgr_ttm
->fd
, 0, &fence_ttm
->drm_fence
,
314 _glthread_UNLOCK_MUTEX(bufmgr_ttm
->mutex
);
316 _mesa_printf("%s:%d: Error %d waiting for fence %s.\n",
317 __FILE__
, __LINE__
, fence_ttm
->name
);
323 * Initializes the TTM buffer manager, which uses the kernel to allocate, map,
324 * and manage map buffer objections.
326 * \param fd File descriptor of the opened DRM device.
327 * \param fence_type Driver-specific fence type used for fences with no flush.
328 * \param fence_type_flush Driver-specific fence type used for fences with a
332 dri_bufmgr_ttm_init(int fd
, unsigned int fence_type
,
333 unsigned int fence_type_flush
)
335 dri_bufmgr_ttm
*bufmgr_ttm
;
337 bufmgr_ttm
= malloc(sizeof(*bufmgr_ttm
));
339 bufmgr_ttm
->fence_type
= fence_type
;
340 bufmgr_ttm
->fence_type_flush
= fence_type_flush
;
341 _glthread_INIT_MUTEX(bufmgr_ttm
->mutex
);
343 bufmgr_ttm
->bufmgr
.bo_alloc
= dri_ttm_alloc
;
344 bufmgr_ttm
->bufmgr
.bo_alloc_static
= dri_ttm_alloc_static
;
345 bufmgr_ttm
->bufmgr
.bo_reference
= dri_ttm_bo_reference
;
346 bufmgr_ttm
->bufmgr
.bo_unreference
= dri_ttm_bo_unreference
;
347 bufmgr_ttm
->bufmgr
.bo_map
= dri_ttm_bo_map
;
348 bufmgr_ttm
->bufmgr
.bo_unmap
= dri_ttm_bo_unmap
;
349 bufmgr_ttm
->bufmgr
.bo_validate
= dri_ttm_validate
;
350 bufmgr_ttm
->bufmgr
.fence_validated
= dri_ttm_fence_validated
;
351 bufmgr_ttm
->bufmgr
.fence_reference
= dri_ttm_fence_reference
;
352 bufmgr_ttm
->bufmgr
.fence_unreference
= dri_ttm_fence_unreference
;
353 bufmgr_ttm
->bufmgr
.fence_wait
= dri_ttm_fence_wait
;
355 return &bufmgr_ttm
->bufmgr
;