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