4 * Copyright Red Hat, Inc. 2013-2014
7 * Dave Airlie <airlied@redhat.com>
8 * Gerd Hoffmann <kraxel@redhat.com>
10 * This work is licensed under the terms of the GNU GPL, version 2 or later.
11 * See the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
16 #include "qemu/module.h"
17 #include "qemu/error-report.h"
18 #include "qapi/error.h"
19 #include "sysemu/sysemu.h"
20 #include "hw/virtio/virtio.h"
21 #include "hw/virtio/virtio-gpu.h"
22 #include "hw/virtio/virtio-gpu-bswap.h"
23 #include "hw/virtio/virtio-gpu-pixman.h"
24 #include "hw/qdev-properties.h"
26 #include <virglrenderer.h>
28 static void virtio_gpu_gl_update_cursor_data(VirtIOGPU
*g
,
29 struct virtio_gpu_scanout
*s
,
32 uint32_t width
, height
;
33 uint32_t pixels
, *data
;
35 data
= virgl_renderer_get_cursor_data(resource_id
, &width
, &height
);
40 if (width
!= s
->current_cursor
->width
||
41 height
!= s
->current_cursor
->height
) {
46 pixels
= s
->current_cursor
->width
* s
->current_cursor
->height
;
47 memcpy(s
->current_cursor
->data
, data
, pixels
* sizeof(uint32_t));
51 static void virtio_gpu_gl_flushed(VirtIOGPUBase
*b
)
53 VirtIOGPU
*g
= VIRTIO_GPU(b
);
55 virtio_gpu_process_cmdq(g
);
58 static void virtio_gpu_gl_handle_ctrl(VirtIODevice
*vdev
, VirtQueue
*vq
)
60 VirtIOGPU
*g
= VIRTIO_GPU(vdev
);
61 VirtIOGPUGL
*gl
= VIRTIO_GPU_GL(vdev
);
62 struct virtio_gpu_ctrl_command
*cmd
;
64 if (!virtio_queue_ready(vq
)) {
68 if (!gl
->renderer_inited
) {
69 virtio_gpu_virgl_init(g
);
70 gl
->renderer_inited
= true;
72 if (gl
->renderer_reset
) {
73 gl
->renderer_reset
= false;
74 virtio_gpu_virgl_reset(g
);
77 cmd
= virtqueue_pop(vq
, sizeof(struct virtio_gpu_ctrl_command
));
81 cmd
->finished
= false;
82 QTAILQ_INSERT_TAIL(&g
->cmdq
, cmd
, next
);
83 cmd
= virtqueue_pop(vq
, sizeof(struct virtio_gpu_ctrl_command
));
86 virtio_gpu_process_cmdq(g
);
87 virtio_gpu_virgl_fence_poll(g
);
90 static void virtio_gpu_gl_reset(VirtIODevice
*vdev
)
92 VirtIOGPU
*g
= VIRTIO_GPU(vdev
);
93 VirtIOGPUGL
*gl
= VIRTIO_GPU_GL(vdev
);
95 virtio_gpu_reset(vdev
);
98 * GL functions must be called with the associated GL context in main
99 * thread, and when the renderer is unblocked.
101 if (gl
->renderer_inited
&& !gl
->renderer_reset
) {
102 virtio_gpu_virgl_reset_scanout(g
);
103 gl
->renderer_reset
= true;
107 static void virtio_gpu_gl_device_realize(DeviceState
*qdev
, Error
**errp
)
110 VirtIOGPU
*g
= VIRTIO_GPU(qdev
);
113 error_setg(errp
, "virgl is not supported on bigendian platforms");
117 if (!object_resolve_path_type("", TYPE_VIRTIO_GPU_GL
, NULL
)) {
118 error_setg(errp
, "at most one %s device is permitted", TYPE_VIRTIO_GPU_GL
);
122 if (!display_opengl
) {
124 "The display backend does not have OpenGL support enabled");
125 error_append_hint(errp
,
126 "It can be enabled with '-display BACKEND,gl=on' "
127 "where BACKEND is the name of the display backend "
132 g
->parent_obj
.conf
.flags
|= (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED
);
133 VIRTIO_GPU_BASE(g
)->virtio_config
.num_capsets
=
134 virtio_gpu_virgl_get_num_capsets(g
);
136 virtio_gpu_device_realize(qdev
, errp
);
139 static Property virtio_gpu_gl_properties
[] = {
140 DEFINE_PROP_BIT("stats", VirtIOGPU
, parent_obj
.conf
.flags
,
141 VIRTIO_GPU_FLAG_STATS_ENABLED
, false),
142 DEFINE_PROP_END_OF_LIST(),
145 static void virtio_gpu_gl_class_init(ObjectClass
*klass
, void *data
)
147 DeviceClass
*dc
= DEVICE_CLASS(klass
);
148 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
149 VirtIOGPUBaseClass
*vbc
= VIRTIO_GPU_BASE_CLASS(klass
);
150 VirtIOGPUClass
*vgc
= VIRTIO_GPU_CLASS(klass
);
152 vbc
->gl_flushed
= virtio_gpu_gl_flushed
;
153 vgc
->handle_ctrl
= virtio_gpu_gl_handle_ctrl
;
154 vgc
->process_cmd
= virtio_gpu_virgl_process_cmd
;
155 vgc
->update_cursor_data
= virtio_gpu_gl_update_cursor_data
;
157 vdc
->realize
= virtio_gpu_gl_device_realize
;
158 vdc
->reset
= virtio_gpu_gl_reset
;
159 device_class_set_props(dc
, virtio_gpu_gl_properties
);
162 static const TypeInfo virtio_gpu_gl_info
= {
163 .name
= TYPE_VIRTIO_GPU_GL
,
164 .parent
= TYPE_VIRTIO_GPU
,
165 .instance_size
= sizeof(VirtIOGPUGL
),
166 .class_init
= virtio_gpu_gl_class_init
,
168 module_obj(TYPE_VIRTIO_GPU_GL
);
169 module_kconfig(VIRTIO_GPU
);
171 static void virtio_register_types(void)
173 type_register_static(&virtio_gpu_gl_info
);
176 type_init(virtio_register_types
)
178 module_dep("hw-display-virtio-gpu");
179 module_dep("ui-opengl");