Fix another round of squirrel coverity issues
[supertux.git] / contrib / supertux-nogl.diff
index de007ab..99fb95a 100644 (file)
 #  with SDL functions only. Many features are removed from the video engine,
 #  so don't expect much.
 #
-#  Note that the patched sources will need an additional library, SDL_gfx, to 
-#  compile.
-#
 #  Installing the patch should be pretty straightforward. Simply run the
 #  following command prior to running autogen.sh and configure:
 #
-#  patch -p1 < contrib/supertux-nogl.diff
+#  patch -p0 < contrib/supertux-nogl.diff
 #
-#  This patch works for revision 3858. It may break for later revisions.
+#  This patch works for revision 5072. It may break for later revisions.
 #
 # -----------------------------------------------------------------------------
-diff -Naur supertux/INSTALL supertux-nogl/INSTALL
---- supertux/INSTALL   2006-03-03 21:49:07.000000000 +0100
-+++ supertux-nogl/INSTALL      2006-04-07 04:13:00.000000000 +0200
-@@ -1,7 +1,7 @@
- - Install instructions for SuperTux -
- http://supertux.berlios.de/
--Last update: October 11, 2005 by Ondra Hosek
-+Last update: March 4, 2006 by Christoph Sommer
- BINARIES
- --------
-@@ -34,17 +34,15 @@
-     Download: ftp://ftp.perforce.com/pub/jam
-     Homepage: http://www.perforce.com/jam/jam.html
--* OpenGL headers and libraries
--    opengl libraries and headers are specific to your graphics card. Make sure
--    that you have hardware accelerated opengl drivers installed. Software
--    renderers like Mesa will make supertux unplayable slow.
--
- * SDL 1.2.5 or later (1.2.8 is recommended on MacOS/X)
-     http://www.libsdl.org
- * SDL_image (any version)
-     http://www.libsdl.org/projects/SDL_image
-+* SDL_gfx (2.0.13 or later)
-+    http://www.ferzkopp.net/Software/SDL_gfx-2.0/
-+
- * PhysicsFS (1.0.0, the development branch 1.1.x is buggy and does not work,
-              1.2.0 and later should work when it is released)
-     http://www.icculus.org/physfs
-diff -Naur supertux/README supertux-nogl/README
---- supertux/README    2006-03-03 20:43:38.000000000 +0100
-+++ supertux-nogl/README       2006-04-07 04:13:00.000000000 +0200
-@@ -2,7 +2,7 @@
- - An introduction for SuperTux -
- http://supertux.berlios.de/
--Last update: October 13, 2005
-+Last update: March 4, 2006 by Christoph Sommer
- DESCRIPTION
- -----------
-@@ -75,10 +75,9 @@
-   Also, notice that SuperTux saves the options, so it's often enough to
-   specify them once.
--  The game uses OpenGL to render the graphics. You will either need a CPU
--  with about 10 GHz or an accelerated video card with the vendor's drivers.
--  (On Linux, the team recommends using cards from NVidia with the proprietary
--  drivers, but ATI or another verndor should do.)
-+  The game uses SDL to render the graphics. You will either need a CPU
-+  with about 1 GHz or go get the original version of SuperTux which uses
-+  OpenGL.
- PLAYING THE GAME
-diff -Naur supertux/configure.ac supertux-nogl/configure.ac
---- supertux/configure.ac      2006-03-03 20:43:38.000000000 +0100
-+++ supertux-nogl/configure.ac 2006-04-07 04:13:00.000000000 +0200
-@@ -11,7 +11,7 @@
- dnl Process this file with autoconf to produce a configure script.
- AC_PREREQ([2.54])
--AC_INIT(supertux, 0.2-svn)
-+AC_INIT(supertux, 0.2-nogl-svn)
- AC_CONFIG_SRCDIR([src/main.cpp])
- AC_CONFIG_AUX_DIR([mk/autoconf])
- AC_CANONICAL_TARGET
-@@ -112,6 +105,14 @@
-         [AC_MSG_ERROR([Please install SDLImage >= 1.2.1])],
-         [$SDL_CFLAGS], [$SDL_LIBS])
-+dnl FIXME: This is far from perfect
-+NP_FINDLIB([SDLGFX], [SDL_gfx], [SDL_gfx >= 2.0.13],
-+        NP_LANG_PROGRAM([#include <SDL_rotozoom.h>], [0;]),
-+        [], [-lSDL_gfx],
-+        [],
-+        [AC_MSG_ERROR([Please install SDL_gfx >= 2.0.13])],
-+        [$SDL_CFLAGS], [$SDL_LIBS])
+Index: src/gameconfig.hpp
+===================================================================
+--- src/gameconfig.hpp (revision 5071)
++++ src/gameconfig.hpp (working copy)
+@@ -19,6 +19,8 @@
+ #ifndef SUPERTUX_CONFIG_H
+ #define SUPERTUX_CONFIG_H
++#include <config.h>
 +
- NP_FINDLIB([PHYSFS], [physfs], [physfs >= 1.0.0],
-         NP_LANG_PROGRAM([
- #include <stdio.h>
-@@ -131,11 +132,6 @@
-          [AC_MSG_ERROR([Please intall OpenAL])],
-          [], [])
--AX_CHECK_GL
--if test "$no_gl" = "yes"; then
--  AC_MSG_ERROR([Please install opengl libraries and headers])
--fi
--
- dnl Checks for library functions.
- AC_CHECK_FUNCS(mkdir strdup strstr)
-diff -Naur supertux/src/Jamfile supertux-nogl/src/Jamfile
---- supertux/src/Jamfile       2006-03-03 20:34:49.000000000 +0100
-+++ supertux-nogl/src/Jamfile  2006-04-07 04:11:50.000000000 +0200
-@@ -24,7 +24,7 @@
- Application supertux : $(sources) $(wrapper_objects) ;
- C++Flags supertux : -DAPPDATADIR='\"$(appdatadir)\"' ;
- LinkWith supertux : squirrel ;
--ExternalLibs supertux : SDL SDLIMAGE GL OPENAL VORBIS VORBISFILE OGG ICONV PHYSFS BINRELOC ;
-+ExternalLibs supertux : SDL SDLIMAGE SDLGFX OPENAL VORBIS VORBISFILE OGG ICONV PHYSFS BINRELOC ;
- Help supertux : "Build the supertux executable" ;
- IncludeDir supertux : squirrel/include ;
-diff -Naur supertux/src/main.cpp supertux-nogl/src/main.cpp
---- supertux/src/main.cpp      2006-04-07 03:32:14.000000000 +0200
-+++ supertux-nogl/src/main.cpp 2006-04-07 04:11:50.000000000 +0200
-@@ -35,7 +35,6 @@
- #include <physfs.h>
- #include <SDL.h>
- #include <SDL_image.h>
--#include <GL/gl.h>
- #include "gameconfig.hpp"
- #include "resources.hpp"
-@@ -317,7 +275,7 @@
-   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
-   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
-   
--  int flags = SDL_OPENGL;
-+  int flags = SDL_SWSURFACE;
-   if(config->use_fullscreen)
-     flags |= SDL_FULLSCREEN;
-   int width = config->screenwidth;
-@@ -347,24 +305,6 @@
-   }
- #endif
+ #include <string>
  
--  // setup opengl state and transform
--  glDisable(GL_DEPTH_TEST);
--  glDisable(GL_CULL_FACE);
--  glEnable(GL_TEXTURE_2D);
--  glEnable(GL_BLEND);
--  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
--
--  glViewport(0, 0, screen->w, screen->h);
--  glMatrixMode(GL_PROJECTION);
--  glLoadIdentity();
--  // logical resolution here not real monitor resolution
--  glOrtho(0, 800, 600, 0, -1.0, 1.0);
--  glMatrixMode(GL_MODELVIEW);
--  glLoadIdentity();
--  glTranslatef(0, 0, 0);
--
--  check_gl_error("Setting up view matrices");
--
-   if(texture_manager != NULL)
-     texture_manager->reload_textures();
-   else
-diff -aur supertux/src/video/drawing_context.cpp supertux-nogl/src/video/drawing_context.cpp
---- supertux/src/video/drawing_context.cpp     2006-07-03 02:00:48.000000000 +0200
-+++ supertux-nogl/src/video/drawing_context.cpp        2006-07-03 02:00:29.000000000 +0200
-@@ -23,7 +23,6 @@
+ class Config
+@@ -39,6 +41,9 @@
+   float aspect_ratio;
+   bool use_fullscreen;
++#ifdef HAVE_OPENGL
++  bool use_opengl;
++#endif
+   bool try_vsync;
+   bool show_fps;
+   bool sound_enabled;
+Index: src/video/drawing_context.cpp
+===================================================================
+--- src/video/drawing_context.cpp      (revision 5071)
++++ src/video/drawing_context.cpp      (working copy)
+@@ -23,17 +23,16 @@
  #include <cassert>
  #include <iostream>
  #include <SDL_image.h>
 -#include <GL/gl.h>
+ #include <sstream>
+ #include <iomanip>
+ #include <physfs.h>
  
++#include "glutil.hpp"
  #include "drawing_context.hpp"
  #include "surface.hpp"
-@@ -49,24 +48,12 @@
+ #include "font.hpp"
+ #include "main.hpp"
+ #include "gameconfig.hpp"
+-#include "glutil.hpp"
+ #include "texture.hpp"
+ #include "texture_manager.hpp"
+ #include "obstack/obstackpp.hpp"
+@@ -113,6 +112,7 @@
  {
    screen = SDL_GetVideoSurface();
  
--  lightmap_width = screen->w / LIGHTMAP_DIV;
--  lightmap_height = screen->h / LIGHTMAP_DIV;
--  unsigned int width = next_po2(lightmap_width);
--  unsigned int height = next_po2(lightmap_height);
--
--  lightmap = new Texture(width, height, GL_RGB);
--
--  lightmap_uv_right = static_cast<float>(lightmap_width) / static_cast<float>(width);
--  lightmap_uv_bottom = static_cast<float>(lightmap_height) / static_cast<float>(height);
--  texture_manager->register_texture(lightmap);
--
-+  target = NORMAL;
-   requests = &drawing_requests;
- }
- DrawingContext::~DrawingContext()
- {
--  texture_manager->remove_texture(lightmap);
--  delete lightmap;
- }
- void
-@@ -74,6 +61,8 @@
-                              float angle, const Color& color, const Blend& blend,
-                              int layer)
- {
-+  if(target != NORMAL) return;
-+
-   assert(surface != 0);
-   
-   DrawingRequest request;
-@@ -109,6 +98,8 @@
- DrawingContext::draw_surface_part(const Surface* surface, const Vector& source,
-     const Vector& size, const Vector& dest, int layer)
- {
-+  if(target != NORMAL) return;
-+
-   assert(surface != 0);
-   DrawingRequest request;
-@@ -148,6 +139,8 @@
- DrawingContext::draw_text(const Font* font, const std::string& text,
-     const Vector& position, FontAlignment alignment, int layer)
- {
-+  if(target != NORMAL) return;
-+
-   DrawingRequest request;
-   request.type = TEXT;
-@@ -169,6 +162,8 @@
- DrawingContext::draw_center_text(const Font* font, const std::string& text,
-     const Vector& position, int layer)
- {
-+  if(target != NORMAL) return;
-+
-   draw_text(font, text, Vector(position.x + SCREEN_WIDTH/2, position.y),
-       CENTER_ALLIGN, layer);
- }
-@@ -176,6 +171,8 @@
- void
- DrawingContext::draw_gradient(const Color& top, const Color& bottom, int layer)
- {
-+  if(target != NORMAL) return;
-+
-   DrawingRequest request;
++#ifdef HAVE_OPENGL
+   lightmap_width = screen->w / LIGHTMAP_DIV;
+   lightmap_height = screen->h / LIGHTMAP_DIV;
+   unsigned int width = next_po2(lightmap_width);
+@@ -123,6 +123,7 @@
+   lightmap_uv_right = static_cast<float>(lightmap_width) / static_cast<float>(width);
+   lightmap_uv_bottom = static_cast<float>(lightmap_height) / static_cast<float>(height);
+   texture_manager->register_texture(lightmap);
++#endif
  
-   request.type = GRADIENT;
-@@ -197,6 +194,8 @@
- DrawingContext::draw_filled_rect(const Vector& topleft, const Vector& size,
-                                  const Color& color, int layer)
- {
-+  if(target != NORMAL) return;
-+
-   DrawingRequest request;
+   requests = &drawing_requests;
  
-   request.type = FILLRECT;
-@@ -219,6 +218,8 @@
- DrawingContext::draw_filled_rect(const Rect& rect, const Color& color,
-                                  int layer)
+@@ -133,8 +134,10 @@
  {
-+  if(target != NORMAL) return;
-+
-   DrawingRequest request;
+   obstack_free(&obst, NULL);
  
-   request.type = FILLRECT;
-@@ -252,24 +253,56 @@
-   delete surfacepartrequest;
++#ifdef HAVE_OPENGL
+   texture_manager->remove_texture(lightmap);
+   delete lightmap;
++#endif
  }
  
-+namespace
-+{
-+  void fillrect(SDL_Surface* screen, float x, float y, float w, float h, int r, int g, int b, int a)
+ void
+@@ -338,15 +341,31 @@
+   const GetLightRequest* getlightrequest 
+     = (GetLightRequest*) request.request_data;
+-  float pixels[3];
+-  for( int i = 0; i<3; i++)
+-    pixels[i] = 0.0f; //set to black
++#ifdef HAVE_OPENGL
++  if(config->use_opengl)
 +  {
-+    if(w < 0) {
-+      x += w;
-+      w = -w;
-+    }
-+    if(h < 0) {
-+      y += h;
-+      h = -h;
-+    }
-+
-+    SDL_Rect src, rect;
-+    SDL_Surface *temp = NULL;
-+
-+    rect.x = (int)x;
-+    rect.y = (int)y;
-+    rect.w = (int)w;
-+    rect.h = (int)h;
-+
-+    if(a != 255) {
-+      temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
-+
-+      src.x = 0;
-+      src.y = 0;
-+      src.w = rect.w;
-+      src.h = rect.h;
-+
-+      SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, r, g, b));
-+      SDL_SetAlpha(temp, SDL_SRCALPHA, a);
-+      SDL_BlitSurface(temp,0,screen,&rect);
-+      SDL_FreeSurface(temp);
++    float pixels[3];
++    for( int i = 0; i<3; i++)
++      pixels[i] = 0.0f; //set to black
+-  float posX = request.pos.x * lightmap_width / SCREEN_WIDTH;
+-  float posY = screen->h - request.pos.y * lightmap_height / SCREEN_HEIGHT;
+-  glReadPixels((GLint) posX, (GLint) posY , 1, 1, GL_RGB, GL_FLOAT, pixels);
++    float posX = request.pos.x * lightmap_width / SCREEN_WIDTH;
++    float posY = screen->h - request.pos.y * lightmap_height / SCREEN_HEIGHT;
++    glReadPixels((GLint) posX, (GLint) posY , 1, 1, GL_RGB, GL_FLOAT, pixels);
+     *(getlightrequest->color_ptr) = Color( pixels[0], pixels[1], pixels[2]);
+-  //printf("get_light %f/%f =>%f/%f r%f g%f b%f\n", request.pos.x, request.pos.y, posX, posY, pixels[0], pixels[1], pixels[2]);
++    //printf("get_light %f/%f =>%f/%f r%f g%f b%f\n", request.pos.x, request.pos.y, posX, posY, pixels[0], pixels[1], pixels[2]);
++  }
++  else
++#endif
++  {
++    // FIXME: implement properly for SDL
++    static int i = 0;
++    i += 1; i &= 0xFFFF;
++    if (i & 0x8000) {
++      *(getlightrequest->color_ptr) = Color(0.0f, 0.0f, 0.0f);
 +    } else {
-+      SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
++      *(getlightrequest->color_ptr) = Color(1.0f, 1.0f, 1.0f);
 +    }
 +  }
-+}
-+
+ }
  void
- DrawingContext::draw_gradient(DrawingRequest& request)
- {
-   GradientRequest* gradientrequest = (GradientRequest*) request.request_data;
+@@ -370,17 +389,50 @@
    const Color& top = gradientrequest->top;
    const Color& bottom = gradientrequest->bottom;
--  
 -  glDisable(GL_TEXTURE_2D);
 -  glBegin(GL_QUADS);
 -  glColor4f(top.red, top.green, top.blue, top.alpha);
@@ -350,22 +158,77 @@ diff -aur supertux/src/video/drawing_context.cpp supertux-nogl/src/video/drawing
 -  glVertex2f(0, SCREEN_HEIGHT);
 -  glEnd();
 -  glEnable(GL_TEXTURE_2D);
-+  int width = 800;
-+  int height = 600;
-+  for(float y = 0; y < height; y += 2) ::fillrect(screen, 0, (int)y, width, 2, (int)(((float)(top.red-bottom.red)/(0-height)) * y + top.red), (int)(((float)(top.green-bottom.green)/(0-height)) * y + top.green), (int)(((float)(top.blue-bottom.blue)/(0-height)) * y + top.blue), 255);
+-  glColor4f(1, 1, 1, 1);
++#ifdef HAVE_OPENGL
++  if(config->use_opengl)
++  {
++    glDisable(GL_TEXTURE_2D);
++    glBegin(GL_QUADS);
++    glColor4f(top.red, top.green, top.blue, top.alpha);
++    glVertex2f(0, 0);
++    glVertex2f(SCREEN_WIDTH, 0);
++    glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
++    glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
++    glVertex2f(0, SCREEN_HEIGHT);
++    glEnd();
++    glEnable(GL_TEXTURE_2D);
++    glColor4f(1, 1, 1, 1);
++  }
++  else
++#endif
++  {
++    for(int y = 0;y < screen->h;++y)
++    {
++      Uint8 r = (Uint8)((((float)(top.red-bottom.red)/(0-screen->h)) * y + top.red) * 255);
++      Uint8 g = (Uint8)((((float)(top.green-bottom.green)/(0-screen->h)) * y + top.green) * 255);
++      Uint8 b = (Uint8)((((float)(top.blue-bottom.blue)/(0-screen->h)) * y + top.blue) * 255);
++      Uint8 a = (Uint8)((((float)(top.alpha-bottom.alpha)/(0-screen->h)) * y + top.alpha) * 255);
++      Uint32 color = SDL_MapRGB(screen->format, r, g, b);
 +
-   delete gradientrequest;
++      SDL_Rect rect;
++      rect.x = 0;
++      rect.y = y;
++      rect.w = screen->w;
++      rect.h = 1;
++
++      if(a == SDL_ALPHA_OPAQUE) {
++        SDL_FillRect(screen, &rect, color);
++      } else if(a != SDL_ALPHA_TRANSPARENT) {
++        SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
++
++        SDL_FillRect(temp, 0, color);
++        SDL_SetAlpha(temp, SDL_SRCALPHA, a);
++        SDL_BlitSurface(temp, 0, screen, &rect);
++        SDL_FreeSurface(temp);
++      }
++    }
++  }
  }
  
-@@ -294,18 +327,13 @@
-   float w = fillrectrequest->size.x;
-   float h = fillrectrequest->size.y;
+ void
+@@ -398,29 +450,76 @@
+   const FillRectRequest* fillrectrequest
+     = (FillRectRequest*) request.request_data;
+-  float x = request.pos.x;
+-  float y = request.pos.y;
+-  float w = fillrectrequest->size.x;
+-  float h = fillrectrequest->size.y;
++#ifdef HAVE_OPENGL
++  if(config->use_opengl)
++  {
++    float x = request.pos.x;
++    float y = request.pos.y;
++    float w = fillrectrequest->size.x;
++    float h = fillrectrequest->size.y;
  
 -  glDisable(GL_TEXTURE_2D);
 -  glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
 -            fillrectrequest->color.blue, fillrectrequest->color.alpha);
-- 
++    glDisable(GL_TEXTURE_2D);
++    glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
++              fillrectrequest->color.blue, fillrectrequest->color.alpha);
 -  glBegin(GL_QUADS);
 -  glVertex2f(x, y);
 -  glVertex2f(x+w, y);
@@ -373,214 +236,614 @@ diff -aur supertux/src/video/drawing_context.cpp supertux-nogl/src/video/drawing
 -  glVertex2f(x, y+h);
 -  glEnd();
 -  glEnable(GL_TEXTURE_2D);
-+  int r = static_cast<int>(fillrectrequest->color.red);
-+  int g = static_cast<int>(fillrectrequest->color.green);
-+  int b = static_cast<int>(fillrectrequest->color.blue);
-+  int a = static_cast<int>(fillrectrequest->color.alpha);
-+  ::fillrect(screen, x, y, w, h, r, g, b, a);
+-  
+-  glColor4f(1, 1, 1, 1);
++    glBegin(GL_QUADS);
++    glVertex2f(x, y);
++    glVertex2f(x+w, y);
++    glVertex2f(x+w, y+h);
++    glVertex2f(x, y+h);
++    glEnd();
++    glEnable(GL_TEXTURE_2D);
++    glColor4f(1, 1, 1, 1);
++  }
++  else
++#endif
++  {
++    float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
++    float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
++    int numerator;
++    int denominator;
++    if(xfactor < yfactor)
++    {
++      numerator = config->screenwidth;
++      denominator = SCREEN_WIDTH;
++    }
++    else
++    {
++      numerator = config->screenheight;
++      denominator = SCREEN_HEIGHT;
++    }
++
++    SDL_Rect rect;
++    rect.x = (Sint16)request.pos.x * numerator / denominator;
++    rect.y = (Sint16)request.pos.y * numerator / denominator;
++    rect.w = (Uint16)fillrectrequest->size.x * numerator / denominator;
++    rect.h = (Uint16)fillrectrequest->size.y * numerator / denominator;
++    Uint8 r = static_cast<Uint8>(fillrectrequest->color.red * 255);
++    Uint8 g = static_cast<Uint8>(fillrectrequest->color.green * 255);
++    Uint8 b = static_cast<Uint8>(fillrectrequest->color.blue * 255);
++    Uint8 a = static_cast<Uint8>(fillrectrequest->color.alpha * 255);
++    Uint32 color = SDL_MapRGB(screen->format, r, g, b);
++    if(a == SDL_ALPHA_OPAQUE) {
++      SDL_FillRect(screen, &rect, color);
++    } else if(a != SDL_ALPHA_TRANSPARENT) {
++      SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
 +
-   delete fillrectrequest;
++      SDL_FillRect(temp, 0, color);
++      SDL_SetAlpha(temp, SDL_SRCALPHA, a);
++      SDL_BlitSurface(temp, 0, screen, &rect);
++      SDL_FreeSurface(temp);
++    }
++  }
  }
  
-@@ -319,67 +347,10 @@
-   transformstack.clear();
-   target_stack.clear();
+ void
++#ifdef HAVE_OPENGL
+ DrawingContext::draw_lightmap(const DrawingRequest& request) const
++#else
++DrawingContext::draw_lightmap(const DrawingRequest&) const
++#endif
+ {
++#ifdef HAVE_OPENGL
+   const Texture* texture = reinterpret_cast<Texture*> (request.request_data);
  
--  bool use_lightmap = lightmap_requests.size() != 0;
--  
--  // PART1: create lightmap
--  if(use_lightmap) {
+   // multiple the lightmap with the framebuffer
+@@ -444,6 +543,7 @@
+   glEnd();
+   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
++#endif
+ }
+ void
+@@ -462,29 +562,38 @@
+   // PART1: create lightmap
+   if(use_lightmap) {
 -    glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
 -    glMatrixMode(GL_PROJECTION);
--    glLoadIdentity();               
+-    glLoadIdentity();
 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
 -    glMatrixMode(GL_MODELVIEW);
 -    glLoadIdentity();
--
--    // FIXME: Add ambient light support here
--    glClearColor(0.3, 0.3, 0.4, 1);
++#ifdef HAVE_OPENGL
++    if(config->use_opengl)
++    {
++      glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
++      glMatrixMode(GL_PROJECTION);
++      glLoadIdentity();
++      glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
++      glMatrixMode(GL_MODELVIEW);
++      glLoadIdentity();
+-    glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
 -    glClear(GL_COLOR_BUFFER_BIT);
 -    handle_drawing_requests(lightmap_requests);
 -    lightmap_requests.clear();
--  
++      glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
++      glClear(GL_COLOR_BUFFER_BIT);
++      handle_drawing_requests(lightmap_requests);
++      lightmap_requests.clear();
 -    glDisable(GL_BLEND);
 -    glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
 -    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
--
++      glDisable(GL_BLEND);
++      glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
++      glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
 -    glViewport(0, 0, screen->w, screen->h);
 -    glMatrixMode(GL_PROJECTION);
--    glLoadIdentity();               
+-    glLoadIdentity();
 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
--    glMatrixMode(GL_MODELVIEW);    
+-    glMatrixMode(GL_MODELVIEW);
 -    glLoadIdentity();
 -    glEnable(GL_BLEND);
--  }
--
--  //glClear(GL_COLOR_BUFFER_BIT);
-   handle_drawing_requests(drawing_requests);
++      glViewport(0, 0, screen->w, screen->h);
++      glMatrixMode(GL_PROJECTION);
++      glLoadIdentity();
++      glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
++      glMatrixMode(GL_MODELVIEW);
++      glLoadIdentity();
++      glEnable(GL_BLEND);
++    }
++    else
++#endif
++    {
++      // FIXME: SDL alternative
++    }
+     // add a lightmap drawing request into the queue
+     DrawingRequest* request = new(obst) DrawingRequest();
+@@ -499,7 +608,12 @@
    drawing_requests.clear();
+   obstack_free(&obst, NULL);
+   obstack_init(&obst);
+-  assert_gl("drawing");
++#ifdef HAVE_OPENGL
++  if(config->use_opengl)
++  {
++    assert_gl("drawing");
++  }
++#endif
  
--  if(use_lightmap) {
--    // multiple the lightmap with the framebuffer
--    glBlendFunc(GL_DST_COLOR, GL_ZERO);
--     
--    glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
--    glBegin(GL_QUADS);
--
--    glTexCoord2f(0, lightmap_uv_bottom);
--    glVertex2f(0, 0);
--
--    glTexCoord2f(lightmap_uv_right, lightmap_uv_bottom);
--    glVertex2f(SCREEN_WIDTH, 0);
--
--    glTexCoord2f(lightmap_uv_right, 0);
--    glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
--
--    glTexCoord2f(0, 0);
--    glVertex2f(0, SCREEN_HEIGHT);
--    
--    glEnd();
--
--    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+   // if a screenshot was requested, take one
+   if (screenshot_requested) {
+@@ -507,7 +621,16 @@
+     screenshot_requested = false;
+   }
+-  SDL_GL_SwapBuffers();
++#ifdef HAVE_OPENGL
++  if(config->use_opengl)
++  {
++    SDL_GL_SwapBuffers();
++  }
++  else
++#endif
++  {
++    SDL_Flip(screen);
++  }
+ }
+ class RequestPtrCompare
+@@ -644,36 +767,47 @@
+ {
+   // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it?
+-  // create surface to hold screenshot
+-  #if SDL_BYTEORDER == SDL_BIG_ENDIAN
+-  SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
+-  #else
+-  SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
+-  #endif
+-  if (!shot_surf) {
+-    log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
+-    return;
 -  }
++  SDL_Surface *shot_surf;
++#ifdef HAVE_OPENGL
++  if(config->use_opengl)
++  {
++    // create surface to hold screenshot
++    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
++    shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
++    #else
++    shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
++    #endif
++    if (!shot_surf) {
++      log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
++      return;
++    }
+-  // read pixels into array
+-  char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
+-  if (!pixels) {
+-    log_warning << "Could not allocate memory to store screenshot" << std::endl;
+-    SDL_FreeSurface(shot_surf);
+-    return;
+-  }
+-  glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
++    // read pixels into array
++    char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
++    if (!pixels) {
++      log_warning << "Could not allocate memory to store screenshot" << std::endl;
++      SDL_FreeSurface(shot_surf);
++      return;
++    }
++    glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
+-  // copy array line-by-line
+-  for (int i = 0; i < SCREEN_HEIGHT; i++) {
+-    char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
+-    char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
+-    memcpy(dst, src, 3 * SCREEN_WIDTH);
++    // copy array line-by-line
++    for (int i = 0; i < SCREEN_HEIGHT; i++) {
++      char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
++      char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
++      memcpy(dst, src, 3 * SCREEN_WIDTH);
++    }
++
++    // free array
++    delete[](pixels);
+   }
++  else
++#endif
++  {
++    shot_surf = SDL_GetVideoSurface();
++    shot_surf->refcount++;
++  }
+-  // free array
+-  delete[](pixels);
 -
--  assert_gl("drawing");
--
--  SDL_GL_SwapBuffers();
-+  SDL_Flip(screen);
+   // save screenshot
+   static const std::string writeDir = PHYSFS_getWriteDir();
+   static const std::string dirSep = PHYSFS_getDirSeparator();
+Index: src/video/texture_manager.hpp
+===================================================================
+--- src/video/texture_manager.hpp      (revision 5071)
++++ src/video/texture_manager.hpp      (working copy)
+@@ -20,7 +20,7 @@
+ #ifndef __IMAGE_TEXTURE_MANAGER_HPP__
+ #define __IMAGE_TEXTURE_MANAGER_HPP__
+-#include <GL/gl.h>
++#include "glutil.hpp"
+ #include <string>
+ #include <vector>
+ #include <map>
+Index: src/video/texture.cpp
+===================================================================
+--- src/video/texture.cpp      (revision 5071)
++++ src/video/texture.cpp      (working copy)
+@@ -20,90 +20,134 @@
+ #include <config.h>
+ #include "texture.hpp"
++#include "gameconfig.hpp"
++#include "glutil.hpp"
+-#include <GL/gl.h>
+ #include <assert.h>
+-#include "glutil.hpp"
++#include <stdexcept>
+ static inline bool is_power_of_2(int v)
+ {
+   return (v & (v-1)) == 0;
+ }
++#ifdef HAVE_OPENGL
+ Texture::Texture(unsigned int w, unsigned int h, GLenum glformat)
++#else
++Texture::Texture(unsigned int w, unsigned int h, GLenum)
++#endif
+ {
+   assert(is_power_of_2(w));
+   assert(is_power_of_2(h));
++#ifdef HAVE_OPENGL
++  use_opengl = config->use_opengl;
+-  this->width = w;
+-  this->height = h;
++  if(use_opengl)
++  {
++    surface.opengl.width = w;
++    surface.opengl.height = h;
+-  assert_gl("before creating texture");
+-  glGenTextures(1, &handle);
++    assert_gl("before creating texture");
++    glGenTextures(1, &surface.opengl.handle);
+-  try {
+-    glBindTexture(GL_TEXTURE_2D, handle);
++    try {
++      glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
+-    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
+-                 GL_UNSIGNED_BYTE, 0);
++      glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
++                   surface.opengl.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+-    set_texture_params();
+-  } catch(...) {
+-    glDeleteTextures(1, &handle);
+-    throw;
++      set_texture_params();
++    } catch(...) {
++      glDeleteTextures(1, &surface.opengl.handle);
++      throw;
++    }
+   }
++  else
++#endif
++  {
++    surface.sdl = 0;
++  }
+ }
++#ifdef HAVE_OPENGL
+ Texture::Texture(SDL_Surface* image, GLenum glformat)
++#else
++Texture::Texture(SDL_Surface* image, GLenum)
++#endif
+ {
+   const SDL_PixelFormat* format = image->format;
+   if(!is_power_of_2(image->w) || !is_power_of_2(image->h))
+-    throw std::runtime_error("image has no power of 2 size");
++    throw std::runtime_error("image does not have power of 2 size");
+   if(format->BitsPerPixel != 24 && format->BitsPerPixel != 32)
+-    throw std::runtime_error("image has no 24 or 32 bit color depth");
++    throw std::runtime_error("image does not have 24 or 32 bit color depth");
++#ifdef HAVE_OPENGL
++  use_opengl = config->use_opengl;
+-  this->width = image->w;
+-  this->height = image->h;
++  if(use_opengl)
++  {
++    surface.opengl.width = image->w;
++    surface.opengl.height = image->h;
+-  assert_gl("before creating texture");
+-  glGenTextures(1, &handle);
++    assert_gl("before creating texture");
++    glGenTextures(1, &surface.opengl.handle);
+-  try {
+-    GLenum sdl_format;
+-    if(format->BytesPerPixel == 3)
+-      sdl_format = GL_RGB;
+-    else if(format->BytesPerPixel == 4)
+-      sdl_format = GL_RGBA;
+-    else
+-      assert(false);
++    try {
++      GLenum sdl_format;
++      if(format->BytesPerPixel == 3)
++        sdl_format = GL_RGB;
++      else if(format->BytesPerPixel == 4)
++        sdl_format = GL_RGBA;
++      else
++        assert(false);
+-    glBindTexture(GL_TEXTURE_2D, handle);
+-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+-    glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
+-    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
+-            GL_UNSIGNED_BYTE, image->pixels);
++      glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
++      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
++      glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
++      glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
++              surface.opengl.height, 0, sdl_format,
++              GL_UNSIGNED_BYTE, image->pixels);
+-    assert_gl("creating texture");
++      assert_gl("creating texture");
+-    set_texture_params();
+-  } catch(...) {
+-    glDeleteTextures(1, &handle);
+-    throw;
++      set_texture_params();
++    } catch(...) {
++      glDeleteTextures(1, &surface.opengl.handle);
++      throw;
++    }
+   }
++  else
++#endif
++  {
++    surface.sdl = SDL_DisplayFormatAlpha(image);
++  }
+ }
+ Texture::~Texture()
+ {
+-  glDeleteTextures(1, &handle);
++#ifdef HAVE_OPENGL
++  if(use_opengl)
++  {
++    glDeleteTextures(1, &surface.opengl.handle);
++  }
++  else
++#endif
++  {
++    SDL_FreeSurface(surface.sdl);
++  }
  }
  
  void
-@@ -471,9 +442,5 @@
- DrawingContext::set_target(Target target)
+ Texture::set_texture_params()
  {
-   this->target = target;
--  if(target == LIGHTMAP)
--    requests = &lightmap_requests;
--  else
--    requests = &drawing_requests;
+-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
++#ifdef HAVE_OPENGL
++  if(use_opengl)
++  {
++    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
++    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+-  assert_gl("set texture params");
++    assert_gl("set texture params");
++  }
++#endif
  }
+Index: src/video/drawing_context.hpp
+===================================================================
+--- src/video/drawing_context.hpp      (revision 5071)
++++ src/video/drawing_context.hpp      (working copy)
+@@ -25,9 +25,9 @@
  
-diff -aur supertux/src/video/drawing_context.hpp supertux-nogl/src/video/drawing_context.hpp
---- supertux/src/video/drawing_context.hpp     2006-07-03 02:00:48.000000000 +0200
-+++ supertux-nogl/src/video/drawing_context.hpp        2006-07-03 02:00:29.000000000 +0200
-@@ -24,7 +24,6 @@
- #include <string>
  #include <stdint.h>
  
 -#include <GL/gl.h>
- #include <SDL.h>
- #include <stdint.h>
- #include <memory>
-@@ -35,8 +34,9 @@
- #include "font.hpp"
- #include "color.hpp"
+ #include <SDL_video.h>
  
 +#include "glutil.hpp"
+ #include "obstack/obstack.h"
+ #include "math/vector.hpp"
+ #include "math/rect.hpp"
+Index: src/video/glutil.hpp
+===================================================================
+--- src/video/glutil.hpp       (revision 5071)
++++ src/video/glutil.hpp       (working copy)
+@@ -19,9 +19,14 @@
+ #ifndef __GLUTIL_HPP__
+ #define __GLUTIL_HPP__
++#include <config.h>
++
++#ifdef HAVE_OPENGL
 +
- class Surface;
--class Texture;
- // some constants for predefined layer values
- enum {
-@@ -214,16 +214,12 @@
-   void draw_filled_rect(DrawingRequest& request);
-   
-   DrawingRequests drawing_requests;
--  DrawingRequests lightmap_requests;
-   DrawingRequests* requests;
-   SDL_Surface* screen;
-   Target target;
-   std::vector<Target> target_stack;
--  Texture* lightmap;
--  int lightmap_width, lightmap_height;
--  float lightmap_uv_right, lightmap_uv_bottom;
- };
- #endif
-diff -aur supertux/src/video/glutil.hpp supertux-nogl/src/video/glutil.hpp
---- supertux/src/video/glutil.hpp      2006-07-03 02:00:48.000000000 +0200
-+++ supertux-nogl/src/video/glutil.hpp 2006-07-03 02:00:29.000000000 +0200
-@@ -21,58 +21,12 @@
  #include <sstream>
  #include <stdexcept>
--#include <GL/gl.h>
+ #include <GL/gl.h>
++#include <GL/glext.h>
  
--static inline void check_gl_error(const char* message)
--{
--#ifdef DEBUG
--  GLenum error = glGetError();
--  if(error != GL_NO_ERROR) {
--    std::ostringstream msg;
--    msg << "OpenGLError while '" << message << "': ";
--    switch(error) {
--      case GL_INVALID_ENUM:
--        msg << "INVALID_ENUM: An unacceptable value is specified for an "
--               "enumerated argument.";
--        break;
--      case GL_INVALID_VALUE:
--        msg << "INVALID_VALUE: A numeric argument is out of range.";
--        break;
--      case GL_INVALID_OPERATION:
--        msg << "INVALID_OPERATION: The specified operation is not allowed "
--               "in the current state.";
--        break;
--      case GL_STACK_OVERFLOW:
--        msg << "STACK_OVERFLOW: This command would cause a stack overflow.";
--        break;
--      case GL_STACK_UNDERFLOW:
--        msg << "STACK_UNDERFLOW: This command would cause a stack underflow.";
--        break;
--      case GL_OUT_OF_MEMORY:
--        msg << "OUT_OF_MEMORY: There is not enough memory left to execute the "
--               "command.";
--        break;
--#ifdef GL_TABLE_TOO_LARGE
--      case GL_TABLE_TOO_LARGE:
--        msg << "TABLE_TOO_LARGE: table is too large";
--        break;
--#endif                        
--      default:
--        msg << "Unknown error (code " << error << ")";
--    }
--        
--    throw std::runtime_error(msg.str());
--  }
--#endif
--}
+ static inline void check_gl_error(const char* message)
+ {
+@@ -77,4 +82,15 @@
+ #endif
+ }
++#else
++
 +#define GLenum int
 +#define GLint int
 +#define GL_SRC_ALPHA 0
 +#define GL_ONE_MINUS_SRC_ALPHA 1
 +#define GL_RGBA 2
 +#define GL_ONE 3
--static inline void assert_gl(const char* message)
--{
--#ifdef DEBUG
--  check_gl_error(message);
--#else
--  (void) message;
++
  #endif
--}
--
--#endif
-diff -aur supertux/src/video/surface.cpp supertux-nogl/src/video/surface.cpp
---- supertux/src/video/surface.cpp     2006-07-03 02:00:48.000000000 +0200
-+++ supertux-nogl/src/video/surface.cpp        2006-07-03 02:00:29.000000000 +0200
-@@ -28,6 +28,7 @@
++
++#endif
+Index: src/video/texture.hpp
+===================================================================
+--- src/video/texture.hpp      (revision 5071)
++++ src/video/texture.hpp      (working copy)
+@@ -20,9 +20,15 @@
+ #ifndef __TEXTURE_HPP__
+ #define __TEXTURE_HPP__
++#include <config.h>
++
++#include <assert.h>
++
+ #include <SDL.h>
+-#include <GL/gl.h>
++#include "gameconfig.hpp"
++#include "glutil.hpp"
++
+ /**
+  * This class is a wrapper around a texture handle. It stores the texture width
+  * and height and provides convenience functions for uploading SDL_Surfaces
+@@ -31,29 +37,82 @@
+ class Texture
+ {
+ protected:
+-  friend class TextureManager;
+-  GLuint handle;
+-  unsigned int width;
+-  unsigned int height;
++#ifdef HAVE_OPENGL
++  bool use_opengl;
++  union
++  {
++    struct
++    {
++      GLuint handle;
++      unsigned int width;
++      unsigned int height;
++    } opengl;
++#else
++  struct
++  {
++#endif
++    SDL_Surface *sdl;
++  } surface;
+ public:
+   Texture(unsigned int width, unsigned int height, GLenum glformat);
+-  Texture(SDL_Surface* surface, GLenum glformat);
++  Texture(SDL_Surface* sdlsurface, GLenum glformat);
+   virtual ~Texture();
+-  GLuint get_handle() const
++#ifdef HAVE_OPENGL
++  const GLuint &get_handle() const {
++    assert(use_opengl);
++    return surface.opengl.handle;
++  }
++
++  void set_handle(GLuint handle) {
++    assert(use_opengl);
++    surface.opengl.handle = handle;
++  }
++#endif
++
++  SDL_Surface *get_surface() const
+   {
+-    return handle;
++#ifdef HAVE_OPENGL
++    assert(!use_opengl);
++#endif
++    return surface.sdl;
+   }
++  void set_surface(SDL_Surface *sdlsurface)
++  {
++#ifdef HAVE_OPENGL
++    assert(!use_opengl);
++#endif
++    surface.sdl = sdlsurface;
++  }
++
+   unsigned int get_width() const
+   {
+-    return width;
++#ifdef HAVE_OPENGL
++    if(use_opengl)
++    {
++      return surface.opengl.width;
++    }
++    else
++#endif
++    {
++      return surface.sdl->w;
++    }
+   }
+   unsigned int get_height() const
+   {
+-    return height;
++#ifdef HAVE_OPENGL
++    if(use_opengl)
++    {
++      return surface.opengl.height;
++    }
++    else
++#endif
++    {
++      return surface.sdl->h;
++    }
+   }
  
+ private:
+Index: src/video/surface.cpp
+===================================================================
+--- src/video/surface.cpp      (revision 5071)
++++ src/video/surface.cpp      (working copy)
+@@ -29,6 +29,7 @@
  #include <SDL.h>
  #include <SDL_image.h>
-+#include <SDL_rotozoom.h>
  
++#include "main.hpp"
  #include "gameconfig.hpp"
  #include "physfs/physfs_sdl.hpp"
-@@ -41,13 +42,13 @@
+ #include "video/surface.hpp"
+@@ -41,13 +42,32 @@
  {
    texture = texture_manager->get(file);
    texture->ref();
@@ -591,16 +854,35 @@ diff -aur supertux/src/video/surface.cpp supertux-nogl/src/video/surface.cpp
  
 -  width = texture->get_image_width();
 -  height = texture->get_image_height();
-+  offsetx = 0;
-+  offsety = 0;
-+  width = static_cast<int>(texture->get_image_width());
-+  height = static_cast<int>(texture->get_image_height());
++#ifdef HAVE_OPENGL
++  use_opengl = config->use_opengl;
++
++  if(use_opengl)
++  {
++    surface.opengl.uv_left = 0;
++    surface.opengl.uv_top = 0;
++    surface.opengl.uv_right = texture->get_uv_right();
++    surface.opengl.uv_bottom = texture->get_uv_bottom();
++
++    surface.opengl.width = texture->get_image_width();
++    surface.opengl.height = texture->get_image_height();
++  }
++  else
++#endif
++  {
++    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
 +
-+  flipx = false;
++    surface.sdl.offsetx = 0;
++    surface.sdl.offsety = 0;
++    surface.sdl.width = static_cast<int>(texture->get_image_width());
++    surface.sdl.height = static_cast<int>(texture->get_image_height());
++
++    surface.sdl.flipx = false;
++  }
  }
  
  Surface::Surface(const std::string& file, int x, int y, int w, int h)
-@@ -55,15 +56,12 @@
+@@ -55,15 +75,33 @@
    texture = texture_manager->get(file);
    texture->ref();
  
@@ -610,17 +892,39 @@ diff -aur supertux/src/video/surface.cpp supertux-nogl/src/video/surface.cpp
 -  uv_top = static_cast<float>(y) / tex_h;
 -  uv_right = static_cast<float>(x+w) / tex_w;
 -  uv_bottom = static_cast<float>(y+h) / tex_h;
--
-+  offsetx = x;
-+  offsety = y;
-   width = w;
-   height = h;
++#ifdef HAVE_OPENGL
++  use_opengl = config->use_opengl;
+-  width = w;
+-  height = h;
++  if(use_opengl)
++  {
++    float tex_w = static_cast<float> (texture->get_width());
++    float tex_h = static_cast<float> (texture->get_height());
++    surface.opengl.uv_left = static_cast<float>(x) / tex_w;
++    surface.opengl.uv_top = static_cast<float>(y) / tex_h;
++    surface.opengl.uv_right = static_cast<float>(x+w) / tex_w;
++    surface.opengl.uv_bottom = static_cast<float>(y+h) / tex_h;
++
++    surface.opengl.width = w;
++    surface.opengl.height = h;
++  }
++  else
++#endif
++  {
++    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
 +
-+  flipx = false;
++    surface.sdl.offsetx = x;
++    surface.sdl.offsety = y;
++    surface.sdl.width = w;
++    surface.sdl.height = h;
++
++    surface.sdl.flipx = false;
++  }
  }
  
  Surface::Surface(const Surface& other)
-@@ -71,12 +69,12 @@
+@@ -71,12 +109,30 @@
    texture = other.texture;
    texture->ref();
  
@@ -628,16 +932,36 @@ diff -aur supertux/src/video/surface.cpp supertux-nogl/src/video/surface.cpp
 -  uv_top = other.uv_top;
 -  uv_right = other.uv_right;
 -  uv_bottom = other.uv_bottom;
-+  offsetx = other.offsetx;
-+  offsety = other.offsety;
-   width = other.width;
-   height = other.height;
+-  width = other.width;
+-  height = other.height;
++#ifdef HAVE_OPENGL
++  use_opengl = config->use_opengl;
++
++  if(use_opengl)
++  {
++    surface.opengl.uv_left = other.surface.opengl.uv_left;
++    surface.opengl.uv_top = other.surface.opengl.uv_top;
++    surface.opengl.uv_right = other.surface.opengl.uv_right;
++    surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
++    surface.opengl.width = other.surface.opengl.width;
++    surface.opengl.height = other.surface.opengl.height;
++  }
++  else
++#endif
++  {
++    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
 +
-+  flipx = other.flipx;
++    surface.sdl.offsetx = other.surface.sdl.offsetx;
++    surface.sdl.offsety = other.surface.sdl.offsety;
++    surface.sdl.width = other.surface.sdl.width;
++    surface.sdl.height = other.surface.sdl.height;
++
++    surface.sdl.flipx = other.surface.sdl.flipx;
++  }
  }
  
  const Surface&
-@@ -86,52 +84,33 @@
+@@ -86,148 +142,584 @@
    texture->unref();
    texture = other.texture;
  
@@ -645,12 +969,32 @@ diff -aur supertux/src/video/surface.cpp supertux-nogl/src/video/surface.cpp
 -  uv_top = other.uv_top;
 -  uv_right = other.uv_right;
 -  uv_bottom = other.uv_bottom;
-+  offsetx = other.offsetx;
-+  offsety = other.offsety;
-   width = other.width;
-   height = other.height;
+-  width = other.width;
+-  height = other.height;
++#ifdef HAVE_OPENGL
++  use_opengl = config->use_opengl;
  
-+  flipx = other.flipx;
++  if(use_opengl)
++  {
++    surface.opengl.uv_left = other.surface.opengl.uv_left;
++    surface.opengl.uv_top = other.surface.opengl.uv_top;
++    surface.opengl.uv_right = other.surface.opengl.uv_right;
++    surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
++    surface.opengl.width = other.surface.opengl.width;
++    surface.opengl.height = other.surface.opengl.height;
++  }
++  else
++#endif
++  {
++    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
++
++    surface.sdl.offsetx = other.surface.sdl.offsetx;
++    surface.sdl.offsety = other.surface.sdl.offsety;
++    surface.sdl.width = other.surface.sdl.width;
++    surface.sdl.height = other.surface.sdl.height;
++
++    surface.sdl.flipx = other.surface.sdl.flipx;
++  }
 +
    return *this;
  }
@@ -659,9 +1003,11 @@ diff -aur supertux/src/video/surface.cpp supertux-nogl/src/video/surface.cpp
  {
    texture->unref();
 +
-+  for (std::list<TransformedSurface*>::iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
-+    SDL_FreeSurface((*i)->surface);
-+    delete (*i);
++#ifdef HAVE_OPENGL
++  if(!use_opengl)
++#endif
++  {
++    std::for_each(transforms, transforms + NUM_EFFECTS, SDL_FreeSurface);
 +  }
  }
  
@@ -669,363 +1015,637 @@ diff -aur supertux/src/video/surface.cpp supertux-nogl/src/video/surface.cpp
  Surface::hflip()
  {
 -  std::swap(uv_left, uv_right);
-+  flipx = !flipx;
++#ifdef HAVE_OPENGL
++  if(use_opengl)
++  {
++    std::swap(surface.opengl.uv_left, surface.opengl.uv_right);
++  }
++  else
++#endif
++  {
++    surface.sdl.flipx = !surface.sdl.flipx;
++  }
  }
  
 -static inline void intern_draw(float left, float top, float right, float bottom,                               float uv_left, float uv_top,
 -                               float uv_right, float uv_bottom,
 -                               DrawingEffect effect)
--{
++#ifdef HAVE_OPENGL
++namespace
+ {
 -  if(effect & HORIZONTAL_FLIP)
 -    std::swap(uv_left, uv_right);
 -  if(effect & VERTICAL_FLIP) {
 -    std::swap(uv_top, uv_bottom);
 -  }
--  
++  inline void intern_draw(float left, float top, float right, float bottom,                               float uv_left, float uv_top,
++                                 float uv_right, float uv_bottom,
++                                 DrawingEffect effect)
++  {
++    if(effect & HORIZONTAL_FLIP)
++      std::swap(uv_left, uv_right);
++    if(effect & VERTICAL_FLIP) {
++      std::swap(uv_top, uv_bottom);
++    }
 -  glBegin(GL_QUADS);
 -  glTexCoord2f(uv_left, uv_top);
 -  glVertex2f(left, top);
--  
++    glBegin(GL_QUADS);
++    glTexCoord2f(uv_left, uv_top);
++    glVertex2f(left, top);
 -  glTexCoord2f(uv_right, uv_top);
 -  glVertex2f(right, top);
--
++    glTexCoord2f(uv_right, uv_top);
++    glVertex2f(right, top);
 -  glTexCoord2f(uv_right, uv_bottom);
 -  glVertex2f(right, bottom);
--
++    glTexCoord2f(uv_right, uv_bottom);
++    glVertex2f(right, bottom);
 -  glTexCoord2f(uv_left, uv_bottom);
 -  glVertex2f(left, bottom);
 -  glEnd();
 -}
 -
-+/*
- static inline void intern_draw2(float left, float top, float right, float bottom,
-                                 float uv_left, float uv_top,
-                                 float uv_right, float uv_bottom,
-@@ -182,51 +161,77 @@
-   glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
-   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-+*/
- void
--Surface::draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const
-+Surface::draw(float x, float y, float alpha, float, const Color&, const Blend&, DrawingEffect effect) const
- {
--  glColor4f(1.0f, 1.0f, 1.0f, alpha);
--  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
--
--  intern_draw2(x, y,
--               x + width, y + height,
--               uv_left, uv_top, uv_right, uv_bottom, 
--               angle,
--               color,
--               blend, 
--               effect);
-+  draw_part(0, 0, x, y, width, height, alpha, effect);
- }
- void
- Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
- {
--  glColor4f(1.0f, 1.0f, 1.0f, alpha);
--  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
--
--  intern_draw(x, y,
--              x + width, y + height,
--              uv_left, uv_top, uv_right, uv_bottom, effect);
-+  draw_part(0, 0, x, y, width, height, alpha, effect);
- }
+-static inline void intern_draw2(float left, float top, float right, float bottom,
+-                                float uv_left, float uv_top,
+-                                float uv_right, float uv_bottom,
+-                                float angle, float alpha,
+-                                const Color& color,
+-                                const Blend& blend,
+-                                DrawingEffect effect)
+-{
+-  if(effect & HORIZONTAL_FLIP)
+-    std::swap(uv_left, uv_right);
+-  if(effect & VERTICAL_FLIP) {
+-    std::swap(uv_top, uv_bottom);
++    glTexCoord2f(uv_left, uv_bottom);
++    glVertex2f(left, bottom);
++    glEnd();
+   }
  
- void
- Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
--                   float width, float height, float alpha,
-+                   float width, float height, float,
-                    DrawingEffect effect) const
- {
--  float uv_width = uv_right - uv_left;
--  float uv_height = uv_bottom - uv_top;
--  
--  float uv_left = this->uv_left + (uv_width * src_x) / this->width;
--  float uv_top = this->uv_top + (uv_height * src_y) / this->height;
--  float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
--  float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
--  
--  glColor4f(1.0f, 1.0f, 1.0f, alpha);
--  glBindTexture(GL_TEXTURE_2D, texture->get_handle());  
--  
--  intern_draw(dst_x, dst_y,
--              dst_x + width, dst_y + height,
--              uv_left, uv_top, uv_right, uv_bottom, effect);
-+  //FIXME: support parameter "alpha"
-+  SDL_Surface* surface = texture->getSurface();
-+
-+  // get and check SDL_Surface
-+  if (surface == 0) {
-+    std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
-+    return;
-+  }   
-+
-+  SDL_Surface* transformedSurface = surface;
-+
-+  if (flipx) effect = HORIZONTAL_FLIP;
-+
-+  if (effect != NO_EFFECT) {
-+    transformedSurface = 0;
-+
-+    // check if we have this effect buffered
-+    for (std::list<TransformedSurface*>::const_iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
-+      if ((*i)->effect == effect) transformedSurface = (*i)->surface;
-+    }
-+
-+    // if not: transform and buffer
-+    if (!transformedSurface) {
-+      if (effect == HORIZONTAL_FLIP) transformedSurface = zoomSurface(surface, -1, 1, 0);
-+      if (effect == VERTICAL_FLIP) transformedSurface = zoomSurface(surface, 1, -1, 0);
-+      if (transformedSurface == 0) {
-+        std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
-+        return;
-+      }       
-+      TransformedSurface* su = new TransformedSurface();
-+      su->surface = transformedSurface;
-+      su->effect = effect;
-+
-+      transformedSurfaces.push_front(su);
+-  float center_x = (left + right) / 2;
+-  float center_y = (top + bottom) / 2;
++  inline void intern_draw2(float left, float top, float right, float bottom,
++                                  float uv_left, float uv_top,
++                                  float uv_right, float uv_bottom,
++                                  float angle, float alpha,
++                                  const Color& color,
++                                  const Blend& blend,
++                                  DrawingEffect effect)
++  {
++    if(effect & HORIZONTAL_FLIP)
++      std::swap(uv_left, uv_right);
++    if(effect & VERTICAL_FLIP) {
++      std::swap(uv_top, uv_bottom);
 +    }
-+  }
-+
-+  int ox = offsetx; if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(surface->w) - (ox+static_cast<int>(width));
-+  int oy = offsety; if (effect == VERTICAL_FLIP) oy = static_cast<int>(surface->h) - (oy+static_cast<int>(height));
-+  // draw surface to screen
-+  SDL_Surface* screen = SDL_GetVideoSurface();
-+
-+  SDL_Rect srcRect;
-+  srcRect.x = static_cast<int>(ox+src_x);
-+  srcRect.y = static_cast<int>(oy+src_y);
-+  srcRect.w = static_cast<int>(width);
-+  srcRect.h = static_cast<int>(height);
-+
-+  SDL_Rect dstRect;
-+  dstRect.x = static_cast<int>(dst_x);
-+  dstRect.y = static_cast<int>(dst_y);
-+
-+  SDL_BlitSurface(transformedSurface, &srcRect, screen, &dstRect);
- }
-diff -aur supertux/src/video/surface.hpp supertux-nogl/src/video/surface.hpp
---- supertux/src/video/surface.hpp     2006-07-03 02:00:48.000000000 +0200
-+++ supertux-nogl/src/video/surface.hpp        2006-07-03 02:00:29.000000000 +0200
-@@ -20,7 +20,9 @@
- #ifndef __SURFACE_HPP__
- #define __SURFACE_HPP__
-+#include <SDL_image.h>
- #include <string>
-+#include <list>
- class Color;
- class Blend;
-@@ -37,6 +39,15 @@
- };
- /**
-+ * Helper class to buffer a pre-transformed SDL_Surface
-+ */
-+class TransformedSurface {
-+    public:
-+       SDL_Surface* surface;
-+       DrawingEffect effect;
-+};
-+
-+/**
-  * A rectangular image.
-  * The class basically holds a reference to a texture with additional UV
-  * coordinates that specify a rectangular area on this texture
-@@ -48,19 +59,26 @@
-   friend class Font;
-   ImageTexture* texture;
--  float uv_left;
--  float uv_top;
--  float uv_right;
--  float uv_bottom;
-+  bool flipx;
-+  /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
-   void draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const;
-+
-+  /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
-   void draw(float x, float y, float alpha, DrawingEffect effect) const;
-+
-+  /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
-   void draw_part(float src_x, float src_y, float dst_x, float dst_y,
-                  float width, float height,
-                  float alpha, DrawingEffect effect) const;
--  float width;
--  float height;
-+  int offsetx; /**< Region in ::surface to be used for blitting */
-+  int offsety; /**< Region in ::surface to be used for blitting */
-+  int width;   /**< Region in ::surface to be used for blitting */
-+  int height;  /**< Region in ::surface to be used for blitting */
-+
-+  mutable std::list<TransformedSurface*> transformedSurfaces; /**< Cache for pre-transformed surfaces */
-+
- public:
-   Surface(const std::string& file);
-   Surface(const std::string& file, int x, int y, int w, int h);
-diff -aur supertux/src/video/texture.cpp supertux-nogl/src/video/texture.cpp
---- supertux/src/video/texture.cpp     2006-07-03 02:00:48.000000000 +0200
-+++ supertux-nogl/src/video/texture.cpp        2006-07-03 02:00:29.000000000 +0200
-@@ -21,7 +21,6 @@
- #include "texture.hpp"
--#include <GL/gl.h>
- #include <assert.h>
- #include "glutil.hpp"
-@@ -30,81 +29,37 @@
-   return (v & (v-1)) == 0;
- }
--Texture::Texture(unsigned int w, unsigned int h, GLenum glformat)
-+Texture::Texture(unsigned int w, unsigned int h, GLenum)
- {
-   assert(is_power_of_2(w));
-   assert(is_power_of_2(h));
-   this->width = w;
-   this->height = h;
--  
--  assert_gl("before creating texture");
--  glGenTextures(1, &handle);
--  
--  try {
--    glBindTexture(GL_TEXTURE_2D, handle);
--
--    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
--                 GL_UNSIGNED_BYTE, 0);
--
--    set_texture_params();
--  } catch(...) {
--    glDeleteTextures(1, &handle);
--    throw;
--  }
-+
-+  surface = 0;
- }
--Texture::Texture(SDL_Surface* image, GLenum glformat)
-+Texture::Texture(SDL_Surface* image, GLenum)
- {
-   const SDL_PixelFormat* format = image->format;
-   if(!is_power_of_2(image->w) || !is_power_of_2(image->h))
-     throw std::runtime_error("image has no power of 2 size");
-   if(format->BitsPerPixel != 24 && format->BitsPerPixel != 32)
-     throw std::runtime_error("image has no 24 or 32 bit color depth");
--  
-+
-   this->width = image->w;
-   this->height = image->h;
  
--  assert_gl("before creating texture");
--  glGenTextures(1, &handle);
--  
--  try {
--    GLenum sdl_format;
--    if(format->BytesPerPixel == 3)
--      sdl_format = GL_RGB;
--    else if(format->BytesPerPixel == 4)
--      sdl_format = GL_RGBA;
--    else
--      assert(false);
--
--    glBindTexture(GL_TEXTURE_2D, handle);
--    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
--    glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
--    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
--            GL_UNSIGNED_BYTE, image->pixels);
--
--    assert_gl("creating texture");
--
--    set_texture_params();    
--  } catch(...) {
--    glDeleteTextures(1, &handle);
--    throw;
--  }
-+  surface = SDL_DisplayFormatAlpha(image);
- }
+-  float sa = sinf(angle/180.0f*M_PI);
+-  float ca = cosf(angle/180.0f*M_PI);
++    float center_x = (left + right) / 2;
++    float center_y = (top + bottom) / 2;
  
- Texture::~Texture()
- {
--  glDeleteTextures(1, &handle);
+-  left  -= center_x;
+-  right -= center_x;
++    float sa = sinf(angle/180.0f*M_PI);
++    float ca = cosf(angle/180.0f*M_PI);
+-  top    -= center_y;
+-  bottom -= center_y;
++    left  -= center_x;
++    right -= center_x;
+-  glBlendFunc(blend.sfactor, blend.dfactor);
+-  glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
+-  glBegin(GL_QUADS);
+-  glTexCoord2f(uv_left, uv_top);
+-  glVertex2f(left*ca - top*sa + center_x,
+-             left*sa + top*ca + center_y);
++    top    -= center_y;
++    bottom -= center_y;
+-  glTexCoord2f(uv_right, uv_top);
+-  glVertex2f(right*ca - top*sa + center_x,
+-             right*sa + top*ca + center_y);
++    glBlendFunc(blend.sfactor, blend.dfactor);
++    glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
++    glBegin(GL_QUADS);
++    glTexCoord2f(uv_left, uv_top);
++    glVertex2f(left*ca - top*sa + center_x,
++               left*sa + top*ca + center_y);
+-  glTexCoord2f(uv_right, uv_bottom);
+-  glVertex2f(right*ca - bottom*sa + center_x,
+-             right*sa + bottom*ca + center_y);
++    glTexCoord2f(uv_right, uv_top);
++    glVertex2f(right*ca - top*sa + center_x,
++               right*sa + top*ca + center_y);
+-  glTexCoord2f(uv_left, uv_bottom);
+-  glVertex2f(left*ca - bottom*sa + center_x,
+-             left*sa + bottom*ca + center_y);
+-  glEnd();
++    glTexCoord2f(uv_right, uv_bottom);
++    glVertex2f(right*ca - bottom*sa + center_x,
++               right*sa + bottom*ca + center_y);
+-  // FIXME: find a better way to restore the blend mode
+-  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
++    glTexCoord2f(uv_left, uv_bottom);
++    glVertex2f(left*ca - bottom*sa + center_x,
++               left*sa + bottom*ca + center_y);
++    glEnd();
++
++    // FIXME: find a better way to restore the blend mode
++    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
++    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
++  }
  }
++#endif
  
  void
- Texture::set_texture_params()
+-Surface::draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const
++Surface::draw(float x, float y, float alpha,
++#ifdef HAVE_OPENGL
++              float angle, const Color& color, const Blend& blend,
++#else
++              float, const Color&, const Blend&,
++#endif
++              DrawingEffect effect) const
  {
--  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
--  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
--  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
--  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+-  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
 -
--  assert_gl("set texture params");
+-  intern_draw2(x, y,
+-               x + width, y + height,
+-               uv_left, uv_top, uv_right, uv_bottom,
+-               angle,
+-               alpha,
+-               color,
+-               blend,
+-               effect);
++#ifdef HAVE_OPENGL
++  if(use_opengl)
++  {
++    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
++    intern_draw2(x, y,
++                 x + surface.opengl.width, y + surface.opengl.height,
++                 surface.opengl.uv_left, surface.opengl.uv_top,
++                 surface.opengl.uv_right, surface.opengl.uv_bottom,
++                 angle,
++                 alpha,
++                 color,
++                 blend,
++                 effect);
++  }
++  else
++#endif
++  {
++    draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
++  }
  }
  
-diff -aur supertux/src/video/texture.hpp supertux-nogl/src/video/texture.hpp
---- supertux/src/video/texture.hpp     2006-07-03 02:00:48.000000000 +0200
-+++ supertux-nogl/src/video/texture.hpp        2006-07-03 02:00:29.000000000 +0200
-@@ -21,7 +21,7 @@
- #define __TEXTURE_HPP__
+ void
+ Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
+ {
+-  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
++#ifdef HAVE_OPENGL
++  if(use_opengl)
++  {
++    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
++    glColor4f(1, 1, 1, alpha);
++    intern_draw(x, y,
++                x + surface.opengl.width, y + surface.opengl.height,
++                surface.opengl.uv_left, surface.opengl.uv_top,
++                surface.opengl.uv_right, surface.opengl.uv_bottom, effect);
++    glColor4f(1, 1, 1, 1);
++  }
++  else
++#endif
++  {
++    draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
++  }
++}
  
- #include <SDL.h>
--#include <GL/gl.h>
-+#include "glutil.hpp"
+-  glColor4f(1, 1, 1, alpha);
+-  intern_draw(x, y,
+-              x + width, y + height,
+-              uv_left, uv_top, uv_right, uv_bottom, effect);
+-  glColor4f(1, 1, 1, 1);
++namespace
++{
++#define BILINEAR
++
++#ifdef NAIVE
++  SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
++  {
++    if(numerator == denominator)
++    {
++      src->refcount++;
++      return src;
++    }
++    else
++    {
++      SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
++      int bpp = dst->format->BytesPerPixel;
++      for(int y = 0;y < dst->h;y++) {
++        for(int x = 0;x < dst->w;x++) {
++          Uint8 *srcpixel = (Uint8 *) src->pixels + (y * denominator / numerator) * src->pitch + (x * denominator / numerator) * bpp;
++          Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
++          switch(bpp) {
++            case 4:
++              dstpixel[3] = srcpixel[3];
++            case 3:
++              dstpixel[2] = srcpixel[2];
++            case 2:
++              dstpixel[1] = srcpixel[1];
++            case 1:
++              dstpixel[0] = srcpixel[0];
++          }
++        }
++      }
++      return dst;
++    }
++  }
++#endif
++
++#ifdef BILINEAR
++  void getpixel(SDL_Surface *src, int srcx, int srcy, Uint8 color[4])
++  {
++    int bpp = src->format->BytesPerPixel;
++    Uint8 *srcpixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp;
++    Uint32 mapped = 0;
++    switch(bpp) {
++      case 1:
++        mapped = *srcpixel;
++        break;
++      case 2:
++        mapped = *(Uint16 *)srcpixel;
++        break;
++      case 3:
++#if SDL_BYTEORDER == SDL_BIG_ENDIAN
++        mapped |= srcpixel[0] << 16;
++        mapped |= srcpixel[1] << 8;
++        mapped |= srcpixel[2] << 0;
++#else
++        mapped |= srcpixel[0] << 0;
++        mapped |= srcpixel[1] << 8;
++        mapped |= srcpixel[2] << 16;
++#endif
++        break;
++      case 4:
++        mapped = *(Uint32 *)srcpixel;
++        break;
++    }
++    SDL_GetRGBA(mapped, src->format, &color[0], &color[1], &color[2], &color[3]);
++  }
++
++  void merge(Uint8 color[4], Uint8 color0[4], Uint8 color1[4], int rem, int total)
++  {
++    color[0] = (color0[0] * (total - rem) + color1[0] * rem) / total;
++    color[1] = (color0[1] * (total - rem) + color1[1] * rem) / total;
++    color[2] = (color0[2] * (total - rem) + color1[2] * rem) / total;
++    color[3] = (color0[3] * (total - rem) + color1[3] * rem) / total;
++  }
++
++  SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
++  {
++    if(numerator == denominator)
++    {
++      src->refcount++;
++      return src;
++    }
++    else
++    {
++      SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
++      int bpp = dst->format->BytesPerPixel;
++      for(int y = 0;y < dst->h;y++) {
++        for(int x = 0;x < dst->w;x++) {
++          int srcx = x * denominator / numerator;
++          int srcy = y * denominator / numerator;
++          Uint8 color00[4], color01[4], color10[4], color11[4];
++          getpixel(src, srcx, srcy, color00);
++          getpixel(src, srcx + 1, srcy, color01);
++          getpixel(src, srcx, srcy + 1, color10);
++          getpixel(src, srcx + 1, srcy + 1, color11);
++          Uint8 color0[4], color1[4], color[4];
++          int remx = x * denominator % numerator;
++          merge(color0, color00, color01, remx, numerator);
++          merge(color1, color10, color11, remx, numerator);
++          int remy = y * denominator % numerator;
++          merge(color, color0, color1, remy, numerator);
++          Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
++          Uint32 mapped = SDL_MapRGBA(dst->format, color[0], color[1], color[2], color[3]);
++          switch(bpp) {
++            case 1:
++              *dstpixel = mapped;
++              break;
++            case 2:
++              *(Uint16 *)dstpixel = mapped;
++              break;
++            case 3:
++#if SDL_BYTEORDER == SDL_BIG_ENDIAN
++              dstpixel[0] = (mapped >> 16) & 0xff;
++              dstpixel[1] = (mapped >> 8) & 0xff;
++              dstpixel[2] = (mapped >> 0) & 0xff;
++#else
++              dstpixel[0] = (mapped >> 0) & 0xff;
++              dstpixel[1] = (mapped >> 8) & 0xff;
++              dstpixel[2] = (mapped >> 16) & 0xff;
++#endif
++              break;
++            case 4:
++              *(Uint32 *)dstpixel = mapped;
++              break;
++          }
++        }
++      }
++      return dst;
++    }
++  }
++#endif
++
++  // FIXME: Horizontal and vertical line problem
++#ifdef BRESENHAM
++  void accumulate(SDL_Surface *src, int srcx, int srcy, int color[4], int weight)
++  {
++    if(srcx < 0 || srcy < 0 || weight == 0) {
++      return;
++    }
++    int bpp = src->format->BytesPerPixel;
++    Uint8 *srcpixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp;
++    Uint32 mapped = 0;
++    switch(bpp) {
++      case 1:
++        mapped = *srcpixel;
++        break;
++      case 2:
++        mapped = *(Uint16 *)srcpixel;
++        break;
++      case 3:
++#if SDL_BYTEORDER == SDL_BIG_ENDIAN
++        mapped |= srcpixel[0] << 16;
++        mapped |= srcpixel[1] << 8;
++        mapped |= srcpixel[2] << 0;
++#else
++        mapped |= srcpixel[0] << 0;
++        mapped |= srcpixel[1] << 8;
++        mapped |= srcpixel[2] << 16;
++#endif
++        break;
++      case 4:
++        mapped = *(Uint32 *)srcpixel;
++        break;
++    }
++    Uint8 red, green, blue, alpha;
++    SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
++    color[0] += red * weight;
++    color[1] += green * weight;
++    color[2] += blue * weight;
++    color[3] += alpha * weight;
++  }
++
++  void accumulate_line(SDL_Surface *src, int srcy, int line[][4], int linesize, int weight, int numerator, int denominator)
++  {
++    int intpart = denominator / numerator;
++    int fractpart = denominator % numerator;
++    for(int x = 0, xe = 0, srcx = 0;x < linesize;x++) {
++      accumulate(src, srcx, srcy, line[x], (numerator - xe) * weight);
++      srcx++;
++      for(int i = 0;i < intpart - 1;i++) {
++        accumulate(src, srcx, srcy, line[x], numerator * weight);
++        srcx++;
++      }
++      xe += fractpart;
++      if(xe >= numerator) {
++        xe -= numerator;
++        srcx++;
++      }
++      accumulate(src, srcx, srcy, line[x], xe * weight);
++    }
++  }
++
++  SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
++  {
++    if(numerator == denominator)
++    {
++      src->refcount++;
++      return src;
++    }
++    else
++    {
++      SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
++      int bpp = dst->format->BytesPerPixel;
++      int intpart = denominator / numerator;
++      int fractpart = denominator % numerator;
++      for(int y = 0, ye = 0, srcy = 0;y < dst->h;y++) {
++        int line[dst->w][4];
++        memset(line, 0, sizeof(int) * dst->w * 4);
++        accumulate_line(src, srcy, line, dst->w, numerator - ye, numerator, denominator);
++        srcy++;
++        for(int i = 0;i < intpart - 1;i++) {
++          accumulate_line(src, srcy, line, dst->w, numerator, numerator, denominator);
++          srcy++;
++        }
++        ye += fractpart;
++        if(ye >= numerator) {
++          ye -= numerator;
++          srcy++;
++        }
++        accumulate_line(src, srcy, line, dst->w, ye, numerator, denominator);
++        for(int x = 0;x < dst->w;x++) {
++          Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
++          Uint32 mapped = SDL_MapRGBA(dst->format, line[x][0] / (denominator * denominator), line[x][1] / (denominator * denominator), line[x][2] / (denominator * denominator), line[x][3] / (denominator * denominator));
++          switch(bpp) {
++            case 1:
++              *dstpixel = mapped;
++              break;
++            case 2:
++              *(Uint16 *)dstpixel = mapped;
++              break;
++            case 3:
++#if SDL_BYTEORDER == SDL_BIG_ENDIAN
++              dstpixel[0] = (mapped >> 16) & 0xff;
++              dstpixel[1] = (mapped >> 8) & 0xff;
++              dstpixel[2] = (mapped >> 0) & 0xff;
++#else
++              dstpixel[0] = (mapped >> 0) & 0xff;
++              dstpixel[1] = (mapped >> 8) & 0xff;
++              dstpixel[2] = (mapped >> 16) & 0xff;
++#endif
++              break;
++            case 4:
++              *(Uint32 *)dstpixel = mapped;
++              break;
++          }
++        }
++      }
++      return dst;
++    }
++  }
++#endif
++
++  SDL_Surface *horz_flip(SDL_Surface *src)
++  {
++    SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
++    int bpp = dst->format->BytesPerPixel;
++    for(int y = 0;y < dst->h;y++) {
++      for(int x = 0;x < dst->w;x++) {
++        Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
++        Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + (dst->w - x - 1) * bpp;
++        switch(bpp) {
++          case 4:
++            dstpixel[3] = srcpixel[3];
++          case 3:
++            dstpixel[2] = srcpixel[2];
++          case 2:
++            dstpixel[1] = srcpixel[1];
++          case 1:
++            dstpixel[0] = srcpixel[0];
++        }
++      }
++    }
++    return dst;
++  }
++
++  SDL_Surface *vert_flip(SDL_Surface *src)
++  {
++    SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
++    int bpp = dst->format->BytesPerPixel;
++    for(int y = 0;y < dst->h;y++) {
++      for(int x = 0;x < dst->w;x++) {
++        Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
++        Uint8 *dstpixel = (Uint8 *) dst->pixels + (dst->h - y - 1) * dst->pitch + x * bpp;
++        switch(bpp) {
++          case 4:
++            dstpixel[3] = srcpixel[3];
++          case 3:
++            dstpixel[2] = srcpixel[2];
++          case 2:
++            dstpixel[1] = srcpixel[1];
++          case 1:
++            dstpixel[0] = srcpixel[0];
++        }
++      }
++    }
++    return dst;
++  }
+ }
  
- /**
-  * This class is a wrapper around a texture handle. It stores the texture width
-@@ -31,8 +31,9 @@
- class Texture
+ void
+ Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
++#ifdef HAVE_OPENGL
+                    float width, float height, float alpha,
++#else
++                   float width, float height, float,
++#endif
+                    DrawingEffect effect) const
  {
- protected:
-+  SDL_Surface* surface; /**< non-GL branch stores optimized surface */
-+
-   friend class TextureManager;
--  GLuint handle;
-   unsigned int width;
-   unsigned int height;
+-  float uv_width = uv_right - uv_left;
+-  float uv_height = uv_bottom - uv_top;
++#ifdef HAVE_OPENGL
++  if(use_opengl)
++  {
++    float uv_width = surface.opengl.uv_right - surface.opengl.uv_left;
++    float uv_height = surface.opengl.uv_bottom - surface.opengl.uv_top;
  
-@@ -41,11 +42,6 @@
-   Texture(SDL_Surface* surface, GLenum glformat);
-   virtual ~Texture();
-   
--  GLuint get_handle() const
--  {
--    return handle;
--  }
--
-   unsigned int get_width() const
-   {
-     return width;
-@@ -56,6 +52,14 @@
-     return height;
-   }
+-  float uv_left = this->uv_left + (uv_width * src_x) / this->width;
+-  float uv_top = this->uv_top + (uv_height * src_y) / this->height;
+-  float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
+-  float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
++    float uv_left = surface.opengl.uv_left + (uv_width * src_x) / surface.opengl.width;
++    float uv_top = surface.opengl.uv_top + (uv_height * src_y) / surface.opengl.height;
++    float uv_right = surface.opengl.uv_left + (uv_width * (src_x + width)) / surface.opengl.width;
++    float uv_bottom = surface.opengl.uv_top + (uv_height * (src_y + height)) / surface.opengl.height;
  
-+  SDL_Surface* getSurface() {
-+    return surface;
+-  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
++    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
++    glColor4f(1, 1, 1, alpha);
++    intern_draw(dst_x, dst_y,
++                dst_x + width, dst_y + height,
++                uv_left, uv_top, uv_right, uv_bottom, effect);
++    glColor4f(1, 1, 1, 1);
 +  }
++  else
++#endif
++  {
++    //FIXME: support parameter "alpha"
++ 
++    // get and check SDL_Surface
++    if (texture->get_surface() == 0) {
++      std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
++      return;
++    } 
+-  glColor4f(1, 1, 1, alpha);
+-  intern_draw(dst_x, dst_y,
+-              dst_x + width, dst_y + height,
+-              uv_left, uv_top, uv_right, uv_bottom, effect);
+-  glColor4f(1, 1, 1, 1);
++    if (surface.sdl.flipx) effect = HORIZONTAL_FLIP;
 +
-+  void setSurface(SDL_Surface* surface) {
-+    this->surface = surface;
-+  }
++    float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
++    float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
++    int numerator;
++    int denominator;
++    if(xfactor < yfactor)
++    {
++      numerator = config->screenwidth;
++      denominator = SCREEN_WIDTH;
++    }
++    else
++    {
++      numerator = config->screenheight;
++      denominator = SCREEN_HEIGHT;
++    }
 +
- private:
-   void set_texture_params();
- };
-diff -aur supertux/src/video/texture_manager.cpp supertux-nogl/src/video/texture_manager.cpp
---- supertux/src/video/texture_manager.cpp     2006-07-03 02:00:48.000000000 +0200
-+++ supertux-nogl/src/video/texture_manager.cpp        2006-07-03 02:00:29.000000000 +0200
-@@ -24,8 +24,6 @@
++    if(transforms[effect] == 0) {
++      if(transforms[NO_EFFECT] == 0) {
++        transforms[NO_EFFECT] = scale(texture->get_surface(), numerator, denominator);
++      }
++      switch(effect) {
++        case NO_EFFECT:
++          break;
++        case HORIZONTAL_FLIP:
++          transforms[HORIZONTAL_FLIP] = horz_flip(transforms[NO_EFFECT]);
++          break;
++        case VERTICAL_FLIP:
++          transforms[VERTICAL_FLIP] = vert_flip(transforms[NO_EFFECT]);
++          break;
++        default:
++          std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
++          return;
++      }
++    }
++
++    int ox = surface.sdl.offsetx;
++    if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(texture->get_surface()->w) - (ox+static_cast<int>(width));
++    int oy = surface.sdl.offsety;
++    if (effect == VERTICAL_FLIP) oy = static_cast<int>(texture->get_surface()->h) - (oy+static_cast<int>(height));
++    // draw surface to screen
++    SDL_Surface* screen = SDL_GetVideoSurface();
++
++    SDL_Rect srcRect;
++    srcRect.x = static_cast<int>((ox + src_x) * numerator / denominator);
++    srcRect.y = static_cast<int>((oy + src_y) * numerator / denominator);
++    srcRect.w = static_cast<int>(width * numerator / denominator);
++    srcRect.h = static_cast<int>(height * numerator / denominator);
++
++    SDL_Rect dstRect;
++    dstRect.x = static_cast<int>(dst_x * numerator / denominator);
++    dstRect.y = static_cast<int>(dst_y * numerator / denominator);
++
++    SDL_BlitSurface(transforms[effect], &srcRect, screen, &dstRect);
++  }
+ }
+Index: src/video/texture_manager.cpp
+===================================================================
+--- src/video/texture_manager.cpp      (revision 5071)
++++ src/video/texture_manager.cpp      (working copy)
+@@ -24,14 +24,13 @@
  #include <assert.h>
  #include <SDL.h>
  #include <SDL_image.h>
