updated -nogl patch to support fading and simple particles
[supertux.git] / contrib / supertux-nogl.diff
1 #
2 #  SuperTux -nogl patch
3 #  Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
4 #
5 #  This program is free software; you can redistribute it and/or
6 #  modify it under the terms of the GNU General Public License
7 #  as published by the Free Software Foundation; either version 2
8 #  of the License, or (at your option) any later version.
9 #
10 #  This program is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #  GNU General Public License for more details.
14 #
15 #  You should have received a copy of the GNU General Public License
16 #  along with this program; if not, write to the Free Software
17 #  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 #
19 # -----------------------------------------------------------------------------
20 #
21 #  This patch allows running the game on systems without OpenGL support. 
22 #
23 #  It modifies the video portion of the SuperTux engine to render all graphics
24 #  with SDL functions only. Many features are removed from the video engine,
25 #  so don't expect much.
26 #
27 #  Note that the patched sources will need an additional library, SDL_gfx, to 
28 #  compile.
29 #
30 #  Installing the patch should be pretty straightforward. Simply run the
31 #  following command prior to running autogen.sh and configure:
32 #
33 #  patch -p1 < contrib/supertux-nogl.diff
34 #
35 #  This patch works for revision 3677. It may break for later revisions.
36 #
37 # -----------------------------------------------------------------------------
38 diff -Naur supertux/INSTALL supertux-nogl/INSTALL
39 --- supertux/INSTALL    2006-03-03 21:49:07.000000000 +0100
40 +++ supertux-nogl/INSTALL       2006-04-07 04:13:00.000000000 +0200
41 @@ -1,7 +1,7 @@
42  - Install instructions for SuperTux -
43  http://supertux.berlios.de/
44  
45 -Last update: October 11, 2005 by Ondra Hosek
46 +Last update: March 4, 2006 by Christoph Sommer
47  
48  BINARIES
49  --------
50 @@ -34,17 +34,15 @@
51      Download: ftp://ftp.perforce.com/pub/jam
52      Homepage: http://www.perforce.com/jam/jam.html
53  
54 -* OpenGL headers and libraries
55 -    opengl libraries and headers are specific to your graphics card. Make sure
56 -    that you have hardware accelerated opengl drivers installed. Software
57 -    renderers like Mesa will make supertux unplayable slow.
58 -
59  * SDL 1.2.5 or later (1.2.8 is recommended on MacOS/X)
60      http://www.libsdl.org
61  
62  * SDL_image (any version)
63      http://www.libsdl.org/projects/SDL_image
64  
65 +* SDL_gfx (2.0.13 or later)
66 +    http://www.ferzkopp.net/Software/SDL_gfx-2.0/
67 +
68  * PhysicsFS (1.0.0, the development branch 1.1.x is buggy and does not work,
69               1.2.0 and later should work when it is released)
70      http://www.icculus.org/physfs
71 diff -Naur supertux/README supertux-nogl/README
72 --- supertux/README     2006-03-03 20:43:38.000000000 +0100
73 +++ supertux-nogl/README        2006-04-07 04:13:00.000000000 +0200
74 @@ -2,7 +2,7 @@
75  - An introduction for SuperTux -
76  http://supertux.berlios.de/
77  
78 -Last update: October 13, 2005
79 +Last update: March 4, 2006 by Christoph Sommer
80  
81  DESCRIPTION
82  -----------
83 @@ -75,10 +75,9 @@
84    Also, notice that SuperTux saves the options, so it's often enough to
85    specify them once.
86  
87 -  The game uses OpenGL to render the graphics. You will either need a CPU
88 -  with about 10 GHz or an accelerated video card with the vendor's drivers.
89 -  (On Linux, the team recommends using cards from NVidia with the proprietary
90 -  drivers, but ATI or another verndor should do.)
91 +  The game uses SDL to render the graphics. You will either need a CPU
92 +  with about 1 GHz or go get the original version of SuperTux which uses
93 +  OpenGL.
94  
95  
96  PLAYING THE GAME
97 diff -Naur supertux/configure.ac supertux-nogl/configure.ac
98 --- supertux/configure.ac       2006-03-03 20:43:38.000000000 +0100
99 +++ supertux-nogl/configure.ac  2006-04-07 04:13:00.000000000 +0200
100 @@ -11,7 +11,7 @@
101  
102  dnl Process this file with autoconf to produce a configure script.
103  AC_PREREQ([2.54])
104 -AC_INIT(supertux, 0.2-svn)
105 +AC_INIT(supertux, 0.2-nogl-svn)
106  AC_CONFIG_SRCDIR([src/main.cpp])
107  AC_CONFIG_AUX_DIR([mk/autoconf])
108  AC_CANONICAL_TARGET
109 @@ -112,6 +105,14 @@
110          [AC_MSG_ERROR([Please install SDLImage >= 1.2.1])],
111          [$SDL_CFLAGS], [$SDL_LIBS])
112  
113 +dnl FIXME: This is far from perfect
114 +NP_FINDLIB([SDLGFX], [SDL_gfx], [SDL_gfx >= 2.0.13],
115 +        NP_LANG_PROGRAM([#include <SDL_rotozoom.h>], [0;]),
116 +        [], [-lSDL_gfx],
117 +        [],
118 +        [AC_MSG_ERROR([Please install SDL_gfx >= 2.0.13])],
119 +        [$SDL_CFLAGS], [$SDL_LIBS])
120 +
121  NP_FINDLIB([PHYSFS], [physfs], [physfs >= 1.0.0],
122          NP_LANG_PROGRAM([
123  #include <stdio.h>
124 @@ -131,11 +132,6 @@
125           [AC_MSG_ERROR([Please intall OpenAL])],
126           [], [])
127  
128 -AX_CHECK_GL
129 -if test "$no_gl" = "yes"; then
130 -  AC_MSG_ERROR([Please install opengl libraries and headers])
131 -fi
132 -
133  dnl Checks for library functions.
134  AC_CHECK_FUNCS(mkdir strdup strstr)
135  
136 diff -Naur supertux/src/Jamfile supertux-nogl/src/Jamfile
137 --- supertux/src/Jamfile        2006-03-03 20:34:49.000000000 +0100
138 +++ supertux-nogl/src/Jamfile   2006-04-07 04:11:50.000000000 +0200
139 @@ -24,7 +24,7 @@
140  Application supertux : $(sources) $(wrapper_objects) ;
141  C++Flags supertux : -DAPPDATADIR='\"$(appdatadir)\"' ;
142  LinkWith supertux : squirrel ;
143 -ExternalLibs supertux : SDL SDLIMAGE GL OPENAL VORBIS VORBISFILE OGG ICONV PHYSFS BINRELOC ;
144 +ExternalLibs supertux : SDL SDLIMAGE SDLGFX OPENAL VORBIS VORBISFILE OGG ICONV PHYSFS BINRELOC ;
145  Help supertux : "Build the supertux executable" ;
146  IncludeDir supertux : squirrel/include ;
147  
148 diff -Naur supertux/src/main.cpp supertux-nogl/src/main.cpp
149 --- supertux/src/main.cpp       2006-04-07 03:32:14.000000000 +0200
150 +++ supertux-nogl/src/main.cpp  2006-04-07 04:11:50.000000000 +0200
151 @@ -35,7 +35,6 @@
152  #include <physfs.h>
153  #include <SDL.h>
154  #include <SDL_image.h>
155 -#include <GL/gl.h>
156  
157  #include "gameconfig.hpp"
158  #include "resources.hpp"
159 @@ -317,7 +275,7 @@
160    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
161    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
162    
163 -  int flags = SDL_OPENGL;
164 +  int flags = SDL_SWSURFACE;
165    if(config->use_fullscreen)
166      flags |= SDL_FULLSCREEN;
167    int width = config->screenwidth;
168 @@ -347,24 +305,6 @@
169    }
170  #endif
171  
172 -  // setup opengl state and transform
173 -  glDisable(GL_DEPTH_TEST);
174 -  glDisable(GL_CULL_FACE);
175 -  glEnable(GL_TEXTURE_2D);
176 -  glEnable(GL_BLEND);
177 -  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
178 -
179 -  glViewport(0, 0, screen->w, screen->h);
180 -  glMatrixMode(GL_PROJECTION);
181 -  glLoadIdentity();
182 -  // logical resolution here not real monitor resolution
183 -  glOrtho(0, 800, 600, 0, -1.0, 1.0);
184 -  glMatrixMode(GL_MODELVIEW);
185 -  glLoadIdentity();
186 -  glTranslatef(0, 0, 0);
187 -
188 -  check_gl_error("Setting up view matrices");
189 -
190    if(texture_manager != NULL)
191      texture_manager->reload_textures();
192    else
193 diff -Naur supertux/src/video/drawing_context.cpp supertux-nogl/src/video/drawing_context.cpp
194 --- supertux/src/video/drawing_context.cpp      2006-03-31 04:18:01.000000000 +0200
195 +++ supertux-nogl/src/video/drawing_context.cpp 2006-04-07 04:11:49.000000000 +0200
196 @@ -23,7 +23,7 @@
197  #include <cassert>
198  #include <iostream>
199  #include <SDL_image.h>
200 -#include <GL/gl.h>
201 +#include <SDL_gfxPrimitives.h>
202  
203  #include "drawing_context.hpp"
204  #include "surface.hpp"
205 @@ -49,30 +49,20 @@
206  {
207    screen = SDL_GetVideoSurface();
208  
209 -  lightmap_width = screen->w / LIGHTMAP_DIV;
210 -  lightmap_height = screen->h / LIGHTMAP_DIV;
211 -  unsigned int width = next_po2(lightmap_width);
212 -  unsigned int height = next_po2(lightmap_height);
213 -
214 -  lightmap = new Texture(width, height, GL_RGB);
215 -
216 -  lightmap_uv_right = static_cast<float>(lightmap_width) / static_cast<float>(width);
217 -  lightmap_uv_bottom = static_cast<float>(lightmap_height) / static_cast<float>(height);
218 -  texture_manager->register_texture(lightmap);
219 -
220 +  target = NORMAL;
221    requests = &drawing_requests;
222  }
223  
224  DrawingContext::~DrawingContext()
225  {
226 -  texture_manager->remove_texture(lightmap);
227 -  delete lightmap;
228  }
229  
230  void
231  DrawingContext::draw_surface(const Surface* surface, const Vector& position,
232      int layer)
233  {
234 +  if(target != NORMAL) return;
235 +
236    assert(surface != 0);
237    
238    DrawingRequest request;
239 @@ -97,6 +87,8 @@
240  DrawingContext::draw_surface_part(const Surface* surface, const Vector& source,
241      const Vector& size, const Vector& dest, int layer)
242  {
243 +  if(target != NORMAL) return;
244 +
245    assert(surface != 0);
246  
247    DrawingRequest request;
248 @@ -136,6 +128,8 @@
249  DrawingContext::draw_text(const Font* font, const std::string& text,
250      const Vector& position, FontAlignment alignment, int layer)
251  {
252 +  if(target != NORMAL) return;
253 +
254    DrawingRequest request;
255  
256    request.type = TEXT;
257 @@ -157,6 +151,8 @@
258  DrawingContext::draw_center_text(const Font* font, const std::string& text,
259      const Vector& position, int layer)
260  {
261 +  if(target != NORMAL) return;
262 +
263    draw_text(font, text, Vector(position.x + SCREEN_WIDTH/2, position.y),
264        CENTER_ALLIGN, layer);
265  }
266 @@ -164,6 +160,8 @@
267  void
268  DrawingContext::draw_gradient(const Color& top, const Color& bottom, int layer)
269  {
270 +  if(target != NORMAL) return;
271 +
272    DrawingRequest request;
273  
274    request.type = GRADIENT;
275 @@ -185,6 +183,8 @@
276  DrawingContext::draw_filled_rect(const Vector& topleft, const Vector& size,
277                                   const Color& color, int layer)
278  {
279 +  if(target != NORMAL) return;
280 +
281    DrawingRequest request;
282  
283    request.type = FILLRECT;
284 @@ -246,18 +246,21 @@
285    GradientRequest* gradientrequest = (GradientRequest*) request.request_data;
286    const Color& top = gradientrequest->top;
287    const Color& bottom = gradientrequest->bottom;
288 -  
289 -  glDisable(GL_TEXTURE_2D);
290 -  glBegin(GL_QUADS);
291 -  glColor4f(top.red, top.green, top.blue, top.alpha);
292 -  glVertex2f(0, 0);
293 -  glVertex2f(SCREEN_WIDTH, 0);
294 -  glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
295 -  glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
296 -  glVertex2f(0, SCREEN_HEIGHT);
297 -  glEnd();
298 -  glEnable(GL_TEXTURE_2D);
299  
300 +  int width = 800;
301 +  int height = 600;
302 +  for(int y = 0; y < height; y += 2) {
303 +    SDL_Rect rect; 
304 +    rect.x = 0;
305 +    rect.y = y;
306 +    rect.w = width;
307 +    rect.h = 2;
308 +    int r = (int)(255.0 * (((float)(top.red-bottom.red)/(0-height)) * y + top.red));
309 +    int g = (int)(255.0 * (((float)(top.green-bottom.green)/(0-height)) * y + top.green));
310 +    int b = (int)(255.0 * (((float)(top.blue-bottom.blue)/(0-height)) * y + top.blue));
311 +    SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
312 +  }
313 +
314    delete gradientrequest;
315  }
316  
317 @@ -277,23 +280,18 @@
318  {
319    FillRectRequest* fillrectrequest = (FillRectRequest*) request.request_data;
320  
321 -  float x = request.pos.x;
322 -  float y = request.pos.y;
323 -  float w = fillrectrequest->size.x;
324 -  float h = fillrectrequest->size.y;
325 +  int x = static_cast<int>(request.pos.x);
326 +  int y = static_cast<int>(request.pos.y);
327 +  int w = static_cast<int>(fillrectrequest->size.x);
328 +  int h = static_cast<int>(fillrectrequest->size.y);
329  
330 -  glDisable(GL_TEXTURE_2D);
331 -  glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
332 -            fillrectrequest->color.blue, fillrectrequest->color.alpha);
333
334 -  glBegin(GL_QUADS);
335 -  glVertex2f(x, y);
336 -  glVertex2f(x+w, y);
337 -  glVertex2f(x+w, y+h);
338 -  glVertex2f(x, y+h);
339 -  glEnd();
340 -  glEnable(GL_TEXTURE_2D);
341 +  int r = static_cast<int>(255.0 * fillrectrequest->color.red);
342 +  int g = static_cast<int>(255.0 * fillrectrequest->color.green);
343 +  int b = static_cast<int>(255.0 * fillrectrequest->color.blue);
344 +  int a = static_cast<int>(255.0 * fillrectrequest->color.alpha);
345  
346 +  boxRGBA(screen, x, y, x + w, y + h, r, g, b, a); 
347 +
348    delete fillrectrequest;
349  }
350  
351 @@ -307,66 +305,10 @@
352    transformstack.clear();
353    target_stack.clear();
354  
355 -  bool use_lightmap = lightmap_requests.size() != 0;
356 -  
357 -  // PART1: create lightmap
358 -  if(use_lightmap) {
359 -    glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
360 -    glMatrixMode(GL_PROJECTION);
361 -    glLoadIdentity();               
362 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
363 -    glMatrixMode(GL_MODELVIEW);
364 -    glLoadIdentity();
365 -
366 -    //glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
367 -    glClearColor(0, 0, 0, 1);
368 -    glClear(GL_COLOR_BUFFER_BIT);
369 -    handle_drawing_requests(lightmap_requests);
370 -    lightmap_requests.clear();
371 -  
372 -    glDisable(GL_BLEND);
373 -    glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
374 -    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
375 -
376 -    glViewport(0, 0, screen->w, screen->h);
377 -    glMatrixMode(GL_PROJECTION);
378 -    glLoadIdentity();               
379 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
380 -    glMatrixMode(GL_MODELVIEW);    
381 -    glLoadIdentity();
382 -    glEnable(GL_BLEND);
383 -  }
384 -
385 -  //glClear(GL_COLOR_BUFFER_BIT);
386    handle_drawing_requests(drawing_requests);
387    drawing_requests.clear();
388  
389 -  if(use_lightmap) {
390 -    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
391 -
392 -    glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
393 -    glBegin(GL_QUADS);
394 -
395 -    glTexCoord2f(0, lightmap_uv_bottom);
396 -    glVertex2f(0, 0);
397 -
398 -    glTexCoord2f(lightmap_uv_right, lightmap_uv_bottom);
399 -    glVertex2f(SCREEN_WIDTH, 0);
400 -
401 -    glTexCoord2f(lightmap_uv_right, 0);
402 -    glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
403 -
404 -    glTexCoord2f(0, 0);
405 -    glVertex2f(0, SCREEN_HEIGHT);
406 -    
407 -    glEnd();
408 -
409 -    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
410 -  }
411 -
412 -  assert_gl("drawing");
413 -
414 -  SDL_GL_SwapBuffers();
415 +  SDL_Flip(screen);
416  }
417  
418  void
419 @@ -455,9 +397,5 @@
420  DrawingContext::set_target(Target target)
421  {
422    this->target = target;
423 -  if(target == LIGHTMAP)
424 -    requests = &lightmap_requests;
425 -  else
426 -    requests = &drawing_requests;
427  }
428
429 diff -Naur supertux/src/video/drawing_context.hpp supertux-nogl/src/video/drawing_context.hpp
430 --- supertux/src/video/drawing_context.hpp      2006-03-03 20:34:27.000000000 +0100
431 +++ supertux-nogl/src/video/drawing_context.hpp 2006-04-07 04:11:49.000000000 +0200
432 @@ -23,7 +23,6 @@
433  #include <string>
434  #include <stdint.h>
435  
436 -#include <GL/gl.h>
437  #include <SDL.h>
438  #include <stdint.h>
439  #include <memory>
440 @@ -33,8 +32,9 @@
441  #include "font.hpp"
442  #include "color.hpp"
443  
444 +#include "glutil.hpp"
445 +
446  class Surface;
447 -class Texture;
448  
449  // some constants for predefined layer values
450  enum {
451 @@ -202,16 +202,12 @@
452    void draw_filled_rect(DrawingRequest& request);
453    
454    DrawingRequests drawing_requests;
455 -  DrawingRequests lightmap_requests;
456  
457    DrawingRequests* requests;
458  
459    SDL_Surface* screen;
460    Target target;
461    std::vector<Target> target_stack;
462 -  Texture* lightmap;
463 -  int lightmap_width, lightmap_height;
464 -  float lightmap_uv_right, lightmap_uv_bottom;
465  };
466  
467  #endif
468 diff -Naur supertux/src/video/glutil.hpp supertux-nogl/src/video/glutil.hpp
469 --- supertux/src/video/glutil.hpp       2006-03-21 16:13:11.000000000 +0100
470 +++ supertux-nogl/src/video/glutil.hpp  2006-04-07 04:11:49.000000000 +0200
471 @@ -21,53 +21,6 @@
472 -#include <GL/gl.h>
473  
474 -static inline void check_gl_error(const char* message)
475 -{
476 -#ifdef DEBUG
477 -  GLenum error = glGetError();
478 -  if(error != GL_NO_ERROR) {
479 -    std::ostringstream msg;
480 -    msg << "OpenGLError while '" << message << "': ";
481 -    switch(error) {
482 -      case GL_INVALID_ENUM:
483 -        msg << "INVALID_ENUM: An unacceptable value is specified for an "
484 -               "enumerated argument.";
485 -        break;
486 -      case GL_INVALID_VALUE:
487 -        msg << "INVALID_VALUE: A numeric argument is out of range.";
488 -        break;
489 -      case GL_INVALID_OPERATION:
490 -        msg << "INVALID_OPERATION: The specified operation is not allowed "
491 -               "in the current state.";
492 -        break;
493 -      case GL_STACK_OVERFLOW:
494 -        msg << "STACK_OVERFLOW: This command would cause a stack overflow.";
495 -        break;
496 -      case GL_STACK_UNDERFLOW:
497 -        msg << "STACK_UNDERFLOW: This command would cause a stack underflow.";
498 -        break;
499 -      case GL_OUT_OF_MEMORY:
500 -        msg << "OUT_OF_MEMORY: There is not enough memory left to execute the "
501 -               "command.";
502 -        break;
503 -#ifdef GL_TABLE_TOO_LARGE
504 -      case GL_TABLE_TOO_LARGE:
505 -        msg << "TABLE_TOO_LARGE: table is too large";
506 -        break;
507 -#endif                        
508 -      default:
509 -        msg << "Unknown error (code " << error << ")";
510 -    }
511 -        
512 -    throw std::runtime_error(msg.str());
513 -  }
514 -#endif
515 -}
516 -
517 -static inline void assert_gl(const char* message)
518 -{
519 -#ifdef DEBUG
520 -  check_gl_error(message);
521 -#else
522 -  (void) message;
523 -#endif
524 -}
525 +#define GLenum int
526 +#define GLint int
527 +#define GL_SRC_ALPHA 0
528 +#define GL_ONE_MINUS_SRC_ALPHA 1
529 +#define GL_RGBA 2
530 diff -Naur supertux/src/video/surface.cpp supertux-nogl/src/video/surface.cpp
531 --- supertux/src/video/surface.cpp      2006-03-25 01:16:31.000000000 +0100
532 +++ supertux-nogl/src/video/surface.cpp 2006-04-07 04:11:49.000000000 +0200
533 @@ -28,6 +29,7 @@
534  
535  #include <SDL.h>
536  #include <SDL_image.h>
537 +#include <SDL_rotozoom.h>
538  
539  #include "gameconfig.hpp"
540  #include "physfs/physfs_sdl.hpp"
541 @@ -40,13 +42,13 @@
542  {
543    texture = texture_manager->get(file);
544    texture->ref();
545 -  uv_left = 0;
546 -  uv_top = 0;
547 -  uv_right = texture->get_uv_right();
548 -  uv_bottom = texture->get_uv_bottom();
549  
550 -  width = texture->get_image_width();
551 -  height = texture->get_image_height();
552 +  offsetx = 0;
553 +  offsety = 0;
554 +  width = static_cast<int>(texture->get_image_width());
555 +  height = static_cast<int>(texture->get_image_height());
556 +
557 +  flipx = false;
558  }
559  
560  Surface::Surface(const std::string& file, int x, int y, int w, int h)
561 @@ -54,15 +56,12 @@
562    texture = texture_manager->get(file);
563    texture->ref();
564  
565 -  float tex_w = static_cast<float> (texture->get_width());
566 -  float tex_h = static_cast<float> (texture->get_height());
567 -  uv_left = static_cast<float>(x) / tex_w;
568 -  uv_top = static_cast<float>(y) / tex_h;
569 -  uv_right = static_cast<float>(x+w) / tex_w;
570 -  uv_bottom = static_cast<float>(y+h) / tex_h;
571 -
572 +  offsetx = x;
573 +  offsety = y;
574    width = w;
575    height = h;
576 +
577 +  flipx = false;
578  }
579  
580  Surface::Surface(const Surface& other)
581 @@ -70,12 +69,12 @@
582    texture = other.texture;
583    texture->ref();
584  
585 -  uv_left = other.uv_left;
586 -  uv_top = other.uv_top;
587 -  uv_right = other.uv_right;
588 -  uv_bottom = other.uv_bottom;
589 +  offsetx = other.offsetx;
590 +  offsety = other.offsety;
591    width = other.width;
592    height = other.height;
593 +
594 +  flipx = other.flipx;
595  }
596  
597  const Surface&
598 @@ -85,81 +84,95 @@
599    texture->unref();
600    texture = other.texture;
601  
602 -  uv_left = other.uv_left;
603 -  uv_top = other.uv_top;
604 -  uv_right = other.uv_right;
605 -  uv_bottom = other.uv_bottom;
606 +  offsetx = other.offsetx;
607 +  offsety = other.offsety;
608    width = other.width;
609    height = other.height;
610  
611 +  flipx = other.flipx;
612 +
613    return *this;
614  }
615  
616  Surface::~Surface()
617  {
618    texture->unref();
619 +
620 +  for (std::list<TransformedSurface*>::iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
621 +    SDL_FreeSurface((*i)->surface);
622 +    delete (*i);
623 +  }
624  }
625  
626  void
627  Surface::hflip()
628  {
629 -  std::swap(uv_left, uv_right);
630 -}
631 -
632 -static inline void intern_draw(float left, float top, float right, float bottom,                               float uv_left, float uv_top,
633 -                               float uv_right, float uv_bottom,
634 -                               DrawingEffect effect)
635 -{
636 -  if(effect & HORIZONTAL_FLIP)
637 -    std::swap(uv_left, uv_right);
638 -  if(effect & VERTICAL_FLIP) {
639 -    std::swap(uv_top, uv_bottom);
640 -  }
641 -  
642 -  glBegin(GL_QUADS);
643 -  glTexCoord2f(uv_left, uv_top);
644 -  glVertex2f(left, top);
645 -  
646 -  glTexCoord2f(uv_right, uv_top);
647 -  glVertex2f(right, top);
648 -
649 -  glTexCoord2f(uv_right, uv_bottom);
650 -  glVertex2f(right, bottom);
651 -
652 -  glTexCoord2f(uv_left, uv_bottom);
653 -  glVertex2f(left, bottom);
654 -  glEnd();
655 +  flipx = !flipx;
656  }
657  
658  void
659  Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
660  {
661 -  glColor4f(1.0f, 1.0f, 1.0f, alpha);
662 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
663 -
664 -  intern_draw(x, y,
665 -              x + width, y + height,
666 -              uv_left, uv_top, uv_right, uv_bottom, effect);
667 +  draw_part(0, 0, x, y, width, height, alpha, effect);
668  }
669  
670  void
671  Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
672 -                   float width, float height, float alpha,
673 +                   float width, float height, float,
674                     DrawingEffect effect) const
675  {
676 -  float uv_width = uv_right - uv_left;
677 -  float uv_height = uv_bottom - uv_top;
678 -  
679 -  float uv_left = this->uv_left + (uv_width * src_x) / this->width;
680 -  float uv_top = this->uv_top + (uv_height * src_y) / this->height;
681 -  float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
682 -  float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
683 -  
684 -  glColor4f(1.0f, 1.0f, 1.0f, alpha);
685 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());  
686 -  
687 -  intern_draw(dst_x, dst_y,
688 -              dst_x + width, dst_y + height,
689 -              uv_left, uv_top, uv_right, uv_bottom, effect);
690 +  //FIXME: support parameter "alpha"
691 +  SDL_Surface* surface = texture->getSurface();
692 +
693 +  // get and check SDL_Surface
694 +  if (surface == 0) {
695 +    std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
696 +    return;
697 +  }    
698 +
699 +  SDL_Surface* transformedSurface = surface;
700 +
701 +  if (flipx) effect = HORIZONTAL_FLIP;
702 +
703 +  if (effect != NO_EFFECT) {
704 +    transformedSurface = 0;
705 +
706 +    // check if we have this effect buffered
707 +    for (std::list<TransformedSurface*>::const_iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
708 +      if ((*i)->effect == effect) transformedSurface = (*i)->surface;
709 +    }
710 +
711 +    // if not: transform and buffer
712 +    if (!transformedSurface) {
713 +      if (effect == HORIZONTAL_FLIP) transformedSurface = zoomSurface(surface, -1, 1, 0);
714 +      if (effect == VERTICAL_FLIP) transformedSurface = zoomSurface(surface, 1, -1, 0);
715 +      if (transformedSurface == 0) {
716 +        std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
717 +        return;
718 +      }        
719 +      TransformedSurface* su = new TransformedSurface();
720 +      su->surface = transformedSurface;
721 +      su->effect = effect;
722 +
723 +      transformedSurfaces.push_front(su);
724 +    }
725 +  }
726 +
727 +  int ox = offsetx; if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(surface->w) - (ox+static_cast<int>(width));
728 +  int oy = offsety; if (effect == VERTICAL_FLIP) oy = static_cast<int>(surface->h) - (oy+static_cast<int>(height));
729 +  // draw surface to screen
730 +  SDL_Surface* screen = SDL_GetVideoSurface();
731 +
732 +  SDL_Rect srcRect;
733 +  srcRect.x = static_cast<int>(ox+src_x);
734 +  srcRect.y = static_cast<int>(oy+src_y);
735 +  srcRect.w = static_cast<int>(width);
736 +  srcRect.h = static_cast<int>(height);
737 +
738 +  SDL_Rect dstRect;
739 +  dstRect.x = static_cast<int>(dst_x);
740 +  dstRect.y = static_cast<int>(dst_y);
741 +
742 +  SDL_BlitSurface(transformedSurface, &srcRect, screen, &dstRect);
743  }
744  
745 diff -Naur supertux/src/video/surface.hpp supertux-nogl/src/video/surface.hpp
746 --- supertux/src/video/surface.hpp      2006-03-03 20:34:27.000000000 +0100
747 +++ supertux-nogl/src/video/surface.hpp 2006-04-07 04:11:49.000000000 +0200
748 @@ -20,7 +20,9 @@
749  #ifndef __SURFACE_HPP__
750  #define __SURFACE_HPP__
751  
752 +#include <SDL_image.h>
753  #include <string>
754 +#include <list>
755  
756  class ImageTexture;
757  
758 @@ -35,6 +37,15 @@
759  };
760  
761  /**
762 + * Helper class to buffer a pre-transformed SDL_Surface
763 + */
764 +class TransformedSurface {
765 +    public:
766 +       SDL_Surface* surface;
767 +       DrawingEffect effect;
768 +};
769 +
770 +/**
771   * A rectangular image.
772   * The class basically holds a reference to a texture with additional UV
773   * coordinates that specify a rectangular area on this texture
774 @@ -46,18 +57,23 @@
775    friend class Font;
776    ImageTexture* texture;
777  
778 -  float uv_left;
779 -  float uv_top;
780 -  float uv_right;
781 -  float uv_bottom;
782 +  bool flipx;
783  
784 +  /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
785    void draw(float x, float y, float alpha, DrawingEffect effect) const;
786 +
787 +  /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
788    void draw_part(float src_x, float src_y, float dst_x, float dst_y,
789                   float width, float height,
790                   float alpha, DrawingEffect effect) const;
791  
792 -  float width;
793 -  float height;
794 +  int offsetx; /**< Region in ::surface to be used for blitting */
795 +  int offsety; /**< Region in ::surface to be used for blitting */
796 +  int width;   /**< Region in ::surface to be used for blitting */
797 +  int height;  /**< Region in ::surface to be used for blitting */
798 +
799 +  mutable std::list<TransformedSurface*> transformedSurfaces; /**< Cache for pre-transformed surfaces */
800 +
801  public:
802    Surface(const std::string& file);
803    Surface(const std::string& file, int x, int y, int w, int h);
804 diff -Naur supertux/src/video/texture.cpp supertux-nogl/src/video/texture.cpp
805 --- supertux/src/video/texture.cpp      2006-03-03 20:34:27.000000000 +0100
806 +++ supertux-nogl/src/video/texture.cpp 2006-04-07 04:11:49.000000000 +0200
807 @@ -20,7 +20,6 @@
808  
809  #include "texture.hpp"
810  
811 -#include <GL/gl.h>
812  #include <assert.h>
813  #include "glutil.hpp"
814  
815 @@ -29,81 +28,37 @@
816    return (v & (v-1)) == 0;
817  }
818  
819 -Texture::Texture(unsigned int w, unsigned int h, GLenum glformat)
820 +Texture::Texture(unsigned int w, unsigned int h, GLenum)
821  {
822    assert(is_power_of_2(w));
823    assert(is_power_of_2(h));
824  
825    this->width = w;
826    this->height = h;
827 -  
828 -  assert_gl("before creating texture");
829 -  glGenTextures(1, &handle);
830 -  
831 -  try {
832 -    glBindTexture(GL_TEXTURE_2D, handle);
833 -
834 -    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
835 -                 GL_UNSIGNED_BYTE, 0);
836 -
837 -    set_texture_params();
838 -  } catch(...) {
839 -    glDeleteTextures(1, &handle);
840 -    throw;
841 -  }
842 +
843 +  surface = 0;
844  }
845  
846 -Texture::Texture(SDL_Surface* image, GLenum glformat)
847 +Texture::Texture(SDL_Surface* image, GLenum)
848  {
849    const SDL_PixelFormat* format = image->format;
850    if(!is_power_of_2(image->w) || !is_power_of_2(image->h))
851      throw std::runtime_error("image has no power of 2 size");
852    if(format->BitsPerPixel != 24 && format->BitsPerPixel != 32)
853      throw std::runtime_error("image has no 24 or 32 bit color depth");
854 -  
855 +
856    this->width = image->w;
857    this->height = image->h;
858  
859 -  assert_gl("before creating texture");
860 -  glGenTextures(1, &handle);
861 -  
862 -  try {
863 -    GLenum sdl_format;
864 -    if(format->BytesPerPixel == 3)
865 -      sdl_format = GL_RGB;
866 -    else if(format->BytesPerPixel == 4)
867 -      sdl_format = GL_RGBA;
868 -    else
869 -      assert(false);
870 -
871 -    glBindTexture(GL_TEXTURE_2D, handle);
872 -    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
873 -    glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
874 -    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
875 -            GL_UNSIGNED_BYTE, image->pixels);
876 -
877 -    assert_gl("creating texture");
878 -
879 -    set_texture_params();    
880 -  } catch(...) {
881 -    glDeleteTextures(1, &handle);
882 -    throw;
883 -  }
884 +  surface = SDL_DisplayFormatAlpha(image);
885  }
886  
887  Texture::~Texture()
888  {
889 -  glDeleteTextures(1, &handle);
890  }
891  
892  void
893  Texture::set_texture_params()
894  {
895 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
896 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
897 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
898 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
899 -
900 -  assert_gl("set texture params");
901  }
902  
903 diff -Naur supertux/src/video/texture.hpp supertux-nogl/src/video/texture.hpp
904 --- supertux/src/video/texture.hpp      2006-03-03 20:34:27.000000000 +0100
905 +++ supertux-nogl/src/video/texture.hpp 2006-04-07 04:11:49.000000000 +0200
906 @@ -20,7 +20,7 @@
907  #define __TEXTURE_HPP__
908  
909  #include <SDL.h>
910 -#include <GL/gl.h>
911 +#include "glutil.hpp"
912  
913  /**
914   * This class is a wrapper around a texture handle. It stores the texture width
915 @@ -30,8 +30,9 @@
916  class Texture
917  {
918  protected:
919 +  SDL_Surface* surface; /**< non-GL branch stores optimized surface */
920 +
921    friend class TextureManager;
922 -  GLuint handle;
923    unsigned int width;
924    unsigned int height;
925  
926 @@ -40,11 +41,6 @@
927    Texture(SDL_Surface* surface, GLenum glformat);
928    virtual ~Texture();
929    
930 -  GLuint get_handle() const
931 -  {
932 -    return handle;
933 -  }
934 -
935    unsigned int get_width() const
936    {
937      return width;
938 @@ -55,6 +51,14 @@
939      return height;
940    }
941  
942 +  SDL_Surface* getSurface() {
943 +    return surface;
944 +  }
945 +
946 +  void setSurface(SDL_Surface* surface) {
947 +    this->surface = surface;
948 +  }
949 +
950  private:
951    void set_texture_params();
952  };
953 diff -Naur supertux/src/video/texture_manager.cpp supertux-nogl/src/video/texture_manager.cpp
954 --- supertux/src/video/texture_manager.cpp      2006-04-07 03:32:13.000000000 +0200
955 +++ supertux-nogl/src/video/texture_manager.cpp 2006-04-07 04:11:49.000000000 +0200
956 @@ -5,8 +5,6 @@
957  #include <assert.h>
958  #include <SDL.h>
959  #include <SDL_image.h>
960 -#include <GL/gl.h>
961 -#include <GL/glext.h>
962  #include <iostream>
963  #include <sstream>
964  #include <stdexcept>
965 @@ -126,12 +124,6 @@
966  void
967  TextureManager::save_textures()
968  {
969 -  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
970 -  glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
971 -  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
972 -  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
973 -  glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
974 -  glPixelStorei(GL_PACK_ALIGNMENT, 1);
975    for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
976      save_texture(*i);
977    }
978 @@ -146,75 +138,16 @@
979  {
980    SavedTexture saved_texture;
981    saved_texture.texture = texture;
982 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
983 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
984 -                           &saved_texture.width);
985 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
986 -                           &saved_texture.height);
987 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
988 -                           &saved_texture.border);
989 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
990 -                      &saved_texture.min_filter);
991 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
992 -                      &saved_texture.mag_filter);
993 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
994 -                      &saved_texture.wrap_s);
995 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
996 -                      &saved_texture.wrap_t);
997  
998    size_t pixelssize = saved_texture.width * saved_texture.height * 4;
999    saved_texture.pixels = new char[pixelssize];
1000 -  
1001 -  glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1002 -                saved_texture.pixels);
1003  
1004    saved_textures.push_back(saved_texture);
1005 -
1006 -  glDeleteTextures(1, &(texture->handle));
1007 -  texture->handle = 0;
1008 -
1009 -  assert_gl("retrieving texture for save");
1010  }
1011  
1012  void
1013  TextureManager::reload_textures()
1014  {
1015 -  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1016 -  glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1017 -  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1018 -  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1019 -  glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1020 -  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1021 -  
1022 -  for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1023 -      i != saved_textures.end(); ++i) {
1024 -    SavedTexture& saved_texture = *i;
1025 -    
1026 -    GLuint handle;
1027 -    glGenTextures(1, &handle);
1028 -    assert_gl("creating texture handle");
1029 -
1030 -    glBindTexture(GL_TEXTURE_2D, handle);
1031 -    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1032 -                 saved_texture.width, saved_texture.height,
1033 -                 saved_texture.border, GL_RGBA,
1034 -                 GL_UNSIGNED_BYTE, saved_texture.pixels);
1035 -    delete[] saved_texture.pixels;
1036 -    assert_gl("uploading texture pixel data");
1037 -
1038 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1039 -                    saved_texture.min_filter);
1040 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1041 -                    saved_texture.mag_filter);
1042 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1043 -                    saved_texture.wrap_s);
1044 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1045 -                    saved_texture.wrap_t);
1046 -
1047 -    assert_gl("setting texture_params");
1048 -    saved_texture.texture->handle = handle;
1049 -  }
1050 -
1051    saved_textures.clear();
1052  }
1053  
1054 diff -Naur supertux/src/video/texture_manager.hpp supertux-nogl/src/video/texture_manager.hpp
1055 --- supertux/src/video/texture_manager.hpp      2006-03-03 20:34:27.000000000 +0100
1056 +++ supertux-nogl/src/video/texture_manager.hpp 2006-04-07 04:11:49.000000000 +0200
1057 @@ -1,7 +1,7 @@
1058  #ifndef __IMAGE_TEXTURE_MANAGER_HPP__
1059  #define __IMAGE_TEXTURE_MANAGER_HPP__
1060  
1061 -#include <GL/gl.h>
1062 +#include "video/glutil.hpp"
1063  #include <string>
1064  #include <vector>
1065  #include <map>
1066