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 #include <check.h>
25 #include <stdlib.h>
26 #include <time.h>
27 #include <errno.h>
28 #include <sys/uio.h>
29 #include <virglrenderer.h>
30 #include "virgl_hw.h"
31 #include "pipe/p_format.h"
32 #include "testvirgl_encode.h"
33 #include "virgl_protocol.h"
34 #include "util/u_memory.h"
35
36 #include "large_shader.h"
37 /* test creating objects with same ID causes context err */
START_TEST(virgl_test_overlap_obj_id)38 START_TEST(virgl_test_overlap_obj_id)
39 {
40 int ret;
41 struct virgl_context ctx;
42 int ctx_handle = 1;
43 ret = testvirgl_init_ctx_cmdbuf(&ctx);
44 ck_assert_int_eq(ret, 0);
45
46 /* set blend state */
47 {
48 struct pipe_blend_state blend;
49 int blend_handle = ctx_handle;
50 memset(&blend, 0, sizeof(blend));
51 blend.rt[0].colormask = PIPE_MASK_RGBA;
52 virgl_encode_blend_state(&ctx, blend_handle, &blend);
53 virgl_encode_bind_object(&ctx, blend_handle, VIRGL_OBJECT_BLEND);
54 }
55
56 /* set depth stencil alpha state */
57 {
58 struct pipe_depth_stencil_alpha_state dsa;
59 int dsa_handle = ctx_handle;
60 memset(&dsa, 0, sizeof(dsa));
61 dsa.depth.writemask = 1;
62 dsa.depth.func = PIPE_FUNC_LESS;
63 virgl_encode_dsa_state(&ctx, dsa_handle, &dsa);
64 virgl_encode_bind_object(&ctx, dsa_handle, VIRGL_OBJECT_DSA);
65 }
66 testvirgl_fini_ctx_cmdbuf(&ctx);
67 }
68 END_TEST
69
70 #ifdef PIPE_ARCH_LITTLE_ENDIAN
71 static const uint32_t test_green = 0xff00ff00;
72 #else
73 static const uint32_t test_green = 0x00ff00ff;
74 #endif
75
76 /* create a resource - clear it to a color, do a transfer */
START_TEST(virgl_test_clear)77 START_TEST(virgl_test_clear)
78 {
79 struct virgl_context ctx;
80 struct virgl_resource res;
81 struct virgl_surface surf;
82 struct pipe_framebuffer_state fb_state;
83 union pipe_color_union color;
84 struct virgl_box box;
85 int ret;
86 int i;
87
88 ret = testvirgl_init_ctx_cmdbuf(&ctx);
89 ck_assert_int_eq(ret, 0);
90
91 /* init and create simple 2D resource */
92 ret = testvirgl_create_backed_simple_2d_res(&res, 1, 50, 50);
93 ck_assert_int_eq(ret, 0);
94
95 /* attach resource to context */
96 virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
97
98 /* create a surface for the resource */
99 memset(&surf, 0, sizeof(surf));
100 surf.base.format = PIPE_FORMAT_B8G8R8X8_UNORM;
101 surf.handle = 1;
102 surf.base.texture = &res.base;
103
104 virgl_encoder_create_surface(&ctx, surf.handle, &res, &surf.base);
105
106 /* set the framebuffer state */
107 fb_state.nr_cbufs = 1;
108 fb_state.zsbuf = NULL;
109 fb_state.cbufs[0] = &surf.base;
110 virgl_encoder_set_framebuffer_state(&ctx, &fb_state);
111
112 /* clear the resource */
113 /* clear buffer to green */
114 color.f[0] = 0.0;
115 color.f[1] = 1.0;
116 color.f[2] = 0.0;
117 color.f[3] = 1.0;
118 virgl_encode_clear(&ctx, PIPE_CLEAR_COLOR0, &color, 0.0, 0);
119
120 /* submit the cmd stream */
121 virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
122
123 /* read back the cleared values in the resource */
124 box.x = 0;
125 box.y = 0;
126 box.z = 0;
127 box.w = 5;
128 box.h = 1;
129 box.d = 1;
130 ret = virgl_renderer_transfer_read_iov(res.handle, ctx.ctx_id, 0, 50, 0, &box, 0, NULL, 0);
131 ck_assert_int_eq(ret, 0);
132
133 /* check the returned values */
134 for (i = 0; i < 5; i++) {
135 uint32_t *ptr = res.iovs[0].iov_base;
136 ck_assert_int_eq(ptr[i], test_green);
137 }
138
139 /* cleanup */
140 virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
141
142 testvirgl_destroy_backed_res(&res);
143
144 testvirgl_fini_ctx_cmdbuf(&ctx);
145 }
146 END_TEST
147
START_TEST(virgl_test_blit_simple)148 START_TEST(virgl_test_blit_simple)
149 {
150 struct virgl_context ctx;
151 struct virgl_resource res, res2;
152 struct virgl_surface surf;
153 struct pipe_framebuffer_state fb_state;
154 union pipe_color_union color;
155 struct pipe_blit_info blit;
156 struct virgl_box box;
157 int ret;
158 int i;
159
160 ret = testvirgl_init_ctx_cmdbuf(&ctx);
161 ck_assert_int_eq(ret, 0);
162
163 /* init and create simple 2D resource */
164 ret = testvirgl_create_backed_simple_2d_res(&res, 1, 50, 50);
165 ck_assert_int_eq(ret, 0);
166
167 /* init and create simple 2D resource */
168 ret = testvirgl_create_backed_simple_2d_res(&res2, 2, 50, 50);
169 ck_assert_int_eq(ret, 0);
170
171 /* attach resource to context */
172 virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
173 virgl_renderer_ctx_attach_resource(ctx.ctx_id, res2.handle);
174
175 /* create a surface for the resource */
176 memset(&surf, 0, sizeof(surf));
177 surf.base.format = PIPE_FORMAT_B8G8R8X8_UNORM;
178 surf.handle = 1;
179 surf.base.texture = &res.base;
180
181 virgl_encoder_create_surface(&ctx, surf.handle, &res, &surf.base);
182
183 /* set the framebuffer state */
184 fb_state.nr_cbufs = 1;
185 fb_state.zsbuf = NULL;
186 fb_state.cbufs[0] = &surf.base;
187 virgl_encoder_set_framebuffer_state(&ctx, &fb_state);
188
189 /* clear the resource */
190 /* clear buffer to green */
191 color.f[0] = 0.0;
192 color.f[1] = 1.0;
193 color.f[2] = 0.0;
194 color.f[3] = 1.0;
195 virgl_encode_clear(&ctx, PIPE_CLEAR_COLOR0, &color, 0.0, 0);
196
197 memset(&blit, 0, sizeof(blit));
198 blit.mask = PIPE_MASK_RGBA;
199 blit.dst.format = res2.base.format;
200 blit.dst.box.width = 10;
201 blit.dst.box.height = 1;
202 blit.dst.box.depth = 1;
203 blit.src.format = res.base.format;
204 blit.src.box.width = 10;
205 blit.src.box.height = 1;
206 blit.src.box.depth = 1;
207 virgl_encode_blit(&ctx, &res2, &res, &blit);
208
209 /* submit the cmd stream */
210 virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
211
212 /* read back the cleared values in the resource */
213 box.x = 0;
214 box.y = 0;
215 box.z = 0;
216 box.w = 5;
217 box.h = 1;
218 box.d = 1;
219 ret = virgl_renderer_transfer_read_iov(res2.handle, ctx.ctx_id, 0, 50, 0, &box, 0, NULL, 0);
220 ck_assert_int_eq(ret, 0);
221
222 /* check the returned values */
223 for (i = 0; i < 5; i++) {
224 uint32_t *ptr = res2.iovs[0].iov_base;
225 ck_assert_int_eq(ptr[i], test_green);
226 }
227
228 /* cleanup */
229 virgl_renderer_ctx_detach_resource(ctx.ctx_id, res2.handle);
230 virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
231
232 testvirgl_destroy_backed_res(&res);
233 testvirgl_destroy_backed_res(&res2);
234
235 testvirgl_fini_ctx_cmdbuf(&ctx);
236 }
237 END_TEST
238
239 struct vertex {
240 float position[4];
241 float color[4];
242 };
243
244 static struct vertex vertices[3] =
245 {
246 {
247 { 0.0f, -0.9f, 0.0f, 1.0f },
248 { 1.0f, 0.0f, 0.0f, 1.0f }
249 },
250 {
251 { -0.9f, 0.9f, 0.0f, 1.0f },
252 { 0.0f, 1.0f, 0.0f, 1.0f }
253 },
254 {
255 { 0.9f, 0.9f, 0.0f, 1.0f },
256 { 0.0f, 0.0f, 1.0f, 1.0f }
257 }
258 };
259
260 /* create a resource - clear it to a color, render something */
START_TEST(virgl_test_render_simple)261 START_TEST(virgl_test_render_simple)
262 {
263 struct virgl_context ctx;
264 struct virgl_resource res;
265 struct virgl_resource vbo;
266 struct virgl_surface surf;
267 struct pipe_framebuffer_state fb_state;
268 struct pipe_vertex_element ve[2];
269 struct pipe_vertex_buffer vbuf;
270 int ve_handle, vs_handle, fs_handle;
271 int ctx_handle = 1;
272 union pipe_color_union color;
273 struct virgl_box box;
274 int ret;
275 int tw = 300, th = 300;
276
277 ret = testvirgl_init_ctx_cmdbuf(&ctx);
278 ck_assert_int_eq(ret, 0);
279
280 /* init and create simple 2D resource */
281 ret = testvirgl_create_backed_simple_2d_res(&res, 1, tw, th);
282 ck_assert_int_eq(ret, 0);
283
284 /* attach resource to context */
285 virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
286
287 /* create a surface for the resource */
288 memset(&surf, 0, sizeof(surf));
289 surf.base.format = PIPE_FORMAT_B8G8R8X8_UNORM;
290 surf.handle = ctx_handle++;
291 surf.base.texture = &res.base;
292
293 virgl_encoder_create_surface(&ctx, surf.handle, &res, &surf.base);
294
295 /* set the framebuffer state */
296 fb_state.nr_cbufs = 1;
297 fb_state.zsbuf = NULL;
298 fb_state.cbufs[0] = &surf.base;
299 virgl_encoder_set_framebuffer_state(&ctx, &fb_state);
300
301 /* clear the resource */
302 /* clear buffer to green */
303 color.f[0] = 0.0;
304 color.f[1] = 1.0;
305 color.f[2] = 0.0;
306 color.f[3] = 1.0;
307 virgl_encode_clear(&ctx, PIPE_CLEAR_COLOR0, &color, 0.0, 0);
308
309 /* create vertex elements */
310 ve_handle = ctx_handle++;
311 memset(ve, 0, sizeof(ve));
312 ve[0].src_offset = Offset(struct vertex, position);
313 ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
314 ve[1].src_offset = Offset(struct vertex, color);
315 ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
316 virgl_encoder_create_vertex_elements(&ctx, ve_handle, 2, ve);
317
318 virgl_encode_bind_object(&ctx, ve_handle, VIRGL_OBJECT_VERTEX_ELEMENTS);
319
320 /* create vbo */
321 ret = testvirgl_create_backed_simple_buffer(&vbo, 2, sizeof(vertices), PIPE_BIND_VERTEX_BUFFER);
322 ck_assert_int_eq(ret, 0);
323 virgl_renderer_ctx_attach_resource(ctx.ctx_id, vbo.handle);
324
325 /* inline write the data to it */
326 box.x = 0;
327 box.y = 0;
328 box.z = 0;
329 box.w = sizeof(vertices);
330 box.h = 1;
331 box.d = 1;
332 virgl_encoder_inline_write(&ctx, &vbo, 0, 0, (struct pipe_box *)&box, &vertices, box.w, 0);
333
334 vbuf.stride = sizeof(struct vertex);
335 vbuf.buffer_offset = 0;
336 vbuf.buffer = &vbo.base;
337 virgl_encoder_set_vertex_buffers(&ctx, 1, &vbuf);
338
339 /* create vertex shader */
340 {
341 struct pipe_shader_state vs;
342 const char *text =
343 "VERT\n"
344 "DCL IN[0]\n"
345 "DCL IN[1]\n"
346 "DCL OUT[0], POSITION\n"
347 "DCL OUT[1], COLOR\n"
348 " 0: MOV OUT[1], IN[1]\n"
349 " 1: MOV OUT[0], IN[0]\n"
350 " 2: END\n";
351 memset(&vs, 0, sizeof(vs));
352 vs_handle = ctx_handle++;
353 virgl_encode_shader_state(&ctx, vs_handle, PIPE_SHADER_VERTEX,
354 &vs, text);
355 virgl_encode_bind_shader(&ctx, vs_handle, PIPE_SHADER_VERTEX);
356 }
357
358 /* create fragment shader */
359 {
360 struct pipe_shader_state fs;
361 const char *text =
362 "FRAG\n"
363 "DCL IN[0], COLOR, LINEAR\n"
364 "DCL OUT[0], COLOR\n"
365 " 0: MOV OUT[0], IN[0]\n"
366 " 1: END\n";
367 memset(&fs, 0, sizeof(fs));
368 fs_handle = ctx_handle++;
369 virgl_encode_shader_state(&ctx, fs_handle, PIPE_SHADER_FRAGMENT,
370 &fs, text);
371
372 virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT);
373 }
374
375 /* set blend state */
376 {
377 struct pipe_blend_state blend;
378 int blend_handle = ctx_handle++;
379 memset(&blend, 0, sizeof(blend));
380 blend.rt[0].colormask = PIPE_MASK_RGBA;
381 virgl_encode_blend_state(&ctx, blend_handle, &blend);
382 virgl_encode_bind_object(&ctx, blend_handle, VIRGL_OBJECT_BLEND);
383 }
384
385 /* set depth stencil alpha state */
386 {
387 struct pipe_depth_stencil_alpha_state dsa;
388 int dsa_handle = ctx_handle++;
389 memset(&dsa, 0, sizeof(dsa));
390 dsa.depth.writemask = 1;
391 dsa.depth.func = PIPE_FUNC_LESS;
392 virgl_encode_dsa_state(&ctx, dsa_handle, &dsa);
393 virgl_encode_bind_object(&ctx, dsa_handle, VIRGL_OBJECT_DSA);
394 }
395
396 /* set rasterizer state */
397 {
398 struct pipe_rasterizer_state rasterizer;
399 int rs_handle = ctx_handle++;
400 memset(&rasterizer, 0, sizeof(rasterizer));
401 rasterizer.cull_face = PIPE_FACE_NONE;
402 rasterizer.half_pixel_center = 1;
403 rasterizer.bottom_edge_rule = 1;
404 rasterizer.depth_clip = 1;
405 virgl_encode_rasterizer_state(&ctx, rs_handle, &rasterizer);
406 virgl_encode_bind_object(&ctx, rs_handle, VIRGL_OBJECT_RASTERIZER);
407 }
408
409 /* set viewport state */
410 {
411 struct pipe_viewport_state vp;
412 float znear = 0, zfar = 1.0;
413 float half_w = tw / 2.0f;
414 float half_h = th / 2.0f;
415 float half_d = (zfar - znear) / 2.0f;
416
417 vp.scale[0] = half_w;
418 vp.scale[1] = half_h;
419 vp.scale[2] = half_d;
420
421 vp.translate[0] = half_w + 0;
422 vp.translate[1] = half_h + 0;
423 vp.translate[2] = half_d + znear;
424 virgl_encoder_set_viewport_states(&ctx, 0, 1, &vp);
425 }
426
427 /* draw */
428 {
429 struct pipe_draw_info info;
430 memset(&info, 0, sizeof(info));
431 info.count = 3;
432 info.mode = PIPE_PRIM_TRIANGLES;
433 virgl_encoder_draw_vbo(&ctx, &info);
434 }
435
436 virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
437
438 /* create a fence */
439 testvirgl_reset_fence();
440 ret = virgl_renderer_create_fence(1, ctx.ctx_id);
441 ck_assert_int_eq(ret, 0);
442
443 do {
444 int fence;
445
446 virgl_renderer_poll();
447 fence = testvirgl_get_last_fence();
448 if (fence >= 1)
449 break;
450 nanosleep((struct timespec[]){{0, 50000}}, NULL);
451 } while(1);
452
453 /* read back the tri values in the resource */
454 box.x = 0;
455 box.y = 0;
456 box.z = 0;
457 box.w = tw;
458 box.h = th;
459 box.d = 1;
460 ret = virgl_renderer_transfer_read_iov(res.handle, ctx.ctx_id, 0, 0, 0, &box, 0, NULL, 0);
461 ck_assert_int_eq(ret, 0);
462
463 {
464 int w, h;
465 bool all_cleared = true;
466 uint32_t *ptr = res.iovs[0].iov_base;
467 for (h = 0; h < th; h++) {
468 for (w = 0; w < tw; w++) {
469 if (ptr[h * tw + w] != test_green)
470 all_cleared = false;
471 }
472 }
473 ck_assert_int_eq(all_cleared, false);
474 }
475
476 /* cleanup */
477 virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
478
479 testvirgl_destroy_backed_res(&vbo);
480 testvirgl_destroy_backed_res(&res);
481
482 testvirgl_fini_ctx_cmdbuf(&ctx);
483 }
484 END_TEST
485
486 /* create a resource - clear it to a color, render something */
START_TEST(virgl_test_render_geom_simple)487 START_TEST(virgl_test_render_geom_simple)
488 {
489 struct virgl_context ctx;
490 struct virgl_resource res;
491 struct virgl_resource vbo;
492 struct virgl_surface surf;
493 struct pipe_framebuffer_state fb_state;
494 struct pipe_vertex_element ve[2];
495 struct pipe_vertex_buffer vbuf;
496 int ve_handle, vs_handle, fs_handle, gs_handle;
497 int ctx_handle = 1;
498 union pipe_color_union color;
499 struct virgl_box box;
500 int ret;
501 int tw = 300, th = 300;
502
503 ret = testvirgl_init_ctx_cmdbuf(&ctx);
504 ck_assert_int_eq(ret, 0);
505
506 /* Geometry shader are only available since GLSL 150 */
507 uint32_t glsl_level = testvirgl_get_glsl_level_from_caps();
508 if (glsl_level < 150) {
509 testvirgl_fini_ctx_cmdbuf(&ctx);
510 return;
511 }
512
513 /* init and create simple 2D resource */
514 ret = testvirgl_create_backed_simple_2d_res(&res, 1, tw, th);
515 ck_assert_int_eq(ret, 0);
516
517 /* attach resource to context */
518 virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
519
520 /* create a surface for the resource */
521 memset(&surf, 0, sizeof(surf));
522 surf.base.format = PIPE_FORMAT_B8G8R8X8_UNORM;
523 surf.handle = ctx_handle++;
524 surf.base.texture = &res.base;
525
526 virgl_encoder_create_surface(&ctx, surf.handle, &res, &surf.base);
527
528 /* set the framebuffer state */
529 fb_state.nr_cbufs = 1;
530 fb_state.zsbuf = NULL;
531 fb_state.cbufs[0] = &surf.base;
532 virgl_encoder_set_framebuffer_state(&ctx, &fb_state);
533
534 /* clear the resource */
535 /* clear buffer to green */
536 color.f[0] = 0.0;
537 color.f[1] = 1.0;
538 color.f[2] = 0.0;
539 color.f[3] = 1.0;
540 virgl_encode_clear(&ctx, PIPE_CLEAR_COLOR0, &color, 0.0, 0);
541
542 /* create vertex elements */
543 ve_handle = ctx_handle++;
544 memset(ve, 0, sizeof(ve));
545 ve[0].src_offset = Offset(struct vertex, position);
546 ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
547 ve[1].src_offset = Offset(struct vertex, color);
548 ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
549 virgl_encoder_create_vertex_elements(&ctx, ve_handle, 2, ve);
550
551 virgl_encode_bind_object(&ctx, ve_handle, VIRGL_OBJECT_VERTEX_ELEMENTS);
552
553 /* create vbo */
554 ret = testvirgl_create_backed_simple_buffer(&vbo, 2, sizeof(vertices), PIPE_BIND_VERTEX_BUFFER);
555 ck_assert_int_eq(ret, 0);
556 virgl_renderer_ctx_attach_resource(ctx.ctx_id, vbo.handle);
557
558 /* inline write the data to it */
559 box.x = 0;
560 box.y = 0;
561 box.z = 0;
562 box.w = sizeof(vertices);
563 box.h = 1;
564 box.d = 1;
565 virgl_encoder_inline_write(&ctx, &vbo, 0, 0, (struct pipe_box *)&box, &vertices, box.w, 0);
566
567 vbuf.stride = sizeof(struct vertex);
568 vbuf.buffer_offset = 0;
569 vbuf.buffer = &vbo.base;
570 virgl_encoder_set_vertex_buffers(&ctx, 1, &vbuf);
571
572 /* create vertex shader */
573 {
574 struct pipe_shader_state vs;
575 const char *text =
576 "VERT\n"
577 "DCL IN[0]\n"
578 "DCL IN[1]\n"
579 "DCL OUT[0], POSITION\n"
580 "DCL OUT[1], GENERIC[20]\n"
581 " 0: MOV OUT[1], IN[1]\n"
582 " 1: MOV OUT[0], IN[0]\n"
583 " 2: END\n";
584 memset(&vs, 0, sizeof(vs));
585 vs_handle = ctx_handle++;
586 virgl_encode_shader_state(&ctx, vs_handle, PIPE_SHADER_VERTEX,
587 &vs, text);
588 virgl_encode_bind_shader(&ctx, vs_handle, PIPE_SHADER_VERTEX);
589 }
590
591 /* create geometry shader */
592 {
593 struct pipe_shader_state gs;
594 const char *text =
595 "GEOM\n"
596 "PROPERTY GS_INPUT_PRIMITIVE TRIANGLES\n"
597 "PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP\n"
598 "PROPERTY GS_MAX_OUTPUT_VERTICES 3\n"
599 "PROPERTY GS_INVOCATIONS 1\n"
600 "DCL IN[][0], POSITION\n"
601 "DCL IN[][1], GENERIC[20]\n"
602 "DCL OUT[0], POSITION\n"
603 "DCL OUT[1], GENERIC[20]\n"
604 "IMM[0] INT32 {0, 0, 0, 0}\n"
605 "0:MOV OUT[0], IN[0][0]\n"
606 "1:MOV OUT[1], IN[0][1]\n"
607 "2:EMIT IMM[0].xxxx\n"
608 "3:MOV OUT[0], IN[1][0]\n"
609 "4:MOV OUT[1], IN[0][1]\n" /* copy color from input vertex 0 */
610 "5:EMIT IMM[0].xxxx\n"
611 "6:MOV OUT[0], IN[2][0]\n"
612 "7:MOV OUT[1], IN[2][1]\n"
613 "8:EMIT IMM[0].xxxx\n"
614 "9:END\n";
615 memset(&gs, 0, sizeof(gs));
616 gs_handle = ctx_handle++;
617 virgl_encode_shader_state(&ctx, gs_handle, PIPE_SHADER_GEOMETRY,
618 &gs, text);
619 virgl_encode_bind_shader(&ctx, gs_handle, PIPE_SHADER_GEOMETRY);
620 }
621
622 /* create fragment shader */
623 {
624 struct pipe_shader_state fs;
625 const char *text =
626 "FRAG\n"
627 "DCL IN[0], GENERIC[20], LINEAR\n"
628 "DCL OUT[0], COLOR\n"
629 " 0: MOV OUT[0], IN[0]\n"
630 " 1: END\n";
631 memset(&fs, 0, sizeof(fs));
632 fs_handle = ctx_handle++;
633 virgl_encode_shader_state(&ctx, fs_handle, PIPE_SHADER_FRAGMENT,
634 &fs, text);
635
636 virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT);
637 }
638
639 /* set blend state */
640 {
641 struct pipe_blend_state blend;
642 int blend_handle = ctx_handle++;
643 memset(&blend, 0, sizeof(blend));
644 blend.rt[0].colormask = PIPE_MASK_RGBA;
645 virgl_encode_blend_state(&ctx, blend_handle, &blend);
646 virgl_encode_bind_object(&ctx, blend_handle, VIRGL_OBJECT_BLEND);
647 }
648
649 /* set depth stencil alpha state */
650 {
651 struct pipe_depth_stencil_alpha_state dsa;
652 int dsa_handle = ctx_handle++;
653 memset(&dsa, 0, sizeof(dsa));
654 dsa.depth.writemask = 1;
655 dsa.depth.func = PIPE_FUNC_LESS;
656 virgl_encode_dsa_state(&ctx, dsa_handle, &dsa);
657 virgl_encode_bind_object(&ctx, dsa_handle, VIRGL_OBJECT_DSA);
658 }
659
660 /* set rasterizer state */
661 {
662 struct pipe_rasterizer_state rasterizer;
663 int rs_handle = ctx_handle++;
664 memset(&rasterizer, 0, sizeof(rasterizer));
665 rasterizer.cull_face = PIPE_FACE_NONE;
666 rasterizer.half_pixel_center = 1;
667 rasterizer.bottom_edge_rule = 1;
668 rasterizer.depth_clip = 1;
669 virgl_encode_rasterizer_state(&ctx, rs_handle, &rasterizer);
670 virgl_encode_bind_object(&ctx, rs_handle, VIRGL_OBJECT_RASTERIZER);
671 }
672
673 /* set viewport state */
674 {
675 struct pipe_viewport_state vp;
676 float znear = 0, zfar = 1.0;
677 float half_w = tw / 2.0f;
678 float half_h = th / 2.0f;
679 float half_d = (zfar - znear) / 2.0f;
680
681 vp.scale[0] = half_w;
682 vp.scale[1] = half_h;
683 vp.scale[2] = half_d;
684
685 vp.translate[0] = half_w + 0;
686 vp.translate[1] = half_h + 0;
687 vp.translate[2] = half_d + znear;
688 virgl_encoder_set_viewport_states(&ctx, 0, 1, &vp);
689 }
690
691 /* draw */
692 {
693 struct pipe_draw_info info;
694 memset(&info, 0, sizeof(info));
695 info.count = 3;
696 info.mode = PIPE_PRIM_TRIANGLES;
697 virgl_encoder_draw_vbo(&ctx, &info);
698 }
699
700 virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
701
702 /* create a fence */
703 testvirgl_reset_fence();
704 ret = virgl_renderer_create_fence(1, ctx.ctx_id);
705 ck_assert_int_eq(ret, 0);
706
707 do {
708 int fence;
709
710 virgl_renderer_poll();
711 fence = testvirgl_get_last_fence();
712 if (fence >= 1)
713 break;
714 nanosleep((struct timespec[]){{0, 50000}}, NULL);
715 } while(1);
716
717 /* read back the tri values in the resource */
718 box.x = 0;
719 box.y = 0;
720 box.z = 0;
721 box.w = tw;
722 box.h = th;
723 box.d = 1;
724 ret = virgl_renderer_transfer_read_iov(res.handle, ctx.ctx_id, 0, 0, 0, &box, 0, NULL, 0);
725 ck_assert_int_eq(ret, 0);
726
727 {
728 int w, h;
729 bool all_cleared = true;
730 uint32_t *ptr = res.iovs[0].iov_base;
731 for (h = 0; h < th; h++) {
732 for (w = 0; w < tw; w++) {
733 if (ptr[h * tw + w] != test_green)
734 all_cleared = false;
735 }
736 }
737 ck_assert_int_eq(all_cleared, false);
738 }
739
740 /* cleanup */
741 virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
742
743 testvirgl_destroy_backed_res(&vbo);
744 testvirgl_destroy_backed_res(&res);
745
746 testvirgl_fini_ctx_cmdbuf(&ctx);
747 }
748 END_TEST
749
750 /* create a resource - clear it to a color, render something
751 * and test transform feedback
752 */
START_TEST(virgl_test_render_xfb)753 START_TEST(virgl_test_render_xfb)
754 {
755 struct virgl_context ctx;
756 struct virgl_resource res;
757 struct virgl_resource vbo;
758 struct virgl_resource xfb;
759 struct virgl_surface surf;
760 struct virgl_so_target so_target;
761 struct virgl_so_target *so_target_ptr;
762 struct pipe_framebuffer_state fb_state;
763 struct pipe_vertex_element ve[2];
764 struct pipe_vertex_buffer vbuf;
765 int ve_handle, vs_handle, fs_handle, xfb_handle;
766 int ctx_handle = 1;
767 union pipe_color_union color;
768 struct virgl_box box;
769 int ret;
770 int tw = 300, th = 300;
771
772 ret = testvirgl_init_ctx_cmdbuf(&ctx);
773 ck_assert_int_eq(ret, 0);
774
775 /* init and create simple 2D resource */
776 ret = testvirgl_create_backed_simple_2d_res(&res, 1, tw, th);
777 ck_assert_int_eq(ret, 0);
778
779 /* attach resource to context */
780 virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
781
782 /* create a surface for the resource */
783 memset(&surf, 0, sizeof(surf));
784 surf.base.format = PIPE_FORMAT_B8G8R8X8_UNORM;
785 surf.handle = ctx_handle++;
786 surf.base.texture = &res.base;
787
788 virgl_encoder_create_surface(&ctx, surf.handle, &res, &surf.base);
789
790 /* set the framebuffer state */
791 fb_state.nr_cbufs = 1;
792 fb_state.zsbuf = NULL;
793 fb_state.cbufs[0] = &surf.base;
794 virgl_encoder_set_framebuffer_state(&ctx, &fb_state);
795
796 /* clear the resource */
797 /* clear buffer to green */
798 color.f[0] = 0.0;
799 color.f[1] = 1.0;
800 color.f[2] = 0.0;
801 color.f[3] = 1.0;
802 virgl_encode_clear(&ctx, PIPE_CLEAR_COLOR0, &color, 0.0, 0);
803
804 /* create vertex elements */
805 ve_handle = ctx_handle++;
806 memset(ve, 0, sizeof(ve));
807 ve[0].src_offset = Offset(struct vertex, position);
808 ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
809 ve[1].src_offset = Offset(struct vertex, color);
810 ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
811 virgl_encoder_create_vertex_elements(&ctx, ve_handle, 2, ve);
812
813 virgl_encode_bind_object(&ctx, ve_handle, VIRGL_OBJECT_VERTEX_ELEMENTS);
814
815 /* create vbo */
816 ret = testvirgl_create_backed_simple_buffer(&vbo, 2, sizeof(vertices), PIPE_BIND_VERTEX_BUFFER);
817 ck_assert_int_eq(ret, 0);
818 virgl_renderer_ctx_attach_resource(ctx.ctx_id, vbo.handle);
819
820 /* inline write the data to it */
821 box.x = 0;
822 box.y = 0;
823 box.z = 0;
824 box.w = sizeof(vertices);
825 box.h = 1;
826 box.d = 1;
827 virgl_encoder_inline_write(&ctx, &vbo, 0, 0, (struct pipe_box *)&box, &vertices, box.w, 0);
828
829 vbuf.stride = sizeof(struct vertex);
830 vbuf.buffer_offset = 0;
831 vbuf.buffer = &vbo.base;
832 virgl_encoder_set_vertex_buffers(&ctx, 1, &vbuf);
833
834 /* create stream output buffer */
835 ret = testvirgl_create_backed_simple_buffer(&xfb, 3, 3*sizeof(vertices), PIPE_BIND_STREAM_OUTPUT);
836 ck_assert_int_eq(ret, 0);
837 virgl_renderer_ctx_attach_resource(ctx.ctx_id, xfb.handle);
838
839 /* set streamout target */
840 xfb_handle = ctx_handle++;
841 virgl_encoder_create_so_target(&ctx, xfb_handle, &xfb, 0, 3*sizeof(vertices));
842 so_target.handle = xfb_handle;
843 so_target_ptr = &so_target;
844 virgl_encoder_set_so_targets(&ctx, 1, (struct pipe_stream_output_target **)&so_target_ptr, 0);
845
846 /* create vertex shader */
847 {
848 struct pipe_shader_state vs;
849 const char *text =
850 "VERT\n"
851 "DCL IN[0]\n"
852 "DCL IN[1]\n"
853 "DCL OUT[0], POSITION\n"
854 "DCL OUT[1], COLOR\n"
855 " 0: MOV OUT[1], IN[1]\n"
856 " 1: MOV OUT[0], IN[0]\n"
857 " 2: END\n";
858 memset(&vs, 0, sizeof(vs));
859 vs_handle = ctx_handle++;
860 vs.stream_output.num_outputs = 1;
861 vs.stream_output.stride[0] = 4;
862 vs.stream_output.output[0].num_components = 4;
863 virgl_encode_shader_state(&ctx, vs_handle, PIPE_SHADER_VERTEX,
864 &vs, text);
865 virgl_encode_bind_shader(&ctx, vs_handle, PIPE_SHADER_VERTEX);
866 }
867
868 /* create fragment shader */
869 {
870 struct pipe_shader_state fs;
871 const char *text =
872 "FRAG\n"
873 "DCL IN[0], COLOR, LINEAR\n"
874 "DCL OUT[0], COLOR\n"
875 " 0: MOV OUT[0], IN[0]\n"
876 " 1: END\n";
877 memset(&fs, 0, sizeof(fs));
878 fs_handle = ctx_handle++;
879 virgl_encode_shader_state(&ctx, fs_handle, PIPE_SHADER_FRAGMENT,
880 &fs, text);
881 virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT);
882 }
883
884 /* set blend state */
885 {
886 struct pipe_blend_state blend;
887 int blend_handle = ctx_handle++;
888 memset(&blend, 0, sizeof(blend));
889 blend.rt[0].colormask = PIPE_MASK_RGBA;
890 virgl_encode_blend_state(&ctx, blend_handle, &blend);
891 virgl_encode_bind_object(&ctx, blend_handle, VIRGL_OBJECT_BLEND);
892 }
893
894 /* set depth stencil alpha state */
895 {
896 struct pipe_depth_stencil_alpha_state dsa;
897 int dsa_handle = ctx_handle++;
898 memset(&dsa, 0, sizeof(dsa));
899 dsa.depth.writemask = 1;
900 dsa.depth.func = PIPE_FUNC_LESS;
901 virgl_encode_dsa_state(&ctx, dsa_handle, &dsa);
902 virgl_encode_bind_object(&ctx, dsa_handle, VIRGL_OBJECT_DSA);
903 }
904
905 /* set rasterizer state */
906 {
907 struct pipe_rasterizer_state rasterizer;
908 int rs_handle = ctx_handle++;
909 memset(&rasterizer, 0, sizeof(rasterizer));
910 rasterizer.cull_face = PIPE_FACE_NONE;
911 rasterizer.half_pixel_center = 1;
912 rasterizer.bottom_edge_rule = 1;
913 rasterizer.depth_clip = 1;
914 virgl_encode_rasterizer_state(&ctx, rs_handle, &rasterizer);
915 virgl_encode_bind_object(&ctx, rs_handle, VIRGL_OBJECT_RASTERIZER);
916 }
917
918 /* set viewport state */
919 {
920 struct pipe_viewport_state vp;
921 float znear = 0, zfar = 1.0;
922 float half_w = tw / 2.0f;
923 float half_h = th / 2.0f;
924 float half_d = (zfar - znear) / 2.0f;
925
926 vp.scale[0] = half_w;
927 vp.scale[1] = half_h;
928 vp.scale[2] = half_d;
929
930 vp.translate[0] = half_w + 0;
931 vp.translate[1] = half_h + 0;
932 vp.translate[2] = half_d + znear;
933 virgl_encoder_set_viewport_states(&ctx, 0, 1, &vp);
934 }
935
936 /* draw */
937 {
938 struct pipe_draw_info info;
939 memset(&info, 0, sizeof(info));
940 info.count = 3;
941 info.mode = PIPE_PRIM_TRIANGLES;
942 virgl_encoder_draw_vbo(&ctx, &info);
943 }
944
945 virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
946
947 /* create a fence */
948 testvirgl_reset_fence();
949 ret = virgl_renderer_create_fence(1, ctx.ctx_id);
950 ck_assert_int_eq(ret, 0);
951
952 do {
953 int fence;
954
955 virgl_renderer_poll();
956 fence = testvirgl_get_last_fence();
957 if (fence >= 1)
958 break;
959 nanosleep((struct timespec[]){{0, 50000}}, NULL);
960 } while(1);
961
962 /* read back the tri values in the resource */
963 box.x = 0;
964 box.y = 0;
965 box.z = 0;
966 box.w = tw;
967 box.h = th;
968 box.d = 1;
969 ret = virgl_renderer_transfer_read_iov(res.handle, ctx.ctx_id, 0, 0, 0, &box, 0, NULL, 0);
970 ck_assert_int_eq(ret, 0);
971
972 {
973 int w, h;
974 bool all_cleared = true;
975 uint32_t *ptr = res.iovs[0].iov_base;
976 for (h = 0; h < th; h++) {
977 for (w = 0; w < tw; w++) {
978 if (ptr[h * tw + w] != test_green)
979 all_cleared = false;
980 }
981 }
982 ck_assert_int_eq(all_cleared, false);
983 }
984
985 /* cleanup */
986 virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
987
988 testvirgl_destroy_backed_res(&xfb);
989 testvirgl_destroy_backed_res(&vbo);
990 testvirgl_destroy_backed_res(&res);
991
992 testvirgl_fini_ctx_cmdbuf(&ctx);
993 }
994 END_TEST
995
996 /* send a large shader across */
START_TEST(virgl_test_large_shader)997 START_TEST(virgl_test_large_shader)
998 {
999 int ret;
1000 struct virgl_context ctx;
1001 int ctx_handle = 1;
1002 int fs_handle;
1003 ret = testvirgl_init_ctx_cmdbuf(&ctx);
1004 ck_assert_int_eq(ret, 0);
1005
1006 /* create large fragment shader */
1007 {
1008 struct pipe_shader_state fs;
1009 const char *text = large_frag;
1010
1011 memset(&fs, 0, sizeof(fs));
1012 fs_handle = ctx_handle++;
1013 virgl_encode_shader_state(&ctx, fs_handle, PIPE_SHADER_FRAGMENT,
1014 &fs, text);
1015
1016 virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT);
1017 }
1018
1019 testvirgl_fini_ctx_cmdbuf(&ctx);
1020 }
1021 END_TEST
1022
virgl_init_suite(void)1023 static Suite *virgl_init_suite(void)
1024 {
1025 Suite *s;
1026 TCase *tc_core;
1027
1028 s = suite_create("virgl_clear");
1029 tc_core = tcase_create("clear");
1030 tcase_add_test(tc_core, virgl_test_clear);
1031 tcase_add_test(tc_core, virgl_test_blit_simple);
1032 tcase_add_test(tc_core, virgl_test_overlap_obj_id);
1033 tcase_add_test(tc_core, virgl_test_large_shader);
1034 tcase_add_test(tc_core, virgl_test_render_simple);
1035 tcase_add_test(tc_core, virgl_test_render_geom_simple);
1036 tcase_add_test(tc_core, virgl_test_render_xfb);
1037
1038 suite_add_tcase(s, tc_core);
1039 return s;
1040
1041 }
1042
main(void)1043 int main(void)
1044 {
1045 Suite *s;
1046 SRunner *sr;
1047 int number_failed;
1048
1049 if (getenv("VRENDTEST_USE_EGL_SURFACELESS"))
1050 context_flags |= VIRGL_RENDERER_USE_SURFACELESS;
1051 if (getenv("VRENDTEST_USE_EGL_GLES"))
1052 context_flags |= VIRGL_RENDERER_USE_GLES;
1053
1054 s = virgl_init_suite();
1055 sr = srunner_create(s);
1056
1057 srunner_run_all(sr, CK_NORMAL);
1058 number_failed = srunner_ntests_failed(sr);
1059 srunner_free(sr);
1060
1061 return number_failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1062 }
1063