summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/drivers/dri/Makefile.template3
-rw-r--r--src/mesa/drivers/dri/common/dri_bufmgr.c519
-rw-r--r--src/mesa/drivers/dri/common/dri_bufmgr.h205
-rw-r--r--src/mesa/drivers/dri/common/dri_bufmgr_fake.c882
-rw-r--r--src/mesa/drivers/dri/common/dri_bufmgr_ttm.c469
-rw-r--r--src/mesa/drivers/dri/common/dri_bufpool.h86
-rw-r--r--src/mesa/drivers/dri/common/dri_drmpool.c228
-rw-r--r--src/mesa/drivers/dri/i915tex/Makefile5
-rw-r--r--src/mesa/drivers/dri/i915tex/i830_context.h6
-rw-r--r--src/mesa/drivers/dri/i915tex/i830_metaops.c2
-rw-r--r--src/mesa/drivers/dri/i915tex/i830_texstate.c8
-rw-r--r--src/mesa/drivers/dri/i915tex/i830_vtbl.c5
-rw-r--r--src/mesa/drivers/dri/i915tex/i915_context.h6
-rw-r--r--src/mesa/drivers/dri/i915tex/i915_metaops.c2
-rw-r--r--src/mesa/drivers/dri/i915tex/i915_texstate.c8
-rw-r--r--src/mesa/drivers/dri/i915tex/i915_vtbl.c5
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_batchbuffer.c226
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_batchbuffer.h22
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_batchpool.c418
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_blit.c35
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_blit.h6
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_buffer_objects.c71
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_buffer_objects.h8
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_context.c46
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_context.h23
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_decode.c2
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_ioctl.c19
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_ioctl.h4
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_pixel_draw.c14
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_pixel_read.c18
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_regions.c106
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_regions.h10
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_screen.c240
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_screen.h23
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_tex_image.c9
-rw-r--r--src/mesa/drivers/dri/i915tex/server/i830_common.h10
-rw-r--r--src/mesa/drivers/dri/i965/intel_context.c6
37 files changed, 2069 insertions, 1686 deletions
diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template
index 3576d0bac8f..770b19e1618 100644
--- a/src/mesa/drivers/dri/Makefile.template
+++ b/src/mesa/drivers/dri/Makefile.template
@@ -13,7 +13,8 @@ COMMON_SOURCES = \
COMMON_BM_SOURCES = \
../common/dri_bufmgr.c \
- ../common/dri_drmpool.c
+ ../common/dri_bufmgr_ttm.c \
+ ../common/dri_bufmgr_fake.c
ifeq ($(WINDOW_SYSTEM),dri)
diff --git a/src/mesa/drivers/dri/common/dri_bufmgr.c b/src/mesa/drivers/dri/common/dri_bufmgr.c
index eaa4fb09c70..407409bf06d 100644
--- a/src/mesa/drivers/dri/common/dri_bufmgr.c
+++ b/src/mesa/drivers/dri/common/dri_bufmgr.c
@@ -1,499 +1,152 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
- * All Rights Reserved.
- *
+/*
+ * Copyright © 2007 Intel Corporation
+ *
* 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:
- *
+ * 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, sublicense,
+ * 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 above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
* 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.
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors:
+ * Eric Anholt <[email protected]>
*
- * 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>
*/
-#include <xf86drm.h>
-#include <stdlib.h>
-#include "glthread.h"
-#include "errno.h"
+#include "mtypes.h"
#include "dri_bufmgr.h"
-#include "string.h"
-#include "imports.h"
-#include "dri_bufpool.h"
-_glthread_DECLARE_STATIC_MUTEX(bmMutex);
-
-/*
- * TODO: Introduce fence pools in the same way as
- * buffer object pools.
+/** @file dri_bufmgr.c
+ *
+ * Convenience functions for buffer management methods.
*/
-
-
-typedef struct _DriFenceObject
-{
- int fd;
- _glthread_Mutex mutex;
- int refCount;
- const char *name;
- drmFence fence;
-} DriFenceObject;
-
-typedef struct _DriBufferObject
-{
- DriBufferPool *pool;
- _glthread_Mutex mutex;
- int refCount;
- const char *name;
- unsigned flags;
- unsigned hint;
- unsigned alignment;
- void *private;
-} DriBufferObject;
-
-
-void
-bmError(int val, const char *file, const char *function, int line)
-{
- _mesa_printf("Fatal video memory manager error \"%s\".\n"
- "Check kernel logs or set the LIBGL_DEBUG\n"
- "environment variable to \"verbose\" for more info.\n"
- "Detected in file %s, line %d, function %s.\n",
- strerror(-val), file, line, function);
-#ifndef NDEBUG
- abort();
-#else
- abort();
-#endif
-}
-
-DriFenceObject *
-driFenceBuffers(int fd, char *name, unsigned flags)
-{
- DriFenceObject *fence = (DriFenceObject *) malloc(sizeof(*fence));
- int ret;
-
- if (!fence)
- BM_CKFATAL(-EINVAL);
-
- _glthread_LOCK_MUTEX(bmMutex);
- fence->refCount = 1;
- fence->name = name;
- fence->fd = fd;
- _glthread_INIT_MUTEX(fence->mutex);
- ret = drmFenceBuffers(fd, flags, &fence->fence);
- _glthread_UNLOCK_MUTEX(bmMutex);
- if (ret) {
- free(fence);
- BM_CKFATAL(ret);
- }
- return fence;
-}
-
-
-unsigned
-driFenceType(DriFenceObject * fence)
-{
- unsigned ret;
-
- _glthread_LOCK_MUTEX(bmMutex);
- ret = fence->fence.flags;
- _glthread_UNLOCK_MUTEX(bmMutex);
-
- return ret;
-}
-
-
-DriFenceObject *
-driFenceReference(DriFenceObject * fence)
-{
- _glthread_LOCK_MUTEX(bmMutex);
- ++fence->refCount;
- _glthread_UNLOCK_MUTEX(bmMutex);
- return fence;
-}
-
-void
-driFenceUnReference(DriFenceObject * fence)
-{
- if (!fence)
- return;
-
- _glthread_LOCK_MUTEX(bmMutex);
- if (--fence->refCount == 0) {
- drmFenceDestroy(fence->fd, &fence->fence);
- free(fence);
- }
- _glthread_UNLOCK_MUTEX(bmMutex);
-}
-
-void
-driFenceFinish(DriFenceObject * fence, unsigned type, int lazy)
-{
- int ret;
- unsigned flags = (lazy) ? DRM_FENCE_FLAG_WAIT_LAZY : 0;
-
- _glthread_LOCK_MUTEX(fence->mutex);
- ret = drmFenceWait(fence->fd, flags, &fence->fence, type);
- _glthread_UNLOCK_MUTEX(fence->mutex);
- BM_CKFATAL(ret);
-}
-
-int
-driFenceSignaled(DriFenceObject * fence, unsigned type)
-{
- int signaled;
- int ret;
-
- if (fence == NULL)
- return GL_TRUE;
-
- _glthread_LOCK_MUTEX(fence->mutex);
- ret = drmFenceSignaled(fence->fd, &fence->fence, type, &signaled);
- _glthread_UNLOCK_MUTEX(fence->mutex);
- BM_CKFATAL(ret);
- return signaled;
-}
-
-
-extern drmBO *
-driBOKernel(struct _DriBufferObject *buf)
-{
- drmBO *ret;
-
- assert(buf->private != NULL);
- ret = buf->pool->kernel(buf->pool, buf->private);
- if (!ret)
- BM_CKFATAL(-EINVAL);
-
- return ret;
-}
-
-void
-driBOWaitIdle(struct _DriBufferObject *buf, int lazy)
+dri_bo *
+dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size,
+ unsigned int alignment, unsigned int location_mask)
{
- struct _DriBufferPool *pool;
- void *priv;
+ assert((location_mask & ~(DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_MEM_TT |
+ DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_PRIV0 |
+ DRM_BO_FLAG_MEM_PRIV1 | DRM_BO_FLAG_MEM_PRIV2 |
+ DRM_BO_FLAG_MEM_PRIV3 |
+ DRM_BO_FLAG_MEM_PRIV4)) == 0);
- _glthread_LOCK_MUTEX(buf->mutex);
- pool = buf->pool;
- priv = buf->private;
- _glthread_UNLOCK_MUTEX(buf->mutex);
-
- assert(priv != NULL);
- BM_CKFATAL(buf->pool->waitIdle(pool, priv, lazy));
+ return bufmgr->bo_alloc(bufmgr, name, size, alignment, location_mask);
}
-void *
-driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint)
+dri_bo *
+dri_bo_alloc_static(dri_bufmgr *bufmgr, const char *name, unsigned long offset,
+ unsigned long size, void *virtual,
+ unsigned int location_mask)
{
- void *virtual;
+ assert((location_mask & ~(DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_MEM_TT |
+ DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_PRIV0 |
+ DRM_BO_FLAG_MEM_PRIV1 | DRM_BO_FLAG_MEM_PRIV2 |
+ DRM_BO_FLAG_MEM_PRIV3 |
+ DRM_BO_FLAG_MEM_PRIV4)) == 0);
- assert(buf->private != NULL);
-
- _glthread_LOCK_MUTEX(buf->mutex);
- BM_CKFATAL(buf->pool->map(buf->pool, buf->private, flags, hint, &virtual));
- _glthread_UNLOCK_MUTEX(buf->mutex);
- return virtual;
+ return bufmgr->bo_alloc_static(bufmgr, name, offset, size, virtual,
+ location_mask);
}
void
-driBOUnmap(struct _DriBufferObject *buf)
-{
- assert(buf->private != NULL);
-
- buf->pool->unmap(buf->pool, buf->private);
-}
-
-unsigned long
-driBOOffset(struct _DriBufferObject *buf)
-{
- unsigned long ret;
-
- assert(buf->private != NULL);
-
- _glthread_LOCK_MUTEX(buf->mutex);
- ret = buf->pool->offset(buf->pool, buf->private);
- _glthread_UNLOCK_MUTEX(buf->mutex);
- return ret;
-}
-
-unsigned
-driBOFlags(struct _DriBufferObject *buf)
-{
- unsigned ret;
-
- assert(buf->private != NULL);
-
- _glthread_LOCK_MUTEX(buf->mutex);
- ret = buf->pool->flags(buf->pool, buf->private);
- _glthread_UNLOCK_MUTEX(buf->mutex);
- return ret;
-}
-
-struct _DriBufferObject *
-driBOReference(struct _DriBufferObject *buf)
+dri_bo_reference(dri_bo *bo)
{
- _glthread_LOCK_MUTEX(bmMutex);
- if (++buf->refCount == 1) {
- BM_CKFATAL(-EINVAL);
- }
- _glthread_UNLOCK_MUTEX(bmMutex);
- return buf;
+ bo->bufmgr->bo_reference(bo);
}
void
-driBOUnReference(struct _DriBufferObject *buf)
+dri_bo_unreference(dri_bo *bo)
{
- int tmp;
-
- if (!buf)
+ if (bo == NULL)
return;
- _glthread_LOCK_MUTEX(bmMutex);
- tmp = --buf->refCount;
- _glthread_UNLOCK_MUTEX(bmMutex);
- if (!tmp) {
- buf->pool->destroy(buf->pool, buf->private);
- free(buf);
- }
+ bo->bufmgr->bo_unreference(bo);
}
-void
-driBOData(struct _DriBufferObject *buf,
- unsigned size, const void *data, unsigned flags)
-{
- void *virtual;
- int newBuffer;
- struct _DriBufferPool *pool;
-
- _glthread_LOCK_MUTEX(buf->mutex);
- pool = buf->pool;
- if (!pool->create) {
- _mesa_error(NULL, GL_INVALID_OPERATION,
- "driBOData called on invalid buffer\n");
- BM_CKFATAL(-EINVAL);
- }
- newBuffer = !buf->private || (pool->size(pool, buf->private) < size) ||
- pool->map(pool, buf->private, DRM_BO_FLAG_WRITE,
- DRM_BO_HINT_DONT_BLOCK, &virtual);
-
- if (newBuffer) {
- if (buf->private)
- pool->destroy(pool, buf->private);
- if (!flags)
- flags = buf->flags;
- buf->private = pool->create(pool, size, flags, DRM_BO_HINT_DONT_FENCE,
- buf->alignment);
- if (!buf->private)
- BM_CKFATAL(-ENOMEM);
- BM_CKFATAL(pool->map(pool, buf->private,
- DRM_BO_FLAG_WRITE,
- DRM_BO_HINT_DONT_BLOCK, &virtual));
- }
-
- if (data != NULL)
- memcpy(virtual, data, size);
-
- BM_CKFATAL(pool->unmap(pool, buf->private));
- _glthread_UNLOCK_MUTEX(buf->mutex);
-}
-
-void
-driBOSubData(struct _DriBufferObject *buf,
- unsigned long offset, unsigned long size, const void *data)
+int
+dri_bo_map(dri_bo *buf, GLboolean write_enable)
{
- void *virtual;
-
- _glthread_LOCK_MUTEX(buf->mutex);
- if (size && data) {
- BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
- DRM_BO_FLAG_WRITE, 0, &virtual));
- memcpy((unsigned char *) virtual + offset, data, size);
- BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
- }
- _glthread_UNLOCK_MUTEX(buf->mutex);
+ return buf->bufmgr->bo_map(buf, write_enable);
}
-void
-driBOGetSubData(struct _DriBufferObject *buf,
- unsigned long offset, unsigned long size, void *data)
+int
+dri_bo_unmap(dri_bo *buf)
{
- void *virtual;
-
- _glthread_LOCK_MUTEX(buf->mutex);
- if (size && data) {
- BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
- DRM_BO_FLAG_READ, 0, &virtual));
- memcpy(data, (unsigned char *) virtual + offset, size);
- BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
- }
- _glthread_UNLOCK_MUTEX(buf->mutex);
+ return buf->bufmgr->bo_unmap(buf);
}
-void
-driBOSetStatic(struct _DriBufferObject *buf,
- unsigned long offset,
- unsigned long size, void *virtual, unsigned flags)
+int
+dri_bo_validate(dri_bo *buf, unsigned int flags)
{
- _glthread_LOCK_MUTEX(buf->mutex);
- if (buf->private != NULL) {
- _mesa_error(NULL, GL_INVALID_OPERATION,
- "Invalid buffer for setStatic\n");
- BM_CKFATAL(-EINVAL);
- }
- if (buf->pool->setstatic == NULL) {
- _mesa_error(NULL, GL_INVALID_OPERATION,
- "Invalid buffer pool for setStatic\n");
- BM_CKFATAL(-EINVAL);
- }
-
- if (!flags)
- flags = buf->flags;
-
- buf->private = buf->pool->setstatic(buf->pool, offset, size,
- virtual, flags);
- if (!buf->private) {
- _mesa_error(NULL, GL_OUT_OF_MEMORY,
- "Invalid buffer pool for setStatic\n");
- BM_CKFATAL(-ENOMEM);
- }
- _glthread_UNLOCK_MUTEX(buf->mutex);
+ return buf->bufmgr->bo_validate(buf, flags);
}
-
-
-void
-driGenBuffers(struct _DriBufferPool *pool,
- const char *name,
- unsigned n,
- struct _DriBufferObject *buffers[],
- unsigned alignment, unsigned flags, unsigned hint)
+dri_fence *
+dri_fence_validated(dri_bufmgr *bufmgr, const char *name, GLboolean flushed)
{
- struct _DriBufferObject *buf;
- int i;
-
- flags = (flags) ? flags : DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM |
- DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE;
-
-
- for (i = 0; i < n; ++i) {
- buf = (struct _DriBufferObject *) calloc(1, sizeof(*buf));
- if (!buf)
- BM_CKFATAL(-ENOMEM);
-
- _glthread_INIT_MUTEX(buf->mutex);
- _glthread_LOCK_MUTEX(buf->mutex);
- _glthread_LOCK_MUTEX(bmMutex);
- buf->refCount = 1;
- _glthread_UNLOCK_MUTEX(bmMutex);
- buf->flags = flags;
- buf->hint = hint;
- buf->name = name;
- buf->alignment = alignment;
- buf->pool = pool;
- _glthread_UNLOCK_MUTEX(buf->mutex);
- buffers[i] = buf;
- }
+ return bufmgr->fence_validated(bufmgr, name, flushed);
}
void
-driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[])
+dri_fence_wait(dri_fence *fence)
{
- int i;
-
- for (i = 0; i < n; ++i) {
- driBOUnReference(buffers[i]);
- }
+ fence->bufmgr->fence_wait(fence);
}
-
void
-driInitBufMgr(int fd)
+dri_fence_reference(dri_fence *fence)
{
- ;
+ fence->bufmgr->fence_reference(fence);
}
-
void
-driBOCreateList(int target, drmBOList * list)
+dri_fence_unreference(dri_fence *fence)
{
- _glthread_LOCK_MUTEX(bmMutex);
- BM_CKFATAL(drmBOCreateList(target, list));
- _glthread_UNLOCK_MUTEX(bmMutex);
-}
+ if (fence == NULL)
+ return;
-void
-driBOResetList(drmBOList * list)
-{
- _glthread_LOCK_MUTEX(bmMutex);
- BM_CKFATAL(drmBOResetList(list));
- _glthread_UNLOCK_MUTEX(bmMutex);
+ fence->bufmgr->fence_unreference(fence);
}
void
-driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf,
- unsigned flags, unsigned mask)
+dri_bo_subdata(dri_bo *bo, unsigned long offset,
+ unsigned long size, const void *data)
{
- int newItem;
-
- _glthread_LOCK_MUTEX(buf->mutex);
- _glthread_LOCK_MUTEX(bmMutex);
- BM_CKFATAL(drmAddValidateItem(list, driBOKernel(buf),
- flags, mask, &newItem));
- _glthread_UNLOCK_MUTEX(bmMutex);
-
- /*
- * Tell userspace pools to validate the buffer. This should be a
- * noop if the pool is already validated.
- * FIXME: We should have a list for this as well.
- */
-
- if (buf->pool->validate) {
- BM_CKFATAL(buf->pool->validate(buf->pool, buf->private));
- }
+ if (size == 0 || data == NULL)
+ return;
- _glthread_UNLOCK_MUTEX(buf->mutex);
+ dri_bo_map(bo, GL_TRUE);
+ memcpy((unsigned char *)bo->virtual + offset, data, size);
+ dri_bo_unmap(bo);
}
void
-driBOFence(struct _DriBufferObject *buf, struct _DriFenceObject *fence)
+dri_bo_get_subdata(dri_bo *bo, unsigned long offset,
+ unsigned long size, void *data)
{
- _glthread_LOCK_MUTEX(buf->mutex);
- BM_CKFATAL(buf->pool->fence(buf->pool, buf->private, fence));
- _glthread_UNLOCK_MUTEX(buf->mutex);
+ if (size == 0 || data == NULL)
+ return;
+ dri_bo_map(bo, GL_FALSE);
+ memcpy(data, (unsigned char *)bo->virtual + offset, size);
+ dri_bo_unmap(bo);
}
void
-driBOValidateList(int fd, drmBOList * list)
+dri_bufmgr_destroy(dri_bufmgr *bufmgr)
{
- _glthread_LOCK_MUTEX(bmMutex);
- BM_CKFATAL(drmBOValidateList(fd, list));
- _glthread_UNLOCK_MUTEX(bmMutex);
-}
-
-void
-driPoolTakeDown(struct _DriBufferPool *pool)
-{
- pool->takeDown(pool);
-
+ bufmgr->destroy(bufmgr);
}
diff --git a/src/mesa/drivers/dri/common/dri_bufmgr.h b/src/mesa/drivers/dri/common/dri_bufmgr.h
index 01f149ae4ed..3be342926f7 100644
--- a/src/mesa/drivers/dri/common/dri_bufmgr.h
+++ b/src/mesa/drivers/dri/common/dri_bufmgr.h
@@ -1,5 +1,6 @@
/**************************************************************************
*
+ * Copyright � 2007 Intel Corporation
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
* All Rights Reserved.
*
@@ -28,72 +29,170 @@
/*
* Authors: Thomas Hellstr�m <thomas-at-tungstengraphics-dot-com>
* Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ * Eric Anholt <[email protected]>
*/
#ifndef _DRI_BUFMGR_H_
#define _DRI_BUFMGR_H_
#include <xf86drm.h>
+typedef struct _dri_bufmgr dri_bufmgr;
+typedef struct _dri_bo dri_bo;
+typedef struct _dri_fence dri_fence;
-struct _DriFenceObject;
-struct _DriBufferObject;
-struct _DriBufferPool;
+struct _dri_bo {
+ /** Size in bytes of the buffer object. */
+ unsigned long size;
+ /**
+ * Card virtual address (offset from the beginning of the aperture) for the
+ * object. Only valid while validated.
+ */
+ unsigned long offset;
+ /**
+ * Virtual address for accessing the buffer data. Only valid while mapped.
+ */
+ void *virtual;
+ /** Buffer manager context associated with this buffer object */
+ dri_bufmgr *bufmgr;
+};
-extern struct _DriFenceObject *driFenceBuffers(int fd, char *name,
- unsigned flags);
+struct _dri_fence {
+ /**
+ * This is an ORed mask of DRM_BO_FLAG_READ, DRM_BO_FLAG_WRITE, and
+ * DRM_FLAG_EXE indicating the operations associated with this fence.
+ *
+ * It is constant for the life of the fence object.
+ */
+ unsigned int type;
+ /** Buffer manager context associated with this fence */
+ dri_bufmgr *bufmgr;
+};
-extern struct _DriFenceObject *driFenceReference(struct _DriFenceObject *fence);
+/**
+ * Context for a buffer manager instance.
+ *
+ * Contains public methods followed by private storage for the buffer manager.
+ */
+struct _dri_bufmgr {
+ /**
+ * Allocate a buffer object.
+ *
+ * Buffer objects are not necessarily initially mapped into CPU virtual
+ * address space or graphics device aperture. They must be mapped using
+ * bo_map() to be used by the CPU, and validated for use using bo_validate()
+ * to be used from the graphics device.
+ */
+ dri_bo *(*bo_alloc)(dri_bufmgr *bufmgr_ctx, const char *name,
+ unsigned long size, unsigned int alignment,
+ unsigned int location_mask);
-extern void driFenceUnReference(struct _DriFenceObject *fence);
+ /**
+ * Allocates a buffer object for a static allocation.
+ *
+ * Static allocations are ones such as the front buffer that are offered by
+ * the X Server, which are never evicted and never moved.
+ */
+ dri_bo *(*bo_alloc_static)(dri_bufmgr *bufmgr_ctx, const char *name,
+ unsigned long offset, unsigned long size,
+ void *virtual, unsigned int location_mask);
-extern void
-driFenceFinish(struct _DriFenceObject *fence, unsigned type, int lazy);
+ /** Takes a reference on a buffer object */
+ void (*bo_reference)(dri_bo *bo);
-extern int driFenceSignaled(struct _DriFenceObject *fence, unsigned type);
-extern unsigned driFenceType(struct _DriFenceObject *fence);
+ /**
+ * Releases a reference on a buffer object, freeing the data if
+ * rerefences remain.
+ */
+ void (*bo_unreference)(dri_bo *bo);
-/*
- * Return a pointer to the libdrm buffer object this DriBufferObject
- * uses.
- */
+ /**
+ * Maps the buffer into userspace.
+ *
+ * This function will block waiting for any existing fence on the buffer to
+ * clear, first. The resulting mapping is available at buf->virtual.
+\ */
+ int (*bo_map)(dri_bo *buf, GLboolean write_enable);
+
+ /** 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);
+
+ /**
+ * Releases a reference on a fence object, freeing the data if
+ * rerefences remain.
+ */
+ void (*fence_unreference)(dri_fence *fence);
+
+ /**
+ * Blocks until the given fence is signaled.
+ */
+ void (*fence_wait)(dri_fence *fence);
+
+ /**
+ * Tears down the buffer manager instance.
+ */
+ void (*destroy)(dri_bufmgr *bufmgr);
+};
+
+dri_bo *dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size,
+ unsigned int alignment, unsigned int location_mask);
+dri_bo *dri_bo_alloc_static(dri_bufmgr *bufmgr, const char *name,
+ unsigned long offset, unsigned long size,
+ void *virtual, unsigned int location_mask);
+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);
+
+void dri_bo_subdata(dri_bo *bo, unsigned long offset,
+ unsigned long size, const void *data);
+void dri_bo_get_subdata(dri_bo *bo, unsigned long offset,
+ unsigned long size, void *data);
+
+dri_bufmgr *dri_bufmgr_ttm_init(int fd, unsigned int fence_type,
+ unsigned int fence_type_flush);
-extern drmBO *driBOKernel(struct _DriBufferObject *buf);
-extern void *driBOMap(struct _DriBufferObject *buf, unsigned flags,
- unsigned hint);
-extern void driBOUnmap(struct _DriBufferObject *buf);
-extern unsigned long driBOOffset(struct _DriBufferObject *buf);
-extern unsigned driBOFlags(struct _DriBufferObject *buf);
-extern struct _DriBufferObject *driBOReference(struct _DriBufferObject *buf);
-extern void driBOUnReference(struct _DriBufferObject *buf);
-extern void driBOData(struct _DriBufferObject *r_buf,
- unsigned size, const void *data, unsigned flags);
-extern void driBOSubData(struct _DriBufferObject *buf,
- unsigned long offset, unsigned long size,
- const void *data);
-extern void driBOGetSubData(struct _DriBufferObject *buf,
- unsigned long offset, unsigned long size,
- void *data);
-extern void driGenBuffers(struct _DriBufferPool *pool,
- const char *name,
- unsigned n,
- struct _DriBufferObject *buffers[],
- unsigned alignment, unsigned flags, unsigned hint);
-extern void driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]);
-extern void driInitBufMgr(int fd);
-extern void driBOCreateList(int target, drmBOList * list);
-extern void driBOResetList(drmBOList * list);
-extern void driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf,
- unsigned flags, unsigned mask);
-extern void driBOValidateList(int fd, drmBOList * list);
-
-extern void driBOFence(struct _DriBufferObject *buf,
- struct _DriFenceObject *fence);
-
-extern void driPoolTakeDown(struct _DriBufferPool *pool);
-extern void driBOSetStatic(struct _DriBufferObject *buf,
- unsigned long offset,
- unsigned long size, void *virtual, unsigned flags);
-extern void driBOWaitIdle(struct _DriBufferObject *buf, int lazy);
-extern void driPoolTakeDown(struct _DriBufferPool *pool);
+void dri_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr);
+dri_bufmgr *dri_bufmgr_fake_init(unsigned long low_offset, void *low_virtual,
+ unsigned long size,
+ unsigned int (*fence_emit)(void *private),
+ int (*fence_wait)(void *private,
+ unsigned int cookie),
+ void *driver_priv);
+void dri_bufmgr_destroy(dri_bufmgr *bufmgr);
+dri_bo *dri_ttm_bo_create_from_handle(dri_bufmgr *bufmgr, const char *name,
+ unsigned int handle);
#endif
diff --git a/src/mesa/drivers/dri/common/dri_bufmgr_fake.c b/src/mesa/drivers/dri/common/dri_bufmgr_fake.c
new file mode 100644
index 00000000000..e0d23a36477
--- /dev/null
+++ b/src/mesa/drivers/dri/common/dri_bufmgr_fake.c
@@ -0,0 +1,882 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * 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 TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+/* Originally a fake version of the buffer manager so that we can
+ * prototype the changes in a driver fairly quickly, has been fleshed
+ * out to a fully functional interim solution.
+ *
+ * Basically wraps the old style memory management in the new
+ * programming interface, but is more expressive and avoids many of
+ * the bugs in the old texture manager.
+ */
+#include "mtypes.h"
+#include "dri_bufmgr.h"
+#include "drm.h"
+
+#include "simple_list.h"
+#include "mm.h"
+#include "imports.h"
+
+#if 0
+#define DBG(...) _mesa_printf(__VA_ARGS__)
+#else
+#define DBG(...)
+#endif
+
+/* Internal flags:
+ */
+#define BM_NO_BACKING_STORE 0x00000001
+#define BM_NO_FENCE_SUBDATA 0x00000002
+#define BM_PINNED 0x00000004
+
+/* Wrapper around mm.c's mem_block, which understands that you must
+ * wait for fences to expire before memory can be freed. This is
+ * specific to our use of memcpy for uploads - an upload that was
+ * processed through the command queue wouldn't need to care about
+ * fences.
+ */
+struct block {
+ struct block *next, *prev;
+ struct mem_block *mem; /* BM_MEM_AGP */
+
+ unsigned on_hardware:1;
+ unsigned fenced:1;
+
+ unsigned fence; /* BM_MEM_AGP, Split to read_fence, write_fence */
+
+ dri_bo *bo;
+ void *virtual;
+};
+
+typedef struct _bufmgr_fake {
+ dri_bufmgr bufmgr;
+
+ _glthread_Mutex mutex; /**< for thread safety */
+
+ unsigned long low_offset;
+ unsigned long size;
+ void *virtual;
+
+ struct mem_block *heap;
+ struct block lru; /* only allocated, non-fence-pending blocks here */
+
+ unsigned buf_nr; /* for generating ids */
+
+ struct block on_hardware; /* after bmValidateBuffers */
+ struct block fenced; /* after bmFenceBuffers (mi_flush, emit irq, write dword) */
+ /* then to bufmgr->lru or free() */
+
+ unsigned int last_fence;
+
+ unsigned fail:1;
+ unsigned need_fence:1;
+ GLboolean thrashing;
+
+ /**
+ * Driver callback to emit a fence, returning the cookie.
+ *
+ * Currently, this also requires that a write flush be emitted before
+ * emitting the fence, but this should change.
+ */
+ unsigned int (*fence_emit)(void *private);
+ /** Driver callback to wait for a fence cookie to have passed. */
+ int (*fence_wait)(void *private, unsigned int fence_cookie);
+ /** Driver-supplied argument to driver callbacks */
+ void *driver_priv;
+} dri_bufmgr_fake;
+
+typedef struct _dri_bo_fake {
+ dri_bo bo;
+
+ unsigned id; /* debug only */
+ const char *name;
+
+ unsigned dirty:1;
+ unsigned int refcount;
+ /* Flags may consist of any of the DRM_BO flags, plus
+ * DRM_BO_NO_BACKING_STORE and BM_NO_FENCE_SUBDATA, which are the first two
+ * driver private flags.
+ */
+ unsigned int flags;
+ unsigned int alignment;
+ GLboolean is_static;
+
+ struct block *block;
+ void *backing_store;
+ void (*invalidate_cb)(dri_bufmgr *bufmgr, void * );
+ void *invalidate_ptr;
+} dri_bo_fake;
+
+typedef struct _dri_fence_fake {
+ dri_fence fence;
+
+ const char *name;
+ unsigned int refcount;
+ unsigned int fence_cookie;
+ GLboolean flushed;
+} dri_fence_fake;
+
+static int clear_fenced(dri_bufmgr_fake *bufmgr_fake,
+ unsigned int fence_cookie);
+
+#define MAXFENCE 0x7fffffff
+
+static GLboolean FENCE_LTE( unsigned a, unsigned b )
+{
+ if (a == b)
+ return GL_TRUE;
+
+ if (a < b && b - a < (1<<24))
+ return GL_TRUE;
+
+ if (a > b && MAXFENCE - a + b < (1<<24))
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+static unsigned int
+_fence_emit_internal(dri_bufmgr_fake *bufmgr_fake)
+{
+ bufmgr_fake->last_fence = bufmgr_fake->fence_emit(bufmgr_fake->driver_priv);
+ return bufmgr_fake->last_fence;
+}
+
+static void
+_fence_wait_internal(dri_bufmgr_fake *bufmgr_fake, unsigned int cookie)
+{
+ int ret;
+
+ ret = bufmgr_fake->fence_wait(bufmgr_fake->driver_priv, cookie);
+ if (ret != 0) {
+ _mesa_printf("%s:%d: Error %d waiting for fence.\n",
+ __FILE__, __LINE__);
+ abort();
+ }
+ clear_fenced(bufmgr_fake, cookie);
+}
+
+static GLboolean
+_fence_test(dri_bufmgr_fake *bufmgr_fake, unsigned fence)
+{
+ /* Slight problem with wrap-around:
+ */
+ return fence == 0 || FENCE_LTE(fence, bufmgr_fake->last_fence);
+}
+
+/**
+ * Allocate a memory manager block for the buffer.
+ */
+static GLboolean
+alloc_block(dri_bo *bo)
+{
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+ dri_bufmgr_fake *bufmgr_fake= (dri_bufmgr_fake *)bo->bufmgr;
+ struct block *block = (struct block *)calloc(sizeof *block, 1);
+ unsigned int align_log2 = ffs(bo_fake->alignment);
+ GLuint sz;
+
+ if (!block)
+ return GL_FALSE;
+
+ sz = (bo->size + bo_fake->alignment - 1) & ~(bo_fake->alignment - 1);
+
+ block->mem = mmAllocMem(bufmgr_fake->heap, sz, align_log2, 0);
+ if (!block->mem) {
+ free(block);
+ return GL_FALSE;
+ }
+
+ make_empty_list(block);
+
+ /* Insert at head or at tail???
+ */
+ insert_at_tail(&bufmgr_fake->lru, block);
+
+ block->virtual = bufmgr_fake->virtual +
+ block->mem->ofs - bufmgr_fake->low_offset;
+ block->bo = bo;
+
+ bo_fake->block = block;
+
+ return GL_TRUE;
+}
+
+/* Release the card storage associated with buf:
+ */
+static void free_block(dri_bufmgr_fake *bufmgr_fake, struct block *block)
+{
+ DBG("free block %p\n", block);
+
+ if (!block)
+ return;
+
+ if (block->on_hardware) {
+ block->bo = NULL;
+ }
+ else if (block->fenced) {
+ block->bo = NULL;
+ }
+ else {
+ DBG(" - free immediately\n");
+ remove_from_list(block);
+
+ mmFreeMem(block->mem);
+ free(block);
+ }
+}
+
+static void
+alloc_backing_store(dri_bo *bo)
+{
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+ assert(!bo_fake->backing_store);
+ assert(!(bo_fake->flags & (BM_PINNED|BM_NO_BACKING_STORE)));
+
+ bo_fake->backing_store = ALIGN_MALLOC(bo->size, 64);
+}
+
+static void
+free_backing_store(dri_bo *bo)
+{
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+ assert(!(bo_fake->flags & (BM_PINNED|BM_NO_BACKING_STORE)));
+
+ if (bo_fake->backing_store) {
+ ALIGN_FREE(bo_fake->backing_store);
+ bo_fake->backing_store = NULL;
+ }
+}
+
+static void
+set_dirty(dri_bo *bo)
+{
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr;
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+
+ if (bo_fake->flags & BM_NO_BACKING_STORE)
+ bo_fake->invalidate_cb(&bufmgr_fake->bufmgr, bo_fake->invalidate_ptr);
+
+ assert(!(bo_fake->flags & BM_PINNED));
+
+ DBG("set_dirty - buf %d\n", bo_fake->id);
+ bo_fake->dirty = 1;
+}
+
+static GLboolean
+evict_lru(dri_bufmgr_fake *bufmgr_fake, GLuint max_fence)
+{
+ struct block *block, *tmp;
+
+ DBG("%s\n", __FUNCTION__);
+
+ foreach_s(block, tmp, &bufmgr_fake->lru) {
+ dri_bo_fake *bo_fake = (dri_bo_fake *)block->bo;
+
+ if (bo_fake != NULL && (bo_fake->flags & BM_NO_FENCE_SUBDATA))
+ continue;
+
+ if (block->fence && max_fence && !FENCE_LTE(block->fence, max_fence))
+ return 0;
+
+ set_dirty(&bo_fake->bo);
+ bo_fake->block = NULL;
+
+ free_block(bufmgr_fake, block);
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+#define foreach_s_rev(ptr, t, list) \
+ for(ptr=(list)->prev,t=(ptr)->prev; list != ptr; ptr=t, t=(t)->prev)
+
+static GLboolean
+evict_mru(dri_bufmgr_fake *bufmgr_fake)
+{
+ struct block *block, *tmp;
+
+ DBG("%s\n", __FUNCTION__);
+
+ foreach_s_rev(block, tmp, &bufmgr_fake->lru) {
+ dri_bo_fake *bo_fake = (dri_bo_fake *)block->bo;
+
+ if (bo_fake && (bo_fake->flags & BM_NO_FENCE_SUBDATA))
+ continue;
+
+ set_dirty(&bo_fake->bo);
+ bo_fake->block = NULL;
+
+ free_block(bufmgr_fake, block);
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+/**
+ * Removes all objects from the fenced list older than the given fence.
+ */
+static int clear_fenced(dri_bufmgr_fake *bufmgr_fake,
+ unsigned int fence_cookie)
+{
+ struct block *block, *tmp;
+ int ret = 0;
+
+ foreach_s(block, tmp, &bufmgr_fake->fenced) {
+ assert(block->fenced);
+
+ if (_fence_test(bufmgr_fake, block->fence)) {
+
+ block->fenced = 0;
+
+ if (!block->bo) {
+ DBG("delayed free: offset %x sz %x\n",
+ block->mem->ofs, block->mem->size);
+ remove_from_list(block);
+ mmFreeMem(block->mem);
+ free(block);
+ }
+ else {
+ DBG("return to lru: offset %x sz %x\n",
+ block->mem->ofs, block->mem->size);
+ move_to_tail(&bufmgr_fake->lru, block);
+ }
+
+ ret = 1;
+ }
+ else {
+ /* Blocks are ordered by fence, so if one fails, all from
+ * here will fail also:
+ */
+ break;
+ }
+ }
+
+ DBG("%s: %d\n", __FUNCTION__, ret);
+ return ret;
+}
+
+static void fence_blocks(dri_bufmgr_fake *bufmgr_fake, unsigned fence)
+{
+ struct block *block, *tmp;
+
+ foreach_s (block, tmp, &bufmgr_fake->on_hardware) {
+ DBG("Fence block %p (sz 0x%x buf %p) with fence %d\n", block,
+ block->mem->size, block->bo, fence);
+ block->fence = fence;
+
+ block->on_hardware = 0;
+ block->fenced = 1;
+
+ /* Move to tail of pending list here
+ */
+ move_to_tail(&bufmgr_fake->fenced, block);
+ }
+
+ assert(is_empty_list(&bufmgr_fake->on_hardware));
+}
+
+static GLboolean evict_and_alloc_block(dri_bo *bo)
+{
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr;
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+
+ assert(bo_fake->block == NULL);
+
+ /* Search for already free memory:
+ */
+ if (alloc_block(bo))
+ return GL_TRUE;
+
+ /* If we're not thrashing, allow lru eviction to dig deeper into
+ * recently used textures. We'll probably be thrashing soon:
+ */
+ if (!bufmgr_fake->thrashing) {
+ while (evict_lru(bufmgr_fake, 0))
+ if (alloc_block(bo))
+ return GL_TRUE;
+ }
+
+ /* Keep thrashing counter alive?
+ */
+ if (bufmgr_fake->thrashing)
+ bufmgr_fake->thrashing = 20;
+
+ /* Wait on any already pending fences - here we are waiting for any
+ * freed memory that has been submitted to hardware and fenced to
+ * become available:
+ */
+ while (!is_empty_list(&bufmgr_fake->fenced)) {
+ GLuint fence = bufmgr_fake->fenced.next->fence;
+ _fence_wait_internal(bufmgr_fake, fence);
+
+ if (alloc_block(bo))
+ return GL_TRUE;
+ }
+
+ if (!is_empty_list(&bufmgr_fake->on_hardware)) {
+ while (!is_empty_list(&bufmgr_fake->fenced)) {
+ GLuint fence = bufmgr_fake->fenced.next->fence;
+ _fence_wait_internal(bufmgr_fake, fence);
+ }
+
+ if (!bufmgr_fake->thrashing) {
+ DBG("thrashing\n");
+ }
+ bufmgr_fake->thrashing = 20;
+
+ if (alloc_block(bo))
+ return GL_TRUE;
+ }
+
+ while (evict_mru(bufmgr_fake))
+ if (alloc_block(bo))
+ return GL_TRUE;
+
+ DBG("%s 0x%x bytes failed\n", __FUNCTION__, bo->size);
+
+ assert(is_empty_list(&bufmgr_fake->on_hardware));
+ assert(is_empty_list(&bufmgr_fake->fenced));
+
+ return GL_FALSE;
+}
+
+/***********************************************************************
+ * Public functions
+ */
+
+/**
+ * Wait for hardware idle by emitting a fence and waiting for it.
+ */
+static void
+dri_bufmgr_fake_wait_idle(dri_bufmgr_fake *bufmgr_fake)
+{
+ unsigned int cookie;
+
+ cookie = bufmgr_fake->fence_emit(bufmgr_fake->driver_priv);
+ _fence_wait_internal(bufmgr_fake, cookie);
+}
+
+/* Specifically ignore texture memory sharing.
+ * -- just evict everything
+ * -- and wait for idle
+ */
+void
+dri_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr)
+{
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr;
+
+ _glthread_LOCK_MUTEX(bufmgr_fake->mutex);
+ {
+ struct block *block, *tmp;
+
+ bufmgr_fake->need_fence = 1;
+ bufmgr_fake->fail = 0;
+
+ /* Wait for hardware idle. We don't know where acceleration has been
+ * happening, so we'll need to wait anyway before letting anything get
+ * put on the card again.
+ */
+ dri_bufmgr_fake_wait_idle(bufmgr_fake);
+
+ /* Check that we hadn't released the lock without having fenced the last
+ * set of buffers.
+ */
+ assert(is_empty_list(&bufmgr_fake->fenced));
+ assert(is_empty_list(&bufmgr_fake->on_hardware));
+
+ foreach_s(block, tmp, &bufmgr_fake->lru) {
+ assert(_fence_test(bufmgr_fake, block->fence));
+ set_dirty(block->bo);
+ }
+ }
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+}
+
+static dri_bo *
+dri_fake_bo_alloc(dri_bufmgr *bufmgr, const char *name,
+ unsigned long size, unsigned int alignment,
+ unsigned int location_mask)
+{
+ dri_bufmgr_fake *bufmgr_fake;
+ dri_bo_fake *bo_fake;
+
+ bufmgr_fake = (dri_bufmgr_fake *)bufmgr;
+
+ bo_fake = calloc(1, sizeof(*bo_fake));
+ if (!bo_fake)
+ return NULL;
+
+ bo_fake->bo.size = size;
+ bo_fake->bo.offset = -1;
+ bo_fake->bo.virtual = NULL;
+ bo_fake->bo.bufmgr = bufmgr;
+ bo_fake->refcount = 1;
+
+ /* Alignment must be a power of two */
+ assert((alignment & (alignment - 1)) == 0);
+ if (alignment == 0)
+ alignment = 1;
+ bo_fake->alignment = alignment;
+ bo_fake->id = ++bufmgr_fake->buf_nr;
+ bo_fake->name = name;
+ bo_fake->flags = 0;
+ bo_fake->is_static = GL_FALSE;
+
+ DBG("drm_bo_alloc: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name,
+ bo_fake->bo.size / 1024);
+
+ return &bo_fake->bo;
+}
+
+static dri_bo *
+dri_fake_bo_alloc_static(dri_bufmgr *bufmgr, const char *name,
+ unsigned long offset, unsigned long size,
+ void *virtual, unsigned int location_mask)
+{
+ dri_bufmgr_fake *bufmgr_fake;
+ dri_bo_fake *bo_fake;
+
+ bufmgr_fake = (dri_bufmgr_fake *)bufmgr;
+
+ bo_fake = calloc(1, sizeof(*bo_fake));
+ if (!bo_fake)
+ return NULL;
+
+ bo_fake->bo.size = size;
+ bo_fake->bo.offset = offset;
+ bo_fake->bo.virtual = virtual;
+ bo_fake->bo.bufmgr = bufmgr;
+ bo_fake->refcount = 1;
+ bo_fake->id = ++bufmgr_fake->buf_nr;
+ bo_fake->name = name;
+ bo_fake->flags = BM_PINNED | DRM_BO_FLAG_NO_MOVE;
+ bo_fake->is_static = GL_TRUE;
+
+ DBG("drm_bo_alloc_static: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name,
+ bo_fake->bo.size / 1024);
+
+ return &bo_fake->bo;
+}
+
+static void
+dri_fake_bo_reference(dri_bo *bo)
+{
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr;
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+
+ _glthread_LOCK_MUTEX(bufmgr_fake->mutex);
+ bo_fake->refcount++;
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+}
+
+static void
+dri_fake_bo_unreference(dri_bo *bo)
+{
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr;
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+
+ if (!bo)
+ return;
+
+ _glthread_LOCK_MUTEX(bufmgr_fake->mutex);
+ if (--bo_fake->refcount == 0) {
+ /* No remaining references, so free it */
+ if (bo_fake->block)
+ free_block(bufmgr_fake, bo_fake->block);
+ free_backing_store(bo);
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+ free(bo);
+ return;
+ }
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+}
+
+/**
+ * Map a buffer into bo->virtual, allocating either card memory space (If
+ * BM_NO_BACKING_STORE or BM_PINNED) or backing store, as necessary.
+ */
+static int
+dri_fake_bo_map(dri_bo *bo, GLboolean write_enable)
+{
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr;
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+
+ /* Static buffers are always mapped. */
+ if (bo_fake->is_static)
+ return 0;
+
+ _glthread_LOCK_MUTEX(bufmgr_fake->mutex);
+ {
+ DBG("drm_bo_map: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name,
+ bo_fake->bo.size / 1024);
+
+ if (bo->virtual != NULL) {
+ _mesa_printf("%s: already mapped\n", __FUNCTION__);
+ abort();
+ }
+ else if (bo_fake->flags & (BM_NO_BACKING_STORE|BM_PINNED)) {
+
+ if (!bo_fake->block && !evict_and_alloc_block(bo)) {
+ DBG("%s: alloc failed\n", __FUNCTION__);
+ bufmgr_fake->fail = 1;
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+ return 1;
+ }
+ else {
+ assert(bo_fake->block);
+ bo_fake->dirty = 0;
+
+ if (!(bo_fake->flags & BM_NO_FENCE_SUBDATA))
+ dri_bufmgr_fake_wait_idle(bufmgr_fake);
+
+ bo->virtual = bo_fake->block->virtual;
+ }
+ }
+ else {
+ if (write_enable)
+ set_dirty(bo);
+
+ if (bo_fake->backing_store == 0)
+ alloc_backing_store(bo);
+
+ bo->virtual = bo_fake->backing_store;
+ }
+ }
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+ return 0;
+}
+
+static int
+dri_fake_bo_unmap(dri_bo *bo)
+{
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+
+ /* Static buffers are always mapped. */
+ if (bo_fake->is_static)
+ return 0;
+
+ if (bo == NULL)
+ return 0;
+
+ DBG("drm_bo_unmap: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name,
+ bo_fake->bo.size / 1024);
+
+ bo->virtual = NULL;
+
+ return 0;
+}
+
+static int
+dri_fake_bo_validate(dri_bo *bo, unsigned int flags)
+{
+ dri_bufmgr_fake *bufmgr_fake;
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+
+ /* XXX: Sanity-check whether we've already validated this one under
+ * different flags. See drmAddValidateItem().
+ */
+
+ DBG("drm_bo_validate: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name,
+ bo_fake->bo.size / 1024);
+ bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr;
+
+ _glthread_LOCK_MUTEX(bufmgr_fake->mutex);
+ {
+ if (bo_fake->is_static) {
+ /* Add it to the needs-fence list */
+ bufmgr_fake->need_fence = 1;
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+ return 0;
+ }
+
+ /* Allocate the card memory */
+ if (!bo_fake->block && !evict_and_alloc_block(bo)) {
+ bufmgr_fake->fail = 1;
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+ DBG("Failed to validate buf %d:%s\n", bo_fake->id, bo_fake->name);
+ return -1;
+ }
+
+ assert(bo_fake->block);
+ assert(bo_fake->block->bo == &bo_fake->bo);
+
+ bo->offset = bo_fake->block->mem->ofs;
+
+ /* Upload the buffer contents if necessary */
+ if (bo_fake->dirty) {
+ DBG("Upload dirty buf %d:%s, sz %d offset 0x%x\n", bo_fake->id,
+ bo_fake->name, bo->size, bo_fake->block->mem->ofs);
+
+ assert(!(bo_fake->flags &
+ (BM_NO_BACKING_STORE|BM_PINNED)));
+
+ /* Actually, should be able to just wait for a fence on the memory,
+ * which we would be tracking when we free it. Waiting for idle is
+ * a sufficiently large hammer for now.
+ */
+ dri_bufmgr_fake_wait_idle(bufmgr_fake);
+
+ memcpy(bo_fake->block->virtual, bo_fake->backing_store, bo->size);
+ bo_fake->dirty = 0;
+ }
+
+ bo_fake->block->on_hardware = 1;
+ move_to_tail(&bufmgr_fake->on_hardware, bo_fake->block);
+
+ bufmgr_fake->need_fence = 1;
+ }
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+
+ return 0;
+}
+
+static dri_fence *
+dri_fake_fence_validated(dri_bufmgr *bufmgr, const char *name,
+ GLboolean flushed)
+{
+ dri_fence_fake *fence_fake;
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr;
+ unsigned int cookie;
+
+ fence_fake = malloc(sizeof(*fence_fake));
+ if (!fence_fake)
+ return NULL;
+
+ fence_fake->refcount = 1;
+ fence_fake->name = name;
+ fence_fake->flushed = flushed;
+ fence_fake->fence.bufmgr = bufmgr;
+
+ _glthread_LOCK_MUTEX(bufmgr_fake->mutex);
+ cookie = _fence_emit_internal(bufmgr_fake);
+ fence_fake->fence_cookie = cookie;
+ fence_blocks(bufmgr_fake, cookie);
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+
+ DBG("drm_fence_validated: 0x%08x cookie\n", fence_fake->fence_cookie);
+
+ return &fence_fake->fence;
+}
+
+static void
+dri_fake_fence_reference(dri_fence *fence)
+{
+ dri_fence_fake *fence_fake = (dri_fence_fake *)fence;
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)fence->bufmgr;
+
+ _glthread_LOCK_MUTEX(bufmgr_fake->mutex);
+ ++fence_fake->refcount;
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+}
+
+static void
+dri_fake_fence_unreference(dri_fence *fence)
+{
+ dri_fence_fake *fence_fake = (dri_fence_fake *)fence;
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)fence->bufmgr;
+
+ if (!fence)
+ return;
+
+ _glthread_LOCK_MUTEX(bufmgr_fake->mutex);
+ if (--fence_fake->refcount == 0) {
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+ free(fence);
+ return;
+ }
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+}
+
+static void
+dri_fake_fence_wait(dri_fence *fence)
+{
+ dri_fence_fake *fence_fake = (dri_fence_fake *)fence;
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)fence->bufmgr;
+
+ DBG("drm_fence_wait: 0x%08x cookie\n", fence_fake->fence_cookie);
+
+ _glthread_LOCK_MUTEX(bufmgr_fake->mutex);
+ _fence_wait_internal(bufmgr_fake, fence_fake->fence_cookie);
+ _glthread_UNLOCK_MUTEX(bufmgr_fake->mutex);
+}
+
+static void
+dri_fake_destroy(dri_bufmgr *bufmgr)
+{
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bufmgr;
+
+ _glthread_DESTROY_MUTEX(bufmgr_fake->mutex);
+ mmDestroy(bufmgr_fake->heap);
+ free(bufmgr);
+}
+
+dri_bufmgr *
+dri_bufmgr_fake_init(unsigned long low_offset, void *low_virtual,
+ unsigned long size,
+ unsigned int (*fence_emit)(void *private),
+ int (*fence_wait)(void *private, unsigned int cookie),
+ void *driver_priv)
+{
+ dri_bufmgr_fake *bufmgr_fake;
+
+ bufmgr_fake = calloc(1, sizeof(*bufmgr_fake));
+
+ /* Initialize allocator */
+ make_empty_list(&bufmgr_fake->fenced);
+ make_empty_list(&bufmgr_fake->on_hardware);
+ make_empty_list(&bufmgr_fake->lru);
+
+ bufmgr_fake->low_offset = low_offset;
+ bufmgr_fake->virtual = low_virtual;
+ bufmgr_fake->size = size;
+ bufmgr_fake->heap = mmInit(low_offset, size);
+
+ _glthread_INIT_MUTEX(bufmgr_fake->mutex);
+
+ /* Hook in methods */
+ bufmgr_fake->bufmgr.bo_alloc = dri_fake_bo_alloc;
+ bufmgr_fake->bufmgr.bo_alloc_static = dri_fake_bo_alloc_static;
+ bufmgr_fake->bufmgr.bo_reference = dri_fake_bo_reference;
+ 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->fence_emit = fence_emit;
+ bufmgr_fake->fence_wait = fence_wait;
+ bufmgr_fake->driver_priv = driver_priv;
+
+ return &bufmgr_fake->bufmgr;
+}
diff --git a/src/mesa/drivers/dri/common/dri_bufmgr_ttm.c b/src/mesa/drivers/dri/common/dri_bufmgr_ttm.c
new file mode 100644
index 00000000000..bda8e341908
--- /dev/null
+++ b/src/mesa/drivers/dri/common/dri_bufmgr_ttm.c
@@ -0,0 +1,469 @@
+/**************************************************************************
+ *
+ * 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 <[email protected]>
+ */
+
+#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, 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, &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;
+}
diff --git a/src/mesa/drivers/dri/common/dri_bufpool.h b/src/mesa/drivers/dri/common/dri_bufpool.h
deleted file mode 100644
index c6fb2c3ce01..00000000000
--- a/src/mesa/drivers/dri/common/dri_bufpool.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/**************************************************************************
- *
- * 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>
- */
-
-#ifndef _DRI_BUFPOOL_H_
-#define _DRI_BUFPOOL_H_
-
-#include <xf86drm.h>
-struct _DriFenceObject;
-
-typedef struct _DriBufferPool
-{
- int fd;
- int (*map) (struct _DriBufferPool * pool, void *private,
- unsigned flags, int hint, void **virtual);
- int (*unmap) (struct _DriBufferPool * pool, void *private);
- int (*destroy) (struct _DriBufferPool * pool, void *private);
- unsigned long (*offset) (struct _DriBufferPool * pool, void *private);
- unsigned (*flags) (struct _DriBufferPool * pool, void *private);
- unsigned long (*size) (struct _DriBufferPool * pool, void *private);
- void *(*create) (struct _DriBufferPool * pool, unsigned long size,
- unsigned flags, unsigned hint, unsigned alignment);
- int (*fence) (struct _DriBufferPool * pool, void *private,
- struct _DriFenceObject * fence);
- drmBO *(*kernel) (struct _DriBufferPool * pool, void *private);
- int (*validate) (struct _DriBufferPool * pool, void *private);
- void *(*setstatic) (struct _DriBufferPool * pool, unsigned long offset,
- unsigned long size, void *virtual, unsigned flags);
- int (*waitIdle) (struct _DriBufferPool *pool, void *private,
- int lazy);
- void (*takeDown) (struct _DriBufferPool * pool);
- void *data;
-} DriBufferPool;
-
-extern void bmError(int val, const char *file, const char *function,
- int line);
-#define BM_CKFATAL(val) \
- do{ \
- int tstVal = (val); \
- if (tstVal) \
- bmError(tstVal, __FILE__, __FUNCTION__, __LINE__); \
- } while(0);
-
-
-
-
-
-/*
- * Builtin pools.
- */
-
-/*
- * Kernel buffer objects. Size in multiples of page size. Page size aligned.
- */
-
-extern struct _DriBufferPool *driDRMPoolInit(int fd);
-extern struct _DriBufferPool *driDRMStaticPoolInit(int fd);
-
-#endif
diff --git a/src/mesa/drivers/dri/common/dri_drmpool.c b/src/mesa/drivers/dri/common/dri_drmpool.c
deleted file mode 100644
index 592ac105428..00000000000
--- a/src/mesa/drivers/dri/common/dri_drmpool.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/**************************************************************************
- *
- * 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>
- */
-
-#include <xf86drm.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "dri_bufpool.h"
-
-/*
- * Buffer pool implementation using DRM buffer objects as DRI buffer objects.
- */
-
-static void *
-pool_create(struct _DriBufferPool *pool,
- unsigned long size, unsigned flags, unsigned hint,
- unsigned alignment)
-{
- drmBO *buf = (drmBO *) malloc(sizeof(*buf));
- int ret;
- unsigned pageSize = getpagesize();
-
- if (!buf)
- return NULL;
-
- if ((alignment > pageSize) && (alignment % pageSize)) {
- free(buf);
- return NULL;
- }
-
- ret = drmBOCreate(pool->fd, 0, size, alignment / pageSize,
- NULL, drm_bo_type_dc,
- flags, hint, buf);
- if (ret) {
- free(buf);
- return NULL;
- }
-
- return (void *) buf;
-}
-
-static int
-pool_destroy(struct _DriBufferPool *pool, void *private)
-{
- int ret;
- drmBO *buf = (drmBO *) private;
- ret = drmBODestroy(pool->fd, buf);
- free(buf);
- return ret;
-}
-
-static int
-pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,
- int hint, void **virtual)
-{
- drmBO *buf = (drmBO *) private;
-
- return drmBOMap(pool->fd, buf, flags, hint, virtual);
-}
-
-static int
-pool_unmap(struct _DriBufferPool *pool, void *private)
-{
- drmBO *buf = (drmBO *) private;
- return drmBOUnmap(pool->fd, buf);
-}
-
-static unsigned long
-pool_offset(struct _DriBufferPool *pool, void *private)
-{
- drmBO *buf = (drmBO *) private;
- return buf->offset;
-}
-
-static unsigned
-pool_flags(struct _DriBufferPool *pool, void *private)
-{
- drmBO *buf = (drmBO *) private;
- return buf->flags;
-}
-
-
-static unsigned long
-pool_size(struct _DriBufferPool *pool, void *private)
-{
- drmBO *buf = (drmBO *) private;
- return buf->size;
-}
-
-static int
-pool_fence(struct _DriBufferPool *pool, void *private,
- struct _DriFenceObject *fence)
-{
- /*
- * Noop. The kernel handles all fencing.
- */
-
- return 0;
-}
-
-static drmBO *
-pool_kernel(struct _DriBufferPool *pool, void *private)
-{
- return (drmBO *) private;
-}
-
-static int
-pool_waitIdle(struct _DriBufferPool *pool, void *private, int lazy)
-{
- drmBO *buf = (drmBO *) private;
- return drmBOWaitIdle(pool->fd, buf, (lazy) ? DRM_BO_HINT_WAIT_LAZY:0);
-}
-
-
-static void
-pool_takedown(struct _DriBufferPool *pool)
-{
- free(pool);
-}
-
-
-struct _DriBufferPool *
-driDRMPoolInit(int fd)
-{
- struct _DriBufferPool *pool;
-
- pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
-
- if (!pool)
- return NULL;
-
- pool->fd = fd;
- pool->map = &pool_map;
- pool->unmap = &pool_unmap;
- pool->destroy = &pool_destroy;
- pool->offset = &pool_offset;
- pool->flags = &pool_flags;
- pool->size = &pool_size;
- pool->create = &pool_create;
- pool->fence = &pool_fence;
- pool->kernel = &pool_kernel;
- pool->validate = NULL;
- pool->setstatic = NULL;
- pool->waitIdle = &pool_waitIdle;
- pool->takeDown = &pool_takedown;
- pool->data = NULL;
- return pool;
-}
-
-
-static void *
-pool_setstatic(struct _DriBufferPool *pool, unsigned long offset,
- unsigned long size, void *virtual, unsigned flags)
-{
- drmBO *buf = (drmBO *) malloc(sizeof(*buf));
- int ret;
-
- if (!buf)
- return NULL;
-
- ret = drmBOCreate(pool->fd, offset, size, 0, NULL, drm_bo_type_fake,
- flags, DRM_BO_HINT_DONT_FENCE, buf);
-
- if (ret) {
- free(buf);
- return NULL;
- }
-
- buf->virtual = virtual;
-
- return (void *) buf;
-}
-
-
-struct _DriBufferPool *
-driDRMStaticPoolInit(int fd)
-{
- struct _DriBufferPool *pool;
-
- pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
-
- if (!pool)
- return NULL;
-
- pool->fd = fd;
- pool->map = &pool_map;
- pool->unmap = &pool_unmap;
- pool->destroy = &pool_destroy;
- pool->offset = &pool_offset;
- pool->flags = &pool_flags;
- pool->size = &pool_size;
- pool->create = NULL;
- pool->fence = &pool_fence;
- pool->kernel = &pool_kernel;
- pool->validate = NULL;
- pool->setstatic = &pool_setstatic;
- pool->waitIdle = &pool_waitIdle;
- pool->takeDown = &pool_takedown;
- pool->data = NULL;
- return pool;
-}
diff --git a/src/mesa/drivers/dri/i915tex/Makefile b/src/mesa/drivers/dri/i915tex/Makefile
index ed8483a028c..d3d0bd570c1 100644
--- a/src/mesa/drivers/dri/i915tex/Makefile
+++ b/src/mesa/drivers/dri/i915tex/Makefile
@@ -2,7 +2,7 @@
TOP = ../../../../..
include $(TOP)/configs/current
-LIBNAME = i915tex_dri.so
+LIBNAME = i915_dri.so
MINIGLX_SOURCES = server/intel_dri.c
@@ -52,8 +52,7 @@ DRIVER_SOURCES = \
intel_state.c \
intel_tris.c \
intel_fbo.c \
- intel_depthstencil.c \
- intel_batchpool.c
+ intel_depthstencil.c
C_SOURCES = \
$(COMMON_SOURCES) \
diff --git a/src/mesa/drivers/dri/i915tex/i830_context.h b/src/mesa/drivers/dri/i915tex/i830_context.h
index 3d754103c0a..9397fa45b52 100644
--- a/src/mesa/drivers/dri/i915tex/i830_context.h
+++ b/src/mesa/drivers/dri/i915tex/i830_context.h
@@ -114,10 +114,10 @@ struct i830_hw_state
struct intel_region *depth_region;
/* Regions aren't actually that appropriate here as the memory may
- * be from a PBO or FBO. Just use the buffer id. Will have to do
- * this for draw and depth for FBO's...
+ * be from a PBO or FBO. Will have to do this for draw and depth for
+ * FBO's...
*/
- struct _DriBufferObject *tex_buffer[I830_TEX_UNITS];
+ dri_bo *tex_buffer[I830_TEX_UNITS];
GLuint tex_offset[I830_TEX_UNITS];
GLuint emitted; /* I810_UPLOAD_* */
diff --git a/src/mesa/drivers/dri/i915tex/i830_metaops.c b/src/mesa/drivers/dri/i915tex/i830_metaops.c
index f76646d89db..13e4ab3aaca 100644
--- a/src/mesa/drivers/dri/i915tex/i830_metaops.c
+++ b/src/mesa/drivers/dri/i915tex/i830_metaops.c
@@ -238,7 +238,7 @@ set_texture_blend_replace(struct intel_context *intel)
*/
static GLboolean
set_tex_rect_source(struct intel_context *intel,
- struct _DriBufferObject *buffer,
+ dri_bo *buffer,
GLuint offset,
GLuint pitch, GLuint height, GLenum format, GLenum type)
{
diff --git a/src/mesa/drivers/dri/i915tex/i830_texstate.c b/src/mesa/drivers/dri/i915tex/i830_texstate.c
index 0d3f053226f..7613b9d2a6f 100644
--- a/src/mesa/drivers/dri/i915tex/i830_texstate.c
+++ b/src/mesa/drivers/dri/i915tex/i830_texstate.c
@@ -124,7 +124,7 @@ i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
/*We need to refcount these. */
if (i830->state.tex_buffer[unit] != NULL) {
- driBOUnReference(i830->state.tex_buffer[unit]);
+ dri_bo_unreference(i830->state.tex_buffer[unit]);
i830->state.tex_buffer[unit] = NULL;
}
@@ -155,8 +155,8 @@ i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
pitch = intelObj->pitchOverride;
} else {
- i830->state.tex_buffer[unit] = driBOReference(intelObj->mt->region->
- buffer);
+ dri_bo_reference(intelObj->mt->region->buffer);
+ i830->state.tex_buffer[unit] = intelObj->mt->region->buffer;
i830->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt,
0, intelObj->
firstLevel);
@@ -324,7 +324,7 @@ i830UpdateTextureState(struct intel_context *intel)
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), GL_FALSE);
if (i830->state.tex_buffer[i] != NULL) {
- driBOUnReference(i830->state.tex_buffer[i]);
+ dri_bo_unreference(i830->state.tex_buffer[i]);
i830->state.tex_buffer[i] = NULL;
}
break;
diff --git a/src/mesa/drivers/dri/i915tex/i830_vtbl.c b/src/mesa/drivers/dri/i915tex/i830_vtbl.c
index b2a1ba0ce34..eecff2729fd 100644
--- a/src/mesa/drivers/dri/i915tex/i830_vtbl.c
+++ b/src/mesa/drivers/dri/i915tex/i830_vtbl.c
@@ -456,7 +456,6 @@ i830_emit_state(struct intel_context *intel)
OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR1]);
OUT_RELOC(state->draw_region->buffer,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE,
state->draw_region->draw_offset);
if (state->depth_region) {
@@ -464,7 +463,6 @@ i830_emit_state(struct intel_context *intel)
OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR1]);
OUT_RELOC(state->depth_region->buffer,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE,
state->depth_region->draw_offset);
}
@@ -492,7 +490,6 @@ i830_emit_state(struct intel_context *intel)
if (state->tex_buffer[i]) {
OUT_RELOC(state->tex_buffer[i],
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_READ,
state->tex_offset[i] | TM0S0_USE_FENCE);
}
else if (state == &i830->meta) {
@@ -529,7 +526,7 @@ i830_destroy_context(struct intel_context *intel)
for (i = 0; i < I830_TEX_UNITS; i++) {
if (i830->state.tex_buffer[i] != NULL) {
- driBOUnReference(i830->state.tex_buffer[i]);
+ dri_bo_unreference(i830->state.tex_buffer[i]);
i830->state.tex_buffer[i] = NULL;
}
}
diff --git a/src/mesa/drivers/dri/i915tex/i915_context.h b/src/mesa/drivers/dri/i915tex/i915_context.h
index 3a41d66c148..0be2b3cc8b0 100644
--- a/src/mesa/drivers/dri/i915tex/i915_context.h
+++ b/src/mesa/drivers/dri/i915tex/i915_context.h
@@ -219,10 +219,10 @@ struct i915_hw_state
/* struct intel_region *tex_region[I915_TEX_UNITS]; */
/* Regions aren't actually that appropriate here as the memory may
- * be from a PBO or FBO. Just use the buffer id. Will have to do
- * this for draw and depth for FBO's...
+ * be from a PBO or FBO. Will have to do this for draw and depth for
+ * FBO's...
*/
- struct _DriBufferObject *tex_buffer[I915_TEX_UNITS];
+ dri_bo *tex_buffer[I915_TEX_UNITS];
GLuint tex_offset[I915_TEX_UNITS];
diff --git a/src/mesa/drivers/dri/i915tex/i915_metaops.c b/src/mesa/drivers/dri/i915tex/i915_metaops.c
index 397ff75b6f1..a739bd65811 100644
--- a/src/mesa/drivers/dri/i915tex/i915_metaops.c
+++ b/src/mesa/drivers/dri/i915tex/i915_metaops.c
@@ -326,7 +326,7 @@ meta_texture_blend_replace(struct intel_context *intel)
*/
static GLboolean
meta_tex_rect_source(struct intel_context *intel,
- struct _DriBufferObject *buffer,
+ dri_bo *buffer,
GLuint offset,
GLuint pitch, GLuint height, GLenum format, GLenum type)
{
diff --git a/src/mesa/drivers/dri/i915tex/i915_texstate.c b/src/mesa/drivers/dri/i915tex/i915_texstate.c
index 3d68187cf88..09684e87b4e 100644
--- a/src/mesa/drivers/dri/i915tex/i915_texstate.c
+++ b/src/mesa/drivers/dri/i915tex/i915_texstate.c
@@ -129,7 +129,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
/*We need to refcount these. */
if (i915->state.tex_buffer[unit] != NULL) {
- driBOUnReference(i915->state.tex_buffer[unit]);
+ dri_bo_unreference(i915->state.tex_buffer[unit]);
i915->state.tex_buffer[unit] = NULL;
}
@@ -160,8 +160,8 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
pitch = intelObj->pitchOverride;
} else {
- i915->state.tex_buffer[unit] = driBOReference(intelObj->mt->region->
- buffer);
+ dri_bo_reference(intelObj->mt->region->buffer);
+ i915->state.tex_buffer[unit] = intelObj->mt->region->buffer;
i915->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt,
0, intelObj->
firstLevel);
@@ -343,7 +343,7 @@ i915UpdateTextureState(struct intel_context *intel)
I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), GL_FALSE);
if (i915->state.tex_buffer[i] != NULL) {
- driBOUnReference(i915->state.tex_buffer[i]);
+ dri_bo_unreference(i915->state.tex_buffer[i]);
i915->state.tex_buffer[i] = NULL;
}
diff --git a/src/mesa/drivers/dri/i915tex/i915_vtbl.c b/src/mesa/drivers/dri/i915tex/i915_vtbl.c
index 1d651a40d75..35757e17eb9 100644
--- a/src/mesa/drivers/dri/i915tex/i915_vtbl.c
+++ b/src/mesa/drivers/dri/i915tex/i915_vtbl.c
@@ -337,7 +337,6 @@ i915_emit_state(struct intel_context *intel)
OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]);
OUT_RELOC(state->draw_region->buffer,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE,
state->draw_region->draw_offset);
if (state->depth_region) {
@@ -345,7 +344,6 @@ i915_emit_state(struct intel_context *intel)
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]);
OUT_RELOC(state->depth_region->buffer,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE,
state->depth_region->draw_offset);
}
@@ -389,7 +387,6 @@ i915_emit_state(struct intel_context *intel)
if (state->tex_buffer[i]) {
OUT_RELOC(state->tex_buffer[i],
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_READ,
state->tex_offset[i]);
}
else if (state == &i915->meta) {
@@ -445,7 +442,7 @@ i915_destroy_context(struct intel_context *intel)
for (i = 0; i < I915_TEX_UNITS; i++) {
if (i915->state.tex_buffer[i] != NULL) {
- driBOUnReference(i915->state.tex_buffer[i]);
+ dri_bo_unreference(i915->state.tex_buffer[i]);
i915->state.tex_buffer[i] = NULL;
}
}
diff --git a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c
index c740c3d7f62..8ee48b5a689 100644
--- a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c
@@ -71,62 +71,31 @@
void
intel_batchbuffer_reset(struct intel_batchbuffer *batch)
{
+ struct intel_context *intel = batch->intel;
- int i;
-
- /*
- * Get a new, free batchbuffer.
- */
-
- batch->size = batch->intel->intelScreen->maxBatchSize;
- driBOData(batch->buffer, batch->size, NULL, 0);
-
- driBOResetList(&batch->list);
-
- /*
- * Unreference buffers previously on the relocation list.
- */
-
- for (i = 0; i < batch->nr_relocs; i++) {
- struct buffer_reloc *r = &batch->reloc[i];
- driBOUnReference(r->buf);
+ if (batch->buf != NULL) {
+ dri_bo_unreference(batch->buf);
+ batch->buf = NULL;
}
- batch->list_count = 0;
- batch->nr_relocs = 0;
- batch->flags = 0;
-
- /*
- * We don't refcount the batchbuffer itself since we can't destroy it
- * while it's on the list.
- */
-
-
- driBOAddListItem(&batch->list, batch->buffer,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_EXE);
-
-
- batch->map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0);
+ batch->buf = dri_bo_alloc(intel->intelScreen->bufmgr, "batchbuffer",
+ intel->intelScreen->maxBatchSize, 4096,
+ DRM_BO_FLAG_MEM_TT);
+ dri_bo_map(batch->buf, GL_TRUE);
+ batch->map = batch->buf->virtual;
+ batch->size = intel->intelScreen->maxBatchSize;
batch->ptr = batch->map;
}
-/*======================================================================
- * Public functions
- */
struct intel_batchbuffer *
intel_batchbuffer_alloc(struct intel_context *intel)
{
struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1);
batch->intel = intel;
-
- driGenBuffers(intel->intelScreen->batchPool, "batchbuffer", 1,
- &batch->buffer, 4096,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE, 0);
batch->last_fence = NULL;
- driBOCreateList(20, &batch->list);
intel_batchbuffer_reset(batch);
+
return batch;
}
@@ -134,20 +103,27 @@ void
intel_batchbuffer_free(struct intel_batchbuffer *batch)
{
if (batch->last_fence) {
- driFenceFinish(batch->last_fence,
- DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, GL_FALSE);
- driFenceUnReference(batch->last_fence);
+ dri_fence_wait(batch->last_fence);
+ dri_fence_unreference(batch->last_fence);
batch->last_fence = NULL;
}
if (batch->map) {
- driBOUnmap(batch->buffer);
+ dri_bo_unmap(batch->buf);
batch->map = NULL;
}
- driBOUnReference(batch->buffer);
- batch->buffer = NULL;
+ dri_bo_unreference(batch->buf);
+ batch->buf = NULL;
free(batch);
}
+static int
+relocation_sort(const void *a_in, const void *b_in) {
+ const struct buffer_reloc *a = a_in, *b = b_in;
+
+ return (intptr_t)a->buf < (intptr_t)b->buf ? -1 : 1;
+}
+
+
/* TODO: Push this whole function into bufmgr.
*/
static void
@@ -158,30 +134,68 @@ do_flush_locked(struct intel_batchbuffer *batch,
GLuint *ptr;
GLuint i;
struct intel_context *intel = batch->intel;
- unsigned fenceFlags;
- struct _DriFenceObject *fo;
+ dri_fence *fo;
+ GLboolean performed_rendering = GL_FALSE;
- driBOValidateList(batch->intel->driFd, &batch->list);
+ assert(batch->buf->virtual != NULL);
+ ptr = batch->buf->virtual;
- /* Apply the relocations. This nasty map indicates to me that the
- * whole task should be done internally by the memory manager, and
- * that dma buffers probably need to be pinned within agp space.
+ /* 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.
*/
- ptr = (GLuint *) driBOMap(batch->buffer, DRM_BO_FLAG_WRITE,
- DRM_BO_HINT_ALLOW_UNFENCED_MAP);
-
+ qsort(batch->reloc, batch->nr_relocs, sizeof(batch->reloc[0]),
+ relocation_sort);
+ /* Perform the necessary validations of buffers, and enter the relocations
+ * in the batchbuffer.
+ */
for (i = 0; i < batch->nr_relocs; i++) {
struct buffer_reloc *r = &batch->reloc[i];
- ptr[r->offset / 4] = driBOOffset(r->buf) + r->delta;
+ if (r->validate_flags & DRM_BO_FLAG_WRITE)
+ 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 || batch->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 < batch->nr_relocs; j++) {
+ if (batch->reloc[j].buf != r->buf)
+ break;
+ validate_flags |= batch->reloc[j].validate_flags;
+ }
+
+ /* Validate. If we fail, fence to clear the unfenced list and bail
+ * out.
+ */
+ ret = dri_bo_validate(r->buf, validate_flags);
+ if (ret != 0) {
+ dri_bo_unmap(batch->buf);
+ fo = dri_fence_validated(intel->intelScreen->bufmgr,
+ "batchbuffer failure fence", GL_TRUE);
+ dri_fence_unreference(fo);
+ goto done;
+ }
+ }
+ ptr[r->offset / 4] = r->buf->offset + r->delta;
+ dri_bo_unreference(r->buf);
}
- if (INTEL_DEBUG & DEBUG_BATCH)
- intel_decode(ptr, used / 4, 0);
-
- driBOUnmap(batch->buffer);
+ dri_bo_unmap(batch->buf);
batch->map = NULL;
+ batch->ptr = NULL;
+
+ dri_bo_validate(batch->buf, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE);
+
+ batch->list_count = 0;
+ batch->nr_relocs = 0;
+ batch->flags = 0;
/* Throw away non-effective packets. Won't work once we have
* hardware contexts which would preserve statechanges beyond a
@@ -190,55 +204,49 @@ do_flush_locked(struct intel_batchbuffer *batch,
if (!(intel->numClipRects == 0 && !ignore_cliprects)) {
intel_batch_ioctl(batch->intel,
- driBOOffset(batch->buffer),
+ batch->buf->offset,
used, ignore_cliprects, allow_unlock);
}
-
- /*
- * Kernel fencing. The flags tells the kernel that we've
- * programmed an MI_FLUSH.
+ /* Associate a fence with the validated buffers, and note that we included
+ * a flush at the end.
*/
-
- fenceFlags = DRM_I915_FENCE_FLAG_FLUSHED;
- fo = driFenceBuffers(batch->intel->driFd,
- "Batch fence", fenceFlags);
-
- /*
- * User space fencing.
- */
-
- driBOFence(batch->buffer, fo);
-
- if (driFenceType(fo) == DRM_FENCE_TYPE_EXE) {
+ fo = dri_fence_validated(intel->intelScreen->bufmgr,
+ "Batch fence", GL_TRUE);
- /*
- * Oops. We only validated a batch buffer. This means we
- * didn't do any proper rendering. Discard this fence object.
- */
-
- driFenceUnReference(fo);
- } else {
- driFenceUnReference(batch->last_fence);
+ if (performed_rendering) {
+ dri_fence_unreference(batch->last_fence);
batch->last_fence = fo;
- for (i = 0; i < batch->nr_relocs; i++) {
- struct buffer_reloc *r = &batch->reloc[i];
- driBOFence(r->buf, fo);
- }
+ } else {
+ /* If we didn't validate any buffers for writing by the card, we don't
+ * need to track the fence for glFinish().
+ */
+ dri_fence_unreference(fo);
}
if (intel->numClipRects == 0 && !ignore_cliprects) {
if (allow_unlock) {
+ /* If we are not doing any actual user-visible rendering,
+ * do a sched_yield to keep the app from pegging the cpu while
+ * achieving nothing.
+ */
UNLOCK_HARDWARE(intel);
sched_yield();
LOCK_HARDWARE(intel);
}
intel->vtbl.lost_hardware(intel);
}
+
+done:
+ if (INTEL_DEBUG & DEBUG_BATCH) {
+ dri_bo_map(batch->buf, GL_FALSE);
+ intel_decode(ptr, used / 4, batch->buf->offset);
+ dri_bo_unmap(batch->buf);
+ }
}
-struct _DriFenceObject *
+void
intel_batchbuffer_flush(struct intel_batchbuffer *batch)
{
struct intel_context *intel = batch->intel;
@@ -246,7 +254,7 @@ intel_batchbuffer_flush(struct intel_batchbuffer *batch)
GLboolean was_locked = intel->locked;
if (used == 0)
- return batch->last_fence;
+ return;
/* Add the MI_BATCH_BUFFER_END. Always add an MI_FLUSH - this is a
* performance drain that we would like to avoid.
@@ -263,10 +271,6 @@ intel_batchbuffer_flush(struct intel_batchbuffer *batch)
used += 8;
}
- driBOUnmap(batch->buffer);
- batch->ptr = NULL;
- batch->map = NULL;
-
/* TODO: Just pass the relocation list and dma buffer up to the
* kernel.
*/
@@ -282,16 +286,14 @@ intel_batchbuffer_flush(struct intel_batchbuffer *batch)
/* Reset the buffer:
*/
intel_batchbuffer_reset(batch);
- return batch->last_fence;
}
void
intel_batchbuffer_finish(struct intel_batchbuffer *batch)
{
- struct _DriFenceObject *fence = intel_batchbuffer_flush(batch);
- driFenceReference(fence);
- driFenceFinish(fence, 3, GL_FALSE);
- driFenceUnReference(fence);
+ intel_batchbuffer_flush(batch);
+ if (batch->last_fence != NULL)
+ dri_fence_wait(batch->last_fence);
}
@@ -299,20 +301,18 @@ intel_batchbuffer_finish(struct intel_batchbuffer *batch)
*/
GLboolean
intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
- struct _DriBufferObject *buffer,
- GLuint flags, GLuint mask, GLuint delta)
+ dri_bo *buffer,
+ GLuint flags, GLuint delta)
{
- assert(batch->nr_relocs < MAX_RELOCS);
+ struct buffer_reloc *r = &batch->reloc[batch->nr_relocs++];
- driBOAddListItem(&batch->list, buffer, flags, mask);
+ assert(batch->nr_relocs <= MAX_RELOCS);
- {
- struct buffer_reloc *r = &batch->reloc[batch->nr_relocs++];
- driBOReference(buffer);
- r->buf = buffer;
- r->offset = batch->ptr - batch->map;
- r->delta = delta;
- }
+ dri_bo_reference(buffer);
+ r->buf = buffer;
+ r->offset = batch->ptr - batch->map;
+ r->delta = delta;
+ r->validate_flags = flags;
batch->ptr += 4;
return GL_TRUE;
diff --git a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.h b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.h
index 212f1301012..850a91e1c91 100644
--- a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.h
+++ b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.h
@@ -16,18 +16,18 @@ struct intel_context;
struct buffer_reloc
{
- struct _DriBufferObject *buf;
+ dri_bo *buf;
GLuint offset;
GLuint delta; /* not needed? */
+ GLuint validate_flags;
};
struct intel_batchbuffer
{
- struct bufmgr *bm;
struct intel_context *intel;
- struct _DriBufferObject *buffer;
- struct _DriFenceObject *last_fence;
+ dri_bo *buf;
+ dri_fence *last_fence;
GLuint flags;
drmBOList list;
@@ -48,8 +48,7 @@ void intel_batchbuffer_free(struct intel_batchbuffer *batch);
void intel_batchbuffer_finish(struct intel_batchbuffer *batch);
-struct _DriFenceObject *intel_batchbuffer_flush(struct intel_batchbuffer
- *batch);
+void intel_batchbuffer_flush(struct intel_batchbuffer *batch);
void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
@@ -65,9 +64,8 @@ void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
GLuint bytes);
GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
- struct _DriBufferObject *buffer,
- GLuint flags,
- GLuint mask, GLuint offset);
+ dri_bo *buffer,
+ GLuint flags, GLuint offset);
/* Inline functions - might actually be better off with these
* non-inlined. Certainly better off switching all command packets to
@@ -113,9 +111,9 @@ intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d)
-#define OUT_RELOC(buf,flags,mask,delta) do { \
- assert((delta) >= 0); \
- intel_batchbuffer_emit_reloc(intel->batch, buf, flags, mask, delta); \
+#define OUT_RELOC(buf, flags, delta) do { \
+ assert((delta) >= 0); \
+ intel_batchbuffer_emit_reloc(intel->batch, buf, flags, delta); \
} while (0)
#define ADVANCE_BATCH() do { } while(0)
diff --git a/src/mesa/drivers/dri/i915tex/intel_batchpool.c b/src/mesa/drivers/dri/i915tex/intel_batchpool.c
deleted file mode 100644
index 2503b8a62a1..00000000000
--- a/src/mesa/drivers/dri/i915tex/intel_batchpool.c
+++ /dev/null
@@ -1,418 +0,0 @@
-/**************************************************************************
- *
- * 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>
- */
-
-#include <xf86drm.h>
-#include <stdlib.h>
-#include <errno.h>
-#include "imports.h"
-#include "glthread.h"
-#include "dri_bufpool.h"
-#include "dri_bufmgr.h"
-#include "intel_screen.h"
-
-typedef struct
-{
- drmMMListHead head;
- struct _BPool *parent;
- struct _DriFenceObject *fence;
- unsigned long start;
- int unfenced;
- int mapped;
-} BBuf;
-
-typedef struct _BPool
-{
- _glthread_Mutex mutex;
- unsigned long bufSize;
- unsigned poolSize;
- unsigned numFree;
- unsigned numTot;
- unsigned numDelayed;
- unsigned checkDelayed;
- drmMMListHead free;
- drmMMListHead delayed;
- drmMMListHead head;
- drmBO kernelBO;
- void *virtual;
- BBuf *bufs;
-} BPool;
-
-
-static BPool *
-createBPool(int fd, unsigned long bufSize, unsigned numBufs, unsigned flags,
- unsigned checkDelayed)
-{
- BPool *p = (BPool *) malloc(sizeof(*p));
- BBuf *buf;
- int i;
-
- if (!p)
- return NULL;
-
- p->bufs = (BBuf *) malloc(numBufs * sizeof(*p->bufs));
- if (!p->bufs) {
- free(p);
- return NULL;
- }
-
- DRMINITLISTHEAD(&p->free);
- DRMINITLISTHEAD(&p->head);
- DRMINITLISTHEAD(&p->delayed);
-
- p->numTot = numBufs;
- p->numFree = numBufs;
- p->bufSize = bufSize;
- p->numDelayed = 0;
- p->checkDelayed = checkDelayed;
-
- _glthread_INIT_MUTEX(p->mutex);
-
- if (drmBOCreate(fd, 0, numBufs * bufSize, 0, NULL, drm_bo_type_dc,
- flags, DRM_BO_HINT_DONT_FENCE, &p->kernelBO)) {
- free(p->bufs);
- free(p);
- return NULL;
- }
- if (drmBOMap(fd, &p->kernelBO, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0,
- &p->virtual)) {
- drmBODestroy(fd, &p->kernelBO);
- free(p->bufs);
- free(p);
- return NULL;
- }
-
- /*
- * We unmap the buffer so that we can validate it later. Note that this is
- * just a synchronizing operation. The buffer will have a virtual mapping
- * until it is destroyed.
- */
-
- drmBOUnmap(fd, &p->kernelBO);
-
- buf = p->bufs;
- for (i = 0; i < numBufs; ++i) {
- buf->parent = p;
- buf->fence = NULL;
- buf->start = i * bufSize;
- buf->mapped = 0;
- buf->unfenced = 0;
- DRMLISTADDTAIL(&buf->head, &p->free);
- buf++;
- }
-
- return p;
-}
-
-
-static void
-pool_checkFree(BPool * p, int wait)
-{
- drmMMListHead *list, *prev;
- BBuf *buf;
- int signaled = 0;
- int i;
-
- list = p->delayed.next;
-
- if (p->numDelayed > 3) {
- for (i = 0; i < p->numDelayed; i += 3) {
- list = list->next;
- }
- }
-
- prev = list->prev;
- for (; list != &p->delayed; list = prev, prev = list->prev) {
-
- buf = DRMLISTENTRY(BBuf, list, head);
-
- if (!signaled) {
- if (wait) {
- driFenceFinish(buf->fence, DRM_FENCE_TYPE_EXE, 1);
- signaled = 1;
- }
- else {
- signaled = driFenceSignaled(buf->fence, DRM_FENCE_TYPE_EXE);
- }
- }
-
- if (!signaled)
- break;
-
- driFenceUnReference(buf->fence);
- buf->fence = NULL;
- DRMLISTDEL(list);
- p->numDelayed--;
- DRMLISTADD(list, &p->free);
- p->numFree++;
- }
-}
-
-static void *
-pool_create(struct _DriBufferPool *pool,
- unsigned long size, unsigned flags, unsigned hint,
- unsigned alignment)
-{
- BPool *p = (BPool *) pool->data;
-
- drmMMListHead *item;
-
- if (alignment && (alignment != 4096))
- return NULL;
-
- _glthread_LOCK_MUTEX(p->mutex);
-
- if (p->numFree == 0)
- pool_checkFree(p, GL_TRUE);
-
- if (p->numFree == 0) {
- fprintf(stderr, "Out of fixed size buffer objects\n");
- BM_CKFATAL(-ENOMEM);
- }
-
- item = p->free.next;
-
- if (item == &p->free) {
- fprintf(stderr, "Fixed size buffer pool corruption\n");
- }
-
- DRMLISTDEL(item);
- --p->numFree;
-
- _glthread_UNLOCK_MUTEX(p->mutex);
- return (void *) DRMLISTENTRY(BBuf, item, head);
-}
-
-
-static int
-pool_destroy(struct _DriBufferPool *pool, void *private)
-{
- BBuf *buf = (BBuf *) private;
- BPool *p = buf->parent;
-
- _glthread_LOCK_MUTEX(p->mutex);
-
- if (buf->fence) {
- DRMLISTADDTAIL(&buf->head, &p->delayed);
- p->numDelayed++;
- }
- else {
- buf->unfenced = 0;
- DRMLISTADD(&buf->head, &p->free);
- p->numFree++;
- }
-
- if ((p->numDelayed % p->checkDelayed) == 0)
- pool_checkFree(p, 0);
-
- _glthread_UNLOCK_MUTEX(p->mutex);
- return 0;
-}
-
-
-static int
-pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,
- int hint, void **virtual)
-{
-
- BBuf *buf = (BBuf *) private;
- BPool *p = buf->parent;
-
- _glthread_LOCK_MUTEX(p->mutex);
-
- /*
- * Currently Mesa doesn't have any condition variables to resolve this
- * cleanly in a multithreading environment.
- * We bail out instead.
- */
-
- if (buf->mapped) {
- fprintf(stderr, "Trying to map already mapped buffer object\n");
- BM_CKFATAL(-EINVAL);
- }
-
-#if 0
- if (buf->unfenced && !(hint & DRM_BO_HINT_ALLOW_UNFENCED_MAP)) {
- fprintf(stderr, "Trying to map an unfenced buffer object 0x%08x"
- " 0x%08x %d\n", hint, flags, buf->start);
- BM_CKFATAL(-EINVAL);
- }
-
-#endif
-
- if (buf->fence) {
- _glthread_UNLOCK_MUTEX(p->mutex);
- return -EBUSY;
- }
-
- buf->mapped = GL_TRUE;
- *virtual = (unsigned char *) p->virtual + buf->start;
- _glthread_UNLOCK_MUTEX(p->mutex);
- return 0;
-}
-
-static int
-pool_waitIdle(struct _DriBufferPool *pool, void *private, int lazy)
-{
- BBuf *buf = (BBuf *) private;
- driFenceFinish(buf->fence, 0, lazy);
- return 0;
-}
-
-static int
-pool_unmap(struct _DriBufferPool *pool, void *private)
-{
- BBuf *buf = (BBuf *) private;
-
- buf->mapped = 0;
- return 0;
-}
-
-static unsigned long
-pool_offset(struct _DriBufferPool *pool, void *private)
-{
- BBuf *buf = (BBuf *) private;
- BPool *p = buf->parent;
-
- return p->kernelBO.offset + buf->start;
-}
-
-static unsigned
-pool_flags(struct _DriBufferPool *pool, void *private)
-{
- BPool *p = (BPool *) pool->data;
-
- return p->kernelBO.flags;
-}
-
-static unsigned long
-pool_size(struct _DriBufferPool *pool, void *private)
-{
- BPool *p = (BPool *) pool->data;
-
- return p->bufSize;
-}
-
-
-static int
-pool_fence(struct _DriBufferPool *pool, void *private,
- struct _DriFenceObject *fence)
-{
- BBuf *buf = (BBuf *) private;
- BPool *p = buf->parent;
-
- _glthread_LOCK_MUTEX(p->mutex);
- if (buf->fence) {
- driFenceUnReference(buf->fence);
- }
- buf->fence = fence;
- buf->unfenced = 0;
- driFenceReference(buf->fence);
- _glthread_UNLOCK_MUTEX(p->mutex);
-
- return 0;
-}
-
-static drmBO *
-pool_kernel(struct _DriBufferPool *pool, void *private)
-{
- BBuf *buf = (BBuf *) private;
- BPool *p = buf->parent;
-
- return &p->kernelBO;
-}
-
-static int
-pool_validate(struct _DriBufferPool *pool, void *private)
-{
- BBuf *buf = (BBuf *) private;
- BPool *p = buf->parent;
- _glthread_LOCK_MUTEX(p->mutex);
- buf->unfenced = GL_TRUE;
- _glthread_UNLOCK_MUTEX(p->mutex);
- return 0;
-}
-
-static void
-pool_takedown(struct _DriBufferPool *pool)
-{
- BPool *p = (BPool *) pool->data;
-
- /*
- * Wait on outstanding fences.
- */
-
- _glthread_LOCK_MUTEX(p->mutex);
- while ((p->numFree < p->numTot) && p->numDelayed) {
- _glthread_UNLOCK_MUTEX(p->mutex);
- sched_yield();
- pool_checkFree(p, GL_TRUE);
- _glthread_LOCK_MUTEX(p->mutex);
- }
-
- drmBODestroy(pool->fd, &p->kernelBO);
- free(p->bufs);
- _glthread_UNLOCK_MUTEX(p->mutex);
- free(p);
- free(pool);
-}
-
-
-struct _DriBufferPool *
-driBatchPoolInit(int fd, unsigned flags,
- unsigned long bufSize,
- unsigned numBufs, unsigned checkDelayed)
-{
- struct _DriBufferPool *pool;
-
- pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
- if (!pool)
- return NULL;
-
- pool->data = createBPool(fd, bufSize, numBufs, flags, checkDelayed);
- if (!pool->data)
- return NULL;
-
- pool->fd = fd;
- pool->map = &pool_map;
- pool->unmap = &pool_unmap;
- pool->destroy = &pool_destroy;
- pool->offset = &pool_offset;
- pool->flags = &pool_flags;
- pool->size = &pool_size;
- pool->create = &pool_create;
- pool->fence = &pool_fence;
- pool->kernel = &pool_kernel;
- pool->validate = &pool_validate;
- pool->waitIdle = &pool_waitIdle;
- pool->setstatic = NULL;
- pool->takeDown = &pool_takedown;
- return pool;
-}
diff --git a/src/mesa/drivers/dri/i915tex/intel_blit.c b/src/mesa/drivers/dri/i915tex/intel_blit.c
index dbe4ba2ac5e..5d97f08434a 100644
--- a/src/mesa/drivers/dri/i915tex/intel_blit.c
+++ b/src/mesa/drivers/dri/i915tex/intel_blit.c
@@ -67,8 +67,8 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
intelScreen = intel->intelScreen;
if (intel->last_swap_fence) {
- driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
- driFenceUnReference(intel->last_swap_fence);
+ dri_fence_wait(intel->last_swap_fence);
+ dri_fence_unreference(intel->last_swap_fence);
intel->last_swap_fence = NULL;
}
intel->last_swap_fence = intel->first_swap_fence;
@@ -140,19 +140,20 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
OUT_BATCH((pbox->y2 << 16) | pbox->x2);
OUT_RELOC(frontRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
+ 0);
OUT_BATCH((pbox->y1 << 16) | pbox->x1);
OUT_BATCH(BR13 & 0xffff);
OUT_RELOC(backRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
+ 0);
ADVANCE_BATCH();
}
if (intel->first_swap_fence)
- driFenceUnReference(intel->first_swap_fence);
- intel->first_swap_fence = intel_batchbuffer_flush(intel->batch);
- driFenceReference(intel->first_swap_fence);
+ dri_fence_unreference(intel->first_swap_fence);
+ intel_batchbuffer_flush(intel->batch);
+ intel->first_swap_fence = intel->batch->last_fence;
+ dri_fence_reference(intel->first_swap_fence);
}
UNLOCK_HARDWARE(intel);
@@ -165,7 +166,7 @@ void
intelEmitFillBlit(struct intel_context *intel,
GLuint cpp,
GLshort dst_pitch,
- struct _DriBufferObject *dst_buffer,
+ dri_bo *dst_buffer,
GLuint dst_offset,
GLshort x, GLshort y, GLshort w, GLshort h, GLuint color)
{
@@ -199,8 +200,7 @@ intelEmitFillBlit(struct intel_context *intel,
OUT_BATCH(BR13);
OUT_BATCH((y << 16) | x);
OUT_BATCH(((y + h) << 16) | (x + w));
- OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset);
+ OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, dst_offset);
OUT_BATCH(color);
ADVANCE_BATCH();
}
@@ -236,10 +236,10 @@ void
intelEmitCopyBlit(struct intel_context *intel,
GLuint cpp,
GLshort src_pitch,
- struct _DriBufferObject *src_buffer,
+ dri_bo *src_buffer,
GLuint src_offset,
GLshort dst_pitch,
- struct _DriBufferObject *dst_buffer,
+ dri_bo *dst_buffer,
GLuint dst_offset,
GLshort src_x, GLshort src_y,
GLshort dst_x, GLshort dst_y,
@@ -297,12 +297,10 @@ intelEmitCopyBlit(struct intel_context *intel,
OUT_BATCH(BR13);
OUT_BATCH((dst_y << 16) | dst_x);
OUT_BATCH((dst_y2 << 16) | dst_x2);
- OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset);
+ OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, dst_offset);
OUT_BATCH((src_y << 16) | src_x);
OUT_BATCH(((GLint) src_pitch & 0xffff));
- OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, src_offset);
+ OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, src_offset);
ADVANCE_BATCH();
}
else {
@@ -312,12 +310,10 @@ intelEmitCopyBlit(struct intel_context *intel,
OUT_BATCH((0 << 16) | dst_x);
OUT_BATCH((h << 16) | dst_x2);
OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE,
dst_offset + dst_y * dst_pitch);
OUT_BATCH((0 << 16) | src_x);
OUT_BATCH(((GLint) src_pitch & 0xffff));
OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_READ,
src_offset + src_y * src_pitch);
ADVANCE_BATCH();
}
@@ -420,7 +416,7 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask)
/* OK, clear this renderbuffer */
struct intel_region *irb_region =
intel_get_rb_region(fb, buf);
- struct _DriBufferObject *write_buffer =
+ dri_bo *write_buffer =
intel_region_buffer(intel->intelScreen, irb_region,
all ? INTEL_WRITE_FULL :
INTEL_WRITE_PART);
@@ -483,7 +479,6 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask)
OUT_BATCH((b.y1 << 16) | b.x1);
OUT_BATCH((b.y2 << 16) | b.x2);
OUT_RELOC(write_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
- DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE,
irb_region->draw_offset);
OUT_BATCH(clearVal);
ADVANCE_BATCH();
diff --git a/src/mesa/drivers/dri/i915tex/intel_blit.h b/src/mesa/drivers/dri/i915tex/intel_blit.h
index e7bc280f58a..a66af863591 100644
--- a/src/mesa/drivers/dri/i915tex/intel_blit.h
+++ b/src/mesa/drivers/dri/i915tex/intel_blit.h
@@ -40,10 +40,10 @@ extern void intelClearWithBlit(GLcontext * ctx, GLbitfield mask);
extern void intelEmitCopyBlit(struct intel_context *intel,
GLuint cpp,
GLshort src_pitch,
- struct _DriBufferObject *src_buffer,
+ dri_bo *src_buffer,
GLuint src_offset,
GLshort dst_pitch,
- struct _DriBufferObject *dst_buffer,
+ dri_bo *dst_buffer,
GLuint dst_offset,
GLshort srcx, GLshort srcy,
GLshort dstx, GLshort dsty,
@@ -53,7 +53,7 @@ extern void intelEmitCopyBlit(struct intel_context *intel,
extern void intelEmitFillBlit(struct intel_context *intel,
GLuint cpp,
GLshort dst_pitch,
- struct _DriBufferObject *dst_buffer,
+ dri_bo *dst_buffer,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h, GLuint color);
diff --git a/src/mesa/drivers/dri/i915tex/intel_buffer_objects.c b/src/mesa/drivers/dri/i915tex/intel_buffer_objects.c
index 91c45ad95be..3c73c402d96 100644
--- a/src/mesa/drivers/dri/i915tex/intel_buffer_objects.c
+++ b/src/mesa/drivers/dri/i915tex/intel_buffer_objects.c
@@ -35,6 +35,16 @@
#include "intel_regions.h"
#include "dri_bufmgr.h"
+/** Allocates a new dri_bo to store the data for the buffer object. */
+static void
+intel_bufferobj_alloc_buffer(struct intel_context *intel,
+ struct intel_buffer_object *intel_obj)
+{
+ intel_obj->buffer = dri_bo_alloc(intel->intelScreen->bufmgr, "bufferobj",
+ intel_obj->Base.Size, 64,
+ DRM_BO_FLAG_MEM_TT);
+}
+
/**
* There is some duplication between mesa's bufferobjects and our
* bufmgr buffers. Both have an integer handle and a hashtable to
@@ -44,21 +54,15 @@
static struct gl_buffer_object *
intel_bufferobj_alloc(GLcontext * ctx, GLuint name, GLenum target)
{
- struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *obj = CALLOC_STRUCT(intel_buffer_object);
_mesa_initialize_buffer_object(&obj->Base, name, target);
- driGenBuffers(intel->intelScreen->regionPool,
- "bufferobj", 1, &obj->buffer, 64,
- DRM_BO_FLAG_MEM_LOCAL |
- DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
- 0);
+ obj->buffer = NULL;
return &obj->Base;
}
-
/* Break the COW tie to the region. The region gets to keep the data.
*/
void
@@ -68,17 +72,9 @@ intel_bufferobj_release_region(struct intel_context *intel,
assert(intel_obj->region->buffer == intel_obj->buffer);
intel_obj->region->pbo = NULL;
intel_obj->region = NULL;
- driBOUnReference(intel_obj->buffer);
- intel_obj->buffer = NULL;
- /* This leads to a large number of buffer deletion/creation events.
- * Currently the drm doesn't like that:
- */
- driGenBuffers(intel->intelScreen->regionPool,
- "buffer object", 1, &intel_obj->buffer, 64, 0, 0);
- LOCK_HARDWARE(intel);
- driBOData(intel_obj->buffer, intel_obj->Base.Size, NULL, 0);
- UNLOCK_HARDWARE(intel);
+ dri_bo_unreference(intel_obj->buffer);
+ intel_obj->buffer = NULL;
}
/* Break the COW tie to the region. Both the pbo and the region end
@@ -109,7 +105,7 @@ intel_bufferobj_free(GLcontext * ctx, struct gl_buffer_object *obj)
intel_bufferobj_release_region(intel, intel_obj);
}
else if (intel_obj->buffer) {
- driDeleteBuffers(1, &intel_obj->buffer);
+ dri_bo_unreference(intel_obj->buffer);
}
_mesa_free(intel_obj);
@@ -139,9 +135,15 @@ intel_bufferobj_data(GLcontext * ctx,
if (intel_obj->region)
intel_bufferobj_release_region(intel, intel_obj);
- LOCK_HARDWARE(intel);
- driBOData(intel_obj->buffer, size, data, 0);
- UNLOCK_HARDWARE(intel);
+ if (intel_obj->buffer != NULL && intel_obj->buffer->size != size) {
+ dri_bo_unreference(intel_obj->buffer);
+ intel_obj->buffer = NULL;
+ }
+
+ intel_bufferobj_alloc_buffer(intel, intel_obj);
+
+ if (data != NULL)
+ dri_bo_subdata(intel_obj->buffer, 0, size, data);
}
@@ -166,7 +168,7 @@ intel_bufferobj_subdata(GLcontext * ctx,
if (intel_obj->region)
intel_bufferobj_cow(intel, intel_obj);
- driBOSubData(intel_obj->buffer, offset, size, data);
+ dri_bo_subdata(intel_obj->buffer, offset, size, data);
}
@@ -183,7 +185,7 @@ intel_bufferobj_get_subdata(GLcontext * ctx,
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
- driBOGetSubData(intel_obj->buffer, offset, size, data);
+ dri_bo_get_subdata(intel_obj->buffer, offset, size, data);
}
@@ -206,8 +208,13 @@ intel_bufferobj_map(GLcontext * ctx,
if (intel_obj->region)
intel_bufferobj_cow(intel, intel_obj);
- obj->Pointer = driBOMap(intel_obj->buffer,
- DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
+ if (intel_obj->buffer == NULL) {
+ obj->Pointer = NULL;
+ return NULL;
+ }
+
+ dri_bo_map(intel_obj->buffer, GL_TRUE);
+ obj->Pointer = intel_obj->buffer->virtual;
return obj->Pointer;
}
@@ -222,21 +229,25 @@ intel_bufferobj_unmap(GLcontext * ctx,
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
- assert(obj->Pointer);
- driBOUnmap(intel_obj->buffer);
- obj->Pointer = NULL;
+ if (intel_obj->buffer != NULL) {
+ assert(obj->Pointer);
+ dri_bo_unmap(intel_obj->buffer);
+ obj->Pointer = NULL;
+ }
return GL_TRUE;
}
-struct _DriBufferObject *
+dri_bo *
intel_bufferobj_buffer(struct intel_context *intel,
struct intel_buffer_object *intel_obj, GLuint flag)
{
if (intel_obj->region) {
if (flag == INTEL_WRITE_PART)
intel_bufferobj_cow(intel, intel_obj);
- else if (flag == INTEL_WRITE_FULL)
+ else if (flag == INTEL_WRITE_FULL) {
intel_bufferobj_release_region(intel, intel_obj);
+ intel_bufferobj_alloc_buffer(intel, intel_obj);
+ }
}
return intel_obj->buffer;
diff --git a/src/mesa/drivers/dri/i915tex/intel_buffer_objects.h b/src/mesa/drivers/dri/i915tex/intel_buffer_objects.h
index afe9b2f7cf2..db579a8ae40 100644
--- a/src/mesa/drivers/dri/i915tex/intel_buffer_objects.h
+++ b/src/mesa/drivers/dri/i915tex/intel_buffer_objects.h
@@ -41,7 +41,7 @@ struct gl_buffer_object;
struct intel_buffer_object
{
struct gl_buffer_object Base;
- struct _DriBufferObject *buffer; /* the low-level buffer manager's buffer handle */
+ dri_bo *buffer; /* the low-level buffer manager's buffer handle */
struct intel_region *region; /* Is there a zero-copy texture
associated with this (pixel)
@@ -51,9 +51,9 @@ struct intel_buffer_object
/* Get the bm buffer associated with a GL bufferobject:
*/
-struct _DriBufferObject *intel_bufferobj_buffer(struct intel_context *intel,
- struct intel_buffer_object
- *obj, GLuint flag);
+dri_bo *intel_bufferobj_buffer(struct intel_context *intel,
+ struct intel_buffer_object
+ *obj, GLuint flag);
/* Hook the bufferobject implementation into mesa:
*/
diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c
index 40ea7564126..16fbe38e647 100644
--- a/src/mesa/drivers/dri/i915tex/intel_context.c
+++ b/src/mesa/drivers/dri/i915tex/intel_context.c
@@ -59,6 +59,7 @@
#include "intel_regions.h"
#include "intel_buffer_objects.h"
#include "intel_fbo.h"
+#include "intel_decode.h"
#include "drirenderbuffer.h"
#include "vblank.h"
@@ -176,7 +177,6 @@ const struct dri_extension card_extensions[] = {
{"GL_ARB_texture_mirrored_repeat", NULL},
{"GL_ARB_texture_rectangle", NULL},
{"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
- {"GL_ARB_pixel_buffer_object", NULL},
{"GL_ARB_vertex_program", GL_ARB_vertex_program_functions},
{"GL_ARB_window_pos", GL_ARB_window_pos_functions},
{"GL_EXT_blend_color", GL_EXT_blend_color_functions},
@@ -187,7 +187,6 @@ const struct dri_extension card_extensions[] = {
{"GL_EXT_blend_subtract", NULL},
{"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions},
{"GL_EXT_fog_coord", GL_EXT_fog_coord_functions},
- {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions},
{"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions},
#if 1 /* XXX FBO temporary? */
{"GL_EXT_packed_depth_stencil", NULL},
@@ -210,6 +209,12 @@ const struct dri_extension card_extensions[] = {
{NULL, NULL}
};
+const struct dri_extension ttm_extensions[] = {
+ {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions},
+ {"GL_ARB_pixel_buffer_object", NULL},
+ {NULL, NULL}
+};
+
extern const struct tnl_pipeline_stage _intel_render_stage;
static const struct tnl_pipeline_stage *intel_pipeline[] = {
@@ -314,9 +319,8 @@ intelFinish(GLcontext * ctx)
struct intel_context *intel = intel_context(ctx);
intelFlush(ctx);
if (intel->batch->last_fence) {
- driFenceFinish(intel->batch->last_fence,
- 0, GL_FALSE);
- driFenceUnReference(intel->batch->last_fence);
+ dri_fence_wait(intel->batch->last_fence);
+ dri_fence_unreference(intel->batch->last_fence);
intel->batch->last_fence = NULL;
}
intelCheckFrontRotate(ctx);
@@ -358,15 +362,7 @@ intelInitContext(struct intel_context *intel,
drmI830Sarea *saPriv = (drmI830Sarea *)
(((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset);
int fthrottle_mode;
- GLboolean havePools;
- DRM_LIGHT_LOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext);
- havePools = intelCreatePools(intelScreen);
- DRM_UNLOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext);
-
- if (!havePools)
- return GL_FALSE;
-
if (!_mesa_initialize_context(&intel->ctx,
mesaVis, shareCtx,
functions, (void *) intel))
@@ -460,7 +456,6 @@ intelInitContext(struct intel_context *intel,
intel->RenderIndex = ~0;
fthrottle_mode = driQueryOptioni(&intel->optionCache, "fthrottle_mode");
- intel->iw.irq_seq = -1;
intel->irqsEmitted = 0;
intel->do_irqs = (intel->intelScreen->irq_active &&
@@ -477,6 +472,9 @@ intelInitContext(struct intel_context *intel,
/* GL_TRUE, */
GL_FALSE);
+ if (intelScreen->ttm)
+ driInitExtensions(ctx, ttm_extensions, GL_FALSE);
+
intel->batch = intel_batchbuffer_alloc(intel);
intel->last_swap_fence = NULL;
@@ -533,13 +531,13 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv)
intel_batchbuffer_free(intel->batch);
if (intel->last_swap_fence) {
- driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
- driFenceUnReference(intel->last_swap_fence);
+ dri_fence_wait(intel->last_swap_fence);
+ dri_fence_unreference(intel->last_swap_fence);
intel->last_swap_fence = NULL;
}
if (intel->first_swap_fence) {
- driFenceFinish(intel->first_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
- driFenceUnReference(intel->first_swap_fence);
+ dri_fence_wait(intel->first_swap_fence);
+ dri_fence_unreference(intel->first_swap_fence);
intel->first_swap_fence = NULL;
}
@@ -671,6 +669,18 @@ intelContendedLock(struct intel_context *intel, GLuint flags)
if (dPriv)
DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
+ /* If the last consumer of the texture memory wasn't us, notify the fake
+ * bufmgr and record the new owner. We should have the memory shared
+ * between contexts of a single fake bufmgr, but this will at least make
+ * things correct for now.
+ */
+ if (!intel->intelScreen->ttm && sarea->texAge != intel->hHWContext) {
+ sarea->texAge = intel->hHWContext;
+ dri_bufmgr_fake_contended_lock_take(intel->intelScreen->bufmgr);
+ if (INTEL_DEBUG & DEBUG_BATCH)
+ intel_decode_context_reset();
+ }
+
if (sarea->width != intelScreen->width ||
sarea->height != intelScreen->height ||
sarea->rotation != intelScreen->current_rotation) {
diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h
index 3bb34796b1c..1e9ccd5cdc0 100644
--- a/src/mesa/drivers/dri/i915tex/intel_context.h
+++ b/src/mesa/drivers/dri/i915tex/intel_context.h
@@ -50,7 +50,6 @@
struct intel_region;
struct intel_context;
-struct _DriBufferObject;
typedef void (*intel_tri_func) (struct intel_context *, intelVertex *,
intelVertex *, intelVertex *);
@@ -169,12 +168,12 @@ struct intel_context
void (*meta_import_pixel_state) (struct intel_context * intel);
- GLboolean(*meta_tex_rect_source) (struct intel_context * intel,
- struct _DriBufferObject * buffer,
- GLuint offset,
- GLuint pitch,
- GLuint height,
- GLenum format, GLenum type);
+ GLboolean(*meta_tex_rect_source) (struct intel_context * intel,
+ dri_bo * buffer,
+ GLuint offset,
+ GLuint pitch,
+ GLuint height,
+ GLenum format, GLenum type);
void (*rotate_window) (struct intel_context * intel,
__DRIdrawablePrivate * dPriv, GLuint srcBuf);
@@ -186,8 +185,8 @@ struct intel_context
GLuint Fallback;
GLuint NewGLState;
- struct _DriFenceObject *last_swap_fence;
- struct _DriFenceObject *first_swap_fence;
+ dri_fence *last_swap_fence;
+ dri_fence *first_swap_fence;
struct intel_batchbuffer *batch;
@@ -221,11 +220,6 @@ struct intel_context
GLboolean hw_stipple;
GLboolean strict_conformance;
- /* AGP memory buffer manager:
- */
- struct bufmgr *bm;
-
-
/* State for intelvb.c and inteltris.c.
*/
GLuint RenderIndex;
@@ -261,7 +255,6 @@ struct intel_context
GLuint do_usleeps;
int do_irqs;
GLuint irqsEmitted;
- drm_i915_irq_wait_t iw;
drm_context_t hHWContext;
drmLock *driHwLock;
diff --git a/src/mesa/drivers/dri/i915tex/intel_decode.c b/src/mesa/drivers/dri/i915tex/intel_decode.c
index 6fc02c999c3..bf3387b28e6 100644
--- a/src/mesa/drivers/dri/i915tex/intel_decode.c
+++ b/src/mesa/drivers/dri/i915tex/intel_decode.c
@@ -824,7 +824,7 @@ intel_decode(uint32_t *data, int count, uint32_t hw_offset)
return failures;
}
-void intel_disasm_context_reset()
+void intel_decode_context_reset()
{
saved_s2_set = 0;
saved_s4_set = 1;
diff --git a/src/mesa/drivers/dri/i915tex/intel_ioctl.c b/src/mesa/drivers/dri/i915tex/intel_ioctl.c
index 3250c6b3a9c..6e76737c783 100644
--- a/src/mesa/drivers/dri/i915tex/intel_ioctl.c
+++ b/src/mesa/drivers/dri/i915tex/intel_ioctl.c
@@ -45,18 +45,15 @@
#define FILE_DEBUG_FLAG DEBUG_IOCTL
int
-intelEmitIrqLocked(struct intel_context *intel)
+intelEmitIrqLocked(intelScreenPrivate *intelScreen)
{
drmI830IrqEmit ie;
int ret, seq;
- assert(((*(int *) intel->driHwLock) & ~DRM_LOCK_CONT) ==
- (DRM_LOCK_HELD | intel->hHWContext));
-
ie.irq_seq = &seq;
- ret = drmCommandWriteRead(intel->driFd, DRM_I830_IRQ_EMIT,
- &ie, sizeof(ie));
+ ret = drmCommandWriteRead(intelScreen->driScrnPriv->fd,
+ DRM_I830_IRQ_EMIT, &ie, sizeof(ie));
if (ret) {
fprintf(stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret);
exit(1);
@@ -68,18 +65,18 @@ intelEmitIrqLocked(struct intel_context *intel)
}
void
-intelWaitIrq(struct intel_context *intel, int seq)
+intelWaitIrq(intelScreenPrivate *intelScreen, int seq)
{
+ drm_i915_irq_wait_t iw;
int ret;
DBG("%s %d\n", __FUNCTION__, seq);
- intel->iw.irq_seq = seq;
+ iw.irq_seq = seq;
do {
- ret =
- drmCommandWrite(intel->driFd, DRM_I830_IRQ_WAIT, &intel->iw,
- sizeof(intel->iw));
+ ret = drmCommandWrite(intelScreen->driScrnPriv->fd,
+ DRM_I830_IRQ_WAIT, &iw, sizeof(iw));
} while (ret == -EAGAIN || ret == -EINTR);
if (ret) {
diff --git a/src/mesa/drivers/dri/i915tex/intel_ioctl.h b/src/mesa/drivers/dri/i915tex/intel_ioctl.h
index e8d07de893e..7a5b175ed1c 100644
--- a/src/mesa/drivers/dri/i915tex/intel_ioctl.h
+++ b/src/mesa/drivers/dri/i915tex/intel_ioctl.h
@@ -30,8 +30,8 @@
#include "intel_context.h"
-void intelWaitIrq(struct intel_context *intel, int seq);
-int intelEmitIrqLocked(struct intel_context *intel);
+void intelWaitIrq(intelScreenPrivate *intelScreen, int seq);
+int intelEmitIrqLocked(intelScreenPrivate *intelScreen);
void intel_batch_ioctl(struct intel_context *intel,
GLuint start_offset,
diff --git a/src/mesa/drivers/dri/i915tex/intel_pixel_draw.c b/src/mesa/drivers/dri/i915tex/intel_pixel_draw.c
index e4e57cb3a7e..afb586b4a33 100644
--- a/src/mesa/drivers/dri/i915tex/intel_pixel_draw.c
+++ b/src/mesa/drivers/dri/i915tex/intel_pixel_draw.c
@@ -217,7 +217,7 @@ do_blit_drawpixels(GLcontext * ctx,
struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
GLuint src_offset;
GLuint rowLength;
- struct _DriFenceObject *fence = NULL;
+ dri_fence *fence = NULL;
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s\n", __FUNCTION__);
@@ -298,8 +298,7 @@ do_blit_drawpixels(GLcontext * ctx,
drm_clip_rect_t *box = dPriv->pClipRects;
drm_clip_rect_t rect;
drm_clip_rect_t dest_rect;
- struct _DriBufferObject *src_buffer =
- intel_bufferobj_buffer(intel, src, INTEL_READ);
+ dri_bo *src_buffer = intel_bufferobj_buffer(intel, src, INTEL_READ);
int i;
dest_rect.x1 = dPriv->x + x;
@@ -324,14 +323,15 @@ do_blit_drawpixels(GLcontext * ctx,
ctx->Color.ColorLogicOpEnabled ?
ctx->Color.LogicOp : GL_COPY);
}
- fence = intel_batchbuffer_flush(intel->batch);
- driFenceReference(fence);
+ intel_batchbuffer_flush(intel->batch);
+ fence = intel->batch->last_fence;
+ dri_fence_reference(fence);
}
UNLOCK_HARDWARE(intel);
if (fence) {
- driFenceFinish(fence, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, GL_FALSE);
- driFenceUnReference(fence);
+ dri_fence_wait(fence);
+ dri_fence_unreference(fence);
}
if (INTEL_DEBUG & DEBUG_PIXEL)
diff --git a/src/mesa/drivers/dri/i915tex/intel_pixel_read.c b/src/mesa/drivers/dri/i915tex/intel_pixel_read.c
index 24e49ae0663..a22844926c9 100644
--- a/src/mesa/drivers/dri/i915tex/intel_pixel_read.c
+++ b/src/mesa/drivers/dri/i915tex/intel_pixel_read.c
@@ -173,7 +173,7 @@ do_blit_readpixels(GLcontext * ctx,
struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
GLuint dst_offset;
GLuint rowLength;
- struct _DriFenceObject *fence = NULL;
+ dri_fence *fence = NULL;
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s\n", __FUNCTION__);
@@ -241,9 +241,9 @@ do_blit_readpixels(GLcontext * ctx,
GLboolean all = (width * height * src->cpp == dst->Base.Size &&
x == 0 && dst_offset == 0);
- struct _DriBufferObject *dst_buffer =
- intel_bufferobj_buffer(intel, dst, all ? INTEL_WRITE_FULL :
- INTEL_WRITE_PART);
+ dri_bo *dst_buffer = intel_bufferobj_buffer(intel, dst,
+ all ? INTEL_WRITE_FULL :
+ INTEL_WRITE_PART);
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
drm_clip_rect_t *box = dPriv->pClipRects;
@@ -275,16 +275,16 @@ do_blit_readpixels(GLcontext * ctx,
GL_COPY);
}
- fence = intel_batchbuffer_flush(intel->batch);
- driFenceReference(fence);
+ intel_batchbuffer_flush(intel->batch);
+ fence = intel->batch->last_fence;
+ dri_fence_reference(fence);
}
UNLOCK_HARDWARE(intel);
if (fence) {
- driFenceFinish(fence, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW,
- GL_FALSE);
- driFenceUnReference(fence);
+ dri_fence_wait(fence);
+ dri_fence_unreference(fence);
}
if (INTEL_DEBUG & DEBUG_PIXEL)
diff --git a/src/mesa/drivers/dri/i915tex/intel_regions.c b/src/mesa/drivers/dri/i915tex/intel_regions.c
index 7d19bd07d36..4eac859a133 100644
--- a/src/mesa/drivers/dri/i915tex/intel_regions.c
+++ b/src/mesa/drivers/dri/i915tex/intel_regions.c
@@ -52,8 +52,17 @@ void
intel_region_idle(intelScreenPrivate *intelScreen, struct intel_region *region)
{
DBG("%s\n", __FUNCTION__);
- if (region && region->buffer)
- driBOWaitIdle(region->buffer, GL_FALSE);
+ /* XXX: Using this function is likely bogus -- it ought to only have been
+ * used before a map, anyway, but leave this cheap implementation of it
+ * for now.
+ */
+ if (region && region->buffer) {
+ /* Mapping it for read will ensure that any acceleration to the region
+ * would have landed already.
+ */
+ dri_bo_map(region->buffer, GL_TRUE);
+ dri_bo_unmap(region->buffer);
+ }
}
/* XXX: Thread safety?
@@ -66,8 +75,8 @@ intel_region_map(intelScreenPrivate *intelScreen, struct intel_region *region)
if (region->pbo)
intel_region_cow(intelScreen, region);
- region->map = driBOMap(region->buffer,
- DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
+ dri_bo_map(region->buffer, GL_TRUE);
+ region->map = region->buffer->virtual;
}
return region->map;
@@ -78,19 +87,16 @@ intel_region_unmap(intelScreenPrivate *intelScreen, struct intel_region *region)
{
DBG("%s\n", __FUNCTION__);
if (!--region->map_refcount) {
- driBOUnmap(region->buffer);
+ dri_bo_unmap(region->buffer);
region->map = NULL;
}
}
-#undef TEST_CACHED_TEXTURES
-
struct intel_region *
intel_region_alloc(intelScreenPrivate *intelScreen,
GLuint cpp, GLuint pitch, GLuint height)
{
struct intel_region *region = calloc(sizeof(*region), 1);
- struct intel_context *intel = intelScreenContext(intelScreen);
DBG("%s\n", __FUNCTION__);
@@ -99,18 +105,8 @@ intel_region_alloc(intelScreenPrivate *intelScreen,
region->height = height; /* needed? */
region->refcount = 1;
- driGenBuffers(intelScreen->regionPool,
- "region", 1, &region->buffer, 64,
-#ifdef TEST_CACHED_TEXTURES
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_BIND_CACHED |
- DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
-#else
- 0,
-#endif
- 0);
- LOCK_HARDWARE(intel);
- driBOData(region->buffer, pitch * cpp * height, NULL, 0);
- UNLOCK_HARDWARE(intel);
+ region->buffer = dri_bo_alloc(intelScreen->bufmgr, "region",
+ pitch * cpp * height, 64, DRM_BO_FLAG_MEM_TT);
return region;
}
@@ -141,7 +137,7 @@ intel_region_release(struct intel_region **region)
if ((*region)->pbo)
(*region)->pbo->region = NULL;
(*region)->pbo = NULL;
- driBOUnReference((*region)->buffer);
+ dri_bo_unreference((*region)->buffer);
free(*region);
}
*region = NULL;
@@ -151,6 +147,7 @@ intel_region_release(struct intel_region **region)
struct intel_region *
intel_region_create_static(intelScreenPrivate *intelScreen,
GLuint mem_type,
+ unsigned int bo_handle,
GLuint offset,
void *virtual,
GLuint cpp, GLuint pitch, GLuint height)
@@ -163,16 +160,18 @@ intel_region_create_static(intelScreenPrivate *intelScreen,
region->height = height; /* needed? */
region->refcount = 1;
- /*
- * We use a "shared" buffer type to indicate buffers created and
- * shared by others.
- */
-
- driGenBuffers(intelScreen->staticPool, "static region", 1,
- &region->buffer, 64,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE |
- DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
- driBOSetStatic(region->buffer, offset, pitch * cpp * height, virtual, 0);
+ if (intelScreen->ttm) {
+ assert(bo_handle != -1);
+ region->buffer = dri_ttm_bo_create_from_handle(intelScreen->bufmgr,
+ "static region",
+ bo_handle);
+ } else {
+ region->buffer = dri_bo_alloc_static(intelScreen->bufmgr,
+ "static region",
+ offset, pitch * cpp * height,
+ virtual,
+ DRM_BO_FLAG_MEM_TT);
+ }
return region;
}
@@ -183,6 +182,7 @@ void
intel_region_update_static(intelScreenPrivate *intelScreen,
struct intel_region *region,
GLuint mem_type,
+ unsigned int bo_handle,
GLuint offset,
void *virtual,
GLuint cpp, GLuint pitch, GLuint height)
@@ -198,13 +198,19 @@ intel_region_update_static(intelScreenPrivate *intelScreen,
* shared by others.
*/
- driDeleteBuffers(1, &region->buffer);
- driGenBuffers(intelScreen->staticPool, "static region", 1,
- &region->buffer, 64,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE |
- DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
- driBOSetStatic(region->buffer, offset, pitch * cpp * height, virtual, 0);
-
+ dri_bo_unreference(region->buffer);
+ if (intelScreen->ttm) {
+ assert(bo_handle != -1);
+ region->buffer = dri_ttm_bo_create_from_handle(intelScreen->bufmgr,
+ "static region",
+ bo_handle);
+ } else {
+ region->buffer = dri_bo_alloc_static(intelScreen->bufmgr,
+ "static region",
+ offset, pitch * cpp * height,
+ virtual,
+ DRM_BO_FLAG_MEM_TT);
+ }
}
@@ -379,37 +385,33 @@ intel_region_attach_pbo(intelScreenPrivate *intelScreen,
}
if (region->buffer) {
- driDeleteBuffers(1, &region->buffer);
+ dri_bo_unreference(region->buffer);
region->buffer = NULL;
}
region->pbo = pbo;
region->pbo->region = region;
- region->buffer = driBOReference(pbo->buffer);
+ dri_bo_reference(pbo->buffer);
+ region->buffer = pbo->buffer;
}
-/* Break the COW tie to the pbo. The pbo gets to keep the data.
+/* Break the COW tie to the pbo and allocate a new buffer.
+ * The pbo gets to keep the data.
*/
void
intel_region_release_pbo(intelScreenPrivate *intelScreen,
struct intel_region *region)
{
- struct intel_context *intel = intelScreenContext(intelScreen);
-
assert(region->buffer == region->pbo->buffer);
region->pbo->region = NULL;
region->pbo = NULL;
- driBOUnReference(region->buffer);
+ dri_bo_unreference(region->buffer);
region->buffer = NULL;
- driGenBuffers(intelScreen->regionPool,
- "region", 1, &region->buffer, 64, 0, 0);
-
- LOCK_HARDWARE(intel);
- driBOData(region->buffer,
- region->cpp * region->pitch * region->height, NULL, 0);
- UNLOCK_HARDWARE(intel);
+ region->buffer = dri_bo_alloc(intelScreen->bufmgr, "region",
+ region->pitch * region->cpp * region->height,
+ 64, DRM_BO_FLAG_MEM_TT);
}
/* Break the COW tie to the pbo. Both the pbo and the region end up
@@ -465,7 +467,7 @@ intel_region_cow(intelScreenPrivate *intelScreen, struct intel_region *region)
}
}
-struct _DriBufferObject *
+dri_bo *
intel_region_buffer(intelScreenPrivate *intelScreen,
struct intel_region *region, GLuint flag)
{
diff --git a/src/mesa/drivers/dri/i915tex/intel_regions.h b/src/mesa/drivers/dri/i915tex/intel_regions.h
index d938c107a46..42d7b177117 100644
--- a/src/mesa/drivers/dri/i915tex/intel_regions.h
+++ b/src/mesa/drivers/dri/i915tex/intel_regions.h
@@ -44,7 +44,7 @@ struct intel_buffer_object;
*/
struct intel_region
{
- struct _DriBufferObject *buffer; /**< buffer manager's buffer ID */
+ dri_bo *buffer; /**< buffer manager's buffer */
GLuint refcount; /**< Reference count for region */
GLuint cpp; /**< bytes per pixel */
GLuint pitch; /**< in pixels */
@@ -73,6 +73,7 @@ void intel_region_release(struct intel_region **ib);
extern struct intel_region
*intel_region_create_static(intelScreenPrivate *intelScreen,
GLuint mem_type,
+ unsigned int bo_handle,
GLuint offset,
void *virtual,
GLuint cpp,
@@ -81,6 +82,7 @@ extern void
intel_region_update_static(intelScreenPrivate *intelScreen,
struct intel_region *region,
GLuint mem_type,
+ unsigned int bo_handle,
GLuint offset,
void *virtual,
GLuint cpp, GLuint pitch, GLuint height);
@@ -134,8 +136,8 @@ void intel_region_release_pbo(intelScreenPrivate *intelScreen,
void intel_region_cow(intelScreenPrivate *intelScreen,
struct intel_region *region);
-struct _DriBufferObject *intel_region_buffer(intelScreenPrivate *intelScreen,
- struct intel_region *region,
- GLuint flag);
+dri_bo *intel_region_buffer(intelScreenPrivate *intelScreen,
+ struct intel_region *region,
+ GLuint flag);
#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.c b/src/mesa/drivers/dri/i915tex/intel_screen.c
index 2acdead63d5..2721a900945 100644
--- a/src/mesa/drivers/dri/i915tex/intel_screen.c
+++ b/src/mesa/drivers/dri/i915tex/intel_screen.c
@@ -46,7 +46,7 @@
#include "intel_fbo.h"
#include "i830_dri.h"
-#include "dri_bufpool.h"
+#include "dri_bufmgr.h"
#include "intel_regions.h"
#include "intel_batchbuffer.h"
@@ -120,16 +120,18 @@ intelMapScreenRegions(__DRIscreenPrivate * sPriv)
return GL_FALSE;
}
-#if 0
- _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle);
- if (drmMap(sPriv->fd,
- intelScreen->tex.handle,
- intelScreen->tex.size,
- (drmAddress *) & intelScreen->tex.map) != 0) {
- intelUnmapScreenRegions(intelScreen);
- return GL_FALSE;
+ if (0)
+ _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle);
+ if (intelScreen->tex.size != 0) {
+ if (drmMap(sPriv->fd,
+ intelScreen->tex.handle,
+ intelScreen->tex.size,
+ (drmAddress *) & intelScreen->tex.map) != 0) {
+ intelUnmapScreenRegions(intelScreen);
+ return GL_FALSE;
+ }
}
-#endif
+
if (0)
printf("Mappings: front: %p back: %p third: %p depth: %p tex: %p\n",
intelScreen->front.map,
@@ -138,22 +140,56 @@ intelMapScreenRegions(__DRIscreenPrivate * sPriv)
return GL_TRUE;
}
+/** Driver-specific fence emit implementation for the fake memory manager. */
+static unsigned int
+intel_fence_emit(void *private)
+{
+ intelScreenPrivate *intelScreen = (intelScreenPrivate *)private;
+ unsigned int fence;
+
+ /* XXX: Need to emit a flush, if we haven't already (at least with the
+ * current batchbuffer implementation, we have).
+ */
+
+ fence = intelEmitIrqLocked(intelScreen);
+
+ return fence;
+}
+
+/** Driver-specific fence wait implementation for the fake memory manager. */
+static int
+intel_fence_wait(void *private, unsigned int cookie)
+{
+ intelScreenPrivate *intelScreen = (intelScreenPrivate *)private;
+
+ intelWaitIrq(intelScreen, cookie);
+
+ return 0;
+}
static struct intel_region *
intel_recreate_static(intelScreenPrivate *intelScreen,
struct intel_region *region,
- GLuint mem_type,
- GLuint offset,
- void *virtual,
- GLuint cpp, GLuint pitch, GLuint height)
+ intelRegion *region_desc,
+ GLuint mem_type)
{
if (region) {
- intel_region_update_static(intelScreen, region, mem_type, offset,
- virtual, cpp, pitch, height);
+ intel_region_update_static(intelScreen, region, mem_type,
+ region_desc->bo_handle, region_desc->offset,
+ region_desc->map, intelScreen->cpp,
+ region_desc->pitch / intelScreen->cpp,
+ intelScreen->height);
} else {
- region = intel_region_create_static(intelScreen, mem_type, offset,
- virtual, cpp, pitch, height);
+ region = intel_region_create_static(intelScreen, mem_type,
+ region_desc->bo_handle,
+ region_desc->offset,
+ region_desc->map, intelScreen->cpp,
+ region_desc->pitch / intelScreen->cpp,
+ intelScreen->height);
}
+
+ assert(region->buffer != NULL);
+
return region;
}
@@ -175,57 +211,42 @@ intel_recreate_static_regions(intelScreenPrivate *intelScreen)
intelScreen->front_region =
intel_recreate_static(intelScreen,
intelScreen->front_region,
- DRM_BO_FLAG_MEM_TT,
- intelScreen->front.offset,
- intelScreen->front.map,
- intelScreen->cpp,
- intelScreen->front.pitch / intelScreen->cpp,
- intelScreen->height);
-
- intelScreen->rotated_region =
- intel_recreate_static(intelScreen,
- intelScreen->rotated_region,
- DRM_BO_FLAG_MEM_TT,
- intelScreen->rotated.offset,
- intelScreen->rotated.map,
- intelScreen->cpp,
- intelScreen->rotated.pitch /
- intelScreen->cpp, intelScreen->height);
+ &intelScreen->front,
+ DRM_BO_FLAG_MEM_TT);
+ /* The rotated region is only used for old DDXes that didn't handle rotation
+\ * on their own.
+ */
+ if (intelScreen->driScrnPriv->ddxMinor < 8) {
+ intelScreen->rotated_region =
+ intel_recreate_static(intelScreen,
+ intelScreen->rotated_region,
+ &intelScreen->rotated,
+ DRM_BO_FLAG_MEM_TT);
+ }
intelScreen->back_region =
intel_recreate_static(intelScreen,
intelScreen->back_region,
- DRM_BO_FLAG_MEM_TT,
- intelScreen->back.offset,
- intelScreen->back.map,
- intelScreen->cpp,
- intelScreen->back.pitch / intelScreen->cpp,
- intelScreen->height);
+ &intelScreen->back,
+ DRM_BO_FLAG_MEM_TT);
if (intelScreen->third.handle) {
intelScreen->third_region =
intel_recreate_static(intelScreen,
intelScreen->third_region,
- DRM_BO_FLAG_MEM_TT,
- intelScreen->third.offset,
- intelScreen->third.map,
- intelScreen->cpp,
- intelScreen->third.pitch / intelScreen->cpp,
- intelScreen->height);
+ &intelScreen->third,
+ DRM_BO_FLAG_MEM_TT);
}
- /* Still assuming front.cpp == depth.cpp
+ /* Still assumes front.cpp == depth.cpp. We can kill this when we move to
+ * private buffers.
*/
intelScreen->depth_region =
intel_recreate_static(intelScreen,
intelScreen->depth_region,
- DRM_BO_FLAG_MEM_TT,
- intelScreen->depth.offset,
- intelScreen->depth.map,
- intelScreen->cpp,
- intelScreen->depth.pitch / intelScreen->cpp,
- intelScreen->height);
+ &intelScreen->depth,
+ DRM_BO_FLAG_MEM_TT);
}
/**
@@ -368,6 +389,18 @@ intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
intelScreen->depth.handle = sarea->depth_handle;
intelScreen->depth.size = sarea->depth_size;
+ if (intelScreen->driScrnPriv->ddxMinor >= 9) {
+ intelScreen->front.bo_handle = sarea->front_bo_handle;
+ intelScreen->back.bo_handle = sarea->back_bo_handle;
+ intelScreen->third.bo_handle = sarea->third_bo_handle;
+ intelScreen->depth.bo_handle = sarea->depth_bo_handle;
+ } else {
+ intelScreen->front.bo_handle = -1;
+ intelScreen->back.bo_handle = -1;
+ intelScreen->third.bo_handle = -1;
+ intelScreen->depth.bo_handle = -1;
+ }
+
intelScreen->tex.offset = sarea->tex_offset;
intelScreen->logTextureGranularity = sarea->log_tex_granularity;
intelScreen->tex.handle = sarea->tex_handle;
@@ -386,45 +419,6 @@ intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
intelPrintSAREA(sarea);
}
-GLboolean
-intelCreatePools(intelScreenPrivate *intelScreen)
-{
- unsigned batchPoolSize = 1024*1024;
- __DRIscreenPrivate * sPriv = intelScreen->driScrnPriv;
-
- if (intelScreen->havePools)
- return GL_TRUE;
-
- batchPoolSize /= intelScreen->maxBatchSize;
- intelScreen->regionPool = driDRMPoolInit(sPriv->fd);
-
- if (!intelScreen->regionPool)
- return GL_FALSE;
-
- intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd);
-
- if (!intelScreen->staticPool)
- return GL_FALSE;
-
- intelScreen->texPool = intelScreen->regionPool;
-
- intelScreen->batchPool = driBatchPoolInit(sPriv->fd,
- DRM_BO_FLAG_EXE |
- DRM_BO_FLAG_MEM_TT |
- DRM_BO_FLAG_MEM_LOCAL,
- intelScreen->maxBatchSize,
- batchPoolSize, 5);
- if (!intelScreen->batchPool) {
- fprintf(stderr, "Failed to initialize batch pool - possible incorrect agpgart installed\n");
- return GL_FALSE;
- }
-
- intel_recreate_static_regions(intelScreen);
- intelScreen->havePools = GL_TRUE;
-
- return GL_TRUE;
-}
-
static GLboolean
intelInitDriver(__DRIscreenPrivate * sPriv)
@@ -460,10 +454,11 @@ intelInitDriver(__DRIscreenPrivate * sPriv)
sarea = (drmI830Sarea *)
(((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset);
- intelScreen->maxBatchSize = BATCH_SZ;
intelScreen->deviceID = gDRIPriv->deviceID;
if (intelScreen->deviceID == PCI_CHIP_I865_G)
intelScreen->maxBatchSize = 4096;
+ else
+ intelScreen->maxBatchSize = BATCH_SZ;
intelScreen->mem = gDRIPriv->mem;
intelScreen->cpp = gDRIPriv->cpp;
@@ -489,24 +484,6 @@ intelInitDriver(__DRIscreenPrivate * sPriv)
return GL_FALSE;
}
-#if 0
-
- /*
- * FIXME: Remove this code and its references.
- */
-
- intelScreen->tex.offset = gDRIPriv->textureOffset;
- intelScreen->logTextureGranularity = gDRIPriv->logTextureGranularity;
- intelScreen->tex.handle = gDRIPriv->textures;
- intelScreen->tex.size = gDRIPriv->textureSize;
-
-#else
- intelScreen->tex.offset = 0;
- intelScreen->logTextureGranularity = 0;
- intelScreen->tex.handle = 0;
- intelScreen->tex.size = 0;
-#endif
-
intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
if (0)
@@ -554,6 +531,39 @@ intelInitDriver(__DRIscreenPrivate * sPriv)
(*glx_enable_extension) (psc, "GLX_SGI_make_current_read");
}
+ /* If we've got a new enough DDX that's initializing TTM and giving us
+ * object handles for the shared buffers, use that.
+ */
+ intelScreen->ttm = GL_FALSE;
+ if (getenv("INTEL_NO_TTM") == NULL &&
+ intelScreen->driScrnPriv->ddxMinor >= 9 &&
+ intelScreen->front.bo_handle != -1) {
+ intelScreen->bufmgr = dri_bufmgr_ttm_init(sPriv->fd,
+ DRM_FENCE_TYPE_EXE,
+ DRM_FENCE_TYPE_EXE |
+ DRM_I915_FENCE_TYPE_RW);
+ if (intelScreen->bufmgr != NULL)
+ intelScreen->ttm = GL_TRUE;
+ }
+ /* Otherwise, use the classic buffer manager. */
+ if (intelScreen->bufmgr == NULL) {
+ if (intelScreen->tex.size == 0) {
+ fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n",
+ __func__, __LINE__);
+ return GL_FALSE;
+ }
+ fprintf(stderr, "[%s:%u] Failed to init TTM buffer manager, falling back"
+ " to classic.\n", __func__, __LINE__);
+ intelScreen->bufmgr = dri_bufmgr_fake_init(intelScreen->tex.offset,
+ intelScreen->tex.map,
+ intelScreen->tex.size,
+ intel_fence_emit,
+ intel_fence_wait,
+ intelScreen);
+ }
+
+ intel_recreate_static_regions(intelScreen);
+
return GL_TRUE;
}
@@ -565,11 +575,7 @@ intelDestroyScreen(__DRIscreenPrivate * sPriv)
intelUnmapScreenRegions(intelScreen);
- if (intelScreen->havePools) {
- driPoolTakeDown(intelScreen->regionPool);
- driPoolTakeDown(intelScreen->staticPool);
- driPoolTakeDown(intelScreen->batchPool);
- }
+ dri_bufmgr_destroy(intelScreen->bufmgr);
FREE(intelScreen);
sPriv->private = NULL;
}
@@ -896,7 +902,7 @@ __driCreateNewScreen_20050727(__DRInativeDisplay * dpy, int scrn,
__DRIscreenPrivate *psp;
static const __DRIversion ddx_expected = { 1, 5, 0 };
static const __DRIversion dri_expected = { 4, 0, 0 };
- static const __DRIversion drm_expected = { 1, 7, 0 };
+ static const __DRIversion drm_expected = { 1, 5, 0 };
dri_interface = interface;
diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.h b/src/mesa/drivers/dri/i915tex/intel_screen.h
index bac43aadddf..aa0ef2c5090 100644
--- a/src/mesa/drivers/dri/i915tex/intel_screen.h
+++ b/src/mesa/drivers/dri/i915tex/intel_screen.h
@@ -33,7 +33,7 @@
#include "intel_rotate.h"
#include "i830_common.h"
#include "xmlconfig.h"
-#include "dri_bufpool.h"
+#include "dri_bufmgr.h"
/* XXX: change name or eliminate to avoid conflict with "struct
* intel_region"!!!
@@ -45,6 +45,7 @@ typedef struct
char *map; /* memory map */
int offset; /* from start of video mem, in bytes */
int pitch; /* row stride, in bytes */
+ unsigned int bo_handle; /* buffer object id if available, or -1 */
} intelRegion;
typedef struct
@@ -90,12 +91,15 @@ typedef struct
* Configuration cache with default values for all contexts
*/
driOptionCache optionCache;
- struct _DriBufferPool *batchPool;
- struct _DriBufferPool *texPool;
- struct _DriBufferPool *regionPool;
- struct _DriBufferPool *staticPool;
+
+ dri_bufmgr *bufmgr;
unsigned int maxBatchSize;
- GLboolean havePools;
+
+ /**
+ * This value indicates that the kernel memory manager is being used
+ * instead of the fake client-side memory manager.
+ */
+ GLboolean ttm;
} intelScreenPrivate;
@@ -122,16 +126,9 @@ extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv);
extern void
intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h);
-extern struct _DriBufferPool *driBatchPoolInit(int fd, unsigned flags,
- unsigned long bufSize,
- unsigned numBufs,
- unsigned checkDelayed);
-
extern struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen);
extern void
intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea);
-extern GLboolean
-intelCreatePools(intelScreenPrivate *intelScreen);
#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_tex_image.c b/src/mesa/drivers/dri/i915tex/intel_tex_image.c
index f790b1e6f73..197cf35ebe6 100644
--- a/src/mesa/drivers/dri/i915tex/intel_tex_image.c
+++ b/src/mesa/drivers/dri/i915tex/intel_tex_image.c
@@ -221,11 +221,10 @@ try_pbo_upload(struct intel_context *intel,
intelFlush(&intel->ctx);
LOCK_HARDWARE(intel);
{
- struct _DriBufferObject *src_buffer =
- intel_bufferobj_buffer(intel, pbo, INTEL_READ);
- struct _DriBufferObject *dst_buffer =
- intel_region_buffer(intel->intelScreen, intelImage->mt->region,
- INTEL_WRITE_FULL);
+ dri_bo *src_buffer = intel_bufferobj_buffer(intel, pbo, INTEL_READ);
+ dri_bo *dst_buffer = intel_region_buffer(intel->intelScreen,
+ intelImage->mt->region,
+ INTEL_WRITE_FULL);
intelEmitCopyBlit(intel,
diff --git a/src/mesa/drivers/dri/i915tex/server/i830_common.h b/src/mesa/drivers/dri/i915tex/server/i830_common.h
index 8735f93d146..a877f3c2f40 100644
--- a/src/mesa/drivers/dri/i915tex/server/i830_common.h
+++ b/src/mesa/drivers/dri/i915tex/server/i830_common.h
@@ -85,6 +85,7 @@ typedef struct {
int last_enqueue; /* last time a buffer was enqueued */
int last_dispatch; /* age of the most recently dispatched buffer */
int ctxOwner; /* last context to upload state */
+ /** Last context that used the buffer manager. */
int texAge;
int pf_enabled; /* is pageflipping allowed? */
int pf_active;
@@ -135,6 +136,15 @@ typedef struct {
int third_offset;
int third_size;
unsigned int third_tiled;
+
+ /* buffer object handles for the static buffers. May change
+ * over the lifetime of the client, though it doesn't in our current
+ * implementation.
+ */
+ unsigned int front_bo_handle;
+ unsigned int back_bo_handle;
+ unsigned int third_bo_handle;
+ unsigned int depth_bo_handle;
} drmI830Sarea;
/* Flags for perf_boxes
diff --git a/src/mesa/drivers/dri/i965/intel_context.c b/src/mesa/drivers/dri/i965/intel_context.c
index 1fbf571184e..4a95087d78f 100644
--- a/src/mesa/drivers/dri/i965/intel_context.c
+++ b/src/mesa/drivers/dri/i965/intel_context.c
@@ -669,7 +669,7 @@ void LOCK_HARDWARE( struct intel_context *intel )
intel->locked = 1;
if (intel->aub_wrap) {
- bm_fake_NotifyContendedLockTake( intel );
+ bm_fake_NotifyContendedLockTake( intel );
intel->vtbl.lost_hardware( intel );
intel->vtbl.aub_wrap(intel);
intel->aub_wrap = 0;
@@ -680,7 +680,7 @@ void LOCK_HARDWARE( struct intel_context *intel )
intel->vtbl.lost_hardware( intel );
}
- /* Make sure nothing has been emitted prior to getting the lock:
+ /* Make sure nothing has been emitted prior to getting the lock:
*/
assert(intel->batch->map == 0);
@@ -713,8 +713,6 @@ void UNLOCK_HARDWARE( struct intel_context *intel )
intel->vtbl.note_unlock( intel );
intel->locked = 0;
-
-
DRM_UNLOCK(intel->driFd, intel->driHwLock, intel->hHWContext);
_glthread_UNLOCK_MUTEX(lockMutex);
}