drm: update bufmgr code to reflect changes in drm interface
[mesa.git] / src / mesa / drivers / dri / common / dri_bufmgr.c
index 65d654596573a66e47719da622411ef71ce62968..407409bf06df0cc7229ebe3523ff27278d54a04b 100644 (file)
-/**************************************************************************
- * 
- * 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 <eric@anholt.net>
  *
- * 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)
 {
-   assert(buf->private != NULL);
+   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);
-   BM_CKFATAL(buf->pool->waitIdle(buf->pool, buf->private, lazy));
-   _glthread_UNLOCK_MUTEX(buf->mutex);
+   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, 0, 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);
 }