summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/common')
-rw-r--r--src/mesa/drivers/dri/common/dri_bufmgr.c28
-rw-r--r--src/mesa/drivers/dri/common/dri_bufmgr.h40
-rw-r--r--src/mesa/drivers/dri/common/dri_bufmgr_fake.c136
-rw-r--r--src/mesa/drivers/dri/common/dri_bufmgr_ttm.c469
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;
-}