qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 6 of 6] opengl rendering in the sdl window


From: Stefano Stabellini
Subject: [Qemu-devel] [PATCH 6 of 6] opengl rendering in the sdl window
Date: Fri, 12 Sep 2008 12:26:46 +0100
User-agent: Thunderbird 2.0.0.14 (X11/20080505)

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 = 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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]