qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/kraxel/tags/opengl-20171017-pull-request' into staging

ui: opengl updates for dma-buf support.

# gpg: Signature made Tue 17 Oct 2017 12:13:36 BST
# gpg: using RSA key 0x4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/opengl-20171017-pull-request:
egl-headless: add dmabuf support
egl-helpers: add egl_texture_blit and egl_texture_blend
egl-helpers: add dmabuf import support
opengl: add flipping vertex shader
opengl: move shader init from console-gl.c to shader.c
console: add support for dmabufs

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+283 -75
+4 -2
Makefile
··· 724 724 perl $(SRC_PATH)/scripts/shaderinclude.pl $< > $@,\ 725 725 "FRAG","$@") 726 726 727 - ui/console-gl.o: $(SRC_PATH)/ui/console-gl.c \ 728 - ui/shader/texture-blit-vert.h ui/shader/texture-blit-frag.h 727 + ui/shader.o: $(SRC_PATH)/ui/shader.c \ 728 + ui/shader/texture-blit-vert.h \ 729 + ui/shader/texture-blit-flip-vert.h \ 730 + ui/shader/texture-blit-frag.h 729 731 730 732 # documentation 731 733 MAKEINFO=makeinfo
+1
include/qemu/typedefs.h
··· 83 83 typedef struct PS2State PS2State; 84 84 typedef struct QEMUBH QEMUBH; 85 85 typedef struct QemuConsole QemuConsole; 86 + typedef struct QemuDmaBuf QemuDmaBuf; 86 87 typedef struct QEMUFile QEMUFile; 87 88 typedef struct QemuOpt QemuOpt; 88 89 typedef struct QemuOpts QemuOpts;
+31 -8
include/ui/console.h
··· 5 5 #include "qom/object.h" 6 6 #include "qapi/qmp/qdict.h" 7 7 #include "qemu/notify.h" 8 + #include "qemu/typedefs.h" 8 9 #include "qapi-types.h" 9 10 #include "qemu/error-report.h" 10 11 #include "qapi/error.h" 11 12 12 13 #ifdef CONFIG_OPENGL 13 14 # include <epoxy/gl.h> 15 + # include "ui/shader.h" 14 16 #endif 15 17 16 18 /* keyboard/mouse support */ ··· 180 182 int minor_ver; 181 183 }; 182 184 185 + struct QemuDmaBuf { 186 + int fd; 187 + uint32_t width; 188 + uint32_t height; 189 + uint32_t stride; 190 + uint32_t fourcc; 191 + uint32_t texture; 192 + }; 193 + 183 194 typedef struct DisplayChangeListenerOps { 184 195 const char *dpy_name; 185 196 ··· 220 231 uint32_t backing_height, 221 232 uint32_t x, uint32_t y, 222 233 uint32_t w, uint32_t h); 234 + void (*dpy_gl_scanout_dmabuf)(DisplayChangeListener *dcl, 235 + QemuDmaBuf *dmabuf); 236 + void (*dpy_gl_cursor_dmabuf)(DisplayChangeListener *dcl, 237 + QemuDmaBuf *dmabuf, 238 + uint32_t pos_x, uint32_t pos_y); 239 + void (*dpy_gl_release_dmabuf)(DisplayChangeListener *dcl, 240 + QemuDmaBuf *dmabuf); 223 241 void (*dpy_gl_update)(DisplayChangeListener *dcl, 224 242 uint32_t x, uint32_t y, uint32_t w, uint32_t h); 225 243 ··· 288 306 uint32_t backing_id, bool backing_y_0_top, 289 307 uint32_t backing_width, uint32_t backing_height, 290 308 uint32_t x, uint32_t y, uint32_t w, uint32_t h); 309 + void dpy_gl_scanout_dmabuf(QemuConsole *con, 310 + QemuDmaBuf *dmabuf); 311 + void dpy_gl_cursor_dmabuf(QemuConsole *con, 312 + QemuDmaBuf *dmabuf, 313 + uint32_t pos_x, uint32_t pos_y); 314 + void dpy_gl_release_dmabuf(QemuConsole *con, 315 + QemuDmaBuf *dmabuf); 291 316 void dpy_gl_update(QemuConsole *con, 292 317 uint32_t x, uint32_t y, uint32_t w, uint32_t h); 293 318 ··· 298 323 QEMUGLContext dpy_gl_ctx_get_current(QemuConsole *con); 299 324 300 325 bool console_has_gl(QemuConsole *con); 326 + bool console_has_gl_dmabuf(QemuConsole *con); 301 327 302 328 static inline int surface_stride(DisplaySurface *s) 303 329 { ··· 390 416 DisplaySurface *qemu_console_surface(QemuConsole *con); 391 417 392 418 /* console-gl.c */ 393 - typedef struct ConsoleGLState ConsoleGLState; 394 419 #ifdef CONFIG_OPENGL 395 - ConsoleGLState *console_gl_init_context(void); 396 - void console_gl_fini_context(ConsoleGLState *gls); 397 420 bool console_gl_check_format(DisplayChangeListener *dcl, 398 421 pixman_format_code_t format); 399 - void surface_gl_create_texture(ConsoleGLState *gls, 422 + void surface_gl_create_texture(QemuGLShader *gls, 400 423 DisplaySurface *surface); 401 - void surface_gl_update_texture(ConsoleGLState *gls, 424 + void surface_gl_update_texture(QemuGLShader *gls, 402 425 DisplaySurface *surface, 403 426 int x, int y, int w, int h); 404 - void surface_gl_render_texture(ConsoleGLState *gls, 427 + void surface_gl_render_texture(QemuGLShader *gls, 405 428 DisplaySurface *surface); 406 - void surface_gl_destroy_texture(ConsoleGLState *gls, 429 + void surface_gl_destroy_texture(QemuGLShader *gls, 407 430 DisplaySurface *surface); 408 - void surface_gl_setup_viewport(ConsoleGLState *gls, 431 + void surface_gl_setup_viewport(QemuGLShader *gls, 409 432 DisplaySurface *surface, 410 433 int ww, int wh); 411 434 #endif
+7
include/ui/egl-helpers.h
··· 24 24 void egl_fb_blit(egl_fb *dst, egl_fb *src, bool flip); 25 25 void egl_fb_read(void *dst, egl_fb *src); 26 26 27 + void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip); 28 + void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip, 29 + int x, int y); 30 + 27 31 #ifdef CONFIG_OPENGL_DMABUF 28 32 29 33 extern int qemu_egl_rn_fd; ··· 32 36 33 37 int egl_rendernode_init(const char *rendernode); 34 38 int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc); 39 + 40 + void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf); 41 + void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf); 35 42 36 43 #endif 37 44
+1 -1
include/ui/gtk.h
··· 47 47 double scale_x; 48 48 double scale_y; 49 49 #if defined(CONFIG_OPENGL) 50 - ConsoleGLState *gls; 50 + QemuGLShader *gls; 51 51 EGLContext ectx; 52 52 EGLSurface esurface; 53 53 int glupdates;
+1 -1
include/ui/sdl2.h
··· 26 26 int idle_counter; 27 27 SDL_GLContext winctx; 28 28 #ifdef CONFIG_OPENGL 29 - ConsoleGLState *gls; 29 + QemuGLShader *gls; 30 30 egl_fb guest_fb; 31 31 egl_fb win_fb; 32 32 bool y0_top;
+5 -7
include/ui/shader.h
··· 3 3 4 4 #include <epoxy/gl.h> 5 5 6 - GLuint qemu_gl_init_texture_blit(GLint texture_blit_prog); 7 - void qemu_gl_run_texture_blit(GLint texture_blit_prog, 8 - GLint texture_blit_vao); 6 + typedef struct QemuGLShader QemuGLShader; 9 7 10 - GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src); 11 - GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag); 12 - GLuint qemu_gl_create_compile_link_program(const GLchar *vert_src, 13 - const GLchar *frag_src); 8 + void qemu_gl_run_texture_blit(QemuGLShader *gls, bool flip); 9 + 10 + QemuGLShader *qemu_gl_init_shader(void); 11 + void qemu_gl_fini_shader(QemuGLShader *gls); 14 12 15 13 #endif /* QEMU_SHADER_H */
+1 -1
include/ui/spice-display.h
··· 119 119 /* opengl rendering */ 120 120 QEMUBH *gl_unblock_bh; 121 121 QEMUTimer *gl_unblock_timer; 122 - ConsoleGLState *gls; 122 + QemuGLShader *gls; 123 123 int gl_updates; 124 124 bool have_scanout; 125 125 bool have_surface;
+6 -39
ui/console-gl.c
··· 29 29 #include "ui/console.h" 30 30 #include "ui/shader.h" 31 31 32 - #include "shader/texture-blit-vert.h" 33 - #include "shader/texture-blit-frag.h" 34 - 35 - struct ConsoleGLState { 36 - GLint texture_blit_prog; 37 - GLint texture_blit_vao; 38 - }; 39 - 40 32 /* ---------------------------------------------------------------------- */ 41 33 42 - ConsoleGLState *console_gl_init_context(void) 43 - { 44 - ConsoleGLState *gls = g_new0(ConsoleGLState, 1); 45 - 46 - gls->texture_blit_prog = qemu_gl_create_compile_link_program 47 - (texture_blit_vert_src, texture_blit_frag_src); 48 - if (!gls->texture_blit_prog) { 49 - exit(1); 50 - } 51 - 52 - gls->texture_blit_vao = 53 - qemu_gl_init_texture_blit(gls->texture_blit_prog); 54 - 55 - return gls; 56 - } 57 - 58 - void console_gl_fini_context(ConsoleGLState *gls) 59 - { 60 - if (!gls) { 61 - return; 62 - } 63 - g_free(gls); 64 - } 65 - 66 34 bool console_gl_check_format(DisplayChangeListener *dcl, 67 35 pixman_format_code_t format) 68 36 { ··· 76 44 } 77 45 } 78 46 79 - void surface_gl_create_texture(ConsoleGLState *gls, 47 + void surface_gl_create_texture(QemuGLShader *gls, 80 48 DisplaySurface *surface) 81 49 { 82 50 assert(gls); ··· 116 84 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 117 85 } 118 86 119 - void surface_gl_update_texture(ConsoleGLState *gls, 87 + void surface_gl_update_texture(QemuGLShader *gls, 120 88 DisplaySurface *surface, 121 89 int x, int y, int w, int h) 122 90 { ··· 133 101 + surface_bytes_per_pixel(surface) * x); 134 102 } 135 103 136 - void surface_gl_render_texture(ConsoleGLState *gls, 104 + void surface_gl_render_texture(QemuGLShader *gls, 137 105 DisplaySurface *surface) 138 106 { 139 107 assert(gls); ··· 141 109 glClearColor(0.1f, 0.1f, 0.1f, 0.0f); 142 110 glClear(GL_COLOR_BUFFER_BIT); 143 111 144 - qemu_gl_run_texture_blit(gls->texture_blit_prog, 145 - gls->texture_blit_vao); 112 + qemu_gl_run_texture_blit(gls, false); 146 113 } 147 114 148 - void surface_gl_destroy_texture(ConsoleGLState *gls, 115 + void surface_gl_destroy_texture(QemuGLShader *gls, 149 116 DisplaySurface *surface) 150 117 { 151 118 if (!surface || !surface->texture) { ··· 155 122 surface->texture = 0; 156 123 } 157 124 158 - void surface_gl_setup_viewport(ConsoleGLState *gls, 125 + void surface_gl_setup_viewport(QemuGLShader *gls, 159 126 DisplaySurface *surface, 160 127 int ww, int wh) 161 128 {
+33
ui/console.c
··· 1404 1404 return con->gl != NULL; 1405 1405 } 1406 1406 1407 + bool console_has_gl_dmabuf(QemuConsole *con) 1408 + { 1409 + return con->gl != NULL && con->gl->ops->dpy_gl_scanout_dmabuf != NULL; 1410 + } 1411 + 1407 1412 void register_displaychangelistener(DisplayChangeListener *dcl) 1408 1413 { 1409 1414 static const char nodev[] = ··· 1743 1748 backing_y_0_top, 1744 1749 backing_width, backing_height, 1745 1750 x, y, width, height); 1751 + } 1752 + 1753 + void dpy_gl_scanout_dmabuf(QemuConsole *con, 1754 + QemuDmaBuf *dmabuf) 1755 + { 1756 + assert(con->gl); 1757 + con->gl->ops->dpy_gl_scanout_dmabuf(con->gl, dmabuf); 1758 + } 1759 + 1760 + void dpy_gl_cursor_dmabuf(QemuConsole *con, 1761 + QemuDmaBuf *dmabuf, 1762 + uint32_t pos_x, uint32_t pos_y) 1763 + { 1764 + assert(con->gl); 1765 + 1766 + if (con->gl->ops->dpy_gl_cursor_dmabuf) { 1767 + con->gl->ops->dpy_gl_cursor_dmabuf(con->gl, dmabuf, pos_x, pos_y); 1768 + } 1769 + } 1770 + 1771 + void dpy_gl_release_dmabuf(QemuConsole *con, 1772 + QemuDmaBuf *dmabuf) 1773 + { 1774 + assert(con->gl); 1775 + 1776 + if (con->gl->ops->dpy_gl_release_dmabuf) { 1777 + con->gl->ops->dpy_gl_release_dmabuf(con->gl, dmabuf); 1778 + } 1746 1779 } 1747 1780 1748 1781 void dpy_gl_update(QemuConsole *con,
+57 -2
ui/egl-headless.c
··· 4 4 #include "ui/console.h" 5 5 #include "ui/egl-helpers.h" 6 6 #include "ui/egl-context.h" 7 + #include "ui/shader.h" 7 8 8 9 typedef struct egl_dpy { 9 10 DisplayChangeListener dcl; 10 11 DisplaySurface *ds; 12 + QemuGLShader *gls; 11 13 egl_fb guest_fb; 14 + egl_fb cursor_fb; 12 15 egl_fb blit_fb; 13 16 bool y_0_top; 17 + uint32_t pos_x; 18 + uint32_t pos_y; 14 19 } egl_dpy; 15 20 16 21 /* ------------------------------------------------------------------ */ ··· 65 70 } 66 71 } 67 72 73 + static void egl_scanout_dmabuf(DisplayChangeListener *dcl, 74 + QemuDmaBuf *dmabuf) 75 + { 76 + egl_dmabuf_import_texture(dmabuf); 77 + if (!dmabuf->texture) { 78 + return; 79 + } 80 + 81 + egl_scanout_texture(dcl, dmabuf->texture, 82 + false, dmabuf->width, dmabuf->height, 83 + 0, 0, dmabuf->width, dmabuf->height); 84 + } 85 + 86 + static void egl_cursor_dmabuf(DisplayChangeListener *dcl, 87 + QemuDmaBuf *dmabuf, 88 + uint32_t pos_x, uint32_t pos_y) 89 + { 90 + egl_dpy *edpy = container_of(dcl, egl_dpy, dcl); 91 + 92 + edpy->pos_x = pos_x; 93 + edpy->pos_y = pos_y; 94 + 95 + egl_dmabuf_import_texture(dmabuf); 96 + if (!dmabuf->texture) { 97 + return; 98 + } 99 + 100 + egl_fb_setup_for_tex(&edpy->cursor_fb, dmabuf->width, dmabuf->height, 101 + dmabuf->texture, false); 102 + } 103 + 104 + static void egl_release_dmabuf(DisplayChangeListener *dcl, 105 + QemuDmaBuf *dmabuf) 106 + { 107 + egl_dmabuf_release_texture(dmabuf); 108 + } 109 + 68 110 static void egl_scanout_flush(DisplayChangeListener *dcl, 69 111 uint32_t x, uint32_t y, 70 112 uint32_t w, uint32_t h) ··· 78 120 assert(surface_height(edpy->ds) == edpy->guest_fb.height); 79 121 assert(surface_format(edpy->ds) == PIXMAN_x8r8g8b8); 80 122 81 - egl_fb_blit(&edpy->blit_fb, &edpy->guest_fb, edpy->y_0_top); 82 - egl_fb_read(surface_data(edpy->ds), &edpy->blit_fb); 123 + if (edpy->cursor_fb.texture) { 124 + /* have cursor -> render using textures */ 125 + egl_texture_blit(edpy->gls, &edpy->blit_fb, &edpy->guest_fb, 126 + !edpy->y_0_top); 127 + egl_texture_blend(edpy->gls, &edpy->blit_fb, &edpy->cursor_fb, 128 + !edpy->y_0_top, edpy->pos_x, edpy->pos_y); 129 + } else { 130 + /* no cursor -> use simple framebuffer blit */ 131 + egl_fb_blit(&edpy->blit_fb, &edpy->guest_fb, edpy->y_0_top); 132 + } 83 133 134 + egl_fb_read(surface_data(edpy->ds), &edpy->blit_fb); 84 135 dpy_gfx_update(edpy->dcl.con, x, y, w, h); 85 136 } 86 137 ··· 97 148 98 149 .dpy_gl_scanout_disable = egl_scanout_disable, 99 150 .dpy_gl_scanout_texture = egl_scanout_texture, 151 + .dpy_gl_scanout_dmabuf = egl_scanout_dmabuf, 152 + .dpy_gl_cursor_dmabuf = egl_cursor_dmabuf, 153 + .dpy_gl_release_dmabuf = egl_release_dmabuf, 100 154 .dpy_gl_update = egl_scanout_flush, 101 155 }; 102 156 ··· 120 174 edpy = g_new0(egl_dpy, 1); 121 175 edpy->dcl.con = con; 122 176 edpy->dcl.ops = &egl_ops; 177 + edpy->gls = qemu_gl_init_shader(); 123 178 register_displaychangelistener(&edpy->dcl); 124 179 } 125 180 }
+73
ui/egl-helpers.c
··· 19 19 #include <dirent.h> 20 20 21 21 #include "qemu/error-report.h" 22 + #include "ui/console.h" 22 23 #include "ui/egl-helpers.h" 23 24 24 25 EGLDisplay *qemu_egl_display; ··· 108 109 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); 109 110 glReadPixels(0, 0, src->width, src->height, 110 111 GL_BGRA, GL_UNSIGNED_BYTE, dst); 112 + } 113 + 114 + void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip) 115 + { 116 + glBindFramebuffer(GL_FRAMEBUFFER_EXT, dst->framebuffer); 117 + glViewport(0, 0, dst->width, dst->height); 118 + glEnable(GL_TEXTURE_2D); 119 + glBindTexture(GL_TEXTURE_2D, src->texture); 120 + qemu_gl_run_texture_blit(gls, flip); 121 + } 122 + 123 + void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip, 124 + int x, int y) 125 + { 126 + glBindFramebuffer(GL_FRAMEBUFFER_EXT, dst->framebuffer); 127 + if (flip) { 128 + glViewport(x, y, src->width, src->height); 129 + } else { 130 + glViewport(x, dst->height - src->height - y, 131 + src->width, src->height); 132 + } 133 + glEnable(GL_TEXTURE_2D); 134 + glBindTexture(GL_TEXTURE_2D, src->texture); 135 + glEnable(GL_BLEND); 136 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 137 + qemu_gl_run_texture_blit(gls, flip); 138 + glDisable(GL_BLEND); 111 139 } 112 140 113 141 /* ---------------------------------------------------------------------- */ ··· 239 267 eglDestroyImageKHR(qemu_egl_display, image); 240 268 241 269 return fd; 270 + } 271 + 272 + void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) 273 + { 274 + EGLImageKHR image = EGL_NO_IMAGE_KHR; 275 + EGLint attrs[] = { 276 + EGL_DMA_BUF_PLANE0_FD_EXT, dmabuf->fd, 277 + EGL_DMA_BUF_PLANE0_PITCH_EXT, dmabuf->stride, 278 + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, 279 + EGL_WIDTH, dmabuf->width, 280 + EGL_HEIGHT, dmabuf->height, 281 + EGL_LINUX_DRM_FOURCC_EXT, dmabuf->fourcc, 282 + EGL_NONE, /* end of list */ 283 + }; 284 + 285 + if (dmabuf->texture != 0) { 286 + return; 287 + } 288 + 289 + image = eglCreateImageKHR(qemu_egl_display, 290 + EGL_NO_CONTEXT, 291 + EGL_LINUX_DMA_BUF_EXT, 292 + NULL, attrs); 293 + if (image == EGL_NO_IMAGE_KHR) { 294 + error_report("eglCreateImageKHR failed"); 295 + return; 296 + } 297 + 298 + glGenTextures(1, &dmabuf->texture); 299 + glBindTexture(GL_TEXTURE_2D, dmabuf->texture); 300 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 301 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 302 + 303 + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); 304 + eglDestroyImageKHR(qemu_egl_display, image); 305 + } 306 + 307 + void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) 308 + { 309 + if (dmabuf->texture == 0) { 310 + return; 311 + } 312 + 313 + glDeleteTextures(1, &dmabuf->texture); 314 + dmabuf->texture = 0; 242 315 } 243 316 244 317 #endif /* CONFIG_OPENGL_DMABUF */
+1 -1
ui/gtk-egl.c
··· 113 113 if (!vc->gfx.esurface) { 114 114 return; 115 115 } 116 - vc->gfx.gls = console_gl_init_context(); 116 + vc->gfx.gls = qemu_gl_init_shader(); 117 117 if (vc->gfx.ds) { 118 118 surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds); 119 119 }
+1 -1
ui/gtk-gl-area.c
··· 96 96 return; 97 97 } 98 98 gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); 99 - vc->gfx.gls = console_gl_init_context(); 99 + vc->gfx.gls = qemu_gl_init_shader(); 100 100 if (vc->gfx.ds) { 101 101 surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds); 102 102 }
+2 -2
ui/sdl2-gl.c
··· 90 90 scon->surface = new_surface; 91 91 92 92 if (!new_surface) { 93 - console_gl_fini_context(scon->gls); 93 + qemu_gl_fini_shader(scon->gls); 94 94 scon->gls = NULL; 95 95 sdl2_window_destroy(scon); 96 96 return; ··· 98 98 99 99 if (!scon->real_window) { 100 100 sdl2_window_create(scon); 101 - scon->gls = console_gl_init_context(); 101 + scon->gls = qemu_gl_init_shader(); 102 102 } else if (old_surface && 103 103 ((surface_width(old_surface) != surface_width(new_surface)) || 104 104 (surface_height(old_surface) != surface_height(new_surface)))) {
+48 -9
ui/shader.c
··· 28 28 #include "qemu-common.h" 29 29 #include "ui/shader.h" 30 30 31 + #include "shader/texture-blit-vert.h" 32 + #include "shader/texture-blit-flip-vert.h" 33 + #include "shader/texture-blit-frag.h" 34 + 35 + struct QemuGLShader { 36 + GLint texture_blit_prog; 37 + GLint texture_blit_flip_prog; 38 + GLint texture_blit_vao; 39 + }; 40 + 31 41 /* ---------------------------------------------------------------------- */ 32 42 33 - GLuint qemu_gl_init_texture_blit(GLint texture_blit_prog) 43 + static GLuint qemu_gl_init_texture_blit(GLint texture_blit_prog) 34 44 { 35 45 static const GLfloat in_position[] = { 36 46 -1, -1, ··· 60 70 return vao; 61 71 } 62 72 63 - void qemu_gl_run_texture_blit(GLint texture_blit_prog, 64 - GLint texture_blit_vao) 73 + void qemu_gl_run_texture_blit(QemuGLShader *gls, bool flip) 65 74 { 66 - glUseProgram(texture_blit_prog); 67 - glBindVertexArray(texture_blit_vao); 75 + glUseProgram(flip 76 + ? gls->texture_blit_flip_prog 77 + : gls->texture_blit_prog); 78 + glBindVertexArray(gls->texture_blit_vao); 68 79 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 69 80 } 70 81 71 82 /* ---------------------------------------------------------------------- */ 72 83 73 - GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src) 84 + static GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src) 74 85 { 75 86 GLuint shader; 76 87 GLint status, length; ··· 94 105 return shader; 95 106 } 96 107 97 - GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag) 108 + static GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag) 98 109 { 99 110 GLuint program; 100 111 GLint status, length; ··· 117 128 return program; 118 129 } 119 130 120 - GLuint qemu_gl_create_compile_link_program(const GLchar *vert_src, 121 - const GLchar *frag_src) 131 + static GLuint qemu_gl_create_compile_link_program(const GLchar *vert_src, 132 + const GLchar *frag_src) 122 133 { 123 134 GLuint vert_shader, frag_shader, program; 124 135 ··· 134 145 135 146 return program; 136 147 } 148 + 149 + /* ---------------------------------------------------------------------- */ 150 + 151 + QemuGLShader *qemu_gl_init_shader(void) 152 + { 153 + QemuGLShader *gls = g_new0(QemuGLShader, 1); 154 + 155 + gls->texture_blit_prog = qemu_gl_create_compile_link_program 156 + (texture_blit_vert_src, texture_blit_frag_src); 157 + gls->texture_blit_flip_prog = qemu_gl_create_compile_link_program 158 + (texture_blit_flip_vert_src, texture_blit_frag_src); 159 + if (!gls->texture_blit_prog || !gls->texture_blit_flip_prog) { 160 + exit(1); 161 + } 162 + 163 + gls->texture_blit_vao = 164 + qemu_gl_init_texture_blit(gls->texture_blit_prog); 165 + 166 + return gls; 167 + } 168 + 169 + void qemu_gl_fini_shader(QemuGLShader *gls) 170 + { 171 + if (!gls) { 172 + return; 173 + } 174 + g_free(gls); 175 + }
+10
ui/shader/texture-blit-flip.vert
··· 1 + 2 + #version 300 es 3 + 4 + in vec2 in_position; 5 + out vec2 ex_tex_coord; 6 + 7 + void main(void) { 8 + gl_Position = vec4(in_position, 0.0, 1.0); 9 + ex_tex_coord = vec2(1.0 + in_position.x, 1.0 + in_position.y) * 0.5; 10 + }
+1 -1
ui/spice-display.c
··· 1019 1019 ssd->gl_unblock_bh = qemu_bh_new(qemu_spice_gl_unblock_bh, ssd); 1020 1020 ssd->gl_unblock_timer = timer_new_ms(QEMU_CLOCK_REALTIME, 1021 1021 qemu_spice_gl_block_timer, ssd); 1022 - ssd->gls = console_gl_init_context(); 1022 + ssd->gls = qemu_gl_init_shader(); 1023 1023 ssd->have_surface = false; 1024 1024 ssd->have_scanout = false; 1025 1025 }