diff options
Diffstat (limited to 'lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_socket.c')
-rw-r--r-- | lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_socket.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_socket.c b/lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_socket.c new file mode 100644 index 000000000..4541419d8 --- /dev/null +++ b/lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_socket.c @@ -0,0 +1,293 @@ +/* + * 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. + */ + +#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" + +#include "virgl_vtest_winsys.h" +#include "virgl_vtest_public.h" + +/* 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]; + vtest_hdr[VTEST_CMD_LEN] = VCMD_TRANSFER_HDR_SIZE; + vtest_hdr[VTEST_CMD_ID] = vcmd; + + if (vcmd == VCMD_TRANSFER_PUT) + vtest_hdr[VTEST_CMD_LEN] += data_size + 3 / 4; + + 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; + 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]; +} |