]>
Commit | Line | Data |
---|---|---|
063cd34a GH |
1 | /* |
2 | * Virtio GPU Device | |
3 | * | |
4 | * Copyright Red Hat, Inc. 2013-2014 | |
5 | * | |
6 | * Authors: | |
7 | * Dave Airlie <airlied@redhat.com> | |
8 | * Gerd Hoffmann <kraxel@redhat.com> | |
9 | * | |
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. | |
12 | */ | |
13 | ||
14 | #include "qemu/osdep.h" | |
15 | #include "qemu/iov.h" | |
16 | #include "qemu/module.h" | |
17 | #include "qemu/error-report.h" | |
18 | #include "qapi/error.h" | |
37f86af0 | 19 | #include "sysemu/sysemu.h" |
063cd34a GH |
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" | |
25 | ||
2c267d66 GH |
26 | #include <virglrenderer.h> |
27 | ||
28 | static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g, | |
29 | struct virtio_gpu_scanout *s, | |
30 | uint32_t resource_id) | |
31 | { | |
32 | uint32_t width, height; | |
33 | uint32_t pixels, *data; | |
34 | ||
49afbca3 GH |
35 | data = virgl_renderer_get_cursor_data(resource_id, &width, &height); |
36 | if (!data) { | |
2c267d66 GH |
37 | return; |
38 | } | |
2c267d66 | 39 | |
49afbca3 GH |
40 | if (width != s->current_cursor->width || |
41 | height != s->current_cursor->height) { | |
42 | free(data); | |
2f47691a GH |
43 | return; |
44 | } | |
49afbca3 GH |
45 | |
46 | pixels = s->current_cursor->width * s->current_cursor->height; | |
47 | memcpy(s->current_cursor->data, data, pixels * sizeof(uint32_t)); | |
48 | free(data); | |
2f47691a GH |
49 | } |
50 | ||
3e48b7a3 GH |
51 | static void virtio_gpu_gl_flushed(VirtIOGPUBase *b) |
52 | { | |
53 | VirtIOGPU *g = VIRTIO_GPU(b); | |
eff6fa17 | 54 | VirtIOGPUGL *gl = VIRTIO_GPU_GL(b); |
3e48b7a3 | 55 | |
eff6fa17 GH |
56 | if (gl->renderer_reset) { |
57 | gl->renderer_reset = false; | |
3e48b7a3 GH |
58 | virtio_gpu_virgl_reset(g); |
59 | } | |
60 | virtio_gpu_process_cmdq(g); | |
61 | } | |
62 | ||
ce537a4f GH |
63 | static void virtio_gpu_gl_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) |
64 | { | |
65 | VirtIOGPU *g = VIRTIO_GPU(vdev); | |
eff6fa17 | 66 | VirtIOGPUGL *gl = VIRTIO_GPU_GL(vdev); |
ce537a4f GH |
67 | struct virtio_gpu_ctrl_command *cmd; |
68 | ||
69 | if (!virtio_queue_ready(vq)) { | |
70 | return; | |
71 | } | |
72 | ||
eff6fa17 | 73 | if (!gl->renderer_inited) { |
ce537a4f | 74 | virtio_gpu_virgl_init(g); |
eff6fa17 | 75 | gl->renderer_inited = true; |
ce537a4f GH |
76 | } |
77 | ||
78 | cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command)); | |
79 | while (cmd) { | |
80 | cmd->vq = vq; | |
81 | cmd->error = 0; | |
82 | cmd->finished = false; | |
83 | QTAILQ_INSERT_TAIL(&g->cmdq, cmd, next); | |
84 | cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command)); | |
85 | } | |
86 | ||
87 | virtio_gpu_process_cmdq(g); | |
49afbca3 | 88 | virtio_gpu_virgl_fence_poll(g); |
ce537a4f GH |
89 | } |
90 | ||
76fa8b35 GH |
91 | static void virtio_gpu_gl_reset(VirtIODevice *vdev) |
92 | { | |
93 | VirtIOGPU *g = VIRTIO_GPU(vdev); | |
eff6fa17 | 94 | VirtIOGPUGL *gl = VIRTIO_GPU_GL(vdev); |
76fa8b35 GH |
95 | |
96 | virtio_gpu_reset(vdev); | |
97 | ||
eff6fa17 | 98 | if (gl->renderer_inited) { |
76fa8b35 | 99 | if (g->parent_obj.renderer_blocked) { |
eff6fa17 | 100 | gl->renderer_reset = true; |
76fa8b35 GH |
101 | } else { |
102 | virtio_gpu_virgl_reset(g); | |
103 | } | |
76fa8b35 GH |
104 | } |
105 | } | |
106 | ||
37f86af0 GH |
107 | static void virtio_gpu_gl_device_realize(DeviceState *qdev, Error **errp) |
108 | { | |
109 | VirtIOGPU *g = VIRTIO_GPU(qdev); | |
110 | ||
111 | #if defined(HOST_WORDS_BIGENDIAN) | |
112 | error_setg(errp, "virgl is not supported on bigendian platforms"); | |
113 | return; | |
114 | #endif | |
115 | ||
116 | if (!display_opengl) { | |
117 | error_setg(errp, "opengl is not available"); | |
118 | return; | |
119 | } | |
120 | ||
121 | g->parent_obj.conf.flags |= (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED); | |
122 | VIRTIO_GPU_BASE(g)->virtio_config.num_capsets = | |
123 | virtio_gpu_virgl_get_num_capsets(g); | |
124 | ||
125 | virtio_gpu_device_realize(qdev, errp); | |
126 | } | |
127 | ||
128 | static Property virtio_gpu_gl_properties[] = { | |
129 | DEFINE_PROP_BIT("stats", VirtIOGPU, parent_obj.conf.flags, | |
130 | VIRTIO_GPU_FLAG_STATS_ENABLED, false), | |
131 | DEFINE_PROP_END_OF_LIST(), | |
132 | }; | |
133 | ||
063cd34a GH |
134 | static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data) |
135 | { | |
37f86af0 GH |
136 | DeviceClass *dc = DEVICE_CLASS(klass); |
137 | VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); | |
3e48b7a3 | 138 | VirtIOGPUBaseClass *vbc = VIRTIO_GPU_BASE_CLASS(klass); |
ce537a4f GH |
139 | VirtIOGPUClass *vgc = VIRTIO_GPU_CLASS(klass); |
140 | ||
3e48b7a3 | 141 | vbc->gl_flushed = virtio_gpu_gl_flushed; |
ce537a4f | 142 | vgc->handle_ctrl = virtio_gpu_gl_handle_ctrl; |
49afbca3 | 143 | vgc->process_cmd = virtio_gpu_virgl_process_cmd; |
2c267d66 | 144 | vgc->update_cursor_data = virtio_gpu_gl_update_cursor_data; |
37f86af0 GH |
145 | |
146 | vdc->realize = virtio_gpu_gl_device_realize; | |
76fa8b35 | 147 | vdc->reset = virtio_gpu_gl_reset; |
37f86af0 | 148 | device_class_set_props(dc, virtio_gpu_gl_properties); |
063cd34a GH |
149 | } |
150 | ||
151 | static const TypeInfo virtio_gpu_gl_info = { | |
152 | .name = TYPE_VIRTIO_GPU_GL, | |
153 | .parent = TYPE_VIRTIO_GPU, | |
154 | .instance_size = sizeof(VirtIOGPUGL), | |
155 | .class_init = virtio_gpu_gl_class_init, | |
156 | }; | |
561d0f45 | 157 | module_obj(TYPE_VIRTIO_GPU_GL); |
063cd34a GH |
158 | |
159 | static void virtio_register_types(void) | |
160 | { | |
161 | type_register_static(&virtio_gpu_gl_info); | |
162 | } | |
163 | ||
164 | type_init(virtio_register_types) | |
561d0f45 GH |
165 | |
166 | module_dep("hw-display-virtio-gpu"); |