summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk_cubox@arm.linux.org.uk>2013-05-05 13:48:04 +0100
committerRussell King <rmk@arm.linux.org.uk>2013-05-05 16:36:41 +0100
commit38c232e6ae0b9eed2b15146bd940f95c9f0b36b7 (patch)
treeb2340ad81adb4a9817e103156e5ec524ca24b6e8
parent41aecd32dee1306351b411571284877c11768ac3 (diff)
Caching support - v2
* Re-vamp API to allow a buffer manager object, stop passing fd into every function. * Add caching support Signed-off-by: Russell King <rmk_cubox@arm.linux.org.uk>
-rw-r--r--Makefile.am7
-rw-r--r--configure.ac7
-rw-r--r--debian/changelog8
-rw-r--r--debian/control13
-rw-r--r--debian/libdrm-dove1.install1
-rw-r--r--debian/libdrm-dove1.postinst.debhelper5
-rw-r--r--debian/libdrm-dove1.postrm.debhelper5
-rw-r--r--debian/libdrm-dove2.install1
-rwxr-xr-xdebian/rules2
-rw-r--r--dove_bufmgr.c368
-rw-r--r--dove_bufmgr.h30
-rw-r--r--libdrm_lists.h89
12 files changed, 444 insertions, 92 deletions
diff --git a/Makefile.am b/Makefile.am
index b628087..3f0c0e4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,11 +4,12 @@ AM_CFLAGS = $(WARN_CFLAGS) @LIBDRM_CFLAGS@
libdrm_dove_la_LTLIBRARIES = libdrm_dove.la
libdrm_dove_ladir = $(libdir)
-libdrm_dove_la_LDFLAGS = -version-number 1:0:0 -no-undefined
-libdrm_dove_la_LIBADD = @LIBDRM_LIBS@
+libdrm_dove_la_LDFLAGS = -version-info 2:0:0 -no-undefined
+libdrm_dove_la_LIBADD = @LIBDRM_LIBS@ @CLOCK_LIB@
libdrm_dove_la_SOURCES = \
- dove_bufmgr.c
+ dove_bufmgr.c \
+ libdrm_lists.h
libdrm_doveincludedir = ${includedir}/libdrm
libdrm_doveinclude_HEADERS = dove_bufmgr.h
diff --git a/configure.ac b/configure.ac
index 8553fc1..0d5e518 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
AC_PREREQ([2.63])
-AC_INIT([libdrm_dove], [1.0.0], [], [libdrm_dove])
+AC_INIT([libdrm_dove], [2.0.0], [], [libdrm_dove])
AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_MACRO_DIR([m4])
@@ -20,6 +20,11 @@ AC_USE_SYSTEM_EXTENSIONS
LT_PREREQ([2.2])
LT_INIT([disable-static])
+AC_CHECK_FUNCS([clock_gettime], [CLOCK_LIB=],
+ [AC_CHECK_LIB([rt], [clock_gettime], [CLOCK_LIB=-lrt],
+ [AC_MSG_ERROR([Could not find clock_gettime])])])
+AC_SUBST([CLOCK_LIB])
+
PKG_CHECK_MODULES(LIBDRM, libdrm)
AC_SUBST(LIBDRM_CFLAGS)
AC_SUBST(LIBDRM_LIBS)
diff --git a/debian/changelog b/debian/changelog
index 5ec6932..95e7cd7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+libdrm-dove (2.0.0-1) unstable; urgency=low
+
+ * Re-vamp API to allow a buffer manager object, stop passing fd into
+ every function.
+ * Add caching support
+
+ -- Russell King <rmk_cubox@arm.linux.org.uk> Sun, 5 May 2013 13:47:28 +0100
+
libdrm-dove (1.0.1-1) unstable; urgency=low
* Add drm_dove_bo_create_from_name()
diff --git a/debian/control b/debian/control
index 6799de2..efbf3d0 100644
--- a/debian/control
+++ b/debian/control
@@ -13,7 +13,7 @@ Package: libdrm-dove-dev
Section: libdevel
Architecture: any
Depends:
- libdrm-dove1 (= ${binary:Version}),
+ libdrm-dove2 (= ${binary:Version}),
${misc:Depends},
Description: Userspace interface to kernel DRM services -- development files
This library implements the userspace interface to the kernel DRM
@@ -22,9 +22,9 @@ Description: Userspace interface to kernel DRM services -- development files
The DRI is currently used on Linux to provide hardware-accelerated
OpenGL drivers.
.
- This package provides the development environment for libdrm-dove1.
+ This package provides the development environment for libdrm-dove2.
-Package: libdrm-dove1
+Package: libdrm-dove2
Section: libs
Priority: extra
Architecture: linux-any
@@ -40,14 +40,13 @@ Description: Userspace interface to kernel DRM services -- runtime
The DRI is currently used on Linux to provide hardware-accelerated
OpenGL drivers.
.
- This package provides the runtime environment for libdrm-dove1.
+ This package provides the runtime environment for libdrm-dove2.
-Package: libdrm-dove1-dbg
+Package: libdrm-dove2-dbg
Section: debug
Priority: extra
Architecture: linux-any
Depends:
- libdrm2 (= ${binary:Version}),
${misc:Depends},
Multi-Arch: same
Description: Userspace interface to kernel DRM services -- debugging symbols
@@ -57,4 +56,4 @@ Description: Userspace interface to kernel DRM services -- debugging symbols
The DRI is currently used on Linux to provide hardware-accelerated
OpenGL drivers.
.
- This package provides debugging symbols for the libdrm-dove1 package.
+ This package provides debugging symbols for the libdrm-dove2 package.
diff --git a/debian/libdrm-dove1.install b/debian/libdrm-dove1.install
deleted file mode 100644
index 99c7f23..0000000
--- a/debian/libdrm-dove1.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/*/libdrm_dove.so.1*
diff --git a/debian/libdrm-dove1.postinst.debhelper b/debian/libdrm-dove1.postinst.debhelper
deleted file mode 100644
index 3d89d3e..0000000
--- a/debian/libdrm-dove1.postinst.debhelper
+++ /dev/null
@@ -1,5 +0,0 @@
-# Automatically added by dh_makeshlibs
-if [ "$1" = "configure" ]; then
- ldconfig
-fi
-# End automatically added section
diff --git a/debian/libdrm-dove1.postrm.debhelper b/debian/libdrm-dove1.postrm.debhelper
deleted file mode 100644
index 7f44047..0000000
--- a/debian/libdrm-dove1.postrm.debhelper
+++ /dev/null
@@ -1,5 +0,0 @@
-# Automatically added by dh_makeshlibs
-if [ "$1" = "remove" ]; then
- ldconfig
-fi
-# End automatically added section
diff --git a/debian/libdrm-dove2.install b/debian/libdrm-dove2.install
new file mode 100644
index 0000000..c131245
--- /dev/null
+++ b/debian/libdrm-dove2.install
@@ -0,0 +1 @@
+usr/lib/*/libdrm_dove.so.2*
diff --git a/debian/rules b/debian/rules
index 00c9b22..cc315f2 100755
--- a/debian/rules
+++ b/debian/rules
@@ -15,7 +15,7 @@ override_dh_install:
dh_install --fail-missing
override_dh_strip:
- dh_strip -plibdrm-dove1 --dbg-package=libdrm-dove1-dbg
+ dh_strip -plibdrm-dove2 --dbg-package=libdrm-dove2-dbg
dh_strip -s --remaining-packages
%:
diff --git a/dove_bufmgr.c b/dove_bufmgr.c
index 32e192a..eb2596b 100644
--- a/dove_bufmgr.c
+++ b/dove_bufmgr.c
@@ -4,9 +4,11 @@
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
+#include <time.h>
#include <drm.h>
+#include "libdrm_lists.h"
#include "dove_bufmgr.h"
#include "dove_ioctl.h"
@@ -16,10 +18,58 @@
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
+/* The interval in seconds between cache cleans */
+#define BO_CACHE_CLEAN_INTERVAL 1
+/* The maximum age in seconds of a BO in the cache */
+#define BO_CACHE_MAX_AGE 2
+/* Number of buckets in the BO cache */
+#define NUM_BUCKETS (3*9)
+
+/*
+ * These sizes come from the i915 DRM backend - which uses roughly
+ * for n = 2..
+ * (4096 << n) + (4096 << n) * 1 / 4
+ * (4096 << n) + (4096 << n) * 2 / 4
+ * (4096 << n) + (4096 << n) * 3 / 4
+ * The reasoning being that powers of two are too wasteful in X.
+ */
+static size_t bucket_size[NUM_BUCKETS] = {
+ 4096, 8192, 12288,
+ 20480, 24576, 28672,
+ 40960, 49152, 57344,
+ 81920, 98304, 114688,
+ 163840, 196608, 229376,
+ 327680, 393216, 458752,
+ 655360, 786432, 917504,
+ 1310720, 1572864, 1835008,
+ 2621440, 3145728, 3670016,
+};
+
+struct dove_bucket {
+ drmMMListHead head; /* LRU list of bos in this size */
+ size_t size;
+};
+
+struct dove_bo_cache {
+ struct dove_bucket buckets[NUM_BUCKETS];
+ drmMMListHead head; /* LRU list of all freed bos */
+ time_t last_cleaned;
+};
+
+struct drm_dove_bufmgr {
+ struct dove_bo_cache cache;
+ int fd;
+};
+
struct dove_bo {
struct drm_dove_bo bo;
- uint32_t ref;
- uint32_t name; /* Global name */
+ struct drm_dove_bufmgr *mgr; /* manager associated with this bo */
+ drmMMListHead bucket; /* Cache bucket list */
+ drmMMListHead free; /* Free list */
+ time_t free_time; /* Time this bo was freed */
+ size_t alloc_size; /* Allocated size */
+ uint32_t ref; /* Reference count */
+ uint32_t name; /* Global name */
};
#define to_dove_bo(_bo) container_of(_bo, struct dove_bo, bo)
@@ -55,9 +105,164 @@ struct drm_mode_map_dumb {
#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb)
#endif
-struct drm_dove_bo *drm_dove_bo_create_phys(int fd, uint32_t phys, size_t size)
+/* Given a width and bpp, return the pitch of a bo */
+static unsigned dove_bo_pitch(unsigned width, unsigned bpp)
+{
+ unsigned pitch = bpp != 4 ? width * ((bpp + 7) / 8) : width / 2;
+
+ /* 88AP510 spec recommends pitch be a multiple of 128 */
+ return (pitch + 127) & ~127;
+}
+
+/* Given the pitch and height, return the allocated size in bytes of a bo */
+static size_t dove_bo_size(unsigned pitch, unsigned height)
+{
+ return pitch * height;
+}
+
+static size_t dove_bo_round_size(size_t size)
+{
+ if (size > 1048576)
+ size = (size + 1048575) & ~1048575;
+ else if (size > 65536)
+ size = (size + 65535) & ~65535;
+ else
+ size = (size + 4095) & ~4095;
+ return size;
+}
+
+static void dove_bo_free(struct dove_bo *bo)
+{
+ int ret, fd = bo->mgr->fd;
+
+ if (bo->bo.ptr) {
+ munmap(bo->bo.ptr, bo->alloc_size);
+ bo->bo.ptr = NULL;
+ }
+
+ if (bo->bo.type == DRM_DOVE_BO_DUMB) {
+ struct drm_mode_destroy_dumb arg;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = bo->bo.handle;
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
+ } else {
+ struct drm_gem_close close;
+
+ memset(&close, 0, sizeof(close));
+ close.handle = bo->bo.handle;
+ ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close);
+ }
+
+ if (ret == 0)
+ free(bo);
+}
+
+static void dove_bo_cache_init(struct dove_bo_cache *cache)
+{
+ struct timespec time;
+ unsigned i;
+
+ clock_gettime(CLOCK_MONOTONIC, &time);
+
+ cache->last_cleaned = time.tv_sec;
+ DRMINITLISTHEAD(&cache->head);
+
+ for (i = 0; i < NUM_BUCKETS; i++) {
+ DRMINITLISTHEAD(&cache->buckets[i].head);
+ cache->buckets[i].size = bucket_size[i];
+ }
+}
+
+static void dove_bo_cache_fini(struct dove_bo_cache *cache)
+{
+ while (!DRMLISTEMPTY(&cache->head)) {
+ struct dove_bo *bo;
+
+ bo = DRMLISTENTRY(struct dove_bo, cache->head.next, free);
+
+ DRMLISTDEL(&bo->bucket);
+ DRMLISTDEL(&bo->free);
+
+ dove_bo_free(bo);
+ }
+}
+
+static struct dove_bucket *dove_find_bucket(struct dove_bo_cache *cache, size_t size)
+{
+ unsigned i;
+
+ for (i = 0; i < NUM_BUCKETS; i++) {
+ struct dove_bucket *bucket = &cache->buckets[i];
+
+ if (bucket->size >= size)
+ return bucket;
+ }
+
+ return NULL;
+}
+
+static void dove_bo_cache_clean(struct dove_bo_cache *cache, time_t time)
+{
+ if (time - cache->last_cleaned < BO_CACHE_CLEAN_INTERVAL)
+ return;
+
+ cache->last_cleaned = time;
+
+ while (!DRMLISTEMPTY(&cache->head)) {
+ struct dove_bo *bo;
+
+ bo = DRMLISTENTRY(struct dove_bo, cache->head.next, free);
+ if (time - bo->free_time < BO_CACHE_MAX_AGE)
+ break;
+
+ DRMLISTDEL(&bo->bucket);
+ DRMLISTDEL(&bo->free);
+
+ dove_bo_free(bo);
+ }
+}
+
+static struct dove_bo *dove_bo_bucket_get(struct dove_bucket *bucket, size_t size)
+{
+ struct dove_bo *bo = NULL;
+
+ if (!DRMLISTEMPTY(&bucket->head)) {
+ drmMMListHead *entry = bucket->head.next;
+
+ bo = DRMLISTENTRY(struct dove_bo, entry, bucket);
+ DRMLISTDEL(&bo->bucket);
+ DRMLISTDEL(&bo->free);
+ }
+ return bo;
+}
+
+static void dove_bo_cache_put(struct dove_bo *bo)
+{
+ struct dove_bo_cache *cache = &bo->mgr->cache;
+ struct dove_bucket *bucket = dove_find_bucket(cache, bo->alloc_size);
+
+ if (bucket) {
+ struct timespec time;
+
+ clock_gettime(CLOCK_MONOTONIC, &time);
+
+ bo->free_time = time.tv_sec;
+ DRMLISTADDTAIL(&bo->bucket, &bucket->head);
+ DRMLISTADDTAIL(&bo->free, &cache->head);
+
+ dove_bo_cache_clean(cache, time.tv_sec);
+
+ return;
+ }
+ dove_bo_free(bo);
+}
+
+struct drm_dove_bo *drm_dove_bo_create_phys(struct drm_dove_bufmgr *mgr,
+ uint32_t phys, size_t size)
{
struct dove_bo *bo;
+ int fd = mgr->fd;
bo = calloc(1, sizeof *bo);
if (bo) {
@@ -78,44 +283,80 @@ struct drm_dove_bo *drm_dove_bo_create_phys(int fd, uint32_t phys, size_t size)
bo->bo.size = size;
bo->bo.phys = phys;
bo->bo.type = DRM_DOVE_BO_LINEAR;
+ bo->alloc_size = size;
bo->ref = 1;
+ bo->mgr = mgr;
}
return &bo->bo;
}
-struct drm_dove_bo *drm_dove_bo_create(int fd, unsigned w, unsigned h, unsigned bpp)
+struct drm_dove_bo *drm_dove_bo_create(struct drm_dove_bufmgr *mgr,
+ unsigned w, unsigned h, unsigned bpp)
{
+ struct drm_dove_gem_create arg;
+ struct dove_bucket *bucket;
struct dove_bo *bo;
+ unsigned pitch;
+ size_t alloc_size;
+ int fd = mgr->fd;
+ int ret;
- bo = calloc(1, sizeof *bo);
- if (bo) {
- struct drm_dove_gem_create arg;
- int ret;
+ pitch = dove_bo_pitch(w, bpp);
+ alloc_size = dove_bo_size(pitch, h);
+
+ /* Try to find a bucket for this allocation */
+ bucket = dove_find_bucket(&mgr->cache, alloc_size);
+ if (bucket) {
+ /* Can we allocate from our cache? */
+ bo = dove_bo_bucket_get(bucket, alloc_size);
+ if (bo) {
+ bo->bo.size = pitch * h;
+ bo->bo.pitch = pitch;
+ bo->ref = 1;
+ return &bo->bo;
+ }
- memset(&arg, 0, sizeof(arg));
- arg.width = w;
- arg.height = h;
- arg.bpp = bpp;
+ /* Otherwise, allocate a bo of the bucket size */
+ alloc_size = bucket->size;
+ } else {
+ /* No bucket, so round the size up according to our old rules */
+ alloc_size = dove_bo_round_size(alloc_size);
+ }
- ret = drmIoctl(fd, DRM_IOCTL_DOVE_GEM_CREATE, &arg);
- if (ret) {
- free(bo);
- return NULL;
- }
+ /* No, create a new bo */
+ bo = calloc(1, sizeof *bo);
+ if (!bo)
+ return NULL;
- bo->bo.ref = 1;
- bo->bo.handle = arg.handle;
- bo->bo.size = arg.size;
- bo->bo.pitch = arg.pitch;
- bo->bo.type = DRM_DOVE_BO_SHMEM;
- bo->ref = 1;
+ memset(&arg, 0, sizeof(arg));
+ arg.width = w;
+ arg.height = h;
+ arg.bpp = bpp;
+ arg.size = alloc_size;
+
+ ret = drmIoctl(fd, DRM_IOCTL_DOVE_GEM_CREATE, &arg);
+ if (ret) {
+ free(bo);
+ return NULL;
}
+
+ bo->bo.ref = 1;
+ bo->bo.handle = arg.handle;
+ bo->bo.size = pitch * h;
+ bo->bo.pitch = pitch;
+ bo->bo.type = DRM_DOVE_BO_SHMEM;
+ bo->alloc_size = alloc_size;
+ bo->ref = 1;
+ bo->mgr = mgr;
+
return &bo->bo;
}
-struct drm_dove_bo *drm_dove_bo_create_from_name(int fd, uint32_t name)
+struct drm_dove_bo *drm_dove_bo_create_from_name(struct drm_dove_bufmgr *mgr,
+ uint32_t name)
{
struct dove_bo *bo;
+ int fd = mgr->fd;
bo = calloc(1, sizeof *bo);
if (bo) {
@@ -133,16 +374,19 @@ struct drm_dove_bo *drm_dove_bo_create_from_name(int fd, uint32_t name)
bo->bo.handle = arg.handle;
bo->bo.size = arg.size;
bo->bo.type = DRM_DOVE_BO_LINEAR; /* assumed */
+ bo->alloc_size = arg.size;
bo->ref = 1;
bo->name = name;
+ bo->mgr = mgr;
}
return &bo->bo;
}
-struct drm_dove_bo *drm_dove_bo_dumb_create(int fd, unsigned w, unsigned h,
- unsigned bpp)
+struct drm_dove_bo *drm_dove_bo_dumb_create(struct drm_dove_bufmgr *mgr,
+ unsigned w, unsigned h, unsigned bpp)
{
struct dove_bo *bo;
+ int fd = mgr->fd;
bo = calloc(1, sizeof *bo);
if (bo) {
@@ -164,51 +408,37 @@ struct drm_dove_bo *drm_dove_bo_dumb_create(int fd, unsigned w, unsigned h,
bo->bo.size = arg.size;
bo->bo.pitch = arg.pitch;
bo->bo.type = DRM_DOVE_BO_DUMB;
+ bo->alloc_size = arg.size;
bo->ref = 1;
+ bo->mgr = mgr;
}
return &bo->bo;
}
-void drm_dove_bo_get(int fd, struct drm_dove_bo *dbo)
+void drm_dove_bo_get(struct drm_dove_bo *dbo)
{
struct dove_bo *bo = to_dove_bo(dbo);
bo->ref++;
}
-void drm_dove_bo_put(int fd, struct drm_dove_bo *dbo)
+void drm_dove_bo_put(struct drm_dove_bo *dbo)
{
struct dove_bo *bo = to_dove_bo(dbo);
if (bo->ref-- == 1) {
int ret;
- if (bo->bo.ptr) {
- munmap(bo->bo.ptr, bo->bo.size);
- bo->bo.ptr = NULL;
- }
-
- if (bo->bo.type == DRM_DOVE_BO_DUMB) {
- struct drm_mode_destroy_dumb arg;
-
- memset(&arg, 0, sizeof(arg));
- arg.handle = bo->bo.handle;
- ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
- } else {
- struct drm_gem_close close;
-
- memset(&close, 0, sizeof(close));
- close.handle = bo->bo.handle;
- ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close);
- }
-
- if (ret == 0)
- free(bo);
+ if (bo->bo.type == DRM_DOVE_BO_SHMEM)
+ dove_bo_cache_put(bo);
+ else
+ dove_bo_free(bo);
}
}
-int drm_dove_bo_flink(int fd, struct drm_dove_bo *dbo, uint32_t *name)
+int drm_dove_bo_flink(struct drm_dove_bo *dbo, uint32_t *name)
{
struct dove_bo *bo = to_dove_bo(dbo);
+ int fd = bo->mgr->fd;
if (!bo->name) {
struct drm_gem_flink flink;
@@ -225,11 +455,11 @@ int drm_dove_bo_flink(int fd, struct drm_dove_bo *dbo, uint32_t *name)
return 0;
}
-int drm_dove_bo_map(int fd, struct drm_dove_bo *dbo)
+int drm_dove_bo_map(struct drm_dove_bo *dbo)
{
struct dove_bo *bo = to_dove_bo(dbo);
void *map;
- int ret;
+ int ret, fd = bo->mgr->fd;
if (bo->bo.ptr)
return 0;
@@ -244,7 +474,7 @@ int drm_dove_bo_map(int fd, struct drm_dove_bo *dbo)
if (ret)
return ret;
- map = mmap(0, bo->bo.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ map = mmap(0, bo->alloc_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
arg.offset);
if (map == MAP_FAILED)
@@ -255,7 +485,7 @@ int drm_dove_bo_map(int fd, struct drm_dove_bo *dbo)
memset(&arg, 0, sizeof(arg));
arg.handle = bo->bo.handle;
arg.offset = 0;
- arg.size = bo->bo.size;
+ arg.size = bo->alloc_size;
ret = drmIoctl(fd, DRM_IOCTL_DOVE_GEM_MMAP, &arg);
if (ret)
@@ -272,11 +502,11 @@ int drm_dove_bo_map(int fd, struct drm_dove_bo *dbo)
return 0;
}
-uint32_t drm_dove_bo_phys(int fd, struct drm_dove_bo *dbo)
+uint32_t drm_dove_bo_phys(struct drm_dove_bo *dbo)
{
struct dove_bo *bo = to_dove_bo(dbo);
struct drm_dove_gem_prop arg;
- int ret;
+ int ret, fd = bo->mgr->fd;
memset(&arg, 0, sizeof(arg));
arg.handle = bo->bo.handle;
@@ -286,13 +516,15 @@ uint32_t drm_dove_bo_phys(int fd, struct drm_dove_bo *dbo)
return ret ? -1 : (uint32_t)arg.phys;
}
-int drm_dove_bo_subdata(int fd, struct drm_dove_bo *bo, unsigned long offset,
+int drm_dove_bo_subdata(struct drm_dove_bo *dbo, unsigned long offset,
unsigned long size, const void *data)
{
+ struct dove_bo *bo = to_dove_bo(dbo);
struct drm_dove_gem_pwrite arg;
+ int fd = bo->mgr->fd;
memset(&arg, 0, sizeof(arg));
- arg.handle = bo->handle;
+ arg.handle = bo->bo.handle;
arg.offset = offset;
arg.size = size;
arg.ptr = (uint64_t)(uintptr_t)data;
@@ -300,3 +532,23 @@ int drm_dove_bo_subdata(int fd, struct drm_dove_bo *bo, unsigned long offset,
return drmIoctl(fd, DRM_IOCTL_DOVE_GEM_PWRITE, &arg);
}
+int drm_dove_init(int fd, struct drm_dove_bufmgr **mgrp)
+{
+ struct drm_dove_bufmgr *mgr;
+
+ mgr = calloc(1, sizeof(*mgr));
+ if (!mgr)
+ return -1;
+
+ dove_bo_cache_init(&mgr->cache);
+ mgr->fd = fd;
+ *mgrp = mgr;
+
+ return 0;
+}
+
+void drm_dove_fini(struct drm_dove_bufmgr *mgr)
+{
+ dove_bo_cache_fini(&mgr->cache);
+ free(mgr);
+}
diff --git a/dove_bufmgr.h b/dove_bufmgr.h
index 88918f6..18fae64 100644
--- a/dove_bufmgr.h
+++ b/dove_bufmgr.h
@@ -7,6 +7,8 @@ enum drm_dove_bo_type {
DRM_DOVE_BO_SHMEM
};
+struct drm_dove_bufmgr;
+
struct drm_dove_bo {
uint32_t ref;
uint32_t handle;
@@ -17,22 +19,28 @@ struct drm_dove_bo {
enum drm_dove_bo_type type;
};
-struct drm_dove_bo *drm_dove_bo_create(int fd, unsigned w, unsigned h, unsigned bpp);
-struct drm_dove_bo *drm_dove_bo_create_phys(int fd, uint32_t phys, size_t size);
-struct drm_dove_bo *drm_dove_bo_dumb_create(int fd, unsigned w, unsigned h,
- unsigned bpp);
+int drm_dove_init(int fd, struct drm_dove_bufmgr **mgr);
+void drm_dove_fini(struct drm_dove_bufmgr *);
+
+struct drm_dove_bo *drm_dove_bo_create(struct drm_dove_bufmgr *,
+ unsigned w, unsigned h, unsigned bpp);
+struct drm_dove_bo *drm_dove_bo_create_phys(struct drm_dove_bufmgr *,
+ uint32_t phys, size_t size);
+struct drm_dove_bo *drm_dove_bo_dumb_create(struct drm_dove_bufmgr *,
+ unsigned w, unsigned h, unsigned bpp);
/* Create a BO from a global name */
-struct drm_dove_bo *drm_dove_bo_create_from_name(int fd, uint32_t name);
+struct drm_dove_bo *drm_dove_bo_create_from_name(struct drm_dove_bufmgr *,
+ uint32_t name);
/* Create a global name from a BO */
-int drm_dove_bo_flink(int fd, struct drm_dove_bo *bo, uint32_t *name);
+int drm_dove_bo_flink(struct drm_dove_bo *bo, uint32_t *name);
-int drm_dove_bo_map(int fd, struct drm_dove_bo *bo);
-uint32_t drm_dove_bo_phys(int fd, struct drm_dove_bo *bo);
-void drm_dove_bo_get(int fd, struct drm_dove_bo *bo);
-void drm_dove_bo_put(int fd, struct drm_dove_bo *bo);
-int drm_dove_bo_subdata(int fd, struct drm_dove_bo *bo, unsigned long offset,
+int drm_dove_bo_map(struct drm_dove_bo *bo);
+uint32_t drm_dove_bo_phys(struct drm_dove_bo *bo);
+void drm_dove_bo_get(struct drm_dove_bo *bo);
+void drm_dove_bo_put(struct drm_dove_bo *bo);
+int drm_dove_bo_subdata(struct drm_dove_bo *bo, unsigned long offset,
unsigned long size, const void *data);
#endif
diff --git a/libdrm_lists.h b/libdrm_lists.h
new file mode 100644
index 0000000..6410f57
--- /dev/null
+++ b/libdrm_lists.h
@@ -0,0 +1,89 @@
+/**************************************************************************
+ *
+ * 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.
+ */
+
+/*
+ * List macros heavily inspired by the Linux kernel
+ * list handling. No list looping yet.
+ */
+
+#include <stddef.h>
+
+typedef struct _drmMMListHead
+{
+ struct _drmMMListHead *prev;
+ struct _drmMMListHead *next;
+} drmMMListHead;
+
+#define DRMINITLISTHEAD(__item) \
+ do{ \
+ (__item)->prev = (__item); \
+ (__item)->next = (__item); \
+ } while (0)
+
+#define DRMLISTADD(__item, __list) \
+ do { \
+ (__item)->prev = (__list); \
+ (__item)->next = (__list)->next; \
+ (__list)->next->prev = (__item); \
+ (__list)->next = (__item); \
+ } while (0)
+
+#define DRMLISTADDTAIL(__item, __list) \
+ do { \
+ (__item)->next = (__list); \
+ (__item)->prev = (__list)->prev; \
+ (__list)->prev->next = (__item); \
+ (__list)->prev = (__item); \
+ } while(0)
+
+#define DRMLISTDEL(__item) \
+ do { \
+ (__item)->prev->next = (__item)->next; \
+ (__item)->next->prev = (__item)->prev; \
+ } while(0)
+
+#define DRMLISTDELINIT(__item) \
+ do { \
+ (__item)->prev->next = (__item)->next; \
+ (__item)->next->prev = (__item)->prev; \
+ (__item)->next = (__item); \
+ (__item)->prev = (__item); \
+ } while(0)
+
+#define DRMLISTENTRY(__type, __item, __field) \
+ ((__type *)(((char *) (__item)) - offsetof(__type, __field)))
+
+#define DRMLISTEMPTY(__item) ((__item)->next == (__item))
+
+#define DRMLISTFOREACHSAFE(__item, __temp, __list) \
+ for ((__item) = (__list)->next, (__temp) = (__item)->next; \
+ (__item) != (__list); \
+ (__item) = (__temp), (__temp) = (__item)->next)
+
+#define DRMLISTFOREACHSAFEREVERSE(__item, __temp, __list) \
+ for ((__item) = (__list)->prev, (__temp) = (__item)->prev; \
+ (__item) != (__list); \
+ (__item) = (__temp), (__temp) = (__item)->prev)