VirtIO-GPU commands may be processed outside of main-loop, from a CPU thread. This results in GL context switch failure because context is held by main-loop thread when GL is invoked from CPU thread. Always release GL context after performing GL operations such that other threads could take over the context.
0 SDL_GL_MakeCurrent() (libSDL3) 1 SDL_GL_MakeCurrent_REAL() (libSDL2) 2 sdl2_gl_make_context_current() (ui/sdl2-gl.c:201) 3 make_current() (virglrenderer.c:639) 4 vrend_finish_context_switch() (vrend_renderer.c:11630) 5 vrend_hw_switch_context() (vrend_renderer.c:11613) 6 vrend_renderer_force_ctx_0() (vrend_renderer.c:12986) 7 virgl_renderer_force_ctx_0() (virglrenderer.c:460) 8 virtio_gpu_virgl_process_cmd() (virtio-gpu-virgl.c:1013) 9 virtio_gpu_process_cmdq() (virtio-gpu.c:1050) 10 virtio_gpu_gl_handle_ctrl() (virtio-gpu-gl.c:86) 11 aio_bh_poll() (util/async.c) 12 aio_poll() (util/aio-posix.c) 13 blk_pwrite() (block/block-gen.c:1985) 14 pflash_update() (pflash_cfi01.c:396) 15 pflash_write() (pflash_cfi01.c:541) 16 memory_region_dispatch_write() (system/memory.c:1554) 17 flatview_write() (system/physmem.c:3333) 18 address_space_write() (system/physmem.c:3453) 19 kvm_cpu_exec() (accel/kvm/kall-all.c:3248) 20 kvm_vcpu_thread_fn() (accel/kvm/kaccel-ops.c:53) Signed-off-by: Dmitry Osipenko <[email protected]> --- hw/display/virtio-gpu-virgl.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c index 0f754829fb71..0021df45d4b2 100644 --- a/hw/display/virtio-gpu-virgl.c +++ b/hw/display/virtio-gpu-virgl.c @@ -896,14 +896,20 @@ static void virgl_cmd_set_scanout_blob(VirtIOGPU *g, } #endif -void virtio_gpu_virgl_process_cmd(VirtIOGPU *g, - struct virtio_gpu_ctrl_command *cmd) +static void virtio_gpu_virgl_unset_ctx_0(VirtIOGPU *g) +{ + /* Virglrender always uses first scanout for GL. */ + dpy_gl_ctx_make_current(g->parent_obj.scanout[0].con, NULL); +} + +static void +virtio_gpu_virgl_process_cmd_with_ctx_0(VirtIOGPU *g, + struct virtio_gpu_ctrl_command *cmd) { bool cmd_suspended = false; VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr); - virgl_renderer_force_ctx_0(); switch (cmd->cmd_hdr.type) { case VIRTIO_GPU_CMD_CTX_CREATE: virgl_cmd_context_create(g, cmd); @@ -1010,6 +1016,14 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g, virgl_renderer_create_fence(cmd->cmd_hdr.fence_id, cmd->cmd_hdr.type); } +void virtio_gpu_virgl_process_cmd(VirtIOGPU *g, + struct virtio_gpu_ctrl_command *cmd) +{ + virgl_renderer_force_ctx_0(); + virtio_gpu_virgl_process_cmd_with_ctx_0(g, cmd); + virtio_gpu_virgl_unset_ctx_0(g); +} + static void virgl_write_fence(void *opaque, uint32_t fence) { VirtIOGPU *g = opaque; @@ -1136,8 +1150,10 @@ static void virtio_gpu_fence_poll(void *opaque) VirtIOGPU *g = opaque; VirtIOGPUGL *gl = VIRTIO_GPU_GL(g); + virgl_renderer_force_ctx_0(); virgl_renderer_poll(); virtio_gpu_process_cmdq(g); + virtio_gpu_virgl_unset_ctx_0(g); if (!QTAILQ_EMPTY(&g->cmdq) || !QTAILQ_EMPTY(&g->fenceq)) { timer_mod(gl->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10); } -- 2.52.0
