From 38c232e6ae0b9eed2b15146bd940f95c9f0b36b7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 5 May 2013 13:48:04 +0100 Subject: 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 --- Makefile.am | 7 +- configure.ac | 7 +- debian/changelog | 8 + debian/control | 13 +- debian/libdrm-dove1.install | 1 - debian/libdrm-dove1.postinst.debhelper | 5 - debian/libdrm-dove1.postrm.debhelper | 5 - debian/libdrm-dove2.install | 1 + debian/rules | 2 +- dove_bufmgr.c | 368 +++++++++++++++++++++++++++------ dove_bufmgr.h | 30 ++- libdrm_lists.h | 89 ++++++++ 12 files changed, 444 insertions(+), 92 deletions(-) delete mode 100644 debian/libdrm-dove1.install delete mode 100644 debian/libdrm-dove1.postinst.debhelper delete mode 100644 debian/libdrm-dove1.postrm.debhelper create mode 100644 debian/libdrm-dove2.install create mode 100644 libdrm_lists.h 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 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 #include #include +#include #include +#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 + +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) -- cgit