@@ -1034,7 +1654,14 @@ diff -aur supertux/src/video/texture_manager.cpp supertux-nogl/src/video/texture
  #include <iostream>
  #include <sstream>
  #include <stdexcept>
-@@ -145,12 +143,6 @@
+ #include "physfs/physfs_sdl.hpp"
+ #include "image_texture.hpp"
+ #include "glutil.hpp"
++#include "gameconfig.hpp"
+ #include "file_system.hpp"
+ #include "log.hpp"
+@@ -149,12 +148,16 @@
  void
  TextureManager::save_textures()
  {
@@ -1044,10 +1671,20 @@ diff -aur supertux/src/video/texture_manager.cpp supertux-nogl/src/video/texture
 -  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
 -  glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
 -  glPixelStorei(GL_PACK_ALIGNMENT, 1);
++#ifdef HAVE_OPENGL
++  if(config->use_opengl) {
++    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
++    glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
++    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
++    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
++    glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
++    glPixelStorei(GL_PACK_ALIGNMENT, 1);
++  }
++#endif
    for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
      save_texture(*i);
    }
-@@ -165,75 +157,16 @@
+@@ -169,74 +172,90 @@
  {
    SavedTexture saved_texture;
    saved_texture.texture = texture;
@@ -1066,19 +1703,51 @@ diff -aur supertux/src/video/texture_manager.cpp supertux-nogl/src/video/texture
 -                      &saved_texture.wrap_s);
 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
 -                      &saved_texture.wrap_t);
