From 4083733db5e4120939acee57019ff52db1f45b9d Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Sun, 29 Nov 2015 22:28:24 +0900 Subject: ui/curses: Fix color attribute of monitor for curses Current text_console_update() writes totally broken color attributes to console_write_ch(). The format now is writing, [WRONG] bold << 21 | fg << 12 | bg << 8 | char fg == 3bits curses color number bg == 3bits curses color number I can't see this format is where come from. Anyway, this doesn't work at all. What curses expects is actually (and vga.c is using), [RIGHT] bold << 21 | bg << 11 | fg << 8 | char fg == 3bits vga color number bg == 3bits vga color number And curses set COLOR_PAIR() up to match this format, and curses's chtype. I.e, bold | color_pair | char color_pair == (bg << 3 | fg) To fix, this simply uses VGA color number everywhere except curses.c internal. Then, convert it to above [RIGHT] format to write by console_write_ch(). And as bonus, this reduces to expose curses define to other parts (removes COLOR_* from console.c). [Tested the first line is displayed as white on blue back for monitor in curses console] Signed-off-by: OGAWA Hirofumi Message-id: 87r3j95407.fsf@mail.parknet.co.jp Signed-off-by: Gerd Hoffmann --- include/ui/console.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'include') diff --git a/include/ui/console.h b/include/ui/console.h index c249db4f7c..adac36dd52 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -30,6 +30,21 @@ #define GUI_REFRESH_INTERVAL_DEFAULT 30 #define GUI_REFRESH_INTERVAL_IDLE 3000 +/* Color number is match to standard vga palette */ +enum qemu_color_names { + QEMU_COLOR_BLACK = 0, + QEMU_COLOR_BLUE = 1, + QEMU_COLOR_GREEN = 2, + QEMU_COLOR_CYAN = 3, + QEMU_COLOR_RED = 4, + QEMU_COLOR_MAGENTA = 5, + QEMU_COLOR_YELLOW = 6, + QEMU_COLOR_WHITE = 7 +}; +/* Convert to curses char attributes */ +#define ATTR2CHTYPE(c, fg, bg, bold) \ + ((bold) << 21 | (bg) << 11 | (fg) << 8 | (c)) + typedef void QEMUPutKBDEvent(void *opaque, int keycode); typedef void QEMUPutLEDEvent(void *opaque, int ledstate); typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state); -- cgit v1.2.3-55-g7522 From cb47dc9ab9f55083017291b2b8fbae639c576ec2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 19 Nov 2014 14:56:46 +0100 Subject: sdl2/opengl: add opengl context and scanout support This allows virtio-gpu to render in 3d mode. Signed-off-by: Gerd Hoffmann Reviewed-by: Max Reitz --- include/ui/sdl2.h | 22 ++++++++- ui/sdl2-gl.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ui/sdl2.c | 7 +++ 3 files changed, 163 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h index 2fdad8f300..b7ac38f198 100644 --- a/include/ui/sdl2.h +++ b/include/ui/sdl2.h @@ -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 */ diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c index b604c0671e..2bb3d06bab 100644 --- a/ui/sdl2-gl.c +++ b/ui/sdl2-gl.c @@ -31,11 +31,37 @@ #include "ui/sdl2.h" #include "sysemu/sysemu.h" +#include + +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); +} diff --git a/ui/sdl2.c b/ui/sdl2.c index cf38df2684..46270f4172 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -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 -- cgit v1.2.3-55-g7522