Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/winsys/virgl/vtest/virgl_vtest_socket.c
4566 views
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 */
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
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
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
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
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
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
const char *override_socket_name = getenv("VTEST_SOCKET_NAME");
208
snprintf(un.sun_path, sizeof(un.sun_path), "%s", override_socket_name ?
209
override_socket_name : VTEST_DEFAULT_SOCKET_NAME);
210
211
do {
212
ret = 0;
213
if (connect(sock, (struct sockaddr *)&un, sizeof(un)) < 0) {
214
ret = -errno;
215
}
216
} while (ret == -EINTR);
217
218
vws->sock_fd = sock;
219
virgl_vtest_send_init(vws);
220
vws->protocol_version = virgl_vtest_negotiate_version(vws);
221
222
/* Version 1 is deprecated. */
223
if (vws->protocol_version == 1)
224
vws->protocol_version = 0;
225
226
return 0;
227
}
228
229
int virgl_vtest_send_get_caps(struct virgl_vtest_winsys *vws,
230
struct virgl_drm_caps *caps)
231
{
232
uint32_t get_caps_buf[VTEST_HDR_SIZE * 2];
233
uint32_t resp_buf[VTEST_HDR_SIZE];
234
uint32_t caps_size = sizeof(struct virgl_caps_v2);
235
int ret;
236
get_caps_buf[VTEST_CMD_LEN] = 0;
237
get_caps_buf[VTEST_CMD_ID] = VCMD_GET_CAPS2;
238
get_caps_buf[VTEST_CMD_LEN + 2] = 0;
239
get_caps_buf[VTEST_CMD_ID + 2] = VCMD_GET_CAPS;
240
241
virgl_block_write(vws->sock_fd, &get_caps_buf, sizeof(get_caps_buf));
242
243
ret = virgl_block_read(vws->sock_fd, resp_buf, sizeof(resp_buf));
244
if (ret <= 0)
245
return 0;
246
247
if (resp_buf[1] == 2) {
248
struct virgl_caps_v1 dummy;
249
uint32_t resp_size = resp_buf[0] - 1;
250
uint32_t dummy_size = 0;
251
if (resp_size > caps_size) {
252
dummy_size = resp_size - caps_size;
253
resp_size = caps_size;
254
}
255
256
ret = virgl_block_read(vws->sock_fd, &caps->caps, resp_size);
257
258
if (dummy_size)
259
ret = virgl_block_read(vws->sock_fd, &dummy, dummy_size);
260
261
/* now read back the pointless caps v1 we requested */
262
ret = virgl_block_read(vws->sock_fd, resp_buf, sizeof(resp_buf));
263
if (ret <= 0)
264
return 0;
265
ret = virgl_block_read(vws->sock_fd, &dummy, sizeof(struct virgl_caps_v1));
266
} else
267
ret = virgl_block_read(vws->sock_fd, &caps->caps, sizeof(struct virgl_caps_v1));
268
269
return 0;
270
}
271
272
static int virgl_vtest_send_resource_create2(struct virgl_vtest_winsys *vws,
273
uint32_t handle,
274
enum pipe_texture_target target,
275
uint32_t format,
276
uint32_t bind,
277
uint32_t width,
278
uint32_t height,
279
uint32_t depth,
280
uint32_t array_size,
281
uint32_t last_level,
282
uint32_t nr_samples,
283
uint32_t size,
284
int *out_fd)
285
{
286
uint32_t res_create_buf[VCMD_RES_CREATE2_SIZE], vtest_hdr[VTEST_HDR_SIZE];
287
288
vtest_hdr[VTEST_CMD_LEN] = VCMD_RES_CREATE2_SIZE;
289
vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_CREATE2;
290
291
res_create_buf[VCMD_RES_CREATE2_RES_HANDLE] = handle;
292
res_create_buf[VCMD_RES_CREATE2_TARGET] = target;
293
res_create_buf[VCMD_RES_CREATE2_FORMAT] = format;
294
res_create_buf[VCMD_RES_CREATE2_BIND] = bind;
295
res_create_buf[VCMD_RES_CREATE2_WIDTH] = width;
296
res_create_buf[VCMD_RES_CREATE2_HEIGHT] = height;
297
res_create_buf[VCMD_RES_CREATE2_DEPTH] = depth;
298
res_create_buf[VCMD_RES_CREATE2_ARRAY_SIZE] = array_size;
299
res_create_buf[VCMD_RES_CREATE2_LAST_LEVEL] = last_level;
300
res_create_buf[VCMD_RES_CREATE2_NR_SAMPLES] = nr_samples;
301
res_create_buf[VCMD_RES_CREATE2_DATA_SIZE] = size;
302
303
virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
304
virgl_block_write(vws->sock_fd, &res_create_buf, sizeof(res_create_buf));
305
306
/* Multi-sampled textures have no backing store attached. */
307
if (size == 0)
308
return 0;
309
310
*out_fd = virgl_vtest_receive_fd(vws->sock_fd);
311
if (*out_fd < 0) {
312
fprintf(stderr, "failed to get fd\n");
313
return -1;
314
}
315
316
return 0;
317
}
318
319
int virgl_vtest_send_resource_create(struct virgl_vtest_winsys *vws,
320
uint32_t handle,
321
enum pipe_texture_target target,
322
uint32_t format,
323
uint32_t bind,
324
uint32_t width,
325
uint32_t height,
326
uint32_t depth,
327
uint32_t array_size,
328
uint32_t last_level,
329
uint32_t nr_samples,
330
uint32_t size,
331
int *out_fd)
332
{
333
uint32_t res_create_buf[VCMD_RES_CREATE_SIZE], vtest_hdr[VTEST_HDR_SIZE];
334
335
if (vws->protocol_version >= 2)
336
return virgl_vtest_send_resource_create2(vws, handle, target, format,
337
bind, width, height, depth,
338
array_size, last_level,
339
nr_samples, size, out_fd);
340
341
vtest_hdr[VTEST_CMD_LEN] = VCMD_RES_CREATE_SIZE;
342
vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_CREATE;
343
344
res_create_buf[VCMD_RES_CREATE_RES_HANDLE] = handle;
345
res_create_buf[VCMD_RES_CREATE_TARGET] = target;
346
res_create_buf[VCMD_RES_CREATE_FORMAT] = format;
347
res_create_buf[VCMD_RES_CREATE_BIND] = bind;
348
res_create_buf[VCMD_RES_CREATE_WIDTH] = width;
349
res_create_buf[VCMD_RES_CREATE_HEIGHT] = height;
350
res_create_buf[VCMD_RES_CREATE_DEPTH] = depth;
351
res_create_buf[VCMD_RES_CREATE_ARRAY_SIZE] = array_size;
352
res_create_buf[VCMD_RES_CREATE_LAST_LEVEL] = last_level;
353
res_create_buf[VCMD_RES_CREATE_NR_SAMPLES] = nr_samples;
354
355
virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
356
virgl_block_write(vws->sock_fd, &res_create_buf, sizeof(res_create_buf));
357
358
return 0;
359
}
360
361
int virgl_vtest_submit_cmd(struct virgl_vtest_winsys *vws,
362
struct virgl_vtest_cmd_buf *cbuf)
363
{
364
uint32_t vtest_hdr[VTEST_HDR_SIZE];
365
366
vtest_hdr[VTEST_CMD_LEN] = cbuf->base.cdw;
367
vtest_hdr[VTEST_CMD_ID] = VCMD_SUBMIT_CMD;
368
369
virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
370
virgl_block_write(vws->sock_fd, cbuf->buf, cbuf->base.cdw * 4);
371
return 0;
372
}
373
374
int virgl_vtest_send_resource_unref(struct virgl_vtest_winsys *vws,
375
uint32_t handle)
376
{
377
uint32_t vtest_hdr[VTEST_HDR_SIZE];
378
uint32_t cmd[1];
379
vtest_hdr[VTEST_CMD_LEN] = 1;
380
vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_UNREF;
381
382
cmd[0] = handle;
383
virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
384
virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
385
return 0;
386
}
387
388
static int virgl_vtest_send_transfer_cmd(struct virgl_vtest_winsys *vws,
389
uint32_t vcmd,
390
uint32_t handle,
391
uint32_t level, uint32_t stride,
392
uint32_t layer_stride,
393
const struct pipe_box *box,
394
uint32_t data_size)
395
{
396
uint32_t vtest_hdr[VTEST_HDR_SIZE];
397
uint32_t cmd[VCMD_TRANSFER_HDR_SIZE];
398
vtest_hdr[VTEST_CMD_LEN] = VCMD_TRANSFER_HDR_SIZE;
399
vtest_hdr[VTEST_CMD_ID] = vcmd;
400
401
/* The host expects the size in dwords so calculate the rounded up
402
* value here. */
403
if (vcmd == VCMD_TRANSFER_PUT)
404
vtest_hdr[VTEST_CMD_LEN] += (data_size + 3) / 4;
405
406
cmd[0] = handle;
407
cmd[1] = level;
408
cmd[2] = stride;
409
cmd[3] = layer_stride;
410
cmd[4] = box->x;
411
cmd[5] = box->y;
412
cmd[6] = box->z;
413
cmd[7] = box->width;
414
cmd[8] = box->height;
415
cmd[9] = box->depth;
416
cmd[10] = data_size;
417
virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
418
virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
419
420
return 0;
421
}
422
423
static int virgl_vtest_send_transfer_cmd2(struct virgl_vtest_winsys *vws,
424
uint32_t vcmd,
425
uint32_t handle,
426
uint32_t level,
427
const struct pipe_box *box,
428
uint32_t data_size,
429
uint32_t offset)
430
{
431
uint32_t vtest_hdr[VTEST_HDR_SIZE];
432
uint32_t cmd[VCMD_TRANSFER2_HDR_SIZE];
433
vtest_hdr[VTEST_CMD_LEN] = VCMD_TRANSFER2_HDR_SIZE;
434
vtest_hdr[VTEST_CMD_ID] = vcmd;
435
436
/* The host expects the size in dwords so calculate the rounded up
437
* value here. */
438
if (vcmd == VCMD_TRANSFER_PUT2)
439
vtest_hdr[VTEST_CMD_LEN] += (data_size + 3) / 4;
440
441
cmd[VCMD_TRANSFER2_RES_HANDLE] = handle;
442
cmd[VCMD_TRANSFER2_LEVEL] = level;
443
cmd[VCMD_TRANSFER2_X] = box->x;
444
cmd[VCMD_TRANSFER2_Y] = box->y;
445
cmd[VCMD_TRANSFER2_Z] = box->z;
446
cmd[VCMD_TRANSFER2_WIDTH] = box->width;
447
cmd[VCMD_TRANSFER2_HEIGHT] = box->height;
448
cmd[VCMD_TRANSFER2_DEPTH] = box->depth;
449
cmd[VCMD_TRANSFER2_DATA_SIZE] = data_size;
450
cmd[VCMD_TRANSFER2_OFFSET] = offset;
451
virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
452
virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
453
454
return 0;
455
}
456
457
int virgl_vtest_send_transfer_get(struct virgl_vtest_winsys *vws,
458
uint32_t handle,
459
uint32_t level, uint32_t stride,
460
uint32_t layer_stride,
461
const struct pipe_box *box,
462
uint32_t data_size,
463
uint32_t offset)
464
{
465
if (vws->protocol_version < 2)
466
return virgl_vtest_send_transfer_cmd(vws, VCMD_TRANSFER_GET, handle,
467
level, stride, layer_stride, box,
468
data_size);
469
470
return virgl_vtest_send_transfer_cmd2(vws, VCMD_TRANSFER_GET2, handle,
471
level, box, data_size, offset);
472
}
473
474
int virgl_vtest_send_transfer_put(struct virgl_vtest_winsys *vws,
475
uint32_t handle,
476
uint32_t level, uint32_t stride,
477
uint32_t layer_stride,
478
const struct pipe_box *box,
479
uint32_t data_size,
480
uint32_t offset)
481
{
482
if (vws->protocol_version < 2)
483
return virgl_vtest_send_transfer_cmd(vws, VCMD_TRANSFER_PUT, handle,
484
level, stride, layer_stride, box,
485
data_size);
486
487
return virgl_vtest_send_transfer_cmd2(vws, VCMD_TRANSFER_PUT2, handle,
488
level, box, data_size, offset);
489
}
490
491
int virgl_vtest_send_transfer_put_data(struct virgl_vtest_winsys *vws,
492
void *data,
493
uint32_t data_size)
494
{
495
return virgl_block_write(vws->sock_fd, data, data_size);
496
}
497
498
int virgl_vtest_recv_transfer_get_data(struct virgl_vtest_winsys *vws,
499
void *data,
500
uint32_t data_size,
501
uint32_t stride,
502
const struct pipe_box *box,
503
uint32_t format)
504
{
505
void *line;
506
void *ptr = data;
507
int hblocks = util_format_get_nblocksy(format, box->height);
508
509
line = malloc(stride);
510
while (hblocks) {
511
virgl_block_read(vws->sock_fd, line, stride);
512
memcpy(ptr, line, util_format_get_stride(format, box->width));
513
ptr += stride;
514
hblocks--;
515
}
516
free(line);
517
return 0;
518
}
519
520
int virgl_vtest_busy_wait(struct virgl_vtest_winsys *vws, int handle,
521
int flags)
522
{
523
uint32_t vtest_hdr[VTEST_HDR_SIZE];
524
uint32_t cmd[VCMD_BUSY_WAIT_SIZE];
525
uint32_t result[1];
526
ASSERTED int ret;
527
vtest_hdr[VTEST_CMD_LEN] = VCMD_BUSY_WAIT_SIZE;
528
vtest_hdr[VTEST_CMD_ID] = VCMD_RESOURCE_BUSY_WAIT;
529
cmd[VCMD_BUSY_WAIT_HANDLE] = handle;
530
cmd[VCMD_BUSY_WAIT_FLAGS] = flags;
531
532
virgl_block_write(vws->sock_fd, &vtest_hdr, sizeof(vtest_hdr));
533
virgl_block_write(vws->sock_fd, &cmd, sizeof(cmd));
534
535
ret = virgl_block_read(vws->sock_fd, vtest_hdr, sizeof(vtest_hdr));
536
assert(ret);
537
ret = virgl_block_read(vws->sock_fd, result, sizeof(result));
538
assert(ret);
539
return result[0];
540
}
541
542