diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index c0f2c3d..105a914 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -246,6 +246,11 @@ struct vrend_viewport { GLclampd near_val, far_val; }; +#define XFB_STATE_OFF 0 +#define XFB_STATE_STARTED_NEED_BEGIN 1 +#define XFB_STATE_STARTED 2 +#define XFB_STATE_PAUSED 3 + struct vrend_sub_context { struct list_head head; @@ -327,6 +332,8 @@ struct vrend_sub_context { struct pipe_rasterizer_state hw_rs_state; struct pipe_blend_state hw_blend_state; + + int xfb_state; }; struct vrend_context { @@ -2365,12 +2372,15 @@ void vrend_draw_vbo(struct vrend_context *ctx, glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // vrend_ctx_restart_queries(ctx); - - if (ctx->sub->num_so_targets) { + if (ctx->sub->xfb_state == XFB_STATE_STARTED_NEED_BEGIN) { if (ctx->sub->gs) glBeginTransformFeedback(get_gs_xfb_mode(ctx->sub->gs->sinfo.gs_out_prim)); else glBeginTransformFeedback(get_xfb_mode(info->mode)); + ctx->sub->xfb_state = XFB_STATE_STARTED; + } else if (ctx->sub->xfb_state == XFB_STATE_PAUSED) { + glResumeTransformFeedback(); + ctx->sub->xfb_state = XFB_STATE_STARTED; } if (info->primitive_restart) { @@ -2422,15 +2432,17 @@ void vrend_draw_vbo(struct vrend_context *ctx, glDrawElements(mode, info->count, elsz, (void *)(unsigned long)ctx->sub->ib.offset); } - if (ctx->sub->num_so_targets) - glEndTransformFeedback(); - if (info->primitive_restart) { if (vrend_state.have_nv_prim_restart) glDisableClientState(GL_PRIMITIVE_RESTART_NV); else if (vrend_state.have_gl_prim_restart) glDisable(GL_PRIMITIVE_RESTART); } + + if (ctx->sub->xfb_state == XFB_STATE_STARTED) { + glPauseTransformFeedback(); + ctx->sub->xfb_state = XFB_STATE_PAUSED; + } } static GLenum translate_blend_func(uint32_t pipe_blend) @@ -4412,7 +4424,7 @@ static void vrend_hw_emit_streamout_targets(struct vrend_context *ctx) int i; for (i = 0; i < ctx->sub->num_so_targets; i++) { - if (ctx->sub->so_targets[i]->buffer_offset) + if (ctx->sub->so_targets[i]->buffer_offset || ctx->sub->so_targets[i]->buffer_size < ctx->sub->so_targets[i]->buffer->base.width0) glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, ctx->sub->so_targets[i]->buffer->id, ctx->sub->so_targets[i]->buffer_offset, ctx->sub->so_targets[i]->buffer_size); else glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, ctx->sub->so_targets[i]->buffer->id); @@ -4429,6 +4441,12 @@ void vrend_set_streamout_targets(struct vrend_context *ctx, int old_num = ctx->sub->num_so_targets; ctx->sub->num_so_targets = num_targets; + + if (num_targets == 0 && (ctx->sub->xfb_state == XFB_STATE_STARTED || ctx->sub->xfb_state == XFB_STATE_PAUSED)) { + glEndTransformFeedback(); + ctx->sub->xfb_state = XFB_STATE_OFF; + } + for (i = 0; i < num_targets; i++) { target = vrend_object_lookup(ctx->sub->object_hash, handles[i], VIRGL_OBJECT_STREAMOUT_TARGET); if (!target) { @@ -4438,10 +4456,18 @@ void vrend_set_streamout_targets(struct vrend_context *ctx, vrend_so_target_reference(&ctx->sub->so_targets[i], target); } - for (i = num_targets; i < old_num; i++) + for (i = num_targets; i < old_num; i++) { + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, 0); vrend_so_target_reference(&ctx->sub->so_targets[i], NULL); + } vrend_hw_emit_streamout_targets(ctx); + + if (ctx->sub->num_so_targets) { + if (ctx->sub->xfb_state == XFB_STATE_OFF) + ctx->sub->xfb_state = XFB_STATE_STARTED_NEED_BEGIN; + } + } static void vrend_resource_buffer_copy(struct vrend_context *ctx,