Signed-off-by: Stefano Stabellini <
address@hidden>
---
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 <GL/gl.h>
+#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 <<EOF
@@ -941,6 +963,7 @@ if test "$sdl" != "no" ; then
echo "SDL static link $sdl_static"
fi
echo "curses support $curses"
+echo "OpenGL support $opengl"
echo "mingw32 support $mingw32"
echo "Audio drivers $audio_drv_list"
echo "Extra audio cards $audio_card_list"
@@ -1199,6 +1222,14 @@ if test "$sdl1" = "yes" ; then
echo "SDL_CFLAGS=`$sdl_config --cflags`" >> $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 <signal.h>
#endif
+#ifdef CONFIG_OPENGL
+#include <SDL_opengl.h>
+#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 = "">+
+ 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 = "">+ 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