1 /**************************************************************************
2 *
3 * Copyright (C) 2014 Red Hat Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 **************************************************************************/
24
25 /* transfer and iov related tests */
26 #include <check.h>
27 #include <stdlib.h>
28 #include <sys/uio.h>
29 #include <errno.h>
30 #include <virglrenderer.h>
31 #include "pipe/p_defines.h"
32 #include "virgl_hw.h"
33 #include "virgl_protocol.h"
34 #include "testvirgl_encode.h"
35
36 /* pass an illegal context to transfer fn */
START_TEST(virgl_test_transfer_read_illegal_ctx)37 START_TEST(virgl_test_transfer_read_illegal_ctx)
38 {
39 int ret;
40 struct virgl_box box;
41
42 ret = virgl_renderer_transfer_read_iov(1, 2, 0, 1, 1, &box, 0, NULL, 0);
43 ck_assert_int_eq(ret, EINVAL);
44 }
45 END_TEST
46
START_TEST(virgl_test_transfer_write_illegal_ctx)47 START_TEST(virgl_test_transfer_write_illegal_ctx)
48 {
49 int ret;
50 struct virgl_box box;
51
52 ret = virgl_renderer_transfer_write_iov(1, 2, 0, 1, 1, &box, 0, NULL, 0);
53 ck_assert_int_eq(ret, EINVAL);
54 }
55 END_TEST
56
57 /* pass a resource not bound to the context to transfers */
START_TEST(virgl_test_transfer_read_unbound_res)58 START_TEST(virgl_test_transfer_read_unbound_res)
59 {
60 int ret;
61 struct virgl_box box;
62
63 ret = virgl_renderer_transfer_read_iov(1, 1, 0, 1, 1, &box, 0, NULL, 0);
64 ck_assert_int_eq(ret, EINVAL);
65 }
66 END_TEST
67
START_TEST(virgl_test_transfer_write_unbound_res)68 START_TEST(virgl_test_transfer_write_unbound_res)
69 {
70 int ret;
71 struct virgl_box box;
72
73 ret = virgl_renderer_transfer_write_iov(1, 1, 0, 1, 1, &box, 0, NULL, 0);
74 ck_assert_int_eq(ret, EINVAL);
75 }
76 END_TEST
77
78 /* don't pass an IOV to read into */
START_TEST(virgl_test_transfer_read_no_iov)79 START_TEST(virgl_test_transfer_read_no_iov)
80 {
81 struct virgl_box box;
82 struct virgl_renderer_resource_create_args res;
83 int ret;
84
85 testvirgl_init_simple_1d_resource(&res, 1);
86
87 ret = virgl_renderer_resource_create(&res, NULL, 0);
88 ck_assert_int_eq(ret, 0);
89
90 virgl_renderer_ctx_attach_resource(1, res.handle);
91
92 ret = virgl_renderer_transfer_read_iov(1, 1, 0, 1, 1, &box, 0, NULL, 0);
93 ck_assert_int_eq(ret, EINVAL);
94 virgl_renderer_ctx_detach_resource(1, res.handle);
95
96 virgl_renderer_resource_unref(1);
97 }
98 END_TEST
99
START_TEST(virgl_test_transfer_write_no_iov)100 START_TEST(virgl_test_transfer_write_no_iov)
101 {
102 struct virgl_box box;
103 struct virgl_renderer_resource_create_args res;
104 int ret;
105
106 testvirgl_init_simple_1d_resource(&res, 1);
107
108 ret = virgl_renderer_resource_create(&res, NULL, 0);
109 ck_assert_int_eq(ret, 0);
110
111 virgl_renderer_ctx_attach_resource(1, res.handle);
112
113 ret = virgl_renderer_transfer_write_iov(1, 1, 0, 1, 1, &box, 0, NULL, 0);
114 ck_assert_int_eq(ret, EINVAL);
115 virgl_renderer_ctx_detach_resource(1, res.handle);
116
117 virgl_renderer_resource_unref(1);
118 }
119 END_TEST
120
START_TEST(virgl_test_transfer_read_no_box)121 START_TEST(virgl_test_transfer_read_no_box)
122 {
123 struct virgl_renderer_resource_create_args res;
124 struct iovec iovs[1];
125 int niovs = 1;
126 int ret;
127
128 testvirgl_init_simple_1d_resource(&res, 1);
129
130 ret = virgl_renderer_resource_create(&res, NULL, 0);
131 ck_assert_int_eq(ret, 0);
132
133 virgl_renderer_ctx_attach_resource(1, res.handle);
134
135 ret = virgl_renderer_transfer_read_iov(1, 1, 0, 1, 1, NULL, 0, iovs, niovs);
136 ck_assert_int_eq(ret, EINVAL);
137 virgl_renderer_ctx_detach_resource(1, res.handle);
138
139 virgl_renderer_resource_unref(1);
140 }
141 END_TEST
142
START_TEST(virgl_test_transfer_write_no_box)143 START_TEST(virgl_test_transfer_write_no_box)
144 {
145 struct virgl_renderer_resource_create_args res;
146 struct iovec iovs[1];
147 int niovs = 1;
148 int ret;
149
150 testvirgl_init_simple_1d_resource(&res, 1);
151
152 ret = virgl_renderer_resource_create(&res, NULL, 0);
153 ck_assert_int_eq(ret, 0);
154
155 virgl_renderer_ctx_attach_resource(1, res.handle);
156
157 ret = virgl_renderer_transfer_write_iov(1, 1, 0, 1, 1, NULL, 0, iovs, niovs);
158 ck_assert_int_eq(ret, EINVAL);
159 virgl_renderer_ctx_detach_resource(1, res.handle);
160
161 virgl_renderer_resource_unref(1);
162 }
163 END_TEST
164
165
166 /* pass a bad box argument */
START_TEST(virgl_test_transfer_read_1d_bad_box)167 START_TEST(virgl_test_transfer_read_1d_bad_box)
168 {
169 struct virgl_renderer_resource_create_args res;
170 struct iovec iovs[1];
171 int niovs = 1;
172 int ret;
173 struct virgl_box box;
174
175 testvirgl_init_simple_1d_resource(&res, 1);
176
177 ret = virgl_renderer_resource_create(&res, NULL, 0);
178 ck_assert_int_eq(ret, 0);
179
180 virgl_renderer_ctx_attach_resource(1, res.handle);
181
182 box.x = box.y = box.z = 0;
183 box.w = 10;
184 box.h = 2;
185 box.d = 1;
186
187 ret = virgl_renderer_transfer_read_iov(1, 1, 0, 1, 1, &box, 0, iovs, niovs);
188 ck_assert_int_eq(ret, EINVAL);
189 virgl_renderer_ctx_detach_resource(1, res.handle);
190
191 virgl_renderer_resource_unref(1);
192 }
193 END_TEST
194
START_TEST(virgl_test_transfer_write_1d_bad_box)195 START_TEST(virgl_test_transfer_write_1d_bad_box)
196 {
197 struct virgl_renderer_resource_create_args res;
198 struct iovec iovs[1];
199 int niovs = 1;
200 int ret;
201 struct virgl_box box;
202
203 testvirgl_init_simple_1d_resource(&res, 1);
204
205 ret = virgl_renderer_resource_create(&res, NULL, 0);
206 ck_assert_int_eq(ret, 0);
207
208 virgl_renderer_ctx_attach_resource(1, res.handle);
209
210 box.x = box.y = box.z = 0;
211 box.w = 10;
212 box.h = 2;
213 box.d = 1;
214
215 ret = virgl_renderer_transfer_write_iov(1, 1, 0, 1, 1, &box, 0, iovs, niovs);
216 ck_assert_int_eq(ret, EINVAL);
217 virgl_renderer_ctx_detach_resource(1, res.handle);
218
219 virgl_renderer_resource_unref(1);
220 }
221 END_TEST
222
START_TEST(virgl_test_transfer_read_1d_array_bad_box)223 START_TEST(virgl_test_transfer_read_1d_array_bad_box)
224 {
225 struct virgl_renderer_resource_create_args res;
226 struct iovec iovs[1];
227 int niovs = 1;
228 int ret;
229 struct virgl_box box;
230
231 testvirgl_init_simple_1d_resource(&res, 1);
232 res.target = PIPE_TEXTURE_1D_ARRAY;
233 res.array_size = 5;
234
235 ret = virgl_renderer_resource_create(&res, NULL, 0);
236 ck_assert_int_eq(ret, 0);
237
238 virgl_renderer_ctx_attach_resource(1, res.handle);
239
240 box.x = box.y = box.z = 0;
241 box.w = 10;
242 box.h = 2;
243 box.d = 6;
244
245 ret = virgl_renderer_transfer_read_iov(1, 1, 0, 1, 1, &box, 0, iovs, niovs);
246 ck_assert_int_eq(ret, EINVAL);
247 virgl_renderer_ctx_detach_resource(1, res.handle);
248
249 virgl_renderer_resource_unref(1);
250 }
251 END_TEST
252
START_TEST(virgl_test_transfer_read_3d_bad_box)253 START_TEST(virgl_test_transfer_read_3d_bad_box)
254 {
255 struct virgl_renderer_resource_create_args res;
256 struct iovec iovs[1];
257 int niovs = 1;
258 int ret;
259 struct virgl_box box;
260
261 testvirgl_init_simple_1d_resource(&res, 1);
262 res.target = PIPE_TEXTURE_3D;
263 res.depth = 5;
264
265 ret = virgl_renderer_resource_create(&res, NULL, 0);
266 ck_assert_int_eq(ret, 0);
267
268 virgl_renderer_ctx_attach_resource(1, res.handle);
269
270 box.x = box.y = box.z = 0;
271 box.w = 10;
272 box.h = 2;
273 box.d = 6;
274
275 ret = virgl_renderer_transfer_read_iov(1, 1, 0, 1, 1, &box, 0, iovs, niovs);
276 ck_assert_int_eq(ret, EINVAL);
277 virgl_renderer_ctx_detach_resource(1, res.handle);
278
279 virgl_renderer_resource_unref(1);
280 }
281 END_TEST
282
START_TEST(virgl_test_transfer_1d)283 START_TEST(virgl_test_transfer_1d)
284 {
285 struct virgl_resource res;
286 unsigned char data[50*4];
287 struct iovec iov = { .iov_base = data, .iov_len = sizeof(data) };
288 int niovs = 1;
289 int ret;
290 unsigned i;
291 struct virgl_box box;
292
293 /* init and create simple 2D resource */
294 ret = testvirgl_create_backed_simple_1d_res(&res, 1);
295 ck_assert_int_eq(ret, 0);
296
297 /* attach resource to context */
298 virgl_renderer_ctx_attach_resource(1, res.handle);
299
300 box.x = box.y = box.z = 0;
301 box.w = 50;
302 box.h = 1;
303 box.d = 1;
304 for (i = 0; i < sizeof(data); i++)
305 data[i] = i;
306
307 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 0, 0, 0, &box, 0, &iov, niovs);
308 ck_assert_int_eq(ret, 0);
309
310 ret = virgl_renderer_transfer_read_iov(res.handle, 1, 0, 0, 0, &box, 0, NULL, 0);
311 ck_assert_int_eq(ret, 0);
312
313 /* check the returned values */
314 unsigned char *ptr = res.iovs[0].iov_base;
315 for (i = 0; i < sizeof(data); i++) {
316 ck_assert_int_eq(ptr[i], i);
317 }
318
319 virgl_renderer_ctx_detach_resource(1, res.handle);
320 testvirgl_destroy_backed_res(&res);
321 }
322 END_TEST
323
START_TEST(virgl_test_transfer_1d_bad_iov)324 START_TEST(virgl_test_transfer_1d_bad_iov)
325 {
326 struct virgl_renderer_resource_create_args res;
327 struct iovec iovs[1] = { { NULL, 23 } };
328 int niovs = 1;
329 int ret;
330 struct virgl_box box = { .w = 50, .h = 1, .d = 1 };
331
332 testvirgl_init_simple_1d_resource(&res, 1);
333 res.target = PIPE_TEXTURE_1D;
334 res.depth = 1;
335
336 ret = virgl_renderer_resource_create(&res, NULL, 0);
337 ck_assert_int_eq(ret, 0);
338
339 virgl_renderer_ctx_attach_resource(1, res.handle);
340
341 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 0, 0, 0, &box, 0, iovs, niovs);
342 ck_assert_int_eq(ret, EINVAL);
343
344 virgl_renderer_ctx_detach_resource(1, res.handle);
345
346 virgl_renderer_resource_unref(1);
347 }
348 END_TEST
349
START_TEST(virgl_test_transfer_1d_bad_iov_offset)350 START_TEST(virgl_test_transfer_1d_bad_iov_offset)
351 {
352 struct virgl_renderer_resource_create_args res;
353 unsigned char data[50*4];
354 struct iovec iov = { .iov_base = data, .iov_len = sizeof(data) };
355 int niovs = 1;
356 int ret;
357 struct virgl_box box = { .w = 50, .h = 1, .d = 1 };
358
359 testvirgl_init_simple_1d_resource(&res, 1);
360 res.target = PIPE_TEXTURE_1D;
361 res.depth = 1;
362
363 ret = virgl_renderer_resource_create(&res, NULL, 0);
364 ck_assert_int_eq(ret, 0);
365
366 virgl_renderer_ctx_attach_resource(1, res.handle);
367
368 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 0, 0, 0, &box, 20, &iov, niovs);
369 ck_assert_int_eq(ret, EINVAL);
370
371 virgl_renderer_ctx_detach_resource(1, res.handle);
372
373 virgl_renderer_resource_unref(1);
374 }
375 END_TEST
376
START_TEST(virgl_test_transfer_1d_bad_strides)377 START_TEST(virgl_test_transfer_1d_bad_strides)
378 {
379 struct virgl_renderer_resource_create_args res;
380 unsigned char data[50*4];
381 struct iovec iov = { .iov_base = data, .iov_len = sizeof(data) };
382 int niovs = 1;
383 int ret;
384 struct virgl_box box = { .w = 50, .h = 1, .d = 1 };
385 int bad_stride = box.w - 1;
386
387 testvirgl_init_simple_1d_resource(&res, 1);
388 res.target = PIPE_TEXTURE_1D;
389 res.depth = 1;
390
391 ret = virgl_renderer_resource_create(&res, NULL, 0);
392 ck_assert_int_eq(ret, 0);
393
394 virgl_renderer_ctx_attach_resource(1, res.handle);
395
396 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 0, bad_stride, 0,
397 &box, 0, &iov, niovs);
398 ck_assert_int_eq(ret, EINVAL);
399 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 0, 0, bad_stride,
400 &box, 0, &iov, niovs);
401 ck_assert_int_eq(ret, EINVAL);
402
403 virgl_renderer_ctx_detach_resource(1, res.handle);
404
405 virgl_renderer_resource_unref(1);
406 }
407 END_TEST
408
START_TEST(virgl_test_transfer_2d_bad_strides)409 START_TEST(virgl_test_transfer_2d_bad_strides)
410 {
411 struct virgl_renderer_resource_create_args res;
412 unsigned char data[50*4];
413 struct iovec iov = { .iov_base = data, .iov_len = sizeof(data) };
414 int niovs = 1;
415 int ret;
416 struct virgl_box box = { .w = 50, .h = 1, .d = 1 };
417 int bad_stride = box.w - 1;
418
419 testvirgl_init_simple_2d_resource(&res, 1);
420
421 ret = virgl_renderer_resource_create(&res, NULL, 0);
422 ck_assert_int_eq(ret, 0);
423
424 virgl_renderer_ctx_attach_resource(1, res.handle);
425
426 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 0, bad_stride, 0,
427 &box, 0, &iov, niovs);
428 ck_assert_int_eq(ret, EINVAL);
429 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 0, 0, bad_stride,
430 &box, 0, &iov, niovs);
431 ck_assert_int_eq(ret, EINVAL);
432
433 virgl_renderer_ctx_detach_resource(1, res.handle);
434
435 virgl_renderer_resource_unref(1);
436 }
437 END_TEST
438
START_TEST(virgl_test_transfer_buffer_bad_strides)439 START_TEST(virgl_test_transfer_buffer_bad_strides)
440 {
441 struct virgl_renderer_resource_create_args res;
442 unsigned char data[50*4];
443 struct iovec iov = { .iov_base = data, .iov_len = sizeof(data) };
444 int niovs = 1;
445 int ret;
446 struct virgl_box box = { .w = 50, .h = 1, .d = 1 };
447 int bad_stride = box.w - 1;
448
449 testvirgl_init_simple_buffer(&res, 1);
450
451 ret = virgl_renderer_resource_create(&res, NULL, 0);
452 ck_assert_int_eq(ret, 0);
453
454 virgl_renderer_ctx_attach_resource(1, res.handle);
455
456 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 0, bad_stride, 0,
457 &box, 0, &iov, niovs);
458 ck_assert_int_eq(ret, EINVAL);
459 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 0, 0, bad_stride,
460 &box, 0, &iov, niovs);
461 ck_assert_int_eq(ret, EINVAL);
462
463 virgl_renderer_ctx_detach_resource(1, res.handle);
464
465 virgl_renderer_resource_unref(1);
466 }
467 END_TEST
468
START_TEST(virgl_test_transfer_2d_array_bad_layer_stride)469 START_TEST(virgl_test_transfer_2d_array_bad_layer_stride)
470 {
471 struct virgl_renderer_resource_create_args res;
472 unsigned char *data;
473 struct iovec iov;
474 int niovs = 1;
475 int ret;
476 struct virgl_box box = { .w = 50, .h = 5, .d = 2 };
477 int size = 50*50*2*4;
478 data = calloc(1, size);
479 iov.iov_base = data;
480 iov.iov_len = size;
481 testvirgl_init_simple_2d_resource(&res, 1);
482 res.target = PIPE_TEXTURE_2D_ARRAY;
483 res.array_size = 5;
484
485 ret = virgl_renderer_resource_create(&res, NULL, 0);
486 ck_assert_int_eq(ret, 0);
487
488 virgl_renderer_ctx_attach_resource(1, res.handle);
489
490 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 0, 0, 100, &box, 0, &iov, niovs);
491 ck_assert_int_eq(ret, EINVAL);
492
493 virgl_renderer_ctx_detach_resource(1, res.handle);
494
495 virgl_renderer_resource_unref(1);
496 free(data);
497 }
498 END_TEST
499
START_TEST(virgl_test_transfer_2d_bad_level)500 START_TEST(virgl_test_transfer_2d_bad_level)
501 {
502 struct virgl_renderer_resource_create_args res;
503 unsigned char data[50*4];
504 struct iovec iov = { .iov_base = data, .iov_len = sizeof(data) };
505 int niovs = 1;
506 int ret;
507 struct virgl_box box = { .w = 50, .h = 1, .d = 1 };
508
509 testvirgl_init_simple_2d_resource(&res, 1);
510 res.last_level = 1;
511 ret = virgl_renderer_resource_create(&res, NULL, 0);
512 ck_assert_int_eq(ret, 0);
513
514 virgl_renderer_ctx_attach_resource(1, res.handle);
515
516 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 2, 0, 0, &box, 0, &iov, niovs);
517 ck_assert_int_eq(ret, EINVAL);
518
519 virgl_renderer_ctx_detach_resource(1, res.handle);
520
521 virgl_renderer_resource_unref(1);
522 }
523 END_TEST
524
525 /* for each texture type construct a valid and invalid transfer,
526 invalid using a box outside the bounds of the transfer */
527 #define LARGE_FLAG_WIDTH (1 << 0)
528 #define LARGE_FLAG_HEIGHT (1 << 1)
529 #define LARGE_FLAG_DEPTH (1 << 2)
get_resource_args(enum pipe_texture_target target,bool invalid,struct virgl_renderer_resource_create_args * args,struct pipe_box * box,int nsamples,int large_flags)530 static void get_resource_args(enum pipe_texture_target target, bool invalid,
531 struct virgl_renderer_resource_create_args *args,
532 struct pipe_box *box, int nsamples, int large_flags)
533 {
534 memset(args, 0, sizeof(*args));
535 memset(box, 0, sizeof(*box));
536
537 args->handle = 1;
538 args->target = target;
539 if (args->target == PIPE_BUFFER) {
540 args->format = PIPE_FORMAT_R8_UNORM;
541 args->bind = PIPE_BIND_VERTEX_BUFFER;
542 } else {
543 args->bind = PIPE_BIND_SAMPLER_VIEW;
544 args->format = PIPE_FORMAT_B8G8R8X8_UNORM;
545 }
546 args->nr_samples = nsamples;
547 args->flags = 0;
548
549 if (large_flags & LARGE_FLAG_WIDTH)
550 if (args->target == PIPE_BUFFER)
551 args->width = 65536*2;
552 else if (args->target == PIPE_TEXTURE_3D)
553 args->width = 1024;
554 else
555 args->width = 4096;
556 else
557 args->width = 50;
558 args->height = args->depth = args->array_size = 1;
559
560 switch (target) {
561 case PIPE_TEXTURE_CUBE_ARRAY:
562 args->array_size = 12;
563 args->height = args->width;
564 break;
565 case PIPE_TEXTURE_1D_ARRAY:
566 case PIPE_TEXTURE_2D_ARRAY:
567 args->array_size = 10;
568 break;
569 case PIPE_TEXTURE_3D:
570 args->depth = 8;
571 break;
572 case PIPE_TEXTURE_CUBE:
573 args->array_size = 6;
574 args->height = args->width;
575 break;
576 default:
577 break;
578 }
579
580 switch (target) {
581 case PIPE_BUFFER:
582 case PIPE_TEXTURE_1D:
583 case PIPE_TEXTURE_1D_ARRAY:
584 case PIPE_TEXTURE_CUBE:
585 case PIPE_TEXTURE_CUBE_ARRAY:
586 break;
587 default:
588 if (large_flags & LARGE_FLAG_HEIGHT) {
589 if (args->target == PIPE_BUFFER)
590 args->height = 64000;
591 else if (args->target == PIPE_TEXTURE_3D)
592 args->height = 1024;
593 else
594 args->height = 4096;
595 } else
596 args->height = 50;
597 break;
598 }
599
600 if (invalid) {
601 box->width = args->width + 10;
602 box->height = args->height;
603 box->depth = 1;
604 } else {
605 box->width = args->width;
606 box->height = args->height;
607 box->depth = 1;
608 if (args->depth > 1)
609 box->depth = 6;
610 if (args->array_size > 1)
611 box->depth = 4;
612 }
613 }
614
get_box_size(struct pipe_box * box,int elsize)615 static unsigned get_box_size(struct pipe_box *box, int elsize)
616 {
617 return elsize * box->width * box->height * box->depth;
618 }
619
virgl_test_transfer_res(enum pipe_texture_target target,bool write,bool invalid)620 static void virgl_test_transfer_res(enum pipe_texture_target target,
621 bool write, bool invalid)
622 {
623 struct virgl_renderer_resource_create_args res;
624 struct pipe_box box;
625 void *data;
626 struct iovec iovs[1];
627 int niovs = 1;
628 int ret;
629 int size;
630
631 get_resource_args(target, invalid, &res, &box, 0, 0);
632
633 size = get_box_size(&box, target == PIPE_BUFFER ? 1 : 4);
634 data = calloc(1, size);
635 iovs[0].iov_base = data;
636 iovs[0].iov_len = size;
637
638 ret = virgl_renderer_resource_create(&res, NULL, 0);
639 ck_assert_int_eq(ret, 0);
640
641 virgl_renderer_ctx_attach_resource(1, res.handle);
642
643 if (write)
644 ret = virgl_renderer_transfer_write_iov(res.handle, 1, 0, 0, 0,
645 (struct virgl_box *)&box, 0, iovs, niovs);
646 else
647 ret = virgl_renderer_transfer_read_iov(res.handle, 1, 0, 0, 0,
648 (struct virgl_box *)&box, 0, iovs, niovs);
649 ck_assert_int_eq(ret, invalid ? EINVAL : 0);
650 virgl_renderer_ctx_detach_resource(1, res.handle);
651
652 virgl_renderer_resource_unref(res.handle);
653 free(data);
654 }
655
START_TEST(virgl_test_transfer_res_read_valid)656 START_TEST(virgl_test_transfer_res_read_valid)
657 {
658 virgl_test_transfer_res(_i, false, false);
659 }
660 END_TEST
661
START_TEST(virgl_test_transfer_res_write_valid)662 START_TEST(virgl_test_transfer_res_write_valid)
663 {
664 virgl_test_transfer_res(_i, true, false);
665 }
666 END_TEST
667
START_TEST(virgl_test_transfer_res_read_invalid)668 START_TEST(virgl_test_transfer_res_read_invalid)
669 {
670 virgl_test_transfer_res(_i, false, true);
671 }
672 END_TEST
673
START_TEST(virgl_test_transfer_res_write_invalid)674 START_TEST(virgl_test_transfer_res_write_invalid)
675 {
676 virgl_test_transfer_res(_i, true, true);
677 }
678 END_TEST
679
virgl_test_transfer_inline(enum pipe_texture_target target,bool invalid,int large_flags)680 static void virgl_test_transfer_inline(enum pipe_texture_target target,
681 bool invalid, int large_flags)
682 {
683 struct virgl_renderer_resource_create_args args;
684 struct pipe_box box;
685 struct virgl_context ctx;
686 struct virgl_resource res;
687 int ret;
688 int elsize = target == 0 ? 1 : 4;
689 void *data;
690 unsigned size;
691 ret = testvirgl_init_ctx_cmdbuf(&ctx);
692 ck_assert_int_eq(ret, 0);
693
694 get_resource_args(target, invalid, &args, &box, 0, large_flags);
695
696 size = get_box_size(&box, elsize);
697 data = calloc(1, size);
698 ret = virgl_renderer_resource_create(&args, NULL, 0);
699 ck_assert_int_eq(ret, 0);
700
701 res.handle = args.handle;
702 res.base.target = args.target;
703 res.base.format = args.format;
704
705 virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
706 virgl_encoder_inline_write(&ctx, &res, 0, 0, (struct pipe_box *)&box, data, box.width * elsize, 0);
707 ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
708 ck_assert_int_eq(ret, invalid ? EINVAL : 0);
709 virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
710
711 virgl_renderer_resource_unref(res.handle);
712 testvirgl_fini_ctx_cmdbuf(&ctx);
713 free(data);
714 }
715
START_TEST(virgl_test_transfer_inline_valid)716 START_TEST(virgl_test_transfer_inline_valid)
717 {
718 virgl_test_transfer_inline(_i, false, 0);
719 }
720 END_TEST
721
START_TEST(virgl_test_transfer_inline_invalid)722 START_TEST(virgl_test_transfer_inline_invalid)
723 {
724 virgl_test_transfer_inline(_i, true, 0);
725 }
726 END_TEST
727
START_TEST(virgl_test_transfer_inline_valid_large)728 START_TEST(virgl_test_transfer_inline_valid_large)
729 {
730 virgl_test_transfer_inline(_i, false, LARGE_FLAG_WIDTH);
731 }
732 END_TEST
733
START_TEST(virgl_test_transfer_to_staging_without_iov_fails)734 START_TEST(virgl_test_transfer_to_staging_without_iov_fails)
735 {
736 static const unsigned bufsize = 50;
737 struct virgl_context ctx;
738 struct virgl_resource res;
739 struct pipe_box box = {.width = bufsize, .height = 1, .depth = 1};
740 int ret;
741
742 ret = testvirgl_init_ctx_cmdbuf(&ctx);
743 ck_assert_int_eq(ret, 0);
744
745 ret = testvirgl_create_unbacked_simple_buffer(&res, 1, bufsize, VIRGL_BIND_STAGING);
746 ck_assert_int_eq(ret, 0);
747 virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
748
749 box.width = bufsize;
750 virgl_encoder_transfer(&ctx, &res, 0, 0, &box, 0, VIRGL_TRANSFER_TO_HOST);
751
752 ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
753 ck_assert_int_eq(ret, EINVAL);
754
755 virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
756 virgl_renderer_resource_unref(res.handle);
757 testvirgl_fini_ctx_cmdbuf(&ctx);
758 }
759 END_TEST
760
START_TEST(virgl_test_transfer_to_staging_with_iov_succeeds)761 START_TEST(virgl_test_transfer_to_staging_with_iov_succeeds)
762 {
763 static const unsigned bufsize = 50;
764 struct virgl_context ctx = {0};
765 struct virgl_resource res = {0};
766 struct pipe_box box = {.width = bufsize, .height = 1, .depth = 1};
767 int ret;
768
769 ret = testvirgl_init_ctx_cmdbuf(&ctx);
770 ck_assert_int_eq(ret, 0);
771
772 ret = testvirgl_create_backed_simple_buffer(&res, 1, bufsize, VIRGL_BIND_STAGING);
773 ck_assert_int_eq(ret, 0);
774 virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
775
776 box.width = bufsize;
777 virgl_encoder_transfer(&ctx, &res, 0, 0, &box, 0, VIRGL_TRANSFER_TO_HOST);
778
779 ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
780 ck_assert_int_eq(ret, 0);
781
782 virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
783 testvirgl_destroy_backed_res(&res);
784 testvirgl_fini_ctx_cmdbuf(&ctx);
785 }
786 END_TEST
787
START_TEST(virgl_test_copy_transfer_from_staging_without_iov_fails)788 START_TEST(virgl_test_copy_transfer_from_staging_without_iov_fails)
789 {
790 static const unsigned bufsize = 50;
791 static const unsigned synchronized = 1;
792 struct virgl_context ctx = {0};
793 struct virgl_resource src_res = {0};
794 struct virgl_resource dst_res = {0};
795 struct pipe_box box = {.width = bufsize, .height = 1, .depth = 1};
796 int ret;
797
798 ret = testvirgl_init_ctx_cmdbuf(&ctx);
799 ck_assert_int_eq(ret, 0);
800
801 ret = testvirgl_create_unbacked_simple_buffer(&src_res, 1, bufsize, VIRGL_BIND_STAGING);
802 ck_assert_int_eq(ret, 0);
803 virgl_renderer_ctx_attach_resource(ctx.ctx_id, src_res.handle);
804
805 ret = testvirgl_create_backed_simple_buffer(&dst_res, 2, bufsize, VIRGL_BIND_VERTEX_BUFFER);
806 ck_assert_int_eq(ret, 0);
807 virgl_renderer_ctx_attach_resource(ctx.ctx_id, dst_res.handle);
808
809 box.width = bufsize;
810 virgl_encoder_copy_transfer(&ctx, &dst_res, 0, 0, &box, &src_res, 0, synchronized);
811
812 ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
813 ck_assert_int_eq(ret, EINVAL);
814
815 virgl_renderer_ctx_detach_resource(ctx.ctx_id, src_res.handle);
816 virgl_renderer_ctx_detach_resource(ctx.ctx_id, dst_res.handle);
817 virgl_renderer_resource_unref(src_res.handle);
818 testvirgl_destroy_backed_res(&dst_res);
819 testvirgl_fini_ctx_cmdbuf(&ctx);
820 }
821 END_TEST
822
START_TEST(virgl_test_copy_transfer_from_staging_with_iov_succeeds)823 START_TEST(virgl_test_copy_transfer_from_staging_with_iov_succeeds)
824 {
825 static const unsigned bufsize = 50;
826 const unsigned synchronized = 1;
827 struct virgl_context ctx = {0};
828 struct virgl_resource src_res = {0};
829 struct virgl_resource dst_res = {0};
830 struct pipe_box box = {.width = bufsize, .height = 1, .depth = 1};
831 int ret;
832
833 ret = testvirgl_init_ctx_cmdbuf(&ctx);
834 ck_assert_int_eq(ret, 0);
835
836 ret = testvirgl_create_backed_simple_buffer(&src_res, 1, bufsize, VIRGL_BIND_STAGING);
837 ck_assert_int_eq(ret, 0);
838 virgl_renderer_ctx_attach_resource(ctx.ctx_id, src_res.handle);
839
840 ret = testvirgl_create_backed_simple_buffer(&dst_res, 2, bufsize, VIRGL_BIND_VERTEX_BUFFER);
841 ck_assert_int_eq(ret, 0);
842 virgl_renderer_ctx_attach_resource(ctx.ctx_id, dst_res.handle);
843
844 box.width = bufsize;
845 virgl_encoder_copy_transfer(&ctx, &dst_res, 0, 0, &box, &src_res, 0, synchronized);
846
847 ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
848 ck_assert_int_eq(ret, 0);
849
850 virgl_renderer_ctx_detach_resource(ctx.ctx_id, src_res.handle);
851 virgl_renderer_ctx_detach_resource(ctx.ctx_id, dst_res.handle);
852 testvirgl_destroy_backed_res(&src_res);
853 testvirgl_destroy_backed_res(&dst_res);
854 testvirgl_fini_ctx_cmdbuf(&ctx);
855 }
856 END_TEST
857
START_TEST(virgl_test_copy_transfer_to_staging_without_iov_fails)858 START_TEST(virgl_test_copy_transfer_to_staging_without_iov_fails)
859 {
860 static const unsigned bufsize = 50;
861 const unsigned synchronized = 1;
862 struct virgl_context ctx = {0};
863 struct virgl_resource src_res = {0};
864 struct virgl_resource dst_res = {0};
865 struct pipe_box box = {.width = bufsize, .height = 1, .depth = 1};
866 int ret;
867
868 ret = testvirgl_init_ctx_cmdbuf(&ctx);
869 ck_assert_int_eq(ret, 0);
870
871 ret = testvirgl_create_backed_simple_buffer(&src_res, 1, bufsize, VIRGL_BIND_STAGING);
872 ck_assert_int_eq(ret, 0);
873 virgl_renderer_ctx_attach_resource(ctx.ctx_id, src_res.handle);
874
875 ret = testvirgl_create_unbacked_simple_buffer(&dst_res, 2, bufsize, VIRGL_BIND_STAGING);
876 ck_assert_int_eq(ret, 0);
877 virgl_renderer_ctx_attach_resource(ctx.ctx_id, dst_res.handle);
878
879 virgl_encoder_copy_transfer(&ctx, &dst_res, 0, 0, &box, &src_res, 0, synchronized);
880
881 ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
882 ck_assert_int_eq(ret, 0);
883
884 virgl_renderer_ctx_detach_resource(ctx.ctx_id, src_res.handle);
885 virgl_renderer_ctx_detach_resource(ctx.ctx_id, dst_res.handle);
886 testvirgl_destroy_backed_res(&src_res);
887 virgl_renderer_resource_unref(dst_res.handle);
888 testvirgl_fini_ctx_cmdbuf(&ctx);
889 }
890 END_TEST
891
START_TEST(virgl_test_copy_transfer_to_staging_with_iov_succeeds)892 START_TEST(virgl_test_copy_transfer_to_staging_with_iov_succeeds)
893 {
894 static const unsigned bufsize = 50;
895 const unsigned synchronized = 1;
896 struct virgl_context ctx = {0};
897 struct virgl_resource src_res = {0};
898 struct virgl_resource dst_res = {0};
899 struct pipe_box box = {.width = bufsize, .height = 1, .depth = 1};
900 int ret;
901
902 ret = testvirgl_init_ctx_cmdbuf(&ctx);
903 ck_assert_int_eq(ret, 0);
904
905 ret = testvirgl_create_backed_simple_buffer(&src_res, 1, bufsize, VIRGL_BIND_STAGING);
906 ck_assert_int_eq(ret, 0);
907 virgl_renderer_ctx_attach_resource(ctx.ctx_id, src_res.handle);
908
909 ret = testvirgl_create_backed_simple_buffer(&dst_res, 2, bufsize, VIRGL_BIND_STAGING);
910 ck_assert_int_eq(ret, 0);
911 virgl_renderer_ctx_attach_resource(ctx.ctx_id, dst_res.handle);
912
913 virgl_encoder_copy_transfer(&ctx, &dst_res, 0, 0, &box, &src_res, 0, synchronized);
914
915 ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
916 ck_assert_int_eq(ret, 0);
917
918 virgl_renderer_ctx_detach_resource(ctx.ctx_id, src_res.handle);
919 virgl_renderer_ctx_detach_resource(ctx.ctx_id, dst_res.handle);
920 testvirgl_destroy_backed_res(&src_res);
921 testvirgl_destroy_backed_res(&dst_res);
922 testvirgl_fini_ctx_cmdbuf(&ctx);
923 }
924 END_TEST
925
START_TEST(virgl_test_transfer_near_res_bounds_with_stride_succeeds)926 START_TEST(virgl_test_transfer_near_res_bounds_with_stride_succeeds)
927 {
928 struct virgl_context ctx = {0};
929 struct virgl_resource res = {0};
930 int res_width = 4;
931 int res_height = 3;
932 int res_stride = res_width * 4;
933 struct pipe_box box = {.x = 2, .y = 1, .z = 0, .width = 2, .height = 2, .depth = 1};
934 int ret;
935
936 ret = testvirgl_init_ctx_cmdbuf(&ctx);
937 ck_assert_int_eq(ret, 0);
938
939 ret = testvirgl_create_backed_simple_2d_res(&res, 1, res_width, res_height);
940 ck_assert_int_eq(ret, 0);
941 virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
942
943 virgl_encoder_transfer_with_stride(&ctx, &res, 0, 0, &box, 6 * 4, VIRGL_TRANSFER_TO_HOST,
944 res_stride, 0);
945
946 ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
947 ck_assert_int_eq(ret, 0);
948
949 virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
950 testvirgl_destroy_backed_res(&res);
951 testvirgl_fini_ctx_cmdbuf(&ctx);
952 }
953 END_TEST
954
virgl_init_suite(void)955 static Suite *virgl_init_suite(void)
956 {
957 Suite *s;
958 TCase *tc_core;
959
960 s = suite_create("virgl_transfer");
961 tc_core = tcase_create("transfer_direct");
962
963 tcase_add_checked_fixture(tc_core, testvirgl_init_single_ctx_nr, testvirgl_fini_single_ctx);
964 tcase_add_test(tc_core, virgl_test_transfer_read_illegal_ctx);
965 tcase_add_test(tc_core, virgl_test_transfer_write_illegal_ctx);
966 tcase_add_test(tc_core, virgl_test_transfer_read_unbound_res);
967 tcase_add_test(tc_core, virgl_test_transfer_write_unbound_res);
968 tcase_add_test(tc_core, virgl_test_transfer_read_no_iov);
969 tcase_add_test(tc_core, virgl_test_transfer_write_no_iov);
970 tcase_add_test(tc_core, virgl_test_transfer_read_no_box);
971 tcase_add_test(tc_core, virgl_test_transfer_write_no_box);
972 tcase_add_test(tc_core, virgl_test_transfer_read_1d_bad_box);
973 tcase_add_test(tc_core, virgl_test_transfer_write_1d_bad_box);
974 tcase_add_test(tc_core, virgl_test_transfer_read_1d_array_bad_box);
975 tcase_add_test(tc_core, virgl_test_transfer_read_3d_bad_box);
976 tcase_add_test(tc_core, virgl_test_transfer_1d);
977 tcase_add_test(tc_core, virgl_test_transfer_1d_bad_iov);
978 tcase_add_test(tc_core, virgl_test_transfer_1d_bad_iov_offset);
979 tcase_add_test(tc_core, virgl_test_transfer_1d_bad_strides);
980 tcase_add_test(tc_core, virgl_test_transfer_2d_bad_strides);
981 tcase_add_test(tc_core, virgl_test_transfer_buffer_bad_strides);
982 tcase_add_test(tc_core, virgl_test_transfer_2d_array_bad_layer_stride);
983 tcase_add_test(tc_core, virgl_test_transfer_2d_bad_level);
984
985 tcase_add_loop_test(tc_core, virgl_test_transfer_res_read_valid, 0, PIPE_MAX_TEXTURE_TYPES);
986 tcase_add_loop_test(tc_core, virgl_test_transfer_res_write_valid, 0, PIPE_MAX_TEXTURE_TYPES);
987 tcase_add_loop_test(tc_core, virgl_test_transfer_res_read_invalid, 0, PIPE_MAX_TEXTURE_TYPES);
988 tcase_add_loop_test(tc_core, virgl_test_transfer_res_write_invalid, 0, PIPE_MAX_TEXTURE_TYPES);
989 suite_add_tcase(s, tc_core);
990
991 tc_core = tcase_create("transfer_inline_write");
992 tcase_add_loop_test(tc_core, virgl_test_transfer_inline_valid, 0, PIPE_MAX_TEXTURE_TYPES);
993 tcase_add_loop_test(tc_core, virgl_test_transfer_inline_invalid, 0, PIPE_MAX_TEXTURE_TYPES);
994 tcase_add_loop_test(tc_core, virgl_test_transfer_inline_valid_large, 0, PIPE_MAX_TEXTURE_TYPES);
995
996 suite_add_tcase(s, tc_core);
997
998 tc_core = tcase_create("transfers_staging");
999 tcase_add_test(tc_core, virgl_test_transfer_to_staging_without_iov_fails);
1000 tcase_add_test(tc_core, virgl_test_transfer_to_staging_with_iov_succeeds);
1001 tcase_add_test(tc_core, virgl_test_copy_transfer_from_staging_without_iov_fails);
1002 tcase_add_test(tc_core, virgl_test_copy_transfer_from_staging_with_iov_succeeds);
1003 tcase_add_test(tc_core, virgl_test_copy_transfer_to_staging_without_iov_fails);
1004 tcase_add_test(tc_core, virgl_test_copy_transfer_to_staging_with_iov_succeeds);
1005
1006 suite_add_tcase(s, tc_core);
1007
1008 tc_core = tcase_create("transfer_command_bounds");
1009 tcase_add_test(tc_core, virgl_test_transfer_near_res_bounds_with_stride_succeeds);
1010
1011 suite_add_tcase(s, tc_core);
1012
1013 return s;
1014
1015 }
1016
1017
main(void)1018 int main(void)
1019 {
1020 Suite *s;
1021 SRunner *sr;
1022 int number_failed;
1023
1024 if (getenv("VRENDTEST_USE_EGL_SURFACELESS"))
1025 context_flags |= VIRGL_RENDERER_USE_SURFACELESS;
1026 if (getenv("VRENDTEST_USE_EGL_GLES"))
1027 context_flags |= VIRGL_RENDERER_USE_GLES;
1028
1029 s = virgl_init_suite();
1030 sr = srunner_create(s);
1031
1032 srunner_run_all(sr, CK_ENV);
1033 number_failed = srunner_ntests_failed(sr);
1034 srunner_free(sr);
1035
1036 return number_failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1037 }
1038