ia64/xen-unstable

changeset 17242:cbb0dffdc07a

ioemu: SDL rendering using OpenGL

Add opengl support for rendering the guest framebuffer in the SDL
window. SDL is needed anyway to open the window and handle the
events. Opengl rendering is optional and can be turned off at both
compile time and in the vm configuration file.

Some of the benefits of using opengl are:

- faster rendering, less CPU intensive, especially with good graphic
cards;
- makes the window resizing possible and hardware accelerated, thus
very efficient and smooth;
- allows other optimizations like sharing directly a buffer in vram
with the guest (not yet implemented).

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 18 11:47:58 2008 +0000 (2008-03-18)
parents ef85eeaf439a
children 8cc1ed987d5f
files tools/examples/xmexample.hvm tools/ioemu/configure tools/ioemu/sdl.c tools/ioemu/vl.c tools/ioemu/vl.h tools/python/xen/xend/XendConfig.py tools/python/xen/xend/image.py tools/python/xen/xm/create.py
line diff
     1.1 --- a/tools/examples/xmexample.hvm	Tue Mar 18 11:40:30 2008 +0000
     1.2 +++ b/tools/examples/xmexample.hvm	Tue Mar 18 11:47:58 2008 +0000
     1.3 @@ -135,6 +135,11 @@ device_model = '/usr/' + arch_libdir + '
     1.4  sdl=0
     1.5  
     1.6  #----------------------------------------------------------------------------
     1.7 +# enable OpenGL for texture rendering inside the SDL window, default = 1
     1.8 +# valid only if sdl is enabled.
     1.9 +opengl=1
    1.10 +
    1.11 +#----------------------------------------------------------------------------
    1.12  # enable VNC library for graphics, default = 1
    1.13  vnc=1
    1.14  
     2.1 --- a/tools/ioemu/configure	Tue Mar 18 11:40:30 2008 +0000
     2.2 +++ b/tools/ioemu/configure	Tue Mar 18 11:47:58 2008 +0000
     2.3 @@ -190,6 +190,8 @@ for opt do
     2.4    ;;
     2.5    --disable-sdl) sdl="no"
     2.6    ;;
     2.7 +  --disable-opengl) opengl="no"
     2.8 +  ;;
     2.9    --enable-coreaudio) coreaudio="yes"
    2.10    ;;
    2.11    --enable-alsa) alsa="yes"
    2.12 @@ -539,6 +541,26 @@ else
    2.13  fi # -z $sdl
    2.14  
    2.15  ##########################################
    2.16 +# OpenGL test
    2.17 +
    2.18 +if test -z "$opengl" && test "$sdl" = "yes"
    2.19 +then
    2.20 +cat > $TMPC << EOF
    2.21 +#include <GL/gl.h>
    2.22 +#ifndef GL_TEXTURE_RECTANGLE_ARB
    2.23 +#error "Opengl doesn't support GL_TEXTURE_RECTANGLE_ARB"
    2.24 +#endif
    2.25 +int main( void ) { return (int) glGetString(GL_EXTENSIONS); }
    2.26 +EOF
    2.27 +if $cc -o $TMPE $TMPC -lGL 2> /dev/null
    2.28 +then
    2.29 +opengl="yes"
    2.30 +else
    2.31 +opengl="no"
    2.32 +fi
    2.33 +fi
    2.34 +
    2.35 +##########################################
    2.36  # alsa sound support libraries
    2.37  
    2.38  if test "$alsa" = "yes" ; then
    2.39 @@ -612,6 +634,7 @@ echo "SDL support       $sdl"
    2.40  if test "$sdl" != "no" ; then
    2.41      echo "SDL static link   $sdl_static"
    2.42  fi
    2.43 +echo "OpenGL support    $opengl"
    2.44  echo "mingw32 support   $mingw32"
    2.45  echo "Adlib support     $adlib"
    2.46  echo "CoreAudio support $coreaudio"
    2.47 @@ -995,6 +1018,15 @@ if test "$target_user_only" = "no"; then
    2.48      fi
    2.49  fi
    2.50  
    2.51 +if test $opengl = "yes"
    2.52 +then
    2.53 +    echo "#define CONFIG_OPENGL 1" >> $config_h
    2.54 +    echo "CONFIG_OPENGL=yes" >> $config_mak
    2.55 +    echo "SDL_CFLAGS+=-I/usr/include/GL" >> $config_mak
    2.56 +    echo "SDL_LIBS+=-lXext" >> $config_mak
    2.57 +    echo "SDL_LIBS+=-lGL" >> $config_mak
    2.58 +fi
    2.59 +
    2.60  if test "$cocoa" = "yes" ; then
    2.61      echo "#define CONFIG_COCOA 1" >> $config_h
    2.62      echo "CONFIG_COCOA=yes" >> $config_mak
     3.1 --- a/tools/ioemu/sdl.c	Tue Mar 18 11:40:30 2008 +0000
     3.2 +++ b/tools/ioemu/sdl.c	Tue Mar 18 11:47:58 2008 +0000
     3.3 @@ -29,6 +29,10 @@
     3.4  #include <signal.h>
     3.5  #endif
     3.6  
     3.7 +#ifdef CONFIG_OPENGL
     3.8 +#include <SDL_opengl.h>
     3.9 +#endif
    3.10 +
    3.11  static SDL_Surface *screen;
    3.12  static SDL_Surface *shared = NULL;
    3.13  static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
    3.14 @@ -44,6 +48,99 @@ static int width, height;
    3.15  static SDL_Cursor *sdl_cursor_normal;
    3.16  static SDL_Cursor *sdl_cursor_hidden;
    3.17  static int absolute_enabled = 0;
    3.18 +static int opengl_enabled;
    3.19 +
    3.20 +#ifdef CONFIG_OPENGL
    3.21 +static GLint tex_format;
    3.22 +static GLint tex_type;
    3.23 +static GLuint texture_ref = 0;
    3.24 +static GLint gl_format;
    3.25 +
    3.26 +static void opengl_setdata(DisplayState *ds, void *pixels)
    3.27 +{
    3.28 +    glEnable(GL_TEXTURE_RECTANGLE_ARB);
    3.29 +    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    3.30 +    glClearColor(0, 0, 0, 0);
    3.31 +    glDisable(GL_BLEND);
    3.32 +    glDisable(GL_LIGHTING);
    3.33 +    glDisable(GL_DEPTH_TEST);
    3.34 +    glDepthMask(GL_FALSE);
    3.35 +    glDisable(GL_CULL_FACE);
    3.36 +    glViewport( 0, 0, screen->w, screen->h);
    3.37 +    glMatrixMode(GL_PROJECTION);
    3.38 +    glLoadIdentity();
    3.39 +    glOrtho(0, screen->w, screen->h, 0, -1,1);
    3.40 +    glMatrixMode(GL_MODELVIEW);
    3.41 +    glLoadIdentity();
    3.42 +    glClear(GL_COLOR_BUFFER_BIT);
    3.43 +    ds->data = pixels;
    3.44 +
    3.45 +    if (texture_ref) {
    3.46 +        glDeleteTextures(1, &texture_ref);
    3.47 +        texture_ref = 0;
    3.48 +    }
    3.49 +
    3.50 +    glGenTextures(1, &texture_ref);
    3.51 +    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_ref);
    3.52 +    glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
    3.53 +    switch (ds->depth) {
    3.54 +        case 8:
    3.55 +            tex_format = GL_RGB;
    3.56 +            tex_type = GL_UNSIGNED_BYTE_3_3_2;
    3.57 +            glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
    3.58 +            break;
    3.59 +        case 16:
    3.60 +            tex_format = GL_RGB;
    3.61 +            tex_type = GL_UNSIGNED_SHORT_5_6_5;
    3.62 +            glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
    3.63 +            break;
    3.64 +        case 24:
    3.65 +            tex_format = GL_BGR;
    3.66 +            tex_type = GL_UNSIGNED_BYTE;
    3.67 +            glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
    3.68 +            break;
    3.69 +        case 32:
    3.70 +            if (!ds->bgr) {
    3.71 +                tex_format = GL_BGRA;
    3.72 +                tex_type = GL_UNSIGNED_BYTE;
    3.73 +            } else {
    3.74 +                tex_format = GL_RGBA;
    3.75 +                tex_type = GL_UNSIGNED_BYTE;                
    3.76 +            }
    3.77 +            glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
    3.78 +            break;
    3.79 +    }   
    3.80 +    glPixelStorei(GL_UNPACK_ROW_LENGTH, (ds->linesize * 8 / ds->depth) - ds->width);
    3.81 +    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, gl_format, ds->width, ds->height, 0, tex_format, tex_type, pixels);
    3.82 +    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_PRIORITY, 1.0);
    3.83 +    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    3.84 +    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    3.85 +    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    3.86 +    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    3.87 +    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
    3.88 +}
    3.89 +
    3.90 +static void opengl_update(DisplayState *ds, int x, int y, int w, int h)
    3.91 +{  
    3.92 +    int bpp = ds->depth / 8;
    3.93 +    GLvoid *pixels = ds->data + y * ds->linesize + x * bpp;
    3.94 +    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_ref);
    3.95 +    glPixelStorei(GL_UNPACK_ROW_LENGTH, (ds->linesize / bpp) - w);
    3.96 +    glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, w, h, tex_format, tex_type, pixels);
    3.97 +    glBegin(GL_QUADS);
    3.98 +        glTexCoord2d(0, 0);
    3.99 +        glVertex2d(0, 0);
   3.100 +        glTexCoord2d(ds->width, 0);
   3.101 +        glVertex2d(screen->w, 0);
   3.102 +        glTexCoord2d(ds->width, ds->height);
   3.103 +        glVertex2d(screen->w, screen->h);
   3.104 +        glTexCoord2d(0, ds->height);
   3.105 +        glVertex2d(0, screen->h);
   3.106 +    glEnd();
   3.107 +    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
   3.108 +    SDL_GL_SwapBuffers();
   3.109 +}
   3.110 +#endif
   3.111  
   3.112  static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
   3.113  {
   3.114 @@ -96,17 +193,26 @@ static void sdl_resize(DisplayState *ds,
   3.115  
   3.116      //    printf("resizing to %d %d\n", w, h);
   3.117  
   3.118 -    flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_DOUBLEBUF|SDL_HWPALETTE;
   3.119 -    if (gui_fullscreen)
   3.120 +#ifdef CONFIG_OPENGL
   3.121 +    if (ds->shared_buf && opengl_enabled)
   3.122 +        flags = SDL_OPENGL|SDL_RESIZABLE;
   3.123 +    else
   3.124 +#endif
   3.125 +        flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_DOUBLEBUF|SDL_HWPALETTE;
   3.126 +
   3.127 +    if (gui_fullscreen) {
   3.128          flags |= SDL_FULLSCREEN;
   3.129 -
   3.130 +        flags &= ~SDL_RESIZABLE;
   3.131 +    }
   3.132 +    
   3.133      width = w;
   3.134      height = h;
   3.135  
   3.136   again:
   3.137      screen = SDL_SetVideoMode(w, h, 0, flags);
   3.138 +#ifndef CONFIG_OPENGL
   3.139      if (!screen) {
   3.140 -        fprintf(stderr, "Could not open SDL display\n");
   3.141 +        fprintf(stderr, "Could not open SDL display: %s\n", SDL_GetError());
   3.142          exit(1);
   3.143      }
   3.144      if (!screen->pixels && (flags & SDL_HWSURFACE) && (flags & SDL_FULLSCREEN)) {
   3.145 @@ -115,9 +221,10 @@ static void sdl_resize(DisplayState *ds,
   3.146      }
   3.147  
   3.148      if (!screen->pixels) {
   3.149 -        fprintf(stderr, "Could not open SDL display\n");
   3.150 +        fprintf(stderr, "Could not open SDL display: %s\n", SDL_GetError());
   3.151          exit(1);
   3.152      }
   3.153 +#endif
   3.154      ds->width = w;
   3.155      ds->height = h;
   3.156      if (!ds->shared_buf) {
   3.157 @@ -131,6 +238,25 @@ static void sdl_resize(DisplayState *ds,
   3.158          ds->linesize = screen->pitch;
   3.159      } else {
   3.160          ds->linesize = linesize;
   3.161 +#ifdef CONFIG_OPENGL
   3.162 +        switch(screen->format->BitsPerPixel) {
   3.163 +        case 8:
   3.164 +            gl_format = GL_RGB;
   3.165 +            break;
   3.166 +        case 16:
   3.167 +            gl_format = GL_RGB;
   3.168 +            break;
   3.169 +        case 24:
   3.170 +            gl_format = GL_RGB;
   3.171 +            break;
   3.172 +        case 32:
   3.173 +            if (!screen->format->Rshift)
   3.174 +                gl_format = GL_BGRA;
   3.175 +            else
   3.176 +                gl_format = GL_RGBA;
   3.177 +            break;
   3.178 +        };
   3.179 +#endif
   3.180      }
   3.181  }
   3.182  
   3.183 @@ -139,7 +265,13 @@ static void sdl_colourdepth(DisplayState
   3.184      if (!depth || !ds->depth) return;
   3.185      ds->shared_buf = 1;
   3.186      ds->depth = depth;
   3.187 -    ds->linesize = width * depth / 8; 
   3.188 +    ds->linesize = width * depth / 8;
   3.189 +#ifdef CONFIG_OPENGL
   3.190 +    if (opengl_enabled) {
   3.191 +        ds->dpy_update = opengl_update;
   3.192 +        ds->dpy_setdata = opengl_setdata;
   3.193 +    }
   3.194 +#endif
   3.195  }
   3.196  
   3.197  /* generic keyboard conversion */
   3.198 @@ -331,8 +463,8 @@ static void sdl_send_mouse_event(int dx,
   3.199  	}
   3.200  
   3.201  	SDL_GetMouseState(&dx, &dy);
   3.202 -        dx = dx * 0x7FFF / (width - 1);
   3.203 -        dy = dy * 0x7FFF / (height - 1);
   3.204 +        dx = dx * 0x7FFF / (screen->w - 1);
   3.205 +        dy = dy * 0x7FFF / (screen->h - 1);
   3.206      } else if (absolute_enabled) {
   3.207  	sdl_show_cursor();
   3.208  	absolute_enabled = 0;
   3.209 @@ -371,7 +503,7 @@ static void sdl_refresh(DisplayState *ds
   3.210      while (SDL_PollEvent(ev)) {
   3.211          switch (ev->type) {
   3.212          case SDL_VIDEOEXPOSE:
   3.213 -            sdl_update(ds, 0, 0, screen->w, screen->h);
   3.214 +            sdl_update(ds, 0, 0, ds->width, ds->height);
   3.215              break;
   3.216          case SDL_KEYDOWN:
   3.217          case SDL_KEYUP:
   3.218 @@ -528,6 +660,16 @@ static void sdl_refresh(DisplayState *ds
   3.219  		}
   3.220  	    }
   3.221              break;
   3.222 +#ifdef CONFIG_OPENGL
   3.223 +        case SDL_VIDEORESIZE:
   3.224 +        {
   3.225 +            SDL_ResizeEvent *rev = &ev->resize;
   3.226 +            screen = SDL_SetVideoMode(rev->w, rev->h, 0, SDL_OPENGL|SDL_RESIZABLE);
   3.227 +            opengl_setdata(ds, ds->data);
   3.228 +            opengl_update(ds, 0, 0, ds->width, ds->height);
   3.229 +            break;
   3.230 +        }
   3.231 +#endif
   3.232          default:
   3.233              break;
   3.234          }
   3.235 @@ -536,13 +678,17 @@ static void sdl_refresh(DisplayState *ds
   3.236  
   3.237  static void sdl_cleanup(void) 
   3.238  {
   3.239 +#ifdef CONFIG_OPENGL
   3.240 +    if (texture_ref) glDeleteTextures(1, &texture_ref);
   3.241 +#endif
   3.242      SDL_Quit();
   3.243  }
   3.244  
   3.245 -void sdl_display_init(DisplayState *ds, int full_screen)
   3.246 +void sdl_display_init(DisplayState *ds, int full_screen, int opengl)
   3.247  {
   3.248      int flags;
   3.249      uint8_t data = 0;
   3.250 +    opengl_enabled = opengl;
   3.251  
   3.252  #if defined(__APPLE__)
   3.253      /* always use generic keymaps */
     4.1 --- a/tools/ioemu/vl.c	Tue Mar 18 11:40:30 2008 +0000
     4.2 +++ b/tools/ioemu/vl.c	Tue Mar 18 11:47:58 2008 +0000
     4.3 @@ -174,6 +174,11 @@ int graphic_height = 600;
     4.4  #endif
     4.5  int graphic_depth = 15;
     4.6  int full_screen = 0;
     4.7 +#ifdef CONFIG_OPENGL
     4.8 +int opengl_enabled = 1;
     4.9 +#else
    4.10 +int opengl_enabled = 0;
    4.11 +#endif
    4.12  int no_quit = 0;
    4.13  CharDriverState *serial_hds[MAX_SERIAL_PORTS];
    4.14  CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
    4.15 @@ -6488,6 +6493,9 @@ void help(void)
    4.16  #ifdef CONFIG_SDL
    4.17             "-no-quit        disable SDL window close capability\n"
    4.18  #endif
    4.19 +#ifdef CONFIG_OPENGL
    4.20 +           "-disable-opengl disable OpenGL rendering, using SDL"
    4.21 +#endif
    4.22  #ifdef TARGET_I386
    4.23             "-no-fd-bootchk  disable boot signature checking for floppy disks\n"
    4.24  #endif
    4.25 @@ -6666,6 +6674,7 @@ enum {
    4.26      QEMU_OPTION_loadvm,
    4.27      QEMU_OPTION_full_screen,
    4.28      QEMU_OPTION_no_quit,
    4.29 +    QEMU_OPTION_disable_opengl,
    4.30      QEMU_OPTION_pidfile,
    4.31      QEMU_OPTION_no_kqemu,
    4.32      QEMU_OPTION_kernel_kqemu,
    4.33 @@ -6763,6 +6772,7 @@ const QEMUOption qemu_options[] = {
    4.34  #ifdef CONFIG_SDL
    4.35      { "no-quit", 0, QEMU_OPTION_no_quit },
    4.36  #endif
    4.37 +    { "disable-opengl", 0, QEMU_OPTION_disable_opengl },
    4.38      { "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
    4.39      { "win2k-hack", 0, QEMU_OPTION_win2k_hack },
    4.40      { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
    4.41 @@ -7534,6 +7544,9 @@ int main(int argc, char **argv)
    4.42                  no_quit = 1;
    4.43                  break;
    4.44  #endif
    4.45 +            case QEMU_OPTION_disable_opengl:
    4.46 +                opengl_enabled = 0;
    4.47 +                break;
    4.48              case QEMU_OPTION_pidfile:
    4.49                  create_pidfile(optarg);
    4.50                  break;
    4.51 @@ -7860,7 +7873,7 @@ int main(int argc, char **argv)
    4.52  	xenstore_write_vncport(vnc_display_port);
    4.53      } else {
    4.54  #if defined(CONFIG_SDL)
    4.55 -        sdl_display_init(ds, full_screen);
    4.56 +        sdl_display_init(ds, full_screen, opengl_enabled);
    4.57  #elif defined(CONFIG_COCOA)
    4.58          cocoa_display_init(ds, full_screen);
    4.59  #else
     5.1 --- a/tools/ioemu/vl.h	Tue Mar 18 11:40:30 2008 +0000
     5.2 +++ b/tools/ioemu/vl.h	Tue Mar 18 11:47:58 2008 +0000
     5.3 @@ -982,7 +982,7 @@ void isa_cirrus_vga_init(DisplayState *d
     5.4                           unsigned long vga_ram_offset, int vga_ram_size);
     5.5  
     5.6  /* sdl.c */
     5.7 -void sdl_display_init(DisplayState *ds, int full_screen);
     5.8 +void sdl_display_init(DisplayState *ds, int full_screen, int opengl_enable);
     5.9  
    5.10  /* cocoa.m */
    5.11  void cocoa_display_init(DisplayState *ds, int full_screen);
     6.1 --- a/tools/python/xen/xend/XendConfig.py	Tue Mar 18 11:40:30 2008 +0000
     6.2 +++ b/tools/python/xen/xend/XendConfig.py	Tue Mar 18 11:47:58 2008 +0000
     6.3 @@ -142,6 +142,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
     6.4      'rtc_timeoffset': int,
     6.5      'serial': str,
     6.6      'sdl': int,
     6.7 +    'opengl': int,
     6.8      'soundhw': str,
     6.9      'stdvga': int,
    6.10      'usb': int,
     7.1 --- a/tools/python/xen/xend/image.py	Tue Mar 18 11:40:30 2008 +0000
     7.2 +++ b/tools/python/xen/xend/image.py	Tue Mar 18 11:47:58 2008 +0000
     7.3 @@ -263,7 +263,8 @@ class ImageHandler:
     7.4  
     7.5          elif has_sdl:
     7.6              # SDL is default in QEMU.
     7.7 -            pass
     7.8 +            if int(vmConfig['platform'].get('opengl', 1)) != 1 :
     7.9 +                ret.append('-disable-opengl')
    7.10          else:
    7.11              ret.append('-nographic')
    7.12  
     8.1 --- a/tools/python/xen/xm/create.py	Tue Mar 18 11:40:30 2008 +0000
     8.2 +++ b/tools/python/xen/xm/create.py	Tue Mar 18 11:47:58 2008 +0000
     8.3 @@ -504,6 +504,10 @@ gopts.var('sdl', val='',
     8.4            fn=set_value, default=None,
     8.5            use="""Should the device model use SDL?""")
     8.6  
     8.7 +gopts.var('opengl', val='',
     8.8 +          fn=set_value, default=None,
     8.9 +          use="""Enable\Disable OpenGL""")
    8.10 +
    8.11  gopts.var('display', val='DISPLAY',
    8.12            fn=set_value, default=None,
    8.13            use="X11 display to use")
    8.14 @@ -745,7 +749,7 @@ def configure_hvm(config_image, vals):
    8.15               'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
    8.16               'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
    8.17               'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
    8.18 -             'guest_os_type', 'hap']
    8.19 +             'guest_os_type', 'hap', 'opengl']
    8.20  
    8.21      for a in args:
    8.22          if a in vals.__dict__ and vals.__dict__[a] is not None: