diff options
Diffstat (limited to 'src/mesa/drivers/dri/common')
-rw-r--r-- | src/mesa/drivers/dri/common/dri_bufmgr.c | 28 | ||||
-rw-r--r-- | src/mesa/drivers/dri/common/dri_bufmgr.h | 40 | ||||
-rw-r--r-- | src/mesa/drivers/dri/common/dri_bufmgr_fake.c | 136 | ||||
-rw-r--r-- | src/mesa/drivers/dri/common/dri_bufmgr_ttm.c | 469 |
4 files changed, 162 insertions, 511 deletions
diff --git a/src/mesa/drivers/dri/common/dri_bufmgr.c b/src/mesa/drivers/dri/common/dri_bufmgr.c index 407409bf06..83886480dd 100644 --- a/src/mesa/drivers/dri/common/dri_bufmgr.c +++ b/src/mesa/drivers/dri/common/dri_bufmgr.c @@ -88,18 +88,6 @@ dri_bo_unmap(dri_bo *buf) return buf->bufmgr->bo_unmap(buf); } -int -dri_bo_validate(dri_bo *buf, unsigned int flags) -{ - return buf->bufmgr->bo_validate(buf, flags); -} - -dri_fence * -dri_fence_validated(dri_bufmgr *bufmgr, const char *name, GLboolean flushed) -{ - return bufmgr->fence_validated(bufmgr, name, flushed); -} - void dri_fence_wait(dri_fence *fence) { @@ -150,3 +138,19 @@ dri_bufmgr_destroy(dri_bufmgr *bufmgr) { bufmgr->destroy(bufmgr); } + + +void dri_emit_reloc(dri_bo *batch_buf, GLuint flags, GLuint delta, GLuint offset, dri_bo *relocatee) +{ + batch_buf->bufmgr->emit_reloc(batch_buf, flags, delta, offset, relocatee); +} + +void *dri_process_relocs(dri_bo *batch_buf, GLuint *count) +{ + return batch_buf->bufmgr->process_relocs(batch_buf, count); +} + +void dri_post_submit(dri_bo *batch_buf, dri_fence **last_fence) +{ + batch_buf->bufmgr->post_submit(batch_buf, last_fence); +} diff --git a/src/mesa/drivers/dri/common/dri_bufmgr.h b/src/mesa/drivers/dri/common/dri_bufmgr.h index 3be342926f..7dbb558949 100644 --- a/src/mesa/drivers/dri/common/dri_bufmgr.h +++ b/src/mesa/drivers/dri/common/dri_bufmgr.h @@ -116,30 +116,6 @@ struct _dri_bufmgr { /** Reduces the refcount on the userspace mapping of the buffer object. */ int (*bo_unmap)(dri_bo *buf); - /** - * Makes the buffer accessible to the graphics chip. - * - * The resulting offset of the buffer within the graphics aperture is then - * available at buf->offset until the buffer is fenced. - * - * Flags should consist of the memory types that the buffer may be validated - * into and the read/write/exe flags appropriate to the use of the buffer. - */ - int (*bo_validate)(dri_bo *buf, unsigned int flags); - - /** - * Associates the current set of validated buffers with a fence. - * - * Once fenced, the buffer manager will allow the validated buffers to be - * evicted when the graphics device's execution has passed the fence - * command. - * - * The fence object will have flags for the sum of the read/write/exe flags - * of the validated buffers associated with it. - */ - dri_fence * (*fence_validated)(dri_bufmgr *bufmgr, const char *name, - GLboolean flushed); - /** Takes a reference on a fence object */ void (*fence_reference)(dri_fence *fence); @@ -158,6 +134,15 @@ struct _dri_bufmgr { * Tears down the buffer manager instance. */ void (*destroy)(dri_bufmgr *bufmgr); + + /** + * Add relocation + */ + void (*emit_reloc)(dri_bo *batch_buf, GLuint flags, GLuint delta, GLuint offset, dri_bo *relocatee); + + void *(*process_relocs)(dri_bo *batch_buf, GLuint *count); + + void (*post_submit)(dri_bo *batch_buf, dri_fence **fence); }; dri_bo *dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size, @@ -169,9 +154,6 @@ void dri_bo_reference(dri_bo *bo); void dri_bo_unreference(dri_bo *bo); int dri_bo_map(dri_bo *buf, GLboolean write_enable); int dri_bo_unmap(dri_bo *buf); -int dri_bo_validate(dri_bo *buf, unsigned int flags); -dri_fence *dri_fence_validated(dri_bufmgr *bufmgr, const char *name, - GLboolean flushed); void dri_fence_wait(dri_fence *fence); void dri_fence_reference(dri_fence *fence); void dri_fence_unreference(dri_fence *fence); @@ -195,4 +177,8 @@ void dri_bufmgr_destroy(dri_bufmgr *bufmgr); dri_bo *dri_ttm_bo_create_from_handle(dri_bufmgr *bufmgr, const char *name, unsigned int handle); +void dri_emit_reloc(dri_bo *batch_buf, GLuint flags, GLuint delta, GLuint offset, dri_bo *relocatee); +void *dri_process_relocs(dri_bo *batch_buf, uint32_t *count); +void dri_post_process_relocs(dri_bo *batch_buf); +void dri_post_submit(dri_bo *batch_buf, dri_fence **last_fence); #endif diff --git a/src/mesa/drivers/dri/common/dri_bufmgr_fake.c b/src/mesa/drivers/dri/common/dri_bufmgr_fake.c index e0d23a3647..bda45d921c 100644 --- a/src/mesa/drivers/dri/common/dri_bufmgr_fake.c +++ b/src/mesa/drivers/dri/common/dri_bufmgr_fake.c @@ -59,6 +59,16 @@ * processed through the command queue wouldn't need to care about * fences. */ +#define MAX_RELOCS 4096 + +struct fake_buffer_reloc +{ + dri_bo *buf; + GLuint offset; + GLuint delta; /* not needed? */ + GLuint validate_flags; +}; + struct block { struct block *next, *prev; struct mem_block *mem; /* BM_MEM_AGP */ @@ -107,6 +117,12 @@ typedef struct _bufmgr_fake { int (*fence_wait)(void *private, unsigned int fence_cookie); /** Driver-supplied argument to driver callbacks */ void *driver_priv; + + + /** fake relocation list */ + struct fake_buffer_reloc reloc[MAX_RELOCS]; + GLuint nr_relocs; + GLboolean performed_rendering; } dri_bufmgr_fake; typedef struct _dri_bo_fake { @@ -837,6 +853,120 @@ dri_fake_destroy(dri_bufmgr *bufmgr) free(bufmgr); } +static void +dri_fake_emit_reloc(dri_bo *batch_buf, GLuint flags, GLuint delta, GLuint offset, + dri_bo *relocatee) +{ + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)batch_buf->bufmgr; + struct fake_buffer_reloc *r = &bufmgr_fake->reloc[bufmgr_fake->nr_relocs++]; + + assert(bufmgr_fake->nr_relocs <= MAX_RELOCS); + + dri_bo_reference(relocatee); + + r->buf = relocatee; + r->offset = offset; + r->delta = delta; + r->validate_flags = flags; + + return; +} + + +static int +relocation_sort(const void *a_in, const void *b_in) { + const struct fake_buffer_reloc *a = a_in, *b = b_in; + + return (intptr_t)a->buf < (intptr_t)b->buf ? -1 : 1; +} + +static void * +dri_fake_process_relocs(dri_bo *batch_buf, GLuint *count_p) +{ + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)batch_buf->bufmgr; + GLuint i; + GLuint *ptr; + GLuint count = 0; + + assert(batch_buf->virtual != NULL); + ptr = batch_buf->virtual; + + bufmgr_fake->performed_rendering = GL_FALSE; + + /* Sort our relocation list in terms of referenced buffer pointer. + * This lets us uniquely validate the buffers with the sum of all the flags, + * while avoiding O(n^2) on number of relocations. + */ + qsort(bufmgr_fake->reloc, bufmgr_fake->nr_relocs, sizeof(bufmgr_fake->reloc[0]), + relocation_sort); + + /* Perform the necessary validations of buffers, and enter the relocations + * in the batchbuffer. + */ + for (i = 0; i < bufmgr_fake->nr_relocs; i++) { + struct fake_buffer_reloc *r = &bufmgr_fake->reloc[i]; + + if (r->validate_flags & DRM_BO_FLAG_WRITE) + bufmgr_fake->performed_rendering = GL_TRUE; + + /* If this is the first time we've seen this buffer in the relocation + * list, figure out our flags and validate it. + */ + if (i == 0 || bufmgr_fake->reloc[i - 1].buf != r->buf) { + uint32_t validate_flags; + int j, ret; + + /* Accumulate the flags we need for validating this buffer. */ + validate_flags = r->validate_flags; + for (j = i + 1; j < bufmgr_fake->nr_relocs; j++) { + if (bufmgr_fake->reloc[j].buf != r->buf) + break; + validate_flags |= bufmgr_fake->reloc[j].validate_flags; + } + + /* Validate. If we fail, fence to clear the unfenced list and bail + * out. + */ + ret = dri_fake_bo_validate(r->buf, validate_flags); + if (ret != 0) { + dri_fence *fo; + dri_bo_unmap(batch_buf); + fo = dri_fake_fence_validated(batch_buf->bufmgr, + "batchbuffer failure fence", GL_TRUE); + dri_fence_unreference(fo); + goto done; + } + count++; + } + ptr[r->offset / 4] = r->buf->offset + r->delta; + dri_bo_unreference(r->buf); + } + dri_bo_unmap(batch_buf); + + dri_fake_bo_validate(batch_buf, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE); + + *count_p = count; + bufmgr_fake->nr_relocs = 0; + done: + return NULL; +} + +static void +dri_fake_post_submit(dri_bo *batch_buf, dri_fence **last_fence) +{ + dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)batch_buf->bufmgr; + dri_fence *fo; + + fo = dri_fake_fence_validated(batch_buf->bufmgr, "Batch fence", GL_TRUE); + + if (bufmgr_fake->performed_rendering) { + dri_fence_unreference(*last_fence); + *last_fence = fo; + } else { + dri_fence_unreference(fo); + } +} + dri_bufmgr * dri_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, unsigned long size, @@ -867,13 +997,13 @@ dri_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, bufmgr_fake->bufmgr.bo_unreference = dri_fake_bo_unreference; bufmgr_fake->bufmgr.bo_map = dri_fake_bo_map; bufmgr_fake->bufmgr.bo_unmap = dri_fake_bo_unmap; - bufmgr_fake->bufmgr.bo_validate = dri_fake_bo_validate; - bufmgr_fake->bufmgr.fence_validated = dri_fake_fence_validated; bufmgr_fake->bufmgr.fence_wait = dri_fake_fence_wait; bufmgr_fake->bufmgr.fence_reference = dri_fake_fence_reference; bufmgr_fake->bufmgr.fence_unreference = dri_fake_fence_unreference; bufmgr_fake->bufmgr.destroy = dri_fake_destroy; - + bufmgr_fake->bufmgr.emit_reloc = dri_fake_emit_reloc; + bufmgr_fake->bufmgr.process_relocs = dri_fake_process_relocs; + bufmgr_fake->bufmgr.post_submit = dri_fake_post_submit; bufmgr_fake->fence_emit = fence_emit; bufmgr_fake->fence_wait = fence_wait; bufmgr_fake->driver_priv = driver_priv; diff --git a/src/mesa/drivers/dri/common/dri_bufmgr_ttm.c b/src/mesa/drivers/dri/common/dri_bufmgr_ttm.c deleted file mode 100644 index 235398eb87..0000000000 --- a/src/mesa/drivers/dri/common/dri_bufmgr_ttm.c +++ /dev/null @@ -1,469 +0,0 @@ -/************************************************************************** - * - * Copyright © 2007 Intel Corporation - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - * Keith Whitwell <keithw-at-tungstengraphics-dot-com> - * Eric Anholt <eric@anholt.net> - */ - -#include <xf86drm.h> -#include <stdlib.h> -#include <unistd.h> -#include "glthread.h" -#include "errno.h" -#include "mtypes.h" -#include "dri_bufmgr.h" -#include "string.h" -#include "imports.h" - -#define BUFMGR_DEBUG 0 - -typedef struct _dri_bufmgr_ttm { - dri_bufmgr bufmgr; - - int fd; - _glthread_Mutex mutex; - unsigned int fence_type; - unsigned int fence_type_flush; -} dri_bufmgr_ttm; - -typedef struct _dri_bo_ttm { - dri_bo bo; - - int refcount; /* Protected by bufmgr->mutex */ - drmBO drm_bo; - const char *name; - /** - * Note whether we are the owner of the buffer, to determine if we must - * drmBODestroy or drmBOUnreference to unreference the buffer. - */ - GLboolean owner; -} dri_bo_ttm; - -typedef struct _dri_fence_ttm -{ - dri_fence fence; - - int refcount; /* Protected by bufmgr->mutex */ - const char *name; - drmFence drm_fence; -} dri_fence_ttm; - -#if 0 -int -driFenceSignaled(DriFenceObject * fence, unsigned type) -{ - int signaled; - int ret; - - if (fence == NULL) - return GL_TRUE; - - _glthread_LOCK_MUTEX(fence->mutex); - ret = drmFenceSignaled(bufmgr_ttm->fd, &fence->fence, type, &signaled); - _glthread_UNLOCK_MUTEX(fence->mutex); - BM_CKFATAL(ret); - return signaled; -} -#endif - -static dri_bo * -dri_ttm_alloc(dri_bufmgr *bufmgr, const char *name, - unsigned long size, unsigned int alignment, - unsigned int location_mask) -{ - dri_bufmgr_ttm *ttm_bufmgr; - dri_bo_ttm *ttm_buf; - unsigned int pageSize = getpagesize(); - int ret; - unsigned int flags, hint; - - ttm_bufmgr = (dri_bufmgr_ttm *)bufmgr; - - ttm_buf = malloc(sizeof(*ttm_buf)); - if (!ttm_buf) - return NULL; - - /* The mask argument doesn't do anything for us that we want other than - * determine which pool (TTM or local) the buffer is allocated into, so just - * pass all of the allocation class flags. - */ - flags = location_mask | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | - DRM_BO_FLAG_EXE; - /* No hints we want to use. */ - hint = 0; - - ret = drmBOCreate(ttm_bufmgr->fd, 0, size, alignment / pageSize, - NULL, drm_bo_type_dc, - flags, hint, &ttm_buf->drm_bo); - if (ret != 0) { - free(ttm_buf); - return NULL; - } - ttm_buf->bo.size = ttm_buf->drm_bo.size; - ttm_buf->bo.offset = ttm_buf->drm_bo.offset; - ttm_buf->bo.virtual = NULL; - ttm_buf->bo.bufmgr = bufmgr; - ttm_buf->name = name; - ttm_buf->refcount = 1; - ttm_buf->owner = GL_TRUE; - -#if BUFMGR_DEBUG - fprintf(stderr, "bo_create: %p (%s)\n", &ttm_buf->bo, ttm_buf->name); -#endif - - return &ttm_buf->bo; -} - -/* Our TTM backend doesn't allow creation of static buffers, as that requires - * privelege for the non-fake case, and the lock in the fake case where we were - * working around the X Server not creating buffers and passing handles to us. - */ -static dri_bo * -dri_ttm_alloc_static(dri_bufmgr *bufmgr, const char *name, - unsigned long offset, unsigned long size, void *virtual, - unsigned int location_mask) -{ - return NULL; -} - -/** Returns a dri_bo wrapping the given buffer object handle. - * - * This can be used when one application needs to pass a buffer object - * to another. - */ -dri_bo * -dri_ttm_bo_create_from_handle(dri_bufmgr *bufmgr, const char *name, - unsigned int handle) -{ - dri_bufmgr_ttm *ttm_bufmgr; - dri_bo_ttm *ttm_buf; - int ret; - - ttm_bufmgr = (dri_bufmgr_ttm *)bufmgr; - - ttm_buf = malloc(sizeof(*ttm_buf)); - if (!ttm_buf) - return NULL; - - ret = drmBOReference(ttm_bufmgr->fd, handle, &ttm_buf->drm_bo); - if (ret != 0) { - free(ttm_buf); - return NULL; - } - ttm_buf->bo.size = ttm_buf->drm_bo.size; - ttm_buf->bo.offset = ttm_buf->drm_bo.offset; - ttm_buf->bo.virtual = NULL; - ttm_buf->bo.bufmgr = bufmgr; - ttm_buf->name = name; - ttm_buf->refcount = 1; - ttm_buf->owner = GL_FALSE; - -#if BUFMGR_DEBUG - fprintf(stderr, "bo_create_from_handle: %p (%s)\n", &ttm_buf->bo, - ttm_buf->name); -#endif - - return &ttm_buf->bo; -} - -static void -dri_ttm_bo_reference(dri_bo *buf) -{ - dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)buf->bufmgr; - dri_bo_ttm *ttm_buf = (dri_bo_ttm *)buf; - - _glthread_LOCK_MUTEX(bufmgr_ttm->mutex); - ttm_buf->refcount++; - _glthread_UNLOCK_MUTEX(bufmgr_ttm->mutex); -} - -static void -dri_ttm_bo_unreference(dri_bo *buf) -{ - dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)buf->bufmgr; - dri_bo_ttm *ttm_buf = (dri_bo_ttm *)buf; - - if (!buf) - return; - - _glthread_LOCK_MUTEX(bufmgr_ttm->mutex); - if (--ttm_buf->refcount == 0) { - int ret; - - /* XXX Having to use drmBODestroy as the opposite of drmBOCreate instead - * of simply unreferencing is madness, and leads to behaviors we may not - * want (making the buffer unsharable). - */ - if (ttm_buf->owner) - ret = drmBODestroy(bufmgr_ttm->fd, &ttm_buf->drm_bo); - else - ret = drmBOUnReference(bufmgr_ttm->fd, &ttm_buf->drm_bo); - if (ret != 0) { - fprintf(stderr, "drmBOUnReference failed (%s): %s\n", ttm_buf->name, - strerror(-ret)); - } -#if BUFMGR_DEBUG - fprintf(stderr, "bo_unreference final: %p (%s)\n", - &ttm_buf->bo, ttm_buf->name); -#endif - _glthread_UNLOCK_MUTEX(bufmgr_ttm->mutex); - free(buf); - return; - } - _glthread_UNLOCK_MUTEX(bufmgr_ttm->mutex); -} - -static int -dri_ttm_bo_map(dri_bo *buf, GLboolean write_enable) -{ - dri_bufmgr_ttm *bufmgr_ttm; - dri_bo_ttm *ttm_buf = (dri_bo_ttm *)buf; - unsigned int flags; - - bufmgr_ttm = (dri_bufmgr_ttm *)buf->bufmgr; - - flags = DRM_BO_FLAG_READ; - if (write_enable) - flags |= DRM_BO_FLAG_WRITE; - - assert(buf->virtual == NULL); - -#if BUFMGR_DEBUG - fprintf(stderr, "bo_map: %p (%s)\n", &ttm_buf->bo, ttm_buf->name); -#endif - - return drmBOMap(bufmgr_ttm->fd, &ttm_buf->drm_bo, flags, 0, &buf->virtual); -} - -static int -dri_ttm_bo_unmap(dri_bo *buf) -{ - dri_bufmgr_ttm *bufmgr_ttm; - dri_bo_ttm *ttm_buf = (dri_bo_ttm *)buf; - - if (buf == NULL) - return 0; - - bufmgr_ttm = (dri_bufmgr_ttm *)buf->bufmgr; - - assert(buf->virtual != NULL); - - buf->virtual = NULL; - -#if BUFMGR_DEBUG - fprintf(stderr, "bo_unmap: %p (%s)\n", &ttm_buf->bo, ttm_buf->name); -#endif - - return drmBOUnmap(bufmgr_ttm->fd, &ttm_buf->drm_bo); -} - -static int -dri_ttm_validate(dri_bo *buf, unsigned int flags) -{ - dri_bufmgr_ttm *bufmgr_ttm; - dri_bo_ttm *ttm_buf = (dri_bo_ttm *)buf; - unsigned int mask; - int err; - - /* XXX: Sanity-check whether we've already validated this one under - * different flags. See drmAddValidateItem(). - */ - - bufmgr_ttm = (dri_bufmgr_ttm *)buf->bufmgr; - - /* Calculate the appropriate mask to pass to the DRM. There appears to be - * be a direct relationship to flags, so it's unnecessary to have it passed - * in as an argument. - */ - mask = DRM_BO_MASK_MEM; - mask |= flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE); - - err = drmBOValidate(bufmgr_ttm->fd, &ttm_buf->drm_bo, 0, flags, mask, 0); - - if (err == 0) { - /* XXX: add to fence list for sanity checking */ - } else { - fprintf(stderr, "failed to validate buffer (%s): %s\n", - ttm_buf->name, strerror(-err)); - } - - buf->offset = ttm_buf->drm_bo.offset; - -#if BUFMGR_DEBUG - fprintf(stderr, "bo_validate: %p (%s)\n", &ttm_buf->bo, ttm_buf->name); -#endif - - return err; -} - -static dri_fence * -dri_ttm_fence_validated(dri_bufmgr *bufmgr, const char *name, - GLboolean flushed) -{ - dri_fence_ttm *fence_ttm = malloc(sizeof(*fence_ttm)); - dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)bufmgr; - int ret; - unsigned int type; - - if (!fence_ttm) - return NULL; - - if (flushed) - type = bufmgr_ttm->fence_type_flush; - else - type = bufmgr_ttm->fence_type; - - fence_ttm->refcount = 1; - fence_ttm->name = name; - fence_ttm->fence.bufmgr = bufmgr; - ret = drmFenceBuffers(bufmgr_ttm->fd, type, 0, &fence_ttm->drm_fence); - if (ret) { - fprintf(stderr, "failed to fence (%s): %s\n", name, strerror(-ret)); - free(fence_ttm); - return NULL; - } - -#if BUFMGR_DEBUG - fprintf(stderr, "fence_validated: %p (%s)\n", &fence_ttm->fence, - fence_ttm->name); -#endif - - return &fence_ttm->fence; -} - -static void -dri_ttm_fence_reference(dri_fence *fence) -{ - dri_fence_ttm *fence_ttm = (dri_fence_ttm *)fence; - dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)fence->bufmgr; - - _glthread_LOCK_MUTEX(bufmgr_ttm->mutex); - ++fence_ttm->refcount; - _glthread_UNLOCK_MUTEX(bufmgr_ttm->mutex); -} - -static void -dri_ttm_fence_unreference(dri_fence *fence) -{ - dri_fence_ttm *fence_ttm = (dri_fence_ttm *)fence; - dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)fence->bufmgr; - - if (!fence) - return; - - _glthread_LOCK_MUTEX(bufmgr_ttm->mutex); - if (--fence_ttm->refcount == 0) { - int ret; - - /* XXX Having to use drmFenceDestroy as the opposite of drmFenceBuffers - * instead of simply unreferencing is madness, and leads to behaviors we - * may not want (making the fence unsharable). This behavior by the DRM - * ioctls should be fixed, and drmFenceDestroy eliminated. - */ - ret = drmFenceDestroy(bufmgr_ttm->fd, &fence_ttm->drm_fence); - if (ret != 0) { - fprintf(stderr, "drmFenceDestroy failed (%s): %s\n", - fence_ttm->name, strerror(-ret)); - } - - _glthread_UNLOCK_MUTEX(bufmgr_ttm->mutex); - free(fence); - return; - } - _glthread_UNLOCK_MUTEX(bufmgr_ttm->mutex); -} - -static void -dri_ttm_fence_wait(dri_fence *fence) -{ - dri_fence_ttm *fence_ttm = (dri_fence_ttm *)fence; - dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)fence->bufmgr; - int ret; - - _glthread_LOCK_MUTEX(bufmgr_ttm->mutex); - ret = drmFenceWait(bufmgr_ttm->fd, 0, &fence_ttm->drm_fence, 0); - _glthread_UNLOCK_MUTEX(bufmgr_ttm->mutex); - if (ret != 0) { - _mesa_printf("%s:%d: Error %d waiting for fence %s.\n", - __FILE__, __LINE__, ret, fence_ttm->name); - abort(); - } - -#if BUFMGR_DEBUG - fprintf(stderr, "fence_wait: %p (%s)\n", &fence_ttm->fence, - fence_ttm->name); -#endif -} - -static void -dri_bufmgr_ttm_destroy(dri_bufmgr *bufmgr) -{ - dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)bufmgr; - - _glthread_DESTROY_MUTEX(bufmgr_ttm->mutex); - free(bufmgr); -} - -/** - * Initializes the TTM buffer manager, which uses the kernel to allocate, map, - * and manage map buffer objections. - * - * \param fd File descriptor of the opened DRM device. - * \param fence_type Driver-specific fence type used for fences with no flush. - * \param fence_type_flush Driver-specific fence type used for fences with a - * flush. - */ -dri_bufmgr * -dri_bufmgr_ttm_init(int fd, unsigned int fence_type, - unsigned int fence_type_flush) -{ - dri_bufmgr_ttm *bufmgr_ttm; - - bufmgr_ttm = malloc(sizeof(*bufmgr_ttm)); - bufmgr_ttm->fd = fd; - bufmgr_ttm->fence_type = fence_type; - bufmgr_ttm->fence_type_flush = fence_type_flush; - _glthread_INIT_MUTEX(bufmgr_ttm->mutex); - - bufmgr_ttm->bufmgr.bo_alloc = dri_ttm_alloc; - bufmgr_ttm->bufmgr.bo_alloc_static = dri_ttm_alloc_static; - bufmgr_ttm->bufmgr.bo_reference = dri_ttm_bo_reference; - bufmgr_ttm->bufmgr.bo_unreference = dri_ttm_bo_unreference; - bufmgr_ttm->bufmgr.bo_map = dri_ttm_bo_map; - bufmgr_ttm->bufmgr.bo_unmap = dri_ttm_bo_unmap; - bufmgr_ttm->bufmgr.bo_validate = dri_ttm_validate; - bufmgr_ttm->bufmgr.fence_validated = dri_ttm_fence_validated; - bufmgr_ttm->bufmgr.fence_reference = dri_ttm_fence_reference; - bufmgr_ttm->bufmgr.fence_unreference = dri_ttm_fence_unreference; - bufmgr_ttm->bufmgr.fence_wait = dri_ttm_fence_wait; - bufmgr_ttm->bufmgr.destroy = dri_bufmgr_ttm_destroy; - - return &bufmgr_ttm->bufmgr; -} |