From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Ke6mD-0001GY-PL for qemu-devel@nongnu.org; Fri, 12 Sep 2008 07:25:25 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Ke6mC-0001Fz-R6 for qemu-devel@nongnu.org; Fri, 12 Sep 2008 07:25:25 -0400 Received: from [199.232.76.173] (port=60325 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ke6mC-0001Ft-H2 for qemu-devel@nongnu.org; Fri, 12 Sep 2008 07:25:24 -0400 Received: from smtp.eu.citrix.com ([62.200.22.115]:12574) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Ke6mB-0002LO-LZ for qemu-devel@nongnu.org; Fri, 12 Sep 2008 07:25:24 -0400 Message-ID: <48CA51F6.3020200@eu.citrix.com> Date: Fri, 12 Sep 2008 12:26:46 +0100 From: Stefano Stabellini MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH 6 of 6] opengl rendering in the sdl window Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Signed-off-by: Stefano Stabellini --- configure | 31 +++++++++ console.h | 2 +- sdl.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- vl.c | 19 ++++++- 4 files changed, 240 insertions(+), 14 deletions(-) diff --git a/configure b/configure index acb4a4a..a794827 100755 --- a/configure +++ b/configure @@ -271,6 +271,8 @@ for opt do ;; --disable-sdl) sdl="no" ;; + --disable-opengl) opengl="no" + ;; --fmod-lib=*) fmod_lib="$optarg" ;; --fmod-inc=*) fmod_inc="$optarg" @@ -749,6 +751,26 @@ else fi # -z $sdl ########################################## +# OpenGL test + +if test -z "$opengl" && test "$sdl" = "yes" +then +cat > $TMPC << EOF +#include +#ifndef GL_TEXTURE_RECTANGLE_ARB +#error "Opengl doesn't support GL_TEXTURE_RECTANGLE_ARB" +#endif +int main( void ) { return (int) glGetString(GL_EXTENSIONS); } +EOF +if $cc -o $TMPE $TMPC -lGL 2> /dev/null +then +opengl="yes" +else +opengl="no" +fi +fi + +########################################## # VNC TLS detection if test "$vnc_tls" = "yes" ; then cat > $TMPC <> $config_mak fi fi +if test $opengl = "yes" +then + echo "#define CONFIG_OPENGL 1" >> $config_h + echo "CONFIG_OPENGL=yes" >> $config_mak + echo "SDL_CFLAGS+=-I/usr/include/GL" >> $config_mak + echo "SDL_LIBS+=-lXext" >> $config_mak + echo "SDL_LIBS+=-lGL" >> $config_mak +fi if test "$cocoa" = "yes" ; then echo "#define CONFIG_COCOA 1" >> $config_h echo "CONFIG_COCOA=yes" >> $config_mak diff --git a/console.h b/console.h index 7d252b7..a2004ba 100644 --- a/console.h +++ b/console.h @@ -153,7 +153,7 @@ void qemu_console_resize_shared(QEMUConsole *console, int width, int height, int depth, int linesize, void *pixels); /* sdl.c */ -void sdl_display_init(DisplayState *ds, int full_screen, int no_frame); +void sdl_display_init(DisplayState *ds, int full_screen, int no_frame, int opengl_enable); /* cocoa.m */ void cocoa_display_init(DisplayState *ds, int full_screen); diff --git a/sdl.c b/sdl.c index 40b6c5a..22440bd 100644 --- a/sdl.c +++ b/sdl.c @@ -31,6 +31,10 @@ #include #endif +#ifdef CONFIG_OPENGL +#include +#endif + static SDL_Surface *screen; static SDL_Surface *shared; static int gui_grab; /* if true, all keyboard/mouse events are grabbed */ @@ -50,9 +54,121 @@ static int absolute_enabled = 0; static int guest_cursor = 0; static int guest_x, guest_y; static SDL_Cursor *guest_sprite = 0; +static int opengl_enabled; static void sdl_colordepth(DisplayState *ds, int depth); +#ifdef CONFIG_OPENGL +static GLint tex_format; +static GLint tex_type; +static GLuint texture_ref = 0; +static GLint gl_format; + +static void opengl_setdata(DisplayState *ds, void *pixels) +{ + glEnable(GL_TEXTURE_RECTANGLE_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glClearColor(0, 0, 0, 0); + glDisable(GL_BLEND); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glDisable(GL_CULL_FACE); + glViewport( 0, 0, screen->w, screen->h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, screen->w, screen->h, 0, -1,1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glClear(GL_COLOR_BUFFER_BIT); + ds->data = pixels; + + if (texture_ref) { + glDeleteTextures(1, &texture_ref); + texture_ref = 0; + } + + glGenTextures(1, &texture_ref); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_ref); + glPixelStorei(GL_UNPACK_LSB_FIRST, 1); + switch (ds->depth) { + case 8: + if (ds->palette == NULL) { + tex_format = GL_RGB; + tex_type = GL_UNSIGNED_BYTE_3_3_2; + } else { + int i; + GLushort paletter[256], paletteg[256], paletteb[256]; + for (i = 0; i < 256; i++) { + uint8_t rgb = ds->palette[i] >> 16; + paletter[i] = ((rgb & 0xe0) >> 5) * 65535 / 7; + paletteg[i] = ((rgb & 0x1c) >> 2) * 65535 / 7; + paletteb[i] = (rgb & 0x3) * 65535 / 3; + } + glPixelMapusv(GL_PIXEL_MAP_I_TO_R, 256, paletter); + glPixelMapusv(GL_PIXEL_MAP_I_TO_G, 256, paletteg); + glPixelMapusv(GL_PIXEL_MAP_I_TO_B, 256, paletteb); + + tex_format = GL_COLOR_INDEX; + tex_type = GL_UNSIGNED_BYTE; + } + break; + case 15: + tex_format = GL_RGB; + tex_type = GL_UNSIGNED_SHORT_5_5_5_1; + case 16: + tex_format = GL_RGB; + tex_type = GL_UNSIGNED_SHORT_5_6_5; + break; + case 24: +#if defined(TARGET_WORDS_BIGENDIAN) + tex_format = GL_RGB; +#else + tex_format = GL_BGR; +#endif + tex_type = GL_UNSIGNED_BYTE; + break; + case 32: +#if defined(TARGET_WORDS_BIGENDIAN) + tex_format = GL_RGBA; +#else + tex_format = GL_BGRA; +#endif + tex_type = GL_UNSIGNED_BYTE; + break; + } + glPixelStorei(GL_UNPACK_ROW_LENGTH, (ds->linesize * 8) / ds->depth); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, gl_format, ds->width, ds->height, 0, tex_format, tex_type, pixels); + glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_PRIORITY, 1.0); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); +} + +static void opengl_update(DisplayState *ds, int x, int y, int w, int h) +{ + int bpp = ds->depth / 8; + GLvoid *pixels = ds->data + y * ds->linesize + x * bpp; + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_ref); + glPixelStorei(GL_UNPACK_ROW_LENGTH, ds->linesize / bpp); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, w, h, tex_format, tex_type, pixels); + glBegin(GL_QUADS); + glTexCoord2d(0, 0); + glVertex2d(0, 0); + glTexCoord2d(ds->width, 0); + glVertex2d(screen->w, 0); + glTexCoord2d(ds->width, ds->height); + glVertex2d(screen->w, screen->h); + glTexCoord2d(0, ds->height); + glVertex2d(0, screen->h); + glEnd(); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + SDL_GL_SwapBuffers(); +} +#endif + static void sdl_update(DisplayState *ds, int x, int y, int w, int h) { // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); @@ -122,7 +238,12 @@ static void sdl_resize_shared(DisplayState *ds, int w, int h, int depth, int lin sdl_colordepth(ds, depth); - flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_DOUBLEBUF|SDL_HWPALETTE; +#ifdef CONFIG_OPENGL + if (ds->shared_buf && opengl_enabled) + flags = SDL_OPENGL|SDL_RESIZABLE; + else +#endif + flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_DOUBLEBUF|SDL_HWPALETTE; if (gui_fullscreen) { flags |= SDL_FULLSCREEN; @@ -136,19 +257,33 @@ static void sdl_resize_shared(DisplayState *ds, int w, int h, int depth, int lin again: screen = SDL_SetVideoMode(w, h, 0, flags); + if (!screen) { fprintf(stderr, "Could not open SDL display: %s\n", SDL_GetError()); + if (opengl_enabled) { + /* Fallback to SDL */ + opengl_enabled = 0; + ds->dpy_update = sdl_update; + ds->dpy_setdata = sdl_setdata; + ds->dpy_resize_shared = sdl_resize_shared; + sdl_resize_shared(ds, w, h, depth, linesize, pixels); + return; + } exit(1); } - if (!screen->pixels && (flags & SDL_HWSURFACE) && (flags & SDL_FULLSCREEN)) { - flags &= ~SDL_HWSURFACE; - goto again; - } - if (!screen->pixels) { - fprintf(stderr, "Could not open SDL display: %s\n", SDL_GetError()); - exit(1); + if (!opengl_enabled) { + if (!screen->pixels && (flags & SDL_HWSURFACE) && (flags & SDL_FULLSCREEN)) { + flags &= ~SDL_HWSURFACE; + goto again; + } + + if (!screen->pixels) { + fprintf(stderr, "Could not open SDL display: %s\n", SDL_GetError()); + exit(1); + } } + ds->width = w; ds->height = h; if (!ds->shared_buf) { @@ -163,6 +298,24 @@ static void sdl_resize_shared(DisplayState *ds, int w, int h, int depth, int lin ds->linesize = screen->pitch; } else { ds->linesize = linesize; +#ifdef CONFIG_OPENGL + switch(screen->format->BitsPerPixel) { + case 8: + case 16: + case 24: + if (screen->format->Bshift > screen->format->Rshift) + gl_format = GL_BGR; + else + gl_format = GL_RGB; + break; + case 32: + if (screen->format->Bshift > screen->format->Rshift) + gl_format = GL_BGRA; + else + gl_format = GL_RGBA; + break; + }; +#endif } if (ds->shared_buf) ds->dpy_setdata(ds, pixels); } @@ -181,6 +334,11 @@ static void sdl_colordepth(DisplayState *ds, int depth) } ds->shared_buf = 1; ds->depth = depth; +#ifdef CONFIG_OPENGL + if (opengl_enabled) { + ds->dpy_update = opengl_update; + } +#endif } /* generic keyboard conversion */ @@ -393,8 +551,8 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state absolute_enabled = 1; } - dx = x * 0x7FFF / (width - 1); - dy = y * 0x7FFF / (height - 1); + dx = x * 0x7FFF / (screen->w - 1); + dy = y * 0x7FFF / (screen->h - 1); } else if (absolute_enabled) { sdl_show_cursor(); absolute_enabled = 0; @@ -442,7 +600,7 @@ static void sdl_refresh(DisplayState *ds) while (SDL_PollEvent(ev)) { switch (ev->type) { case SDL_VIDEOEXPOSE: - sdl_update(ds, 0, 0, screen->w, screen->h); + ds->dpy_update(ds, 0, 0, ds->width, ds->height); break; case SDL_KEYDOWN: case SDL_KEYUP: @@ -606,6 +764,18 @@ static void sdl_refresh(DisplayState *ds) } } break; +#ifdef CONFIG_OPENGL + case SDL_VIDEORESIZE: + { + if (ds->shared_buf && opengl_enabled) { + SDL_ResizeEvent *rev = &ev->resize; + screen = SDL_SetVideoMode(rev->w, rev->h, 0, SDL_OPENGL|SDL_RESIZABLE); + opengl_setdata(ds, ds->data); + opengl_update(ds, 0, 0, ds->width, ds->height); + } + break; + } +#endif default: break; } @@ -681,15 +851,19 @@ static void sdl_mouse_define(int width, int height, int bpp, static void sdl_cleanup(void) { +#ifdef CONFIG_OPENGL + if (texture_ref) glDeleteTextures(1, &texture_ref); +#endif if (guest_sprite) SDL_FreeCursor(guest_sprite); SDL_Quit(); } -void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) +void sdl_display_init(DisplayState *ds, int full_screen, int no_frame, int opengl) { int flags; uint8_t data = 0; + opengl_enabled = opengl; #if defined(__APPLE__) /* always use generic keymaps */ @@ -718,6 +892,10 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) #endif ds->dpy_refresh = sdl_refresh; ds->dpy_setdata = sdl_setdata; +#ifdef CONFIG_OPENGL + if (opengl_enabled) + ds->dpy_setdata = opengl_setdata; +#endif ds->dpy_fill = sdl_fill; ds->mouse_set = sdl_mouse_warp; ds->cursor_define = sdl_mouse_define; diff --git a/vl.c b/vl.c index 245177a..c661fa9 100644 --- a/vl.c +++ b/vl.c @@ -201,6 +201,11 @@ int graphic_height = 600; int graphic_depth = 15; #endif int full_screen = 0; +#ifdef CONFIG_OPENGL +int opengl_enabled = 1; +#else +int opengl_enabled = 0; +#endif int no_frame = 0; int no_quit = 0; CharDriverState *serial_hds[MAX_SERIAL_PORTS]; @@ -7681,6 +7686,9 @@ static void help(int exitcode) "-no-frame open SDL window without a frame and window decorations\n" "-alt-grab use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt)\n" "-no-quit disable SDL window close capability\n" +#ifdef CONFIG_OPENGL + "-disable-opengl disable OpenGL rendering, using SDL\n" +#endif #endif #ifdef TARGET_I386 "-no-fd-bootchk disable boot signature checking for floppy disks\n" @@ -7881,6 +7889,7 @@ enum { QEMU_OPTION_no_frame, QEMU_OPTION_alt_grab, QEMU_OPTION_no_quit, + QEMU_OPTION_disable_opengl, QEMU_OPTION_pidfile, QEMU_OPTION_no_kqemu, QEMU_OPTION_kernel_kqemu, @@ -7983,6 +7992,9 @@ const QEMUOption qemu_options[] = { { "no-frame", 0, QEMU_OPTION_no_frame }, { "alt-grab", 0, QEMU_OPTION_alt_grab }, { "no-quit", 0, QEMU_OPTION_no_quit }, +#ifdef CONFIG_OPENGL + { "disable-opengl", 0, QEMU_OPTION_disable_opengl }, +#endif #endif { "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, { "win2k-hack", 0, QEMU_OPTION_win2k_hack }, @@ -8729,6 +8741,11 @@ int main(int argc, char **argv) case QEMU_OPTION_no_quit: no_quit = 1; break; +#ifdef CONFIG_OPENGL + case QEMU_OPTION_disable_opengl: + opengl_enabled = 0; + break; +#endif #endif case QEMU_OPTION_pidfile: pid_file = optarg; @@ -9104,7 +9121,7 @@ int main(int argc, char **argv) #endif { #if defined(CONFIG_SDL) - sdl_display_init(ds, full_screen, no_frame); + sdl_display_init(ds, full_screen, no_frame, opengl_enabled); #elif defined(CONFIG_COCOA) cocoa_display_init(ds, full_screen); #else -- 1.5.4.3