++#ifdef HAVE_OPENGL
++  if(config->use_opengl) {
++    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
++    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
++                             &saved_texture.width);
++    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
++                             &saved_texture.height);
++    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
++                             &saved_texture.border);
++    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
++                        &saved_texture.min_filter);
++    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
++                        &saved_texture.mag_filter);
++    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
++                        &saved_texture.wrap_s);
++    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
++                        &saved_texture.wrap_t);
++  }
++#endif
  
    size_t pixelssize = saved_texture.width * saved_texture.height * 4;
    saved_texture.pixels = new char[pixelssize];
--  
 -  glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
 -                saved_texture.pixels);
++#ifdef HAVE_OPENGL
++  if(config->use_opengl) {
++    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
++                  saved_texture.pixels);
++  }
++#endif
  
    saved_textures.push_back(saved_texture);
--
 -  glDeleteTextures(1, &(texture->handle));
 -  texture->handle = 0;
--
++#ifdef HAVE_OPENGL
++  if(config->use_opengl) {
++    glDeleteTextures(1, &(texture->get_handle()));
++    texture->set_handle(0);
 -  assert_gl("retrieving texture for save");
++    assert_gl("retrieving texture for save");
++  }
++#endif
  }
  
  void
@@ -1090,15 +1759,29 @@ diff -aur supertux/src/video/texture_manager.cpp supertux-nogl/src/video/texture
 -  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
 -  glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
 -  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
