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 /*
26  * basic library initialisation, teardown, reset
27  * and context creation tests.
28  */
29 
30 #include <check.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <virglrenderer.h>
34 #include <gbm.h>
35 #include <sys/uio.h>
36 #include "testvirgl.h"
37 #include "virgl_hw.h"
38 struct myinfo_struct {
39   uint32_t test;
40 };
41 
42 struct myinfo_struct mystruct;
43 
44 static struct virgl_renderer_callbacks test_cbs;
45 
START_TEST(virgl_init_no_cbs)46 START_TEST(virgl_init_no_cbs)
47 {
48   int ret;
49   ret = virgl_renderer_init(&mystruct, 0, NULL);
50   ck_assert_int_eq(ret, -1);
51 }
52 END_TEST
53 
START_TEST(virgl_init_no_cookie)54 START_TEST(virgl_init_no_cookie)
55 {
56   int ret;
57   ret = virgl_renderer_init(NULL, 0, &test_cbs);
58   ck_assert_int_eq(ret, -1);
59 }
60 END_TEST
61 
START_TEST(virgl_init_cbs_wrong_ver)62 START_TEST(virgl_init_cbs_wrong_ver)
63 {
64   int ret;
65   struct virgl_renderer_callbacks testcbs;
66   memset(&testcbs, 0, sizeof(testcbs));
67   testcbs.version = VIRGL_RENDERER_CALLBACKS_VERSION + 1;
68   ret = virgl_renderer_init(&mystruct, 0, &testcbs);
69   ck_assert_int_eq(ret, -1);
70 }
71 END_TEST
72 
START_TEST(virgl_init_cleanup_without_init)73 START_TEST(virgl_init_cleanup_without_init)
74 {
75   virgl_renderer_cleanup(&mystruct);
76 }
77 END_TEST
78 
START_TEST(virgl_init_reset_without_init)79 START_TEST(virgl_init_reset_without_init)
80 {
81   virgl_renderer_reset();
82 }
83 END_TEST
84 
START_TEST(virgl_init_egl)85 START_TEST(virgl_init_egl)
86 {
87   int ret;
88   test_cbs.version = 1;
89   ret = virgl_renderer_init(&mystruct, context_flags, &test_cbs);
90   ck_assert_int_eq(ret, 0);
91   virgl_renderer_cleanup(&mystruct);
92 }
93 
94 END_TEST
95 
START_TEST(virgl_init_egl_double_init)96 START_TEST(virgl_init_egl_double_init)
97 {
98   int ret;
99   test_cbs.version = 1;
100   ret = virgl_renderer_init(&mystruct, context_flags, &test_cbs);
101   ck_assert_int_eq(ret, 0);
102   ret = virgl_renderer_init(&mystruct, context_flags, &test_cbs);
103   ck_assert_int_eq(ret, 0);
104   virgl_renderer_cleanup(&mystruct);
105 }
106 END_TEST
107 
START_TEST(virgl_init_egl_double_init_conflict_args)108 START_TEST(virgl_init_egl_double_init_conflict_args)
109 {
110   struct myinfo_struct local_struct;
111   struct virgl_renderer_callbacks local_cbs;
112   int ret;
113 
114   test_cbs.version = 1;
115   ret = virgl_renderer_init(&mystruct, context_flags, &test_cbs);
116   ck_assert_int_eq(ret, 0);
117 
118   ret = virgl_renderer_init(&local_struct, context_flags, &test_cbs);
119   ck_assert_int_eq(ret, -EBUSY);
120 
121   ret = virgl_renderer_init(&mystruct, 0, &test_cbs);
122   ck_assert_int_eq(ret, -EBUSY);
123 
124   memset(&local_cbs, 0, sizeof(local_cbs));
125   local_cbs.version = 1;
126   ret = virgl_renderer_init(&mystruct, context_flags, &local_cbs);
127   ck_assert_int_eq(ret, -EBUSY);
128 
129   virgl_renderer_cleanup(&mystruct);
130 }
131 END_TEST
132 
START_TEST(virgl_init_egl_create_ctx)133 START_TEST(virgl_init_egl_create_ctx)
134 {
135   int ret;
136   test_cbs.version = 1;
137   ret = virgl_renderer_init(&mystruct, context_flags, &test_cbs);
138   ck_assert_int_eq(ret, 0);
139   ret = virgl_renderer_context_create(1, strlen("test1"), "test1");
140   ck_assert_int_eq(ret, 0);
141 
142   virgl_renderer_context_destroy(1);
143   virgl_renderer_cleanup(&mystruct);
144 }
145 END_TEST
146 
START_TEST(virgl_init_egl_create_ctx_0)147 START_TEST(virgl_init_egl_create_ctx_0)
148 {
149   int ret;
150 
151   test_cbs.version = 1;
152   ret = virgl_renderer_init(&mystruct, context_flags, &test_cbs);
153   ck_assert_int_eq(ret, 0);
154   ret = virgl_renderer_context_create(0, strlen("test1"), "test1");
155   ck_assert_int_eq(ret, EINVAL);
156 
157   virgl_renderer_cleanup(&mystruct);
158 }
159 END_TEST
160 
START_TEST(virgl_init_egl_destroy_ctx_illegal)161 START_TEST(virgl_init_egl_destroy_ctx_illegal)
162 {
163   int ret;
164   test_cbs.version = 1;
165   ret = virgl_renderer_init(&mystruct, context_flags, &test_cbs);
166   ck_assert_int_eq(ret, 0);
167 
168   virgl_renderer_context_destroy(1);
169   virgl_renderer_cleanup(&mystruct);
170 }
171 END_TEST
172 
START_TEST(virgl_init_egl_create_ctx_leak)173 START_TEST(virgl_init_egl_create_ctx_leak)
174 {
175   testvirgl_init_single_ctx();
176 
177   /* don't destroy the context - leak it make sure cleanup catches it */
178   /*virgl_renderer_context_destroy(1);*/
179   virgl_renderer_cleanup(&mystruct);
180 }
181 END_TEST
182 
START_TEST(virgl_init_egl_create_ctx_create_bind_res)183 START_TEST(virgl_init_egl_create_ctx_create_bind_res)
184 {
185   int ret;
186   struct virgl_renderer_resource_create_args res;
187 
188   testvirgl_init_simple_1d_resource(&res, 1);
189 
190   ret = virgl_renderer_resource_create(&res, NULL, 0);
191   ck_assert_int_eq(ret, 0);
192 
193   virgl_renderer_ctx_attach_resource(1, res.handle);
194 
195   virgl_renderer_ctx_detach_resource(1, res.handle);
196 
197   virgl_renderer_resource_unref(1);
198 }
199 END_TEST
200 
START_TEST(virgl_init_egl_create_ctx_create_bind_res_illegal_ctx)201 START_TEST(virgl_init_egl_create_ctx_create_bind_res_illegal_ctx)
202 {
203   int ret;
204   struct virgl_renderer_resource_create_args res;
205 
206   testvirgl_init_simple_1d_resource(&res, 1);
207 
208   ret = virgl_renderer_resource_create(&res, NULL, 0);
209   ck_assert_int_eq(ret, 0);
210 
211   virgl_renderer_ctx_attach_resource(2, res.handle);
212 
213   virgl_renderer_resource_unref(1);
214 }
215 END_TEST
216 
217 
START_TEST(virgl_init_egl_create_ctx_create_bind_res_illegal_res)218 START_TEST(virgl_init_egl_create_ctx_create_bind_res_illegal_res)
219 {
220   int ret;
221   struct virgl_renderer_resource_create_args res;
222 
223   testvirgl_init_simple_1d_resource(&res, 1);
224 
225   ret = virgl_renderer_resource_create(&res, NULL, 0);
226   ck_assert_int_eq(ret, 0);
227 
228   virgl_renderer_ctx_attach_resource(1, 2);
229 
230   virgl_renderer_resource_unref(1);
231 }
232 END_TEST
233 
START_TEST(virgl_init_egl_create_ctx_create_unbind_no_bind)234 START_TEST(virgl_init_egl_create_ctx_create_unbind_no_bind)
235 {
236   int ret;
237   struct virgl_renderer_resource_create_args res;
238 
239   testvirgl_init_simple_1d_resource(&res, 1);
240 
241   ret = virgl_renderer_resource_create(&res, NULL, 0);
242   ck_assert_int_eq(ret, 0);
243 
244   virgl_renderer_ctx_detach_resource(1, res.handle);
245 
246   virgl_renderer_resource_unref(1);
247 }
248 END_TEST
249 
START_TEST(virgl_init_egl_create_ctx_create_unbind_illegal_ctx)250 START_TEST(virgl_init_egl_create_ctx_create_unbind_illegal_ctx)
251 {
252   int ret;
253   struct virgl_renderer_resource_create_args res;
254 
255   testvirgl_init_simple_1d_resource(&res, 1);
256 
257   ret = virgl_renderer_resource_create(&res, NULL, 0);
258   ck_assert_int_eq(ret, 0);
259 
260   virgl_renderer_ctx_detach_resource(2, res.handle);
261 
262   virgl_renderer_resource_unref(1);
263 }
264 END_TEST
265 
266 
START_TEST(virgl_init_egl_create_ctx_create_bind_res_leak)267 START_TEST(virgl_init_egl_create_ctx_create_bind_res_leak)
268 {
269   int ret;
270   struct virgl_renderer_resource_create_args res;
271 
272   testvirgl_init_single_ctx_nr();
273 
274   testvirgl_init_simple_1d_resource(&res, 1);
275 
276   ret = virgl_renderer_resource_create(&res, NULL, 0);
277   ck_assert_int_eq(ret, 0);
278 
279   virgl_renderer_ctx_attach_resource(1, res.handle);
280 
281   /*virgl_renderer_ctx_detach_resource(1, res.handle);*/
282 
283   /*virgl_renderer_resource_unref(1);*/
284   /* don't detach or destroy resource - it should still get cleanedup */
285   testvirgl_fini_single_ctx();
286 }
287 END_TEST
288 
START_TEST(virgl_init_egl_create_ctx_reset)289 START_TEST(virgl_init_egl_create_ctx_reset)
290 {
291   int ret;
292 
293   ret = testvirgl_init_single_ctx();
294   ck_assert_int_eq(ret, 0);
295 
296   virgl_renderer_reset();
297 
298   /* reset should have destroyed the context */
299   ret = virgl_renderer_context_create(1, strlen("test1"), "test1");
300   ck_assert_int_eq(ret, 0);
301   virgl_renderer_cleanup(&mystruct);
302 }
303 END_TEST
304 
START_TEST(virgl_init_get_caps_set0)305 START_TEST(virgl_init_get_caps_set0)
306 {
307   int ret;
308   uint32_t max_ver, max_size;
309 
310   test_cbs.version = 1;
311   ret = virgl_renderer_init(&mystruct, context_flags, &test_cbs);
312   ck_assert_int_eq(ret, 0);
313 
314   virgl_renderer_get_cap_set(0, &max_ver, &max_size);
315   ck_assert_int_eq(max_ver, 0);
316   ck_assert_int_eq(max_size, 0);
317 
318   virgl_renderer_cleanup(&mystruct);
319 }
320 END_TEST
321 
START_TEST(virgl_init_get_caps_set1)322 START_TEST(virgl_init_get_caps_set1)
323 {
324   int ret;
325   uint32_t max_ver, max_size;
326   void *caps;
327   test_cbs.version = 1;
328   ret = virgl_renderer_init(&mystruct, context_flags, &test_cbs);
329   ck_assert_int_eq(ret, 0);
330 
331   virgl_renderer_get_cap_set(1, &max_ver, &max_size);
332   ck_assert_int_ge(max_ver, 1);
333   ck_assert_int_ne(max_size, 0);
334   ck_assert_int_ge(max_size, sizeof(struct virgl_caps_v1));
335 
336   caps = malloc(max_size);
337 
338   virgl_renderer_fill_caps(0, 0, caps);
339 
340   free(caps);
341   virgl_renderer_cleanup(&mystruct);
342 }
343 END_TEST
344 
START_TEST(virgl_init_get_caps_null)345 START_TEST(virgl_init_get_caps_null)
346 {
347   int ret;
348   uint32_t max_ver, max_size;
349 
350   test_cbs.version = 1;
351   ret = virgl_renderer_init(&mystruct, context_flags, &test_cbs);
352   ck_assert_int_eq(ret, 0);
353 
354   virgl_renderer_get_cap_set(1, &max_ver, &max_size);
355   ck_assert_int_ge(max_ver, 1);
356   ck_assert_int_ne(max_size, 0);
357   ck_assert_int_ge(max_size, sizeof(struct virgl_caps_v1));
358 
359   virgl_renderer_fill_caps(0, 0, NULL);
360 
361   virgl_renderer_cleanup(&mystruct);
362 }
363 END_TEST
364 
START_TEST(virgl_test_get_resource_info)365 START_TEST(virgl_test_get_resource_info)
366 {
367   int ret;
368   struct virgl_renderer_resource_create_args res;
369   struct virgl_renderer_resource_info info;
370 
371   testvirgl_init_simple_2d_resource(&res, 1);
372   res.format = VIRGL_FORMAT_B8G8R8X8_UNORM;
373   ret = virgl_renderer_resource_create(&res, NULL, 0);
374   ck_assert_int_eq(ret, 0);
375 
376   virgl_renderer_ctx_attach_resource(1, res.handle);
377 
378   ret = virgl_renderer_resource_get_info(res.handle, &info);
379   ck_assert_int_eq(ret, 0);
380 
381   ck_assert(info.drm_fourcc == GBM_FORMAT_ABGR8888 ||
382             info.drm_fourcc == GBM_FORMAT_ARGB8888 ||
383             info.drm_fourcc == GBM_FORMAT_XRGB8888);
384   ck_assert_int_eq(info.virgl_format, res.format);
385   ck_assert_int_eq(res.width, info.width);
386   ck_assert_int_eq(res.height, info.height);
387   ck_assert_int_eq(res.depth, info.depth);
388   ck_assert_int_eq(res.flags, info.flags);
389   virgl_renderer_ctx_detach_resource(1, res.handle);
390 
391   virgl_renderer_resource_unref(1);
392 }
393 END_TEST
394 
START_TEST(virgl_test_get_resource_info_no_info)395 START_TEST(virgl_test_get_resource_info_no_info)
396 {
397   int ret;
398   struct virgl_renderer_resource_create_args res;
399 
400   testvirgl_init_simple_1d_resource(&res, 1);
401 
402   ret = virgl_renderer_resource_create(&res, NULL, 0);
403   ck_assert_int_eq(ret, 0);
404 
405   virgl_renderer_ctx_attach_resource(1, res.handle);
406 
407   ret = virgl_renderer_resource_get_info(1, NULL);
408   ck_assert_int_eq(ret, EINVAL);
409 
410   virgl_renderer_ctx_detach_resource(1, res.handle);
411   virgl_renderer_resource_unref(1);
412 }
413 END_TEST
414 
415 
START_TEST(virgl_test_get_resource_info_no_res)416 START_TEST(virgl_test_get_resource_info_no_res)
417 {
418   int ret;
419   struct virgl_renderer_resource_info info;
420 
421   ret = virgl_renderer_resource_get_info(1, &info);
422   ck_assert_int_eq(ret, EINVAL);
423 
424   virgl_renderer_resource_unref(1);
425 }
426 END_TEST
427 
START_TEST(virgl_init_egl_create_ctx_create_attach_res)428 START_TEST(virgl_init_egl_create_ctx_create_attach_res)
429 {
430   int ret;
431   struct virgl_renderer_resource_create_args res;
432   struct iovec iovs[1];
433   struct iovec *iovs_r;
434   int num_r;
435 
436   testvirgl_init_simple_1d_resource(&res, 1);
437 
438   ret = virgl_renderer_resource_create(&res, NULL, 0);
439   ck_assert_int_eq(ret, 0);
440 
441   iovs[0].iov_base = malloc(4096);
442   iovs[0].iov_len = 4096;
443 
444   ret = virgl_renderer_resource_attach_iov(1, iovs, 1);
445   ck_assert_int_eq(ret, 0);
446 
447   virgl_renderer_resource_detach_iov(1, &iovs_r, &num_r);
448 
449   free(iovs[0].iov_base);
450   virgl_renderer_resource_unref(1);
451 }
452 END_TEST
453 
START_TEST(virgl_init_egl_create_ctx_create_attach_res_detach_no_iovs)454 START_TEST(virgl_init_egl_create_ctx_create_attach_res_detach_no_iovs)
455 {
456   int ret;
457   struct virgl_renderer_resource_create_args res;
458   struct iovec iovs[1];
459   int num_r;
460 
461   testvirgl_init_simple_1d_resource(&res, 1);
462 
463   ret = virgl_renderer_resource_create(&res, NULL, 0);
464   ck_assert_int_eq(ret, 0);
465 
466   iovs[0].iov_base = malloc(4096);
467   iovs[0].iov_len = 4096;
468 
469   ret = virgl_renderer_resource_attach_iov(1, iovs, 1);
470   ck_assert_int_eq(ret, 0);
471 
472   virgl_renderer_resource_detach_iov(1, NULL, &num_r);
473 
474   free(iovs[0].iov_base);
475   virgl_renderer_resource_unref(1);
476 }
477 END_TEST
478 
START_TEST(virgl_init_egl_create_ctx_create_attach_res_illegal_res)479 START_TEST(virgl_init_egl_create_ctx_create_attach_res_illegal_res)
480 {
481   int ret;
482   struct iovec iovs[1];
483 
484   test_cbs.version = 1;
485   ret = virgl_renderer_init(&mystruct, context_flags, &test_cbs);
486   ck_assert_int_eq(ret, 0);
487 
488   ret = virgl_renderer_resource_attach_iov(1, iovs, 1);
489   ck_assert_int_eq(ret, EINVAL);
490 
491   virgl_renderer_resource_unref(1);
492   virgl_renderer_context_destroy(1);
493   virgl_renderer_cleanup(&mystruct);
494 }
495 END_TEST
496 
virgl_init_suite(void)497 static Suite *virgl_init_suite(void)
498 {
499   Suite *s;
500   TCase *tc_core;
501 
502   s = suite_create("virgl_init");
503   tc_core = tcase_create("init");
504 
505   tcase_add_test(tc_core, virgl_init_no_cbs);
506   tcase_add_test(tc_core, virgl_init_no_cookie);
507   tcase_add_test(tc_core, virgl_init_cbs_wrong_ver);
508   tcase_add_test(tc_core, virgl_init_cleanup_without_init);
509   tcase_add_test(tc_core, virgl_init_reset_without_init);
510   tcase_add_test(tc_core, virgl_init_egl);
511   tcase_add_test(tc_core, virgl_init_egl_double_init);
512   tcase_add_test(tc_core, virgl_init_egl_double_init_conflict_args);
513   tcase_add_test(tc_core, virgl_init_egl_create_ctx);
514   tcase_add_test(tc_core, virgl_init_egl_create_ctx_0);
515   tcase_add_test(tc_core, virgl_init_egl_destroy_ctx_illegal);
516   tcase_add_test(tc_core, virgl_init_egl_create_ctx_leak);
517   tcase_add_test(tc_core, virgl_init_egl_create_ctx_reset);
518   tcase_add_test(tc_core, virgl_init_get_caps_set0);
519   tcase_add_test(tc_core, virgl_init_get_caps_set1);
520   tcase_add_test(tc_core, virgl_init_get_caps_null);
521   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_attach_res_illegal_res);
522   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_bind_res_leak);
523 
524   suite_add_tcase(s, tc_core);
525 
526   tc_core = tcase_create("init_std");
527   tcase_add_checked_fixture(tc_core, testvirgl_init_single_ctx_nr, testvirgl_fini_single_ctx);
528   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_bind_res);
529   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_bind_res_illegal_ctx);
530   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_bind_res_illegal_res);
531   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_unbind_no_bind);
532   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_unbind_illegal_ctx);
533 
534   tcase_add_test(tc_core, virgl_test_get_resource_info);
535   tcase_add_test(tc_core, virgl_test_get_resource_info_no_info);
536   tcase_add_test(tc_core, virgl_test_get_resource_info_no_res);
537   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_attach_res);
538   tcase_add_test(tc_core, virgl_init_egl_create_ctx_create_attach_res_detach_no_iovs);
539 
540   suite_add_tcase(s, tc_core);
541   return s;
542 
543 }
544 
545 
main(void)546 int main(void)
547 {
548   Suite *s;
549   SRunner *sr;
550   int number_failed;
551 
552   if (getenv("VRENDTEST_USE_EGL_SURFACELESS"))
553      context_flags |= VIRGL_RENDERER_USE_SURFACELESS;
554    if (getenv("VRENDTEST_USE_EGL_GLES"))
555       context_flags |= VIRGL_RENDERER_USE_GLES;
556 
557   s = virgl_init_suite();
558   sr = srunner_create(s);
559 
560   srunner_run_all(sr, CK_NORMAL);
561   number_failed = srunner_ntests_failed(sr);
562   srunner_free(sr);
563 
564   return number_failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
565 }
566