virgl: unwrap the includes
[mesa.git] / src / gallium / winsys / virgl / vtest / virgl_vtest_socket.c
1 /*
2 * Copyright 2014, 2015 Red Hat.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <sys/socket.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <netinet/in.h>
28 #include <sys/un.h>
29 #include <unistd.h>
30
31 #include <os/os_process.h>
32 #include <util/u_format.h>
33 /* connect to remote socket */
34 #define VTEST_SOCKET_NAME "/tmp/.virgl_test"
35
36 #include "virgl_vtest_winsys.h"
37 #include "virgl_vtest_public.h"
38
39 /* block read/write routines */
40 static int virgl_block_write(int fd, void *buf, int size)
41 {
42 void *ptr = buf;
43 int left;
44 int ret;
45 left = size;
46 do {
47 ret = write(fd, ptr, left);
48 if (ret < 0)
49 return -errno;
50 left -= ret;
51 ptr += ret;
52 } while (left);
53 return size;
54 }
55
56 static int virgl_block_read(int fd, void *buf, int size)
57 {
58 void *ptr = buf;
59 int left;
60 int ret;
61 left = size;
62 do {
63 ret = read(fd, ptr, left);
64 if (ret <= 0) {
65 fprintf(stderr, "lost connection to rendering server on %d read %d %d\n", size, ret, errno);
66 abort();
67 return ret < 0 ? -errno : 0;
68 }
69 left -= ret;
70 ptr += ret;
71 } while (left);
72 return size;
73 }
74
75 static int virgl_vtest_send_init(struct virgl_vtest_winsys *vws)
76 {
77 uint32_t buf[VTEST_HDR_SIZE];
78 const char *nstr = "virtest";
79 char cmdline[64];
80 int ret;
81
82 ret = os_get_process_name(cmdline, 63);
83 if (ret == FALSE)
84 strcpy(cmdline, nstr);
85 #if defined(__GLIBC__) || defined(__CYGWIN__)
86 if (!strcmp(cmdline, "shader_runner")) {
87 const char *name;
88 /* hack to get better testname */
89 name = program_invocation_short_name;
90 name += strlen(name) + 1;
91 strncpy(cmdline, name, 63);
92 }
93 #endif
94 buf[VTEST_CMD_LEN] = strlen(cmdline) + 1;
95 buf[VTEST_CMD_ID] = VCMD_CREATE_RENDERER;
96
97 virgl_block_write(vws->sock_fd, &buf, sizeof(buf));
98 virgl_block_write(vws->sock_fd, (void *)cmdline, strlen(cmdline) + 1);
99 return 0;
100 }
101
102 int virgl_vtest_connect(struct virgl_vtest_winsys *vws)
103 {
104 struct sockaddr_un un;
105 int sock, ret;
106
107 sock = socket(PF_UNIX, SOCK_STREAM, 0);
108 if (sock < 0)
109 return -1;
110
111 memset(&un, 0, sizeof(un));
112 un.sun_family = AF_UNIX;
113 snprintf(un.sun_path, sizeof(un.sun_path), "%s", VTEST_SOCKET_NAME);
114
115 do {
116 ret = 0;
117 if (connect(sock, (struct sockaddr *)&un, sizeof(un)) < 0) {
118 ret = -errno;
119 }
120 } while (ret == -EINTR);
121
122 vws->sock_fd = sock;
123 virgl_vtest_send_init(vws);
124 return 0;
125 }
126
127 int virgl_vtest_send_get_caps(struct virgl_vtest_winsys *vws,
128 struct virgl_drm_caps *caps)
129 {
130 uint32_t get_caps_buf[VTEST_HDR_SIZE];
131 uint32_t resp_buf[VTEST_HDR_SIZE];
132
133 int ret;
134 get_caps_buf[VTEST_CMD_LEN] = 0;
135 get_caps_buf[VTEST_CMD_ID] = VCMD_GET_CAPS;
136
137 virgl_block_write(vws->sock_fd, &get_caps_buf, sizeof(get_caps_buf));
138
139 ret = virgl_block_read(vws->sock_fd, resp_buf, sizeof(resp_buf));
140 if (ret <= 0)
141 return 0;
142
143 ret = virgl_block_read(vws->sock_fd, &caps->caps, sizeof(union virgl_caps));
144
145 return 0;
146 }
147
148 int virgl_vtest_send_resource_create(struct virgl_vtest_winsys *vws,
149 uint32_t handle,
150 enum pipe_texture_target target,
151 uint32_t format,
152 uint32_t bind,
153 uint32_t width,
154 uint32_t height,
155 uint32_t depth,
156 uint32_t array_size,
157 uint32_t last_level,
158 uint32_t nr_samples)
159 {
160 uint32_t res_create_buf[VCMD_RES_CREATE_SIZE], vtest_hdr[VTEST_HDR_SIZE];
161
162 vtest_hdr[VTEST_CMD_LEN] = VCMD_RES_CREATE_SIZE;
163 vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_CREATE;
164
165 res_create_buf[VCMD_RES_CREATE_RES_HANDLE] = handle;
166 res_create_buf[VCMD_RES_CREATE_TARGET] = target;
167 res_create_buf[VCMD_RES_CREATE_FORMAT] = format;
168 res_create_buf[VCMD_RES_CREATE_BIND] = bind;
169 res_create_buf[VCMD_RES_CREATE_WIDTH] = width;
170 res_create_buf[VCMD_RES_CREATE_HEIGHT] = height;
171 res_create_buf[VCMD_RES_CREATE_DEPTH] = depth;
172 res_create_buf[VCMD_RES_CREATE_ARRAY_SIZE] = array_size;
173 res_create_buf[VCMD_RES_CREATE_LAST_LEVEL] = last_level;
174 res_create_buf[VCMD_RES_CREATE_NR_SAMPLES] = nr_samples;
175
176 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
177 virgl_block_write(vws->sock_fd, &res_create_buf, sizeof(res_create_buf));
178
179 return 0;
180 }
181
182 int virgl_vtest_submit_cmd(struct virgl_vtest_winsys *vws,
183 struct virgl_vtest_cmd_buf *cbuf)
184 {
185 uint32_t vtest_hdr[VTEST_HDR_SIZE];
186
187 vtest_hdr[VTEST_CMD_LEN] = cbuf->base.cdw;
188 vtest_hdr[VTEST_CMD_ID] = VCMD_SUBMIT_CMD;
189
190 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
191 virgl_block_write(vws->sock_fd, cbuf->buf, cbuf->base.cdw * 4);
192 return 0;
193 }
194
195 int virgl_vtest_send_resource_unref(struct virgl_vtest_winsys *vws,
196 uint32_t handle)
197 {
198 uint32_t vtest_hdr[VTEST_HDR_SIZE];
199 uint32_t cmd[1];
200 vtest_hdr[VTEST_CMD_LEN] = 1;
201 vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_UNREF;
202
203 cmd[0] = handle;
204 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
205 virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
206 return 0;
207 }
208
209 int virgl_vtest_send_transfer_cmd(struct virgl_vtest_winsys *vws,
210 uint32_t vcmd,
211 uint32_t handle,
212 uint32_t level, uint32_t stride,
213 uint32_t layer_stride,
214 const struct pipe_box *box,
215 uint32_t data_size)
216 {
217 uint32_t vtest_hdr[VTEST_HDR_SIZE];
218 uint32_t cmd[VCMD_TRANSFER_HDR_SIZE];
219 bool is_put = (vcmd == VCMD_TRANSFER_PUT);
220 vtest_hdr[VTEST_CMD_LEN] = VCMD_TRANSFER_HDR_SIZE + (is_put ? (data_size + 3 / 4) : 0);
221 vtest_hdr[VTEST_CMD_ID] = vcmd;
222
223 cmd[0] = handle;
224 cmd[1] = level;
225 cmd[2] = stride;
226 cmd[3] = layer_stride;
227 cmd[4] = box->x;
228 cmd[5] = box->y;
229 cmd[6] = box->z;
230 cmd[7] = box->width;
231 cmd[8] = box->height;
232 cmd[9] = box->depth;
233 cmd[10] = data_size;
234 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
235 virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
236
237 return 0;
238 }
239
240 int virgl_vtest_send_transfer_put_data(struct virgl_vtest_winsys *vws,
241 void *data,
242 uint32_t data_size)
243 {
244 return virgl_block_write(vws->sock_fd, data, data_size);
245 }
246
247 int virgl_vtest_recv_transfer_get_data(struct virgl_vtest_winsys *vws,
248 void *data,
249 uint32_t data_size,
250 uint32_t stride,
251 const struct pipe_box *box, uint32_t format)
252 {
253 void *line = malloc(stride);
254 void *ptr = data;
255 int hblocks = util_format_get_nblocksy(format, box->height);
256
257 line = malloc(stride);
258 while (hblocks) {
259 virgl_block_read(vws->sock_fd, line, stride);
260 memcpy(ptr, line, util_format_get_stride(format, box->width));
261 ptr += stride;
262 hblocks--;
263 }
264 free(line);
265 return 0;
266 }
267
268 int virgl_vtest_busy_wait(struct virgl_vtest_winsys *vws, int handle,
269 int flags)
270 {
271 uint32_t vtest_hdr[VTEST_HDR_SIZE];
272 uint32_t cmd[VCMD_BUSY_WAIT_SIZE];
273 uint32_t result[1];
274 int ret;
275 vtest_hdr[VTEST_CMD_LEN] = VCMD_BUSY_WAIT_SIZE;
276 vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_BUSY_WAIT;
277 cmd[VCMD_BUSY_WAIT_HANDLE] = handle;
278 cmd[VCMD_BUSY_WAIT_FLAGS] = flags;
279
280 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
281 virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
282
283 ret = virgl_block_read(vws->sock_fd, vtest_hdr, sizeof(vtest_hdr));
284 assert(ret);
285 ret = virgl_block_read(vws->sock_fd, result, sizeof(result));
286 assert(ret);
287 return result[0];
288 }