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