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