virgl: fix vtest regression since fencing changes.
[mesa.git] / src / gallium / winsys / virgl / vtest / virgl_vtest_winsys.c
index 1c8df6e469d200d8e7bbd44ed53dddd6670117f2..a23f8539241fcf87ee8369cf5a23a327fa7e82c6 100644 (file)
  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 #include <stdio.h>
-#include "virgl_vtest_winsys.h"
-#include "virgl_vtest_public.h"
 #include "util/u_memory.h"
 #include "util/u_format.h"
 #include "util/u_inlines.h"
-#include "state_tracker/drm_driver.h"
-#include "os/os_time.h"
+#include "util/os_time.h"
+#include "state_tracker/sw_winsys.h"
+
+#include "virgl_vtest_winsys.h"
+#include "virgl_vtest_public.h"
+
+static void *virgl_vtest_resource_map(struct virgl_winsys *vws,
+                                      struct virgl_hw_res *res);
+static void virgl_vtest_resource_unmap(struct virgl_winsys *vws,
+                                       struct virgl_hw_res *res);
 
-static void *virgl_vtest_resource_map(struct virgl_winsys *vws, struct virgl_hw_res *res);
-static void virgl_vtest_resource_unmap(struct virgl_winsys *vws, struct virgl_hw_res *res);
 static inline boolean can_cache_resource(struct virgl_hw_res *res)
 {
    return res->cacheable == TRUE;
@@ -72,11 +76,22 @@ virgl_vtest_transfer_put(struct virgl_winsys *vws,
    void *ptr;
    uint32_t valid_stride;
 
-   size = vtest_get_transfer_size(res, box, stride, layer_stride, level, &valid_stride);
+   size = vtest_get_transfer_size(res, box, stride, layer_stride, level,
+                                  &valid_stride);
+
+   /* The size calculated above is the full box size, but if this box origin
+    * is not zero we may have to correct the transfer size to not read past the
+    * end of the resource. The correct adjustment depends on various factors
+    * that are not documented, so instead of going though all the hops to get
+    * the size right up-front, we just make sure we don't read past the end.
+    * FIXME: figure out what it takes to actually get this right.
+    */
+   if (size + buf_offset > res->size)
+      size = res->size - buf_offset;
 
-   virgl_vtest_send_transfer_cmd(vtws, VCMD_TRANSFER_PUT, res->res_handle,
+   virgl_vtest_send_transfer_put(vtws, res->res_handle,
                                  level, stride, layer_stride,
-                                 box, size);
+                                 box, size, buf_offset);
    ptr = virgl_vtest_resource_map(vws, res);
    virgl_vtest_send_transfer_put_data(vtws, ptr + buf_offset, size);
    virgl_vtest_resource_unmap(vws, res);
@@ -95,15 +110,24 @@ virgl_vtest_transfer_get(struct virgl_winsys *vws,
    void *ptr;
    uint32_t valid_stride;
 
-   size = vtest_get_transfer_size(res, box, stride, layer_stride, level, &valid_stride);
+   size = vtest_get_transfer_size(res, box, stride, layer_stride, level,
+                                  &valid_stride);
+   /* Don't ask for more pixels than available (see above) */
+   if (size + buf_offset > res->size)
+      size = res->size - buf_offset;
 
-   virgl_vtest_send_transfer_cmd(vtws, VCMD_TRANSFER_GET, res->res_handle,
+   virgl_vtest_send_transfer_get(vtws, res->res_handle,
                                  level, stride, layer_stride,
-                                 box, size);
-
+                                 box, size, buf_offset);
 
    ptr = virgl_vtest_resource_map(vws, res);
-   virgl_vtest_recv_transfer_get_data(vtws, ptr + buf_offset, size, valid_stride, box, res->format);
+
+   /* This functions seems to be using a specific transfer resource that
+    * has exactly the box size and hence its src stride is equal to the target
+    * stride */
+   virgl_vtest_recv_transfer_get_data(vtws, ptr + buf_offset, size,
+                                      valid_stride, box, res->format, valid_stride);
+
    virgl_vtest_resource_unmap(vws, res);
    return 0;
 }
@@ -137,7 +161,7 @@ virgl_cache_flush(struct virgl_vtest_winsys *vtws)
    struct list_head *curr, *next;
    struct virgl_hw_res *res;
 
-   pipe_mutex_lock(vtws->mutex);
+   mtx_lock(&vtws->mutex);
    curr = vtws->delayed.next;
    next = curr->next;
 
@@ -148,7 +172,7 @@ virgl_cache_flush(struct virgl_vtest_winsys *vtws)
       curr = next;
       next = curr->next;
    }
-   pipe_mutex_unlock(vtws->mutex);
+   mtx_unlock(&vtws->mutex);
 }
 
 static void
