sdl2/opengl: add opengl context and scanout support
This allows virtio-gpu to render in 3d mode. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
		
							parent
							
								
									4083733db5
								
							
						
					
					
						commit
						cb47dc9ab9
					
				| @ -15,12 +15,18 @@ struct sdl2_console { | ||||
|     SDL_Renderer *real_renderer; | ||||
|     int idx; | ||||
|     int last_vm_running; /* per console for caption reasons */ | ||||
|     int x, y; | ||||
|     int x, y, w, h; | ||||
|     int hidden; | ||||
|     int opengl; | ||||
|     int updates; | ||||
|     SDL_GLContext winctx; | ||||
| #ifdef CONFIG_OPENGL | ||||
|     ConsoleGLState *gls; | ||||
|     GLuint tex_id; | ||||
|     GLuint fbo_id; | ||||
|     bool y0_top; | ||||
|     bool scanout_mode; | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| void sdl2_window_create(struct sdl2_console *scon); | ||||
| @ -48,4 +54,18 @@ void sdl2_gl_switch(DisplayChangeListener *dcl, | ||||
| void sdl2_gl_refresh(DisplayChangeListener *dcl); | ||||
| void sdl2_gl_redraw(struct sdl2_console *scon); | ||||
| 
 | ||||
| QEMUGLContext sdl2_gl_create_context(DisplayChangeListener *dcl, | ||||
|                                      QEMUGLParams *params); | ||||
| void sdl2_gl_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx); | ||||
| int sdl2_gl_make_context_current(DisplayChangeListener *dcl, | ||||
|                                  QEMUGLContext ctx); | ||||
| QEMUGLContext sdl2_gl_get_current_context(DisplayChangeListener *dcl); | ||||
| 
 | ||||
| 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); | ||||
| void sdl2_gl_scanout_flush(DisplayChangeListener *dcl, | ||||
|                            uint32_t x, uint32_t y, uint32_t w, uint32_t h); | ||||
| 
 | ||||
| #endif /* SDL2_H */ | ||||
|  | ||||
							
								
								
									
										135
									
								
								ui/sdl2-gl.c
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								ui/sdl2-gl.c
									
									
									
									
									
								
							| @ -31,11 +31,37 @@ | ||||
| #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 +136,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); | ||||
| } | ||||
|  | ||||
| @ -700,6 +700,13 @@ static const DisplayChangeListenerOps dcl_gl_ops = { | ||||
|     .dpy_refresh             = sdl2_gl_refresh, | ||||
|     .dpy_mouse_set           = sdl_mouse_warp, | ||||
|     .dpy_cursor_define       = sdl_mouse_define, | ||||
| 
 | ||||
|     .dpy_gl_ctx_create       = sdl2_gl_create_context, | ||||
|     .dpy_gl_ctx_destroy      = sdl2_gl_destroy_context, | ||||
|     .dpy_gl_ctx_make_current = sdl2_gl_make_context_current, | ||||
|     .dpy_gl_ctx_get_current  = sdl2_gl_get_current_context, | ||||
|     .dpy_gl_scanout          = sdl2_gl_scanout, | ||||
|     .dpy_gl_update           = sdl2_gl_scanout_flush, | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Gerd Hoffmann
						Gerd Hoffmann