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 <util/format/u_format.h>
32 #include <util/u_process.h>
33
34 #include "virgl_vtest_winsys.h"
35 #include "virgl_vtest_public.h"
36
37 /* block read/write routines */
virgl_block_write(int fd,void * buf,int size)38 static int virgl_block_write(int fd, void *buf, int size)
39 {
40 void *ptr = buf;
41 int left;
42 int ret;
43 left = size;
44 do {
45 ret = write(fd, ptr, left);
46 if (ret < 0)
47 return -errno;
48 left -= ret;
49 ptr += ret;
50 } while (left);
51 return size;
52 }
53
virgl_block_read(int fd,void * buf,int size)54 static int virgl_block_read(int fd, void *buf, int size)
55 {
56 void *ptr = buf;
57 int left;
58 int ret;
59 left = size;
60 do {
61 ret = read(fd, ptr, left);
62 if (ret <= 0) {
63 fprintf(stderr,
64 "lost connection to rendering server on %d read %d %d\n",
65 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
virgl_vtest_receive_fd(int socket_fd)75 static int virgl_vtest_receive_fd(int socket_fd)
76 {
77 struct cmsghdr *cmsgh;
78 struct msghdr msgh = { 0 };
79 char buf[CMSG_SPACE(sizeof(int))], c;
80 struct iovec iovec;
81
82 iovec.iov_base = &c;
83 iovec.iov_len = sizeof(char);
84
85 msgh.msg_name = NULL;
86 msgh.msg_namelen = 0;
87 msgh.msg_iov = &iovec;
88 msgh.msg_iovlen = 1;
89 msgh.msg_control = buf;
90 msgh.msg_controllen = sizeof(buf);
91 msgh.msg_flags = 0;
92
93 int size = recvmsg(socket_fd, &msgh, 0);
94 if (size < 0) {
95 fprintf(stderr, "Failed with %s\n", strerror(errno));
96 return -1;
97 }
98
99 cmsgh = CMSG_FIRSTHDR(&msgh);
100 if (!cmsgh) {
101 fprintf(stderr, "No headers available\n");
102 return -1;
103 }
104
105 if (cmsgh->cmsg_level != SOL_SOCKET) {
106 fprintf(stderr, "invalid cmsg_level %d\n", cmsgh->cmsg_level);
107 return -1;
108 }
109
110 if (cmsgh->cmsg_type != SCM_RIGHTS) {
111 fprintf(stderr, "invalid cmsg_type %d\n", cmsgh->cmsg_type);
112 return -1;
113 }
114
115 return *((int *) CMSG_DATA(cmsgh));
116 }
117
virgl_vtest_send_init(struct virgl_vtest_winsys * vws)118 static int virgl_vtest_send_init(struct virgl_vtest_winsys *vws)
119 {
120 uint32_t buf[VTEST_HDR_SIZE];
121 const char *nstr = "virtest";
122 char cmdline[64] = { 0 };
123 const char *proc_name = util_get_process_name();
124
125 if (proc_name)
126 strncpy(cmdline, proc_name, 63);
127 else
128 strcpy(cmdline, nstr);
129 #if defined(HAVE_PROGRAM_INVOCATION_NAME)
130 if (!strcmp(cmdline, "shader_runner")) {
131 const char *name;
132 /* hack to get better testname */
133 name = program_invocation_short_name;
134 name += strlen(name) + 1;
135 strncpy(cmdline, name, 63);
136 }
137 #endif
138 buf[VTEST_CMD_LEN] = strlen(cmdline) + 1;
139 buf[VTEST_CMD_ID] = VCMD_CREATE_RENDERER;
140
141 virgl_block_write(vws->sock_fd, &buf, sizeof(buf));
142 virgl_block_write(vws->sock_fd, (void *)cmdline, strlen(cmdline) + 1);
143 return 0;
144 }
145
virgl_vtest_negotiate_version(struct virgl_vtest_winsys * vws)146 static int virgl_vtest_negotiate_version(struct virgl_vtest_winsys *vws)
147 {
148 uint32_t vtest_hdr[VTEST_HDR_SIZE];
149 uint32_t version_buf[VCMD_PROTOCOL_VERSION_SIZE];
150 uint32_t busy_wait_buf[VCMD_BUSY_WAIT_SIZE];
151 uint32_t busy_wait_result[1];
152 ASSERTED int ret;
153
154 vtest_hdr[VTEST_CMD_LEN] = VCMD_PING_PROTOCOL_VERSION_SIZE;
155 vtest_hdr[VTEST_CMD_ID] = VCMD_PING_PROTOCOL_VERSION;
156 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
157
158 vtest_hdr[VTEST_CMD_LEN] = VCMD_BUSY_WAIT_SIZE;
159 vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_BUSY_WAIT;
160 busy_wait_buf[VCMD_BUSY_WAIT_HANDLE] = 0;
161 busy_wait_buf[VCMD_BUSY_WAIT_FLAGS] = 0;
162 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
163 virgl_block_write(vws->sock_fd, &busy_wait_buf, sizeof(busy_wait_buf));
164
165 ret = virgl_block_read(vws->sock_fd, vtest_hdr, sizeof(vtest_hdr));
166 assert(ret);
167
168 if (vtest_hdr[VTEST_CMD_ID] == VCMD_PING_PROTOCOL_VERSION) {
169 /* Read dummy busy_wait response */
170 ret = virgl_block_read(vws->sock_fd, vtest_hdr, sizeof(vtest_hdr));
171 assert(ret);
172 ret = virgl_block_read(vws->sock_fd, busy_wait_result, sizeof(busy_wait_result));
173 assert(ret);
174
175 vtest_hdr[VTEST_CMD_LEN] = VCMD_PROTOCOL_VERSION_SIZE;
176 vtest_hdr[VTEST_CMD_ID] = VCMD_PROTOCOL_VERSION;
177 version_buf[VCMD_PROTOCOL_VERSION_VERSION] = VTEST_PROTOCOL_VERSION;
178 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
179 virgl_block_write(vws->sock_fd, &version_buf, sizeof(version_buf));
180
181 ret = virgl_block_read(vws->sock_fd, vtest_hdr, sizeof(vtest_hdr));
182 assert(ret);
183 ret = virgl_block_read(vws->sock_fd, version_buf, sizeof(version_buf));
184 assert(ret);
185 return version_buf[VCMD_PROTOCOL_VERSION_VERSION];
186 }
187
188 /* Read dummy busy_wait response */
189 assert(vtest_hdr[VTEST_CMD_ID] == VCMD_RESOURCE_BUSY_WAIT);
190 ret = virgl_block_read(vws->sock_fd, busy_wait_result, sizeof(busy_wait_result));
191 assert(ret);
192
193 /* Old server, return version 0 */
194 return 0;
195 }
196
virgl_vtest_connect(struct virgl_vtest_winsys * vws)197 int virgl_vtest_connect(struct virgl_vtest_winsys *vws)
198 {
199 struct sockaddr_un un;
200 int sock, ret;
201 const char* socket_name = os_get_option("VTEST_SOCKET_NAME");
202
203 sock = socket(PF_UNIX, SOCK_STREAM, 0);
204 if (sock < 0)
205 return -1;
206
207 memset(&un, 0, sizeof(un));
208 un.sun_family = AF_UNIX;
209 snprintf(un.sun_path, sizeof(un.sun_path), "%s", socket_name ?
210 socket_name : VTEST_DEFAULT_SOCKET_NAME);
211
212 do {
213 ret = 0;
214 if (connect(sock, (struct sockaddr *)&un, sizeof(un)) < 0) {
215 ret = -errno;
216 }
217 } while (ret == -EINTR);
218
219 vws->sock_fd = sock;
220 virgl_vtest_send_init(vws);
221 vws->protocol_version = virgl_vtest_negotiate_version(vws);
222
223 /* Version 1 is deprecated. */
224 if (vws->protocol_version == 1)
225 vws->protocol_version = 0;
226
227 return 0;
228 }
229
virgl_vtest_send_get_caps(struct virgl_vtest_winsys * vws,struct virgl_drm_caps * caps)230 int virgl_vtest_send_get_caps(struct virgl_vtest_winsys *vws,
231 struct virgl_drm_caps *caps)
232 {
233 uint32_t get_caps_buf[VTEST_HDR_SIZE * 2];
234 uint32_t resp_buf[VTEST_HDR_SIZE];
235 uint32_t caps_size = sizeof(struct virgl_caps_v2);
236 int ret;
237 get_caps_buf[VTEST_CMD_LEN] = 0;
238 get_caps_buf[VTEST_CMD_ID] = VCMD_GET_CAPS2;
239 get_caps_buf[VTEST_CMD_LEN + 2] = 0;
240 get_caps_buf[VTEST_CMD_ID + 2] = VCMD_GET_CAPS;
241
242 virgl_block_write(vws->sock_fd, &get_caps_buf, sizeof(get_caps_buf));
243
244 ret = virgl_block_read(vws->sock_fd, resp_buf, sizeof(resp_buf));
245 if (ret <= 0)
246 return 0;
247
248 if (resp_buf[1] == 2) {
249 struct virgl_caps_v1 dummy;
250 uint32_t resp_size = resp_buf[0] - 1;
251 uint32_t dummy_size = 0;
252 if (resp_size > caps_size) {
253 dummy_size = resp_size - caps_size;
254 resp_size = caps_size;
255 }
256
257 ret = virgl_block_read(vws->sock_fd, &caps->caps, resp_size);
258
259 while (dummy_size) {
260 ret = virgl_block_read(vws->sock_fd, &dummy,
261 dummy_size < sizeof(dummy) ? dummy_size : sizeof(dummy));
262 if (ret <= 0)
263 break;
264 dummy_size -= ret;
265 }
266
267 /* now read back the pointless caps v1 we requested */
268 ret = virgl_block_read(vws->sock_fd, resp_buf, sizeof(resp_buf));
269 if (ret <= 0)
270 return 0;
271 ret = virgl_block_read(vws->sock_fd, &dummy, sizeof(struct virgl_caps_v1));
272 } else
273 ret = virgl_block_read(vws->sock_fd, &caps->caps, sizeof(struct virgl_caps_v1));
274
275 return 0;
276 }
277
virgl_vtest_send_resource_create2(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 size,int * out_fd)278 static int virgl_vtest_send_resource_create2(struct virgl_vtest_winsys *vws,
279 uint32_t handle,
280 enum pipe_texture_target target,
281 uint32_t format,
282 uint32_t bind,
283 uint32_t width,
284 uint32_t height,
285 uint32_t depth,
286 uint32_t array_size,
287 uint32_t last_level,
288 uint32_t nr_samples,
289 uint32_t size,
290 int *out_fd)
291 {
292 uint32_t res_create_buf[VCMD_RES_CREATE2_SIZE], vtest_hdr[VTEST_HDR_SIZE];
293
294 vtest_hdr[VTEST_CMD_LEN] = VCMD_RES_CREATE2_SIZE;
295 vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_CREATE2;
296
297 res_create_buf[VCMD_RES_CREATE2_RES_HANDLE] = handle;
298 res_create_buf[VCMD_RES_CREATE2_TARGET] = target;
299 res_create_buf[VCMD_RES_CREATE2_FORMAT] = format;
300 res_create_buf[VCMD_RES_CREATE2_BIND] = bind;
301 res_create_buf[VCMD_RES_CREATE2_WIDTH] = width;
302 res_create_buf[VCMD_RES_CREATE2_HEIGHT] = height;
303 res_create_buf[VCMD_RES_CREATE2_DEPTH] = depth;
304 res_create_buf[VCMD_RES_CREATE2_ARRAY_SIZE] = array_size;
305 res_create_buf[VCMD_RES_CREATE2_LAST_LEVEL] = last_level;
306 res_create_buf[VCMD_RES_CREATE2_NR_SAMPLES] = nr_samples;
307 res_create_buf[VCMD_RES_CREATE2_DATA_SIZE] = size;
308
309 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
310 virgl_block_write(vws->sock_fd, &res_create_buf, sizeof(res_create_buf));
311
312 /* Multi-sampled textures have no backing store attached. */
313 if (size == 0)
314 return 0;
315
316 *out_fd = virgl_vtest_receive_fd(vws->sock_fd);
317 if (*out_fd < 0) {
318 fprintf(stderr, "failed to get fd\n");
319 return -1;
320 }
321
322 return 0;
323 }
324
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 size,int * out_fd)325 int virgl_vtest_send_resource_create(struct virgl_vtest_winsys *vws,
326 uint32_t handle,
327 enum pipe_texture_target target,
328 uint32_t format,
329 uint32_t bind,
330 uint32_t width,
331 uint32_t height,
332 uint32_t depth,
333 uint32_t array_size,
334 uint32_t last_level,
335 uint32_t nr_samples,
336 uint32_t size,
337 int *out_fd)
338 {
339 uint32_t res_create_buf[VCMD_RES_CREATE_SIZE], vtest_hdr[VTEST_HDR_SIZE];
340
341 if (vws->protocol_version >= 2)
342 return virgl_vtest_send_resource_create2(vws, handle, target, format,
343 bind, width, height, depth,
344 array_size, last_level,
345 nr_samples, size, out_fd);
346
347 vtest_hdr[VTEST_CMD_LEN] = VCMD_RES_CREATE_SIZE;
348 vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_CREATE;
349
350 res_create_buf[VCMD_RES_CREATE_RES_HANDLE] = handle;
351 res_create_buf[VCMD_RES_CREATE_TARGET] = target;
352 res_create_buf[VCMD_RES_CREATE_FORMAT] = format;
353 res_create_buf[VCMD_RES_CREATE_BIND] = bind;
354 res_create_buf[VCMD_RES_CREATE_WIDTH] = width;
355 res_create_buf[VCMD_RES_CREATE_HEIGHT] = height;
356 res_create_buf[VCMD_RES_CREATE_DEPTH] = depth;
357 res_create_buf[VCMD_RES_CREATE_ARRAY_SIZE] = array_size;
358 res_create_buf[VCMD_RES_CREATE_LAST_LEVEL] = last_level;
359 res_create_buf[VCMD_RES_CREATE_NR_SAMPLES] = nr_samples;
360
361 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
362 virgl_block_write(vws->sock_fd, &res_create_buf, sizeof(res_create_buf));
363
364 return 0;
365 }
366
virgl_vtest_submit_cmd(struct virgl_vtest_winsys * vws,struct virgl_vtest_cmd_buf * cbuf)367 int virgl_vtest_submit_cmd(struct virgl_vtest_winsys *vws,
368 struct virgl_vtest_cmd_buf *cbuf)
369 {
370 uint32_t vtest_hdr[VTEST_HDR_SIZE];
371
372 vtest_hdr[VTEST_CMD_LEN] = cbuf->base.cdw;
373 vtest_hdr[VTEST_CMD_ID] = VCMD_SUBMIT_CMD;
374
375 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
376 virgl_block_write(vws->sock_fd, cbuf->buf, cbuf->base.cdw * 4);
377 return 0;
378 }
379
virgl_vtest_send_resource_unref(struct virgl_vtest_winsys * vws,uint32_t handle)380 int virgl_vtest_send_resource_unref(struct virgl_vtest_winsys *vws,
381 uint32_t handle)
382 {
383 uint32_t vtest_hdr[VTEST_HDR_SIZE];
384 uint32_t cmd[1];
385 vtest_hdr[VTEST_CMD_LEN] = 1;
386 vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_UNREF;
387
388 cmd[0] = handle;
389 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
390 virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
391 return 0;
392 }
393
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)394 static int virgl_vtest_send_transfer_cmd(struct virgl_vtest_winsys *vws,
395 uint32_t vcmd,
396 uint32_t handle,
397 uint32_t level, uint32_t stride,
398 uint32_t layer_stride,
399 const struct pipe_box *box,
400 uint32_t data_size)
401 {
402 uint32_t vtest_hdr[VTEST_HDR_SIZE];
403 uint32_t cmd[VCMD_TRANSFER_HDR_SIZE];
404 vtest_hdr[VTEST_CMD_LEN] = VCMD_TRANSFER_HDR_SIZE;
405 vtest_hdr[VTEST_CMD_ID] = vcmd;
406
407 /* The host expects the size in dwords so calculate the rounded up
408 * value here. */
409 if (vcmd == VCMD_TRANSFER_PUT)
410 vtest_hdr[VTEST_CMD_LEN] += (data_size + 3) / 4;
411
412 cmd[0] = handle;
413 cmd[1] = level;
414 cmd[2] = stride;
415 cmd[3] = layer_stride;
416 cmd[4] = box->x;
417 cmd[5] = box->y;
418 cmd[6] = box->z;
419 cmd[7] = box->width;
420 cmd[8] = box->height;
421 cmd[9] = box->depth;
422 cmd[10] = data_size;
423 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
424 virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
425
426 return 0;
427 }
428
virgl_vtest_send_transfer_cmd2(struct virgl_vtest_winsys * vws,uint32_t vcmd,uint32_t handle,uint32_t level,const struct pipe_box * box,uint32_t data_size,uint32_t offset)429 static int virgl_vtest_send_transfer_cmd2(struct virgl_vtest_winsys *vws,
430 uint32_t vcmd,
431 uint32_t handle,
432 uint32_t level,
433 const struct pipe_box *box,
434 uint32_t data_size,
435 uint32_t offset)
436 {
437 uint32_t vtest_hdr[VTEST_HDR_SIZE];
438 uint32_t cmd[VCMD_TRANSFER2_HDR_SIZE];
439 vtest_hdr[VTEST_CMD_LEN] = VCMD_TRANSFER2_HDR_SIZE;
440 vtest_hdr[VTEST_CMD_ID] = vcmd;
441
442 /* The host expects the size in dwords so calculate the rounded up
443 * value here. */
444 if (vcmd == VCMD_TRANSFER_PUT2)
445 vtest_hdr[VTEST_CMD_LEN] += (data_size + 3) / 4;
446
447 cmd[VCMD_TRANSFER2_RES_HANDLE] = handle;
448 cmd[VCMD_TRANSFER2_LEVEL] = level;
449 cmd[VCMD_TRANSFER2_X] = box->x;
450 cmd[VCMD_TRANSFER2_Y] = box->y;
451 cmd[VCMD_TRANSFER2_Z] = box->z;
452 cmd[VCMD_TRANSFER2_WIDTH] = box->width;
453 cmd[VCMD_TRANSFER2_HEIGHT] = box->height;
454 cmd[VCMD_TRANSFER2_DEPTH] = box->depth;
455 cmd[VCMD_TRANSFER2_DATA_SIZE] = data_size;
456 cmd[VCMD_TRANSFER2_OFFSET] = offset;
457 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
458 virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
459
460 return 0;
461 }
462
virgl_vtest_send_transfer_get(struct virgl_vtest_winsys * vws,uint32_t handle,uint32_t level,uint32_t stride,uint32_t layer_stride,const struct pipe_box * box,uint32_t data_size,uint32_t offset)463 int virgl_vtest_send_transfer_get(struct virgl_vtest_winsys *vws,
464 uint32_t handle,
465 uint32_t level, uint32_t stride,
466 uint32_t layer_stride,
467 const struct pipe_box *box,
468 uint32_t data_size,
469 uint32_t offset)
470 {
471 if (vws->protocol_version < 2)
472 return virgl_vtest_send_transfer_cmd(vws, VCMD_TRANSFER_GET, handle,
473 level, stride, layer_stride, box,
474 data_size);
475
476 return virgl_vtest_send_transfer_cmd2(vws, VCMD_TRANSFER_GET2, handle,
477 level, box, data_size, offset);
478 }
479
virgl_vtest_send_transfer_put(struct virgl_vtest_winsys * vws,uint32_t handle,uint32_t level,uint32_t stride,uint32_t layer_stride,const struct pipe_box * box,uint32_t data_size,uint32_t offset)480 int virgl_vtest_send_transfer_put(struct virgl_vtest_winsys *vws,
481 uint32_t handle,
482 uint32_t level, uint32_t stride,
483 uint32_t layer_stride,
484 const struct pipe_box *box,
485 uint32_t data_size,
486 uint32_t offset)
487 {
488 if (vws->protocol_version < 2)
489 return virgl_vtest_send_transfer_cmd(vws, VCMD_TRANSFER_PUT, handle,
490 level, stride, layer_stride, box,
491 data_size);
492
493 return virgl_vtest_send_transfer_cmd2(vws, VCMD_TRANSFER_PUT2, handle,
494 level, box, data_size, offset);
495 }
496
virgl_vtest_send_transfer_put_data(struct virgl_vtest_winsys * vws,void * data,uint32_t data_size)497 int virgl_vtest_send_transfer_put_data(struct virgl_vtest_winsys *vws,
498 void *data,
499 uint32_t data_size)
500 {
501 return virgl_block_write(vws->sock_fd, data, data_size);
502 }
503
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)504 int virgl_vtest_recv_transfer_get_data(struct virgl_vtest_winsys *vws,
505 void *data,
506 uint32_t data_size,
507 uint32_t stride,
508 const struct pipe_box *box,
509 uint32_t format)
510 {
511 void *line;
512 void *ptr = data;
513 int hblocks = util_format_get_nblocksy(format, box->height);
514
515 line = malloc(stride);
516 while (hblocks) {
517 virgl_block_read(vws->sock_fd, line, stride);
518 memcpy(ptr, line, util_format_get_stride(format, box->width));
519 ptr += stride;
520 hblocks--;
521 }
522 free(line);
523 return 0;
524 }
525
virgl_vtest_busy_wait(struct virgl_vtest_winsys * vws,int handle,int flags)526 int virgl_vtest_busy_wait(struct virgl_vtest_winsys *vws, int handle,
527 int flags)
528 {
529 uint32_t vtest_hdr[VTEST_HDR_SIZE];
530 uint32_t cmd[VCMD_BUSY_WAIT_SIZE];
531 uint32_t result[1];
532 ASSERTED int ret;
533 vtest_hdr[VTEST_CMD_LEN] = VCMD_BUSY_WAIT_SIZE;
534 vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_BUSY_WAIT;
535 cmd[VCMD_BUSY_WAIT_HANDLE] = handle;
536 cmd[VCMD_BUSY_WAIT_FLAGS] = flags;
537
538 virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
539 virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
540
541 ret = virgl_block_read(vws->sock_fd, vtest_hdr, sizeof(vtest_hdr));
542 assert(ret);
543 ret = virgl_block_read(vws->sock_fd, result, sizeof(result));
544 assert(ret);
545 return result[0];
546 }
547