diff options
Diffstat (limited to 'qemu/ui/sdl2-gl.c')
-rw-r--r-- | qemu/ui/sdl2-gl.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/qemu/ui/sdl2-gl.c b/qemu/ui/sdl2-gl.c index b604c0671..a324ecaca 100644 --- a/qemu/ui/sdl2-gl.c +++ b/qemu/ui/sdl2-gl.c @@ -25,17 +25,44 @@ * THE SOFTWARE. */ +#include "qemu/osdep.h" #include "qemu-common.h" #include "ui/console.h" #include "ui/input.h" #include "ui/sdl2.h" #include "sysemu/sysemu.h" +#include <epoxy/gl.h> + +static void sdl2_set_scanout_mode(struct sdl2_console *scon, bool scanout) +{ + if (scon->scanout_mode == scanout) { + return; + } + + scon->scanout_mode = scanout; + if (!scon->scanout_mode) { + if (scon->fbo_id) { + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, 0, 0); + glDeleteFramebuffers(1, &scon->fbo_id); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + scon->fbo_id = 0; + } + if (scon->surface) { + surface_gl_destroy_texture(scon->gls, scon->surface); + surface_gl_create_texture(scon->gls, scon->surface); + } + } +} + static void sdl2_gl_render_surface(struct sdl2_console *scon) { int ww, wh; SDL_GL_MakeCurrent(scon->real_window, scon->winctx); + sdl2_set_scanout_mode(scon, false); SDL_GetWindowSize(scon->real_window, &ww, &wh); surface_gl_setup_viewport(scon->gls, scon->surface, ww, wh); @@ -110,3 +137,112 @@ void sdl2_gl_redraw(struct sdl2_console *scon) sdl2_gl_render_surface(scon); } } + +QEMUGLContext sdl2_gl_create_context(DisplayChangeListener *dcl, + QEMUGLParams *params) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + SDL_GLContext ctx; + + assert(scon->opengl); + + SDL_GL_MakeCurrent(scon->real_window, scon->winctx); + + SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, + SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, params->major_ver); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, params->minor_ver); + + ctx = SDL_GL_CreateContext(scon->real_window); + return (QEMUGLContext)ctx; +} + +void sdl2_gl_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx) +{ + SDL_GLContext sdlctx = (SDL_GLContext)ctx; + + SDL_GL_DeleteContext(sdlctx); +} + +int sdl2_gl_make_context_current(DisplayChangeListener *dcl, + QEMUGLContext ctx) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + SDL_GLContext sdlctx = (SDL_GLContext)ctx; + + assert(scon->opengl); + + return SDL_GL_MakeCurrent(scon->real_window, sdlctx); +} + +QEMUGLContext sdl2_gl_get_current_context(DisplayChangeListener *dcl) +{ + SDL_GLContext sdlctx; + + sdlctx = SDL_GL_GetCurrentContext(); + return (QEMUGLContext)sdlctx; +} + +void sdl2_gl_scanout(DisplayChangeListener *dcl, + uint32_t backing_id, bool backing_y_0_top, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + + assert(scon->opengl); + scon->x = x; + scon->y = y; + scon->w = w; + scon->h = h; + scon->tex_id = backing_id; + scon->y0_top = backing_y_0_top; + + SDL_GL_MakeCurrent(scon->real_window, scon->winctx); + + if (scon->tex_id == 0 || scon->w == 0 || scon->h == 0) { + sdl2_set_scanout_mode(scon, false); + return; + } + + sdl2_set_scanout_mode(scon, true); + if (!scon->fbo_id) { + glGenFramebuffers(1, &scon->fbo_id); + } + + glBindFramebuffer(GL_FRAMEBUFFER_EXT, scon->fbo_id); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, scon->tex_id, 0); +} + +void sdl2_gl_scanout_flush(DisplayChangeListener *dcl, + uint32_t x, uint32_t y, uint32_t w, uint32_t h) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + int ww, wh, y1, y2; + + assert(scon->opengl); + if (!scon->scanout_mode) { + return; + } + if (!scon->fbo_id) { + return; + } + + SDL_GL_MakeCurrent(scon->real_window, scon->winctx); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, scon->fbo_id); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + SDL_GetWindowSize(scon->real_window, &ww, &wh); + glViewport(0, 0, ww, wh); + y1 = scon->y0_top ? 0 : scon->h; + y2 = scon->y0_top ? scon->h : 0; + glBlitFramebuffer(0, y1, scon->w, y2, + 0, 0, ww, wh, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, scon->fbo_id); + + SDL_GL_SwapWindow(scon->real_window); +} |