11dcc6adbSGurchetan Singh /* SPDX-License-Identifier: GPL-2.0-or-later */
21dcc6adbSGurchetan Singh
31dcc6adbSGurchetan Singh #include "qemu/osdep.h"
41dcc6adbSGurchetan Singh #include "qapi/error.h"
51dcc6adbSGurchetan Singh #include "qemu/error-report.h"
61dcc6adbSGurchetan Singh #include "qemu/iov.h"
71dcc6adbSGurchetan Singh #include "trace.h"
81dcc6adbSGurchetan Singh #include "hw/virtio/virtio.h"
91dcc6adbSGurchetan Singh #include "hw/virtio/virtio-gpu.h"
101dcc6adbSGurchetan Singh #include "hw/virtio/virtio-gpu-pixman.h"
111dcc6adbSGurchetan Singh #include "hw/virtio/virtio-iommu.h"
121dcc6adbSGurchetan Singh
131dcc6adbSGurchetan Singh #include <glib/gmem.h>
141dcc6adbSGurchetan Singh #include <rutabaga_gfx/rutabaga_gfx_ffi.h>
151dcc6adbSGurchetan Singh
161dcc6adbSGurchetan Singh #define CHECK(condition, cmd) \
171dcc6adbSGurchetan Singh do { \
181dcc6adbSGurchetan Singh if (!(condition)) { \
191dcc6adbSGurchetan Singh error_report("CHECK failed in %s() %s:" "%d", __func__, \
201dcc6adbSGurchetan Singh __FILE__, __LINE__); \
211dcc6adbSGurchetan Singh (cmd)->error = VIRTIO_GPU_RESP_ERR_UNSPEC; \
221dcc6adbSGurchetan Singh return; \
231dcc6adbSGurchetan Singh } \
241dcc6adbSGurchetan Singh } while (0)
251dcc6adbSGurchetan Singh
261dcc6adbSGurchetan Singh struct rutabaga_aio_data {
271dcc6adbSGurchetan Singh struct VirtIOGPURutabaga *vr;
281dcc6adbSGurchetan Singh struct rutabaga_fence fence;
291dcc6adbSGurchetan Singh };
301dcc6adbSGurchetan Singh
311dcc6adbSGurchetan Singh static void
virtio_gpu_rutabaga_update_cursor(VirtIOGPU * g,struct virtio_gpu_scanout * s,uint32_t resource_id)321dcc6adbSGurchetan Singh virtio_gpu_rutabaga_update_cursor(VirtIOGPU *g, struct virtio_gpu_scanout *s,
331dcc6adbSGurchetan Singh uint32_t resource_id)
341dcc6adbSGurchetan Singh {
351dcc6adbSGurchetan Singh struct virtio_gpu_simple_resource *res;
361dcc6adbSGurchetan Singh struct rutabaga_transfer transfer = { 0 };
371dcc6adbSGurchetan Singh struct iovec transfer_iovec;
381dcc6adbSGurchetan Singh
391dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
401dcc6adbSGurchetan Singh
411dcc6adbSGurchetan Singh res = virtio_gpu_find_resource(g, resource_id);
421dcc6adbSGurchetan Singh if (!res) {
431dcc6adbSGurchetan Singh return;
441dcc6adbSGurchetan Singh }
451dcc6adbSGurchetan Singh
461dcc6adbSGurchetan Singh if (res->width != s->current_cursor->width ||
471dcc6adbSGurchetan Singh res->height != s->current_cursor->height) {
481dcc6adbSGurchetan Singh return;
491dcc6adbSGurchetan Singh }
501dcc6adbSGurchetan Singh
511dcc6adbSGurchetan Singh transfer.x = 0;
521dcc6adbSGurchetan Singh transfer.y = 0;
531dcc6adbSGurchetan Singh transfer.z = 0;
541dcc6adbSGurchetan Singh transfer.w = res->width;
551dcc6adbSGurchetan Singh transfer.h = res->height;
561dcc6adbSGurchetan Singh transfer.d = 1;
571dcc6adbSGurchetan Singh
581dcc6adbSGurchetan Singh transfer_iovec.iov_base = s->current_cursor->data;
591dcc6adbSGurchetan Singh transfer_iovec.iov_len = res->width * res->height * 4;
601dcc6adbSGurchetan Singh
611dcc6adbSGurchetan Singh rutabaga_resource_transfer_read(vr->rutabaga, 0,
621dcc6adbSGurchetan Singh resource_id, &transfer,
631dcc6adbSGurchetan Singh &transfer_iovec);
641dcc6adbSGurchetan Singh }
651dcc6adbSGurchetan Singh
661dcc6adbSGurchetan Singh static void
virtio_gpu_rutabaga_gl_flushed(VirtIOGPUBase * b)671dcc6adbSGurchetan Singh virtio_gpu_rutabaga_gl_flushed(VirtIOGPUBase *b)
681dcc6adbSGurchetan Singh {
691dcc6adbSGurchetan Singh VirtIOGPU *g = VIRTIO_GPU(b);
701dcc6adbSGurchetan Singh virtio_gpu_process_cmdq(g);
711dcc6adbSGurchetan Singh }
721dcc6adbSGurchetan Singh
731dcc6adbSGurchetan Singh static void
rutabaga_cmd_create_resource_2d(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)741dcc6adbSGurchetan Singh rutabaga_cmd_create_resource_2d(VirtIOGPU *g,
751dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
761dcc6adbSGurchetan Singh {
771dcc6adbSGurchetan Singh int32_t result;
781dcc6adbSGurchetan Singh struct rutabaga_create_3d rc_3d = { 0 };
791dcc6adbSGurchetan Singh struct virtio_gpu_simple_resource *res;
801dcc6adbSGurchetan Singh struct virtio_gpu_resource_create_2d c2d;
811dcc6adbSGurchetan Singh
821dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
831dcc6adbSGurchetan Singh
841dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(c2d);
851dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
861dcc6adbSGurchetan Singh c2d.width, c2d.height);
871dcc6adbSGurchetan Singh
881dcc6adbSGurchetan Singh rc_3d.target = 2;
891dcc6adbSGurchetan Singh rc_3d.format = c2d.format;
901dcc6adbSGurchetan Singh rc_3d.bind = (1 << 1);
911dcc6adbSGurchetan Singh rc_3d.width = c2d.width;
921dcc6adbSGurchetan Singh rc_3d.height = c2d.height;
931dcc6adbSGurchetan Singh rc_3d.depth = 1;
941dcc6adbSGurchetan Singh rc_3d.array_size = 1;
951dcc6adbSGurchetan Singh rc_3d.last_level = 0;
961dcc6adbSGurchetan Singh rc_3d.nr_samples = 0;
971dcc6adbSGurchetan Singh rc_3d.flags = VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP;
981dcc6adbSGurchetan Singh
991dcc6adbSGurchetan Singh result = rutabaga_resource_create_3d(vr->rutabaga, c2d.resource_id, &rc_3d);
1001dcc6adbSGurchetan Singh CHECK(!result, cmd);
1011dcc6adbSGurchetan Singh
1021dcc6adbSGurchetan Singh res = g_new0(struct virtio_gpu_simple_resource, 1);
1031dcc6adbSGurchetan Singh res->width = c2d.width;
1041dcc6adbSGurchetan Singh res->height = c2d.height;
1051dcc6adbSGurchetan Singh res->format = c2d.format;
1061dcc6adbSGurchetan Singh res->resource_id = c2d.resource_id;
1071dcc6adbSGurchetan Singh
1081dcc6adbSGurchetan Singh QTAILQ_INSERT_HEAD(&g->reslist, res, next);
1091dcc6adbSGurchetan Singh }
1101dcc6adbSGurchetan Singh
1111dcc6adbSGurchetan Singh static void
rutabaga_cmd_create_resource_3d(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)1121dcc6adbSGurchetan Singh rutabaga_cmd_create_resource_3d(VirtIOGPU *g,
1131dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
1141dcc6adbSGurchetan Singh {
1151dcc6adbSGurchetan Singh int32_t result;
1161dcc6adbSGurchetan Singh struct rutabaga_create_3d rc_3d = { 0 };
1171dcc6adbSGurchetan Singh struct virtio_gpu_simple_resource *res;
1181dcc6adbSGurchetan Singh struct virtio_gpu_resource_create_3d c3d;
1191dcc6adbSGurchetan Singh
1201dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
1211dcc6adbSGurchetan Singh
1221dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(c3d);
1231dcc6adbSGurchetan Singh
1241dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_res_create_3d(c3d.resource_id, c3d.format,
1251dcc6adbSGurchetan Singh c3d.width, c3d.height, c3d.depth);
1261dcc6adbSGurchetan Singh
1271dcc6adbSGurchetan Singh rc_3d.target = c3d.target;
1281dcc6adbSGurchetan Singh rc_3d.format = c3d.format;
1291dcc6adbSGurchetan Singh rc_3d.bind = c3d.bind;
1301dcc6adbSGurchetan Singh rc_3d.width = c3d.width;
1311dcc6adbSGurchetan Singh rc_3d.height = c3d.height;
1321dcc6adbSGurchetan Singh rc_3d.depth = c3d.depth;
1331dcc6adbSGurchetan Singh rc_3d.array_size = c3d.array_size;
1341dcc6adbSGurchetan Singh rc_3d.last_level = c3d.last_level;
1351dcc6adbSGurchetan Singh rc_3d.nr_samples = c3d.nr_samples;
1361dcc6adbSGurchetan Singh rc_3d.flags = c3d.flags;
1371dcc6adbSGurchetan Singh
1381dcc6adbSGurchetan Singh result = rutabaga_resource_create_3d(vr->rutabaga, c3d.resource_id, &rc_3d);
1391dcc6adbSGurchetan Singh CHECK(!result, cmd);
1401dcc6adbSGurchetan Singh
1411dcc6adbSGurchetan Singh res = g_new0(struct virtio_gpu_simple_resource, 1);
1421dcc6adbSGurchetan Singh res->width = c3d.width;
1431dcc6adbSGurchetan Singh res->height = c3d.height;
1441dcc6adbSGurchetan Singh res->format = c3d.format;
1451dcc6adbSGurchetan Singh res->resource_id = c3d.resource_id;
1461dcc6adbSGurchetan Singh
1471dcc6adbSGurchetan Singh QTAILQ_INSERT_HEAD(&g->reslist, res, next);
1481dcc6adbSGurchetan Singh }
1491dcc6adbSGurchetan Singh
1501dcc6adbSGurchetan Singh static void
virtio_gpu_rutabaga_resource_unref(VirtIOGPU * g,struct virtio_gpu_simple_resource * res,Error ** errp)151*588a09daSManos Pitsidianakis virtio_gpu_rutabaga_resource_unref(VirtIOGPU *g,
152*588a09daSManos Pitsidianakis struct virtio_gpu_simple_resource *res,
153*588a09daSManos Pitsidianakis Error **errp)
154*588a09daSManos Pitsidianakis {
155*588a09daSManos Pitsidianakis int32_t result;
156*588a09daSManos Pitsidianakis VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
157*588a09daSManos Pitsidianakis
158*588a09daSManos Pitsidianakis result = rutabaga_resource_unref(vr->rutabaga, res->resource_id);
159*588a09daSManos Pitsidianakis if (result) {
160*588a09daSManos Pitsidianakis error_setg_errno(errp,
161*588a09daSManos Pitsidianakis (int)result,
162*588a09daSManos Pitsidianakis "%s: rutabaga_resource_unref returned %"PRIi32
163*588a09daSManos Pitsidianakis " for resource_id = %"PRIu32, __func__, result,
164*588a09daSManos Pitsidianakis res->resource_id);
165*588a09daSManos Pitsidianakis }
166*588a09daSManos Pitsidianakis
167*588a09daSManos Pitsidianakis if (res->image) {
168*588a09daSManos Pitsidianakis pixman_image_unref(res->image);
169*588a09daSManos Pitsidianakis }
170*588a09daSManos Pitsidianakis
171*588a09daSManos Pitsidianakis QTAILQ_REMOVE(&g->reslist, res, next);
172*588a09daSManos Pitsidianakis g_free(res);
173*588a09daSManos Pitsidianakis }
174*588a09daSManos Pitsidianakis
175*588a09daSManos Pitsidianakis static void
rutabaga_cmd_resource_unref(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)1761dcc6adbSGurchetan Singh rutabaga_cmd_resource_unref(VirtIOGPU *g,
1771dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
1781dcc6adbSGurchetan Singh {
179*588a09daSManos Pitsidianakis int32_t result = 0;
1801dcc6adbSGurchetan Singh struct virtio_gpu_simple_resource *res;
1811dcc6adbSGurchetan Singh struct virtio_gpu_resource_unref unref;
182*588a09daSManos Pitsidianakis Error *local_err = NULL;
1831dcc6adbSGurchetan Singh
1841dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(unref);
1851dcc6adbSGurchetan Singh
1861dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_res_unref(unref.resource_id);
1871dcc6adbSGurchetan Singh
1881dcc6adbSGurchetan Singh res = virtio_gpu_find_resource(g, unref.resource_id);
1891dcc6adbSGurchetan Singh CHECK(res, cmd);
1901dcc6adbSGurchetan Singh
191*588a09daSManos Pitsidianakis virtio_gpu_rutabaga_resource_unref(g, res, &local_err);
192*588a09daSManos Pitsidianakis if (local_err) {
193*588a09daSManos Pitsidianakis error_report_err(local_err);
194*588a09daSManos Pitsidianakis /* local_err was freed, do not reuse it. */
195*588a09daSManos Pitsidianakis local_err = NULL;
196*588a09daSManos Pitsidianakis result = 1;
1971dcc6adbSGurchetan Singh }
198*588a09daSManos Pitsidianakis CHECK(!result, cmd);
1991dcc6adbSGurchetan Singh }
2001dcc6adbSGurchetan Singh
2011dcc6adbSGurchetan Singh static void
rutabaga_cmd_context_create(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)2021dcc6adbSGurchetan Singh rutabaga_cmd_context_create(VirtIOGPU *g,
2031dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
2041dcc6adbSGurchetan Singh {
2051dcc6adbSGurchetan Singh int32_t result;
2061dcc6adbSGurchetan Singh struct virtio_gpu_ctx_create cc;
2071dcc6adbSGurchetan Singh
2081dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
2091dcc6adbSGurchetan Singh
2101dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(cc);
2111dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_ctx_create(cc.hdr.ctx_id,
2121dcc6adbSGurchetan Singh cc.debug_name);
2131dcc6adbSGurchetan Singh
2141dcc6adbSGurchetan Singh result = rutabaga_context_create(vr->rutabaga, cc.hdr.ctx_id,
2151dcc6adbSGurchetan Singh cc.context_init, cc.debug_name, cc.nlen);
2161dcc6adbSGurchetan Singh CHECK(!result, cmd);
2171dcc6adbSGurchetan Singh }
2181dcc6adbSGurchetan Singh
2191dcc6adbSGurchetan Singh static void
rutabaga_cmd_context_destroy(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)2201dcc6adbSGurchetan Singh rutabaga_cmd_context_destroy(VirtIOGPU *g,
2211dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
2221dcc6adbSGurchetan Singh {
2231dcc6adbSGurchetan Singh int32_t result;
2241dcc6adbSGurchetan Singh struct virtio_gpu_ctx_destroy cd;
2251dcc6adbSGurchetan Singh
2261dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
2271dcc6adbSGurchetan Singh
2281dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(cd);
2291dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_ctx_destroy(cd.hdr.ctx_id);
2301dcc6adbSGurchetan Singh
2311dcc6adbSGurchetan Singh result = rutabaga_context_destroy(vr->rutabaga, cd.hdr.ctx_id);
2321dcc6adbSGurchetan Singh CHECK(!result, cmd);
2331dcc6adbSGurchetan Singh }
2341dcc6adbSGurchetan Singh
2351dcc6adbSGurchetan Singh static void
rutabaga_cmd_resource_flush(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)2361dcc6adbSGurchetan Singh rutabaga_cmd_resource_flush(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd)
2371dcc6adbSGurchetan Singh {
2381dcc6adbSGurchetan Singh int32_t result, i;
2391dcc6adbSGurchetan Singh struct virtio_gpu_scanout *scanout = NULL;
2401dcc6adbSGurchetan Singh struct virtio_gpu_simple_resource *res;
2411dcc6adbSGurchetan Singh struct rutabaga_transfer transfer = { 0 };
2421dcc6adbSGurchetan Singh struct iovec transfer_iovec;
2431dcc6adbSGurchetan Singh struct virtio_gpu_resource_flush rf;
2441dcc6adbSGurchetan Singh bool found = false;
2451dcc6adbSGurchetan Singh
2461dcc6adbSGurchetan Singh VirtIOGPUBase *vb = VIRTIO_GPU_BASE(g);
2471dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
2481dcc6adbSGurchetan Singh if (vr->headless) {
2491dcc6adbSGurchetan Singh return;
2501dcc6adbSGurchetan Singh }
2511dcc6adbSGurchetan Singh
2521dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(rf);
2531dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_res_flush(rf.resource_id,
2541dcc6adbSGurchetan Singh rf.r.width, rf.r.height, rf.r.x, rf.r.y);
2551dcc6adbSGurchetan Singh
2561dcc6adbSGurchetan Singh res = virtio_gpu_find_resource(g, rf.resource_id);
2571dcc6adbSGurchetan Singh CHECK(res, cmd);
2581dcc6adbSGurchetan Singh
2591dcc6adbSGurchetan Singh for (i = 0; i < vb->conf.max_outputs; i++) {
2601dcc6adbSGurchetan Singh scanout = &vb->scanout[i];
2611dcc6adbSGurchetan Singh if (i == res->scanout_bitmask) {
2621dcc6adbSGurchetan Singh found = true;
2631dcc6adbSGurchetan Singh break;
2641dcc6adbSGurchetan Singh }
2651dcc6adbSGurchetan Singh }
2661dcc6adbSGurchetan Singh
2671dcc6adbSGurchetan Singh if (!found) {
2681dcc6adbSGurchetan Singh return;
2691dcc6adbSGurchetan Singh }
2701dcc6adbSGurchetan Singh
2711dcc6adbSGurchetan Singh transfer.x = 0;
2721dcc6adbSGurchetan Singh transfer.y = 0;
2731dcc6adbSGurchetan Singh transfer.z = 0;
2741dcc6adbSGurchetan Singh transfer.w = res->width;
2751dcc6adbSGurchetan Singh transfer.h = res->height;
2761dcc6adbSGurchetan Singh transfer.d = 1;
2771dcc6adbSGurchetan Singh
2781dcc6adbSGurchetan Singh transfer_iovec.iov_base = pixman_image_get_data(res->image);
2791dcc6adbSGurchetan Singh transfer_iovec.iov_len = res->width * res->height * 4;
2801dcc6adbSGurchetan Singh
2811dcc6adbSGurchetan Singh result = rutabaga_resource_transfer_read(vr->rutabaga, 0,
2821dcc6adbSGurchetan Singh rf.resource_id, &transfer,
2831dcc6adbSGurchetan Singh &transfer_iovec);
2841dcc6adbSGurchetan Singh CHECK(!result, cmd);
2851dcc6adbSGurchetan Singh dpy_gfx_update_full(scanout->con);
2861dcc6adbSGurchetan Singh }
2871dcc6adbSGurchetan Singh
2881dcc6adbSGurchetan Singh static void
rutabaga_cmd_set_scanout(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)2891dcc6adbSGurchetan Singh rutabaga_cmd_set_scanout(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd)
2901dcc6adbSGurchetan Singh {
2911dcc6adbSGurchetan Singh struct virtio_gpu_simple_resource *res;
2921dcc6adbSGurchetan Singh struct virtio_gpu_scanout *scanout = NULL;
2931dcc6adbSGurchetan Singh struct virtio_gpu_set_scanout ss;
2941dcc6adbSGurchetan Singh
2951dcc6adbSGurchetan Singh VirtIOGPUBase *vb = VIRTIO_GPU_BASE(g);
2961dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
2971dcc6adbSGurchetan Singh if (vr->headless) {
2981dcc6adbSGurchetan Singh return;
2991dcc6adbSGurchetan Singh }
3001dcc6adbSGurchetan Singh
3011dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(ss);
3021dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id,
3031dcc6adbSGurchetan Singh ss.r.width, ss.r.height, ss.r.x, ss.r.y);
3041dcc6adbSGurchetan Singh
3051dcc6adbSGurchetan Singh CHECK(ss.scanout_id < VIRTIO_GPU_MAX_SCANOUTS, cmd);
3061dcc6adbSGurchetan Singh scanout = &vb->scanout[ss.scanout_id];
3071dcc6adbSGurchetan Singh
3081dcc6adbSGurchetan Singh if (ss.resource_id == 0) {
3091dcc6adbSGurchetan Singh dpy_gfx_replace_surface(scanout->con, NULL);
3101dcc6adbSGurchetan Singh dpy_gl_scanout_disable(scanout->con);
3111dcc6adbSGurchetan Singh return;
3121dcc6adbSGurchetan Singh }
3131dcc6adbSGurchetan Singh
3141dcc6adbSGurchetan Singh res = virtio_gpu_find_resource(g, ss.resource_id);
3151dcc6adbSGurchetan Singh CHECK(res, cmd);
3161dcc6adbSGurchetan Singh
3171dcc6adbSGurchetan Singh if (!res->image) {
3181dcc6adbSGurchetan Singh pixman_format_code_t pformat;
3191dcc6adbSGurchetan Singh pformat = virtio_gpu_get_pixman_format(res->format);
3201dcc6adbSGurchetan Singh CHECK(pformat, cmd);
3211dcc6adbSGurchetan Singh
3221dcc6adbSGurchetan Singh res->image = pixman_image_create_bits(pformat,
3231dcc6adbSGurchetan Singh res->width,
3241dcc6adbSGurchetan Singh res->height,
3251dcc6adbSGurchetan Singh NULL, 0);
3261dcc6adbSGurchetan Singh CHECK(res->image, cmd);
3271dcc6adbSGurchetan Singh pixman_image_ref(res->image);
3281dcc6adbSGurchetan Singh }
3291dcc6adbSGurchetan Singh
3301dcc6adbSGurchetan Singh vb->enable = 1;
3311dcc6adbSGurchetan Singh
3321dcc6adbSGurchetan Singh /* realloc the surface ptr */
3331dcc6adbSGurchetan Singh scanout->ds = qemu_create_displaysurface_pixman(res->image);
3341dcc6adbSGurchetan Singh dpy_gfx_replace_surface(scanout->con, NULL);
3351dcc6adbSGurchetan Singh dpy_gfx_replace_surface(scanout->con, scanout->ds);
3361dcc6adbSGurchetan Singh res->scanout_bitmask = ss.scanout_id;
3371dcc6adbSGurchetan Singh }
3381dcc6adbSGurchetan Singh
3391dcc6adbSGurchetan Singh static void
rutabaga_cmd_submit_3d(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)3401dcc6adbSGurchetan Singh rutabaga_cmd_submit_3d(VirtIOGPU *g,
3411dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
3421dcc6adbSGurchetan Singh {
3431dcc6adbSGurchetan Singh int32_t result;
3441dcc6adbSGurchetan Singh struct virtio_gpu_cmd_submit cs;
3451dcc6adbSGurchetan Singh struct rutabaga_command rutabaga_cmd = { 0 };
3461dcc6adbSGurchetan Singh g_autofree uint8_t *buf = NULL;
3471dcc6adbSGurchetan Singh size_t s;
3481dcc6adbSGurchetan Singh
3491dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
3501dcc6adbSGurchetan Singh
3511dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(cs);
3521dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_ctx_submit(cs.hdr.ctx_id, cs.size);
3531dcc6adbSGurchetan Singh
3541dcc6adbSGurchetan Singh buf = g_new0(uint8_t, cs.size);
3551dcc6adbSGurchetan Singh s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
3561dcc6adbSGurchetan Singh sizeof(cs), buf, cs.size);
3571dcc6adbSGurchetan Singh CHECK(s == cs.size, cmd);
3581dcc6adbSGurchetan Singh
3591dcc6adbSGurchetan Singh rutabaga_cmd.ctx_id = cs.hdr.ctx_id;
3601dcc6adbSGurchetan Singh rutabaga_cmd.cmd = buf;
3611dcc6adbSGurchetan Singh rutabaga_cmd.cmd_size = cs.size;
3621dcc6adbSGurchetan Singh
3631dcc6adbSGurchetan Singh result = rutabaga_submit_command(vr->rutabaga, &rutabaga_cmd);
3641dcc6adbSGurchetan Singh CHECK(!result, cmd);
3651dcc6adbSGurchetan Singh }
3661dcc6adbSGurchetan Singh
3671dcc6adbSGurchetan Singh static void
rutabaga_cmd_transfer_to_host_2d(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)3681dcc6adbSGurchetan Singh rutabaga_cmd_transfer_to_host_2d(VirtIOGPU *g,
3691dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
3701dcc6adbSGurchetan Singh {
3711dcc6adbSGurchetan Singh int32_t result;
3721dcc6adbSGurchetan Singh struct rutabaga_transfer transfer = { 0 };
3731dcc6adbSGurchetan Singh struct virtio_gpu_transfer_to_host_2d t2d;
3741dcc6adbSGurchetan Singh
3751dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
3761dcc6adbSGurchetan Singh
3771dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(t2d);
3781dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id);
3791dcc6adbSGurchetan Singh
3801dcc6adbSGurchetan Singh transfer.x = t2d.r.x;
3811dcc6adbSGurchetan Singh transfer.y = t2d.r.y;
3821dcc6adbSGurchetan Singh transfer.z = 0;
3831dcc6adbSGurchetan Singh transfer.w = t2d.r.width;
3841dcc6adbSGurchetan Singh transfer.h = t2d.r.height;
3851dcc6adbSGurchetan Singh transfer.d = 1;
3861dcc6adbSGurchetan Singh
3871dcc6adbSGurchetan Singh result = rutabaga_resource_transfer_write(vr->rutabaga, 0, t2d.resource_id,
3881dcc6adbSGurchetan Singh &transfer);
3891dcc6adbSGurchetan Singh CHECK(!result, cmd);
3901dcc6adbSGurchetan Singh }
3911dcc6adbSGurchetan Singh
3921dcc6adbSGurchetan Singh static void
rutabaga_cmd_transfer_to_host_3d(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)3931dcc6adbSGurchetan Singh rutabaga_cmd_transfer_to_host_3d(VirtIOGPU *g,
3941dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
3951dcc6adbSGurchetan Singh {
3961dcc6adbSGurchetan Singh int32_t result;
3971dcc6adbSGurchetan Singh struct rutabaga_transfer transfer = { 0 };
3981dcc6adbSGurchetan Singh struct virtio_gpu_transfer_host_3d t3d;
3991dcc6adbSGurchetan Singh
4001dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
4011dcc6adbSGurchetan Singh
4021dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(t3d);
4031dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_res_xfer_toh_3d(t3d.resource_id);
4041dcc6adbSGurchetan Singh
4051dcc6adbSGurchetan Singh transfer.x = t3d.box.x;
4061dcc6adbSGurchetan Singh transfer.y = t3d.box.y;
4071dcc6adbSGurchetan Singh transfer.z = t3d.box.z;
4081dcc6adbSGurchetan Singh transfer.w = t3d.box.w;
4091dcc6adbSGurchetan Singh transfer.h = t3d.box.h;
4101dcc6adbSGurchetan Singh transfer.d = t3d.box.d;
4111dcc6adbSGurchetan Singh transfer.level = t3d.level;
4121dcc6adbSGurchetan Singh transfer.stride = t3d.stride;
4131dcc6adbSGurchetan Singh transfer.layer_stride = t3d.layer_stride;
4141dcc6adbSGurchetan Singh transfer.offset = t3d.offset;
4151dcc6adbSGurchetan Singh
4161dcc6adbSGurchetan Singh result = rutabaga_resource_transfer_write(vr->rutabaga, t3d.hdr.ctx_id,
4171dcc6adbSGurchetan Singh t3d.resource_id, &transfer);
4181dcc6adbSGurchetan Singh CHECK(!result, cmd);
4191dcc6adbSGurchetan Singh }
4201dcc6adbSGurchetan Singh
4211dcc6adbSGurchetan Singh static void
rutabaga_cmd_transfer_from_host_3d(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)4221dcc6adbSGurchetan Singh rutabaga_cmd_transfer_from_host_3d(VirtIOGPU *g,
4231dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
4241dcc6adbSGurchetan Singh {
4251dcc6adbSGurchetan Singh int32_t result;
4261dcc6adbSGurchetan Singh struct rutabaga_transfer transfer = { 0 };
4271dcc6adbSGurchetan Singh struct virtio_gpu_transfer_host_3d t3d;
4281dcc6adbSGurchetan Singh
4291dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
4301dcc6adbSGurchetan Singh
4311dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(t3d);
4321dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_res_xfer_fromh_3d(t3d.resource_id);
4331dcc6adbSGurchetan Singh
4341dcc6adbSGurchetan Singh transfer.x = t3d.box.x;
4351dcc6adbSGurchetan Singh transfer.y = t3d.box.y;
4361dcc6adbSGurchetan Singh transfer.z = t3d.box.z;
4371dcc6adbSGurchetan Singh transfer.w = t3d.box.w;
4381dcc6adbSGurchetan Singh transfer.h = t3d.box.h;
4391dcc6adbSGurchetan Singh transfer.d = t3d.box.d;
4401dcc6adbSGurchetan Singh transfer.level = t3d.level;
4411dcc6adbSGurchetan Singh transfer.stride = t3d.stride;
4421dcc6adbSGurchetan Singh transfer.layer_stride = t3d.layer_stride;
4431dcc6adbSGurchetan Singh transfer.offset = t3d.offset;
4441dcc6adbSGurchetan Singh
4451dcc6adbSGurchetan Singh result = rutabaga_resource_transfer_read(vr->rutabaga, t3d.hdr.ctx_id,
4461dcc6adbSGurchetan Singh t3d.resource_id, &transfer, NULL);
4471dcc6adbSGurchetan Singh CHECK(!result, cmd);
4481dcc6adbSGurchetan Singh }
4491dcc6adbSGurchetan Singh
4501dcc6adbSGurchetan Singh static void
rutabaga_cmd_attach_backing(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)4511dcc6adbSGurchetan Singh rutabaga_cmd_attach_backing(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd)
4521dcc6adbSGurchetan Singh {
4531dcc6adbSGurchetan Singh struct rutabaga_iovecs vecs = { 0 };
4541dcc6adbSGurchetan Singh struct virtio_gpu_simple_resource *res;
4551dcc6adbSGurchetan Singh struct virtio_gpu_resource_attach_backing att_rb;
4561dcc6adbSGurchetan Singh int ret;
4571dcc6adbSGurchetan Singh
4581dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
4591dcc6adbSGurchetan Singh
4601dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(att_rb);
4611dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id);
4621dcc6adbSGurchetan Singh
4631dcc6adbSGurchetan Singh res = virtio_gpu_find_resource(g, att_rb.resource_id);
4641dcc6adbSGurchetan Singh CHECK(res, cmd);
4651dcc6adbSGurchetan Singh CHECK(!res->iov, cmd);
4661dcc6adbSGurchetan Singh
4671dcc6adbSGurchetan Singh ret = virtio_gpu_create_mapping_iov(g, att_rb.nr_entries, sizeof(att_rb),
4681dcc6adbSGurchetan Singh cmd, NULL, &res->iov, &res->iov_cnt);
4691dcc6adbSGurchetan Singh CHECK(!ret, cmd);
4701dcc6adbSGurchetan Singh
4711dcc6adbSGurchetan Singh vecs.iovecs = res->iov;
4721dcc6adbSGurchetan Singh vecs.num_iovecs = res->iov_cnt;
4731dcc6adbSGurchetan Singh
4741dcc6adbSGurchetan Singh ret = rutabaga_resource_attach_backing(vr->rutabaga, att_rb.resource_id,
4751dcc6adbSGurchetan Singh &vecs);
4761dcc6adbSGurchetan Singh if (ret != 0) {
4771dcc6adbSGurchetan Singh virtio_gpu_cleanup_mapping(g, res);
4781dcc6adbSGurchetan Singh }
4791dcc6adbSGurchetan Singh
4801dcc6adbSGurchetan Singh CHECK(!ret, cmd);
4811dcc6adbSGurchetan Singh }
4821dcc6adbSGurchetan Singh
4831dcc6adbSGurchetan Singh static void
rutabaga_cmd_detach_backing(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)4841dcc6adbSGurchetan Singh rutabaga_cmd_detach_backing(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd)
4851dcc6adbSGurchetan Singh {
4861dcc6adbSGurchetan Singh struct virtio_gpu_simple_resource *res;
4871dcc6adbSGurchetan Singh struct virtio_gpu_resource_detach_backing detach_rb;
4881dcc6adbSGurchetan Singh
4891dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
4901dcc6adbSGurchetan Singh
4911dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(detach_rb);
4921dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_res_back_detach(detach_rb.resource_id);
4931dcc6adbSGurchetan Singh
4941dcc6adbSGurchetan Singh res = virtio_gpu_find_resource(g, detach_rb.resource_id);
4951dcc6adbSGurchetan Singh CHECK(res, cmd);
4961dcc6adbSGurchetan Singh
4971dcc6adbSGurchetan Singh rutabaga_resource_detach_backing(vr->rutabaga,
4981dcc6adbSGurchetan Singh detach_rb.resource_id);
4991dcc6adbSGurchetan Singh
5001dcc6adbSGurchetan Singh virtio_gpu_cleanup_mapping(g, res);
5011dcc6adbSGurchetan Singh }
5021dcc6adbSGurchetan Singh
5031dcc6adbSGurchetan Singh static void
rutabaga_cmd_ctx_attach_resource(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)5041dcc6adbSGurchetan Singh rutabaga_cmd_ctx_attach_resource(VirtIOGPU *g,
5051dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
5061dcc6adbSGurchetan Singh {
5071dcc6adbSGurchetan Singh int32_t result;
5081dcc6adbSGurchetan Singh struct virtio_gpu_ctx_resource att_res;
5091dcc6adbSGurchetan Singh
5101dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
5111dcc6adbSGurchetan Singh
5121dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(att_res);
5131dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_ctx_res_attach(att_res.hdr.ctx_id,
5141dcc6adbSGurchetan Singh att_res.resource_id);
5151dcc6adbSGurchetan Singh
5161dcc6adbSGurchetan Singh result = rutabaga_context_attach_resource(vr->rutabaga, att_res.hdr.ctx_id,
5171dcc6adbSGurchetan Singh att_res.resource_id);
5181dcc6adbSGurchetan Singh CHECK(!result, cmd);
5191dcc6adbSGurchetan Singh }
5201dcc6adbSGurchetan Singh
5211dcc6adbSGurchetan Singh static void
rutabaga_cmd_ctx_detach_resource(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)5221dcc6adbSGurchetan Singh rutabaga_cmd_ctx_detach_resource(VirtIOGPU *g,
5231dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
5241dcc6adbSGurchetan Singh {
5251dcc6adbSGurchetan Singh int32_t result;
5261dcc6adbSGurchetan Singh struct virtio_gpu_ctx_resource det_res;
5271dcc6adbSGurchetan Singh
5281dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
5291dcc6adbSGurchetan Singh
5301dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(det_res);
5311dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_ctx_res_detach(det_res.hdr.ctx_id,
5321dcc6adbSGurchetan Singh det_res.resource_id);
5331dcc6adbSGurchetan Singh
5341dcc6adbSGurchetan Singh result = rutabaga_context_detach_resource(vr->rutabaga, det_res.hdr.ctx_id,
5351dcc6adbSGurchetan Singh det_res.resource_id);
5361dcc6adbSGurchetan Singh CHECK(!result, cmd);
5371dcc6adbSGurchetan Singh }
5381dcc6adbSGurchetan Singh
5391dcc6adbSGurchetan Singh static void
rutabaga_cmd_get_capset_info(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)5401dcc6adbSGurchetan Singh rutabaga_cmd_get_capset_info(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd)
5411dcc6adbSGurchetan Singh {
5421dcc6adbSGurchetan Singh int32_t result;
5431dcc6adbSGurchetan Singh struct virtio_gpu_get_capset_info info;
5441dcc6adbSGurchetan Singh struct virtio_gpu_resp_capset_info resp;
5451dcc6adbSGurchetan Singh
5461dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
5471dcc6adbSGurchetan Singh
5481dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(info);
5491dcc6adbSGurchetan Singh
5501dcc6adbSGurchetan Singh result = rutabaga_get_capset_info(vr->rutabaga, info.capset_index,
5511dcc6adbSGurchetan Singh &resp.capset_id, &resp.capset_max_version,
5521dcc6adbSGurchetan Singh &resp.capset_max_size);
5531dcc6adbSGurchetan Singh CHECK(!result, cmd);
5541dcc6adbSGurchetan Singh
5551dcc6adbSGurchetan Singh resp.hdr.type = VIRTIO_GPU_RESP_OK_CAPSET_INFO;
5561dcc6adbSGurchetan Singh virtio_gpu_ctrl_response(g, cmd, &resp.hdr, sizeof(resp));
5571dcc6adbSGurchetan Singh }
5581dcc6adbSGurchetan Singh
5591dcc6adbSGurchetan Singh static void
rutabaga_cmd_get_capset(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)5601dcc6adbSGurchetan Singh rutabaga_cmd_get_capset(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd)
5611dcc6adbSGurchetan Singh {
5621dcc6adbSGurchetan Singh int32_t result;
5631dcc6adbSGurchetan Singh struct virtio_gpu_get_capset gc;
5641dcc6adbSGurchetan Singh struct virtio_gpu_resp_capset *resp;
5651dcc6adbSGurchetan Singh uint32_t capset_size, capset_version;
5661dcc6adbSGurchetan Singh uint32_t current_id, i;
5671dcc6adbSGurchetan Singh
5681dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
5691dcc6adbSGurchetan Singh
5701dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(gc);
5711dcc6adbSGurchetan Singh for (i = 0; i < vr->num_capsets; i++) {
5721dcc6adbSGurchetan Singh result = rutabaga_get_capset_info(vr->rutabaga, i,
5731dcc6adbSGurchetan Singh ¤t_id, &capset_version,
5741dcc6adbSGurchetan Singh &capset_size);
5751dcc6adbSGurchetan Singh CHECK(!result, cmd);
5761dcc6adbSGurchetan Singh
5771dcc6adbSGurchetan Singh if (current_id == gc.capset_id) {
5781dcc6adbSGurchetan Singh break;
5791dcc6adbSGurchetan Singh }
5801dcc6adbSGurchetan Singh }
5811dcc6adbSGurchetan Singh
5821dcc6adbSGurchetan Singh CHECK(i < vr->num_capsets, cmd);
5831dcc6adbSGurchetan Singh
5841dcc6adbSGurchetan Singh resp = g_malloc0(sizeof(*resp) + capset_size);
5851dcc6adbSGurchetan Singh resp->hdr.type = VIRTIO_GPU_RESP_OK_CAPSET;
5861dcc6adbSGurchetan Singh rutabaga_get_capset(vr->rutabaga, gc.capset_id, gc.capset_version,
5871dcc6adbSGurchetan Singh resp->capset_data, capset_size);
5881dcc6adbSGurchetan Singh
5891dcc6adbSGurchetan Singh virtio_gpu_ctrl_response(g, cmd, &resp->hdr, sizeof(*resp) + capset_size);
5901dcc6adbSGurchetan Singh g_free(resp);
5911dcc6adbSGurchetan Singh }
5921dcc6adbSGurchetan Singh
5931dcc6adbSGurchetan Singh static void
rutabaga_cmd_resource_create_blob(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)5941dcc6adbSGurchetan Singh rutabaga_cmd_resource_create_blob(VirtIOGPU *g,
5951dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
5961dcc6adbSGurchetan Singh {
5971dcc6adbSGurchetan Singh int result;
5981dcc6adbSGurchetan Singh struct rutabaga_iovecs vecs = { 0 };
5991dcc6adbSGurchetan Singh g_autofree struct virtio_gpu_simple_resource *res = NULL;
6001dcc6adbSGurchetan Singh struct virtio_gpu_resource_create_blob cblob;
6011dcc6adbSGurchetan Singh struct rutabaga_create_blob rc_blob = { 0 };
6021dcc6adbSGurchetan Singh
6031dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
6041dcc6adbSGurchetan Singh
6051dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(cblob);
6061dcc6adbSGurchetan Singh trace_virtio_gpu_cmd_res_create_blob(cblob.resource_id, cblob.size);
6071dcc6adbSGurchetan Singh
6081dcc6adbSGurchetan Singh CHECK(cblob.resource_id != 0, cmd);
6091dcc6adbSGurchetan Singh
6101dcc6adbSGurchetan Singh res = g_new0(struct virtio_gpu_simple_resource, 1);
6111dcc6adbSGurchetan Singh
6121dcc6adbSGurchetan Singh res->resource_id = cblob.resource_id;
6131dcc6adbSGurchetan Singh res->blob_size = cblob.size;
6141dcc6adbSGurchetan Singh
6151dcc6adbSGurchetan Singh if (cblob.blob_mem != VIRTIO_GPU_BLOB_MEM_HOST3D) {
6161dcc6adbSGurchetan Singh result = virtio_gpu_create_mapping_iov(g, cblob.nr_entries,
6171dcc6adbSGurchetan Singh sizeof(cblob), cmd, &res->addrs,
6181dcc6adbSGurchetan Singh &res->iov, &res->iov_cnt);
6191dcc6adbSGurchetan Singh CHECK(!result, cmd);
6201dcc6adbSGurchetan Singh }
6211dcc6adbSGurchetan Singh
6221dcc6adbSGurchetan Singh rc_blob.blob_id = cblob.blob_id;
6231dcc6adbSGurchetan Singh rc_blob.blob_mem = cblob.blob_mem;
6241dcc6adbSGurchetan Singh rc_blob.blob_flags = cblob.blob_flags;
6251dcc6adbSGurchetan Singh rc_blob.size = cblob.size;
6261dcc6adbSGurchetan Singh
6271dcc6adbSGurchetan Singh vecs.iovecs = res->iov;
6281dcc6adbSGurchetan Singh vecs.num_iovecs = res->iov_cnt;
6291dcc6adbSGurchetan Singh
6301dcc6adbSGurchetan Singh result = rutabaga_resource_create_blob(vr->rutabaga, cblob.hdr.ctx_id,
6311dcc6adbSGurchetan Singh cblob.resource_id, &rc_blob, &vecs,
6321dcc6adbSGurchetan Singh NULL);
6331dcc6adbSGurchetan Singh
6341dcc6adbSGurchetan Singh if (result && cblob.blob_mem != VIRTIO_GPU_BLOB_MEM_HOST3D) {
6351dcc6adbSGurchetan Singh virtio_gpu_cleanup_mapping(g, res);
6361dcc6adbSGurchetan Singh }
6371dcc6adbSGurchetan Singh
6381dcc6adbSGurchetan Singh CHECK(!result, cmd);
6391dcc6adbSGurchetan Singh
6401dcc6adbSGurchetan Singh QTAILQ_INSERT_HEAD(&g->reslist, res, next);
6411dcc6adbSGurchetan Singh res = NULL;
6421dcc6adbSGurchetan Singh }
6431dcc6adbSGurchetan Singh
6441dcc6adbSGurchetan Singh static void
rutabaga_cmd_resource_map_blob(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)6451dcc6adbSGurchetan Singh rutabaga_cmd_resource_map_blob(VirtIOGPU *g,
6461dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
6471dcc6adbSGurchetan Singh {
6481dcc6adbSGurchetan Singh int32_t result;
6491dcc6adbSGurchetan Singh uint32_t map_info = 0;
6501dcc6adbSGurchetan Singh uint32_t slot = 0;
6511dcc6adbSGurchetan Singh struct virtio_gpu_simple_resource *res;
6521dcc6adbSGurchetan Singh struct rutabaga_mapping mapping = { 0 };
6531dcc6adbSGurchetan Singh struct virtio_gpu_resource_map_blob mblob;
6541dcc6adbSGurchetan Singh struct virtio_gpu_resp_map_info resp = { 0 };
6551dcc6adbSGurchetan Singh
6561dcc6adbSGurchetan Singh VirtIOGPUBase *vb = VIRTIO_GPU_BASE(g);
6571dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
6581dcc6adbSGurchetan Singh
6591dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(mblob);
6601dcc6adbSGurchetan Singh
6611dcc6adbSGurchetan Singh CHECK(mblob.resource_id != 0, cmd);
6621dcc6adbSGurchetan Singh
6631dcc6adbSGurchetan Singh res = virtio_gpu_find_resource(g, mblob.resource_id);
6641dcc6adbSGurchetan Singh CHECK(res, cmd);
6651dcc6adbSGurchetan Singh
6661dcc6adbSGurchetan Singh result = rutabaga_resource_map_info(vr->rutabaga, mblob.resource_id,
6671dcc6adbSGurchetan Singh &map_info);
6681dcc6adbSGurchetan Singh CHECK(!result, cmd);
6691dcc6adbSGurchetan Singh
6701dcc6adbSGurchetan Singh /*
6711dcc6adbSGurchetan Singh * RUTABAGA_MAP_ACCESS_* flags are not part of the virtio-gpu spec, but do
6721dcc6adbSGurchetan Singh * exist to potentially allow the hypervisor to restrict write access to
6731dcc6adbSGurchetan Singh * memory. QEMU does not need to use this functionality at the moment.
6741dcc6adbSGurchetan Singh */
6751dcc6adbSGurchetan Singh resp.map_info = map_info & RUTABAGA_MAP_CACHE_MASK;
6761dcc6adbSGurchetan Singh
6771dcc6adbSGurchetan Singh result = rutabaga_resource_map(vr->rutabaga, mblob.resource_id, &mapping);
6781dcc6adbSGurchetan Singh CHECK(!result, cmd);
6791dcc6adbSGurchetan Singh
6801dcc6adbSGurchetan Singh /*
6811dcc6adbSGurchetan Singh * There is small risk of the MemoryRegion dereferencing the pointer after
6821dcc6adbSGurchetan Singh * rutabaga unmaps it. Please see discussion here:
6831dcc6adbSGurchetan Singh *
6841dcc6adbSGurchetan Singh * https://lists.gnu.org/archive/html/qemu-devel/2023-09/msg05141.html
6851dcc6adbSGurchetan Singh *
6861dcc6adbSGurchetan Singh * It is highly unlikely to happen in practice and doesn't affect known
6871dcc6adbSGurchetan Singh * use cases. However, it should be fixed and is noted here for posterity.
6881dcc6adbSGurchetan Singh */
6891dcc6adbSGurchetan Singh for (slot = 0; slot < MAX_SLOTS; slot++) {
6901dcc6adbSGurchetan Singh if (vr->memory_regions[slot].used) {
6911dcc6adbSGurchetan Singh continue;
6921dcc6adbSGurchetan Singh }
6931dcc6adbSGurchetan Singh
6941dcc6adbSGurchetan Singh MemoryRegion *mr = &(vr->memory_regions[slot].mr);
6951dcc6adbSGurchetan Singh memory_region_init_ram_ptr(mr, OBJECT(vr), "blob", mapping.size,
6961dcc6adbSGurchetan Singh mapping.ptr);
6971dcc6adbSGurchetan Singh memory_region_add_subregion(&vb->hostmem, mblob.offset, mr);
6981dcc6adbSGurchetan Singh vr->memory_regions[slot].resource_id = mblob.resource_id;
6991dcc6adbSGurchetan Singh vr->memory_regions[slot].used = 1;
7001dcc6adbSGurchetan Singh break;
7011dcc6adbSGurchetan Singh }
7021dcc6adbSGurchetan Singh
7031dcc6adbSGurchetan Singh if (slot >= MAX_SLOTS) {
7041dcc6adbSGurchetan Singh result = rutabaga_resource_unmap(vr->rutabaga, mblob.resource_id);
7051dcc6adbSGurchetan Singh CHECK(!result, cmd);
7061dcc6adbSGurchetan Singh }
7071dcc6adbSGurchetan Singh
7081dcc6adbSGurchetan Singh CHECK(slot < MAX_SLOTS, cmd);
7091dcc6adbSGurchetan Singh
7101dcc6adbSGurchetan Singh resp.hdr.type = VIRTIO_GPU_RESP_OK_MAP_INFO;
7111dcc6adbSGurchetan Singh virtio_gpu_ctrl_response(g, cmd, &resp.hdr, sizeof(resp));
7121dcc6adbSGurchetan Singh }
7131dcc6adbSGurchetan Singh
7141dcc6adbSGurchetan Singh static void
rutabaga_cmd_resource_unmap_blob(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)7151dcc6adbSGurchetan Singh rutabaga_cmd_resource_unmap_blob(VirtIOGPU *g,
7161dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
7171dcc6adbSGurchetan Singh {
7181dcc6adbSGurchetan Singh int32_t result;
7191dcc6adbSGurchetan Singh uint32_t slot = 0;
7201dcc6adbSGurchetan Singh struct virtio_gpu_simple_resource *res;
7211dcc6adbSGurchetan Singh struct virtio_gpu_resource_unmap_blob ublob;
7221dcc6adbSGurchetan Singh
7231dcc6adbSGurchetan Singh VirtIOGPUBase *vb = VIRTIO_GPU_BASE(g);
7241dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
7251dcc6adbSGurchetan Singh
7261dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(ublob);
7271dcc6adbSGurchetan Singh
7281dcc6adbSGurchetan Singh CHECK(ublob.resource_id != 0, cmd);
7291dcc6adbSGurchetan Singh
7301dcc6adbSGurchetan Singh res = virtio_gpu_find_resource(g, ublob.resource_id);
7311dcc6adbSGurchetan Singh CHECK(res, cmd);
7321dcc6adbSGurchetan Singh
7331dcc6adbSGurchetan Singh for (slot = 0; slot < MAX_SLOTS; slot++) {
7341dcc6adbSGurchetan Singh if (vr->memory_regions[slot].resource_id != ublob.resource_id) {
7351dcc6adbSGurchetan Singh continue;
7361dcc6adbSGurchetan Singh }
7371dcc6adbSGurchetan Singh
7381dcc6adbSGurchetan Singh MemoryRegion *mr = &(vr->memory_regions[slot].mr);
7391dcc6adbSGurchetan Singh memory_region_del_subregion(&vb->hostmem, mr);
7401dcc6adbSGurchetan Singh
7411dcc6adbSGurchetan Singh vr->memory_regions[slot].resource_id = 0;
7421dcc6adbSGurchetan Singh vr->memory_regions[slot].used = 0;
7431dcc6adbSGurchetan Singh break;
7441dcc6adbSGurchetan Singh }
7451dcc6adbSGurchetan Singh
7461dcc6adbSGurchetan Singh CHECK(slot < MAX_SLOTS, cmd);
7471dcc6adbSGurchetan Singh result = rutabaga_resource_unmap(vr->rutabaga, res->resource_id);
7481dcc6adbSGurchetan Singh CHECK(!result, cmd);
7491dcc6adbSGurchetan Singh }
7501dcc6adbSGurchetan Singh
7511dcc6adbSGurchetan Singh static void
virtio_gpu_rutabaga_process_cmd(VirtIOGPU * g,struct virtio_gpu_ctrl_command * cmd)7521dcc6adbSGurchetan Singh virtio_gpu_rutabaga_process_cmd(VirtIOGPU *g,
7531dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd)
7541dcc6adbSGurchetan Singh {
7551dcc6adbSGurchetan Singh struct rutabaga_fence fence = { 0 };
7561dcc6adbSGurchetan Singh int32_t result;
7571dcc6adbSGurchetan Singh
7581dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
7591dcc6adbSGurchetan Singh
7601dcc6adbSGurchetan Singh VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr);
7611dcc6adbSGurchetan Singh
7621dcc6adbSGurchetan Singh switch (cmd->cmd_hdr.type) {
7631dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_CTX_CREATE:
7641dcc6adbSGurchetan Singh rutabaga_cmd_context_create(g, cmd);
7651dcc6adbSGurchetan Singh break;
7661dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_CTX_DESTROY:
7671dcc6adbSGurchetan Singh rutabaga_cmd_context_destroy(g, cmd);
7681dcc6adbSGurchetan Singh break;
7691dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D:
7701dcc6adbSGurchetan Singh rutabaga_cmd_create_resource_2d(g, cmd);
7711dcc6adbSGurchetan Singh break;
7721dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_RESOURCE_CREATE_3D:
7731dcc6adbSGurchetan Singh rutabaga_cmd_create_resource_3d(g, cmd);
7741dcc6adbSGurchetan Singh break;
7751dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_SUBMIT_3D:
7761dcc6adbSGurchetan Singh rutabaga_cmd_submit_3d(g, cmd);
7771dcc6adbSGurchetan Singh break;
7781dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D:
7791dcc6adbSGurchetan Singh rutabaga_cmd_transfer_to_host_2d(g, cmd);
7801dcc6adbSGurchetan Singh break;
7811dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D:
7821dcc6adbSGurchetan Singh rutabaga_cmd_transfer_to_host_3d(g, cmd);
7831dcc6adbSGurchetan Singh break;
7841dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D:
7851dcc6adbSGurchetan Singh rutabaga_cmd_transfer_from_host_3d(g, cmd);
7861dcc6adbSGurchetan Singh break;
7871dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING:
7881dcc6adbSGurchetan Singh rutabaga_cmd_attach_backing(g, cmd);
7891dcc6adbSGurchetan Singh break;
7901dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING:
7911dcc6adbSGurchetan Singh rutabaga_cmd_detach_backing(g, cmd);
7921dcc6adbSGurchetan Singh break;
7931dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_SET_SCANOUT:
7941dcc6adbSGurchetan Singh rutabaga_cmd_set_scanout(g, cmd);
7951dcc6adbSGurchetan Singh break;
7961dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_RESOURCE_FLUSH:
7971dcc6adbSGurchetan Singh rutabaga_cmd_resource_flush(g, cmd);
7981dcc6adbSGurchetan Singh break;
7991dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_RESOURCE_UNREF:
8001dcc6adbSGurchetan Singh rutabaga_cmd_resource_unref(g, cmd);
8011dcc6adbSGurchetan Singh break;
8021dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE:
8031dcc6adbSGurchetan Singh rutabaga_cmd_ctx_attach_resource(g, cmd);
8041dcc6adbSGurchetan Singh break;
8051dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE:
8061dcc6adbSGurchetan Singh rutabaga_cmd_ctx_detach_resource(g, cmd);
8071dcc6adbSGurchetan Singh break;
8081dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_GET_CAPSET_INFO:
8091dcc6adbSGurchetan Singh rutabaga_cmd_get_capset_info(g, cmd);
8101dcc6adbSGurchetan Singh break;
8111dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_GET_CAPSET:
8121dcc6adbSGurchetan Singh rutabaga_cmd_get_capset(g, cmd);
8131dcc6adbSGurchetan Singh break;
8141dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_GET_DISPLAY_INFO:
8151dcc6adbSGurchetan Singh virtio_gpu_get_display_info(g, cmd);
8161dcc6adbSGurchetan Singh break;
8171dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_GET_EDID:
8181dcc6adbSGurchetan Singh virtio_gpu_get_edid(g, cmd);
8191dcc6adbSGurchetan Singh break;
8201dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB:
8211dcc6adbSGurchetan Singh rutabaga_cmd_resource_create_blob(g, cmd);
8221dcc6adbSGurchetan Singh break;
8231dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB:
8241dcc6adbSGurchetan Singh rutabaga_cmd_resource_map_blob(g, cmd);
8251dcc6adbSGurchetan Singh break;
8261dcc6adbSGurchetan Singh case VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB:
8271dcc6adbSGurchetan Singh rutabaga_cmd_resource_unmap_blob(g, cmd);
8281dcc6adbSGurchetan Singh break;
8291dcc6adbSGurchetan Singh default:
8301dcc6adbSGurchetan Singh cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
8311dcc6adbSGurchetan Singh break;
8321dcc6adbSGurchetan Singh }
8331dcc6adbSGurchetan Singh
8341dcc6adbSGurchetan Singh if (cmd->finished) {
8351dcc6adbSGurchetan Singh return;
8361dcc6adbSGurchetan Singh }
8371dcc6adbSGurchetan Singh if (cmd->error) {
8381dcc6adbSGurchetan Singh error_report("%s: ctrl 0x%x, error 0x%x", __func__,
8391dcc6adbSGurchetan Singh cmd->cmd_hdr.type, cmd->error);
8401dcc6adbSGurchetan Singh virtio_gpu_ctrl_response_nodata(g, cmd, cmd->error);
8411dcc6adbSGurchetan Singh return;
8421dcc6adbSGurchetan Singh }
8431dcc6adbSGurchetan Singh if (!(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) {
8441dcc6adbSGurchetan Singh virtio_gpu_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA);
8451dcc6adbSGurchetan Singh return;
8461dcc6adbSGurchetan Singh }
8471dcc6adbSGurchetan Singh
8481dcc6adbSGurchetan Singh fence.flags = cmd->cmd_hdr.flags;
8491dcc6adbSGurchetan Singh fence.ctx_id = cmd->cmd_hdr.ctx_id;
8501dcc6adbSGurchetan Singh fence.fence_id = cmd->cmd_hdr.fence_id;
8511dcc6adbSGurchetan Singh fence.ring_idx = cmd->cmd_hdr.ring_idx;
8521dcc6adbSGurchetan Singh
8531dcc6adbSGurchetan Singh trace_virtio_gpu_fence_ctrl(cmd->cmd_hdr.fence_id, cmd->cmd_hdr.type);
8541dcc6adbSGurchetan Singh
8551dcc6adbSGurchetan Singh result = rutabaga_create_fence(vr->rutabaga, &fence);
8561dcc6adbSGurchetan Singh CHECK(!result, cmd);
8571dcc6adbSGurchetan Singh }
8581dcc6adbSGurchetan Singh
8591dcc6adbSGurchetan Singh static void
virtio_gpu_rutabaga_aio_cb(void * opaque)8601dcc6adbSGurchetan Singh virtio_gpu_rutabaga_aio_cb(void *opaque)
8611dcc6adbSGurchetan Singh {
8621dcc6adbSGurchetan Singh struct rutabaga_aio_data *data = opaque;
8631dcc6adbSGurchetan Singh VirtIOGPU *g = VIRTIO_GPU(data->vr);
8641dcc6adbSGurchetan Singh struct rutabaga_fence fence_data = data->fence;
8651dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd, *tmp;
8661dcc6adbSGurchetan Singh
8671dcc6adbSGurchetan Singh uint32_t signaled_ctx_specific = fence_data.flags &
8681dcc6adbSGurchetan Singh RUTABAGA_FLAG_INFO_RING_IDX;
8691dcc6adbSGurchetan Singh
8701dcc6adbSGurchetan Singh QTAILQ_FOREACH_SAFE(cmd, &g->fenceq, next, tmp) {
8711dcc6adbSGurchetan Singh /*
8721dcc6adbSGurchetan Singh * Due to context specific timelines.
8731dcc6adbSGurchetan Singh */
8741dcc6adbSGurchetan Singh uint32_t target_ctx_specific = cmd->cmd_hdr.flags &
8751dcc6adbSGurchetan Singh RUTABAGA_FLAG_INFO_RING_IDX;
8761dcc6adbSGurchetan Singh
8771dcc6adbSGurchetan Singh if (signaled_ctx_specific != target_ctx_specific) {
8781dcc6adbSGurchetan Singh continue;
8791dcc6adbSGurchetan Singh }
8801dcc6adbSGurchetan Singh
8811dcc6adbSGurchetan Singh if (signaled_ctx_specific &&
8821dcc6adbSGurchetan Singh (cmd->cmd_hdr.ring_idx != fence_data.ring_idx)) {
8831dcc6adbSGurchetan Singh continue;
8841dcc6adbSGurchetan Singh }
8851dcc6adbSGurchetan Singh
8861dcc6adbSGurchetan Singh if (cmd->cmd_hdr.fence_id > fence_data.fence_id) {
8871dcc6adbSGurchetan Singh continue;
8881dcc6adbSGurchetan Singh }
8891dcc6adbSGurchetan Singh
8901dcc6adbSGurchetan Singh trace_virtio_gpu_fence_resp(cmd->cmd_hdr.fence_id);
8911dcc6adbSGurchetan Singh virtio_gpu_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA);
8921dcc6adbSGurchetan Singh QTAILQ_REMOVE(&g->fenceq, cmd, next);
8931dcc6adbSGurchetan Singh g_free(cmd);
8941dcc6adbSGurchetan Singh }
8951dcc6adbSGurchetan Singh
8961dcc6adbSGurchetan Singh g_free(data);
8971dcc6adbSGurchetan Singh }
8981dcc6adbSGurchetan Singh
8991dcc6adbSGurchetan Singh static void
virtio_gpu_rutabaga_fence_cb(uint64_t user_data,const struct rutabaga_fence * fence)9001dcc6adbSGurchetan Singh virtio_gpu_rutabaga_fence_cb(uint64_t user_data,
9011dcc6adbSGurchetan Singh const struct rutabaga_fence *fence)
9021dcc6adbSGurchetan Singh {
9031dcc6adbSGurchetan Singh struct rutabaga_aio_data *data;
9041dcc6adbSGurchetan Singh VirtIOGPU *g = (VirtIOGPU *)user_data;
9051dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
9061dcc6adbSGurchetan Singh
9071dcc6adbSGurchetan Singh /*
9081dcc6adbSGurchetan Singh * gfxstream and both cross-domain (and even newer versions virglrenderer:
9091dcc6adbSGurchetan Singh * see VIRGL_RENDERER_ASYNC_FENCE_CB) like to signal fence completion on
9101dcc6adbSGurchetan Singh * threads ("callback threads") that are different from the thread that
9111dcc6adbSGurchetan Singh * processes the command queue ("main thread").
9121dcc6adbSGurchetan Singh *
9131dcc6adbSGurchetan Singh * crosvm and other virtio-gpu 1.1 implementations enable callback threads
9141dcc6adbSGurchetan Singh * via locking. However, on QEMU a deadlock is observed if
9151dcc6adbSGurchetan Singh * virtio_gpu_ctrl_response_nodata(..) [used in the fence callback] is used
9161dcc6adbSGurchetan Singh * from a thread that is not the main thread.
9171dcc6adbSGurchetan Singh *
9181dcc6adbSGurchetan Singh * The reason is QEMU's internal locking is designed to work with QEMU
9191dcc6adbSGurchetan Singh * threads (see rcu_register_thread()) and not generic C/C++/Rust threads.
9201dcc6adbSGurchetan Singh * For now, we can workaround this by scheduling the return of the
9211dcc6adbSGurchetan Singh * fence descriptors on the main thread.
9221dcc6adbSGurchetan Singh */
9231dcc6adbSGurchetan Singh
9241dcc6adbSGurchetan Singh data = g_new0(struct rutabaga_aio_data, 1);
9251dcc6adbSGurchetan Singh data->vr = vr;
9261dcc6adbSGurchetan Singh data->fence = *fence;
9271dcc6adbSGurchetan Singh aio_bh_schedule_oneshot(qemu_get_aio_context(),
9281dcc6adbSGurchetan Singh virtio_gpu_rutabaga_aio_cb,
9291dcc6adbSGurchetan Singh data);
9301dcc6adbSGurchetan Singh }
9311dcc6adbSGurchetan Singh
9321dcc6adbSGurchetan Singh static void
virtio_gpu_rutabaga_debug_cb(uint64_t user_data,const struct rutabaga_debug * debug)9331dcc6adbSGurchetan Singh virtio_gpu_rutabaga_debug_cb(uint64_t user_data,
9341dcc6adbSGurchetan Singh const struct rutabaga_debug *debug)
9351dcc6adbSGurchetan Singh {
9361dcc6adbSGurchetan Singh switch (debug->debug_type) {
9371dcc6adbSGurchetan Singh case RUTABAGA_DEBUG_ERROR:
9381dcc6adbSGurchetan Singh error_report("%s", debug->message);
9391dcc6adbSGurchetan Singh break;
9401dcc6adbSGurchetan Singh case RUTABAGA_DEBUG_WARN:
9411dcc6adbSGurchetan Singh warn_report("%s", debug->message);
9421dcc6adbSGurchetan Singh break;
9431dcc6adbSGurchetan Singh case RUTABAGA_DEBUG_INFO:
9441dcc6adbSGurchetan Singh info_report("%s", debug->message);
9451dcc6adbSGurchetan Singh break;
9461dcc6adbSGurchetan Singh default:
9471dcc6adbSGurchetan Singh error_report("unknown debug type: %u", debug->debug_type);
9481dcc6adbSGurchetan Singh }
9491dcc6adbSGurchetan Singh }
9501dcc6adbSGurchetan Singh
virtio_gpu_rutabaga_init(VirtIOGPU * g,Error ** errp)9511dcc6adbSGurchetan Singh static bool virtio_gpu_rutabaga_init(VirtIOGPU *g, Error **errp)
9521dcc6adbSGurchetan Singh {
9531dcc6adbSGurchetan Singh int result;
9541dcc6adbSGurchetan Singh struct rutabaga_builder builder = { 0 };
9551dcc6adbSGurchetan Singh struct rutabaga_channel channel = { 0 };
9561dcc6adbSGurchetan Singh struct rutabaga_channels channels = { 0 };
9571dcc6adbSGurchetan Singh
9581dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
9591dcc6adbSGurchetan Singh vr->rutabaga = NULL;
9601dcc6adbSGurchetan Singh
9611dcc6adbSGurchetan Singh builder.wsi = RUTABAGA_WSI_SURFACELESS;
9621dcc6adbSGurchetan Singh /*
9631dcc6adbSGurchetan Singh * Currently, if WSI is specified, the only valid strings are "surfaceless"
9641dcc6adbSGurchetan Singh * or "headless". Surfaceless doesn't create a native window surface, but
9651dcc6adbSGurchetan Singh * does copy from the render target to the Pixman buffer if a virtio-gpu
9661dcc6adbSGurchetan Singh * 2D hypercall is issued. Surfacless is the default.
9671dcc6adbSGurchetan Singh *
9681dcc6adbSGurchetan Singh * Headless is like surfaceless, but doesn't copy to the Pixman buffer. The
9691dcc6adbSGurchetan Singh * use case is automated testing environments where there is no need to view
9701dcc6adbSGurchetan Singh * results.
9711dcc6adbSGurchetan Singh *
9721dcc6adbSGurchetan Singh * In the future, more performant virtio-gpu 2D UI integration may be added.
9731dcc6adbSGurchetan Singh */
9741dcc6adbSGurchetan Singh if (vr->wsi) {
9751dcc6adbSGurchetan Singh if (g_str_equal(vr->wsi, "surfaceless")) {
9761dcc6adbSGurchetan Singh vr->headless = false;
9771dcc6adbSGurchetan Singh } else if (g_str_equal(vr->wsi, "headless")) {
9781dcc6adbSGurchetan Singh vr->headless = true;
9791dcc6adbSGurchetan Singh } else {
9801dcc6adbSGurchetan Singh error_setg(errp, "invalid wsi option selected");
9811dcc6adbSGurchetan Singh return false;
9821dcc6adbSGurchetan Singh }
9831dcc6adbSGurchetan Singh }
9841dcc6adbSGurchetan Singh
9851dcc6adbSGurchetan Singh builder.fence_cb = virtio_gpu_rutabaga_fence_cb;
9861dcc6adbSGurchetan Singh builder.debug_cb = virtio_gpu_rutabaga_debug_cb;
9871dcc6adbSGurchetan Singh builder.capset_mask = vr->capset_mask;
9881dcc6adbSGurchetan Singh builder.user_data = (uint64_t)g;
9891dcc6adbSGurchetan Singh
9901dcc6adbSGurchetan Singh /*
9911dcc6adbSGurchetan Singh * If the user doesn't specify the wayland socket path, we try to infer
9921dcc6adbSGurchetan Singh * the socket via a process similar to the one used by libwayland.
9931dcc6adbSGurchetan Singh * libwayland does the following:
9941dcc6adbSGurchetan Singh *
9951dcc6adbSGurchetan Singh * 1) If $WAYLAND_DISPLAY is set, attempt to connect to
9961dcc6adbSGurchetan Singh * $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY
9971dcc6adbSGurchetan Singh * 2) Otherwise, attempt to connect to $XDG_RUNTIME_DIR/wayland-0
9981dcc6adbSGurchetan Singh * 3) Otherwise, don't pass a wayland socket to rutabaga. If a guest
9991dcc6adbSGurchetan Singh * wayland proxy is launched, it will fail to work.
10001dcc6adbSGurchetan Singh */
10011dcc6adbSGurchetan Singh channel.channel_type = RUTABAGA_CHANNEL_TYPE_WAYLAND;
10021dcc6adbSGurchetan Singh g_autofree gchar *path = NULL;
10031dcc6adbSGurchetan Singh if (!vr->wayland_socket_path) {
10041dcc6adbSGurchetan Singh const gchar *runtime_dir = g_get_user_runtime_dir();
10051dcc6adbSGurchetan Singh const gchar *display = g_getenv("WAYLAND_DISPLAY");
10061dcc6adbSGurchetan Singh if (!display) {
10071dcc6adbSGurchetan Singh display = "wayland-0";
10081dcc6adbSGurchetan Singh }
10091dcc6adbSGurchetan Singh
10101dcc6adbSGurchetan Singh if (runtime_dir) {
10111dcc6adbSGurchetan Singh path = g_build_filename(runtime_dir, display, NULL);
10121dcc6adbSGurchetan Singh channel.channel_name = path;
10131dcc6adbSGurchetan Singh }
10141dcc6adbSGurchetan Singh } else {
10151dcc6adbSGurchetan Singh channel.channel_name = vr->wayland_socket_path;
10161dcc6adbSGurchetan Singh }
10171dcc6adbSGurchetan Singh
10181dcc6adbSGurchetan Singh if ((builder.capset_mask & (1 << RUTABAGA_CAPSET_CROSS_DOMAIN))) {
10191dcc6adbSGurchetan Singh if (channel.channel_name) {
10201dcc6adbSGurchetan Singh channels.channels = &channel;
10211dcc6adbSGurchetan Singh channels.num_channels = 1;
10221dcc6adbSGurchetan Singh builder.channels = &channels;
10231dcc6adbSGurchetan Singh }
10241dcc6adbSGurchetan Singh }
10251dcc6adbSGurchetan Singh
10261dcc6adbSGurchetan Singh result = rutabaga_init(&builder, &vr->rutabaga);
10271dcc6adbSGurchetan Singh if (result) {
10281dcc6adbSGurchetan Singh error_setg_errno(errp, -result, "Failed to init rutabaga");
10291dcc6adbSGurchetan Singh return false;
10301dcc6adbSGurchetan Singh }
10311dcc6adbSGurchetan Singh
10321dcc6adbSGurchetan Singh return true;
10331dcc6adbSGurchetan Singh }
10341dcc6adbSGurchetan Singh
virtio_gpu_rutabaga_get_num_capsets(VirtIOGPU * g)10351dcc6adbSGurchetan Singh static int virtio_gpu_rutabaga_get_num_capsets(VirtIOGPU *g)
10361dcc6adbSGurchetan Singh {
10371dcc6adbSGurchetan Singh int result;
10381dcc6adbSGurchetan Singh uint32_t num_capsets;
10391dcc6adbSGurchetan Singh VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
10401dcc6adbSGurchetan Singh
10411dcc6adbSGurchetan Singh result = rutabaga_get_num_capsets(vr->rutabaga, &num_capsets);
10421dcc6adbSGurchetan Singh if (result) {
10431dcc6adbSGurchetan Singh error_report("Failed to get capsets");
10441dcc6adbSGurchetan Singh return 0;
10451dcc6adbSGurchetan Singh }
10461dcc6adbSGurchetan Singh vr->num_capsets = num_capsets;
10471dcc6adbSGurchetan Singh return num_capsets;
10481dcc6adbSGurchetan Singh }
10491dcc6adbSGurchetan Singh
virtio_gpu_rutabaga_handle_ctrl(VirtIODevice * vdev,VirtQueue * vq)10501dcc6adbSGurchetan Singh static void virtio_gpu_rutabaga_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
10511dcc6adbSGurchetan Singh {
10521dcc6adbSGurchetan Singh VirtIOGPU *g = VIRTIO_GPU(vdev);
10531dcc6adbSGurchetan Singh struct virtio_gpu_ctrl_command *cmd;
10541dcc6adbSGurchetan Singh
10551dcc6adbSGurchetan Singh if (!virtio_queue_ready(vq)) {
10561dcc6adbSGurchetan Singh return;
10571dcc6adbSGurchetan Singh }
10581dcc6adbSGurchetan Singh
10591dcc6adbSGurchetan Singh cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
10601dcc6adbSGurchetan Singh while (cmd) {
10611dcc6adbSGurchetan Singh cmd->vq = vq;
10621dcc6adbSGurchetan Singh cmd->error = 0;
10631dcc6adbSGurchetan Singh cmd->finished = false;
10641dcc6adbSGurchetan Singh QTAILQ_INSERT_TAIL(&g->cmdq, cmd, next);
10651dcc6adbSGurchetan Singh cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
10661dcc6adbSGurchetan Singh }
10671dcc6adbSGurchetan Singh
10681dcc6adbSGurchetan Singh virtio_gpu_process_cmdq(g);
10691dcc6adbSGurchetan Singh }
10701dcc6adbSGurchetan Singh
virtio_gpu_rutabaga_realize(DeviceState * qdev,Error ** errp)10711dcc6adbSGurchetan Singh static void virtio_gpu_rutabaga_realize(DeviceState *qdev, Error **errp)
10721dcc6adbSGurchetan Singh {
10731dcc6adbSGurchetan Singh int num_capsets;
10741dcc6adbSGurchetan Singh VirtIOGPUBase *bdev = VIRTIO_GPU_BASE(qdev);
10751dcc6adbSGurchetan Singh VirtIOGPU *gpudev = VIRTIO_GPU(qdev);
10761dcc6adbSGurchetan Singh
10771dcc6adbSGurchetan Singh #if HOST_BIG_ENDIAN
10781dcc6adbSGurchetan Singh error_setg(errp, "rutabaga is not supported on bigendian platforms");
10791dcc6adbSGurchetan Singh return;
10801dcc6adbSGurchetan Singh #endif
10811dcc6adbSGurchetan Singh
10821dcc6adbSGurchetan Singh if (!virtio_gpu_rutabaga_init(gpudev, errp)) {
10831dcc6adbSGurchetan Singh return;
10841dcc6adbSGurchetan Singh }
10851dcc6adbSGurchetan Singh
10861dcc6adbSGurchetan Singh num_capsets = virtio_gpu_rutabaga_get_num_capsets(gpudev);
10871dcc6adbSGurchetan Singh if (!num_capsets) {
10881dcc6adbSGurchetan Singh return;
10891dcc6adbSGurchetan Singh }
10901dcc6adbSGurchetan Singh
10911dcc6adbSGurchetan Singh bdev->conf.flags |= (1 << VIRTIO_GPU_FLAG_RUTABAGA_ENABLED);
10921dcc6adbSGurchetan Singh bdev->conf.flags |= (1 << VIRTIO_GPU_FLAG_BLOB_ENABLED);
10931dcc6adbSGurchetan Singh bdev->conf.flags |= (1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED);
10941dcc6adbSGurchetan Singh
10951dcc6adbSGurchetan Singh bdev->virtio_config.num_capsets = num_capsets;
10961dcc6adbSGurchetan Singh virtio_gpu_device_realize(qdev, errp);
10971dcc6adbSGurchetan Singh }
10981dcc6adbSGurchetan Singh
10991dcc6adbSGurchetan Singh static Property virtio_gpu_rutabaga_properties[] = {
11001dcc6adbSGurchetan Singh DEFINE_PROP_BIT64("gfxstream-vulkan", VirtIOGPURutabaga, capset_mask,
11011dcc6adbSGurchetan Singh RUTABAGA_CAPSET_GFXSTREAM_VULKAN, false),
11021dcc6adbSGurchetan Singh DEFINE_PROP_BIT64("cross-domain", VirtIOGPURutabaga, capset_mask,
11031dcc6adbSGurchetan Singh RUTABAGA_CAPSET_CROSS_DOMAIN, false),
11041dcc6adbSGurchetan Singh DEFINE_PROP_BIT64("x-gfxstream-gles", VirtIOGPURutabaga, capset_mask,
11051dcc6adbSGurchetan Singh RUTABAGA_CAPSET_GFXSTREAM_GLES, false),
11061dcc6adbSGurchetan Singh DEFINE_PROP_BIT64("x-gfxstream-composer", VirtIOGPURutabaga, capset_mask,
11071dcc6adbSGurchetan Singh RUTABAGA_CAPSET_GFXSTREAM_COMPOSER, false),
11081dcc6adbSGurchetan Singh DEFINE_PROP_STRING("wayland-socket-path", VirtIOGPURutabaga,
11091dcc6adbSGurchetan Singh wayland_socket_path),
11101dcc6adbSGurchetan Singh DEFINE_PROP_STRING("wsi", VirtIOGPURutabaga, wsi),
11111dcc6adbSGurchetan Singh DEFINE_PROP_END_OF_LIST(),
11121dcc6adbSGurchetan Singh };
11131dcc6adbSGurchetan Singh
virtio_gpu_rutabaga_class_init(ObjectClass * klass,void * data)11141dcc6adbSGurchetan Singh static void virtio_gpu_rutabaga_class_init(ObjectClass *klass, void *data)
11151dcc6adbSGurchetan Singh {
11161dcc6adbSGurchetan Singh DeviceClass *dc = DEVICE_CLASS(klass);
11171dcc6adbSGurchetan Singh VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
11181dcc6adbSGurchetan Singh VirtIOGPUBaseClass *vbc = VIRTIO_GPU_BASE_CLASS(klass);
11191dcc6adbSGurchetan Singh VirtIOGPUClass *vgc = VIRTIO_GPU_CLASS(klass);
11201dcc6adbSGurchetan Singh
11211dcc6adbSGurchetan Singh vbc->gl_flushed = virtio_gpu_rutabaga_gl_flushed;
11221dcc6adbSGurchetan Singh vgc->handle_ctrl = virtio_gpu_rutabaga_handle_ctrl;
11231dcc6adbSGurchetan Singh vgc->process_cmd = virtio_gpu_rutabaga_process_cmd;
11241dcc6adbSGurchetan Singh vgc->update_cursor_data = virtio_gpu_rutabaga_update_cursor;
1125*588a09daSManos Pitsidianakis vgc->resource_destroy = virtio_gpu_rutabaga_resource_unref;
11261dcc6adbSGurchetan Singh vdc->realize = virtio_gpu_rutabaga_realize;
11271dcc6adbSGurchetan Singh device_class_set_props(dc, virtio_gpu_rutabaga_properties);
11281dcc6adbSGurchetan Singh }
11291dcc6adbSGurchetan Singh
11301dcc6adbSGurchetan Singh static const TypeInfo virtio_gpu_rutabaga_info[] = {
11311dcc6adbSGurchetan Singh {
11321dcc6adbSGurchetan Singh .name = TYPE_VIRTIO_GPU_RUTABAGA,
11331dcc6adbSGurchetan Singh .parent = TYPE_VIRTIO_GPU,
11341dcc6adbSGurchetan Singh .instance_size = sizeof(VirtIOGPURutabaga),
11351dcc6adbSGurchetan Singh .class_init = virtio_gpu_rutabaga_class_init,
11361dcc6adbSGurchetan Singh },
11371dcc6adbSGurchetan Singh };
11381dcc6adbSGurchetan Singh
11391dcc6adbSGurchetan Singh DEFINE_TYPES(virtio_gpu_rutabaga_info)
11401dcc6adbSGurchetan Singh
11411dcc6adbSGurchetan Singh module_obj(TYPE_VIRTIO_GPU_RUTABAGA);
11421dcc6adbSGurchetan Singh module_kconfig(VIRTIO_GPU);
11431dcc6adbSGurchetan Singh module_dep("hw-display-virtio-gpu");
1144