Yet another update
[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 3858. 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 -aur supertux/src/video/drawing_context.cpp supertux-nogl/src/video/drawing_context.cpp
194 --- supertux/src/video/drawing_context.cpp      2006-07-03 02:00:48.000000000 +0200
195 +++ supertux-nogl/src/video/drawing_context.cpp 2006-07-03 02:00:29.000000000 +0200
196 @@ -23,7 +23,6 @@
197  #include <cassert>
198  #include <iostream>
199  #include <SDL_image.h>
200 -#include <GL/gl.h>
201  
202  #include "drawing_context.hpp"
203  #include "surface.hpp"
204 @@ -49,30 +48,20 @@
205  {
206    screen = SDL_GetVideoSurface();
207  
208 -  lightmap_width = screen->w / LIGHTMAP_DIV;
209 -  lightmap_height = screen->h / LIGHTMAP_DIV;
210 -  unsigned int width = next_po2(lightmap_width);
211 -  unsigned int height = next_po2(lightmap_height);
212 -
213 -  lightmap = new Texture(width, height, GL_RGB);
214 -
215 -  lightmap_uv_right = static_cast<float>(lightmap_width) / static_cast<float>(width);
216 -  lightmap_uv_bottom = static_cast<float>(lightmap_height) / static_cast<float>(height);
217 -  texture_manager->register_texture(lightmap);
218 -
219 +  target = NORMAL;
220    requests = &drawing_requests;
221  }
222  
223  DrawingContext::~DrawingContext()
224  {
225 -  texture_manager->remove_texture(lightmap);
226 -  delete lightmap;
227  }
228  
229  void
230  DrawingContext::draw_surface(const Surface* surface, const Vector& position, float angle,
231      int layer)
232  {
233 +  if(target != NORMAL) return;
234 +
235    assert(surface != 0);
236    
237    DrawingRequest request;
238 @@ -105,6 +94,8 @@
239  DrawingContext::draw_surface_part(const Surface* surface, const Vector& source,
240      const Vector& size, const Vector& dest, int layer)
241  {
242 +  if(target != NORMAL) return;
243 +
244    assert(surface != 0);
245  
246    DrawingRequest request;
247 @@ -144,6 +135,8 @@
248  DrawingContext::draw_text(const Font* font, const std::string& text,
249      const Vector& position, FontAlignment alignment, int layer)
250  {
251 +  if(target != NORMAL) return;
252 +
253    DrawingRequest request;
254  
255    request.type = TEXT;
256 @@ -165,6 +158,8 @@
257  DrawingContext::draw_center_text(const Font* font, const std::string& text,
258      const Vector& position, int layer)
259  {
260 +  if(target != NORMAL) return;
261 +
262    draw_text(font, text, Vector(position.x + SCREEN_WIDTH/2, position.y),
263        CENTER_ALLIGN, layer);
264  }
265 @@ -172,6 +167,8 @@
266  void
267  DrawingContext::draw_gradient(const Color& top, const Color& bottom, int layer)
268  {
269 +  if(target != NORMAL) return;
270 +
271    DrawingRequest request;
272  
273    request.type = GRADIENT;
274 @@ -193,6 +190,8 @@
275  DrawingContext::draw_filled_rect(const Vector& topleft, const Vector& size,
276                                   const Color& color, int layer)
277  {
278 +  if(target != NORMAL) return;
279 +
280    DrawingRequest request;
281  
282    request.type = FILLRECT;
283 @@ -248,23 +247,55 @@
284    delete surfacepartrequest;
285  }
286  
287 +namespace
288 +{
289 +  void fillrect(SDL_Surface* screen, float x, float y, float w, float h, int r, int g, int b, int a)
290 +  {
291 +    if(w < 0) {
292 +      x += w;
293 +      w = -w;
294 +    }
295 +    if(h < 0) {
296 +      y += h;
297 +      h = -h;
298 +    }
299 +
300 +    SDL_Rect src, rect;
301 +    SDL_Surface *temp = NULL;
302 +
303 +    rect.x = (int)x;
304 +    rect.y = (int)y;
305 +    rect.w = (int)w;
306 +    rect.h = (int)h;
307 +
308 +    if(a != 255) {
309 +      temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
310 +
311 +      src.x = 0;
312 +      src.y = 0;
313 +      src.w = rect.w;
314 +      src.h = rect.h;
315 +
316 +      SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, r, g, b));
317 +      SDL_SetAlpha(temp, SDL_SRCALPHA, a);
318 +      SDL_BlitSurface(temp,0,screen,&rect);
319 +      SDL_FreeSurface(temp);
320 +    } else {
321 +      SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
322 +    }
323 +  }
324 +}
325 +
326  void
327  DrawingContext::draw_gradient(DrawingRequest& request)
328  {
329    GradientRequest* gradientrequest = (GradientRequest*) request.request_data;
330    const Color& top = gradientrequest->top;
331    const Color& bottom = gradientrequest->bottom;
332 -  
333 -  glDisable(GL_TEXTURE_2D);
334 -  glBegin(GL_QUADS);
335 -  glColor4f(top.red, top.green, top.blue, top.alpha);
336 -  glVertex2f(0, 0);
337 -  glVertex2f(SCREEN_WIDTH, 0);
338 -  glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
339 -  glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
340 -  glVertex2f(0, SCREEN_HEIGHT);
341 -  glEnd();
342 -  glEnable(GL_TEXTURE_2D);
343 +
344 +  int width = 800;
345 +  int height = 600;
346 +  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);
347  
348    delete gradientrequest;
349  }
350 @@ -290,17 +321,12 @@
351    float w = fillrectrequest->size.x;
352    float h = fillrectrequest->size.y;
353  
354 -  glDisable(GL_TEXTURE_2D);
355 -  glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
356 -            fillrectrequest->color.blue, fillrectrequest->color.alpha);
357
358 -  glBegin(GL_QUADS);
359 -  glVertex2f(x, y);
360 -  glVertex2f(x+w, y);
361 -  glVertex2f(x+w, y+h);
362 -  glVertex2f(x, y+h);
363 -  glEnd();
364 -  glEnable(GL_TEXTURE_2D);
365 +  int r = static_cast<int>(fillrectrequest->color.red);
366 +  int g = static_cast<int>(fillrectrequest->color.green);
367 +  int b = static_cast<int>(fillrectrequest->color.blue);
368 +  int a = static_cast<int>(fillrectrequest->color.alpha);
369 +
370 +  ::fillrect(screen, x, y, w, h, r, g, b, a);
371  
372    delete fillrectrequest;
373  }
374 @@ -315,67 +341,10 @@
375    transformstack.clear();
376    target_stack.clear();
377  
378 -  bool use_lightmap = lightmap_requests.size() != 0;
379 -  
380 -  // PART1: create lightmap
381 -  if(use_lightmap) {
382 -    glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
383 -    glMatrixMode(GL_PROJECTION);
384 -    glLoadIdentity();               
385 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
386 -    glMatrixMode(GL_MODELVIEW);
387 -    glLoadIdentity();
388 -
389 -    // FIXME: Add ambient light support here
390 -    glClearColor(0.3, 0.3, 0.4, 1);
391 -    glClear(GL_COLOR_BUFFER_BIT);
392 -    handle_drawing_requests(lightmap_requests);
393 -    lightmap_requests.clear();
394 -  
395 -    glDisable(GL_BLEND);
396 -    glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
397 -    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
398 -
399 -    glViewport(0, 0, screen->w, screen->h);
400 -    glMatrixMode(GL_PROJECTION);
401 -    glLoadIdentity();               
402 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
403 -    glMatrixMode(GL_MODELVIEW);    
404 -    glLoadIdentity();
405 -    glEnable(GL_BLEND);
406 -  }
407 -
408 -  //glClear(GL_COLOR_BUFFER_BIT);
409    handle_drawing_requests(drawing_requests);
410    drawing_requests.clear();
411  
412 -  if(use_lightmap) {
413 -    // multiple the lightmap with the framebuffer
414 -    glBlendFunc(GL_DST_COLOR, GL_ZERO);
415 -     
416 -    glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
417 -    glBegin(GL_QUADS);
418 -
419 -    glTexCoord2f(0, lightmap_uv_bottom);
420 -    glVertex2f(0, 0);
421 -
422 -    glTexCoord2f(lightmap_uv_right, lightmap_uv_bottom);
423 -    glVertex2f(SCREEN_WIDTH, 0);
424 -
425 -    glTexCoord2f(lightmap_uv_right, 0);
426 -    glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
427 -
428 -    glTexCoord2f(0, 0);
429 -    glVertex2f(0, SCREEN_HEIGHT);
430 -    
431 -    glEnd();
432 -
433 -    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
434 -  }
435 -
436 -  assert_gl("drawing");
437 -
438 -  SDL_GL_SwapBuffers();
439 +  SDL_Flip(screen);
440  }
441  
442  void
443 @@ -467,9 +436,5 @@
444  DrawingContext::set_target(Target target)
445  {
446    this->target = target;
447 -  if(target == LIGHTMAP)
448 -    requests = &lightmap_requests;
449 -  else
450 -    requests = &drawing_requests;
451  }
452  
453 diff -aur supertux/src/video/drawing_context.hpp supertux-nogl/src/video/drawing_context.hpp
454 --- supertux/src/video/drawing_context.hpp      2006-07-03 02:00:48.000000000 +0200
455 +++ supertux-nogl/src/video/drawing_context.hpp 2006-07-03 02:00:29.000000000 +0200
456 @@ -24,7 +24,6 @@
457  #include <string>
458  #include <stdint.h>
459  
460 -#include <GL/gl.h>
461  #include <SDL.h>
462  #include <stdint.h>
463  #include <memory>
464 @@ -35,8 +34,9 @@
465  #include "font.hpp"
466  #include "color.hpp"
467  
468 +#include "glutil.hpp"
469 +
470  class Surface;
471 -class Texture;
472  
473  // some constants for predefined layer values
474  enum {
475 @@ -214,16 +214,12 @@
476    void draw_filled_rect(DrawingRequest& request);
477    
478    DrawingRequests drawing_requests;
479 -  DrawingRequests lightmap_requests;
480  
481    DrawingRequests* requests;
482  
483    SDL_Surface* screen;
484    Target target;
485    std::vector<Target> target_stack;
486 -  Texture* lightmap;
487 -  int lightmap_width, lightmap_height;
488 -  float lightmap_uv_right, lightmap_uv_bottom;
489  };
490  
491  #endif
492 diff -aur supertux/src/video/glutil.hpp supertux-nogl/src/video/glutil.hpp
493 --- supertux/src/video/glutil.hpp       2006-07-03 02:00:48.000000000 +0200
494 +++ supertux-nogl/src/video/glutil.hpp  2006-07-03 02:00:29.000000000 +0200
495 @@ -21,58 +21,11 @@
496  
497  #include <sstream>
498  #include <stdexcept>
499 -#include <GL/gl.h>
500  
501 -static inline void check_gl_error(const char* message)
502 -{
503 -#ifdef DEBUG
504 -  GLenum error = glGetError();
505 -  if(error != GL_NO_ERROR) {
506 -    std::ostringstream msg;
507 -    msg << "OpenGLError while '" << message << "': ";
508 -    switch(error) {
509 -      case GL_INVALID_ENUM:
510 -        msg << "INVALID_ENUM: An unacceptable value is specified for an "
511 -               "enumerated argument.";
512 -        break;
513 -      case GL_INVALID_VALUE:
514 -        msg << "INVALID_VALUE: A numeric argument is out of range.";
515 -        break;
516 -      case GL_INVALID_OPERATION:
517 -        msg << "INVALID_OPERATION: The specified operation is not allowed "
518 -               "in the current state.";
519 -        break;
520 -      case GL_STACK_OVERFLOW:
521 -        msg << "STACK_OVERFLOW: This command would cause a stack overflow.";
522 -        break;
523 -      case GL_STACK_UNDERFLOW:
524 -        msg << "STACK_UNDERFLOW: This command would cause a stack underflow.";
525 -        break;
526 -      case GL_OUT_OF_MEMORY:
527 -        msg << "OUT_OF_MEMORY: There is not enough memory left to execute the "
528 -               "command.";
529 -        break;
530 -#ifdef GL_TABLE_TOO_LARGE
531 -      case GL_TABLE_TOO_LARGE:
532 -        msg << "TABLE_TOO_LARGE: table is too large";
533 -        break;
534 -#endif                        
535 -      default:
536 -        msg << "Unknown error (code " << error << ")";
537 -    }
538 -        
539 -    throw std::runtime_error(msg.str());
540 -  }
541 -#endif
542 -}
543 -
544 -static inline void assert_gl(const char* message)
545 -{
546 -#ifdef DEBUG
547 -  check_gl_error(message);
548 -#else
549 -  (void) message;
550 -#endif
551 -}
552 +#define GLenum int
553 +#define GLint int
554 +#define GL_SRC_ALPHA 0
555 +#define GL_ONE_MINUS_SRC_ALPHA 1
556 +#define GL_RGBA 2
557  
558  #endif
559 diff -aur supertux/src/video/surface.cpp supertux-nogl/src/video/surface.cpp
560 --- supertux/src/video/surface.cpp      2006-07-03 02:00:48.000000000 +0200
561 +++ supertux-nogl/src/video/surface.cpp 2006-07-03 02:00:29.000000000 +0200
562 @@ -28,6 +28,7 @@
563  
564  #include <SDL.h>
565  #include <SDL_image.h>
566 +#include <SDL_rotozoom.h>
567  
568  #include "gameconfig.hpp"
569  #include "physfs/physfs_sdl.hpp"
570 @@ -41,13 +42,13 @@
571  {
572    texture = texture_manager->get(file);
573    texture->ref();
574 -  uv_left = 0;
575 -  uv_top = 0;
576 -  uv_right = texture->get_uv_right();
577 -  uv_bottom = texture->get_uv_bottom();
578  
579 -  width = texture->get_image_width();
580 -  height = texture->get_image_height();
581 +  offsetx = 0;
582 +  offsety = 0;
583 +  width = static_cast<int>(texture->get_image_width());
584 +  height = static_cast<int>(texture->get_image_height());
585 +
586 +  flipx = false;
587  }
588  
589  Surface::Surface(const std::string& file, int x, int y, int w, int h)
590 @@ -55,15 +56,12 @@
591    texture = texture_manager->get(file);
592    texture->ref();
593  
594 -  float tex_w = static_cast<float> (texture->get_width());
595 -  float tex_h = static_cast<float> (texture->get_height());
596 -  uv_left = static_cast<float>(x) / tex_w;
597 -  uv_top = static_cast<float>(y) / tex_h;
598 -  uv_right = static_cast<float>(x+w) / tex_w;
599 -  uv_bottom = static_cast<float>(y+h) / tex_h;
600 -
601 +  offsetx = x;
602 +  offsety = y;
603    width = w;
604    height = h;
605 +
606 +  flipx = false;
607  }
608  
609  Surface::Surface(const Surface& other)
610 @@ -71,12 +69,12 @@
611    texture = other.texture;
612    texture->ref();
613  
614 -  uv_left = other.uv_left;
615 -  uv_top = other.uv_top;
616 -  uv_right = other.uv_right;
617 -  uv_bottom = other.uv_bottom;
618 +  offsetx = other.offsetx;
619 +  offsety = other.offsety;
620    width = other.width;
621    height = other.height;
622 +
623 +  flipx = other.flipx;
624  }
625  
626  const Surface&
627 @@ -86,52 +84,33 @@
628    texture->unref();
629    texture = other.texture;
630  
631 -  uv_left = other.uv_left;
632 -  uv_top = other.uv_top;
633 -  uv_right = other.uv_right;
634 -  uv_bottom = other.uv_bottom;
635 +  offsetx = other.offsetx;
636 +  offsety = other.offsety;
637    width = other.width;
638    height = other.height;
639  
640 +  flipx = other.flipx;
641 +
642    return *this;
643  }
644  
645  Surface::~Surface()
646  {
647    texture->unref();
648 +
649 +  for (std::list<TransformedSurface*>::iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
650 +    SDL_FreeSurface((*i)->surface);
651 +    delete (*i);
652 +  }
653  }
654  
655  void
656  Surface::hflip()
657  {
658 -  std::swap(uv_left, uv_right);
659 +  flipx = !flipx;
660  }
661  
662 -static inline void intern_draw(float left, float top, float right, float bottom,                               float uv_left, float uv_top,
663 -                               float uv_right, float uv_bottom,
664 -                               DrawingEffect effect)
665 -{
666 -  if(effect & HORIZONTAL_FLIP)
667 -    std::swap(uv_left, uv_right);
668 -  if(effect & VERTICAL_FLIP) {
669 -    std::swap(uv_top, uv_bottom);
670 -  }
671 -  
672 -  glBegin(GL_QUADS);
673 -  glTexCoord2f(uv_left, uv_top);
674 -  glVertex2f(left, top);
675 -  
676 -  glTexCoord2f(uv_right, uv_top);
677 -  glVertex2f(right, top);
678 -
679 -  glTexCoord2f(uv_right, uv_bottom);
680 -  glVertex2f(right, bottom);
681 -
682 -  glTexCoord2f(uv_left, uv_bottom);
683 -  glVertex2f(left, bottom);
684 -  glEnd();
685 -}
686 -
687 +/*
688  static inline void intern_draw2(float left, float top, float right, float bottom,
689                                  float uv_left, float uv_top,
690                                  float uv_right, float uv_bottom,
691 @@ -182,51 +161,77 @@
692    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
693    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
694  }
695 +*/
696  
697  void
698 -Surface::draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const
699 +Surface::draw(float x, float y, float alpha, float, const Color&, const Blend&, DrawingEffect effect) const
700  {
701 -  glColor4f(1.0f, 1.0f, 1.0f, alpha);
702 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
703 -
704 -  intern_draw2(x, y,
705 -               x + width, y + height,
706 -               uv_left, uv_top, uv_right, uv_bottom, 
707 -               angle,
708 -               color,
709 -               blend, 
710 -               effect);
711 +  draw_part(0, 0, x, y, width, height, alpha, effect);
712  }
713  
714  void
715  Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
716  {
717 -  glColor4f(1.0f, 1.0f, 1.0f, alpha);
718 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
719 -
720 -  intern_draw(x, y,
721 -              x + width, y + height,
722 -              uv_left, uv_top, uv_right, uv_bottom, effect);
723 +  draw_part(0, 0, x, y, width, height, alpha, effect);
724  }
725  
726  void
727  Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
728 -                   float width, float height, float alpha,
729 +                   float width, float height, float,
730                     DrawingEffect effect) const
731  {
732 -  float uv_width = uv_right - uv_left;
733 -  float uv_height = uv_bottom - uv_top;
734 -  
735 -  float uv_left = this->uv_left + (uv_width * src_x) / this->width;
736 -  float uv_top = this->uv_top + (uv_height * src_y) / this->height;
737 -  float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
738 -  float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
739 -  
740 -  glColor4f(1.0f, 1.0f, 1.0f, alpha);
741 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());  
742 -  
743 -  intern_draw(dst_x, dst_y,
744 -              dst_x + width, dst_y + height,
745 -              uv_left, uv_top, uv_right, uv_bottom, effect);
746 +  //FIXME: support parameter "alpha"
747 +  SDL_Surface* surface = texture->getSurface();
748 +
749 +  // get and check SDL_Surface
750 +  if (surface == 0) {
751 +    std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
752 +    return;
753 +  }    
754 +
755 +  SDL_Surface* transformedSurface = surface;
756 +
757 +  if (flipx) effect = HORIZONTAL_FLIP;
758 +
759 +  if (effect != NO_EFFECT) {
760 +    transformedSurface = 0;
761 +
762 +    // check if we have this effect buffered
763 +    for (std::list<TransformedSurface*>::const_iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
764 +      if ((*i)->effect == effect) transformedSurface = (*i)->surface;
765 +    }
766 +
767 +    // if not: transform and buffer
768 +    if (!transformedSurface) {
769 +      if (effect == HORIZONTAL_FLIP) transformedSurface = zoomSurface(surface, -1, 1, 0);
770 +      if (effect == VERTICAL_FLIP) transformedSurface = zoomSurface(surface, 1, -1, 0);
771 +      if (transformedSurface == 0) {
772 +        std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
773 +        return;
774 +      }        
775 +      TransformedSurface* su = new TransformedSurface();
776 +      su->surface = transformedSurface;
777 +      su->effect = effect;
778 +
779 +      transformedSurfaces.push_front(su);
780 +    }
781 +  }
782 +
783 +  int ox = offsetx; if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(surface->w) - (ox+static_cast<int>(width));
784 +  int oy = offsety; if (effect == VERTICAL_FLIP) oy = static_cast<int>(surface->h) - (oy+static_cast<int>(height));
785 +  // draw surface to screen
786 +  SDL_Surface* screen = SDL_GetVideoSurface();
787 +
788 +  SDL_Rect srcRect;
789 +  srcRect.x = static_cast<int>(ox+src_x);
790 +  srcRect.y = static_cast<int>(oy+src_y);
791 +  srcRect.w = static_cast<int>(width);
792 +  srcRect.h = static_cast<int>(height);
793 +
794 +  SDL_Rect dstRect;
795 +  dstRect.x = static_cast<int>(dst_x);
796 +  dstRect.y = static_cast<int>(dst_y);
797 +
798 +  SDL_BlitSurface(transformedSurface, &srcRect, screen, &dstRect);
799  }
800  
801 diff -aur supertux/src/video/surface.hpp supertux-nogl/src/video/surface.hpp
802 --- supertux/src/video/surface.hpp      2006-07-03 02:00:48.000000000 +0200
803 +++ supertux-nogl/src/video/surface.hpp 2006-07-03 02:00:29.000000000 +0200
804 @@ -20,7 +20,9 @@
805  #ifndef __SURFACE_HPP__
806  #define __SURFACE_HPP__
807  
808 +#include <SDL_image.h>
809  #include <string>
810 +#include <list>
811  
812  class Color;
813  class Blend;
814 @@ -37,6 +39,15 @@
815  };
816  
817  /**
818 + * Helper class to buffer a pre-transformed SDL_Surface
819 + */
820 +class TransformedSurface {
821 +    public:
822 +       SDL_Surface* surface;
823 +       DrawingEffect effect;
824 +};
825 +
826 +/**
827   * A rectangular image.
828   * The class basically holds a reference to a texture with additional UV
829   * coordinates that specify a rectangular area on this texture
830 @@ -48,19 +59,26 @@
831    friend class Font;
832    ImageTexture* texture;
833  
834 -  float uv_left;
835 -  float uv_top;
836 -  float uv_right;
837 -  float uv_bottom;
838 +  bool flipx;
839  
840 +  /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
841    void draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const;
842 +
843 +  /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
844    void draw(float x, float y, float alpha, DrawingEffect effect) const;
845 +
846 +  /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
847    void draw_part(float src_x, float src_y, float dst_x, float dst_y,
848                   float width, float height,
849                   float alpha, DrawingEffect effect) const;
850  
851 -  float width;
852 -  float height;
853 +  int offsetx; /**< Region in ::surface to be used for blitting */
854 +  int offsety; /**< Region in ::surface to be used for blitting */
855 +  int width;   /**< Region in ::surface to be used for blitting */
856 +  int height;  /**< Region in ::surface to be used for blitting */
857 +
858 +  mutable std::list<TransformedSurface*> transformedSurfaces; /**< Cache for pre-transformed surfaces */
859 +
860  public:
861    Surface(const std::string& file);
862    Surface(const std::string& file, int x, int y, int w, int h);
863 diff -aur supertux/src/video/texture.cpp supertux-nogl/src/video/texture.cpp
864 --- supertux/src/video/texture.cpp      2006-07-03 02:00:48.000000000 +0200
865 +++ supertux-nogl/src/video/texture.cpp 2006-07-03 02:00:29.000000000 +0200
866 @@ -21,7 +21,6 @@
867  
868  #include "texture.hpp"
869  
870 -#include <GL/gl.h>
871  #include <assert.h>
872  #include "glutil.hpp"
873  
874 @@ -30,81 +29,37 @@
875    return (v & (v-1)) == 0;
876  }
877  
878 -Texture::Texture(unsigned int w, unsigned int h, GLenum glformat)
879 +Texture::Texture(unsigned int w, unsigned int h, GLenum)
880  {
881    assert(is_power_of_2(w));
882    assert(is_power_of_2(h));
883  
884    this->width = w;
885    this->height = h;
886 -  
887 -  assert_gl("before creating texture");
888 -  glGenTextures(1, &handle);
889 -  
890 -  try {
891 -    glBindTexture(GL_TEXTURE_2D, handle);
892 -
893 -    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
894 -                 GL_UNSIGNED_BYTE, 0);
895 -
896 -    set_texture_params();
897 -  } catch(...) {
898 -    glDeleteTextures(1, &handle);
899 -    throw;
900 -  }
901 +
902 +  surface = 0;
903  }
904  
905 -Texture::Texture(SDL_Surface* image, GLenum glformat)
906 +Texture::Texture(SDL_Surface* image, GLenum)
907  {
908    const SDL_PixelFormat* format = image->format;
909    if(!is_power_of_2(image->w) || !is_power_of_2(image->h))
910      throw std::runtime_error("image has no power of 2 size");
911    if(format->BitsPerPixel != 24 && format->BitsPerPixel != 32)
912      throw std::runtime_error("image has no 24 or 32 bit color depth");
913 -  
914 +
915    this->width = image->w;
916    this->height = image->h;
917  
918 -  assert_gl("before creating texture");
919 -  glGenTextures(1, &handle);
920 -  
921 -  try {
922 -    GLenum sdl_format;
923 -    if(format->BytesPerPixel == 3)
924 -      sdl_format = GL_RGB;
925 -    else if(format->BytesPerPixel == 4)
926 -      sdl_format = GL_RGBA;
927 -    else
928 -      assert(false);
929 -
930 -    glBindTexture(GL_TEXTURE_2D, handle);
931 -    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
932 -    glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
933 -    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
934 -            GL_UNSIGNED_BYTE, image->pixels);
935 -
936 -    assert_gl("creating texture");
937 -
938 -    set_texture_params();    
939 -  } catch(...) {
940 -    glDeleteTextures(1, &handle);
941 -    throw;
942 -  }
943 +  surface = SDL_DisplayFormatAlpha(image);
944  }
945  
946  Texture::~Texture()
947  {
948 -  glDeleteTextures(1, &handle);
949  }
950  
951  void
952  Texture::set_texture_params()
953  {
954 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
955 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
956 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
957 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
958 -
959 -  assert_gl("set texture params");
960  }
961  
962 diff -aur supertux/src/video/texture.hpp supertux-nogl/src/video/texture.hpp
963 --- supertux/src/video/texture.hpp      2006-07-03 02:00:48.000000000 +0200
964 +++ supertux-nogl/src/video/texture.hpp 2006-07-03 02:00:29.000000000 +0200
965 @@ -21,7 +21,7 @@
966  #define __TEXTURE_HPP__
967  
968  #include <SDL.h>
969 -#include <GL/gl.h>
970 +#include "glutil.hpp"
971  
972  /**
973   * This class is a wrapper around a texture handle. It stores the texture width
974 @@ -31,8 +31,9 @@
975  class Texture
976  {
977  protected:
978 +  SDL_Surface* surface; /**< non-GL branch stores optimized surface */
979 +
980    friend class TextureManager;
981 -  GLuint handle;
982    unsigned int width;
983    unsigned int height;
984  
985 @@ -41,11 +42,6 @@
986    Texture(SDL_Surface* surface, GLenum glformat);
987    virtual ~Texture();
988    
989 -  GLuint get_handle() const
990 -  {
991 -    return handle;
992 -  }
993 -
994    unsigned int get_width() const
995    {
996      return width;
997 @@ -56,6 +52,14 @@
998      return height;
999    }
1000  
1001 +  SDL_Surface* getSurface() {
1002 +    return surface;
1003 +  }
1004 +
1005 +  void setSurface(SDL_Surface* surface) {
1006 +    this->surface = surface;
1007 +  }
1008 +
1009  private:
1010    void set_texture_params();
1011  };
1012 diff -aur supertux/src/video/texture_manager.cpp supertux-nogl/src/video/texture_manager.cpp
1013 --- supertux/src/video/texture_manager.cpp      2006-07-03 02:00:48.000000000 +0200
1014 +++ supertux-nogl/src/video/texture_manager.cpp 2006-07-03 02:00:29.000000000 +0200
1015 @@ -24,8 +24,6 @@
1016  #include <assert.h>
1017  #include <SDL.h>
1018  #include <SDL_image.h>
1019 -#include <GL/gl.h>
1020 -#include <GL/glext.h>
1021  #include <iostream>
1022  #include <sstream>
1023  #include <stdexcept>
1024 @@ -145,12 +143,6 @@
1025  void
1026  TextureManager::save_textures()
1027  {
1028 -  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1029 -  glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
1030 -  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1031 -  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1032 -  glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
1033 -  glPixelStorei(GL_PACK_ALIGNMENT, 1);
1034    for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
1035      save_texture(*i);
1036    }
1037 @@ -165,75 +157,16 @@
1038  {
1039    SavedTexture saved_texture;
1040    saved_texture.texture = texture;
1041 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1042 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
1043 -                           &saved_texture.width);
1044 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
1045 -                           &saved_texture.height);
1046 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
1047 -                           &saved_texture.border);
1048 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1049 -                      &saved_texture.min_filter);
1050 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1051 -                      &saved_texture.mag_filter);
1052 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1053 -                      &saved_texture.wrap_s);
1054 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1055 -                      &saved_texture.wrap_t);
1056  
1057    size_t pixelssize = saved_texture.width * saved_texture.height * 4;
1058    saved_texture.pixels = new char[pixelssize];
1059 -  
1060 -  glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1061 -                saved_texture.pixels);
1062  
1063    saved_textures.push_back(saved_texture);
1064 -
1065 -  glDeleteTextures(1, &(texture->handle));
1066 -  texture->handle = 0;
1067 -
1068 -  assert_gl("retrieving texture for save");
1069  }
1070  
1071  void
1072  TextureManager::reload_textures()
1073  {
1074 -  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1075 -  glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1076 -  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1077 -  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1078 -  glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1079 -  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1080 -  
1081 -  for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1082 -      i != saved_textures.end(); ++i) {
1083 -    SavedTexture& saved_texture = *i;
1084 -    
1085 -    GLuint handle;
1086 -    glGenTextures(1, &handle);
1087 -    assert_gl("creating texture handle");
1088 -
1089 -    glBindTexture(GL_TEXTURE_2D, handle);
1090 -    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1091 -                 saved_texture.width, saved_texture.height,
1092 -                 saved_texture.border, GL_RGBA,
1093 -                 GL_UNSIGNED_BYTE, saved_texture.pixels);
1094 -    delete[] saved_texture.pixels;
1095 -    assert_gl("uploading texture pixel data");
1096 -
1097 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1098 -                    saved_texture.min_filter);
1099 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1100 -                    saved_texture.mag_filter);
1101 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1102 -                    saved_texture.wrap_s);
1103 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1104 -                    saved_texture.wrap_t);
1105 -
1106 -    assert_gl("setting texture_params");
1107 -    saved_texture.texture->handle = handle;
1108 -  }
1109 -
1110    saved_textures.clear();
1111  }
1112  
1113 diff -aur supertux/src/video/texture_manager.hpp supertux-nogl/src/video/texture_manager.hpp
1114 --- supertux/src/video/texture_manager.hpp      2006-07-03 02:00:48.000000000 +0200
1115 +++ supertux-nogl/src/video/texture_manager.hpp 2006-07-03 02:00:29.000000000 +0200
1116 @@ -20,7 +20,7 @@
1117  #ifndef __IMAGE_TEXTURE_MANAGER_HPP__
1118  #define __IMAGE_TEXTURE_MANAGER_HPP__
1119  
1120 -#include <GL/gl.h>
1121 +#include "video/glutil.hpp"
1122  #include <string>
1123  #include <vector>
1124  #include <map>