@@ -182,31 +206,31 @@ static void virgl_vtest_resource_reference(struct virgl_vtest_winsys *vtws,
       if (!can_cache_resource(old)) {
          virgl_hw_res_destroy(vtws, old);
       } else {
-         pipe_mutex_lock(vtws->mutex);
+         mtx_lock(&vtws->mutex);
          virgl_cache_list_check_free(vtws);
 
          old->start = os_time_get();
          old->end = old->start + vtws->usecs;
          LIST_ADDTAIL(&old->head, &vtws->delayed);
          vtws->num_delayed++;
-         pipe_mutex_unlock(vtws->mutex);
+         mtx_unlock(&vtws->mutex);
       }
    }
    *dres = sres;
 }
 
-static struct virgl_hw_res *virgl_vtest_winsys_resource_create(
-   struct virgl_winsys *vws,
-   enum pipe_texture_target target,
-   uint32_t format,
-   uint32_t bind,
-   uint32_t width,
-   uint32_t height,
-   uint32_t depth,
-   uint32_t array_size,
-   uint32_t last_level,
-   uint32_t nr_samples,
-   uint32_t size)
+static struct virgl_hw_res *
+virgl_vtest_winsys_resource_create(struct virgl_winsys *vws,
+                                   enum pipe_texture_target target,
+                                   uint32_t format,
+                                   uint32_t bind,
+                                   uint32_t width,
+                                   uint32_t height,
+                                   uint32_t depth,
+                                   uint32_t array_size,
+                                   uint32_t last_level,
+                                   uint32_t nr_samples,
+                                   uint32_t size)
 {
    struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
    struct virgl_hw_res *res;
@@ -217,12 +241,8 @@ static struct virgl_hw_res *virgl_vtest_winsys_resource_create(
       return NULL;
 
    if (bind & (VIRGL_BIND_DISPLAY_TARGET | VIRGL_BIND_SCANOUT)) {
-      res->dt = vtws->sws->displaytarget_create(vtws->sws,
-                                                bind,
-                                                format,
-                                                width,
-                                                height,
-                                                64,
+      res->dt = vtws->sws->displaytarget_create(vtws->sws, bind, format,
+                                                width, height, 64, NULL,
                                                 &res->stride);
 
    } else {
@@ -237,9 +257,10 @@ static struct virgl_hw_res *virgl_vtest_winsys_resource_create(
    res->format = format;
    res->height = height;
    res->width = width;
-   virgl_vtest_send_resource_create(vtws, handle, target, format, bind, width,
-                                    height, depth, array_size, last_level,
-                                    nr_samples);
+   res->size = size;
+   virgl_vtest_send_resource_create(vtws, handle, target, format, bind,
+                                    width, height, depth, array_size,
+                                    last_level, nr_samples, size);
 
    res->res_handle = handle++;
    pipe_reference_init(&res->reference, 1);
@@ -253,7 +274,8 @@ static void virgl_vtest_winsys_resource_unref(struct virgl_winsys *vws,
    virgl_vtest_resource_reference(vtws, &hres, NULL);
 }
 
-static void *virgl_vtest_resource_map(struct virgl_winsys *vws, struct virgl_hw_res *res)
+static void *virgl_vtest_resource_map(struct virgl_winsys *vws,
+                                      struct virgl_hw_res *res)
 {
    struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
 
@@ -265,7 +287,8 @@ static void *virgl_vtest_resource_map(struct virgl_winsys *vws, struct virgl_hw_
    }
 }
 
-static void virgl_vtest_resource_unmap(struct virgl_winsys *vws, struct virgl_hw_res *res)
+static void virgl_vtest_resource_unmap(struct virgl_winsys *vws,
+                                       struct virgl_hw_res *res)
 {
    struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
    if (res->mapped)
@@ -275,7 +298,8 @@ static void virgl_vtest_resource_unmap(struct virgl_winsys *vws, struct virgl_hw
       vtws->sws->displaytarget_unmap(vtws->sws, res->dt);
 }
 
-static void virgl_vtest_resource_wait(struct virgl_winsys *vws, struct virgl_hw_res *res)
+static void virgl_vtest_resource_wait(struct virgl_winsys *vws,
+                                      struct virgl_hw_res *res)
 {
    struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
 
@@ -284,7 +308,8 @@ static void virgl_vtest_resource_wait(struct virgl_winsys *vws, struct virgl_hw_
 
 static inline int virgl_is_res_compat(struct virgl_vtest_winsys *vtws,
                                       struct virgl_hw_res *res,
-                                      uint32_t size, uint32_t bind, uint32_t format)
+                                      uint32_t size, uint32_t bind,
+                                      uint32_t format)
 {
    if (res->bind != bind)
       return 0;
@@ -302,17 +327,18 @@ static inline int virgl_is_res_compat(struct virgl_vtest_winsys *vtws,
    return 1;
 }
 
-static struct virgl_hw_res *virgl_vtest_winsys_resource_cache_create(struct virgl_winsys *vws,
-                                               enum pipe_texture_target target,
-                                               uint32_t format,
-                                               uint32_t bind,
-                                               uint32_t width,
-                                               uint32_t height,
-                                               uint32_t depth,
-                                               uint32_t array_size,
-                                               uint32_t last_level,
-                                               uint32_t nr_samples,
-                                               uint32_t size)
+static struct virgl_hw_res *
+virgl_vtest_winsys_resource_cache_create(struct virgl_winsys *vws,
+                                         enum pipe_texture_target target,
+                                         uint32_t format,
+                                         uint32_t bind,
+                                         uint32_t width,
+                                         uint32_t height,
+                                         uint32_t depth,
+                                         uint32_t array_size,
+                                         uint32_t last_level,
+                                         uint32_t nr_samples,
+                                         uint32_t size)
 {
    struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
    struct virgl_hw_res *res, *curr_res;
@@ -325,7 +351,7 @@ static struct virgl_hw_res *virgl_vtest_winsys_resource_cache_create(struct virg
        bind != VIRGL_BIND_VERTEX_BUFFER && bind != VIRGL_BIND_CUSTOM)
       goto alloc;
 
-   pipe_mutex_lock(vtws->mutex);
+   mtx_lock(&vtws->mutex);
 
    res = NULL;
    curr = vtws->delayed.next;
@@ -335,7 +361,7 @@ static struct virgl_hw_res *virgl_vtest_winsys_resource_cache_create(struct virg
    while (curr != &vtws->delayed) {
       curr_res = LIST_ENTRY(struct virgl_hw_res, curr, head);
 
-      if (!res && (ret = virgl_is_res_compat(vtws, curr_res, size, bind, format) > 0))
+      if (!res && ((ret = virgl_is_res_compat(vtws, curr_res, size, bind, format)) > 0))
          res = curr_res;
       else if (os_time_timeout(curr_res->start, curr_res->end, now)) {
          LIST_DEL(&curr_res->head);
@@ -368,17 +394,17 @@ static struct virgl_hw_res *virgl_vtest_winsys_resource_cache_create(struct virg
    if (res) {
       LIST_DEL(&res->head);
       --vtws->num_delayed;
-      pipe_mutex_unlock(vtws->mutex);
+      mtx_unlock(&vtws->mutex);
       pipe_reference_init(&res->reference, 1);
       return res;
    }
 
-   pipe_mutex_unlock(vtws->mutex);
+   mtx_unlock(&vtws->mutex);
 
 alloc:
    res = virgl_vtest_winsys_resource_create(vws, target, format, bind,
-                                           width, height, depth, array_size,
-                                           last_level, nr_samples, size);
+                                            width, height, depth, array_size,
+                                            last_level, nr_samples, size);
    if (bind == VIRGL_BIND_CONSTANT_BUFFER || bind == VIRGL_BIND_INDEX_BUFFER ||
        bind == VIRGL_BIND_VERTEX_BUFFER)
       res->cacheable = TRUE;
@@ -394,14 +420,14 @@ static struct virgl_cmd_buf *virgl_vtest_cmd_buf_create(struct virgl_winsys *vws
       return NULL;
 
    cbuf->nres = 512;
-   cbuf->res_bo = (struct virgl_hw_res **)
-      CALLOC(cbuf->nres, sizeof(struct virgl_hw_buf*));
+   cbuf->res_bo = CALLOC(cbuf->nres, sizeof(struct virgl_hw_buf*));
    if (!cbuf->res_bo) {
       FREE(cbuf);
       return NULL;
    }
    cbuf->ws = vws;
    cbuf->base.buf = cbuf->buf;
+   cbuf->base.in_fence_fd = -1;
    return &cbuf->base;
 }
 
@@ -414,7 +440,7 @@ static void virgl_vtest_cmd_buf_destroy(struct virgl_cmd_buf *_cbuf)
 }
 
 static boolean virgl_vtest_lookup_res(struct virgl_vtest_cmd_buf *cbuf,
-                                    struct virgl_hw_res *res)
+                                      struct virgl_hw_res *res)
 {
    unsigned hash = res->res_handle & (sizeof(cbuf->is_handle_added)-1);
    int i;
@@ -447,13 +473,23 @@ static void virgl_vtest_release_all_res(struct virgl_vtest_winsys *vtws,
 }
 
 static void virgl_vtest_add_res(struct virgl_vtest_winsys *vtws,
-                            struct virgl_vtest_cmd_buf *cbuf, struct virgl_hw_res *res)
+                                struct virgl_vtest_cmd_buf *cbuf,
+                                struct virgl_hw_res *res)
 {
    unsigned hash = res->res_handle & (sizeof(cbuf->is_handle_added)-1);
 
-   if (cbuf->cres > cbuf->nres) {
-      fprintf(stderr,"failure to add relocation\n");
-      return;
+   if (cbuf->cres >= cbuf->nres) {
+      unsigned new_nres = cbuf->nres + 256;
+      struct virgl_hw_res **new_re_bo = REALLOC(cbuf->res_bo,
+                                                cbuf->nres * sizeof(struct virgl_hw_buf*),
+                                                new_nres * sizeof(struct virgl_hw_buf*));
+      if (!new_re_bo) {
+          fprintf(stderr,"failure to add relocation %d, %d\n", cbuf->cres, cbuf->nres);
+          return;
+      }
+
+      cbuf->res_bo = new_re_bo;
+      cbuf->nres = new_nres;
    }
 
    cbuf->res_bo[cbuf->cres] = NULL;
@@ -465,7 +501,9 @@ static void virgl_vtest_add_res(struct virgl_vtest_winsys *vtws,
    cbuf->cres++;
 }
 
-static int virgl_vtest_winsys_submit_cmd(struct virgl_winsys *vws, struct virgl_cmd_buf *_cbuf)
+static int virgl_vtest_winsys_submit_cmd(struct virgl_winsys *vws,
+                                         struct virgl_cmd_buf *_cbuf,
+                                         int in_fence_fd, int *out_fence_fd)
 {
    struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
    struct virgl_vtest_cmd_buf *cbuf = virgl_vtest_cmd_buf(_cbuf);
@@ -474,6 +512,9 @@ static int virgl_vtest_winsys_submit_cmd(struct virgl_winsys *vws, struct virgl_
    if (cbuf->base.cdw == 0)
       return 0;
 
+   assert(in_fence_fd == -1);
+   assert(out_fence_fd == NULL);
+
    ret = virgl_vtest_submit_cmd(vtws, cbuf);
 
    virgl_vtest_release_all_res(vtws, cbuf);
@@ -482,7 +523,9 @@ static int virgl_vtest_winsys_submit_cmd(struct virgl_winsys *vws, struct virgl_
    return ret;
 }
 
-static void virgl_vtest_emit_res(struct virgl_winsys *vws, struct virgl_cmd_buf *_cbuf, struct virgl_hw_res *res, boolean write_buf)
+static void virgl_vtest_emit_res(struct virgl_winsys *vws,
+                                 struct virgl_cmd_buf *_cbuf,
+                                 struct virgl_hw_res *res, boolean write_buf)
 {
    struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
    struct virgl_vtest_cmd_buf *cbuf = virgl_vtest_cmd_buf(_cbuf);
@@ -504,21 +547,24 @@ static boolean virgl_vtest_res_is_ref(struct virgl_winsys *vws,
    return TRUE;
 }
 
-static int virgl_vtest_get_caps(struct virgl_winsys *vws, struct virgl_drm_caps *caps)
+static int virgl_vtest_get_caps(struct virgl_winsys *vws,
+                                struct virgl_drm_caps *caps)
 {
    struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+
+   virgl_ws_fill_new_caps_defaults(caps);
    return virgl_vtest_send_get_caps(vtws, caps);
 }
 
 static struct pipe_fence_handle *
-virgl_cs_create_fence(struct virgl_winsys *vws)
+virgl_cs_create_fence(struct virgl_winsys *vws, int fd)
 {
    struct virgl_hw_res *res;
 
    res = virgl_vtest_winsys_resource_cache_create(vws,
                                                 PIPE_BUFFER,
                                                 PIPE_FORMAT_R8_UNORM,
-                                                PIPE_BIND_CUSTOM,
+                                                VIRGL_BIND_CUSTOM,
                                                 8, 1, 1, 0, 0, 0, 8);
 
    return (struct pipe_fence_handle *)res;
@@ -532,7 +578,7 @@ static bool virgl_fence_wait(struct virgl_winsys *vws,
    struct virgl_hw_res *res = virgl_hw_res(fence);
 
    if (timeout == 0)
-      return virgl_vtest_resource_is_busy(vdws, res);
+      return !virgl_vtest_resource_is_busy(vdws, res);
 
    if (timeout != PIPE_TIMEOUT_INFINITE) {
       int64_t start_time = os_time_get();
@@ -575,7 +621,8 @@ static void virgl_vtest_flush_frontbuffer(struct virgl_winsys *vws,
 
    if (sub_box) {
       box = *sub_box;
-      offset = (res->stride * (box.y / util_format_get_blockheight(res->format))) + (box.x / util_format_get_blockwidth(res->format)) * util_format_get_blocksize(res->format);
+      offset = box.y / util_format_get_blockheight(res->format) * res->stride +
+               box.x / util_format_get_blockwidth(res->format) * util_format_get_blocksize(res->format);
    } else {
       box.z = layer;
       box.width = res->width;
@@ -589,12 +636,20 @@ static void virgl_vtest_flush_frontbuffer(struct virgl_winsys *vws,
    map = vtws->sws->displaytarget_map(vtws->sws, res->dt, 0);
 
    /* execute a transfer */
-   virgl_vtest_send_transfer_cmd(vtws, VCMD_TRANSFER_GET, res->res_handle,
-                                 level, res->stride, 0, &box, size);
-   virgl_vtest_recv_transfer_get_data(vtws, map + offset, size, valid_stride, &box, res->format);
+   virgl_vtest_send_transfer_get(vtws, res->res_handle,
+                                 level, res->stride, 0, &box, size, offset);
+
+   /* This functions gets the resource from the hardware backend that may have
+    * a hardware imposed stride that is different from the IOV stride used to
+    * get the data. */
+   virgl_vtest_recv_transfer_get_data(vtws, map + offset, size, valid_stride,
+                                      &box, res->format,
+                                      util_format_get_stride(res->format, res->width));
+
    vtws->sws->displaytarget_unmap(vtws->sws, res->dt);
 
-   vtws->sws->displaytarget_display(vtws->sws, res->dt, winsys_drawable_handle, sub_box);
+   vtws->sws->displaytarget_display(vtws->sws, res->dt, winsys_drawable_handle,
+                                    sub_box);
 }
 
 static void
@@ -604,7 +659,7 @@ virgl_vtest_winsys_destroy(struct virgl_winsys *vws)
 
    virgl_cache_flush(vtws);
 
-   pipe_mutex_destroy(vtws->mutex);
+   mtx_destroy(&vtws->mutex);
    FREE(vtws);
 }
 
@@ -622,7 +677,7 @@ virgl_vtest_winsys_wrap(struct sw_winsys *sws)
 
    vtws->usecs = 1000000;
    LIST_INITHEAD(&vtws->delayed);
-   pipe_mutex_init(vtws->mutex);
+   (void) mtx_init(&vtws->mutex, mtx_plain);
 
    vtws->base.destroy = virgl_vtest_winsys_destroy;
 
@@ -644,6 +699,7 @@ virgl_vtest_winsys_wrap(struct sw_winsys *sws)
    vtws->base.cs_create_fence = virgl_cs_create_fence;
    vtws->base.fence_wait = virgl_fence_wait;
    vtws->base.fence_reference = virgl_fence_reference;
+   vtws->base.supports_fences =  0;
 
    vtws->base.flush_frontbuffer = virgl_vtest_flush_frontbuffer;