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