intel: Add a none working GEM backend for intel
authorJakob Bornecrantz <wallbraker@gmail.com>
Mon, 5 Jan 2009 10:44:56 +0000 (11:44 +0100)
committerJakob Bornecrantz <wallbraker@gmail.com>
Wed, 14 Jan 2009 11:28:31 +0000 (12:28 +0100)
src/gallium/winsys/drm/intel/gem/Makefile [new file with mode: 0644]
src/gallium/winsys/drm/intel/gem/Makefile.template [new file with mode: 0644]
src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c [new file with mode: 0644]
src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.h [new file with mode: 0644]
src/gallium/winsys/drm/intel/gem/intel_be_context.c [new file with mode: 0644]
src/gallium/winsys/drm/intel/gem/intel_be_context.h [new file with mode: 0644]
src/gallium/winsys/drm/intel/gem/intel_be_device.c [new file with mode: 0644]
src/gallium/winsys/drm/intel/gem/intel_be_device.h [new file with mode: 0644]
src/gallium/winsys/drm/intel/gem/intel_be_fence.h [new file with mode: 0644]

diff --git a/src/gallium/winsys/drm/intel/gem/Makefile b/src/gallium/winsys/drm/intel/gem/Makefile
new file mode 100644 (file)
index 0000000..b25fc25
--- /dev/null
@@ -0,0 +1,18 @@
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = inteldrm
+
+C_SOURCES = \
+       intel_be_batchbuffer.c \
+       intel_be_context.c \
+       intel_be_device.c
+
+
+include ./Makefile.template
+
+DRIVER_DEFINES = $(shell pkg-config libdrm --cflags \
+                && pkg-config libdrm --atleast-version=2.3.1 \
+                && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP")
+symlinks:
+
diff --git a/src/gallium/winsys/drm/intel/gem/Makefile.template b/src/gallium/winsys/drm/intel/gem/Makefile.template
new file mode 100644 (file)
index 0000000..557070a
--- /dev/null
@@ -0,0 +1,64 @@
+# -*-makefile-*-
+
+
+# We still have a dependency on the "dri" buffer manager.  Most likely
+# the interface can be reused in non-dri environments, and also as a
+# frontend to simpler memory managers.
+#
+COMMON_SOURCES =
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+       $(CPP_SOURCES:.cpp=.o) \
+       $(ASM_SOURCES:.S=.o)
+
+
+### Include directories
+INCLUDES = \
+       -I. \
+       -I$(TOP)/src/gallium/include \
+       -I$(TOP)/src/gallium/auxiliary \
+       -I$(TOP)/src/gallium/drivers \
+       -I$(TOP)/include \
+       $(DRIVER_INCLUDES)
+
+
+##### RULES #####
+
+.c.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+.cpp.o:
+       $(CXX) -c $(INCLUDES) $(CXXFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+.S.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES)  $< -o $@
+
+
+##### TARGETS #####
+
+default: depend symlinks $(LIBNAME)
+
+
+$(LIBNAME): $(OBJECTS) Makefile Makefile.template
+       $(TOP)/bin/mklib -o $@ -static $(OBJECTS) $(DRIVER_LIBS)
+
+
+depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
+       rm -f depend
+       touch depend
+       $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) $(CPP_SOURCES) \
+               $(ASM_SOURCES) 2> /dev/null
+
+
+# Emacs tags
+tags:
+       etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean::
+       -rm -f *.o */*.o *~ *.so *.a *~ server/*.o $(SYMLINKS)
+       -rm -f depend depend.bak
+
+
+include depend
diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c b/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.c
new file mode 100644 (file)
index 0000000..2399910
--- /dev/null
@@ -0,0 +1,120 @@
+
+#include "intel_be_batchbuffer.h"
+#include "intel_be_context.h"
+#include "intel_be_device.h"
+#include "intel_be_fence.h"
+#include <errno.h>
+
+#include "util/u_memory.h"
+
+struct intel_be_batchbuffer *
+intel_be_batchbuffer_alloc(struct intel_be_context *intel)
+{
+       struct intel_be_batchbuffer *batch = CALLOC_STRUCT(intel_be_batchbuffer);
+
+       batch->base.buffer = NULL;
+       batch->base.winsys = &intel->base;
+       batch->base.map = NULL;
+       batch->base.ptr = NULL;
+       batch->base.size = 0;
+       batch->base.actual_size = intel->device->max_batch_size;
+       batch->base.relocs = 0;
+       batch->base.max_relocs = INTEL_DEFAULT_RELOCS;
+
+       batch->base.map = malloc(batch->base.actual_size);
+       memset(batch->base.map, 0, batch->base.actual_size);
+
+       batch->base.ptr = batch->base.map;
+
+       intel_be_batchbuffer_reset(batch);
+
+       return NULL;
+}
+
+void
+intel_be_batchbuffer_reset(struct intel_be_batchbuffer *batch)
+{
+       struct intel_be_context *intel = intel_be_context(batch->base.winsys);
+       struct intel_be_device *dev = intel->device;
+
+       if (batch->bo)
+               drm_intel_bo_unreference(batch->bo);
+
+       memset(batch->base.map, 0, batch->base.actual_size);
+       batch->base.ptr = batch->base.map;
+       batch->base.size = batch->base.actual_size - BATCH_RESERVED;
+
+       batch->base.relocs = 0;
+       batch->base.max_relocs = INTEL_DEFAULT_RELOCS;
+
+       batch->bo = drm_intel_bo_alloc(dev->pools.gem,
+                                      "gallium3d_batch_buffer",
+                                      batch->base.actual_size, 0);
+}
+
+int
+intel_be_offset_relocation(struct intel_be_batchbuffer *batch,
+                          unsigned pre_add,
+                          drm_intel_bo *bo,
+                          uint32_t read_domains,
+                          uint32_t write_domain)
+{
+       unsigned offset;
+       int ret = 0;
+
+       assert(batch->base.relocs < batch->base.max_relocs);
+
+       offset = (unsigned)(batch->base.ptr - batch->base.map);
+       batch->base.ptr += 4;
+
+/*
+       TODO: Enable this when we submit batch buffers to HW
+       ret = drm_intel_bo_emit_reloc(bo, pre_add,
+                                     batch->bo, offset,
+                                     read_domains,
+                                     write_domain);
+*/
+
+       if (!ret)
+               batch->base.relocs++;
+
+       return ret;
+}
+
+void
+intel_be_batchbuffer_flush(struct intel_be_batchbuffer *batch,
+                          struct intel_be_fence **fence)
+{
+       struct i915_batchbuffer *i915 = &batch->base;
+
+       assert(i915_batchbuffer_space(i915) >= 0);
+
+       /* TODO: submit stuff to HW */
+
+       intel_be_batchbuffer_reset(batch);
+
+       if (fence) {
+               if (*fence)
+                       intel_be_fence_unreference(*fence);
+
+               (*fence) = CALLOC_STRUCT(intel_be_fence);
+               (*fence)->refcount = 1;
+               (*fence)->bo = NULL;
+       }
+}
+
+void
+intel_be_batchbuffer_finish(struct intel_be_batchbuffer *batch)
+{
+
+}
+
+void
+intel_be_batchbuffer_free(struct intel_be_batchbuffer *batch)
+{
+       if (batch->bo)
+               drm_intel_bo_unreference(batch->bo);
+
+       free(batch->base.map);
+       free(batch);
+}
diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.h b/src/gallium/winsys/drm/intel/gem/intel_be_batchbuffer.h
new file mode 100644 (file)
index 0000000..195bf8d
--- /dev/null
@@ -0,0 +1,55 @@
+
+#ifndef INTEL_BE_BATCHBUFFER_H
+#define INTEL_BE_BATCHBUFFER_H
+
+#include "i915simple/i915_batch.h"
+
+#include "drm.h"
+#include "intel_bufmgr.h"
+
+#define BATCH_RESERVED 16
+
+#define INTEL_DEFAULT_RELOCS 100
+#define INTEL_MAX_RELOCS 400
+
+#define INTEL_BATCH_NO_CLIPRECTS 0x1
+#define INTEL_BATCH_CLIPRECTS    0x2
+
+struct intel_be_context;
+struct intel_be_device;
+struct intel_be_fence;
+
+struct intel_be_batchbuffer
+{
+       struct i915_batchbuffer base;
+
+       struct intel_be_context *intel;
+       struct intel_be_device *device;
+
+       drm_intel_bo *bo;
+};
+
+struct intel_be_batchbuffer *
+intel_be_batchbuffer_alloc(struct intel_be_context *intel);
+
+void
+intel_be_batchbuffer_free(struct intel_be_batchbuffer *batch);
+
+void
+intel_be_batchbuffer_finish(struct intel_be_batchbuffer *batch);
+
+void
+intel_be_batchbuffer_flush(struct intel_be_batchbuffer *batch,
+                          struct intel_be_fence **fence);
+
+void
+intel_be_batchbuffer_reset(struct intel_be_batchbuffer *batch);
+
+int
+intel_be_offset_relocation(struct intel_be_batchbuffer *batch,
+                          unsigned pre_add,
+                          drm_intel_bo *bo,
+                          uint32_t read_domains,
+                          uint32_t write_doman);
+
+#endif
diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_context.c b/src/gallium/winsys/drm/intel/gem/intel_be_context.c
new file mode 100644 (file)
index 0000000..92fc2dd
--- /dev/null
@@ -0,0 +1,79 @@
+
+#include "intel_be_device.h"
+#include "intel_be_context.h"
+#include "intel_be_batchbuffer.h"
+
+#include "i915_drm.h"
+
+static struct i915_batchbuffer *
+intel_be_batch_get(struct i915_winsys *sws)
+{
+       struct intel_be_context *intel = intel_be_context(sws);
+       return &intel->batch->base;
+}
+
+static void
+intel_be_batch_reloc(struct i915_winsys *sws,
+                    struct pipe_buffer *buf,
+                    unsigned access_flags,
+                    unsigned delta)
+{
+       struct intel_be_context *intel = intel_be_context(sws);
+       drm_intel_bo *bo = intel_bo(buf);
+       int ret;
+       uint32_t read = 0;
+       uint32_t write = 0;
+
+       if (access_flags & I915_BUFFER_ACCESS_WRITE) {
+               write = I915_GEM_DOMAIN_RENDER;
+       }
+
+       if (access_flags & I915_BUFFER_ACCESS_READ) {
+               read = I915_GEM_DOMAIN_SAMPLER |
+                      I915_GEM_DOMAIN_INSTRUCTION |
+                      I915_GEM_DOMAIN_VERTEX;
+       }
+
+       ret = intel_be_offset_relocation(intel->batch,
+                                        delta,
+                                        bo,
+                                        read,
+                                        write);
+       /* TODO change return type */
+       /* return ret; */
+}
+
+static void
+intel_be_batch_flush(struct i915_winsys *sws,
+                    struct pipe_fence_handle **fence)
+{
+       struct intel_be_context *intel = intel_be_context(sws);
+       struct intel_be_fence **f = (struct intel_be_fence **)fence;
+
+       if (fence && *fence)
+               assert(0);
+
+       intel_be_batchbuffer_flush(intel->batch, f);
+}
+
+boolean
+intel_be_init_context(struct intel_be_context *intel, struct intel_be_device *device)
+{
+       assert(intel);
+       assert(device);
+       intel->device = device;
+
+       intel->base.batch_get = intel_be_batch_get;
+       intel->base.batch_reloc = intel_be_batch_reloc;
+       intel->base.batch_flush = intel_be_batch_flush;
+
+       intel->batch = intel_be_batchbuffer_alloc(intel);
+
+       return true;
+}
+
+void
+intel_be_destroy_context(struct intel_be_context *intel)
+{
+       intel_be_batchbuffer_free(intel->batch);
+}
diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_context.h b/src/gallium/winsys/drm/intel/gem/intel_be_context.h
new file mode 100644 (file)
index 0000000..9cee1a4
--- /dev/null
@@ -0,0 +1,48 @@
+
+#ifndef INTEL_BE_CONTEXT_H
+#define INTEL_BE_CONTEXT_H
+
+#include "i915simple/i915_winsys.h"
+
+struct intel_be_context
+{
+       /** Interface to i915simple driver */
+       struct i915_winsys base;
+
+       struct intel_be_device *device;
+       struct intel_be_batchbuffer *batch;
+
+       /*
+        * Hardware lock functions.
+        *
+        * Needs to be filled in by the winsys.
+        */
+       void (*hardware_lock)(struct intel_be_context *context);
+       void (*hardware_unlock)(struct intel_be_context *context);
+       boolean (*hardware_locked)(struct intel_be_context *context);
+};
+
+static INLINE struct intel_be_context *
+intel_be_context(struct i915_winsys *sws)
+{
+       return (struct intel_be_context *)sws;
+}
+
+/**
+ * Intialize a allocated intel_be_context struct.
+ *
+ * Remember to set the hardware_* functions.
+ */
+boolean
+intel_be_init_context(struct intel_be_context *intel,
+                     struct intel_be_device *device);
+
+/**
+ * Destroy a intel_be_context.
+ *
+ * Does not free the struct that is up to the winsys.
+ */
+void
+intel_be_destroy_context(struct intel_be_context *intel);
+
+#endif
diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_device.c b/src/gallium/winsys/drm/intel/gem/intel_be_device.c
new file mode 100644 (file)
index 0000000..cf0c140
--- /dev/null
@@ -0,0 +1,260 @@
+
+#include "intel_be_device.h"
+
+#include "pipe/p_winsys.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+
+#include "intel_be_fence.h"
+
+#include "i915simple/i915_screen.h"
+
+
+/**
+ *  Turn a pipe winsys into an intel/pipe winsys:
+ */
+static INLINE struct intel_be_device *
+intel_be_device(struct pipe_winsys *winsys)
+{
+       return (struct intel_be_device *)winsys;
+}
+
+/*
+ * Buffer
+ */
+
+static void *
+intel_be_buffer_map(struct pipe_winsys *winsys,
+                   struct pipe_buffer *buf,
+                   unsigned flags)
+{
+       drm_intel_bo *bo = intel_bo(buf);
+       int write = 0;
+       int ret;
+
+       if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
+               write = 1;
+
+       ret = drm_intel_bo_map(bo, write);
+
+       if (ret)
+               return NULL;
+
+       return bo->virtual;
+}
+
+static void
+intel_be_buffer_unmap(struct pipe_winsys *winsys,
+                     struct pipe_buffer *buf)
+{
+       drm_intel_bo_unmap(intel_bo(buf));
+}
+
+static void
+intel_be_buffer_destroy(struct pipe_winsys *winsys,
+                       struct pipe_buffer *buf)
+{
+       drm_intel_bo_unreference(intel_bo(buf));
+       free(buf);
+}
+
+static struct pipe_buffer *
+intel_be_buffer_create(struct pipe_winsys *winsys,
+                      unsigned alignment,
+                      unsigned usage,
+                      unsigned size)
+{
+       struct intel_be_buffer *buffer = CALLOC_STRUCT(intel_be_buffer);
+       struct intel_be_device *dev = intel_be_device(winsys);
+       drm_intel_bufmgr *pool;
+       char *name;
+
+       if (!buffer)
+               return NULL;
+
+       buffer->base.refcount = 1;
+       buffer->base.alignment = alignment;
+       buffer->base.usage = usage;
+       buffer->base.size = size;
+
+       if (usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_CONSTANT)) {
+               /* Local buffer */
+               name = "gallium3d_local";
+               pool = dev->pools.gem;
+       } else if (usage & PIPE_BUFFER_USAGE_CUSTOM) {
+               /* For vertex buffers */
+               name = "gallium3d_internal_vertex";
+               pool = dev->pools.gem;
+       } else {
+               /* Regular buffers */
+               name = "gallium3d_regular";
+               pool = dev->pools.gem;
+       }
+
+       buffer->bo = drm_intel_bo_alloc(pool, name, size, alignment);
+
+       if (!buffer->bo)
+               goto err;
+
+       return &buffer->base;
+
+err:
+       free(buffer);
+       return NULL;
+}
+
+static struct pipe_buffer *
+intel_be_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes)
+{
+       struct intel_be_buffer *buffer = CALLOC_STRUCT(intel_be_buffer);
+       struct intel_be_device *dev = intel_be_device(winsys);
+       int ret;
+
+       if (!buffer)
+               return NULL;
+
+       buffer->base.refcount = 1;
+       buffer->base.alignment = 0;
+       buffer->base.usage = 0;
+       buffer->base.size = bytes;
+
+       buffer->bo = drm_intel_bo_alloc(dev->pools.gem,
+                                       "gallium3d_user_buffer",
+                                       bytes, 0);
+
+       if (!buffer->bo)
+               goto err;
+
+       ret = drm_intel_bo_subdata(buffer->bo,
+                                  0, bytes, ptr);
+
+       if (ret)
+               goto err;
+
+       return &buffer->base;
+
+err:
+       free(buffer);
+       return NULL;
+}
+
+struct pipe_buffer *
+intel_be_buffer_from_handle(struct intel_be_device *dev,
+                           const char* name, unsigned handle)
+{
+       struct intel_be_buffer *buffer = CALLOC_STRUCT(intel_be_buffer);
+
+       if (!buffer)
+               return NULL;
+
+       buffer->bo = drm_intel_bo_gem_create_from_name(dev->pools.gem, name, handle);
+
+       if (!buffer->bo)
+               goto err;
+
+       buffer->base.refcount = 1;
+       buffer->base.alignment = buffer->bo->align;
+       buffer->base.usage = PIPE_BUFFER_USAGE_GPU_READ |
+                            PIPE_BUFFER_USAGE_GPU_WRITE |
+                            PIPE_BUFFER_USAGE_CPU_READ |
+                            PIPE_BUFFER_USAGE_CPU_WRITE;
+       buffer->base.size = buffer->bo->size;
+
+       return &buffer->base;
+
+err:
+       free(buffer);
+       return NULL;
+}
+
+/*
+ * Fence
+ */
+
+static void
+intel_be_fence_refunref(struct pipe_winsys *sws,
+                        struct pipe_fence_handle **ptr,
+                        struct pipe_fence_handle *fence)
+{
+       struct intel_be_fence **p = (struct intel_be_fence **)ptr;
+       struct intel_be_fence *f = (struct intel_be_fence *)fence;
+
+       assert(p);
+
+       if (f)
+               intel_be_fence_reference(f);
+
+       if (*p)
+               intel_be_fence_unreference(*p);
+
+       *p = f;
+}
+
+static int
+intel_be_fence_signalled(struct pipe_winsys *sws,
+                        struct pipe_fence_handle *fence,
+                        unsigned flag)
+{
+       assert(0);
+
+       return 0;
+}
+
+static int
+intel_be_fence_finish(struct pipe_winsys *sws,
+                     struct pipe_fence_handle *fence,
+                     unsigned flag)
+{
+       struct intel_be_fence *f = (struct intel_be_fence *)fence;
+
+       /* fence already expired */
+       if (!f->bo)
+               return 0;
+
+       drm_intel_bo_wait_rendering(f->bo);
+       drm_intel_bo_unreference(f->bo);
+       f->bo = NULL;
+
+       return 0;
+}
+
+/*
+ * Misc functions
+ */
+
+boolean
+intel_be_init_device(struct intel_be_device *dev, int fd, unsigned id)
+{
+       dev->fd = fd;
+       dev->max_batch_size = 16 * 4096;
+       dev->max_vertex_size = 128 * 4096;
+
+       dev->base.buffer_create = intel_be_buffer_create;
+       dev->base.user_buffer_create = intel_be_user_buffer_create;
+       dev->base.buffer_map = intel_be_buffer_map;
+       dev->base.buffer_unmap = intel_be_buffer_unmap;
+       dev->base.buffer_destroy = intel_be_buffer_destroy;
+
+       /* Not used anymore */
+       dev->base.surface_alloc = NULL;
+       dev->base.surface_alloc_storage = NULL;
+       dev->base.surface_release = NULL;
+
+       dev->base.fence_reference = intel_be_fence_refunref;
+       dev->base.fence_signalled = intel_be_fence_signalled;
+       dev->base.fence_finish = intel_be_fence_finish;
+
+       dev->pools.gem = drm_intel_bufmgr_gem_init(dev->fd, dev->max_batch_size);
+
+       dev->screen = i915_create_screen(&dev->base, id);
+
+       return true;
+}
+
+void
+intel_be_destroy_device(struct intel_be_device *dev)
+{
+       drm_intel_bufmgr_destroy(dev->pools.gem);
+}
diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_device.h b/src/gallium/winsys/drm/intel/gem/intel_be_device.h
new file mode 100644 (file)
index 0000000..53d6353
--- /dev/null
@@ -0,0 +1,70 @@
+
+#ifndef INTEL_DRM_DEVICE_H
+#define INTEL_DRM_DEVICE_H
+
+#include "pipe/p_winsys.h"
+#include "pipe/p_context.h"
+
+#include "drm.h"
+#include "intel_bufmgr.h"
+
+/*
+ * Device
+ */
+
+struct intel_be_device
+{
+       struct pipe_winsys base;
+
+       /**
+        * Hw level screen
+        */
+       struct pipe_screen *screen;
+
+       int fd; /**< Drm file discriptor */
+
+       size_t max_batch_size;
+       size_t max_vertex_size;
+
+       struct {
+               drm_intel_bufmgr *gem;
+       } pools;
+};
+
+boolean
+intel_be_init_device(struct intel_be_device *device, int fd, unsigned id);
+
+void
+intel_be_destroy_device(struct intel_be_device *dev);
+
+/*
+ * Buffer
+ */
+
+struct intel_be_buffer {
+       struct pipe_buffer base;
+       drm_intel_bo *bo;
+};
+
+/**
+ * Create a be buffer from a drm bo handle
+ *
+ * Takes a reference
+ */
+struct pipe_buffer *
+intel_be_buffer_from_handle(struct intel_be_device *device,
+                            const char* name, unsigned handle);
+
+static INLINE struct intel_be_buffer *
+intel_be_buffer(struct pipe_buffer *buf)
+{
+       return (struct intel_be_buffer *)buf;
+}
+
+static INLINE drm_intel_bo *
+intel_bo(struct pipe_buffer *buf)
+{
+       return intel_be_buffer(buf)->bo;
+}
+
+#endif
diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_fence.h b/src/gallium/winsys/drm/intel/gem/intel_be_fence.h
new file mode 100644 (file)
index 0000000..0fe18f6
--- /dev/null
@@ -0,0 +1,38 @@
+
+#ifndef INTEL_BE_FENCE_H
+#define INTEL_BE_FENCE_H
+
+#include "pipe/p_defines.h"
+
+#include "drm.h"
+#include "intel_bufmgr.h"
+
+/**
+ * Because gem does not have fence's we have to create our own fences.
+ *
+ * They work by keeping the batchbuffer around and checking if that has
+ * been idled. If bo is NULL fence has expired.
+ */
+struct intel_be_fence
+{
+       uint32_t refcount;
+       drm_intel_bo *bo;
+};
+
+static INLINE void
+intel_be_fence_reference(struct intel_be_fence *f)
+{
+       f->refcount++;
+}
+
+static INLINE void
+intel_be_fence_unreference(struct intel_be_fence *f)
+{
+       if (!--f->refcount) {
+               if (f->bo)
+                       drm_intel_bo_unreference(f->bo);
+               free(f);
+       }
+}
+
+#endif