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