xref: /aosp_15_r20/external/mesa3d/src/gallium/winsys/virgl/vtest/virgl_vtest_socket.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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