--  
++#ifdef HAVE_OPENGL
++  if(config->use_opengl) {
++    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
++    glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
++    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
++    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
++    glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
++    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 -  for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
 -      i != saved_textures.end(); ++i) {
 -    SavedTexture& saved_texture = *i;
--    
++    for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
++        i != saved_textures.end(); ++i) {
++      SavedTexture& saved_texture = *i;
 -    GLuint handle;
 -    glGenTextures(1, &handle);
 -    assert_gl("creating texture handle");
--
++      GLuint handle;
++      glGenTextures(1, &handle);
++      assert_gl("creating texture handle");
 -    glBindTexture(GL_TEXTURE_2D, handle);
 -    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
 -                 saved_texture.width, saved_texture.height,
@@ -1106,7 +1789,14 @@ diff -aur supertux/src/video/texture_manager.cpp supertux-nogl/src/video/texture
 -                 GL_UNSIGNED_BYTE, saved_texture.pixels);
 -    delete[] saved_texture.pixels;
 -    assert_gl("uploading texture pixel data");
--
++      glBindTexture(GL_TEXTURE_2D, handle);
++      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
++                   saved_texture.width, saved_texture.height,
++                   saved_texture.border, GL_RGBA,
++                   GL_UNSIGNED_BYTE, saved_texture.pixels);
++      delete[] saved_texture.pixels;
++      assert_gl("uploading texture pixel data");
 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
 -                    saved_texture.min_filter);
 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
