etnaviv: Command buffer realloc
[mesa.git] / src / etnaviv / drm / etnaviv_cmd_stream.c
index 7139c3245483a216629937106eb65d42c5b6c89e..ef5143003aebd6c5e62b079464656d2a5e94b83b 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 #include <assert.h>
+#include <stdlib.h>
 
 #include "etnaviv_drmif.h"
 #include "etnaviv_priv.h"
@@ -49,15 +50,44 @@ static void *grow(void *ptr, uint32_t nr, uint32_t *max, uint32_t sz)
        (x)->nr_ ## name ++; \
 })
 
+void etna_cmd_stream_realloc(struct etna_cmd_stream *stream, size_t n)
+{
+       size_t size;
+       void *buffer;
+
+       /*
+        * Increase the command buffer size by 1 kiB. Here we pick 1 kiB
+        * increment to prevent it from growing too much too quickly.
+        */
+       size = ALIGN(stream->size + n, 1024);
+
+       /* Command buffer is too big for older kernel versions */
+       if (size >= 32768)
+               goto error;
+
+       buffer = realloc(stream->buffer, size * 4);
+       if (!buffer)
+               goto error;
+
+       stream->buffer = buffer;
+       stream->size = size;
+
+       return;
+
+error:
+       WARN_MSG("command buffer too long, forcing flush.");
+       etna_cmd_stream_force_flush(stream);
+}
+
 static inline struct etna_cmd_stream_priv *
 etna_cmd_stream_priv(struct etna_cmd_stream *stream)
 {
     return (struct etna_cmd_stream_priv *)stream;
 }
 
-drm_public struct etna_cmd_stream *etna_cmd_stream_new(struct etna_pipe *pipe,
+struct etna_cmd_stream *etna_cmd_stream_new(struct etna_pipe *pipe,
         uint32_t size,
-               void (*reset_notify)(struct etna_cmd_stream *stream, void *priv),
+               void (*force_flush)(struct etna_cmd_stream *stream, void *priv),
                void *priv)
 {
        struct etna_cmd_stream_priv *stream = NULL;
@@ -84,8 +114,8 @@ drm_public struct etna_cmd_stream *etna_cmd_stream_new(struct etna_pipe *pipe,
 
        stream->base.size = size;
        stream->pipe = pipe;
-       stream->reset_notify = reset_notify;
-       stream->reset_notify_priv = priv;
+       stream->force_flush = force_flush;
+       stream->force_flush_priv = priv;
 
        return &stream->base;
 
@@ -96,7 +126,7 @@ fail:
        return NULL;
 }
 
-drm_public void etna_cmd_stream_del(struct etna_cmd_stream *stream)
+void etna_cmd_stream_del(struct etna_cmd_stream *stream)
 {
        struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
 
@@ -106,21 +136,15 @@ drm_public void etna_cmd_stream_del(struct etna_cmd_stream *stream)
        free(priv);
 }
 
-static void reset_buffer(struct etna_cmd_stream *stream)
+void etna_cmd_stream_force_flush(struct etna_cmd_stream *stream)
 {
        struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
 
-       stream->offset = 0;
-       priv->submit.nr_bos = 0;
-       priv->submit.nr_relocs = 0;
-       priv->submit.nr_pmrs = 0;
-       priv->nr_bos = 0;
-
-       if (priv->reset_notify)
-               priv->reset_notify(stream, priv->reset_notify_priv);
+       if (priv->force_flush)
+               priv->force_flush(stream, priv->force_flush_priv);
 }
 
-drm_public uint32_t etna_cmd_stream_timestamp(struct etna_cmd_stream *stream)
+uint32_t etna_cmd_stream_timestamp(struct etna_cmd_stream *stream)
 {
        return etna_cmd_stream_priv(stream)->last_timestamp;
 }
@@ -150,21 +174,25 @@ static uint32_t bo2idx(struct etna_cmd_stream *stream, struct etna_bo *bo,
 
        pthread_mutex_lock(&idx_lock);
 
-       if (!bo->current_stream) {
-               idx = append_bo(stream, bo);
-               bo->current_stream = stream;
-               bo->idx = idx;
-       } else if (bo->current_stream == stream) {
+       if (bo->current_stream == stream) {
                idx = bo->idx;
        } else {
-               /* slow-path: */
-               for (idx = 0; idx < priv->nr_bos; idx++)
-                       if (priv->bos[idx] == bo)
-                               break;
-               if (idx == priv->nr_bos) {
-                       /* not found */
+               void *val;
+
+               if (!priv->bo_table)
+                       priv->bo_table = drmHashCreate();
+
+               if (!drmHashLookup(priv->bo_table, bo->handle, &val)) {
+                       /* found */
+                       idx = (uint32_t)(uintptr_t)val;
+               } else {
                        idx = append_bo(stream, bo);
+                       val = (void *)(uintptr_t)idx;
+                       drmHashInsert(priv->bo_table, bo->handle, val);
                }
+
+               bo->current_stream = stream;
+               bo->idx = idx;
        }
        pthread_mutex_unlock(&idx_lock);
 
@@ -176,8 +204,8 @@ static uint32_t bo2idx(struct etna_cmd_stream *stream, struct etna_bo *bo,
        return idx;
 }
 
-static void flush(struct etna_cmd_stream *stream, int in_fence_fd,
-                 int *out_fence_fd)
+void etna_cmd_stream_flush(struct etna_cmd_stream *stream, int in_fence_fd,
+               int *out_fence_fd)
 {
        struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
        int ret, id = priv->pipe->id;
@@ -219,34 +247,22 @@ static void flush(struct etna_cmd_stream *stream, int in_fence_fd,
                etna_bo_del(bo);
        }
 
+       if (priv->bo_table) {
+               drmHashDestroy(priv->bo_table);
+               priv->bo_table = NULL;
+       }
+
        if (out_fence_fd)
                *out_fence_fd = req.fence_fd;
-}
 
-drm_public void etna_cmd_stream_flush(struct etna_cmd_stream *stream)
-{
-       flush(stream, -1, NULL);
-       reset_buffer(stream);
-}
-
-drm_public void etna_cmd_stream_flush2(struct etna_cmd_stream *stream,
-                                                                          int in_fence_fd,
-                                                                          int *out_fence_fd)
-{
-       flush(stream, in_fence_fd, out_fence_fd);
-       reset_buffer(stream);
-}
-
-drm_public void etna_cmd_stream_finish(struct etna_cmd_stream *stream)
-{
-       struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
-
-       flush(stream, -1, NULL);
-       etna_pipe_wait(priv->pipe, priv->last_timestamp, 5000);
-       reset_buffer(stream);
+       stream->offset = 0;
+       priv->submit.nr_bos = 0;
+       priv->submit.nr_relocs = 0;
+       priv->submit.nr_pmrs = 0;
+       priv->nr_bos = 0;
 }
 
-drm_public void etna_cmd_stream_reloc(struct etna_cmd_stream *stream,
+void etna_cmd_stream_reloc(struct etna_cmd_stream *stream,
                                                                          const struct etna_reloc *r)
 {
        struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
@@ -264,7 +280,7 @@ drm_public void etna_cmd_stream_reloc(struct etna_cmd_stream *stream,
        etna_cmd_stream_emit(stream, addr);
 }
 
-drm_public void etna_cmd_stream_perf(struct etna_cmd_stream *stream, const struct etna_perf *p)
+void etna_cmd_stream_perf(struct etna_cmd_stream *stream, const struct etna_perf *p)
 {
        struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
        struct drm_etnaviv_gem_submit_pmr *pmr;