• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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