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 "hw/virtio/virtio-gpu.h"
17 #include "migration/blocker.h"
18 #include "qapi/error.h"
19 #include "qemu/error-report.h"
23 virtio_gpu_base_reset(VirtIOGPUBase
*g
)
28 g
->use_virgl_renderer
= false;
30 for (i
= 0; i
< g
->conf
.max_outputs
; i
++) {
31 g
->scanout
[i
].resource_id
= 0;
32 g
->scanout
[i
].width
= 0;
33 g
->scanout
[i
].height
= 0;
36 g
->scanout
[i
].ds
= NULL
;
41 virtio_gpu_base_fill_display_info(VirtIOGPUBase
*g
,
42 struct virtio_gpu_resp_display_info
*dpy_info
)
46 for (i
= 0; i
< g
->conf
.max_outputs
; i
++) {
47 if (g
->enabled_output_bitmask
& (1 << i
)) {
48 dpy_info
->pmodes
[i
].enabled
= 1;
49 dpy_info
->pmodes
[i
].r
.width
= cpu_to_le32(g
->req_state
[i
].width
);
50 dpy_info
->pmodes
[i
].r
.height
= cpu_to_le32(g
->req_state
[i
].height
);
55 static void virtio_gpu_invalidate_display(void *opaque
)
59 static void virtio_gpu_update_display(void *opaque
)
63 static void virtio_gpu_text_update(void *opaque
, console_ch_t
*chardata
)
67 static void virtio_gpu_notify_event(VirtIOGPUBase
*g
, uint32_t event_type
)
69 g
->virtio_config
.events_read
|= event_type
;
70 virtio_notify_config(&g
->parent_obj
);
73 static int virtio_gpu_ui_info(void *opaque
, uint32_t idx
, QemuUIInfo
*info
)
75 VirtIOGPUBase
*g
= opaque
;
77 if (idx
>= g
->conf
.max_outputs
) {
81 g
->req_state
[idx
].x
= info
->xoff
;
82 g
->req_state
[idx
].y
= info
->yoff
;
83 g
->req_state
[idx
].width
= info
->width
;
84 g
->req_state
[idx
].height
= info
->height
;
86 if (info
->width
&& info
->height
) {
87 g
->enabled_output_bitmask
|= (1 << idx
);
89 g
->enabled_output_bitmask
&= ~(1 << idx
);
92 /* send event to guest */
93 virtio_gpu_notify_event(g
, VIRTIO_GPU_EVENT_DISPLAY
);
98 virtio_gpu_gl_block(void *opaque
, bool block
)
100 VirtIOGPUBase
*g
= opaque
;
101 VirtIOGPUBaseClass
*vgc
= VIRTIO_GPU_BASE_GET_CLASS(g
);
104 g
->renderer_blocked
++;
106 g
->renderer_blocked
--;
108 assert(g
->renderer_blocked
>= 0);
110 if (g
->renderer_blocked
== 0) {
115 const GraphicHwOps virtio_gpu_ops
= {
116 .invalidate
= virtio_gpu_invalidate_display
,
117 .gfx_update
= virtio_gpu_update_display
,
118 .text_update
= virtio_gpu_text_update
,
119 .ui_info
= virtio_gpu_ui_info
,
120 .gl_block
= virtio_gpu_gl_block
,
124 virtio_gpu_base_device_realize(DeviceState
*qdev
,
125 VirtIOHandleOutput ctrl_cb
,
126 VirtIOHandleOutput cursor_cb
,
129 VirtIODevice
*vdev
= VIRTIO_DEVICE(qdev
);
130 VirtIOGPUBase
*g
= VIRTIO_GPU_BASE(qdev
);
131 Error
*local_err
= NULL
;
134 if (g
->conf
.max_outputs
> VIRTIO_GPU_MAX_SCANOUTS
) {
135 error_setg(errp
, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS
);
139 g
->use_virgl_renderer
= false;
140 if (virtio_gpu_virgl_enabled(g
->conf
)) {
141 error_setg(&g
->migration_blocker
, "virgl is not yet migratable");
142 migrate_add_blocker(g
->migration_blocker
, &local_err
);
144 error_propagate(errp
, local_err
);
145 error_free(g
->migration_blocker
);
150 g
->virtio_config
.num_scanouts
= cpu_to_le32(g
->conf
.max_outputs
);
151 virtio_init(VIRTIO_DEVICE(g
), "virtio-gpu", VIRTIO_ID_GPU
,
152 sizeof(struct virtio_gpu_config
));
154 if (virtio_gpu_virgl_enabled(g
->conf
)) {
155 /* use larger control queue in 3d mode */
156 virtio_add_queue(vdev
, 256, ctrl_cb
);
157 virtio_add_queue(vdev
, 16, cursor_cb
);
159 virtio_add_queue(vdev
, 64, ctrl_cb
);
160 virtio_add_queue(vdev
, 16, cursor_cb
);
163 g
->enabled_output_bitmask
= 1;
165 g
->req_state
[0].width
= g
->conf
.xres
;
166 g
->req_state
[0].height
= g
->conf
.yres
;
168 for (i
= 0; i
< g
->conf
.max_outputs
; i
++) {
170 graphic_console_init(DEVICE(g
), i
, &virtio_gpu_ops
, g
);
172 dpy_gfx_replace_surface(g
->scanout
[i
].con
, NULL
);
180 virtio_gpu_base_get_features(VirtIODevice
*vdev
, uint64_t features
,
183 VirtIOGPUBase
*g
= VIRTIO_GPU_BASE(vdev
);
185 if (virtio_gpu_virgl_enabled(g
->conf
)) {
186 features
|= (1 << VIRTIO_GPU_F_VIRGL
);
188 if (virtio_gpu_edid_enabled(g
->conf
)) {
189 features
|= (1 << VIRTIO_GPU_F_EDID
);
196 virtio_gpu_base_set_features(VirtIODevice
*vdev
, uint64_t features
)
198 static const uint32_t virgl
= (1 << VIRTIO_GPU_F_VIRGL
);
199 VirtIOGPUBase
*g
= VIRTIO_GPU_BASE(vdev
);
201 g
->use_virgl_renderer
= ((features
& virgl
) == virgl
);
202 trace_virtio_gpu_features(g
->use_virgl_renderer
);
206 virtio_gpu_base_device_unrealize(DeviceState
*qdev
, Error
**errp
)
208 VirtIOGPUBase
*g
= VIRTIO_GPU_BASE(qdev
);
210 if (g
->migration_blocker
) {
211 migrate_del_blocker(g
->migration_blocker
);
212 error_free(g
->migration_blocker
);
217 virtio_gpu_base_class_init(ObjectClass
*klass
, void *data
)
219 DeviceClass
*dc
= DEVICE_CLASS(klass
);
220 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
222 vdc
->unrealize
= virtio_gpu_base_device_unrealize
;
223 vdc
->get_features
= virtio_gpu_base_get_features
;
224 vdc
->set_features
= virtio_gpu_base_set_features
;
226 set_bit(DEVICE_CATEGORY_DISPLAY
, dc
->categories
);
227 dc
->hotpluggable
= false;
230 static const TypeInfo virtio_gpu_base_info
= {
231 .name
= TYPE_VIRTIO_GPU_BASE
,
232 .parent
= TYPE_VIRTIO_DEVICE
,
233 .instance_size
= sizeof(VirtIOGPUBase
),
234 .class_size
= sizeof(VirtIOGPUBaseClass
),
235 .class_init
= virtio_gpu_base_class_init
,
240 virtio_register_types(void)
242 type_register_static(&virtio_gpu_base_info
);
245 type_init(virtio_register_types
)
247 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctrl_hdr
) != 24);
248 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_update_cursor
) != 56);
249 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_unref
) != 32);
250 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_2d
) != 40);
251 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_set_scanout
) != 48);
252 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_flush
) != 48);
253 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_to_host_2d
) != 56);
254 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_mem_entry
) != 16);
255 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_attach_backing
) != 32);
256 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_detach_backing
) != 32);
257 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_display_info
) != 408);
259 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_host_3d
) != 72);
260 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_3d
) != 72);
261 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_create
) != 96);
262 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_destroy
) != 24);
263 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_resource
) != 32);
264 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_cmd_submit
) != 32);
265 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset_info
) != 32);
266 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset_info
) != 40);
267 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset
) != 32);
268 QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset
) != 24);