#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 "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 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:
*/
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;
int closefd; /* call close(fd) upon destruction */
+
+ /* just for valgrind: */
+ int bo_size;
};
-drm_private 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: */
drm_private void fd_device_del_locked(struct fd_device *dev);
struct fd_pipe_funcs {
struct fd_ringbuffer * (*ringbuffer_new)(struct fd_pipe *pipe, uint32_t size);
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;
+ const struct fd_pipe_funcs *funcs;
};
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);
};
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);
void (*destroy)(struct fd_bo *bo);
};
uint32_t size;
uint32_t handle;
uint32_t name;
- int fd; /* dmabuf handle */
void *map;
atomic_t refcnt;
- struct fd_bo_funcs *funcs;
+ const struct fd_bo_funcs *funcs;
int bo_reuse;
struct list_head list; /* bucket-list entry */
#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);
+}
+
+#ifdef 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_ */