summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2015-03-13 14:15:47 +1000
committerDave Airlie <airlied@redhat.com>2015-10-21 10:14:59 +1000
commit700079c401234e1b556548d2205d807a072c22cd (patch)
treef662b764c6b6c7b56adb30b0bebb5c5ba8e72c53
parent067f08418948af612ac43dc971285aeb6104f9db (diff)
virgl/vtest: add vtest driver
virgl/vtest is a swrast driver that allows the virgl acceleration to be tested without having a virtual machine. The backend has a unix socket server that this connects to. This is run by setting LIBGL_ALWAYS_SOFTWARE=y GALLIUM_DRIVER=virpipe In this mode all renderering is sent over a socket to the remote renderer, and the results are readback and copies to the screen using drisw. This works well enough to develop new features and to help debug. Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--configure.ac1
-rw-r--r--src/gallium/Makefile.am2
-rw-r--r--src/gallium/auxiliary/target-helpers/inline_sw_helper.h12
-rw-r--r--src/gallium/drivers/virgl/Automake.inc3
-rw-r--r--src/gallium/winsys/virgl/vtest/Makefile.am33
-rw-r--r--src/gallium/winsys/virgl/vtest/Makefile.sources3
-rw-r--r--src/gallium/winsys/virgl/vtest/virgl_vtest_public.h30
-rw-r--r--src/gallium/winsys/virgl/vtest/virgl_vtest_socket.c288
-rw-r--r--src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c653
-rw-r--r--src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.h132
-rw-r--r--src/gallium/winsys/virgl/vtest/vtest_protocol.h88
11 files changed, 1243 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 37ccb3d20de..7bf8781d1dd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2414,6 +2414,7 @@ AC_CONFIG_FILES([Makefile
src/gallium/winsys/sw/xlib/Makefile
src/gallium/winsys/vc4/drm/Makefile
src/gallium/winsys/virgl/drm/Makefile
+ src/gallium/winsys/virgl/vtest/Makefile
src/gbm/Makefile
src/gbm/main/gbm.pc
src/glsl/Makefile
diff --git a/src/gallium/Makefile.am b/src/gallium/Makefile.am
index 2fa93ddfe5d..611d55fafe2 100644
--- a/src/gallium/Makefile.am
+++ b/src/gallium/Makefile.am
@@ -84,7 +84,7 @@ endif
## virgl
if HAVE_GALLIUM_VIRGL
-SUBDIRS += drivers/virgl winsys/virgl/drm
+SUBDIRS += drivers/virgl winsys/virgl/drm winsys/virgl/vtest
endif
## the sw winsys'
diff --git a/src/gallium/auxiliary/target-helpers/inline_sw_helper.h b/src/gallium/auxiliary/target-helpers/inline_sw_helper.h
index 5f46552f6c3..f3693fb1f39 100644
--- a/src/gallium/auxiliary/target-helpers/inline_sw_helper.h
+++ b/src/gallium/auxiliary/target-helpers/inline_sw_helper.h
@@ -19,6 +19,10 @@
#include "llvmpipe/lp_public.h"
#endif
+#ifdef GALLIUM_VIRGL
+#include "virgl/virgl_public.h"
+#include "virgl/vtest/virgl_vtest_public.h"
+#endif
static inline struct pipe_screen *
sw_screen_create_named(struct sw_winsys *winsys, const char *driver)
@@ -30,6 +34,14 @@ sw_screen_create_named(struct sw_winsys *winsys, const char *driver)
screen = llvmpipe_create_screen(winsys);
#endif
+#if defined(GALLIUM_VIRGL)
+ if (screen == NULL && strcmp(driver, "virpipe") == 0) {
+ struct virgl_winsys *vws;
+ vws = virgl_vtest_winsys_wrap(winsys);
+ screen = virgl_create_screen(vws);
+ }
+#endif
+
#if defined(GALLIUM_SOFTPIPE)
if (screen == NULL)
screen = softpipe_create_screen(winsys);
diff --git a/src/gallium/drivers/virgl/Automake.inc b/src/gallium/drivers/virgl/Automake.inc
index 457ca77b3a7..b05d3e314c8 100644
--- a/src/gallium/drivers/virgl/Automake.inc
+++ b/src/gallium/drivers/virgl/Automake.inc
@@ -4,7 +4,8 @@ TARGET_DRIVERS += virtio_gpu
TARGET_CPPFLAGS += -DGALLIUM_VIRGL
TARGET_LIB_DEPS += \
$(top_builddir)/src/gallium/drivers/virgl/libvirgl.la \
- $(top_builddir)/src/gallium/winsys/virgl/drm/libvirgldrm.la
+ $(top_builddir)/src/gallium/winsys/virgl/drm/libvirgldrm.la \
+ $(top_builddir)/src/gallium/winsys/virgl/vtest/libvirglvtest.la \
$(LIBDRM_LIBS)
endif
diff --git a/src/gallium/winsys/virgl/vtest/Makefile.am b/src/gallium/winsys/virgl/vtest/Makefile.am
new file mode 100644
index 00000000000..81270d7b74b
--- /dev/null
+++ b/src/gallium/winsys/virgl/vtest/Makefile.am
@@ -0,0 +1,33 @@
+# Copyright © 2015 Red Hat
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+include Makefile.sources
+include $(top_srcdir)/src/gallium/Automake.inc
+
+AM_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src/gallium/drivers \
+ $(GALLIUM_CFLAGS)
+
+noinst_LTLIBRARIES = libvirglvtest.la
+
+libvirglvtest_la_SOURCES = $(C_SOURCES)
diff --git a/src/gallium/winsys/virgl/vtest/Makefile.sources b/src/gallium/winsys/virgl/vtest/Makefile.sources
new file mode 100644
index 00000000000..ab72560849a
--- /dev/null
+++ b/src/gallium/winsys/virgl/vtest/Makefile.sources
@@ -0,0 +1,3 @@
+C_SOURCES := \
+ virgl_vtest_winsys.c \
+ virgl_vtest_socket.c \ No newline at end of file
diff --git a/src/gallium/winsys/virgl/vtest/virgl_vtest_public.h b/src/gallium/winsys/virgl/vtest/virgl_vtest_public.h
new file mode 100644
index 00000000000..72336499b44
--- /dev/null
+++ b/src/gallium/winsys/virgl/vtest/virgl_vtest_public.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014, 2015 Red Hat.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef VIRGL_VTEST_PUBLIC_H
+#define VIRGL_VTEST_PUBLIC_H
+
+struct virgl_winsys;
+
+struct virgl_winsys *virgl_vtest_winsys_wrap(struct sw_winsys *sws);
+
+#endif
diff --git a/src/gallium/winsys/virgl/vtest/virgl_vtest_socket.c b/src/gallium/winsys/virgl/vtest/virgl_vtest_socket.c
new file mode 100644
index 00000000000..48dff8d0c17
--- /dev/null
+++ b/src/gallium/winsys/virgl/vtest/virgl_vtest_socket.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2014, 2015 Red Hat.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#define _FILE_OFFSET_BITS 64
+
+#include "virgl_vtest_winsys.h"
+#include "virgl_vtest_public.h"
+#include <sys/socket.h>
+#include <errno.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <os/os_process.h>
+#include <util/u_format.h>
+/* connect to remote socket */
+#define VTEST_SOCKET_NAME "/tmp/.virgl_test"
+
+/* block read/write routines */
+static int virgl_block_write(int fd, void *buf, int size)
+{
+ void *ptr = buf;
+ int left;
+ int ret;
+ left = size;
+ do {
+ ret = write(fd, ptr, left);
+ if (ret < 0)
+ return -errno;
+ left -= ret;
+ ptr += ret;
+ } while (left);
+ return size;
+}
+
+static int virgl_block_read(int fd, void *buf, int size)
+{
+ void *ptr = buf;
+ int left;
+ int ret;
+ left = size;
+ do {
+ ret = read(fd, ptr, left);
+ if (ret <= 0) {
+ fprintf(stderr, "lost connection to rendering server on %d read %d %d\n", size, ret, errno);
+ abort();
+ return ret < 0 ? -errno : 0;
+ }
+ left -= ret;
+ ptr += ret;
+ } while (left);
+ return size;
+}
+
+static int virgl_vtest_send_init(struct virgl_vtest_winsys *vws)
+{
+ uint32_t buf[VTEST_HDR_SIZE];
+ const char *nstr = "virtest";
+ char cmdline[64];
+ int ret;
+
+ ret = os_get_process_name(cmdline, 63);
+ if (ret == FALSE)
+ strcpy(cmdline, nstr);
+#if defined(__GLIBC__) || defined(__CYGWIN__)
+ if (!strcmp(cmdline, "shader_runner")) {
+ const char *name;
+ /* hack to get better testname */
+ name = program_invocation_short_name;
+ name += strlen(name) + 1;
+ strncpy(cmdline, name, 63);
+ }
+#endif
+ buf[VTEST_CMD_LEN] = strlen(cmdline) + 1;
+ buf[VTEST_CMD_ID] = VCMD_CREATE_RENDERER;
+
+ virgl_block_write(vws->sock_fd, &buf, sizeof(buf));
+ virgl_block_write(vws->sock_fd, (void *)cmdline, strlen(cmdline) + 1);
+ return 0;
+}
+
+int virgl_vtest_connect(struct virgl_vtest_winsys *vws)
+{
+ struct sockaddr_un un;
+ int sock, ret;
+
+ sock = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0)
+ return -1;
+
+ memset(&un, 0, sizeof(un));
+ un.sun_family = AF_UNIX;
+ snprintf(un.sun_path, sizeof(un.sun_path), "%s", VTEST_SOCKET_NAME);
+
+ do {
+ ret = 0;
+ if (connect(sock, (struct sockaddr *)&un, sizeof(un)) < 0) {
+ ret = -errno;
+ }
+ } while (ret == -EINTR);
+
+ vws->sock_fd = sock;
+ virgl_vtest_send_init(vws);
+ return 0;
+}
+
+int virgl_vtest_send_get_caps(struct virgl_vtest_winsys *vws,
+ struct virgl_drm_caps *caps)
+{
+ uint32_t get_caps_buf[VTEST_HDR_SIZE];
+ uint32_t resp_buf[VTEST_HDR_SIZE];
+
+ int ret;
+ get_caps_buf[VTEST_CMD_LEN] = 0;
+ get_caps_buf[VTEST_CMD_ID] = VCMD_GET_CAPS;
+
+ virgl_block_write(vws->sock_fd, &get_caps_buf, sizeof(get_caps_buf));
+
+ ret = virgl_block_read(vws->sock_fd, resp_buf, sizeof(resp_buf));
+ if (ret <= 0)
+ return 0;
+
+ ret = virgl_block_read(vws->sock_fd, &caps->caps, sizeof(union virgl_caps));
+
+ return 0;
+}
+
+int virgl_vtest_send_resource_create(struct virgl_vtest_winsys *vws,
+ uint32_t handle,
+ 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 res_create_buf[VCMD_RES_CREATE_SIZE], vtest_hdr[VTEST_HDR_SIZE];
+
+ vtest_hdr[VTEST_CMD_LEN] = VCMD_RES_CREATE_SIZE;
+ vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_CREATE;
+
+ res_create_buf[VCMD_RES_CREATE_RES_HANDLE] = handle;
+ res_create_buf[VCMD_RES_CREATE_TARGET] = target;
+ res_create_buf[VCMD_RES_CREATE_FORMAT] = format;
+ res_create_buf[VCMD_RES_CREATE_BIND] = bind;
+ res_create_buf[VCMD_RES_CREATE_WIDTH] = width;
+ res_create_buf[VCMD_RES_CREATE_HEIGHT] = height;
+ res_create_buf[VCMD_RES_CREATE_DEPTH] = depth;
+ res_create_buf[VCMD_RES_CREATE_ARRAY_SIZE] = array_size;
+ res_create_buf[VCMD_RES_CREATE_LAST_LEVEL] = last_level;
+ res_create_buf[VCMD_RES_CREATE_NR_SAMPLES] = nr_samples;
+
+ virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
+ virgl_block_write(vws->sock_fd, &res_create_buf, sizeof(res_create_buf));
+
+ return 0;
+}
+
+int virgl_vtest_submit_cmd(struct virgl_vtest_winsys *vws,
+ struct virgl_vtest_cmd_buf *cbuf)
+{
+ uint32_t vtest_hdr[VTEST_HDR_SIZE];
+
+ vtest_hdr[VTEST_CMD_LEN] = cbuf->base.cdw;
+ vtest_hdr[VTEST_CMD_ID] = VCMD_SUBMIT_CMD;
+
+ virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
+ virgl_block_write(vws->sock_fd, cbuf->buf, cbuf->base.cdw * 4);
+ return 0;
+}
+
+int virgl_vtest_send_resource_unref(struct virgl_vtest_winsys *vws,
+ uint32_t handle)
+{
+ uint32_t vtest_hdr[VTEST_HDR_SIZE];
+ uint32_t cmd[1];
+ vtest_hdr[VTEST_CMD_LEN] = 1;
+ vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_UNREF;
+
+ cmd[0] = handle;
+ virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
+ virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
+ return 0;
+}
+
+int virgl_vtest_send_transfer_cmd(struct virgl_vtest_winsys *vws,
+ uint32_t vcmd,
+ uint32_t handle,
+ uint32_t level, uint32_t stride,
+ uint32_t layer_stride,
+ const struct pipe_box *box,
+ uint32_t data_size)
+{
+ uint32_t vtest_hdr[VTEST_HDR_SIZE];
+ uint32_t cmd[VCMD_TRANSFER_HDR_SIZE];
+ bool is_put = (vcmd == VCMD_TRANSFER_PUT);
+ vtest_hdr[VTEST_CMD_LEN] = VCMD_TRANSFER_HDR_SIZE + (is_put ? (data_size + 3 / 4) : 0);
+ vtest_hdr[VTEST_CMD_ID] = vcmd;
+
+ cmd[0] = handle;
+ cmd[1] = level;
+ cmd[2] = stride;
+ cmd[3] = layer_stride;
+ cmd[4] = box->x;
+ cmd[5] = box->y;
+ cmd[6] = box->z;
+ cmd[7] = box->width;
+ cmd[8] = box->height;
+ cmd[9] = box->depth;
+ cmd[10] = data_size;
+ virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
+ virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
+
+ return 0;
+}
+
+int virgl_vtest_send_transfer_put_data(struct virgl_vtest_winsys *vws,
+ void *data,
+ uint32_t data_size)
+{
+ return virgl_block_write(vws->sock_fd, data, data_size);
+}
+
+int virgl_vtest_recv_transfer_get_data(struct virgl_vtest_winsys *vws,
+ void *data,
+ uint32_t data_size,
+ uint32_t stride,
+ const struct pipe_box *box, uint32_t format)
+{
+ void *line = malloc(stride);
+ void *ptr = data;
+ int hblocks = util_format_get_nblocksy(format, box->height);
+
+ line = malloc(stride);
+ while (hblocks) {
+ virgl_block_read(vws->sock_fd, line, stride);
+ memcpy(ptr, line, util_format_get_stride(format, box->width));
+ ptr += stride;
+ hblocks--;
+ }
+ free(line);
+ return 0;
+}
+
+int virgl_vtest_busy_wait(struct virgl_vtest_winsys *vws, int handle,
+ int flags)
+{
+ uint32_t vtest_hdr[VTEST_HDR_SIZE];
+ uint32_t cmd[VCMD_BUSY_WAIT_SIZE];
+ uint32_t result[1];
+ int ret;
+ vtest_hdr[VTEST_CMD_LEN] = VCMD_BUSY_WAIT_SIZE;
+ vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_BUSY_WAIT;
+ cmd[VCMD_BUSY_WAIT_HANDLE] = handle;
+ cmd[VCMD_BUSY_WAIT_FLAGS] = flags;
+
+ virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
+ virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
+
+ ret = virgl_block_read(vws->sock_fd, vtest_hdr, sizeof(vtest_hdr));
+ assert(ret);
+ ret = virgl_block_read(vws->sock_fd, result, sizeof(result));
+ assert(ret);
+ return result[0];
+}
diff --git a/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c b/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c
new file mode 100644
index 00000000000..9002d40450b
--- /dev/null
+++ b/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c
@@ -0,0 +1,653 @@
+/*
+ * Copyright 2014, 2015 Red Hat.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#define _FILE_OFFSET_BITS 64
+
+#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"
+
+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;
+}
+
+static uint32_t vtest_get_transfer_size(struct virgl_hw_res *res,
+ const struct pipe_box *box,
+ uint32_t stride, uint32_t layer_stride,
+ uint32_t level, uint32_t *valid_stride_p)
+{
+ uint32_t valid_stride, valid_layer_stride;
+
+ valid_stride = util_format_get_stride(res->format, box->width);
+ if (stride) {
+ if (box->height > 1)
+ valid_stride = stride;
+ }
+
+ valid_layer_stride = util_format_get_2d_size(res->format, valid_stride,
+ box->height);
+ if (layer_stride) {
+ if (box->depth > 1)
+ valid_layer_stride = layer_stride;
+ }
+
+ *valid_stride_p = valid_stride;
+ return valid_layer_stride * box->depth;
+}
+
+static int
+virgl_vtest_transfer_put(struct virgl_winsys *vws,
+ struct virgl_hw_res *res,
+ const struct pipe_box *box,
+ uint32_t stride, uint32_t layer_stride,
+ uint32_t buf_offset, uint32_t level)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+ uint32_t size;
+ void *ptr;
+ uint32_t valid_stride;
+
+ size = vtest_get_transfer_size(res, box, stride, layer_stride, level, &valid_stride);
+
+ virgl_vtest_send_transfer_cmd(vtws, VCMD_TRANSFER_PUT, res->res_handle,
+ level, stride, layer_stride,
+ box, size);
+ ptr = virgl_vtest_resource_map(vws, res);
+ virgl_vtest_send_transfer_put_data(vtws, ptr + buf_offset, size);
+ virgl_vtest_resource_unmap(vws, res);
+ return 0;
+}
+
+static int
+virgl_vtest_transfer_get(struct virgl_winsys *vws,
+ struct virgl_hw_res *res,
+ const struct pipe_box *box,
+ uint32_t stride, uint32_t layer_stride,
+ uint32_t buf_offset, uint32_t level)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+ uint32_t size;
+ void *ptr;
+ uint32_t valid_stride;
+
+ size = vtest_get_transfer_size(res, box, stride, layer_stride, level, &valid_stride);
+
+ virgl_vtest_send_transfer_cmd(vtws, VCMD_TRANSFER_GET, res->res_handle,
+ level, stride, layer_stride,
+ box, size);
+
+
+ ptr = virgl_vtest_resource_map(vws, res);
+ virgl_vtest_recv_transfer_get_data(vtws, ptr + buf_offset, size, valid_stride, box, res->format);
+ virgl_vtest_resource_unmap(vws, res);
+ return 0;
+}
+
+static void virgl_hw_res_destroy(struct virgl_vtest_winsys *vtws,
+ struct virgl_hw_res *res)
+{
+ virgl_vtest_send_resource_unref(vtws, res->res_handle);
+ if (res->dt)
+ vtws->sws->displaytarget_destroy(vtws->sws, res->dt);
+ free(res->ptr);
+ FREE(res);
+}
+
+static boolean virgl_vtest_resource_is_busy(struct virgl_vtest_winsys *vtws,
+ struct virgl_hw_res *res)
+{
+ /* implement busy check */
+ int ret;
+ ret = virgl_vtest_busy_wait(vtws, res->res_handle, 0);
+
+ if (ret < 0)
+ return FALSE;
+
+ return ret == 1 ? TRUE : FALSE;
+}
+
+static void
+virgl_cache_flush(struct virgl_vtest_winsys *vtws)
+{
+ struct list_head *curr, *next;
+ struct virgl_hw_res *res;
+
+ pipe_mutex_lock(vtws->mutex);
+ curr = vtws->delayed.next;
+ next = curr->next;
+
+ while (curr != &vtws->delayed) {
+ res = LIST_ENTRY(struct virgl_hw_res, curr, head);
+ LIST_DEL(&res->head);
+ virgl_hw_res_destroy(vtws, res);
+ curr = next;
+ next = curr->next;
+ }
+ pipe_mutex_unlock(vtws->mutex);
+}
+
+static void
+virgl_cache_list_check_free(struct virgl_vtest_winsys *vtws)
+{
+ struct list_head *curr, *next;
+ struct virgl_hw_res *res;
+ int64_t now;
+
+ now = os_time_get();
+ curr = vtws->delayed.next;
+ next = curr->next;
+ while (curr != &vtws->delayed) {
+ res = LIST_ENTRY(struct virgl_hw_res, curr, head);
+ if (!os_time_timeout(res->start, res->end, now))
+ break;
+
+ LIST_DEL(&res->head);
+ virgl_hw_res_destroy(vtws, res);
+ curr = next;
+ next = curr->next;
+ }
+}
+
+static void virgl_vtest_resource_reference(struct virgl_vtest_winsys *vtws,
+ struct virgl_hw_res **dres,
+ struct virgl_hw_res *sres)
+{
+ struct virgl_hw_res *old = *dres;
+ if (pipe_reference(&(*dres)->reference, &sres->reference)) {
+ if (!can_cache_resource(old)) {
+ virgl_hw_res_destroy(vtws, old);
+ } else {
+ pipe_mutex_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);
+ }
+ }
+ *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)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+ struct virgl_hw_res *res;
+ static int handle = 1;
+
+ res = CALLOC_STRUCT(virgl_hw_res);
+ if (!res)
+ 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->stride);
+
+ } else {
+ res->ptr = align_malloc(size, 64);
+ if (!res->ptr) {
+ FREE(res);
+ return NULL;
+ }
+ }
+
+ res->bind = bind;
+ 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->res_handle = handle++;
+ pipe_reference_init(&res->reference, 1);
+ return res;
+}
+
+static void virgl_vtest_winsys_resource_unref(struct virgl_winsys *vws,
+ struct virgl_hw_res *hres)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+ virgl_vtest_resource_reference(vtws, &hres, NULL);
+}
+
+static void *virgl_vtest_resource_map(struct virgl_winsys *vws, struct virgl_hw_res *res)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+
+ if (res->dt) {
+ return vtws->sws->displaytarget_map(vtws->sws, res->dt, 0);
+ } else {
+ res->mapped = res->ptr;
+ return res->mapped;
+ }
+}
+
+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)
+ res->mapped = NULL;
+
+ if (res->dt)
+ vtws->sws->displaytarget_unmap(vtws->sws, res->dt);
+}
+
+static void virgl_vtest_resource_wait(struct virgl_winsys *vws, struct virgl_hw_res *res)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+
+ virgl_vtest_busy_wait(vtws, res->res_handle, VCMD_BUSY_WAIT_FLAG_WAIT);
+}
+
+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)
+{
+ if (res->bind != bind)
+ return 0;
+ if (res->format != format)
+ return 0;
+ if (res->size < size)
+ return 0;
+ if (res->size > size * 2)
+ return 0;
+
+ if (virgl_vtest_resource_is_busy(vtws, res)) {
+ return -1;
+ }
+
+ 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)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+ struct virgl_hw_res *res, *curr_res;
+ struct list_head *curr, *next;
+ int64_t now;
+ int ret;
+
+ /* only store binds for vertex/index/const buffers */
+ if (bind != VIRGL_BIND_CONSTANT_BUFFER && bind != VIRGL_BIND_INDEX_BUFFER &&
+ bind != VIRGL_BIND_VERTEX_BUFFER && bind != VIRGL_BIND_CUSTOM)
+ goto alloc;
+
+ pipe_mutex_lock(vtws->mutex);
+
+ res = NULL;
+ curr = vtws->delayed.next;
+ next = curr->next;
+
+ now = os_time_get();
+ 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))
+ res = curr_res;
+ else if (os_time_timeout(curr_res->start, curr_res->end, now)) {
+ LIST_DEL(&curr_res->head);
+ virgl_hw_res_destroy(vtws, curr_res);
+ } else
+ break;
+
+ if (ret == -1)
+ break;
+
+ curr = next;
+ next = curr->next;
+ }
+
+ if (!res && ret != -1) {
+ while (curr != &vtws->delayed) {
+ curr_res = LIST_ENTRY(struct virgl_hw_res, curr, head);
+ ret = virgl_is_res_compat(vtws, curr_res, size, bind, format);
+ if (ret > 0) {
+ res = curr_res;
+ break;
+ }
+ if (ret == -1)
+ break;
+ curr = next;
+ next = curr->next;
+ }
+ }
+
+ if (res) {
+ LIST_DEL(&res->head);
+ --vtws->num_delayed;
+ pipe_mutex_unlock(vtws->mutex);
+ pipe_reference_init(&res->reference, 1);
+ return res;
+ }
+
+ pipe_mutex_unlock(vtws->mutex);
+
+alloc:
+ res = virgl_vtest_winsys_resource_create(vws, target, format, bind,
+ 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;
+ return res;
+}
+
+static struct virgl_cmd_buf *virgl_vtest_cmd_buf_create(struct virgl_winsys *vws)
+{
+ struct virgl_vtest_cmd_buf *cbuf;
+
+ cbuf = CALLOC_STRUCT(virgl_vtest_cmd_buf);
+ if (!cbuf)
+ return NULL;
+
+ cbuf->nres = 512;
+ cbuf->res_bo = (struct virgl_hw_res **)
+ CALLOC(cbuf->nres, sizeof(struct virgl_hw_buf*));
+ if (!cbuf->res_bo) {
+ FREE(cbuf);
+ return NULL;
+ }
+ cbuf->ws = vws;
+ cbuf->base.buf = cbuf->buf;
+ return &cbuf->base;
+}
+
+static void virgl_vtest_cmd_buf_destroy(struct virgl_cmd_buf *_cbuf)
+{
+ struct virgl_vtest_cmd_buf *cbuf = (struct virgl_vtest_cmd_buf *)_cbuf;
+
+ FREE(cbuf->res_bo);
+ FREE(cbuf);
+}
+
+static boolean virgl_vtest_lookup_res(struct virgl_vtest_cmd_buf *cbuf,
+ struct virgl_hw_res *res)
+{
+ unsigned hash = res->res_handle & (sizeof(cbuf->is_handle_added)-1);
+ int i;
+
+ if (cbuf->is_handle_added[hash]) {
+ i = cbuf->reloc_indices_hashlist[hash];
+ if (cbuf->res_bo[i] == res)
+ return true;
+
+ for (i = 0; i < cbuf->cres; i++) {
+ if (cbuf->res_bo[i] == res) {
+ cbuf->reloc_indices_hashlist[hash] = i;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static void virgl_vtest_release_all_res(struct virgl_vtest_winsys *vtws,
+ struct virgl_vtest_cmd_buf *cbuf)
+{
+ int i;
+
+ for (i = 0; i < cbuf->cres; i++) {
+ p_atomic_dec(&cbuf->res_bo[i]->num_cs_references);
+ virgl_vtest_resource_reference(vtws, &cbuf->res_bo[i], NULL);
+ }
+ cbuf->cres = 0;
+}
+
+static void virgl_vtest_add_res(struct virgl_vtest_winsys *vtws,
+ 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;
+ }
+
+ cbuf->res_bo[cbuf->cres] = NULL;
+ virgl_vtest_resource_reference(vtws, &cbuf->res_bo[cbuf->cres], res);
+ cbuf->is_handle_added[hash] = TRUE;
+
+ cbuf->reloc_indices_hashlist[hash] = cbuf->cres;
+ p_atomic_inc(&res->num_cs_references);
+ cbuf->cres++;
+}
+
+static int virgl_vtest_winsys_submit_cmd(struct virgl_winsys *vws, struct virgl_cmd_buf *_cbuf)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+ struct virgl_vtest_cmd_buf *cbuf = (struct virgl_vtest_cmd_buf *)_cbuf;
+ int ret;
+
+ if (cbuf->base.cdw == 0)
+ return 0;
+
+ ret = virgl_vtest_submit_cmd(vtws, cbuf);
+
+ virgl_vtest_release_all_res(vtws, cbuf);
+ memset(cbuf->is_handle_added, 0, sizeof(cbuf->is_handle_added));
+ cbuf->base.cdw = 0;
+ 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)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+ struct virgl_vtest_cmd_buf *cbuf = (struct virgl_vtest_cmd_buf *)_cbuf;
+ boolean already_in_list = virgl_vtest_lookup_res(cbuf, res);
+
+ if (write_buf)
+ cbuf->base.buf[cbuf->base.cdw++] = res->res_handle;
+ if (!already_in_list)
+ virgl_vtest_add_res(vtws, cbuf, res);
+}
+
+static boolean virgl_vtest_res_is_ref(struct virgl_winsys *vws,
+ struct virgl_cmd_buf *_cbuf,
+ struct virgl_hw_res *res)
+{
+ if (!res->num_cs_references)
+ return FALSE;
+
+ return TRUE;
+}
+
+static int virgl_vtest_get_caps(struct virgl_winsys *vws, struct virgl_drm_caps *caps)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+ return virgl_vtest_send_get_caps(vtws, caps);
+}
+
+static struct pipe_fence_handle *
+virgl_cs_create_fence(struct virgl_winsys *vws)
+{
+ struct virgl_hw_res *res;
+
+ res = virgl_vtest_winsys_resource_cache_create(vws,
+ PIPE_BUFFER,
+ PIPE_FORMAT_R8_UNORM,
+ PIPE_BIND_CUSTOM,
+ 8, 1, 1, 0, 0, 0, 8);
+
+ return (struct pipe_fence_handle *)res;
+}
+
+static bool virgl_fence_wait(struct virgl_winsys *vws,
+ struct pipe_fence_handle *fence,
+ uint64_t timeout)
+{
+ struct virgl_vtest_winsys *vdws = virgl_vtest_winsys(vws);
+ struct virgl_hw_res *res = (struct virgl_hw_res *)fence;
+
+ if (timeout == 0)
+ return virgl_vtest_resource_is_busy(vdws, res);
+
+ if (timeout != PIPE_TIMEOUT_INFINITE) {
+ int64_t start_time = os_time_get();
+ timeout /= 1000;
+ while (virgl_vtest_resource_is_busy(vdws, res)) {
+ if (os_time_get() - start_time >= timeout)
+ return FALSE;
+ os_time_sleep(10);
+ }
+ return TRUE;
+ }
+ virgl_vtest_resource_wait(vws, res);
+ return TRUE;
+}
+
+static void virgl_fence_reference(struct virgl_winsys *vws,
+ struct pipe_fence_handle **dst,
+ struct pipe_fence_handle *src)
+{
+ struct virgl_vtest_winsys *vdws = virgl_vtest_winsys(vws);
+ virgl_vtest_resource_reference(vdws, (struct virgl_hw_res **)dst,
+ (struct virgl_hw_res *)src);
+}
+
+static void virgl_vtest_flush_frontbuffer(struct virgl_winsys *vws,
+ struct virgl_hw_res *res,
+ unsigned level, unsigned layer,
+ void *winsys_drawable_handle,
+ struct pipe_box *sub_box)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+ struct pipe_box box;
+ void *map;
+ uint32_t size;
+ uint32_t offset = 0, valid_stride;
+ if (!res->dt)
+ return;
+
+ memset(&box, 0, sizeof(box));
+
+ 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);
+ } else {
+ box.z = layer;
+ box.width = res->width;
+ box.height = res->height;
+ box.depth = 1;
+ }
+
+ size = vtest_get_transfer_size(res, &box, res->stride, 0, level, &valid_stride);
+
+ virgl_vtest_busy_wait(vtws, res->res_handle, VCMD_BUSY_WAIT_FLAG_WAIT);
+ 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);
+ vtws->sws->displaytarget_unmap(vtws->sws, res->dt);
+
+ vtws->sws->displaytarget_display(vtws->sws, res->dt, winsys_drawable_handle, sub_box);
+}
+
+static void
+virgl_vtest_winsys_destroy(struct virgl_winsys *vws)
+{
+ struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
+
+ virgl_cache_flush(vtws);
+
+ pipe_mutex_destroy(vtws->mutex);
+ FREE(vtws);
+}
+
+struct virgl_winsys *
+virgl_vtest_winsys_wrap(struct sw_winsys *sws)
+{
+ struct virgl_vtest_winsys *vtws;
+
+ vtws = CALLOC_STRUCT(virgl_vtest_winsys);
+ if (!vtws)
+ return NULL;
+
+ virgl_vtest_connect(vtws);
+ vtws->sws = sws;
+
+ vtws->usecs = 1000000;
+ LIST_INITHEAD(&vtws->delayed);
+ pipe_mutex_init(vtws->mutex);
+
+ vtws->base.destroy = virgl_vtest_winsys_destroy;
+
+ vtws->base.transfer_put = virgl_vtest_transfer_put;
+ vtws->base.transfer_get = virgl_vtest_transfer_get;
+
+ vtws->base.resource_create = virgl_vtest_winsys_resource_cache_create;
+ vtws->base.resource_unref = virgl_vtest_winsys_resource_unref;
+ vtws->base.resource_map = virgl_vtest_resource_map;
+ vtws->base.resource_wait = virgl_vtest_resource_wait;
+ vtws->base.cmd_buf_create = virgl_vtest_cmd_buf_create;
+ vtws->base.cmd_buf_destroy = virgl_vtest_cmd_buf_destroy;
+ vtws->base.submit_cmd = virgl_vtest_winsys_submit_cmd;
+
+ vtws->base.emit_res = virgl_vtest_emit_res;
+ vtws->base.res_is_referenced = virgl_vtest_res_is_ref;
+ vtws->base.get_caps = virgl_vtest_get_caps;
+
+ 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.flush_frontbuffer = virgl_vtest_flush_frontbuffer;
+
+ return &vtws->base;
+}
diff --git a/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.h b/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.h
new file mode 100644
index 00000000000..3967befa1a9
--- /dev/null
+++ b/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2014, 2015 Red Hat.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef VIRGL_DRM_WINSYS_H
+#define VIRGL_DRM_WINSYS_H
+
+#include <stdint.h>
+#include "pipe/p_compiler.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "state_tracker/sw_winsys.h"
+#include "../drm/virgl_hw.h"
+#include "virgl/virgl_winsys.h"
+#include "util/list.h"
+#include "os/os_thread.h"
+
+#include "vtest_protocol.h"
+struct virgl_vtest_winsys {
+ struct virgl_winsys base;
+
+ struct sw_winsys *sws;
+
+ /* fd to remote renderer */
+ int sock_fd;
+
+ struct list_head delayed;
+ int num_delayed;
+ unsigned usecs;
+ pipe_mutex mutex;
+};
+
+struct virgl_hw_res {
+ struct pipe_reference reference;
+ uint32_t res_handle;
+ int num_cs_references;
+
+ void *ptr;
+ int size;
+
+ uint32_t format;
+ uint32_t stride;
+ uint32_t width;
+ uint32_t height;
+
+ struct sw_displaytarget *dt;
+ void *mapped;
+
+ struct list_head head;
+ uint32_t bind;
+ boolean cacheable;
+ int64_t start, end;
+
+};
+
+struct virgl_vtest_cmd_buf {
+ struct virgl_cmd_buf base;
+ uint32_t buf[VIRGL_MAX_CMDBUF_DWORDS];
+ unsigned nres;
+ unsigned cres;
+ struct virgl_winsys *ws;
+ struct virgl_hw_res **res_bo;
+
+ char is_handle_added[512];
+ unsigned reloc_indices_hashlist[512];
+};
+
+static inline struct virgl_vtest_winsys *
+virgl_vtest_winsys(struct virgl_winsys *iws)
+{
+ return (struct virgl_vtest_winsys *)iws;
+}
+
+int virgl_vtest_connect(struct virgl_vtest_winsys *vws);
+int virgl_vtest_send_get_caps(struct virgl_vtest_winsys *vws,
+ struct virgl_drm_caps *caps);
+
+int virgl_vtest_send_resource_create(struct virgl_vtest_winsys *vws,
+ uint32_t handle,
+ 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);
+
+int virgl_vtest_send_resource_unref(struct virgl_vtest_winsys *vws,
+ uint32_t handle);
+int virgl_vtest_submit_cmd(struct virgl_vtest_winsys *vtws,
+ struct virgl_vtest_cmd_buf *cbuf);
+
+int virgl_vtest_send_transfer_cmd(struct virgl_vtest_winsys *vws,
+ uint32_t vcmd,
+ uint32_t handle,
+ uint32_t level, uint32_t stride,
+ uint32_t layer_stride,
+ const struct pipe_box *box,
+ uint32_t data_size);
+
+int virgl_vtest_send_transfer_put_data(struct virgl_vtest_winsys *vws,
+ void *data,
+ uint32_t data_size);
+int virgl_vtest_recv_transfer_get_data(struct virgl_vtest_winsys *vws,
+ void *data,
+ uint32_t data_size,
+ uint32_t stride,
+ const struct pipe_box *box, uint32_t format);
+
+int virgl_vtest_busy_wait(struct virgl_vtest_winsys *vws, int handle,
+ int flags);
+#endif
diff --git a/src/gallium/winsys/virgl/vtest/vtest_protocol.h b/src/gallium/winsys/virgl/vtest/vtest_protocol.h
new file mode 100644
index 00000000000..86d197f006c
--- /dev/null
+++ b/src/gallium/winsys/virgl/vtest/vtest_protocol.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2014, 2015 Red Hat.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef VTEST_PROTOCOL
+#define VTEST_PROTOCOL
+
+#define VTEST_DEFAULT_SOCKET_NAME "/tmp/.virgl_test"
+
+/* 32-bit length field */
+/* 32-bit cmd field */
+#define VTEST_HDR_SIZE 2
+#define VTEST_CMD_LEN 0 /* length of data */
+#define VTEST_CMD_ID 1
+#define VTEST_CMD_DATA_START 2
+
+/* vtest cmds */
+#define VCMD_GET_CAPS 1
+
+#define VCMD_RESOURCE_CREATE 2
+#define VCMD_RESOURCE_UNREF 3
+
+#define VCMD_TRANSFER_GET 4
+#define VCMD_TRANSFER_PUT 5
+
+#define VCMD_SUBMIT_CMD 6
+
+#define VCMD_RESOURCE_BUSY_WAIT 7
+
+/* pass the process cmd line for debugging */
+#define VCMD_CREATE_RENDERER 8
+/* get caps */
+/* 0 length cmd */
+/* resp VCMD_GET_CAPS + caps */
+
+#define VCMD_RES_CREATE_SIZE 10
+#define VCMD_RES_CREATE_RES_HANDLE 0
+#define VCMD_RES_CREATE_TARGET 1
+#define VCMD_RES_CREATE_FORMAT 2
+#define VCMD_RES_CREATE_BIND 3
+#define VCMD_RES_CREATE_WIDTH 4
+#define VCMD_RES_CREATE_HEIGHT 5
+#define VCMD_RES_CREATE_DEPTH 6
+#define VCMD_RES_CREATE_ARRAY_SIZE 7
+#define VCMD_RES_CREATE_LAST_LEVEL 8
+#define VCMD_RES_CREATE_NR_SAMPLES 9
+
+#define VCMD_RES_UNREF_SIZE 1
+#define VCMD_RES_UNREF_RES_HANDLE 0
+
+#define VCMD_TRANSFER_HDR_SIZE 11
+#define VCMD_TRANSFER_RES_HANDLE 0
+#define VCMD_TRANSFER_LEVEL 1
+#define VCMD_TRANSFER_STRIDE 2
+#define VCMD_TRANSFER_LAYER_STRIDE 3
+#define VCMD_TRANSFER_X 4
+#define VCMD_TRANSFER_Y 5
+#define VCMD_TRANSFER_Z 6
+#define VCMD_TRANSFER_WIDTH 7
+#define VCMD_TRANSFER_HEIGHT 8
+#define VCMD_TRANSFER_DEPTH 9
+#define VCMD_TRANSFER_DATA_SIZE 10
+
+#define VCMD_BUSY_WAIT_FLAG_WAIT 1
+
+#define VCMD_BUSY_WAIT_SIZE 2
+#define VCMD_BUSY_WAIT_HANDLE 0
+#define VCMD_BUSY_WAIT_FLAGS 1
+
+#endif