@@ -1115,23 +1805,267 @@ diff -aur supertux/src/video/texture_manager.cpp supertux-nogl/src/video/texture
 -                    saved_texture.wrap_s);
 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
 -                    saved_texture.wrap_t);
--
++      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
++                      saved_texture.min_filter);
++      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
++                      saved_texture.mag_filter);
++      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
++                      saved_texture.wrap_s);
++      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
++                      saved_texture.wrap_t);
 -    assert_gl("setting texture_params");
 -    saved_texture.texture->handle = handle;
--  }
--
++      assert_gl("setting texture_params");
++      saved_texture.texture->set_handle(handle);
++    }
+   }
++#endif
    saved_textures.clear();
  }
+Index: src/video/surface.hpp
+===================================================================
+--- src/video/surface.hpp      (revision 5071)
++++ src/video/surface.hpp      (working copy)
+@@ -20,7 +20,11 @@
+ #ifndef __SURFACE_HPP__
+ #define __SURFACE_HPP__
  
-diff -aur supertux/src/video/texture_manager.hpp supertux-nogl/src/video/texture_manager.hpp
---- supertux/src/video/texture_manager.hpp     2006-07-03 02:00:48.000000000 +0200
-+++ supertux-nogl/src/video/texture_manager.hpp        2006-07-03 02:00:29.000000000 +0200
-@@ -20,7 +20,7 @@
- #ifndef __IMAGE_TEXTURE_MANAGER_HPP__
- #define __IMAGE_TEXTURE_MANAGER_HPP__
++#include <config.h>
++
+ #include <string>
++#include <SDL.h>
++#include "gameconfig.hpp"
+ #include "math/vector.hpp"
+ class Color;
+@@ -30,11 +34,12 @@
+ /// bitset for drawing effects
+ enum DrawingEffect {
+   /** Don't apply anything */
+-  NO_EFFECT       = 0x0000,
++  NO_EFFECT,
+   /** Draw the Surface upside down */
+-  VERTICAL_FLIP     = 0x0001,
++  VERTICAL_FLIP,
+   /** Draw the Surface from left to down */
+-  HORIZONTAL_FLIP   = 0x0002,
++  HORIZONTAL_FLIP,
++  NUM_EFFECTS
+ };
+ /**
+@@ -47,21 +52,43 @@
+ private:
+   friend class DrawingContext;
+   friend class Font;
+-  ImageTexture* texture;
+-  float uv_left;
+-  float uv_top;
+-  float uv_right;
+-  float uv_bottom;
+-
+   void draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const;
+   void draw(float x, float y, float alpha, DrawingEffect effect) const;
+   void draw_part(float src_x, float src_y, float dst_x, float dst_y,
+                  float width, float height,
+                  float alpha, DrawingEffect effect) const;
+-  float width;
+-  float height;
++  ImageTexture* texture;
++#ifdef HAVE_OPENGL
++  bool use_opengl;
++  union
++  {
++    struct
++    {
++      float uv_left;
++      float uv_top;
++      float uv_right;
++      float uv_bottom;
++
++      float width;
++      float height;
++    } opengl;
++#else
++  struct
++  {
++#endif
++    struct
++    {
++      bool flipx;
++      int offsetx; /**< Region in ::surface to be used for blitting */
++      int offsety; /**< Region in ::surface to be used for blitting */
++      int width;   /**< Region in ::surface to be used for blitting */
++      int height;  /**< Region in ::surface to be used for blitting */
++    } sdl;
++  } surface;
++  mutable SDL_Surface *transforms[NUM_EFFECTS]; /**< Cache for pre-transformed surfaces */
++
+ public:
+   Surface(const std::string& file);
+   Surface(const std::string& file, int x, int y, int w, int h);
+@@ -75,12 +102,30 @@
+   float get_width() const
+   {
+-    return width;
++#ifdef HAVE_OPENGL
++    if(use_opengl)
++    {
++      return surface.opengl.width;
++    }
++    else
++#endif
++    {
++      return surface.sdl.width;
++    }
+   }
+   float get_height() const
+   {
+-    return height;
++#ifdef HAVE_OPENGL
++    if(use_opengl)
++    {
++      return surface.opengl.height;
++    }
++    else
++#endif
++    {
++      return surface.sdl.height;
++    }
+   }
  
