xref: /aosp_15_r20/external/virglrenderer/tests/test_virgl_cmd.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
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 #if UTIL_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     /* link shader */
376     {
377         uint32_t handles[PIPE_SHADER_TYPES];
378         memset(handles, 0, sizeof(handles));
379         handles[PIPE_SHADER_VERTEX] = vs_handle;
380         handles[PIPE_SHADER_FRAGMENT] = fs_handle;
381         virgl_encode_link_shader(&ctx, handles);
382     }
383 
384     /* set blend state */
385     {
386 	struct pipe_blend_state blend;
387 	int blend_handle = ctx_handle++;
388 	memset(&blend, 0, sizeof(blend));
389 	blend.rt[0].colormask = PIPE_MASK_RGBA;
390 	virgl_encode_blend_state(&ctx, blend_handle, &blend);
391 	virgl_encode_bind_object(&ctx, blend_handle, VIRGL_OBJECT_BLEND);
392     }
393 
394     /* set depth stencil alpha state */
395     {
396 	struct pipe_depth_stencil_alpha_state dsa;
397 	int dsa_handle = ctx_handle++;
398 	memset(&dsa, 0, sizeof(dsa));
399 	dsa.depth.writemask = 1;
400 	dsa.depth.func = PIPE_FUNC_LESS;
401 	virgl_encode_dsa_state(&ctx, dsa_handle, &dsa);
402 	virgl_encode_bind_object(&ctx, dsa_handle, VIRGL_OBJECT_DSA);
403     }
404 
405     /* set rasterizer state */
406     {
407 	struct pipe_rasterizer_state rasterizer;
408 	int rs_handle = ctx_handle++;
409 	memset(&rasterizer, 0, sizeof(rasterizer));
410 	rasterizer.cull_face = PIPE_FACE_NONE;
411 	rasterizer.half_pixel_center = 1;
412 	rasterizer.bottom_edge_rule = 1;
413 	rasterizer.depth_clip = 1;
414 	virgl_encode_rasterizer_state(&ctx, rs_handle, &rasterizer);
415 	virgl_encode_bind_object(&ctx, rs_handle, VIRGL_OBJECT_RASTERIZER);
416     }
417 
418     /* set viewport state */
419     {
420 	struct pipe_viewport_state vp;
421 	float znear = 0, zfar = 1.0;
422 	float half_w = tw / 2.0f;
423 	float half_h = th / 2.0f;
424 	float half_d = (zfar - znear) / 2.0f;
425 
426 	vp.scale[0] = half_w;
427 	vp.scale[1] = half_h;
428 	vp.scale[2] = half_d;
429 
430 	vp.translate[0] = half_w + 0;
431 	vp.translate[1] = half_h + 0;
432 	vp.translate[2] = half_d + znear;
433 	virgl_encoder_set_viewport_states(&ctx, 0, 1, &vp);
434     }
435 
436     /* draw */
437     {
438 	struct pipe_draw_info info;
439 	memset(&info, 0, sizeof(info));
440 	info.count = 3;
441 	info.mode = PIPE_PRIM_TRIANGLES;
442 	virgl_encoder_draw_vbo(&ctx, &info);
443     }
444 
445     virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
446 
447     /* create a fence */
448     testvirgl_reset_fence();
449     ret = virgl_renderer_create_fence(1, ctx.ctx_id);
450     ck_assert_int_eq(ret, 0);
451 
452     do {
453 	int fence;
454 
455 	virgl_renderer_poll();
456 	fence = testvirgl_get_last_fence();
457 	if (fence >= 1)
458 	    break;
459 	nanosleep((struct timespec[]){{0, 50000}}, NULL);
460     } while(1);
461 
462     /* read back the tri values in the resource */
463     box.x = 0;
464     box.y = 0;
465     box.z = 0;
466     box.w = tw;
467     box.h = th;
468     box.d = 1;
469     ret = virgl_renderer_transfer_read_iov(res.handle, ctx.ctx_id, 0, 0, 0, &box, 0, NULL, 0);
470     ck_assert_int_eq(ret, 0);
471 
472     {
473 	int w, h;
474 	bool all_cleared = true;
475 	uint32_t *ptr = res.iovs[0].iov_base;
476 	for (h = 0; h < th; h++) {
477 	    for (w = 0; w < tw; w++) {
478 		if (ptr[h * tw + w] != test_green)
479 		    all_cleared = false;
480 	    }
481 	}
482 	ck_assert_int_eq(all_cleared, false);
483     }
484 
485     /* cleanup */
486     virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
487 
488     testvirgl_destroy_backed_res(&vbo);
489     testvirgl_destroy_backed_res(&res);
490 
491     testvirgl_fini_ctx_cmdbuf(&ctx);
492 }
493 END_TEST
494 
495 /* create a resource - clear it to a color, render something */
START_TEST(virgl_test_render_geom_simple)496 START_TEST(virgl_test_render_geom_simple)
497 {
498     struct virgl_context ctx;
499     struct virgl_resource res;
500     struct virgl_resource vbo;
501     struct virgl_surface surf;
502     struct pipe_framebuffer_state fb_state;
503     struct pipe_vertex_element ve[2];
504     struct pipe_vertex_buffer vbuf;
505     int ve_handle, vs_handle, fs_handle, gs_handle;
506     int ctx_handle = 1;
507     union pipe_color_union color;
508     struct virgl_box box;
509     int ret;
510     int tw = 300, th = 300;
511 
512     ret = testvirgl_init_ctx_cmdbuf(&ctx);
513     ck_assert_int_eq(ret, 0);
514 
515     /* Geometry shader are only available since GLSL 150 */
516     uint32_t glsl_level = testvirgl_get_glsl_level_from_caps();
517     if (glsl_level < 150) {
518       testvirgl_fini_ctx_cmdbuf(&ctx);
519       return;
520     }
521 
522     /* init and create simple 2D resource */
523     ret = testvirgl_create_backed_simple_2d_res(&res, 1, tw, th);
524     ck_assert_int_eq(ret, 0);
525 
526     /* attach resource to context */
527     virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
528 
529     /* create a surface for the resource */
530     memset(&surf, 0, sizeof(surf));
531     surf.base.format = PIPE_FORMAT_B8G8R8X8_UNORM;
532     surf.handle = ctx_handle++;
533     surf.base.texture = &res.base;
534 
535     virgl_encoder_create_surface(&ctx, surf.handle, &res, &surf.base);
536 
537     /* set the framebuffer state */
538     fb_state.nr_cbufs = 1;
539     fb_state.zsbuf = NULL;
540     fb_state.cbufs[0] = &surf.base;
541     virgl_encoder_set_framebuffer_state(&ctx, &fb_state);
542 
543     /* clear the resource */
544     /* clear buffer to green */
545     color.f[0] = 0.0;
546     color.f[1] = 1.0;
547     color.f[2] = 0.0;
548     color.f[3] = 1.0;
549     virgl_encode_clear(&ctx, PIPE_CLEAR_COLOR0, &color, 0.0, 0);
550 
551     /* create vertex elements */
552     ve_handle = ctx_handle++;
553     memset(ve, 0, sizeof(ve));
554     ve[0].src_offset = Offset(struct vertex, position);
555     ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
556     ve[1].src_offset = Offset(struct vertex, color);
557     ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
558     virgl_encoder_create_vertex_elements(&ctx, ve_handle, 2, ve);
559 
560     virgl_encode_bind_object(&ctx, ve_handle, VIRGL_OBJECT_VERTEX_ELEMENTS);
561 
562     /* create vbo */
563     ret = testvirgl_create_backed_simple_buffer(&vbo, 2, sizeof(vertices), PIPE_BIND_VERTEX_BUFFER);
564     ck_assert_int_eq(ret, 0);
565     virgl_renderer_ctx_attach_resource(ctx.ctx_id, vbo.handle);
566 
567     /* inline write the data to it */
568     box.x = 0;
569     box.y = 0;
570     box.z = 0;
571     box.w = sizeof(vertices);
572     box.h = 1;
573     box.d = 1;
574     virgl_encoder_inline_write(&ctx, &vbo, 0, 0, (struct pipe_box *)&box, &vertices, box.w, 0);
575 
576     vbuf.stride = sizeof(struct vertex);
577     vbuf.buffer_offset = 0;
578     vbuf.buffer = &vbo.base;
579     virgl_encoder_set_vertex_buffers(&ctx, 1, &vbuf);
580 
581     /* create vertex shader */
582     {
583 	struct pipe_shader_state vs;
584          const char *text =
585 	   "VERT\n"
586 	   "DCL IN[0]\n"
587 	   "DCL IN[1]\n"
588 	   "DCL OUT[0], POSITION\n"
589 	   "DCL OUT[1], GENERIC[20]\n"
590 	   "  0: MOV OUT[1], IN[1]\n"
591 	   "  1: MOV OUT[0], IN[0]\n"
592 	   "  2: END\n";
593 	 memset(&vs, 0, sizeof(vs));
594 	 vs_handle = ctx_handle++;
595 	 virgl_encode_shader_state(&ctx, vs_handle, PIPE_SHADER_VERTEX,
596 				   &vs, text);
597          virgl_encode_bind_shader(&ctx, vs_handle, PIPE_SHADER_VERTEX);
598     }
599 
600     /* create geometry shader */
601     {
602 	struct pipe_shader_state gs;
603          const char *text =
604 	   "GEOM\n"
605 	   "PROPERTY GS_INPUT_PRIMITIVE TRIANGLES\n"
606 	   "PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP\n"
607 	   "PROPERTY GS_MAX_OUTPUT_VERTICES 3\n"
608 	   "PROPERTY GS_INVOCATIONS 1\n"
609 	   "DCL IN[][0], POSITION\n"
610 	   "DCL IN[][1], GENERIC[20]\n"
611 	   "DCL OUT[0], POSITION\n"
612 	   "DCL OUT[1], GENERIC[20]\n"
613 	   "IMM[0] INT32 {0, 0, 0, 0}\n"
614 	   "0:MOV OUT[0], IN[0][0]\n"
615 	   "1:MOV OUT[1], IN[0][1]\n"
616 	   "2:EMIT IMM[0].xxxx\n"
617 	   "3:MOV OUT[0], IN[1][0]\n"
618 	   "4:MOV OUT[1], IN[0][1]\n" /* copy color from input vertex 0 */
619 	   "5:EMIT IMM[0].xxxx\n"
620 	   "6:MOV OUT[0], IN[2][0]\n"
621 	   "7:MOV OUT[1], IN[2][1]\n"
622 	   "8:EMIT IMM[0].xxxx\n"
623 	   "9:END\n";
624 	 memset(&gs, 0, sizeof(gs));
625 	 gs_handle = ctx_handle++;
626 	 virgl_encode_shader_state(&ctx, gs_handle, PIPE_SHADER_GEOMETRY,
627 				   &gs, text);
628          virgl_encode_bind_shader(&ctx, gs_handle, PIPE_SHADER_GEOMETRY);
629     }
630 
631     /* create fragment shader */
632     {
633 	struct pipe_shader_state fs;
634 	const char *text =
635 	    "FRAG\n"
636 	    "DCL IN[0], GENERIC[20], LINEAR\n"
637 	    "DCL OUT[0], COLOR\n"
638 	    "  0: MOV OUT[0], IN[0]\n"
639 	    "  1: END\n";
640 	memset(&fs, 0, sizeof(fs));
641 	fs_handle = ctx_handle++;
642 	virgl_encode_shader_state(&ctx, fs_handle, PIPE_SHADER_FRAGMENT,
643 				   &fs, text);
644 
645         virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT);
646     }
647 
648     /* set blend state */
649     {
650 	struct pipe_blend_state blend;
651 	int blend_handle = ctx_handle++;
652 	memset(&blend, 0, sizeof(blend));
653 	blend.rt[0].colormask = PIPE_MASK_RGBA;
654 	virgl_encode_blend_state(&ctx, blend_handle, &blend);
655 	virgl_encode_bind_object(&ctx, blend_handle, VIRGL_OBJECT_BLEND);
656     }
657 
658     /* set depth stencil alpha state */
659     {
660 	struct pipe_depth_stencil_alpha_state dsa;
661 	int dsa_handle = ctx_handle++;
662 	memset(&dsa, 0, sizeof(dsa));
663 	dsa.depth.writemask = 1;
664 	dsa.depth.func = PIPE_FUNC_LESS;
665 	virgl_encode_dsa_state(&ctx, dsa_handle, &dsa);
666 	virgl_encode_bind_object(&ctx, dsa_handle, VIRGL_OBJECT_DSA);
667     }
668 
669     /* set rasterizer state */
670     {
671 	struct pipe_rasterizer_state rasterizer;
672 	int rs_handle = ctx_handle++;
673 	memset(&rasterizer, 0, sizeof(rasterizer));
674 	rasterizer.cull_face = PIPE_FACE_NONE;
675 	rasterizer.half_pixel_center = 1;
676 	rasterizer.bottom_edge_rule = 1;
677 	rasterizer.depth_clip = 1;
678 	virgl_encode_rasterizer_state(&ctx, rs_handle, &rasterizer);
679 	virgl_encode_bind_object(&ctx, rs_handle, VIRGL_OBJECT_RASTERIZER);
680     }
681 
682     /* set viewport state */
683     {
684 	struct pipe_viewport_state vp;
685 	float znear = 0, zfar = 1.0;
686 	float half_w = tw / 2.0f;
687 	float half_h = th / 2.0f;
688 	float half_d = (zfar - znear) / 2.0f;
689 
690 	vp.scale[0] = half_w;
691 	vp.scale[1] = half_h;
692 	vp.scale[2] = half_d;
693 
694 	vp.translate[0] = half_w + 0;
695 	vp.translate[1] = half_h + 0;
696 	vp.translate[2] = half_d + znear;
697 	virgl_encoder_set_viewport_states(&ctx, 0, 1, &vp);
698     }
699 
700     /* draw */
701     {
702 	struct pipe_draw_info info;
703 	memset(&info, 0, sizeof(info));
704 	info.count = 3;
705 	info.mode = PIPE_PRIM_TRIANGLES;
706 	virgl_encoder_draw_vbo(&ctx, &info);
707     }
708 
709     virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
710 
711     /* create a fence */
712     testvirgl_reset_fence();
713     ret = virgl_renderer_create_fence(1, ctx.ctx_id);
714     ck_assert_int_eq(ret, 0);
715 
716     do {
717 	int fence;
718 
719 	virgl_renderer_poll();
720 	fence = testvirgl_get_last_fence();
721 	if (fence >= 1)
722 	    break;
723 	nanosleep((struct timespec[]){{0, 50000}}, NULL);
724     } while(1);
725 
726     /* read back the tri values in the resource */
727     box.x = 0;
728     box.y = 0;
729     box.z = 0;
730     box.w = tw;
731     box.h = th;
732     box.d = 1;
733     ret = virgl_renderer_transfer_read_iov(res.handle, ctx.ctx_id, 0, 0, 0, &box, 0, NULL, 0);
734     ck_assert_int_eq(ret, 0);
735 
736     {
737 	int w, h;
738 	bool all_cleared = true;
739 	uint32_t *ptr = res.iovs[0].iov_base;
740 	for (h = 0; h < th; h++) {
741 	    for (w = 0; w < tw; w++) {
742 		if (ptr[h * tw + w] != test_green)
743 		    all_cleared = false;
744 	    }
745 	}
746 	ck_assert_int_eq(all_cleared, false);
747     }
748 
749     /* cleanup */
750     virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
751 
752     testvirgl_destroy_backed_res(&vbo);
753     testvirgl_destroy_backed_res(&res);
754 
755     testvirgl_fini_ctx_cmdbuf(&ctx);
756 }
757 END_TEST
758 
759 /* create a resource - clear it to a color, render something
760  * and test transform feedback
761  */
START_TEST(virgl_test_render_xfb)762 START_TEST(virgl_test_render_xfb)
763 {
764     struct virgl_context ctx;
765     struct virgl_resource res;
766     struct virgl_resource vbo;
767     struct virgl_resource xfb;
768     struct virgl_surface surf;
769     struct virgl_so_target so_target;
770     struct virgl_so_target *so_target_ptr;
771     struct pipe_framebuffer_state fb_state;
772     struct pipe_vertex_element ve[2];
773     struct pipe_vertex_buffer vbuf;
774     int ve_handle, vs_handle, fs_handle, xfb_handle;
775     int ctx_handle = 1;
776     union pipe_color_union color;
777     struct virgl_box box;
778     int ret;
779     int tw = 300, th = 300;
780 
781     ret = testvirgl_init_ctx_cmdbuf(&ctx);
782     ck_assert_int_eq(ret, 0);
783 
784     /* init and create simple 2D resource */
785     ret = testvirgl_create_backed_simple_2d_res(&res, 1, tw, th);
786     ck_assert_int_eq(ret, 0);
787 
788     /* attach resource to context */
789     virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
790 
791     /* create a surface for the resource */
792     memset(&surf, 0, sizeof(surf));
793     surf.base.format = PIPE_FORMAT_B8G8R8X8_UNORM;
794     surf.handle = ctx_handle++;
795     surf.base.texture = &res.base;
796 
797     virgl_encoder_create_surface(&ctx, surf.handle, &res, &surf.base);
798 
799     /* set the framebuffer state */
800     fb_state.nr_cbufs = 1;
801     fb_state.zsbuf = NULL;
802     fb_state.cbufs[0] = &surf.base;
803     virgl_encoder_set_framebuffer_state(&ctx, &fb_state);
804 
805     /* clear the resource */
806     /* clear buffer to green */
807     color.f[0] = 0.0;
808     color.f[1] = 1.0;
809     color.f[2] = 0.0;
810     color.f[3] = 1.0;
811     virgl_encode_clear(&ctx, PIPE_CLEAR_COLOR0, &color, 0.0, 0);
812 
813     /* create vertex elements */
814     ve_handle = ctx_handle++;
815     memset(ve, 0, sizeof(ve));
816     ve[0].src_offset = Offset(struct vertex, position);
817     ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
818     ve[1].src_offset = Offset(struct vertex, color);
819     ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
820     virgl_encoder_create_vertex_elements(&ctx, ve_handle, 2, ve);
821 
822     virgl_encode_bind_object(&ctx, ve_handle, VIRGL_OBJECT_VERTEX_ELEMENTS);
823 
824     /* create vbo */
825     ret = testvirgl_create_backed_simple_buffer(&vbo, 2, sizeof(vertices), PIPE_BIND_VERTEX_BUFFER);
826     ck_assert_int_eq(ret, 0);
827     virgl_renderer_ctx_attach_resource(ctx.ctx_id, vbo.handle);
828 
829     /* inline write the data to it */
830     box.x = 0;
831     box.y = 0;
832     box.z = 0;
833     box.w = sizeof(vertices);
834     box.h = 1;
835     box.d = 1;
836     virgl_encoder_inline_write(&ctx, &vbo, 0, 0, (struct pipe_box *)&box, &vertices, box.w, 0);
837 
838     vbuf.stride = sizeof(struct vertex);
839     vbuf.buffer_offset = 0;
840     vbuf.buffer = &vbo.base;
841     virgl_encoder_set_vertex_buffers(&ctx, 1, &vbuf);
842 
843     /* create stream output buffer */
844     ret = testvirgl_create_backed_simple_buffer(&xfb, 3, 3*sizeof(vertices), PIPE_BIND_STREAM_OUTPUT);
845     ck_assert_int_eq(ret, 0);
846     virgl_renderer_ctx_attach_resource(ctx.ctx_id, xfb.handle);
847 
848     /* set streamout target */
849     xfb_handle = ctx_handle++;
850     virgl_encoder_create_so_target(&ctx, xfb_handle, &xfb, 0, 3*sizeof(vertices));
851     so_target.handle = xfb_handle;
852     so_target_ptr = &so_target;
853     virgl_encoder_set_so_targets(&ctx, 1, (struct pipe_stream_output_target **)&so_target_ptr, 0);
854 
855     /* create vertex shader */
856     {
857 	struct pipe_shader_state vs;
858          const char *text =
859 	   "VERT\n"
860 	   "DCL IN[0]\n"
861 	   "DCL IN[1]\n"
862 	   "DCL OUT[0], POSITION\n"
863 	   "DCL OUT[1], COLOR\n"
864 	   "  0: MOV OUT[1], IN[1]\n"
865 	   "  1: MOV OUT[0], IN[0]\n"
866 	   "  2: END\n";
867 	 memset(&vs, 0, sizeof(vs));
868 	 vs_handle = ctx_handle++;
869 	 vs.stream_output.num_outputs = 1;
870 	 vs.stream_output.stride[0] = 4;
871 	 vs.stream_output.output[0].num_components = 4;
872 	 virgl_encode_shader_state(&ctx, vs_handle, PIPE_SHADER_VERTEX,
873 				   &vs, text);
874          virgl_encode_bind_shader(&ctx, vs_handle, PIPE_SHADER_VERTEX);
875     }
876 
877     /* create fragment shader */
878     {
879 	struct pipe_shader_state fs;
880 	const char *text =
881 	    "FRAG\n"
882 	    "DCL IN[0], COLOR, LINEAR\n"
883 	    "DCL OUT[0], COLOR\n"
884 	    "  0: MOV OUT[0], IN[0]\n"
885 	    "  1: END\n";
886 	memset(&fs, 0, sizeof(fs));
887 	fs_handle = ctx_handle++;
888 	virgl_encode_shader_state(&ctx, fs_handle, PIPE_SHADER_FRAGMENT,
889 				   &fs, text);
890         virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT);
891     }
892 
893     /* set blend state */
894     {
895 	struct pipe_blend_state blend;
896 	int blend_handle = ctx_handle++;
897 	memset(&blend, 0, sizeof(blend));
898 	blend.rt[0].colormask = PIPE_MASK_RGBA;
899 	virgl_encode_blend_state(&ctx, blend_handle, &blend);
900 	virgl_encode_bind_object(&ctx, blend_handle, VIRGL_OBJECT_BLEND);
901     }
902 
903     /* set depth stencil alpha state */
904     {
905 	struct pipe_depth_stencil_alpha_state dsa;
906 	int dsa_handle = ctx_handle++;
907 	memset(&dsa, 0, sizeof(dsa));
908 	dsa.depth.writemask = 1;
909 	dsa.depth.func = PIPE_FUNC_LESS;
910 	virgl_encode_dsa_state(&ctx, dsa_handle, &dsa);
911 	virgl_encode_bind_object(&ctx, dsa_handle, VIRGL_OBJECT_DSA);
912     }
913 
914     /* set rasterizer state */
915     {
916 	struct pipe_rasterizer_state rasterizer;
917 	int rs_handle = ctx_handle++;
918 	memset(&rasterizer, 0, sizeof(rasterizer));
919 	rasterizer.cull_face = PIPE_FACE_NONE;
920 	rasterizer.half_pixel_center = 1;
921 	rasterizer.bottom_edge_rule = 1;
922 	rasterizer.depth_clip = 1;
923 	virgl_encode_rasterizer_state(&ctx, rs_handle, &rasterizer);
924 	virgl_encode_bind_object(&ctx, rs_handle, VIRGL_OBJECT_RASTERIZER);
925     }
926 
927     /* set viewport state */
928     {
929 	struct pipe_viewport_state vp;
930 	float znear = 0, zfar = 1.0;
931 	float half_w = tw / 2.0f;
932 	float half_h = th / 2.0f;
933 	float half_d = (zfar - znear) / 2.0f;
934 
935 	vp.scale[0] = half_w;
936 	vp.scale[1] = half_h;
937 	vp.scale[2] = half_d;
938 
939 	vp.translate[0] = half_w + 0;
940 	vp.translate[1] = half_h + 0;
941 	vp.translate[2] = half_d + znear;
942 	virgl_encoder_set_viewport_states(&ctx, 0, 1, &vp);
943     }
944 
945     /* draw */
946     {
947 	struct pipe_draw_info info;
948 	memset(&info, 0, sizeof(info));
949 	info.count = 3;
950 	info.mode = PIPE_PRIM_TRIANGLES;
951 	virgl_encoder_draw_vbo(&ctx, &info);
952     }
953 
954     virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw);
955 
956     /* create a fence */
957     testvirgl_reset_fence();
958     ret = virgl_renderer_create_fence(1, ctx.ctx_id);
959     ck_assert_int_eq(ret, 0);
960 
961     do {
962 	int fence;
963 
964 	virgl_renderer_poll();
965 	fence = testvirgl_get_last_fence();
966 	if (fence >= 1)
967 	    break;
968 	nanosleep((struct timespec[]){{0, 50000}}, NULL);
969     } while(1);
970 
971     /* read back the tri values in the resource */
972     box.x = 0;
973     box.y = 0;
974     box.z = 0;
975     box.w = tw;
976     box.h = th;
977     box.d = 1;
978     ret = virgl_renderer_transfer_read_iov(res.handle, ctx.ctx_id, 0, 0, 0, &box, 0, NULL, 0);
979     ck_assert_int_eq(ret, 0);
980 
981     {
982 	int w, h;
983 	bool all_cleared = true;
984 	uint32_t *ptr = res.iovs[0].iov_base;
985 	for (h = 0; h < th; h++) {
986 	    for (w = 0; w < tw; w++) {
987 		if (ptr[h * tw + w] != test_green)
988 		    all_cleared = false;
989 	    }
990 	}
991 	ck_assert_int_eq(all_cleared, false);
992     }
993 
994     /* cleanup */
995     virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle);
996 
997     testvirgl_destroy_backed_res(&xfb);
998     testvirgl_destroy_backed_res(&vbo);
999     testvirgl_destroy_backed_res(&res);
1000 
1001     testvirgl_fini_ctx_cmdbuf(&ctx);
1002 }
1003 END_TEST
1004 
1005 /* send a large shader across */
START_TEST(virgl_test_large_shader)1006 START_TEST(virgl_test_large_shader)
1007 {
1008    int ret;
1009    struct virgl_context ctx;
1010    int ctx_handle = 1;
1011    int fs_handle;
1012    ret = testvirgl_init_ctx_cmdbuf(&ctx);
1013    ck_assert_int_eq(ret, 0);
1014 
1015    /* create large fragment shader */
1016    {
1017       struct pipe_shader_state fs;
1018       const char *text = large_frag;
1019 
1020       memset(&fs, 0, sizeof(fs));
1021       fs_handle = ctx_handle++;
1022       virgl_encode_shader_state(&ctx, fs_handle, PIPE_SHADER_FRAGMENT,
1023                                 &fs, text);
1024 
1025       virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT);
1026    }
1027 
1028    testvirgl_fini_ctx_cmdbuf(&ctx);
1029 }
1030 END_TEST
1031 
virgl_init_suite(void)1032 static Suite *virgl_init_suite(void)
1033 {
1034   Suite *s;
1035   TCase *tc_core;
1036 
1037   s = suite_create("virgl_clear");
1038   tc_core = tcase_create("clear");
1039   tcase_add_test(tc_core, virgl_test_clear);
1040   tcase_add_test(tc_core, virgl_test_blit_simple);
1041   tcase_add_test(tc_core, virgl_test_overlap_obj_id);
1042   tcase_add_test(tc_core, virgl_test_large_shader);
1043   tcase_add_test(tc_core, virgl_test_render_simple);
1044   tcase_add_test(tc_core, virgl_test_render_geom_simple);
1045   tcase_add_test(tc_core, virgl_test_render_xfb);
1046 
1047   suite_add_tcase(s, tc_core);
1048   return s;
1049 
1050 }
1051 
main(void)1052 int main(void)
1053 {
1054   Suite *s;
1055   SRunner *sr;
1056   int number_failed;
1057 
1058   if (getenv("VRENDTEST_USE_EGL_SURFACELESS"))
1059      context_flags |= VIRGL_RENDERER_USE_SURFACELESS;
1060    if (getenv("VRENDTEST_USE_EGL_GLES"))
1061       context_flags |= VIRGL_RENDERER_USE_GLES;
1062 
1063   s = virgl_init_suite();
1064   sr = srunner_create(s);
1065 
1066   srunner_run_all(sr, CK_NORMAL);
1067   number_failed = srunner_ntests_failed(sr);
1068   srunner_free(sr);
1069 
1070   return number_failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1071 }
1072