24
25
#include <virglrenderer.h>
26
27
+/*
28
+ * VIRGL_CHECK_VERSION available since libvirglrenderer 1.0.1 and was fixed
29
+ * in 1.1.0. Undefine bugged version of the macro and provide our own.
30
+ */
31
+#if defined(VIRGL_CHECK_VERSION) && \
32
+ VIRGL_VERSION_MAJOR == 1 && VIRGL_VERSION_MINOR < 1
33
+#undef VIRGL_CHECK_VERSION
34
+#endif
35
+
36
+#ifndef VIRGL_CHECK_VERSION
37
+#define VIRGL_CHECK_VERSION(major, minor, micro) \
38
+ (VIRGL_VERSION_MAJOR > (major) || \
39
+ VIRGL_VERSION_MAJOR == (major) && VIRGL_VERSION_MINOR > (minor) || \
40
+ VIRGL_VERSION_MAJOR == (major) && VIRGL_VERSION_MINOR == (minor) && \
41
+ VIRGL_VERSION_MICRO >= (micro))
42
+#endif
43
+
44
struct virtio_gpu_virgl_resource {
45
struct virtio_gpu_simple_resource base;
46
MemoryRegion *mr;
1096
}
1097
#endif
1098
1099
+void virtio_gpu_virgl_reset_async_fences(VirtIOGPU *g)
1100
+{
1101
+ struct virtio_gpu_virgl_context_fence *f;
1102
+ VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
1103
+
1104
+ while (!QSLIST_EMPTY(&gl->async_fenceq)) {
1105
+ f = QSLIST_FIRST(&gl->async_fenceq);
1106
+
1107
+ QSLIST_REMOVE_HEAD(&gl->async_fenceq, next);
1108
+
1109
+ g_free(f);
1110
+ }
1111
+}
1112
+
1113
+#if VIRGL_CHECK_VERSION(1, 1, 2)
1114
+static void virtio_gpu_virgl_async_fence_bh(void *opaque)
1115
+{
1116
+ QSLIST_HEAD(, virtio_gpu_virgl_context_fence) async_fenceq;
1117
+ struct virtio_gpu_ctrl_command *cmd, *tmp;
1118
+ struct virtio_gpu_virgl_context_fence *f;
1119
+ VirtIOGPU *g = opaque;
1120
+ VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
1121
+
1122
+ if (gl->renderer_state != RS_INITED) {
1123
+ return;
1124
+ }
1125
+
1126
+ QSLIST_MOVE_ATOMIC(&async_fenceq, &gl->async_fenceq);
1127
+
1128
+ while (!QSLIST_EMPTY(&async_fenceq)) {
1129
+ f = QSLIST_FIRST(&async_fenceq);
1130
+
1131
+ QSLIST_REMOVE_HEAD(&async_fenceq, next);
1132
+
1133
+ QTAILQ_FOREACH_SAFE(cmd, &g->fenceq, next, tmp) {
1134
+ /*
1135
+ * the guest can end up emitting fences out of order
1136
+ * so we should check all fenced cmds not just the first one.
1137
+ */
1138
+ if (cmd->cmd_hdr.fence_id > f->fence_id) {
1139
+ continue;
1140
+ }
1141
+ if (cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_INFO_RING_IDX) {
1142
+ if (cmd->cmd_hdr.ring_idx != f->ring_idx) {
1143
+ continue;
1144
+ }
1145
+ if (cmd->cmd_hdr.ctx_id != f->ctx_id) {
1146
+ continue;
1147
+ }
1148
+ }
1149
+ virtio_gpu_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA);
1150
+ QTAILQ_REMOVE(&g->fenceq, cmd, next);
1151
+ g_free(cmd);
1152
+ }
1153
+
1154
+ trace_virtio_gpu_fence_resp(f->fence_id);
1155
+ g_free(f);
1156
+ g->inflight--;
1157
+ if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
1158
+ trace_virtio_gpu_dec_inflight_fences(g->inflight);
1159
+ }
1160
+ }
1161
+}
1162
+
1163
+static void
1164
+virtio_gpu_virgl_push_async_fence(VirtIOGPU *g, uint32_t ctx_id,
1165
+ uint32_t ring_idx, uint64_t fence_id)
1166
+{
1167
+ struct virtio_gpu_virgl_context_fence *f;
1168
+ VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
1169
+
1170
+ f = g_new(struct virtio_gpu_virgl_context_fence, 1);
1171
+ f->ctx_id = ctx_id;
1172
+ f->ring_idx = ring_idx;
1173
+ f->fence_id = fence_id;
1174
+
1175
+ QSLIST_INSERT_HEAD_ATOMIC(&gl->async_fenceq, f, next);
1176
+
1177
+ qemu_bh_schedule(gl->async_fence_bh);
1178
+}
1179
+
1180
+static void virgl_write_async_fence(void *opaque, uint32_t fence)
1181
+{
1182
+ VirtIOGPU *g = opaque;
1183
+
1184
+ virtio_gpu_virgl_push_async_fence(g, 0, UINT32_MAX, fence);
1185
+}
1186
+
1187
+static void virgl_write_async_context_fence(void *opaque, uint32_t ctx_id,
1188
+ uint32_t ring_idx, uint64_t fence)
1189
+{
1190
+ VirtIOGPU *g = opaque;
1191
+
1192
+ virtio_gpu_virgl_push_async_fence(g, ctx_id, ring_idx, fence);
1193
+}
1194
+#endif
1195
+
1196
static virgl_renderer_gl_context
1197
virgl_create_context(void *opaque, int scanout_idx,
1198
struct virgl_renderer_gl_ctx_param *params)
1292
void virtio_gpu_virgl_reset(VirtIOGPU *g)
1293
{
1294
virgl_renderer_reset();
1295
+
1296
+ virtio_gpu_virgl_reset_async_fences(g);
1297
}
1298
1299
int virtio_gpu_virgl_init(VirtIOGPU *g)
1306
if (qemu_egl_display) {
1307
virtio_gpu_3d_cbs.version = 4;
1308
virtio_gpu_3d_cbs.get_egl_display = virgl_get_egl_display;
1309
+#if VIRGL_CHECK_VERSION(1, 1, 2)
1310
+ virtio_gpu_3d_cbs.write_fence = virgl_write_async_fence;
1311
+ virtio_gpu_3d_cbs.write_context_fence = virgl_write_async_context_fence;
1312
+ flags |= VIRGL_RENDERER_ASYNC_FENCE_CB;
1313
+ flags |= VIRGL_RENDERER_THREAD_SYNC;
1314
+#endif
1315
}
1316
#endif
1317
#ifdef VIRGL_RENDERER_D3D11_SHARE_TEXTURE
1345
gl->cmdq_resume_bh = virtio_bh_io_new_guarded(DEVICE(g),
1346
virtio_gpu_virgl_resume_cmdq_bh,
1347
g);
1348
+#if VIRGL_CHECK_VERSION(1, 1, 2)
1349
+ gl->async_fence_bh = virtio_bh_io_new_guarded(DEVICE(g),
1350
+ virtio_gpu_virgl_async_fence_bh,
1351
+ g);
1352
+#endif
1353
#endif
1354
1355
return 0;