2
0

virtio-gpu-gl.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #include "qemu/osdep.h"
  14. #include "qemu/iov.h"
  15. #include "qemu/module.h"
  16. #include "qemu/error-report.h"
  17. #include "qapi/error.h"
  18. #include "system/system.h"
  19. #include "hw/virtio/virtio.h"
  20. #include "hw/virtio/virtio-gpu.h"
  21. #include "hw/virtio/virtio-gpu-bswap.h"
  22. #include "hw/virtio/virtio-gpu-pixman.h"
  23. #include "hw/qdev-properties.h"
  24. #include <virglrenderer.h>
  25. static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
  26. struct virtio_gpu_scanout *s,
  27. uint32_t resource_id)
  28. {
  29. VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
  30. uint32_t width, height;
  31. uint32_t pixels, *data;
  32. if (gl->renderer_state != RS_INITED) {
  33. return;
  34. }
  35. data = virgl_renderer_get_cursor_data(resource_id, &width, &height);
  36. if (!data) {
  37. return;
  38. }
  39. if (width != s->current_cursor->width ||
  40. height != s->current_cursor->height) {
  41. free(data);
  42. return;
  43. }
  44. pixels = s->current_cursor->width * s->current_cursor->height;
  45. memcpy(s->current_cursor->data, data, pixels * sizeof(uint32_t));
  46. free(data);
  47. }
  48. static void virtio_gpu_gl_flushed(VirtIOGPUBase *b)
  49. {
  50. VirtIOGPU *g = VIRTIO_GPU(b);
  51. virtio_gpu_process_cmdq(g);
  52. }
  53. static void virtio_gpu_gl_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
  54. {
  55. VirtIOGPU *g = VIRTIO_GPU(vdev);
  56. VirtIOGPUGL *gl = VIRTIO_GPU_GL(vdev);
  57. struct virtio_gpu_ctrl_command *cmd;
  58. if (!virtio_queue_ready(vq)) {
  59. return;
  60. }
  61. switch (gl->renderer_state) {
  62. case RS_RESET:
  63. virtio_gpu_virgl_reset(g);
  64. /* fallthrough */
  65. case RS_START:
  66. if (virtio_gpu_virgl_init(g)) {
  67. gl->renderer_state = RS_INIT_FAILED;
  68. return;
  69. }
  70. gl->renderer_state = RS_INITED;
  71. break;
  72. case RS_INIT_FAILED:
  73. return;
  74. case RS_INITED:
  75. break;
  76. }
  77. cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
  78. while (cmd) {
  79. cmd->vq = vq;
  80. cmd->error = 0;
  81. cmd->finished = false;
  82. QTAILQ_INSERT_TAIL(&g->cmdq, cmd, next);
  83. cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
  84. }
  85. virtio_gpu_process_cmdq(g);
  86. virtio_gpu_virgl_fence_poll(g);
  87. }
  88. static void virtio_gpu_gl_reset(VirtIODevice *vdev)
  89. {
  90. VirtIOGPU *g = VIRTIO_GPU(vdev);
  91. VirtIOGPUGL *gl = VIRTIO_GPU_GL(vdev);
  92. virtio_gpu_reset(vdev);
  93. /*
  94. * GL functions must be called with the associated GL context in main
  95. * thread, and when the renderer is unblocked.
  96. */
  97. if (gl->renderer_state == RS_INITED) {
  98. virtio_gpu_virgl_reset_scanout(g);
  99. gl->renderer_state = RS_RESET;
  100. }
  101. }
  102. static void virtio_gpu_gl_device_realize(DeviceState *qdev, Error **errp)
  103. {
  104. ERRP_GUARD();
  105. VirtIOGPU *g = VIRTIO_GPU(qdev);
  106. #if HOST_BIG_ENDIAN
  107. error_setg(errp, "virgl is not supported on bigendian platforms");
  108. return;
  109. #endif
  110. if (!object_resolve_path_type("", TYPE_VIRTIO_GPU_GL, NULL)) {
  111. error_setg(errp, "at most one %s device is permitted", TYPE_VIRTIO_GPU_GL);
  112. return;
  113. }
  114. if (!display_opengl) {
  115. error_setg(errp,
  116. "The display backend does not have OpenGL support enabled");
  117. error_append_hint(errp,
  118. "It can be enabled with '-display BACKEND,gl=on' "
  119. "where BACKEND is the name of the display backend "
  120. "to use.\n");
  121. return;
  122. }
  123. g->parent_obj.conf.flags |= (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED);
  124. g->capset_ids = virtio_gpu_virgl_get_capsets(g);
  125. VIRTIO_GPU_BASE(g)->virtio_config.num_capsets = g->capset_ids->len;
  126. #if VIRGL_VERSION_MAJOR >= 1
  127. g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
  128. #endif
  129. virtio_gpu_device_realize(qdev, errp);
  130. }
  131. static const Property virtio_gpu_gl_properties[] = {
  132. DEFINE_PROP_BIT("stats", VirtIOGPU, parent_obj.conf.flags,
  133. VIRTIO_GPU_FLAG_STATS_ENABLED, false),
  134. DEFINE_PROP_BIT("venus", VirtIOGPU, parent_obj.conf.flags,
  135. VIRTIO_GPU_FLAG_VENUS_ENABLED, false),
  136. };
  137. static void virtio_gpu_gl_device_unrealize(DeviceState *qdev)
  138. {
  139. VirtIOGPU *g = VIRTIO_GPU(qdev);
  140. VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
  141. if (gl->renderer_state >= RS_INITED) {
  142. #if VIRGL_VERSION_MAJOR >= 1
  143. qemu_bh_delete(gl->cmdq_resume_bh);
  144. #endif
  145. if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
  146. timer_free(gl->print_stats);
  147. }
  148. timer_free(gl->fence_poll);
  149. virgl_renderer_cleanup(NULL);
  150. }
  151. gl->renderer_state = RS_START;
  152. g_array_unref(g->capset_ids);
  153. }
  154. static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
  155. {
  156. DeviceClass *dc = DEVICE_CLASS(klass);
  157. VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
  158. VirtIOGPUBaseClass *vbc = VIRTIO_GPU_BASE_CLASS(klass);
  159. VirtIOGPUClass *vgc = VIRTIO_GPU_CLASS(klass);
  160. vbc->gl_flushed = virtio_gpu_gl_flushed;
  161. vgc->handle_ctrl = virtio_gpu_gl_handle_ctrl;
  162. vgc->process_cmd = virtio_gpu_virgl_process_cmd;
  163. vgc->update_cursor_data = virtio_gpu_gl_update_cursor_data;
  164. vdc->realize = virtio_gpu_gl_device_realize;
  165. vdc->unrealize = virtio_gpu_gl_device_unrealize;
  166. vdc->reset = virtio_gpu_gl_reset;
  167. device_class_set_props(dc, virtio_gpu_gl_properties);
  168. }
  169. static const TypeInfo virtio_gpu_gl_info = {
  170. .name = TYPE_VIRTIO_GPU_GL,
  171. .parent = TYPE_VIRTIO_GPU,
  172. .instance_size = sizeof(VirtIOGPUGL),
  173. .class_init = virtio_gpu_gl_class_init,
  174. };
  175. module_obj(TYPE_VIRTIO_GPU_GL);
  176. module_kconfig(VIRTIO_GPU);
  177. static void virtio_register_types(void)
  178. {
  179. type_register_static(&virtio_gpu_gl_info);
  180. }
  181. type_init(virtio_register_types)
  182. module_dep("hw-display-virtio-gpu");
  183. module_dep("ui-opengl");