+   /**
+Index: src/gameconfig.cpp
+===================================================================
+--- src/gameconfig.cpp (revision 5071)
++++ src/gameconfig.cpp (working copy)
+@@ -36,6 +36,9 @@
+ Config::Config()
+ {
+   use_fullscreen = true;
++#ifdef HAVE_OPENGL
++  use_opengl = true;
++#endif
+   try_vsync = true;
+   show_fps = false;
+   sound_enabled = true;
+@@ -70,7 +73,10 @@
+   const lisp::Lisp* config_video_lisp = config_lisp->get_lisp("video");
+   if(config_video_lisp) {
+     config_video_lisp->get("fullscreen", use_fullscreen);
+-      config_video_lisp->get("vsync", try_vsync);
++#ifdef HAVE_OPENGL
++    config_video_lisp->get("opengl", use_opengl);
++#endif
++    config_video_lisp->get("vsync", try_vsync);
+     config_video_lisp->get("width", screenwidth);
+     config_video_lisp->get("height", screenheight);
+     config_video_lisp->get("aspect_ratio", aspect_ratio);
+@@ -100,6 +106,9 @@
+   writer.start_list("video");
+   writer.write_bool("fullscreen", use_fullscreen);
++#ifdef HAVE_OPENGL
++  writer.write_bool("opengl", use_opengl);
++#endif
+   writer.write_bool("vsync", try_vsync);
+   writer.write_int("width", screenwidth);
+   writer.write_int("height", screenheight);
+Index: src/main.cpp
+===================================================================
+--- src/main.cpp       (revision 5071)
++++ src/main.cpp       (working copy)
+@@ -33,7 +33,6 @@
+ #include <physfs.h>
+ #include <SDL.h>
+ #include <SDL_image.h>
 -#include <GL/gl.h>
-+#include "video/glutil.hpp"
- #include <string>
- #include <vector>
- #include <map>
+ #include "gameconfig.hpp"
+ #include "resources.hpp"
+@@ -383,7 +382,11 @@
+   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
+   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
+-  int flags = SDL_OPENGL;
++#ifdef HAVE_OPENGL
++  int flags = config->use_opengl ? SDL_OPENGL : SDL_SWSURFACE;
++#else
++  int flags = SDL_SWSURFACE;
++#endif
+   if(config->use_fullscreen)
+     flags |= SDL_FULLSCREEN;
+   int width = config->screenwidth;
+@@ -437,23 +440,28 @@
+   log_info << (config->use_fullscreen?"fullscreen ":"window ") << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << " Ratio: " << aspect_ratio << "\n";
+-  // setup opengl state and transform
+-  glDisable(GL_DEPTH_TEST);
+-  glDisable(GL_CULL_FACE);
+-  glEnable(GL_TEXTURE_2D);
+-  glEnable(GL_BLEND);
+-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
++#ifdef HAVE_OPENGL
++  if(config->use_opengl)
++  {
++    // setup opengl state and transform
++    glDisable(GL_DEPTH_TEST);
++    glDisable(GL_CULL_FACE);
++    glEnable(GL_TEXTURE_2D);
++    glEnable(GL_BLEND);
++    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+-  glViewport(0, 0, screen->w, screen->h);
+-  glMatrixMode(GL_PROJECTION);
+-  glLoadIdentity();
+-  // logical resolution here not real monitor resolution
+-  glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
+-  glMatrixMode(GL_MODELVIEW);
+-  glLoadIdentity();
+-  glTranslatef(0, 0, 0);
++    glViewport(0, 0, screen->w, screen->h);
++    glMatrixMode(GL_PROJECTION);
++    glLoadIdentity();
++    // logical resolution here not real monitor resolution
++    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
++    glMatrixMode(GL_MODELVIEW);
++    glLoadIdentity();
++    glTranslatef(0, 0, 0);
+-  check_gl_error("Setting up view matrices");
++    check_gl_error("Setting up view matrices");
++  }
++#endif
+   if(texture_manager != NULL)
+     texture_manager->reload_textures();
+Index: configure.ac
+===================================================================
+--- configure.ac       (revision 5071)
++++ configure.ac       (working copy)
+@@ -154,9 +154,15 @@
+          [AC_MSG_ERROR([Please install OpenAL])],
+          [], [])
+-AX_CHECK_GL
+-if test "$no_gl" = "yes"; then
+-  AC_MSG_ERROR([Please install opengl libraries and headers])
++AC_ARG_ENABLE(opengl,
++              AC_HELP_STRING([--enable-opengl], [enable opengl support]),
++              [enable_opengl=$enableval], [enable_opengl=yes])
++
++if test "$enable_opengl" = "yes"; then
++  AX_CHECK_GL
++  if test "$no_gl" != "yes"; then
++    AC_DEFINE_UNQUOTED(HAVE_OPENGL, 1, Define if OpenGL is present on the system)
++  fi
+ fi
+ dnl Checks for library functions.