OSDN Git Service

freedreno: move ring_cache behind fd_bo_del()
[android-x86/external-libdrm.git] / freedreno / freedreno_priv.h
index 6bd1dec..84dbc5c 100644 (file)
 #ifndef FREEDRENO_PRIV_H_
 #define FREEDRENO_PRIV_H_
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
-#include <sys/mman.h>
 #include <pthread.h>
 #include <stdio.h>
 #include <assert.h>
 
-#include "libdrm.h"
+#include "libdrm_macros.h"
 #include "xf86drm.h"
 #include "xf86atomic.h"
 
-#include "list.h"
+#include "util_double_list.h"
+#include "util_math.h"
 
 #include "freedreno_drmif.h"
 #include "freedreno_ringbuffer.h"
 #include "drm.h"
 
+#ifndef TRUE
+#  define TRUE 1
+#endif
+#ifndef FALSE
+#  define FALSE 0
+#endif
+
 struct fd_device_funcs {
        int (*bo_new_handle)(struct fd_device *dev, uint32_t size,
                        uint32_t flags, uint32_t *handle);
        struct fd_bo * (*bo_from_handle)(struct fd_device *dev,
                        uint32_t size, uint32_t handle);
-       struct fd_pipe * (*pipe_new)(struct fd_device *dev, enum fd_pipe_id id);
+       struct fd_pipe * (*pipe_new)(struct fd_device *dev, enum fd_pipe_id id,
+                       unsigned prio);
        void (*destroy)(struct fd_device *dev);
 };
 
@@ -69,8 +73,15 @@ struct fd_bo_bucket {
        struct list_head list;
 };
 
+struct fd_bo_cache {
+       struct fd_bo_bucket cache_bucket[14 * 4];
+       int num_buckets;
+       time_t time;
+};
+
 struct fd_device {
        int fd;
+       enum fd_version version;
        atomic_t refcnt;
 
        /* tables to keep track of bo's, to avoid "evil-twin" fd_bo objects:
@@ -84,31 +95,44 @@ struct fd_device {
         */
        void *handle_table, *name_table;
 
-       struct fd_device_funcs *funcs;
+       const struct fd_device_funcs *funcs;
 
-       struct fd_bo_bucket cache_bucket[14 * 4];
-       int num_buckets;
-       time_t time;
+       struct fd_bo_cache bo_cache;
+       struct fd_bo_cache ring_cache;
 
        int closefd;        /* call close(fd) upon destruction */
+
+       /* just for valgrind: */
+       int bo_size;
 };
 
-void fd_cleanup_bo_cache(struct fd_device *dev, time_t time);
+drm_private void fd_bo_cache_init(struct fd_bo_cache *cache, int coarse);
+drm_private void fd_bo_cache_cleanup(struct fd_bo_cache *cache, time_t time);
+drm_private struct fd_bo * fd_bo_cache_alloc(struct fd_bo_cache *cache,
+               uint32_t *size, uint32_t flags);
+drm_private int fd_bo_cache_free(struct fd_bo_cache *cache, struct fd_bo *bo);
 
 /* for where @table_lock is already held: */
-void fd_device_del_locked(struct fd_device *dev);
+drm_private void fd_device_del_locked(struct fd_device *dev);
+
+enum fd_ringbuffer_flags {
+       FD_RINGBUFFER_OBJECT = 0x1,
+};
 
 struct fd_pipe_funcs {
-       struct fd_ringbuffer * (*ringbuffer_new)(struct fd_pipe *pipe, uint32_t size);
+       struct fd_ringbuffer * (*ringbuffer_new)(struct fd_pipe *pipe, uint32_t size,
+                       enum fd_ringbuffer_flags flags);
        int (*get_param)(struct fd_pipe *pipe, enum fd_param_id param, uint64_t *value);
-       int (*wait)(struct fd_pipe *pipe, uint32_t timestamp);
+       int (*wait)(struct fd_pipe *pipe, uint32_t timestamp, uint64_t timeout);
        void (*destroy)(struct fd_pipe *pipe);
 };
 
 struct fd_pipe {
        struct fd_device *dev;
        enum fd_pipe_id id;
-       struct fd_pipe_funcs *funcs;
+       uint32_t gpu_id;
+       atomic_t refcnt;
+       const struct fd_pipe_funcs *funcs;
 };
 
 struct fd_ringmarker {
@@ -118,12 +142,16 @@ struct fd_ringmarker {
 
 struct fd_ringbuffer_funcs {
        void * (*hostptr)(struct fd_ringbuffer *ring);
-       int (*flush)(struct fd_ringbuffer *ring, uint32_t *last_start);
+       int (*flush)(struct fd_ringbuffer *ring, uint32_t *last_start,
+                       int in_fence_fd, int *out_fence_fd);
+       void (*grow)(struct fd_ringbuffer *ring, uint32_t size);
        void (*reset)(struct fd_ringbuffer *ring);
        void (*emit_reloc)(struct fd_ringbuffer *ring,
                        const struct fd_reloc *reloc);
-       void (*emit_reloc_ring)(struct fd_ringbuffer *ring,
-                       struct fd_ringmarker *target, struct fd_ringmarker *end);
+       uint32_t (*emit_reloc_ring)(struct fd_ringbuffer *ring,
+                       struct fd_ringbuffer *target, uint32_t cmd_idx,
+                       uint32_t submit_offset, uint32_t size);
+       uint32_t (*cmd_count)(struct fd_ringbuffer *ring);
        void (*destroy)(struct fd_ringbuffer *ring);
 };
 
@@ -131,6 +159,8 @@ struct fd_bo_funcs {
        int (*offset)(struct fd_bo *bo, uint64_t *offset);
        int (*cpu_prep)(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op);
        void (*cpu_fini)(struct fd_bo *bo);
+       int (*madvise)(struct fd_bo *bo, int willneed);
+       uint64_t (*iova)(struct fd_bo *bo);
        void (*destroy)(struct fd_bo *bo);
 };
 
@@ -141,17 +171,21 @@ struct fd_bo {
        uint32_t name;
        void *map;
        atomic_t refcnt;
-       struct fd_bo_funcs *funcs;
+       const struct fd_bo_funcs *funcs;
+
+       enum {
+               NO_CACHE = 0,
+               BO_CACHE = 1,
+               RING_CACHE = 2,
+       } bo_reuse;
 
-       int bo_reuse;
        struct list_head list;   /* bucket-list entry */
        time_t free_time;        /* time when added to bucket-list */
 };
 
-struct fd_bo *fd_bo_from_handle(struct fd_device *dev,
-               uint32_t handle, uint32_t size);
+drm_private struct fd_bo *fd_bo_new_ring(struct fd_device *dev,
+               uint32_t size, uint32_t flags);
 
-#define ALIGN(v,a) (((v) + (a) - 1) & ~((a) - 1))
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 
 #define enable_debug 0  /* TODO make dynamic */
@@ -172,4 +206,63 @@ struct fd_bo *fd_bo_from_handle(struct fd_device *dev,
 #define U642VOID(x) ((void *)(unsigned long)(x))
 #define VOID2U64(x) ((uint64_t)(unsigned long)(x))
 
+static inline uint32_t
+offset_bytes(void *end, void *start)
+{
+       return ((char *)end) - ((char *)start);
+}
+
+#if HAVE_VALGRIND
+#  include <memcheck.h>
+
+/*
+ * For tracking the backing memory (if valgrind enabled, we force a mmap
+ * for the purposes of tracking)
+ */
+static inline void VG_BO_ALLOC(struct fd_bo *bo)
+{
+       if (bo && RUNNING_ON_VALGRIND) {
+               VALGRIND_MALLOCLIKE_BLOCK(fd_bo_map(bo), bo->size, 0, 1);
+       }
+}
+
+static inline void VG_BO_FREE(struct fd_bo *bo)
+{
+       VALGRIND_FREELIKE_BLOCK(bo->map, 0);
+}
+
+/*
+ * For tracking bo structs that are in the buffer-cache, so that valgrind
+ * doesn't attribute ownership to the first one to allocate the recycled
+ * bo.
+ *
+ * Note that the list_head in fd_bo is used to track the buffers in cache
+ * so disable error reporting on the range while they are in cache so
+ * valgrind doesn't squawk about list traversal.
+ *
+ */
+static inline void VG_BO_RELEASE(struct fd_bo *bo)
+{
+       if (RUNNING_ON_VALGRIND) {
+               VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(bo, bo->dev->bo_size);
+               VALGRIND_MAKE_MEM_NOACCESS(bo, bo->dev->bo_size);
+               VALGRIND_FREELIKE_BLOCK(bo->map, 0);
+       }
+}
+static inline void VG_BO_OBTAIN(struct fd_bo *bo)
+{
+       if (RUNNING_ON_VALGRIND) {
+               VALGRIND_MAKE_MEM_DEFINED(bo, bo->dev->bo_size);
+               VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(bo, bo->dev->bo_size);
+               VALGRIND_MALLOCLIKE_BLOCK(bo->map, bo->size, 0, 1);
+       }
+}
+#else
+static inline void VG_BO_ALLOC(struct fd_bo *bo)   {}
+static inline void VG_BO_FREE(struct fd_bo *bo)    {}
+static inline void VG_BO_RELEASE(struct fd_bo *bo) {}
+static inline void VG_BO_OBTAIN(struct fd_bo *bo)  {}
+#endif
+
+
 #endif /* FREEDRENO_PRIV_H_ */