diff options
author | Russell King <rmk@arm.linux.org.uk> | 2015-05-29 21:04:37 +0100 |
---|---|---|
committer | Russell King <rmk@arm.linux.org.uk> | 2015-06-29 12:58:32 +0100 |
commit | 3a0f0de67cebabbd5de5e2cf5d7eaf34aaf95a42 (patch) | |
tree | 2a3d661c0397ea63fb074b2bb65eb8f8e197737e | |
parent | 0b106007a0499afbe1346fef78147b69696d953f (diff) |
etnaviv: add bo caching support to etnadrm
Add bo caching support to etnadrm.
Signed-off-by: Russell King <rmk@arm.linux.org.uk>
-rw-r--r-- | etnaviv/etnadrm.c | 107 |
1 files changed, 95 insertions, 12 deletions
diff --git a/etnaviv/etnadrm.c b/etnaviv/etnadrm.c index c6f26fe..38fbe06 100644 --- a/etnaviv/etnadrm.c +++ b/etnaviv/etnadrm.c @@ -16,6 +16,7 @@ #include <etnaviv/state.xml.h> +#include "bo-cache.h" #include "etnadrm.h" #include "etnaviv_drm.h" #include "compat-list.h" @@ -23,6 +24,13 @@ #define etnadrm_pipe last_fence_id +struct etna_viv_conn { + struct viv_conn conn; + struct bo_cache cache; +}; + +static void etna_bo_cache_free(struct bo_entry *be); + struct chip_specs { uint32_t param; uint32_t offset; @@ -130,15 +138,20 @@ int etnadrm_open_render(const char *name) int viv_open(enum viv_hw_type hw_type, struct viv_conn **out) { + struct etna_viv_conn *ec; struct viv_conn *conn; drmVersionPtr version; Bool found = FALSE; int pipe, err = -1; - conn = calloc(1, sizeof *conn); - if (!conn) + ec = calloc(1, sizeof *ec); + if (!ec) return -1; + bo_cache_init(&ec->cache, etna_bo_cache_free); + + conn = &ec->conn; + conn->fd = etnadrm_open_render("etnaviv"); if (conn->fd == -1) goto error; @@ -231,9 +244,13 @@ error: int viv_close(struct viv_conn *conn) { + struct etna_viv_conn *ec = container_of(conn, struct etna_viv_conn, conn); + if (conn->fd < 0) return -1; + bo_cache_fini(&ec->cache); + close(conn->fd); free(conn); return 0; @@ -271,20 +288,51 @@ struct etna_bo { int ref; int bo_idx; struct xorg_list node; + struct bo_entry cache; }; -int etna_bo_del(struct viv_conn *conn, struct etna_bo *mem, struct etna_queue *queue) +static void etna_bo_free(struct etna_bo *bo) { - if (--mem->ref == 0) { - struct drm_gem_close req = { - .handle = mem->handle, - }; + struct viv_conn *conn = bo->conn; + struct drm_gem_close req = { + .handle = bo->handle, + }; - if (mem->logical) - munmap(mem->logical, mem->size); + if (bo->logical) + munmap(bo->logical, bo->size); - drmIoctl(conn->fd, DRM_IOCTL_GEM_CLOSE, &req); - free(mem); + drmIoctl(conn->fd, DRM_IOCTL_GEM_CLOSE, &req); + free(bo); +} + +static void etna_bo_cache_free(struct bo_entry *be) +{ + etna_bo_free(container_of(be, struct etna_bo, cache)); +} + +static struct etna_bo *etna_bo_bucket_get(struct bo_bucket *bucket) +{ + struct bo_entry *be = bo_cache_bucket_get(bucket); + struct etna_bo *bo = NULL; + + if (be) { + bo = container_of(be, struct etna_bo, cache); + bo->ref = 1; + bo->bo_idx = -1; + } + + return bo; +} + +int etna_bo_del(struct viv_conn *conn, struct etna_bo *mem, struct etna_queue *queue) +{ + struct etna_viv_conn *ec = container_of(conn, struct etna_viv_conn, conn); + + if (--mem->ref == 0) { + if (mem->cache.bucket) + bo_cache_put(&ec->cache, &mem->cache); + else + etna_bo_free(mem); return 0; } return -1; @@ -303,7 +351,8 @@ static struct etna_bo *etna_bo_alloc(struct viv_conn *conn) return mem; } -struct etna_bo *etna_bo_new(struct viv_conn *conn, size_t bytes, uint32_t flags) +static struct etna_bo *etna_bo_get(struct viv_conn *conn, size_t bytes, + uint32_t flags) { struct etna_bo *mem; struct drm_etnaviv_gem_new req = { @@ -332,6 +381,35 @@ struct etna_bo *etna_bo_new(struct viv_conn *conn, size_t bytes, uint32_t flags) return mem; } +struct etna_bo *etna_bo_new(struct viv_conn *conn, size_t bytes, uint32_t flags) +{ + struct etna_viv_conn *ec = container_of(conn, struct etna_viv_conn, conn); + struct bo_bucket *bucket = NULL; + struct etna_bo *bo; + + do { + if ((flags & DRM_ETNA_GEM_TYPE_MASK) == DRM_ETNA_GEM_TYPE_CMD) + break; + + bucket = bo_cache_bucket_find(&ec->cache, bytes); + if (!bucket) + break; + + /* We must allocate the bucket size for it to be re-usable */ + bytes = bucket->size; + + bo = etna_bo_bucket_get(bucket); + if (bo) + return bo; + } while (0); + + bo = etna_bo_get(conn, bytes, flags); + if (bo) + bo->cache.bucket = bucket; + + return bo; +} + struct etna_bo *etna_bo_from_dmabuf(struct viv_conn *conn, int fd, int prot) { struct etna_bo *mem; @@ -418,6 +496,11 @@ uint32_t etna_bo_gpu_address(struct etna_bo *bo) uint32_t etna_bo_handle(struct etna_bo *bo) { + /* + * If we're wanting the handle, we're more than likely + * exporting it, which means we must not re-use this bo. + */ + bo->cache.bucket = NULL; return bo->handle; } |