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