Exclude end sequence from focus lose code
[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 #  Installing the patch should be pretty straightforward. Simply run the
28 #  following command prior to running autogen.sh and configure:
29 #
30 #  patch -p0 < contrib/supertux-nogl.diff
31 #
32 #  This patch works for revision 5072. It may break for later revisions.
33 #
34 # -----------------------------------------------------------------------------
35 Index: src/gameconfig.hpp
36 ===================================================================
37 --- src/gameconfig.hpp  (revision 5071)
38 +++ src/gameconfig.hpp  (working copy)
39 @@ -19,6 +19,8 @@
40  #ifndef SUPERTUX_CONFIG_H
41  #define SUPERTUX_CONFIG_H
42  
43 +#include <config.h>
44 +
45  #include <string>
46  
47  class Config
48 @@ -39,6 +41,9 @@
49    float aspect_ratio;
50  
51    bool use_fullscreen;
52 +#ifdef HAVE_OPENGL
53 +  bool use_opengl;
54 +#endif
55    bool try_vsync;
56    bool show_fps;
57    bool sound_enabled;
58 Index: src/video/drawing_context.cpp
59 ===================================================================
60 --- src/video/drawing_context.cpp       (revision 5071)
61 +++ src/video/drawing_context.cpp       (working copy)
62 @@ -23,17 +23,16 @@
63  #include <cassert>
64  #include <iostream>
65  #include <SDL_image.h>
66 -#include <GL/gl.h>
67  #include <sstream>
68  #include <iomanip>
69  #include <physfs.h>
70  
71 +#include "glutil.hpp"
72  #include "drawing_context.hpp"
73  #include "surface.hpp"
74  #include "font.hpp"
75  #include "main.hpp"
76  #include "gameconfig.hpp"
77 -#include "glutil.hpp"
78  #include "texture.hpp"
79  #include "texture_manager.hpp"
80  #include "obstack/obstackpp.hpp"
81 @@ -113,6 +112,7 @@
82  {
83    screen = SDL_GetVideoSurface();
84  
85 +#ifdef HAVE_OPENGL
86    lightmap_width = screen->w / LIGHTMAP_DIV;
87    lightmap_height = screen->h / LIGHTMAP_DIV;
88    unsigned int width = next_po2(lightmap_width);
89 @@ -123,6 +123,7 @@
90    lightmap_uv_right = static_cast<float>(lightmap_width) / static_cast<float>(width);
91    lightmap_uv_bottom = static_cast<float>(lightmap_height) / static_cast<float>(height);
92    texture_manager->register_texture(lightmap);
93 +#endif
94  
95    requests = &drawing_requests;
96  
97 @@ -133,8 +134,10 @@
98  {
99    obstack_free(&obst, NULL);
100  
101 +#ifdef HAVE_OPENGL
102    texture_manager->remove_texture(lightmap);
103    delete lightmap;
104 +#endif
105  }
106  
107  void
108 @@ -338,15 +341,31 @@
109    const GetLightRequest* getlightrequest 
110      = (GetLightRequest*) request.request_data;
111  
112 -  float pixels[3];
113 -  for( int i = 0; i<3; i++)
114 -    pixels[i] = 0.0f; //set to black
115 +#ifdef HAVE_OPENGL
116 +  if(config->use_opengl)
117 +  {
118 +    float pixels[3];
119 +    for( int i = 0; i<3; i++)
120 +      pixels[i] = 0.0f; //set to black
121  
122 -  float posX = request.pos.x * lightmap_width / SCREEN_WIDTH;
123 -  float posY = screen->h - request.pos.y * lightmap_height / SCREEN_HEIGHT;
124 -  glReadPixels((GLint) posX, (GLint) posY , 1, 1, GL_RGB, GL_FLOAT, pixels);
125 +    float posX = request.pos.x * lightmap_width / SCREEN_WIDTH;
126 +    float posY = screen->h - request.pos.y * lightmap_height / SCREEN_HEIGHT;
127 +    glReadPixels((GLint) posX, (GLint) posY , 1, 1, GL_RGB, GL_FLOAT, pixels);
128      *(getlightrequest->color_ptr) = Color( pixels[0], pixels[1], pixels[2]);
129 -  //printf("get_light %f/%f =>%f/%f r%f g%f b%f\n", request.pos.x, request.pos.y, posX, posY, pixels[0], pixels[1], pixels[2]);
130 +    //printf("get_light %f/%f =>%f/%f r%f g%f b%f\n", request.pos.x, request.pos.y, posX, posY, pixels[0], pixels[1], pixels[2]);
131 +  }
132 +  else
133 +#endif
134 +  {
135 +    // FIXME: implement properly for SDL
136 +    static int i = 0;
137 +    i += 1; i &= 0xFFFF;
138 +    if (i & 0x8000) {
139 +      *(getlightrequest->color_ptr) = Color(0.0f, 0.0f, 0.0f);
140 +    } else {
141 +      *(getlightrequest->color_ptr) = Color(1.0f, 1.0f, 1.0f);
142 +    }
143 +  }
144  }
145  
146  void
147 @@ -370,17 +389,50 @@
148    const Color& top = gradientrequest->top;
149    const Color& bottom = gradientrequest->bottom;
150  
151 -  glDisable(GL_TEXTURE_2D);
152 -  glBegin(GL_QUADS);
153 -  glColor4f(top.red, top.green, top.blue, top.alpha);
154 -  glVertex2f(0, 0);
155 -  glVertex2f(SCREEN_WIDTH, 0);
156 -  glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
157 -  glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
158 -  glVertex2f(0, SCREEN_HEIGHT);
159 -  glEnd();
160 -  glEnable(GL_TEXTURE_2D);
161 -  glColor4f(1, 1, 1, 1);
162 +#ifdef HAVE_OPENGL
163 +  if(config->use_opengl)
164 +  {
165 +    glDisable(GL_TEXTURE_2D);
166 +    glBegin(GL_QUADS);
167 +    glColor4f(top.red, top.green, top.blue, top.alpha);
168 +    glVertex2f(0, 0);
169 +    glVertex2f(SCREEN_WIDTH, 0);
170 +    glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
171 +    glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
172 +    glVertex2f(0, SCREEN_HEIGHT);
173 +    glEnd();
174 +    glEnable(GL_TEXTURE_2D);
175 +    glColor4f(1, 1, 1, 1);
176 +  }
177 +  else
178 +#endif
179 +  {
180 +    for(int y = 0;y < screen->h;++y)
181 +    {
182 +      Uint8 r = (Uint8)((((float)(top.red-bottom.red)/(0-screen->h)) * y + top.red) * 255);
183 +      Uint8 g = (Uint8)((((float)(top.green-bottom.green)/(0-screen->h)) * y + top.green) * 255);
184 +      Uint8 b = (Uint8)((((float)(top.blue-bottom.blue)/(0-screen->h)) * y + top.blue) * 255);
185 +      Uint8 a = (Uint8)((((float)(top.alpha-bottom.alpha)/(0-screen->h)) * y + top.alpha) * 255);
186 +      Uint32 color = SDL_MapRGB(screen->format, r, g, b);
187 +
188 +      SDL_Rect rect;
189 +      rect.x = 0;
190 +      rect.y = y;
191 +      rect.w = screen->w;
192 +      rect.h = 1;
193 +
194 +      if(a == SDL_ALPHA_OPAQUE) {
195 +        SDL_FillRect(screen, &rect, color);
196 +      } else if(a != SDL_ALPHA_TRANSPARENT) {
197 +        SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
198 +
199 +        SDL_FillRect(temp, 0, color);
200 +        SDL_SetAlpha(temp, SDL_SRCALPHA, a);
201 +        SDL_BlitSurface(temp, 0, screen, &rect);
202 +        SDL_FreeSurface(temp);
203 +      }
204 +    }
205 +  }
206  }
207  
208  void
209 @@ -398,29 +450,76 @@
210    const FillRectRequest* fillrectrequest
211      = (FillRectRequest*) request.request_data;
212  
213 -  float x = request.pos.x;
214 -  float y = request.pos.y;
215 -  float w = fillrectrequest->size.x;
216 -  float h = fillrectrequest->size.y;
217 +#ifdef HAVE_OPENGL
218 +  if(config->use_opengl)
219 +  {
220 +    float x = request.pos.x;
221 +    float y = request.pos.y;
222 +    float w = fillrectrequest->size.x;
223 +    float h = fillrectrequest->size.y;
224  
225 -  glDisable(GL_TEXTURE_2D);
226 -  glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
227 -            fillrectrequest->color.blue, fillrectrequest->color.alpha);
228 +    glDisable(GL_TEXTURE_2D);
229 +    glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
230 +              fillrectrequest->color.blue, fillrectrequest->color.alpha);
231  
232 -  glBegin(GL_QUADS);
233 -  glVertex2f(x, y);
234 -  glVertex2f(x+w, y);
235 -  glVertex2f(x+w, y+h);
236 -  glVertex2f(x, y+h);
237 -  glEnd();
238 -  glEnable(GL_TEXTURE_2D);
239 -  
240 -  glColor4f(1, 1, 1, 1);
241 +    glBegin(GL_QUADS);
242 +    glVertex2f(x, y);
243 +    glVertex2f(x+w, y);
244 +    glVertex2f(x+w, y+h);
245 +    glVertex2f(x, y+h);
246 +    glEnd();
247 +    glEnable(GL_TEXTURE_2D);
248 +    glColor4f(1, 1, 1, 1);
249 +  }
250 +  else
251 +#endif
252 +  {
253 +    float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
254 +    float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
255 +    int numerator;
256 +    int denominator;
257 +    if(xfactor < yfactor)
258 +    {
259 +      numerator = config->screenwidth;
260 +      denominator = SCREEN_WIDTH;
261 +    }
262 +    else
263 +    {
264 +      numerator = config->screenheight;
265 +      denominator = SCREEN_HEIGHT;
266 +    }
267 +
268 +    SDL_Rect rect;
269 +    rect.x = (Sint16)request.pos.x * numerator / denominator;
270 +    rect.y = (Sint16)request.pos.y * numerator / denominator;
271 +    rect.w = (Uint16)fillrectrequest->size.x * numerator / denominator;
272 +    rect.h = (Uint16)fillrectrequest->size.y * numerator / denominator;
273 +    Uint8 r = static_cast<Uint8>(fillrectrequest->color.red * 255);
274 +    Uint8 g = static_cast<Uint8>(fillrectrequest->color.green * 255);
275 +    Uint8 b = static_cast<Uint8>(fillrectrequest->color.blue * 255);
276 +    Uint8 a = static_cast<Uint8>(fillrectrequest->color.alpha * 255);
277 +    Uint32 color = SDL_MapRGB(screen->format, r, g, b);
278 +    if(a == SDL_ALPHA_OPAQUE) {
279 +      SDL_FillRect(screen, &rect, color);
280 +    } else if(a != SDL_ALPHA_TRANSPARENT) {
281 +      SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
282 +
283 +      SDL_FillRect(temp, 0, color);
284 +      SDL_SetAlpha(temp, SDL_SRCALPHA, a);
285 +      SDL_BlitSurface(temp, 0, screen, &rect);
286 +      SDL_FreeSurface(temp);
287 +    }
288 +  }
289  }
290  
291  void
292 +#ifdef HAVE_OPENGL
293  DrawingContext::draw_lightmap(const DrawingRequest& request) const
294 +#else
295 +DrawingContext::draw_lightmap(const DrawingRequest&) const
296 +#endif
297  {
298 +#ifdef HAVE_OPENGL
299    const Texture* texture = reinterpret_cast<Texture*> (request.request_data);
300  
301    // multiple the lightmap with the framebuffer
302 @@ -444,6 +543,7 @@
303    glEnd();
304  
305    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
306 +#endif
307  }
308  
309  void
310 @@ -462,29 +562,38 @@
311  
312    // PART1: create lightmap
313    if(use_lightmap) {
314 -    glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
315 -    glMatrixMode(GL_PROJECTION);
316 -    glLoadIdentity();
317 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
318 -    glMatrixMode(GL_MODELVIEW);
319 -    glLoadIdentity();
320 +#ifdef HAVE_OPENGL
321 +    if(config->use_opengl)
322 +    {
323 +      glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
324 +      glMatrixMode(GL_PROJECTION);
325 +      glLoadIdentity();
326 +      glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
327 +      glMatrixMode(GL_MODELVIEW);
328 +      glLoadIdentity();
329  
330 -    glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
331 -    glClear(GL_COLOR_BUFFER_BIT);
332 -    handle_drawing_requests(lightmap_requests);
333 -    lightmap_requests.clear();
334 +      glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
335 +      glClear(GL_COLOR_BUFFER_BIT);
336 +      handle_drawing_requests(lightmap_requests);
337 +      lightmap_requests.clear();
338  
339 -    glDisable(GL_BLEND);
340 -    glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
341 -    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
342 +      glDisable(GL_BLEND);
343 +      glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
344 +      glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
345  
346 -    glViewport(0, 0, screen->w, screen->h);
347 -    glMatrixMode(GL_PROJECTION);
348 -    glLoadIdentity();
349 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
350 -    glMatrixMode(GL_MODELVIEW);
351 -    glLoadIdentity();
352 -    glEnable(GL_BLEND);
353 +      glViewport(0, 0, screen->w, screen->h);
354 +      glMatrixMode(GL_PROJECTION);
355 +      glLoadIdentity();
356 +      glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
357 +      glMatrixMode(GL_MODELVIEW);
358 +      glLoadIdentity();
359 +      glEnable(GL_BLEND);
360 +    }
361 +    else
362 +#endif
363 +    {
364 +      // FIXME: SDL alternative
365 +    }
366  
367      // add a lightmap drawing request into the queue
368      DrawingRequest* request = new(obst) DrawingRequest();
369 @@ -499,7 +608,12 @@
370    drawing_requests.clear();
371    obstack_free(&obst, NULL);
372    obstack_init(&obst);
373 -  assert_gl("drawing");
374 +#ifdef HAVE_OPENGL
375 +  if(config->use_opengl)
376 +  {
377 +    assert_gl("drawing");
378 +  }
379 +#endif
380  
381    // if a screenshot was requested, take one
382    if (screenshot_requested) {
383 @@ -507,7 +621,16 @@
384      screenshot_requested = false;
385    }
386  
387 -  SDL_GL_SwapBuffers();
388 +#ifdef HAVE_OPENGL
389 +  if(config->use_opengl)
390 +  {
391 +    SDL_GL_SwapBuffers();
392 +  }
393 +  else
394 +#endif
395 +  {
396 +    SDL_Flip(screen);
397 +  }
398  }
399  
400  class RequestPtrCompare
401 @@ -644,36 +767,47 @@
402  {
403    // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it?
404  
405 -  // create surface to hold screenshot
406 -  #if SDL_BYTEORDER == SDL_BIG_ENDIAN
407 -  SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
408 -  #else
409 -  SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
410 -  #endif
411 -  if (!shot_surf) {
412 -    log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
413 -    return;
414 -  }
415 +  SDL_Surface *shot_surf;
416 +#ifdef HAVE_OPENGL
417 +  if(config->use_opengl)
418 +  {
419 +    // create surface to hold screenshot
420 +    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
421 +    shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
422 +    #else
423 +    shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
424 +    #endif
425 +    if (!shot_surf) {
426 +      log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
427 +      return;
428 +    }
429  
430 -  // read pixels into array
431 -  char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
432 -  if (!pixels) {
433 -    log_warning << "Could not allocate memory to store screenshot" << std::endl;
434 -    SDL_FreeSurface(shot_surf);
435 -    return;
436 -  }
437 -  glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
438 +    // read pixels into array
439 +    char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
440 +    if (!pixels) {
441 +      log_warning << "Could not allocate memory to store screenshot" << std::endl;
442 +      SDL_FreeSurface(shot_surf);
443 +      return;
444 +    }
445 +    glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
446  
447 -  // copy array line-by-line
448 -  for (int i = 0; i < SCREEN_HEIGHT; i++) {
449 -    char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
450 -    char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
451 -    memcpy(dst, src, 3 * SCREEN_WIDTH);
452 +    // copy array line-by-line
453 +    for (int i = 0; i < SCREEN_HEIGHT; i++) {
454 +      char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
455 +      char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
456 +      memcpy(dst, src, 3 * SCREEN_WIDTH);
457 +    }
458 +
459 +    // free array
460 +    delete[](pixels);
461    }
462 +  else
463 +#endif
464 +  {
465 +    shot_surf = SDL_GetVideoSurface();
466 +    shot_surf->refcount++;
467 +  }
468  
469 -  // free array
470 -  delete[](pixels);
471 -
472    // save screenshot
473    static const std::string writeDir = PHYSFS_getWriteDir();
474    static const std::string dirSep = PHYSFS_getDirSeparator();
475 Index: src/video/texture_manager.hpp
476 ===================================================================
477 --- src/video/texture_manager.hpp       (revision 5071)
478 +++ src/video/texture_manager.hpp       (working copy)
479 @@ -20,7 +20,7 @@
480  #ifndef __IMAGE_TEXTURE_MANAGER_HPP__
481  #define __IMAGE_TEXTURE_MANAGER_HPP__
482  
483 -#include <GL/gl.h>
484 +#include "glutil.hpp"
485  #include <string>
486  #include <vector>
487  #include <map>
488 Index: src/video/texture.cpp
489 ===================================================================
490 --- src/video/texture.cpp       (revision 5071)
491 +++ src/video/texture.cpp       (working copy)
492 @@ -20,90 +20,134 @@
493  #include <config.h>
494  
495  #include "texture.hpp"
496 +#include "gameconfig.hpp"
497 +#include "glutil.hpp"
498  
499 -#include <GL/gl.h>
500  #include <assert.h>
501 -#include "glutil.hpp"
502 +#include <stdexcept>
503  
504  static inline bool is_power_of_2(int v)
505  {
506    return (v & (v-1)) == 0;
507  }
508  
509 +#ifdef HAVE_OPENGL
510  Texture::Texture(unsigned int w, unsigned int h, GLenum glformat)
511 +#else
512 +Texture::Texture(unsigned int w, unsigned int h, GLenum)
513 +#endif
514  {
515    assert(is_power_of_2(w));
516    assert(is_power_of_2(h));
517 +#ifdef HAVE_OPENGL
518 +  use_opengl = config->use_opengl;
519  
520 -  this->width = w;
521 -  this->height = h;
522 +  if(use_opengl)
523 +  {
524 +    surface.opengl.width = w;
525 +    surface.opengl.height = h;
526  
527 -  assert_gl("before creating texture");
528 -  glGenTextures(1, &handle);
529 +    assert_gl("before creating texture");
530 +    glGenTextures(1, &surface.opengl.handle);
531  
532 -  try {
533 -    glBindTexture(GL_TEXTURE_2D, handle);
534 +    try {
535 +      glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
536  
537 -    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
538 -                 GL_UNSIGNED_BYTE, 0);
539 +      glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
540 +                   surface.opengl.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
541  
542 -    set_texture_params();
543 -  } catch(...) {
544 -    glDeleteTextures(1, &handle);
545 -    throw;
546 +      set_texture_params();
547 +    } catch(...) {
548 +      glDeleteTextures(1, &surface.opengl.handle);
549 +      throw;
550 +    }
551    }
552 +  else
553 +#endif
554 +  {
555 +    surface.sdl = 0;
556 +  }
557  }
558  
559 +#ifdef HAVE_OPENGL
560  Texture::Texture(SDL_Surface* image, GLenum glformat)
561 +#else
562 +Texture::Texture(SDL_Surface* image, GLenum)
563 +#endif
564  {
565    const SDL_PixelFormat* format = image->format;
566    if(!is_power_of_2(image->w) || !is_power_of_2(image->h))
567 -    throw std::runtime_error("image has no power of 2 size");
568 +    throw std::runtime_error("image does not have power of 2 size");
569    if(format->BitsPerPixel != 24 && format->BitsPerPixel != 32)
570 -    throw std::runtime_error("image has no 24 or 32 bit color depth");
571 +    throw std::runtime_error("image does not have 24 or 32 bit color depth");
572 +#ifdef HAVE_OPENGL
573 +  use_opengl = config->use_opengl;
574  
575 -  this->width = image->w;
576 -  this->height = image->h;
577 +  if(use_opengl)
578 +  {
579 +    surface.opengl.width = image->w;
580 +    surface.opengl.height = image->h;
581  
582 -  assert_gl("before creating texture");
583 -  glGenTextures(1, &handle);
584 +    assert_gl("before creating texture");
585 +    glGenTextures(1, &surface.opengl.handle);
586  
587 -  try {
588 -    GLenum sdl_format;
589 -    if(format->BytesPerPixel == 3)
590 -      sdl_format = GL_RGB;
591 -    else if(format->BytesPerPixel == 4)
592 -      sdl_format = GL_RGBA;
593 -    else
594 -      assert(false);
595 +    try {
596 +      GLenum sdl_format;
597 +      if(format->BytesPerPixel == 3)
598 +        sdl_format = GL_RGB;
599 +      else if(format->BytesPerPixel == 4)
600 +        sdl_format = GL_RGBA;
601 +      else
602 +        assert(false);
603  
604 -    glBindTexture(GL_TEXTURE_2D, handle);
605 -    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
606 -    glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
607 -    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
608 -            GL_UNSIGNED_BYTE, image->pixels);
609 +      glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
610 +      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
611 +      glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
612 +      glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
613 +              surface.opengl.height, 0, sdl_format,
614 +              GL_UNSIGNED_BYTE, image->pixels);
615  
616 -    assert_gl("creating texture");
617 +      assert_gl("creating texture");
618  
619 -    set_texture_params();
620 -  } catch(...) {
621 -    glDeleteTextures(1, &handle);
622 -    throw;
623 +      set_texture_params();
624 +    } catch(...) {
625 +      glDeleteTextures(1, &surface.opengl.handle);
626 +      throw;
627 +    }
628    }
629 +  else
630 +#endif
631 +  {
632 +    surface.sdl = SDL_DisplayFormatAlpha(image);
633 +  }
634  }
635  
636  Texture::~Texture()
637  {
638 -  glDeleteTextures(1, &handle);
639 +#ifdef HAVE_OPENGL
640 +  if(use_opengl)
641 +  {
642 +    glDeleteTextures(1, &surface.opengl.handle);
643 +  }
644 +  else
645 +#endif
646 +  {
647 +    SDL_FreeSurface(surface.sdl);
648 +  }
649  }
650  
651  void
652  Texture::set_texture_params()
653  {
654 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
655 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
656 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
657 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
658 +#ifdef HAVE_OPENGL
659 +  if(use_opengl)
660 +  {
661 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
662 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
663 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
664 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
665  
666 -  assert_gl("set texture params");
667 +    assert_gl("set texture params");
668 +  }
669 +#endif
670  }
671 Index: src/video/drawing_context.hpp
672 ===================================================================
673 --- src/video/drawing_context.hpp       (revision 5071)
674 +++ src/video/drawing_context.hpp       (working copy)
675 @@ -25,9 +25,9 @@
676  
677  #include <stdint.h>
678  
679 -#include <GL/gl.h>
680  #include <SDL_video.h>
681  
682 +#include "glutil.hpp"
683  #include "obstack/obstack.h"
684  #include "math/vector.hpp"
685  #include "math/rect.hpp"
686 Index: src/video/glutil.hpp
687 ===================================================================
688 --- src/video/glutil.hpp        (revision 5071)
689 +++ src/video/glutil.hpp        (working copy)
690 @@ -19,9 +19,14 @@
691  #ifndef __GLUTIL_HPP__
692  #define __GLUTIL_HPP__
693  
694 +#include <config.h>
695 +
696 +#ifdef HAVE_OPENGL
697 +
698  #include <sstream>
699  #include <stdexcept>
700  #include <GL/gl.h>
701 +#include <GL/glext.h>
702  
703  static inline void check_gl_error(const char* message)
704  {
705 @@ -77,4 +82,15 @@
706  #endif
707  }
708  
709 +#else
710 +
711 +#define GLenum int
712 +#define GLint int
713 +#define GL_SRC_ALPHA 0
714 +#define GL_ONE_MINUS_SRC_ALPHA 1
715 +#define GL_RGBA 2
716 +#define GL_ONE 3
717 +
718  #endif
719 +
720 +#endif
721 Index: src/video/texture.hpp
722 ===================================================================
723 --- src/video/texture.hpp       (revision 5071)
724 +++ src/video/texture.hpp       (working copy)
725 @@ -20,9 +20,15 @@
726  #ifndef __TEXTURE_HPP__
727  #define __TEXTURE_HPP__
728  
729 +#include <config.h>
730 +
731 +#include <assert.h>
732 +
733  #include <SDL.h>
734 -#include <GL/gl.h>
735  
736 +#include "gameconfig.hpp"
737 +#include "glutil.hpp"
738 +
739  /**
740   * This class is a wrapper around a texture handle. It stores the texture width
741   * and height and provides convenience functions for uploading SDL_Surfaces
742 @@ -31,29 +37,82 @@
743  class Texture
744  {
745  protected:
746 -  friend class TextureManager;
747 -  GLuint handle;
748 -  unsigned int width;
749 -  unsigned int height;
750 +#ifdef HAVE_OPENGL
751 +  bool use_opengl;
752 +  union
753 +  {
754 +    struct
755 +    {
756 +      GLuint handle;
757 +      unsigned int width;
758 +      unsigned int height;
759 +    } opengl;
760 +#else
761 +  struct
762 +  {
763 +#endif
764 +    SDL_Surface *sdl;
765 +  } surface;
766  
767  public:
768    Texture(unsigned int width, unsigned int height, GLenum glformat);
769 -  Texture(SDL_Surface* surface, GLenum glformat);
770 +  Texture(SDL_Surface* sdlsurface, GLenum glformat);
771    virtual ~Texture();
772  
773 -  GLuint get_handle() const
774 +#ifdef HAVE_OPENGL
775 +  const GLuint &get_handle() const {
776 +    assert(use_opengl);
777 +    return surface.opengl.handle;
778 +  }
779 +
780 +  void set_handle(GLuint handle) {
781 +    assert(use_opengl);
782 +    surface.opengl.handle = handle;
783 +  }
784 +#endif
785 +
786 +  SDL_Surface *get_surface() const
787    {
788 -    return handle;
789 +#ifdef HAVE_OPENGL
790 +    assert(!use_opengl);
791 +#endif
792 +    return surface.sdl;
793    }
794  
795 +  void set_surface(SDL_Surface *sdlsurface)
796 +  {
797 +#ifdef HAVE_OPENGL
798 +    assert(!use_opengl);
799 +#endif
800 +    surface.sdl = sdlsurface;
801 +  }
802 +
803    unsigned int get_width() const
804    {
805 -    return width;
806 +#ifdef HAVE_OPENGL
807 +    if(use_opengl)
808 +    {
809 +      return surface.opengl.width;
810 +    }
811 +    else
812 +#endif
813 +    {
814 +      return surface.sdl->w;
815 +    }
816    }
817  
818    unsigned int get_height() const
819    {
820 -    return height;
821 +#ifdef HAVE_OPENGL
822 +    if(use_opengl)
823 +    {
824 +      return surface.opengl.height;
825 +    }
826 +    else
827 +#endif
828 +    {
829 +      return surface.sdl->h;
830 +    }
831    }
832  
833  private:
834 Index: src/video/surface.cpp
835 ===================================================================
836 --- src/video/surface.cpp       (revision 5071)
837 +++ src/video/surface.cpp       (working copy)
838 @@ -29,6 +29,7 @@
839  #include <SDL.h>
840  #include <SDL_image.h>
841  
842 +#include "main.hpp"
843  #include "gameconfig.hpp"
844  #include "physfs/physfs_sdl.hpp"
845  #include "video/surface.hpp"
846 @@ -41,13 +42,32 @@
847  {
848    texture = texture_manager->get(file);
849    texture->ref();
850 -  uv_left = 0;
851 -  uv_top = 0;
852 -  uv_right = texture->get_uv_right();
853 -  uv_bottom = texture->get_uv_bottom();
854  
855 -  width = texture->get_image_width();
856 -  height = texture->get_image_height();
857 +#ifdef HAVE_OPENGL
858 +  use_opengl = config->use_opengl;
859 +
860 +  if(use_opengl)
861 +  {
862 +    surface.opengl.uv_left = 0;
863 +    surface.opengl.uv_top = 0;
864 +    surface.opengl.uv_right = texture->get_uv_right();
865 +    surface.opengl.uv_bottom = texture->get_uv_bottom();
866 +
867 +    surface.opengl.width = texture->get_image_width();
868 +    surface.opengl.height = texture->get_image_height();
869 +  }
870 +  else
871 +#endif
872 +  {
873 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
874 +
875 +    surface.sdl.offsetx = 0;
876 +    surface.sdl.offsety = 0;
877 +    surface.sdl.width = static_cast<int>(texture->get_image_width());
878 +    surface.sdl.height = static_cast<int>(texture->get_image_height());
879 +
880 +    surface.sdl.flipx = false;
881 +  }
882  }
883  
884  Surface::Surface(const std::string& file, int x, int y, int w, int h)
885 @@ -55,15 +75,33 @@
886    texture = texture_manager->get(file);
887    texture->ref();
888  
889 -  float tex_w = static_cast<float> (texture->get_width());
890 -  float tex_h = static_cast<float> (texture->get_height());
891 -  uv_left = static_cast<float>(x) / tex_w;
892 -  uv_top = static_cast<float>(y) / tex_h;
893 -  uv_right = static_cast<float>(x+w) / tex_w;
894 -  uv_bottom = static_cast<float>(y+h) / tex_h;
895 +#ifdef HAVE_OPENGL
896 +  use_opengl = config->use_opengl;
897  
898 -  width = w;
899 -  height = h;
900 +  if(use_opengl)
901 +  {
902 +    float tex_w = static_cast<float> (texture->get_width());
903 +    float tex_h = static_cast<float> (texture->get_height());
904 +    surface.opengl.uv_left = static_cast<float>(x) / tex_w;
905 +    surface.opengl.uv_top = static_cast<float>(y) / tex_h;
906 +    surface.opengl.uv_right = static_cast<float>(x+w) / tex_w;
907 +    surface.opengl.uv_bottom = static_cast<float>(y+h) / tex_h;
908 +
909 +    surface.opengl.width = w;
910 +    surface.opengl.height = h;
911 +  }
912 +  else
913 +#endif
914 +  {
915 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
916 +
917 +    surface.sdl.offsetx = x;
918 +    surface.sdl.offsety = y;
919 +    surface.sdl.width = w;
920 +    surface.sdl.height = h;
921 +
922 +    surface.sdl.flipx = false;
923 +  }
924  }
925  
926  Surface::Surface(const Surface& other)
927 @@ -71,12 +109,30 @@
928    texture = other.texture;
929    texture->ref();
930  
931 -  uv_left = other.uv_left;
932 -  uv_top = other.uv_top;
933 -  uv_right = other.uv_right;
934 -  uv_bottom = other.uv_bottom;
935 -  width = other.width;
936 -  height = other.height;
937 +#ifdef HAVE_OPENGL
938 +  use_opengl = config->use_opengl;
939 +
940 +  if(use_opengl)
941 +  {
942 +    surface.opengl.uv_left = other.surface.opengl.uv_left;
943 +    surface.opengl.uv_top = other.surface.opengl.uv_top;
944 +    surface.opengl.uv_right = other.surface.opengl.uv_right;
945 +    surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
946 +    surface.opengl.width = other.surface.opengl.width;
947 +    surface.opengl.height = other.surface.opengl.height;
948 +  }
949 +  else
950 +#endif
951 +  {
952 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
953 +
954 +    surface.sdl.offsetx = other.surface.sdl.offsetx;
955 +    surface.sdl.offsety = other.surface.sdl.offsety;
956 +    surface.sdl.width = other.surface.sdl.width;
957 +    surface.sdl.height = other.surface.sdl.height;
958 +
959 +    surface.sdl.flipx = other.surface.sdl.flipx;
960 +  }
961  }
962  
963  const Surface&
964 @@ -86,148 +142,584 @@
965    texture->unref();
966    texture = other.texture;
967  
968 -  uv_left = other.uv_left;
969 -  uv_top = other.uv_top;
970 -  uv_right = other.uv_right;
971 -  uv_bottom = other.uv_bottom;
972 -  width = other.width;
973 -  height = other.height;
974 +#ifdef HAVE_OPENGL
975 +  use_opengl = config->use_opengl;
976  
977 +  if(use_opengl)
978 +  {
979 +    surface.opengl.uv_left = other.surface.opengl.uv_left;
980 +    surface.opengl.uv_top = other.surface.opengl.uv_top;
981 +    surface.opengl.uv_right = other.surface.opengl.uv_right;
982 +    surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
983 +    surface.opengl.width = other.surface.opengl.width;
984 +    surface.opengl.height = other.surface.opengl.height;
985 +  }
986 +  else
987 +#endif
988 +  {
989 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
990 +
991 +    surface.sdl.offsetx = other.surface.sdl.offsetx;
992 +    surface.sdl.offsety = other.surface.sdl.offsety;
993 +    surface.sdl.width = other.surface.sdl.width;
994 +    surface.sdl.height = other.surface.sdl.height;
995 +
996 +    surface.sdl.flipx = other.surface.sdl.flipx;
997 +  }
998 +
999    return *this;
1000  }
1001  
1002  Surface::~Surface()
1003  {
1004    texture->unref();
1005 +
1006 +#ifdef HAVE_OPENGL
1007 +  if(!use_opengl)
1008 +#endif
1009 +  {
1010 +    std::for_each(transforms, transforms + NUM_EFFECTS, SDL_FreeSurface);
1011 +  }
1012  }
1013  
1014  void
1015  Surface::hflip()
1016  {
1017 -  std::swap(uv_left, uv_right);
1018 +#ifdef HAVE_OPENGL
1019 +  if(use_opengl)
1020 +  {
1021 +    std::swap(surface.opengl.uv_left, surface.opengl.uv_right);
1022 +  }
1023 +  else
1024 +#endif
1025 +  {
1026 +    surface.sdl.flipx = !surface.sdl.flipx;
1027 +  }
1028  }
1029  
1030 -static inline void intern_draw(float left, float top, float right, float bottom,                               float uv_left, float uv_top,
1031 -                               float uv_right, float uv_bottom,
1032 -                               DrawingEffect effect)
1033 +#ifdef HAVE_OPENGL
1034 +namespace
1035  {
1036 -  if(effect & HORIZONTAL_FLIP)
1037 -    std::swap(uv_left, uv_right);
1038 -  if(effect & VERTICAL_FLIP) {
1039 -    std::swap(uv_top, uv_bottom);
1040 -  }
1041 +  inline void intern_draw(float left, float top, float right, float bottom,                               float uv_left, float uv_top,
1042 +                                 float uv_right, float uv_bottom,
1043 +                                 DrawingEffect effect)
1044 +  {
1045 +    if(effect & HORIZONTAL_FLIP)
1046 +      std::swap(uv_left, uv_right);
1047 +    if(effect & VERTICAL_FLIP) {
1048 +      std::swap(uv_top, uv_bottom);
1049 +    }
1050  
1051 -  glBegin(GL_QUADS);
1052 -  glTexCoord2f(uv_left, uv_top);
1053 -  glVertex2f(left, top);
1054 +    glBegin(GL_QUADS);
1055 +    glTexCoord2f(uv_left, uv_top);
1056 +    glVertex2f(left, top);
1057  
1058 -  glTexCoord2f(uv_right, uv_top);
1059 -  glVertex2f(right, top);
1060 +    glTexCoord2f(uv_right, uv_top);
1061 +    glVertex2f(right, top);
1062  
1063 -  glTexCoord2f(uv_right, uv_bottom);
1064 -  glVertex2f(right, bottom);
1065 +    glTexCoord2f(uv_right, uv_bottom);
1066 +    glVertex2f(right, bottom);
1067  
1068 -  glTexCoord2f(uv_left, uv_bottom);
1069 -  glVertex2f(left, bottom);
1070 -  glEnd();
1071 -}
1072 -
1073 -static inline void intern_draw2(float left, float top, float right, float bottom,
1074 -                                float uv_left, float uv_top,
1075 -                                float uv_right, float uv_bottom,
1076 -                                float angle, float alpha,
1077 -                                const Color& color,
1078 -                                const Blend& blend,
1079 -                                DrawingEffect effect)
1080 -{
1081 -  if(effect & HORIZONTAL_FLIP)
1082 -    std::swap(uv_left, uv_right);
1083 -  if(effect & VERTICAL_FLIP) {
1084 -    std::swap(uv_top, uv_bottom);
1085 +    glTexCoord2f(uv_left, uv_bottom);
1086 +    glVertex2f(left, bottom);
1087 +    glEnd();
1088    }
1089  
1090 -  float center_x = (left + right) / 2;
1091 -  float center_y = (top + bottom) / 2;
1092 +  inline void intern_draw2(float left, float top, float right, float bottom,
1093 +                                  float uv_left, float uv_top,
1094 +                                  float uv_right, float uv_bottom,
1095 +                                  float angle, float alpha,
1096 +                                  const Color& color,
1097 +                                  const Blend& blend,
1098 +                                  DrawingEffect effect)
1099 +  {
1100 +    if(effect & HORIZONTAL_FLIP)
1101 +      std::swap(uv_left, uv_right);
1102 +    if(effect & VERTICAL_FLIP) {
1103 +      std::swap(uv_top, uv_bottom);
1104 +    }
1105  
1106 -  float sa = sinf(angle/180.0f*M_PI);
1107 -  float ca = cosf(angle/180.0f*M_PI);
1108 +    float center_x = (left + right) / 2;
1109 +    float center_y = (top + bottom) / 2;
1110  
1111 -  left  -= center_x;
1112 -  right -= center_x;
1113 +    float sa = sinf(angle/180.0f*M_PI);
1114 +    float ca = cosf(angle/180.0f*M_PI);
1115  
1116 -  top    -= center_y;
1117 -  bottom -= center_y;
1118 +    left  -= center_x;
1119 +    right -= center_x;
1120  
1121 -  glBlendFunc(blend.sfactor, blend.dfactor);
1122 -  glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
1123 -  glBegin(GL_QUADS);
1124 -  glTexCoord2f(uv_left, uv_top);
1125 -  glVertex2f(left*ca - top*sa + center_x,
1126 -             left*sa + top*ca + center_y);
1127 +    top    -= center_y;
1128 +    bottom -= center_y;
1129  
1130 -  glTexCoord2f(uv_right, uv_top);
1131 -  glVertex2f(right*ca - top*sa + center_x,
1132 -             right*sa + top*ca + center_y);
1133 +    glBlendFunc(blend.sfactor, blend.dfactor);
1134 +    glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
1135 +    glBegin(GL_QUADS);
1136 +    glTexCoord2f(uv_left, uv_top);
1137 +    glVertex2f(left*ca - top*sa + center_x,
1138 +               left*sa + top*ca + center_y);
1139  
1140 -  glTexCoord2f(uv_right, uv_bottom);
1141 -  glVertex2f(right*ca - bottom*sa + center_x,
1142 -             right*sa + bottom*ca + center_y);
1143 +    glTexCoord2f(uv_right, uv_top);
1144 +    glVertex2f(right*ca - top*sa + center_x,
1145 +               right*sa + top*ca + center_y);
1146  
1147 -  glTexCoord2f(uv_left, uv_bottom);
1148 -  glVertex2f(left*ca - bottom*sa + center_x,
1149 -             left*sa + bottom*ca + center_y);
1150 -  glEnd();
1151 +    glTexCoord2f(uv_right, uv_bottom);
1152 +    glVertex2f(right*ca - bottom*sa + center_x,
1153 +               right*sa + bottom*ca + center_y);
1154  
1155 -  // FIXME: find a better way to restore the blend mode
1156 -  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1157 -  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1158 +    glTexCoord2f(uv_left, uv_bottom);
1159 +    glVertex2f(left*ca - bottom*sa + center_x,
1160 +               left*sa + bottom*ca + center_y);
1161 +    glEnd();
1162 +
1163 +    // FIXME: find a better way to restore the blend mode
1164 +    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1165 +    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1166 +  }
1167  }
1168 +#endif
1169  
1170  void
1171 -Surface::draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const
1172 +Surface::draw(float x, float y, float alpha,
1173 +#ifdef HAVE_OPENGL
1174 +              float angle, const Color& color, const Blend& blend,
1175 +#else
1176 +              float, const Color&, const Blend&,
1177 +#endif
1178 +              DrawingEffect effect) const
1179  {
1180 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1181 -
1182 -  intern_draw2(x, y,
1183 -               x + width, y + height,
1184 -               uv_left, uv_top, uv_right, uv_bottom,
1185 -               angle,
1186 -               alpha,
1187 -               color,
1188 -               blend,
1189 -               effect);
1190 +#ifdef HAVE_OPENGL
1191 +  if(use_opengl)
1192 +  {
1193 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1194 +    intern_draw2(x, y,
1195 +                 x + surface.opengl.width, y + surface.opengl.height,
1196 +                 surface.opengl.uv_left, surface.opengl.uv_top,
1197 +                 surface.opengl.uv_right, surface.opengl.uv_bottom,
1198 +                 angle,
1199 +                 alpha,
1200 +                 color,
1201 +                 blend,
1202 +                 effect);
1203 +  }
1204 +  else
1205 +#endif
1206 +  {
1207 +    draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
1208 +  }
1209  }
1210  
1211  void
1212  Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
1213  {
1214 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1215 +#ifdef HAVE_OPENGL
1216 +  if(use_opengl)
1217 +  {
1218 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1219 +    glColor4f(1, 1, 1, alpha);
1220 +    intern_draw(x, y,
1221 +                x + surface.opengl.width, y + surface.opengl.height,
1222 +                surface.opengl.uv_left, surface.opengl.uv_top,
1223 +                surface.opengl.uv_right, surface.opengl.uv_bottom, effect);
1224 +    glColor4f(1, 1, 1, 1);
1225 +  }
1226 +  else
1227 +#endif
1228 +  {
1229 +    draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
1230 +  }
1231 +}
1232  
1233 -  glColor4f(1, 1, 1, alpha);
1234 -  intern_draw(x, y,
1235 -              x + width, y + height,
1236 -              uv_left, uv_top, uv_right, uv_bottom, effect);
1237 -  glColor4f(1, 1, 1, 1);
1238 +namespace
1239 +{
1240 +#define BILINEAR
1241 +
1242 +#ifdef NAIVE
1243 +  SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
1244 +  {
1245 +    if(numerator == denominator)
1246 +    {
1247 +      src->refcount++;
1248 +      return src;
1249 +    }
1250 +    else
1251 +    {
1252 +      SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
1253 +      int bpp = dst->format->BytesPerPixel;
1254 +      for(int y = 0;y < dst->h;y++) {
1255 +        for(int x = 0;x < dst->w;x++) {
1256 +          Uint8 *srcpixel = (Uint8 *) src->pixels + (y * denominator / numerator) * src->pitch + (x * denominator / numerator) * bpp;
1257 +          Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
1258 +          switch(bpp) {
1259 +            case 4:
1260 +              dstpixel[3] = srcpixel[3];
1261 +            case 3:
1262 +              dstpixel[2] = srcpixel[2];
1263 +            case 2:
1264 +              dstpixel[1] = srcpixel[1];
1265 +            case 1:
1266 +              dstpixel[0] = srcpixel[0];
1267 +          }
1268 +        }
1269 +      }
1270 +      return dst;
1271 +    }
1272 +  }
1273 +#endif
1274 +
1275 +#ifdef BILINEAR
1276 +  void getpixel(SDL_Surface *src, int srcx, int srcy, Uint8 color[4])
1277 +  {
1278 +    int bpp = src->format->BytesPerPixel;
1279 +    Uint8 *srcpixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp;
1280 +    Uint32 mapped = 0;
1281 +    switch(bpp) {
1282 +      case 1:
1283 +        mapped = *srcpixel;
1284 +        break;
1285 +      case 2:
1286 +        mapped = *(Uint16 *)srcpixel;
1287 +        break;
1288 +      case 3:
1289 +#if SDL_BYTEORDER == SDL_BIG_ENDIAN
1290 +        mapped |= srcpixel[0] << 16;
1291 +        mapped |= srcpixel[1] << 8;
1292 +        mapped |= srcpixel[2] << 0;
1293 +#else
1294 +        mapped |= srcpixel[0] << 0;
1295 +        mapped |= srcpixel[1] << 8;
1296 +        mapped |= srcpixel[2] << 16;
1297 +#endif
1298 +        break;
1299 +      case 4:
1300 +        mapped = *(Uint32 *)srcpixel;
1301 +        break;
1302 +    }
1303 +    SDL_GetRGBA(mapped, src->format, &color[0], &color[1], &color[2], &color[3]);
1304 +  }
1305 +
1306 +  void merge(Uint8 color[4], Uint8 color0[4], Uint8 color1[4], int rem, int total)
1307 +  {
1308 +    color[0] = (color0[0] * (total - rem) + color1[0] * rem) / total;
1309 +    color[1] = (color0[1] * (total - rem) + color1[1] * rem) / total;
1310 +    color[2] = (color0[2] * (total - rem) + color1[2] * rem) / total;
1311 +    color[3] = (color0[3] * (total - rem) + color1[3] * rem) / total;
1312 +  }
1313 +
1314 +  SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
1315 +  {
1316 +    if(numerator == denominator)
1317 +    {
1318 +      src->refcount++;
1319 +      return src;
1320 +    }
1321 +    else
1322 +    {
1323 +      SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
1324 +      int bpp = dst->format->BytesPerPixel;
1325 +      for(int y = 0;y < dst->h;y++) {
1326 +        for(int x = 0;x < dst->w;x++) {
1327 +          int srcx = x * denominator / numerator;
1328 +          int srcy = y * denominator / numerator;
1329 +          Uint8 color00[4], color01[4], color10[4], color11[4];
1330 +          getpixel(src, srcx, srcy, color00);
1331 +          getpixel(src, srcx + 1, srcy, color01);
1332 +          getpixel(src, srcx, srcy + 1, color10);
1333 +          getpixel(src, srcx + 1, srcy + 1, color11);
1334 +          Uint8 color0[4], color1[4], color[4];
1335 +          int remx = x * denominator % numerator;
1336 +          merge(color0, color00, color01, remx, numerator);
1337 +          merge(color1, color10, color11, remx, numerator);
1338 +          int remy = y * denominator % numerator;
1339 +          merge(color, color0, color1, remy, numerator);
1340 +          Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
1341 +          Uint32 mapped = SDL_MapRGBA(dst->format, color[0], color[1], color[2], color[3]);
1342 +          switch(bpp) {
1343 +            case 1:
1344 +              *dstpixel = mapped;
1345 +              break;
1346 +            case 2:
1347 +              *(Uint16 *)dstpixel = mapped;
1348 +              break;
1349 +            case 3:
1350 +#if SDL_BYTEORDER == SDL_BIG_ENDIAN
1351 +              dstpixel[0] = (mapped >> 16) & 0xff;
1352 +              dstpixel[1] = (mapped >> 8) & 0xff;
1353 +              dstpixel[2] = (mapped >> 0) & 0xff;
1354 +#else
1355 +              dstpixel[0] = (mapped >> 0) & 0xff;
1356 +              dstpixel[1] = (mapped >> 8) & 0xff;
1357 +              dstpixel[2] = (mapped >> 16) & 0xff;
1358 +#endif
1359 +              break;
1360 +            case 4:
1361 +              *(Uint32 *)dstpixel = mapped;
1362 +              break;
1363 +          }
1364 +        }
1365 +      }
1366 +      return dst;
1367 +    }
1368 +  }
1369 +#endif
1370 +
1371 +  // FIXME: Horizontal and vertical line problem
1372 +#ifdef BRESENHAM
1373 +  void accumulate(SDL_Surface *src, int srcx, int srcy, int color[4], int weight)
1374 +  {
1375 +    if(srcx < 0 || srcy < 0 || weight == 0) {
1376 +      return;
1377 +    }
1378 +    int bpp = src->format->BytesPerPixel;
1379 +    Uint8 *srcpixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp;
1380 +    Uint32 mapped = 0;
1381 +    switch(bpp) {
1382 +      case 1:
1383 +        mapped = *srcpixel;
1384 +        break;
1385 +      case 2:
1386 +        mapped = *(Uint16 *)srcpixel;
1387 +        break;
1388 +      case 3:
1389 +#if SDL_BYTEORDER == SDL_BIG_ENDIAN
1390 +        mapped |= srcpixel[0] << 16;
1391 +        mapped |= srcpixel[1] << 8;
1392 +        mapped |= srcpixel[2] << 0;
1393 +#else
1394 +        mapped |= srcpixel[0] << 0;
1395 +        mapped |= srcpixel[1] << 8;
1396 +        mapped |= srcpixel[2] << 16;
1397 +#endif
1398 +        break;
1399 +      case 4:
1400 +        mapped = *(Uint32 *)srcpixel;
1401 +        break;
1402 +    }
1403 +    Uint8 red, green, blue, alpha;
1404 +    SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
1405 +    color[0] += red * weight;
1406 +    color[1] += green * weight;
1407 +    color[2] += blue * weight;
1408 +    color[3] += alpha * weight;
1409 +  }
1410 +
1411 +  void accumulate_line(SDL_Surface *src, int srcy, int line[][4], int linesize, int weight, int numerator, int denominator)
1412 +  {
1413 +    int intpart = denominator / numerator;
1414 +    int fractpart = denominator % numerator;
1415 +    for(int x = 0, xe = 0, srcx = 0;x < linesize;x++) {
1416 +      accumulate(src, srcx, srcy, line[x], (numerator - xe) * weight);
1417 +      srcx++;
1418 +      for(int i = 0;i < intpart - 1;i++) {
1419 +        accumulate(src, srcx, srcy, line[x], numerator * weight);
1420 +        srcx++;
1421 +      }
1422 +      xe += fractpart;
1423 +      if(xe >= numerator) {
1424 +        xe -= numerator;
1425 +        srcx++;
1426 +      }
1427 +      accumulate(src, srcx, srcy, line[x], xe * weight);
1428 +    }
1429 +  }
1430 +
1431 +  SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
1432 +  {
1433 +    if(numerator == denominator)
1434 +    {
1435 +      src->refcount++;
1436 +      return src;
1437 +    }
1438 +    else
1439 +    {
1440 +      SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
1441 +      int bpp = dst->format->BytesPerPixel;
1442 +      int intpart = denominator / numerator;
1443 +      int fractpart = denominator % numerator;
1444 +      for(int y = 0, ye = 0, srcy = 0;y < dst->h;y++) {
1445 +        int line[dst->w][4];
1446 +        memset(line, 0, sizeof(int) * dst->w * 4);
1447 +        accumulate_line(src, srcy, line, dst->w, numerator - ye, numerator, denominator);
1448 +        srcy++;
1449 +        for(int i = 0;i < intpart - 1;i++) {
1450 +          accumulate_line(src, srcy, line, dst->w, numerator, numerator, denominator);
1451 +          srcy++;
1452 +        }
1453 +        ye += fractpart;
1454 +        if(ye >= numerator) {
1455 +          ye -= numerator;
1456 +          srcy++;
1457 +        }
1458 +        accumulate_line(src, srcy, line, dst->w, ye, numerator, denominator);
1459 +        for(int x = 0;x < dst->w;x++) {
1460 +          Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
1461 +          Uint32 mapped = SDL_MapRGBA(dst->format, line[x][0] / (denominator * denominator), line[x][1] / (denominator * denominator), line[x][2] / (denominator * denominator), line[x][3] / (denominator * denominator));
1462 +          switch(bpp) {
1463 +            case 1:
1464 +              *dstpixel = mapped;
1465 +              break;
1466 +            case 2:
1467 +              *(Uint16 *)dstpixel = mapped;
1468 +              break;
1469 +            case 3:
1470 +#if SDL_BYTEORDER == SDL_BIG_ENDIAN
1471 +              dstpixel[0] = (mapped >> 16) & 0xff;
1472 +              dstpixel[1] = (mapped >> 8) & 0xff;
1473 +              dstpixel[2] = (mapped >> 0) & 0xff;
1474 +#else
1475 +              dstpixel[0] = (mapped >> 0) & 0xff;
1476 +              dstpixel[1] = (mapped >> 8) & 0xff;
1477 +              dstpixel[2] = (mapped >> 16) & 0xff;
1478 +#endif
1479 +              break;
1480 +            case 4:
1481 +              *(Uint32 *)dstpixel = mapped;
1482 +              break;
1483 +          }
1484 +        }
1485 +      }
1486 +      return dst;
1487 +    }
1488 +  }
1489 +#endif
1490 +
1491 +  SDL_Surface *horz_flip(SDL_Surface *src)
1492 +  {
1493 +    SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
1494 +    int bpp = dst->format->BytesPerPixel;
1495 +    for(int y = 0;y < dst->h;y++) {
1496 +      for(int x = 0;x < dst->w;x++) {
1497 +        Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
1498 +        Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + (dst->w - x - 1) * bpp;
1499 +        switch(bpp) {
1500 +          case 4:
1501 +            dstpixel[3] = srcpixel[3];
1502 +          case 3:
1503 +            dstpixel[2] = srcpixel[2];
1504 +          case 2:
1505 +            dstpixel[1] = srcpixel[1];
1506 +          case 1:
1507 +            dstpixel[0] = srcpixel[0];
1508 +        }
1509 +      }
1510 +    }
1511 +    return dst;
1512 +  }
1513 +
1514 +  SDL_Surface *vert_flip(SDL_Surface *src)
1515 +  {
1516 +    SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
1517 +    int bpp = dst->format->BytesPerPixel;
1518 +    for(int y = 0;y < dst->h;y++) {
1519 +      for(int x = 0;x < dst->w;x++) {
1520 +        Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
1521 +        Uint8 *dstpixel = (Uint8 *) dst->pixels + (dst->h - y - 1) * dst->pitch + x * bpp;
1522 +        switch(bpp) {
1523 +          case 4:
1524 +            dstpixel[3] = srcpixel[3];
1525 +          case 3:
1526 +            dstpixel[2] = srcpixel[2];
1527 +          case 2:
1528 +            dstpixel[1] = srcpixel[1];
1529 +          case 1:
1530 +            dstpixel[0] = srcpixel[0];
1531 +        }
1532 +      }
1533 +    }
1534 +    return dst;
1535 +  }
1536  }
1537  
1538  void
1539  Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
1540 +#ifdef HAVE_OPENGL
1541                     float width, float height, float alpha,
1542 +#else
1543 +                   float width, float height, float,
1544 +#endif
1545                     DrawingEffect effect) const
1546  {
1547 -  float uv_width = uv_right - uv_left;
1548 -  float uv_height = uv_bottom - uv_top;
1549 +#ifdef HAVE_OPENGL
1550 +  if(use_opengl)
1551 +  {
1552 +    float uv_width = surface.opengl.uv_right - surface.opengl.uv_left;
1553 +    float uv_height = surface.opengl.uv_bottom - surface.opengl.uv_top;
1554  
1555 -  float uv_left = this->uv_left + (uv_width * src_x) / this->width;
1556 -  float uv_top = this->uv_top + (uv_height * src_y) / this->height;
1557 -  float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
1558 -  float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
1559 +    float uv_left = surface.opengl.uv_left + (uv_width * src_x) / surface.opengl.width;
1560 +    float uv_top = surface.opengl.uv_top + (uv_height * src_y) / surface.opengl.height;
1561 +    float uv_right = surface.opengl.uv_left + (uv_width * (src_x + width)) / surface.opengl.width;
1562 +    float uv_bottom = surface.opengl.uv_top + (uv_height * (src_y + height)) / surface.opengl.height;
1563  
1564 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1565 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1566 +    glColor4f(1, 1, 1, alpha);
1567 +    intern_draw(dst_x, dst_y,
1568 +                dst_x + width, dst_y + height,
1569 +                uv_left, uv_top, uv_right, uv_bottom, effect);
1570 +    glColor4f(1, 1, 1, 1);
1571 +  }
1572 +  else
1573 +#endif
1574 +  {
1575 +    //FIXME: support parameter "alpha"
1576
1577 +    // get and check SDL_Surface
1578 +    if (texture->get_surface() == 0) {
1579 +      std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
1580 +      return;
1581 +    }  
1582  
1583 -  glColor4f(1, 1, 1, alpha);
1584 -  intern_draw(dst_x, dst_y,
1585 -              dst_x + width, dst_y + height,
1586 -              uv_left, uv_top, uv_right, uv_bottom, effect);
1587 -  glColor4f(1, 1, 1, 1);
1588 +    if (surface.sdl.flipx) effect = HORIZONTAL_FLIP;
1589 +
1590 +    float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
1591 +    float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
1592 +    int numerator;
1593 +    int denominator;
1594 +    if(xfactor < yfactor)
1595 +    {
1596 +      numerator = config->screenwidth;
1597 +      denominator = SCREEN_WIDTH;
1598 +    }
1599 +    else
1600 +    {
1601 +      numerator = config->screenheight;
1602 +      denominator = SCREEN_HEIGHT;
1603 +    }
1604 +
1605 +    if(transforms[effect] == 0) {
1606 +      if(transforms[NO_EFFECT] == 0) {
1607 +        transforms[NO_EFFECT] = scale(texture->get_surface(), numerator, denominator);
1608 +      }
1609 +      switch(effect) {
1610 +        case NO_EFFECT:
1611 +          break;
1612 +        case HORIZONTAL_FLIP:
1613 +          transforms[HORIZONTAL_FLIP] = horz_flip(transforms[NO_EFFECT]);
1614 +          break;
1615 +        case VERTICAL_FLIP:
1616 +          transforms[VERTICAL_FLIP] = vert_flip(transforms[NO_EFFECT]);
1617 +          break;
1618 +        default:
1619 +          std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
1620 +          return;
1621 +      }
1622 +    }
1623 +
1624 +    int ox = surface.sdl.offsetx;
1625 +    if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(texture->get_surface()->w) - (ox+static_cast<int>(width));
1626 +    int oy = surface.sdl.offsety;
1627 +    if (effect == VERTICAL_FLIP) oy = static_cast<int>(texture->get_surface()->h) - (oy+static_cast<int>(height));
1628 +    // draw surface to screen
1629 +    SDL_Surface* screen = SDL_GetVideoSurface();
1630 +
1631 +    SDL_Rect srcRect;
1632 +    srcRect.x = static_cast<int>((ox + src_x) * numerator / denominator);
1633 +    srcRect.y = static_cast<int>((oy + src_y) * numerator / denominator);
1634 +    srcRect.w = static_cast<int>(width * numerator / denominator);
1635 +    srcRect.h = static_cast<int>(height * numerator / denominator);
1636 +
1637 +    SDL_Rect dstRect;
1638 +    dstRect.x = static_cast<int>(dst_x * numerator / denominator);
1639 +    dstRect.y = static_cast<int>(dst_y * numerator / denominator);
1640 +
1641 +    SDL_BlitSurface(transforms[effect], &srcRect, screen, &dstRect);
1642 +  }
1643  }
1644 Index: src/video/texture_manager.cpp
1645 ===================================================================
1646 --- src/video/texture_manager.cpp       (revision 5071)
1647 +++ src/video/texture_manager.cpp       (working copy)
1648 @@ -24,14 +24,13 @@
1649  #include <assert.h>
1650  #include <SDL.h>
1651  #include <SDL_image.h>
1652 -#include <GL/gl.h>
1653 -#include <GL/glext.h>
1654  #include <iostream>
1655  #include <sstream>
1656  #include <stdexcept>
1657  #include "physfs/physfs_sdl.hpp"
1658  #include "image_texture.hpp"
1659  #include "glutil.hpp"
1660 +#include "gameconfig.hpp"
1661  #include "file_system.hpp"
1662  #include "log.hpp"
1663  
1664 @@ -149,12 +148,16 @@
1665  void
1666  TextureManager::save_textures()
1667  {
1668 -  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1669 -  glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
1670 -  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1671 -  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1672 -  glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
1673 -  glPixelStorei(GL_PACK_ALIGNMENT, 1);
1674 +#ifdef HAVE_OPENGL
1675 +  if(config->use_opengl) {
1676 +    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1677 +    glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
1678 +    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1679 +    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1680 +    glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
1681 +    glPixelStorei(GL_PACK_ALIGNMENT, 1);
1682 +  }
1683 +#endif
1684    for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
1685      save_texture(*i);
1686    }
1687 @@ -169,74 +172,90 @@
1688  {
1689    SavedTexture saved_texture;
1690    saved_texture.texture = texture;
1691 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1692 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
1693 -                           &saved_texture.width);
1694 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
1695 -                           &saved_texture.height);
1696 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
1697 -                           &saved_texture.border);
1698 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1699 -                      &saved_texture.min_filter);
1700 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1701 -                      &saved_texture.mag_filter);
1702 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1703 -                      &saved_texture.wrap_s);
1704 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1705 -                      &saved_texture.wrap_t);
1706 +#ifdef HAVE_OPENGL
1707 +  if(config->use_opengl) {
1708 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1709 +    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
1710 +                             &saved_texture.width);
1711 +    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
1712 +                             &saved_texture.height);
1713 +    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
1714 +                             &saved_texture.border);
1715 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1716 +                        &saved_texture.min_filter);
1717 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1718 +                        &saved_texture.mag_filter);
1719 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1720 +                        &saved_texture.wrap_s);
1721 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1722 +                        &saved_texture.wrap_t);
1723 +  }
1724 +#endif
1725  
1726    size_t pixelssize = saved_texture.width * saved_texture.height * 4;
1727    saved_texture.pixels = new char[pixelssize];
1728  
1729 -  glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1730 -                saved_texture.pixels);
1731 +#ifdef HAVE_OPENGL
1732 +  if(config->use_opengl) {
1733 +    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1734 +                  saved_texture.pixels);
1735 +  }
1736 +#endif
1737  
1738    saved_textures.push_back(saved_texture);
1739  
1740 -  glDeleteTextures(1, &(texture->handle));
1741 -  texture->handle = 0;
1742 +#ifdef HAVE_OPENGL
1743 +  if(config->use_opengl) {
1744 +    glDeleteTextures(1, &(texture->get_handle()));
1745 +    texture->set_handle(0);
1746  
1747 -  assert_gl("retrieving texture for save");
1748 +    assert_gl("retrieving texture for save");
1749 +  }
1750 +#endif
1751  }
1752  
1753  void
1754  TextureManager::reload_textures()
1755  {
1756 -  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1757 -  glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1758 -  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1759 -  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1760 -  glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1761 -  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1762 +#ifdef HAVE_OPENGL
1763 +  if(config->use_opengl) {
1764 +    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1765 +    glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1766 +    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1767 +    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1768 +    glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1769 +    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1770  
1771 -  for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1772 -      i != saved_textures.end(); ++i) {
1773 -    SavedTexture& saved_texture = *i;
1774 +    for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1775 +        i != saved_textures.end(); ++i) {
1776 +      SavedTexture& saved_texture = *i;
1777  
1778 -    GLuint handle;
1779 -    glGenTextures(1, &handle);
1780 -    assert_gl("creating texture handle");
1781 +      GLuint handle;
1782 +      glGenTextures(1, &handle);
1783 +      assert_gl("creating texture handle");
1784  
1785 -    glBindTexture(GL_TEXTURE_2D, handle);
1786 -    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1787 -                 saved_texture.width, saved_texture.height,
1788 -                 saved_texture.border, GL_RGBA,
1789 -                 GL_UNSIGNED_BYTE, saved_texture.pixels);
1790 -    delete[] saved_texture.pixels;
1791 -    assert_gl("uploading texture pixel data");
1792 +      glBindTexture(GL_TEXTURE_2D, handle);
1793 +      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1794 +                   saved_texture.width, saved_texture.height,
1795 +                   saved_texture.border, GL_RGBA,
1796 +                   GL_UNSIGNED_BYTE, saved_texture.pixels);
1797 +      delete[] saved_texture.pixels;
1798 +      assert_gl("uploading texture pixel data");
1799  
1800 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1801 -                    saved_texture.min_filter);
1802 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1803 -                    saved_texture.mag_filter);
1804 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1805 -                    saved_texture.wrap_s);
1806 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1807 -                    saved_texture.wrap_t);
1808 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1809 +                      saved_texture.min_filter);
1810 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1811 +                      saved_texture.mag_filter);
1812 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1813 +                      saved_texture.wrap_s);
1814 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1815 +                      saved_texture.wrap_t);
1816  
1817 -    assert_gl("setting texture_params");
1818 -    saved_texture.texture->handle = handle;
1819 +      assert_gl("setting texture_params");
1820 +      saved_texture.texture->set_handle(handle);
1821 +    }
1822    }
1823 +#endif
1824  
1825    saved_textures.clear();
1826  }
1827 Index: src/video/surface.hpp
1828 ===================================================================
1829 --- src/video/surface.hpp       (revision 5071)
1830 +++ src/video/surface.hpp       (working copy)
1831 @@ -20,7 +20,11 @@
1832  #ifndef __SURFACE_HPP__
1833  #define __SURFACE_HPP__
1834  
1835 +#include <config.h>
1836 +
1837  #include <string>
1838 +#include <SDL.h>
1839 +#include "gameconfig.hpp"
1840  #include "math/vector.hpp"
1841  
1842  class Color;
1843 @@ -30,11 +34,12 @@
1844  /// bitset for drawing effects
1845  enum DrawingEffect {
1846    /** Don't apply anything */
1847 -  NO_EFFECT       = 0x0000,
1848 +  NO_EFFECT,
1849    /** Draw the Surface upside down */
1850 -  VERTICAL_FLIP     = 0x0001,
1851 +  VERTICAL_FLIP,
1852    /** Draw the Surface from left to down */
1853 -  HORIZONTAL_FLIP   = 0x0002,
1854 +  HORIZONTAL_FLIP,
1855 +  NUM_EFFECTS
1856  };
1857  
1858  /**
1859 @@ -47,21 +52,43 @@
1860  private:
1861    friend class DrawingContext;
1862    friend class Font;
1863 -  ImageTexture* texture;
1864  
1865 -  float uv_left;
1866 -  float uv_top;
1867 -  float uv_right;
1868 -  float uv_bottom;
1869 -
1870    void draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const;
1871    void draw(float x, float y, float alpha, DrawingEffect effect) const;
1872    void draw_part(float src_x, float src_y, float dst_x, float dst_y,
1873                   float width, float height,
1874                   float alpha, DrawingEffect effect) const;
1875  
1876 -  float width;
1877 -  float height;
1878 +  ImageTexture* texture;
1879 +#ifdef HAVE_OPENGL
1880 +  bool use_opengl;
1881 +  union
1882 +  {
1883 +    struct
1884 +    {
1885 +      float uv_left;
1886 +      float uv_top;
1887 +      float uv_right;
1888 +      float uv_bottom;
1889 +
1890 +      float width;
1891 +      float height;
1892 +    } opengl;
1893 +#else
1894 +  struct
1895 +  {
1896 +#endif
1897 +    struct
1898 +    {
1899 +      bool flipx;
1900 +      int offsetx; /**< Region in ::surface to be used for blitting */
1901 +      int offsety; /**< Region in ::surface to be used for blitting */
1902 +      int width;   /**< Region in ::surface to be used for blitting */
1903 +      int height;  /**< Region in ::surface to be used for blitting */
1904 +    } sdl;
1905 +  } surface;
1906 +  mutable SDL_Surface *transforms[NUM_EFFECTS]; /**< Cache for pre-transformed surfaces */
1907 +
1908  public:
1909    Surface(const std::string& file);
1910    Surface(const std::string& file, int x, int y, int w, int h);
1911 @@ -75,12 +102,30 @@
1912  
1913    float get_width() const
1914    {
1915 -    return width;
1916 +#ifdef HAVE_OPENGL
1917 +    if(use_opengl)
1918 +    {
1919 +      return surface.opengl.width;
1920 +    }
1921 +    else
1922 +#endif
1923 +    {
1924 +      return surface.sdl.width;
1925 +    }
1926    }
1927  
1928    float get_height() const
1929    {
1930 -    return height;
1931 +#ifdef HAVE_OPENGL
1932 +    if(use_opengl)
1933 +    {
1934 +      return surface.opengl.height;
1935 +    }
1936 +    else
1937 +#endif
1938 +    {
1939 +      return surface.sdl.height;
1940 +    }
1941    }
1942  
1943    /**
1944 Index: src/gameconfig.cpp
1945 ===================================================================
1946 --- src/gameconfig.cpp  (revision 5071)
1947 +++ src/gameconfig.cpp  (working copy)
1948 @@ -36,6 +36,9 @@
1949  Config::Config()
1950  {
1951    use_fullscreen = true;
1952 +#ifdef HAVE_OPENGL
1953 +  use_opengl = true;
1954 +#endif
1955    try_vsync = true;
1956    show_fps = false;
1957    sound_enabled = true;
1958 @@ -70,7 +73,10 @@
1959    const lisp::Lisp* config_video_lisp = config_lisp->get_lisp("video");
1960    if(config_video_lisp) {
1961      config_video_lisp->get("fullscreen", use_fullscreen);
1962 -       config_video_lisp->get("vsync", try_vsync);
1963 +#ifdef HAVE_OPENGL
1964 +    config_video_lisp->get("opengl", use_opengl);
1965 +#endif
1966 +    config_video_lisp->get("vsync", try_vsync);
1967      config_video_lisp->get("width", screenwidth);
1968      config_video_lisp->get("height", screenheight);
1969      config_video_lisp->get("aspect_ratio", aspect_ratio);
1970 @@ -100,6 +106,9 @@
1971  
1972    writer.start_list("video");
1973    writer.write_bool("fullscreen", use_fullscreen);
1974 +#ifdef HAVE_OPENGL
1975 +  writer.write_bool("opengl", use_opengl);
1976 +#endif
1977    writer.write_bool("vsync", try_vsync);
1978    writer.write_int("width", screenwidth);
1979    writer.write_int("height", screenheight);
1980 Index: src/main.cpp
1981 ===================================================================
1982 --- src/main.cpp        (revision 5071)
1983 +++ src/main.cpp        (working copy)
1984 @@ -33,7 +33,6 @@
1985  #include <physfs.h>
1986  #include <SDL.h>
1987  #include <SDL_image.h>
1988 -#include <GL/gl.h>
1989  
1990  #include "gameconfig.hpp"
1991  #include "resources.hpp"
1992 @@ -383,7 +382,11 @@
1993    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
1994    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
1995  
1996 -  int flags = SDL_OPENGL;
1997 +#ifdef HAVE_OPENGL
1998 +  int flags = config->use_opengl ? SDL_OPENGL : SDL_SWSURFACE;
1999 +#else
2000 +  int flags = SDL_SWSURFACE;
2001 +#endif
2002    if(config->use_fullscreen)
2003      flags |= SDL_FULLSCREEN;
2004    int width = config->screenwidth;
2005 @@ -437,23 +440,28 @@
2006  
2007    log_info << (config->use_fullscreen?"fullscreen ":"window ") << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << " Ratio: " << aspect_ratio << "\n";
2008  
2009 -  // setup opengl state and transform
2010 -  glDisable(GL_DEPTH_TEST);
2011 -  glDisable(GL_CULL_FACE);
2012 -  glEnable(GL_TEXTURE_2D);
2013 -  glEnable(GL_BLEND);
2014 -  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2015 +#ifdef HAVE_OPENGL
2016 +  if(config->use_opengl)
2017 +  {
2018 +    // setup opengl state and transform
2019 +    glDisable(GL_DEPTH_TEST);
2020 +    glDisable(GL_CULL_FACE);
2021 +    glEnable(GL_TEXTURE_2D);
2022 +    glEnable(GL_BLEND);
2023 +    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2024  
2025 -  glViewport(0, 0, screen->w, screen->h);
2026 -  glMatrixMode(GL_PROJECTION);
2027 -  glLoadIdentity();
2028 -  // logical resolution here not real monitor resolution
2029 -  glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
2030 -  glMatrixMode(GL_MODELVIEW);
2031 -  glLoadIdentity();
2032 -  glTranslatef(0, 0, 0);
2033 +    glViewport(0, 0, screen->w, screen->h);
2034 +    glMatrixMode(GL_PROJECTION);
2035 +    glLoadIdentity();
2036 +    // logical resolution here not real monitor resolution
2037 +    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
2038 +    glMatrixMode(GL_MODELVIEW);
2039 +    glLoadIdentity();
2040 +    glTranslatef(0, 0, 0);
2041  
2042 -  check_gl_error("Setting up view matrices");
2043 +    check_gl_error("Setting up view matrices");
2044 +  }
2045 +#endif
2046  
2047    if(texture_manager != NULL)
2048      texture_manager->reload_textures();
2049 Index: configure.ac
2050 ===================================================================
2051 --- configure.ac        (revision 5071)
2052 +++ configure.ac        (working copy)
2053 @@ -154,9 +154,15 @@
2054           [AC_MSG_ERROR([Please install OpenAL])],
2055           [], [])
2056  
2057 -AX_CHECK_GL
2058 -if test "$no_gl" = "yes"; then
2059 -  AC_MSG_ERROR([Please install opengl libraries and headers])
2060 +AC_ARG_ENABLE(opengl,
2061 +              AC_HELP_STRING([--enable-opengl], [enable opengl support]),
2062 +              [enable_opengl=$enableval], [enable_opengl=yes])
2063 +
2064 +if test "$enable_opengl" = "yes"; then
2065 +  AX_CHECK_GL
2066 +  if test "$no_gl" != "yes"; then
2067 +    AC_DEFINE_UNQUOTED(HAVE_OPENGL, 1, Define if OpenGL is present on the system)
2068 +  fi
2069  fi
2070  
2071  dnl Checks for library functions.