diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_virgl_cmd.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/tests/test_virgl_cmd.c b/tests/test_virgl_cmd.c index 86d980e..d317327 100644 --- a/tests/test_virgl_cmd.c +++ b/tests/test_virgl_cmd.c @@ -731,6 +731,252 @@ START_TEST(virgl_test_render_geom_simple) } END_TEST +/* create a resource - clear it to a color, render something + * and test transform feedback + */ +START_TEST(virgl_test_render_xfb) +{ + struct virgl_context ctx; + struct virgl_resource res; + struct virgl_resource vbo; + struct virgl_resource xfb; + struct virgl_surface surf; + struct virgl_so_target so_target; + struct virgl_so_target *so_target_ptr; + struct pipe_framebuffer_state fb_state; + struct pipe_vertex_element ve[2]; + struct pipe_vertex_buffer vbuf; + int ve_handle, vs_handle, fs_handle, xfb_handle; + int ctx_handle = 1; + union pipe_color_union color; + struct virgl_box box; + int ret; + int tw = 300, th = 300; + + ret = testvirgl_init_ctx_cmdbuf(&ctx); + ck_assert_int_eq(ret, 0); + + /* init and create simple 2D resource */ + ret = testvirgl_create_backed_simple_2d_res(&res, 1, tw, th); + ck_assert_int_eq(ret, 0); + + /* attach resource to context */ + virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle); + + /* create a surface for the resource */ + memset(&surf, 0, sizeof(surf)); + surf.base.format = PIPE_FORMAT_B8G8R8X8_UNORM; + surf.handle = ctx_handle++; + surf.base.texture = &res.base; + + virgl_encoder_create_surface(&ctx, surf.handle, &res, &surf.base); + + /* set the framebuffer state */ + fb_state.nr_cbufs = 1; + fb_state.zsbuf = NULL; + fb_state.cbufs[0] = &surf.base; + virgl_encoder_set_framebuffer_state(&ctx, &fb_state); + + /* clear the resource */ + /* clear buffer to green */ + color.f[0] = 0.0; + color.f[1] = 1.0; + color.f[2] = 0.0; + color.f[3] = 1.0; + virgl_encode_clear(&ctx, PIPE_CLEAR_COLOR0, &color, 0.0, 0); + + /* create vertex elements */ + ve_handle = ctx_handle++; + memset(ve, 0, sizeof(ve)); + ve[0].src_offset = Offset(struct vertex, position); + ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + ve[1].src_offset = Offset(struct vertex, color); + ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + virgl_encoder_create_vertex_elements(&ctx, ve_handle, 2, ve); + + virgl_encode_bind_object(&ctx, ve_handle, VIRGL_OBJECT_VERTEX_ELEMENTS); + + /* create vbo */ + ret = testvirgl_create_backed_simple_buffer(&vbo, 2, sizeof(vertices), PIPE_BIND_VERTEX_BUFFER); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, vbo.handle); + + /* inline write the data to it */ + box.x = 0; + box.y = 0; + box.z = 0; + box.w = sizeof(vertices); + box.h = 1; + box.d = 1; + virgl_encoder_inline_write(&ctx, &vbo, 0, 0, (struct pipe_box *)&box, &vertices, box.w, 0); + + vbuf.stride = sizeof(struct vertex); + vbuf.buffer_offset = 0; + vbuf.buffer = &vbo.base; + virgl_encoder_set_vertex_buffers(&ctx, 1, &vbuf); + + /* create stream output buffer */ + ret = testvirgl_create_backed_simple_buffer(&xfb, 3, 3*sizeof(vertices), PIPE_BIND_STREAM_OUTPUT); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, xfb.handle); + + /* set streamout target */ + xfb_handle = ctx_handle++; + virgl_encoder_create_so_target(&ctx, xfb_handle, &xfb, 0, 3*sizeof(vertices)); + so_target.handle = xfb_handle; + so_target_ptr = &so_target; + virgl_encoder_set_so_targets(&ctx, 1, (struct pipe_stream_output_target **)&so_target_ptr, 0); + + /* create vertex shader */ + { + struct pipe_shader_state vs; + const char *text = + "VERT\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], COLOR\n" + " 0: MOV OUT[1], IN[1]\n" + " 1: MOV OUT[0], IN[0]\n" + " 2: END\n"; + memset(&vs, 0, sizeof(vs)); + vs_handle = ctx_handle++; + vs.stream_output.num_outputs = 1; + vs.stream_output.stride[0] = 4; + vs.stream_output.output[0].num_components = 4; + virgl_encode_shader_state(&ctx, vs_handle, VIRGL_OBJECT_VS, + &vs, text); + virgl_encode_bind_object(&ctx, vs_handle, VIRGL_OBJECT_VS); + } + + /* create fragment shader */ + { + struct pipe_shader_state fs; + const char *text = + "FRAG\n" + "DCL IN[0], COLOR, LINEAR\n" + "DCL OUT[0], COLOR\n" + " 0: MOV OUT[0], IN[0]\n" + " 1: END\n"; + memset(&fs, 0, sizeof(fs)); + fs_handle = ctx_handle++; + virgl_encode_shader_state(&ctx, fs_handle, VIRGL_OBJECT_FS, + &fs, text); + + virgl_encode_bind_object(&ctx, fs_handle, VIRGL_OBJECT_FS); + } + + /* set blend state */ + { + struct pipe_blend_state blend; + int blend_handle = ctx_handle++; + memset(&blend, 0, sizeof(blend)); + blend.rt[0].colormask = PIPE_MASK_RGBA; + virgl_encode_blend_state(&ctx, blend_handle, &blend); + virgl_encode_bind_object(&ctx, blend_handle, VIRGL_OBJECT_BLEND); + } + + /* set depth stencil alpha state */ + { + struct pipe_depth_stencil_alpha_state dsa; + int dsa_handle = ctx_handle++; + memset(&dsa, 0, sizeof(dsa)); + dsa.depth.writemask = 1; + dsa.depth.func = PIPE_FUNC_LESS; + virgl_encode_dsa_state(&ctx, dsa_handle, &dsa); + virgl_encode_bind_object(&ctx, dsa_handle, VIRGL_OBJECT_DSA); + } + + /* set rasterizer state */ + { + struct pipe_rasterizer_state rasterizer; + int rs_handle = ctx_handle++; + memset(&rasterizer, 0, sizeof(rasterizer)); + rasterizer.cull_face = PIPE_FACE_NONE; + rasterizer.half_pixel_center = 1; + rasterizer.bottom_edge_rule = 1; + rasterizer.depth_clip = 1; + virgl_encode_rasterizer_state(&ctx, rs_handle, &rasterizer); + virgl_encode_bind_object(&ctx, rs_handle, VIRGL_OBJECT_RASTERIZER); + } + + /* set viewport state */ + { + struct pipe_viewport_state vp; + float znear = 0, zfar = 1.0; + float half_w = tw / 2.0f; + float half_h = th / 2.0f; + float half_d = (zfar - znear) / 2.0f; + + vp.scale[0] = half_w; + vp.scale[1] = half_h; + vp.scale[2] = half_d; + + vp.translate[0] = half_w + 0; + vp.translate[1] = half_h + 0; + vp.translate[2] = half_d + znear; + virgl_encoder_set_viewport_state(&ctx, &vp); + } + + /* draw */ + { + struct pipe_draw_info info; + memset(&info, 0, sizeof(info)); + info.count = 3; + info.mode = PIPE_PRIM_TRIANGLES; + virgl_encoder_draw_vbo(&ctx, &info); + } + + virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw); + + /* create a fence */ + ret = virgl_renderer_create_fence(1, ctx.ctx_id); + ck_assert_int_eq(ret, 0); + + do { + int fence; + + virgl_renderer_poll(); + fence = testvirgl_get_last_fence(); + if (fence >= 1) + break; + nanosleep((struct timespec[]){{0, 50000}}, NULL); + } while(1); + + /* read back the tri values in the resource */ + box.x = 0; + box.y = 0; + box.z = 0; + box.w = tw; + box.h = th; + box.d = 1; + ret = virgl_renderer_transfer_read_iov(res.handle, ctx.ctx_id, 0, 0, 0, &box, 0, NULL, 0); + ck_assert_int_eq(ret, 0); + + { + int w, h; + bool all_cleared = true; + uint32_t *ptr = res.iovs[0].iov_base; + for (h = 0; h < th; h++) { + for (w = 0; w < tw; w++) { + if (ptr[h * tw + w] != 0xff00ff00) + all_cleared = false; + } + } + ck_assert_int_eq(all_cleared, false); + } + + /* cleanup */ + virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle); + + testvirgl_destroy_backed_res(&xfb); + testvirgl_destroy_backed_res(&vbo); + testvirgl_destroy_backed_res(&res); + + testvirgl_fini_ctx_cmdbuf(&ctx); +} +END_TEST + Suite *virgl_init_suite(void) { Suite *s; @@ -743,6 +989,7 @@ Suite *virgl_init_suite(void) tcase_add_test(tc_core, virgl_test_overlap_obj_id); tcase_add_test(tc_core, virgl_test_render_simple); tcase_add_test(tc_core, virgl_test_render_geom_simple); + tcase_add_test(tc_core, virgl_test_render_xfb); suite_add_tcase(s, tc_core); return s; |