Make nogl patch not need OpenGL at all
[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 5070. It may break for later revisions.
33 #
34 # -----------------------------------------------------------------------------
35 Index: src/gameconfig.hpp
36 ===================================================================
37 --- src/gameconfig.hpp  (revision 5069)
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 5069)
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,61 @@
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 +    SDL_Rect rect;
254 +    rect.x = (Sint16)request.pos.x;
255 +    rect.y = (Sint16)request.pos.y;
256 +    rect.w = (Uint16)fillrectrequest->size.x;
257 +    rect.h = (Uint16)fillrectrequest->size.y;
258 +    Uint8 r = static_cast<Uint8>(fillrectrequest->color.red * 255);
259 +    Uint8 g = static_cast<Uint8>(fillrectrequest->color.green * 255);
260 +    Uint8 b = static_cast<Uint8>(fillrectrequest->color.blue * 255);
261 +    Uint8 a = static_cast<Uint8>(fillrectrequest->color.alpha * 255);
262 +    Uint32 color = SDL_MapRGB(screen->format, r, g, b);
263 +    if(a == SDL_ALPHA_OPAQUE) {
264 +      SDL_FillRect(screen, &rect, color);
265 +    } else if(a != SDL_ALPHA_TRANSPARENT) {
266 +      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);
267 +
268 +      SDL_FillRect(temp, 0, color);
269 +      SDL_SetAlpha(temp, SDL_SRCALPHA, a);
270 +      SDL_BlitSurface(temp, 0, screen, &rect);
271 +      SDL_FreeSurface(temp);
272 +    }
273 +  }
274  }
275  
276  void
277 +#ifdef HAVE_OPENGL
278  DrawingContext::draw_lightmap(const DrawingRequest& request) const
279 +#else
280 +DrawingContext::draw_lightmap(const DrawingRequest&) const
281 +#endif
282  {
283 +#ifdef HAVE_OPENGL
284    const Texture* texture = reinterpret_cast<Texture*> (request.request_data);
285  
286    // multiple the lightmap with the framebuffer
287 @@ -444,6 +528,7 @@
288    glEnd();
289  
290    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
291 +#endif
292  }
293  
294  void
295 @@ -462,29 +547,38 @@
296  
297    // PART1: create lightmap
298    if(use_lightmap) {
299 -    glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
300 -    glMatrixMode(GL_PROJECTION);
301 -    glLoadIdentity();
302 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
303 -    glMatrixMode(GL_MODELVIEW);
304 -    glLoadIdentity();
305 +#ifdef HAVE_OPENGL
306 +    if(config->use_opengl)
307 +    {
308 +      glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
309 +      glMatrixMode(GL_PROJECTION);
310 +      glLoadIdentity();
311 +      glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
312 +      glMatrixMode(GL_MODELVIEW);
313 +      glLoadIdentity();
314  
315 -    glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
316 -    glClear(GL_COLOR_BUFFER_BIT);
317 -    handle_drawing_requests(lightmap_requests);
318 -    lightmap_requests.clear();
319 +      glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
320 +      glClear(GL_COLOR_BUFFER_BIT);
321 +      handle_drawing_requests(lightmap_requests);
322 +      lightmap_requests.clear();
323  
324 -    glDisable(GL_BLEND);
325 -    glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
326 -    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
327 +      glDisable(GL_BLEND);
328 +      glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
329 +      glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
330  
331 -    glViewport(0, 0, screen->w, screen->h);
332 -    glMatrixMode(GL_PROJECTION);
333 -    glLoadIdentity();
334 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
335 -    glMatrixMode(GL_MODELVIEW);
336 -    glLoadIdentity();
337 -    glEnable(GL_BLEND);
338 +      glViewport(0, 0, screen->w, screen->h);
339 +      glMatrixMode(GL_PROJECTION);
340 +      glLoadIdentity();
341 +      glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
342 +      glMatrixMode(GL_MODELVIEW);
343 +      glLoadIdentity();
344 +      glEnable(GL_BLEND);
345 +    }
346 +    else
347 +#endif
348 +    {
349 +      // FIXME: SDL alternative
350 +    }
351  
352      // add a lightmap drawing request into the queue
353      DrawingRequest* request = new(obst) DrawingRequest();
354 @@ -499,7 +593,12 @@
355    drawing_requests.clear();
356    obstack_free(&obst, NULL);
357    obstack_init(&obst);
358 -  assert_gl("drawing");
359 +#ifdef HAVE_OPENGL
360 +  if(config->use_opengl)
361 +  {
362 +    assert_gl("drawing");
363 +  }
364 +#endif
365  
366    // if a screenshot was requested, take one
367    if (screenshot_requested) {
368 @@ -507,7 +606,16 @@
369      screenshot_requested = false;
370    }
371  
372 -  SDL_GL_SwapBuffers();
373 +#ifdef HAVE_OPENGL
374 +  if(config->use_opengl)
375 +  {
376 +    SDL_GL_SwapBuffers();
377 +  }
378 +  else
379 +#endif
380 +  {
381 +    SDL_Flip(screen);
382 +  }
383  }
384  
385  class RequestPtrCompare
386 @@ -644,36 +752,47 @@
387  {
388    // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it?
389  
390 -  // create surface to hold screenshot
391 -  #if SDL_BYTEORDER == SDL_BIG_ENDIAN
392 -  SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
393 -  #else
394 -  SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
395 -  #endif
396 -  if (!shot_surf) {
397 -    log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
398 -    return;
399 -  }
400 +  SDL_Surface *shot_surf;
401 +#ifdef HAVE_OPENGL
402 +  if(config->use_opengl)
403 +  {
404 +    // create surface to hold screenshot
405 +    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
406 +    shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
407 +    #else
408 +    shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
409 +    #endif
410 +    if (!shot_surf) {
411 +      log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
412 +      return;
413 +    }
414  
415 -  // read pixels into array
416 -  char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
417 -  if (!pixels) {
418 -    log_warning << "Could not allocate memory to store screenshot" << std::endl;
419 -    SDL_FreeSurface(shot_surf);
420 -    return;
421 -  }
422 -  glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
423 +    // read pixels into array
424 +    char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
425 +    if (!pixels) {
426 +      log_warning << "Could not allocate memory to store screenshot" << std::endl;
427 +      SDL_FreeSurface(shot_surf);
428 +      return;
429 +    }
430 +    glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
431  
432 -  // copy array line-by-line
433 -  for (int i = 0; i < SCREEN_HEIGHT; i++) {
434 -    char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
435 -    char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
436 -    memcpy(dst, src, 3 * SCREEN_WIDTH);
437 +    // copy array line-by-line
438 +    for (int i = 0; i < SCREEN_HEIGHT; i++) {
439 +      char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
440 +      char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
441 +      memcpy(dst, src, 3 * SCREEN_WIDTH);
442 +    }
443 +
444 +    // free array
445 +    delete[](pixels);
446    }
447 +  else
448 +#endif
449 +  {
450 +    shot_surf = SDL_GetVideoSurface();
451 +    shot_surf->refcount++;
452 +  }
453  
454 -  // free array
455 -  delete[](pixels);
456 -
457    // save screenshot
458    static const std::string writeDir = PHYSFS_getWriteDir();
459    static const std::string dirSep = PHYSFS_getDirSeparator();
460 Index: src/video/texture_manager.hpp
461 ===================================================================
462 --- src/video/texture_manager.hpp       (revision 5069)
463 +++ src/video/texture_manager.hpp       (working copy)
464 @@ -20,7 +20,7 @@
465  #ifndef __IMAGE_TEXTURE_MANAGER_HPP__
466  #define __IMAGE_TEXTURE_MANAGER_HPP__
467  
468 -#include <GL/gl.h>
469 +#include "glutil.hpp"
470  #include <string>
471  #include <vector>
472  #include <map>
473 Index: src/video/texture.cpp
474 ===================================================================
475 --- src/video/texture.cpp       (revision 5069)
476 +++ src/video/texture.cpp       (working copy)
477 @@ -20,90 +20,134 @@
478  #include <config.h>
479  
480  #include "texture.hpp"
481 +#include "gameconfig.hpp"
482 +#include "glutil.hpp"
483  
484 -#include <GL/gl.h>
485  #include <assert.h>
486 -#include "glutil.hpp"
487 +#include <stdexcept>
488  
489  static inline bool is_power_of_2(int v)
490  {
491    return (v & (v-1)) == 0;
492  }
493  
494 +#ifdef HAVE_OPENGL
495  Texture::Texture(unsigned int w, unsigned int h, GLenum glformat)
496 +#else
497 +Texture::Texture(unsigned int w, unsigned int h, GLenum)
498 +#endif
499  {
500    assert(is_power_of_2(w));
501    assert(is_power_of_2(h));
502 +#ifdef HAVE_OPENGL
503 +  use_opengl = config->use_opengl;
504  
505 -  this->width = w;
506 -  this->height = h;
507 +  if(use_opengl)
508 +  {
509 +    surface.opengl.width = w;
510 +    surface.opengl.height = h;
511  
512 -  assert_gl("before creating texture");
513 -  glGenTextures(1, &handle);
514 +    assert_gl("before creating texture");
515 +    glGenTextures(1, &surface.opengl.handle);
516  
517 -  try {
518 -    glBindTexture(GL_TEXTURE_2D, handle);
519 +    try {
520 +      glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
521  
522 -    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
523 -                 GL_UNSIGNED_BYTE, 0);
524 +      glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
525 +                   surface.opengl.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
526  
527 -    set_texture_params();
528 -  } catch(...) {
529 -    glDeleteTextures(1, &handle);
530 -    throw;
531 +      set_texture_params();
532 +    } catch(...) {
533 +      glDeleteTextures(1, &surface.opengl.handle);
534 +      throw;
535 +    }
536    }
537 +  else
538 +#endif
539 +  {
540 +    surface.sdl = 0;
541 +  }
542  }
543  
544 +#ifdef HAVE_OPENGL
545  Texture::Texture(SDL_Surface* image, GLenum glformat)
546 +#else
547 +Texture::Texture(SDL_Surface* image, GLenum)
548 +#endif
549  {
550    const SDL_PixelFormat* format = image->format;
551    if(!is_power_of_2(image->w) || !is_power_of_2(image->h))
552 -    throw std::runtime_error("image has no power of 2 size");
553 +    throw std::runtime_error("image does not have power of 2 size");
554    if(format->BitsPerPixel != 24 && format->BitsPerPixel != 32)
555 -    throw std::runtime_error("image has no 24 or 32 bit color depth");
556 +    throw std::runtime_error("image does not have 24 or 32 bit color depth");
557 +#ifdef HAVE_OPENGL
558 +  use_opengl = config->use_opengl;
559  
560 -  this->width = image->w;
561 -  this->height = image->h;
562 +  if(use_opengl)
563 +  {
564 +    surface.opengl.width = image->w;
565 +    surface.opengl.height = image->h;
566  
567 -  assert_gl("before creating texture");
568 -  glGenTextures(1, &handle);
569 +    assert_gl("before creating texture");
570 +    glGenTextures(1, &surface.opengl.handle);
571  
572 -  try {
573 -    GLenum sdl_format;
574 -    if(format->BytesPerPixel == 3)
575 -      sdl_format = GL_RGB;
576 -    else if(format->BytesPerPixel == 4)
577 -      sdl_format = GL_RGBA;
578 -    else
579 -      assert(false);
580 +    try {
581 +      GLenum sdl_format;
582 +      if(format->BytesPerPixel == 3)
583 +        sdl_format = GL_RGB;
584 +      else if(format->BytesPerPixel == 4)
585 +        sdl_format = GL_RGBA;
586 +      else
587 +        assert(false);
588  
589 -    glBindTexture(GL_TEXTURE_2D, handle);
590 -    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
591 -    glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
592 -    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
593 -            GL_UNSIGNED_BYTE, image->pixels);
594 +      glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
595 +      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
596 +      glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
597 +      glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
598 +              surface.opengl.height, 0, sdl_format,
599 +              GL_UNSIGNED_BYTE, image->pixels);
600  
601 -    assert_gl("creating texture");
602 +      assert_gl("creating texture");
603  
604 -    set_texture_params();
605 -  } catch(...) {
606 -    glDeleteTextures(1, &handle);
607 -    throw;
608 +      set_texture_params();
609 +    } catch(...) {
610 +      glDeleteTextures(1, &surface.opengl.handle);
611 +      throw;
612 +    }
613    }
614 +  else
615 +#endif
616 +  {
617 +    surface.sdl = SDL_DisplayFormatAlpha(image);
618 +  }
619  }
620  
621  Texture::~Texture()
622  {
623 -  glDeleteTextures(1, &handle);
624 +#ifdef HAVE_OPENGL
625 +  if(use_opengl)
626 +  {
627 +    glDeleteTextures(1, &surface.opengl.handle);
628 +  }
629 +  else
630 +#endif
631 +  {
632 +    SDL_FreeSurface(surface.sdl);
633 +  }
634  }
635  
636  void
637  Texture::set_texture_params()
638  {
639 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
640 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
641 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
642 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
643 +#ifdef HAVE_OPENGL
644 +  if(use_opengl)
645 +  {
646 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
647 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
648 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
649 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
650  
651 -  assert_gl("set texture params");
652 +    assert_gl("set texture params");
653 +  }
654 +#endif
655  }
656 Index: src/video/drawing_context.hpp
657 ===================================================================
658 --- src/video/drawing_context.hpp       (revision 5069)
659 +++ src/video/drawing_context.hpp       (working copy)
660 @@ -25,9 +25,9 @@
661  
662  #include <stdint.h>
663  
664 -#include <GL/gl.h>
665  #include <SDL_video.h>
666  
667 +#include "glutil.hpp"
668  #include "obstack/obstack.h"
669  #include "math/vector.hpp"
670  #include "math/rect.hpp"
671 Index: src/video/glutil.hpp
672 ===================================================================
673 --- src/video/glutil.hpp        (revision 5069)
674 +++ src/video/glutil.hpp        (working copy)
675 @@ -19,9 +19,14 @@
676  #ifndef __GLUTIL_HPP__
677  #define __GLUTIL_HPP__
678  
679 +#include <config.h>
680 +
681 +#ifdef HAVE_OPENGL
682 +
683  #include <sstream>
684  #include <stdexcept>
685  #include <GL/gl.h>
686 +#include <GL/glext.h>
687  
688  static inline void check_gl_error(const char* message)
689  {
690 @@ -77,4 +82,15 @@
691  #endif
692  }
693  
694 +#else
695 +
696 +#define GLenum int
697 +#define GLint int
698 +#define GL_SRC_ALPHA 0
699 +#define GL_ONE_MINUS_SRC_ALPHA 1
700 +#define GL_RGBA 2
701 +#define GL_ONE 3
702 +
703  #endif
704 +
705 +#endif
706 Index: src/video/texture.hpp
707 ===================================================================
708 --- src/video/texture.hpp       (revision 5069)
709 +++ src/video/texture.hpp       (working copy)
710 @@ -20,9 +20,15 @@
711  #ifndef __TEXTURE_HPP__
712  #define __TEXTURE_HPP__
713  
714 +#include <config.h>
715 +
716 +#include <assert.h>
717 +
718  #include <SDL.h>
719 -#include <GL/gl.h>
720  
721 +#include "gameconfig.hpp"
722 +#include "glutil.hpp"
723 +
724  /**
725   * This class is a wrapper around a texture handle. It stores the texture width
726   * and height and provides convenience functions for uploading SDL_Surfaces
727 @@ -31,29 +37,82 @@
728  class Texture
729  {
730  protected:
731 -  friend class TextureManager;
732 -  GLuint handle;
733 -  unsigned int width;
734 -  unsigned int height;
735 +#ifdef HAVE_OPENGL
736 +  bool use_opengl;
737 +  union
738 +  {
739 +    struct
740 +    {
741 +      GLuint handle;
742 +      unsigned int width;
743 +      unsigned int height;
744 +    } opengl;
745 +#else
746 +  struct
747 +  {
748 +#endif
749 +    SDL_Surface *sdl;
750 +  } surface;
751  
752  public:
753    Texture(unsigned int width, unsigned int height, GLenum glformat);
754 -  Texture(SDL_Surface* surface, GLenum glformat);
755 +  Texture(SDL_Surface* sdlsurface, GLenum glformat);
756    virtual ~Texture();
757  
758 -  GLuint get_handle() const
759 +#ifdef HAVE_OPENGL
760 +  const GLuint &get_handle() const {
761 +    assert(use_opengl);
762 +    return surface.opengl.handle;
763 +  }
764 +
765 +  void set_handle(GLuint handle) {
766 +    assert(use_opengl);
767 +    surface.opengl.handle = handle;
768 +  }
769 +#endif
770 +
771 +  SDL_Surface *get_surface() const
772    {
773 -    return handle;
774 +#ifdef HAVE_OPENGL
775 +    assert(!use_opengl);
776 +#endif
777 +    return surface.sdl;
778    }
779  
780 +  void set_surface(SDL_Surface *sdlsurface)
781 +  {
782 +#ifdef HAVE_OPENGL
783 +    assert(!use_opengl);
784 +#endif
785 +    surface.sdl = sdlsurface;
786 +  }
787 +
788    unsigned int get_width() const
789    {
790 -    return width;
791 +#ifdef HAVE_OPENGL
792 +    if(use_opengl)
793 +    {
794 +      return surface.opengl.width;
795 +    }
796 +    else
797 +#endif
798 +    {
799 +      return surface.sdl->w;
800 +    }
801    }
802  
803    unsigned int get_height() const
804    {
805 -    return height;
806 +#ifdef HAVE_OPENGL
807 +    if(use_opengl)
808 +    {
809 +      return surface.opengl.height;
810 +    }
811 +    else
812 +#endif
813 +    {
814 +      return surface.sdl->h;
815 +    }
816    }
817  
818  private:
819 Index: src/video/surface.cpp
820 ===================================================================
821 --- src/video/surface.cpp       (revision 5069)
822 +++ src/video/surface.cpp       (working copy)
823 @@ -41,13 +41,32 @@
824  {
825    texture = texture_manager->get(file);
826    texture->ref();
827 -  uv_left = 0;
828 -  uv_top = 0;
829 -  uv_right = texture->get_uv_right();
830 -  uv_bottom = texture->get_uv_bottom();
831  
832 -  width = texture->get_image_width();
833 -  height = texture->get_image_height();
834 +#ifdef HAVE_OPENGL
835 +  use_opengl = config->use_opengl;
836 +
837 +  if(use_opengl)
838 +  {
839 +    surface.opengl.uv_left = 0;
840 +    surface.opengl.uv_top = 0;
841 +    surface.opengl.uv_right = texture->get_uv_right();
842 +    surface.opengl.uv_bottom = texture->get_uv_bottom();
843 +
844 +    surface.opengl.width = texture->get_image_width();
845 +    surface.opengl.height = texture->get_image_height();
846 +  }
847 +  else
848 +#endif
849 +  {
850 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
851 +
852 +    surface.sdl.offsetx = 0;
853 +    surface.sdl.offsety = 0;
854 +    surface.sdl.width = static_cast<int>(texture->get_image_width());
855 +    surface.sdl.height = static_cast<int>(texture->get_image_height());
856 +
857 +    surface.sdl.flipx = false;
858 +  }
859  }
860  
861  Surface::Surface(const std::string& file, int x, int y, int w, int h)
862 @@ -55,15 +74,33 @@
863    texture = texture_manager->get(file);
864    texture->ref();
865  
866 -  float tex_w = static_cast<float> (texture->get_width());
867 -  float tex_h = static_cast<float> (texture->get_height());
868 -  uv_left = static_cast<float>(x) / tex_w;
869 -  uv_top = static_cast<float>(y) / tex_h;
870 -  uv_right = static_cast<float>(x+w) / tex_w;
871 -  uv_bottom = static_cast<float>(y+h) / tex_h;
872 +#ifdef HAVE_OPENGL
873 +  use_opengl = config->use_opengl;
874  
875 -  width = w;
876 -  height = h;
877 +  if(use_opengl)
878 +  {
879 +    float tex_w = static_cast<float> (texture->get_width());
880 +    float tex_h = static_cast<float> (texture->get_height());
881 +    surface.opengl.uv_left = static_cast<float>(x) / tex_w;
882 +    surface.opengl.uv_top = static_cast<float>(y) / tex_h;
883 +    surface.opengl.uv_right = static_cast<float>(x+w) / tex_w;
884 +    surface.opengl.uv_bottom = static_cast<float>(y+h) / tex_h;
885 +
886 +    surface.opengl.width = w;
887 +    surface.opengl.height = h;
888 +  }
889 +  else
890 +#endif
891 +  {
892 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
893 +
894 +    surface.sdl.offsetx = x;
895 +    surface.sdl.offsety = y;
896 +    surface.sdl.width = w;
897 +    surface.sdl.height = h;
898 +
899 +    surface.sdl.flipx = false;
900 +  }
901  }
902  
903  Surface::Surface(const Surface& other)
904 @@ -71,12 +108,30 @@
905    texture = other.texture;
906    texture->ref();
907  
908 -  uv_left = other.uv_left;
909 -  uv_top = other.uv_top;
910 -  uv_right = other.uv_right;
911 -  uv_bottom = other.uv_bottom;
912 -  width = other.width;
913 -  height = other.height;
914 +#ifdef HAVE_OPENGL
915 +  use_opengl = config->use_opengl;
916 +
917 +  if(use_opengl)
918 +  {
919 +    surface.opengl.uv_left = other.surface.opengl.uv_left;
920 +    surface.opengl.uv_top = other.surface.opengl.uv_top;
921 +    surface.opengl.uv_right = other.surface.opengl.uv_right;
922 +    surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
923 +    surface.opengl.width = other.surface.opengl.width;
924 +    surface.opengl.height = other.surface.opengl.height;
925 +  }
926 +  else
927 +#endif
928 +  {
929 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
930 +
931 +    surface.sdl.offsetx = other.surface.sdl.offsetx;
932 +    surface.sdl.offsety = other.surface.sdl.offsety;
933 +    surface.sdl.width = other.surface.sdl.width;
934 +    surface.sdl.height = other.surface.sdl.height;
935 +
936 +    surface.sdl.flipx = other.surface.sdl.flipx;
937 +  }
938  }
939  
940  const Surface&
941 @@ -86,148 +141,329 @@
942    texture->unref();
943    texture = other.texture;
944  
945 -  uv_left = other.uv_left;
946 -  uv_top = other.uv_top;
947 -  uv_right = other.uv_right;
948 -  uv_bottom = other.uv_bottom;
949 -  width = other.width;
950 -  height = other.height;
951 +#ifdef HAVE_OPENGL
952 +  use_opengl = config->use_opengl;
953  
954 +  if(use_opengl)
955 +  {
956 +    surface.opengl.uv_left = other.surface.opengl.uv_left;
957 +    surface.opengl.uv_top = other.surface.opengl.uv_top;
958 +    surface.opengl.uv_right = other.surface.opengl.uv_right;
959 +    surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
960 +    surface.opengl.width = other.surface.opengl.width;
961 +    surface.opengl.height = other.surface.opengl.height;
962 +  }
963 +  else
964 +#endif
965 +  {
966 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
967 +
968 +    surface.sdl.offsetx = other.surface.sdl.offsetx;
969 +    surface.sdl.offsety = other.surface.sdl.offsety;
970 +    surface.sdl.width = other.surface.sdl.width;
971 +    surface.sdl.height = other.surface.sdl.height;
972 +
973 +    surface.sdl.flipx = other.surface.sdl.flipx;
974 +  }
975 +
976    return *this;
977  }
978  
979  Surface::~Surface()
980  {
981    texture->unref();
982 +
983 +#ifdef HAVE_OPENGL
984 +  if(!use_opengl)
985 +#endif
986 +  {
987 +    std::for_each(transforms, transforms + NUM_EFFECTS, SDL_FreeSurface);
988 +  }
989  }
990  
991  void
992  Surface::hflip()
993  {
994 -  std::swap(uv_left, uv_right);
995 +#ifdef HAVE_OPENGL
996 +  if(use_opengl)
997 +  {
998 +    std::swap(surface.opengl.uv_left, surface.opengl.uv_right);
999 +  }
1000 +  else
1001 +#endif
1002 +  {
1003 +    surface.sdl.flipx = !surface.sdl.flipx;
1004 +  }
1005  }
1006  
1007 -static inline void intern_draw(float left, float top, float right, float bottom,                               float uv_left, float uv_top,
1008 -                               float uv_right, float uv_bottom,
1009 -                               DrawingEffect effect)
1010 +#ifdef HAVE_OPENGL
1011 +namespace
1012  {
1013 -  if(effect & HORIZONTAL_FLIP)
1014 -    std::swap(uv_left, uv_right);
1015 -  if(effect & VERTICAL_FLIP) {
1016 -    std::swap(uv_top, uv_bottom);
1017 -  }
1018 +  inline void intern_draw(float left, float top, float right, float bottom,                               float uv_left, float uv_top,
1019 +                                 float uv_right, float uv_bottom,
1020 +                                 DrawingEffect effect)
1021 +  {
1022 +    if(effect & HORIZONTAL_FLIP)
1023 +      std::swap(uv_left, uv_right);
1024 +    if(effect & VERTICAL_FLIP) {
1025 +      std::swap(uv_top, uv_bottom);
1026 +    }
1027  
1028 -  glBegin(GL_QUADS);
1029 -  glTexCoord2f(uv_left, uv_top);
1030 -  glVertex2f(left, top);
1031 +    glBegin(GL_QUADS);
1032 +    glTexCoord2f(uv_left, uv_top);
1033 +    glVertex2f(left, top);
1034  
1035 -  glTexCoord2f(uv_right, uv_top);
1036 -  glVertex2f(right, top);
1037 +    glTexCoord2f(uv_right, uv_top);
1038 +    glVertex2f(right, top);
1039  
1040 -  glTexCoord2f(uv_right, uv_bottom);
1041 -  glVertex2f(right, bottom);
1042 +    glTexCoord2f(uv_right, uv_bottom);
1043 +    glVertex2f(right, bottom);
1044  
1045 -  glTexCoord2f(uv_left, uv_bottom);
1046 -  glVertex2f(left, bottom);
1047 -  glEnd();
1048 -}
1049 -
1050 -static inline void intern_draw2(float left, float top, float right, float bottom,
1051 -                                float uv_left, float uv_top,
1052 -                                float uv_right, float uv_bottom,
1053 -                                float angle, float alpha,
1054 -                                const Color& color,
1055 -                                const Blend& blend,
1056 -                                DrawingEffect effect)
1057 -{
1058 -  if(effect & HORIZONTAL_FLIP)
1059 -    std::swap(uv_left, uv_right);
1060 -  if(effect & VERTICAL_FLIP) {
1061 -    std::swap(uv_top, uv_bottom);
1062 +    glTexCoord2f(uv_left, uv_bottom);
1063 +    glVertex2f(left, bottom);
1064 +    glEnd();
1065    }
1066  
1067 -  float center_x = (left + right) / 2;
1068 -  float center_y = (top + bottom) / 2;
1069 +  inline void intern_draw2(float left, float top, float right, float bottom,
1070 +                                  float uv_left, float uv_top,
1071 +                                  float uv_right, float uv_bottom,
1072 +                                  float angle, float alpha,
1073 +                                  const Color& color,
1074 +                                  const Blend& blend,
1075 +                                  DrawingEffect effect)
1076 +  {
1077 +    if(effect & HORIZONTAL_FLIP)
1078 +      std::swap(uv_left, uv_right);
1079 +    if(effect & VERTICAL_FLIP) {
1080 +      std::swap(uv_top, uv_bottom);
1081 +    }
1082  
1083 -  float sa = sinf(angle/180.0f*M_PI);
1084 -  float ca = cosf(angle/180.0f*M_PI);
1085 +    float center_x = (left + right) / 2;
1086 +    float center_y = (top + bottom) / 2;
1087  
1088 -  left  -= center_x;
1089 -  right -= center_x;
1090 +    float sa = sinf(angle/180.0f*M_PI);
1091 +    float ca = cosf(angle/180.0f*M_PI);
1092  
1093 -  top    -= center_y;
1094 -  bottom -= center_y;
1095 +    left  -= center_x;
1096 +    right -= center_x;
1097  
1098 -  glBlendFunc(blend.sfactor, blend.dfactor);
1099 -  glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
1100 -  glBegin(GL_QUADS);
1101 -  glTexCoord2f(uv_left, uv_top);
1102 -  glVertex2f(left*ca - top*sa + center_x,
1103 -             left*sa + top*ca + center_y);
1104 +    top    -= center_y;
1105 +    bottom -= center_y;
1106  
1107 -  glTexCoord2f(uv_right, uv_top);
1108 -  glVertex2f(right*ca - top*sa + center_x,
1109 -             right*sa + top*ca + center_y);
1110 +    glBlendFunc(blend.sfactor, blend.dfactor);
1111 +    glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
1112 +    glBegin(GL_QUADS);
1113 +    glTexCoord2f(uv_left, uv_top);
1114 +    glVertex2f(left*ca - top*sa + center_x,
1115 +               left*sa + top*ca + center_y);
1116  
1117 -  glTexCoord2f(uv_right, uv_bottom);
1118 -  glVertex2f(right*ca - bottom*sa + center_x,
1119 -             right*sa + bottom*ca + center_y);
1120 +    glTexCoord2f(uv_right, uv_top);
1121 +    glVertex2f(right*ca - top*sa + center_x,
1122 +               right*sa + top*ca + center_y);
1123  
1124 -  glTexCoord2f(uv_left, uv_bottom);
1125 -  glVertex2f(left*ca - bottom*sa + center_x,
1126 -             left*sa + bottom*ca + center_y);
1127 -  glEnd();
1128 +    glTexCoord2f(uv_right, uv_bottom);
1129 +    glVertex2f(right*ca - bottom*sa + center_x,
1130 +               right*sa + bottom*ca + center_y);
1131  
1132 -  // FIXME: find a better way to restore the blend mode
1133 -  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1134 -  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1135 +    glTexCoord2f(uv_left, uv_bottom);
1136 +    glVertex2f(left*ca - bottom*sa + center_x,
1137 +               left*sa + bottom*ca + center_y);
1138 +    glEnd();
1139 +
1140 +    // FIXME: find a better way to restore the blend mode
1141 +    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1142 +    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1143 +  }
1144  }
1145 +#endif
1146  
1147  void
1148 -Surface::draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const
1149 +Surface::draw(float x, float y, float alpha,
1150 +#ifdef HAVE_OPENGL
1151 +              float angle, const Color& color, const Blend& blend,
1152 +#else
1153 +              float, const Color&, const Blend&,
1154 +#endif
1155 +              DrawingEffect effect) const
1156  {
1157 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1158 -
1159 -  intern_draw2(x, y,
1160 -               x + width, y + height,
1161 -               uv_left, uv_top, uv_right, uv_bottom,
1162 -               angle,
1163 -               alpha,
1164 -               color,
1165 -               blend,
1166 -               effect);
1167 +#ifdef HAVE_OPENGL
1168 +  if(use_opengl)
1169 +  {
1170 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1171 +    intern_draw2(x, y,
1172 +                 x + surface.opengl.width, y + surface.opengl.height,
1173 +                 surface.opengl.uv_left, surface.opengl.uv_top,
1174 +                 surface.opengl.uv_right, surface.opengl.uv_bottom,
1175 +                 angle,
1176 +                 alpha,
1177 +                 color,
1178 +                 blend,
1179 +                 effect);
1180 +  }
1181 +  else
1182 +#endif
1183 +  {
1184 +    draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
1185 +  }
1186  }
1187  
1188  void
1189  Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
1190  {
1191 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1192 +#ifdef HAVE_OPENGL
1193 +  if(use_opengl)
1194 +  {
1195 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1196 +    glColor4f(1, 1, 1, alpha);
1197 +    intern_draw(x, y,
1198 +                x + surface.opengl.width, y + surface.opengl.height,
1199 +                surface.opengl.uv_left, surface.opengl.uv_top,
1200 +                surface.opengl.uv_right, surface.opengl.uv_bottom, effect);
1201 +    glColor4f(1, 1, 1, 1);
1202 +  }
1203 +  else
1204 +#endif
1205 +  {
1206 +    draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
1207 +  }
1208 +}
1209  
1210 -  glColor4f(1, 1, 1, alpha);
1211 -  intern_draw(x, y,
1212 -              x + width, y + height,
1213 -              uv_left, uv_top, uv_right, uv_bottom, effect);
1214 -  glColor4f(1, 1, 1, 1);
1215 +namespace
1216 +{
1217 +  SDL_Surface *horz_flip(SDL_Surface *src)
1218 +  {
1219 +    SDL_Surface *dst = SDL_ConvertSurface(src, src->format, src->flags);
1220 +    int bpp = dst->format->BytesPerPixel;
1221 +    for(int y = 0;y < dst->h;y++) {
1222 +      Uint8 *line = (Uint8 *) dst->pixels + y * dst->pitch;
1223 +      for(int x = 0;x < (dst->w / 2);x++) {
1224 +        switch(bpp) {
1225 +          case 4:
1226 +            line[3 + x * bpp] ^= line[3 + (dst->w - x - 1) * bpp];
1227 +            line[3 + (dst->w - x - 1) * bpp] ^= line[3 + x * bpp];
1228 +            line[3 + x * bpp] ^= line[3 + (dst->w - x - 1) * bpp];
1229 +          case 3:
1230 +            line[2 + x * bpp] ^= line[2 + (dst->w - x - 1) * bpp];
1231 +            line[2 + (dst->w - x - 1) * bpp] ^= line[2 + x * bpp];
1232 +            line[2 + x * bpp] ^= line[2 + (dst->w - x - 1) * bpp];
1233 +          case 2:
1234 +            line[1 + x * bpp] ^= line[1 + (dst->w - x - 1) * bpp];
1235 +            line[1 + (dst->w - x - 1) * bpp] ^= line[1 + x * bpp];
1236 +            line[1 + x * bpp] ^= line[1 + (dst->w - x - 1) * bpp];
1237 +          case 1:
1238 +            line[0 + x * bpp] ^= line[0 + (dst->w - x - 1) * bpp];
1239 +            line[0 + (dst->w - x - 1) * bpp] ^= line[0 + x * bpp];
1240 +            line[0 + x * bpp] ^= line[0 + (dst->w - x - 1) * bpp];
1241 +        }
1242 +      }
1243 +    }
1244 +    return dst;
1245 +  }
1246 +
1247 +  SDL_Surface *vert_flip(SDL_Surface *src)
1248 +  {
1249 +    SDL_Surface *dst = SDL_ConvertSurface(src, src->format, src->flags);
1250 +    int bpp = dst->format->BytesPerPixel;
1251 +    for(int x = 0;x < dst->w;x++) {
1252 +      Uint8 *rank = (Uint8 *) dst->pixels + x * bpp;
1253 +      for(int y = 0;y < (dst->h / 2);y++) {
1254 +        switch(bpp) {
1255 +          case 4:
1256 +            rank[3 + y * dst->pitch] ^= rank[3 + (dst->h - y - 1) * dst->pitch];
1257 +            rank[3 + (dst->h - y - 1) * dst->pitch] ^= rank[3 + y * dst->pitch];
1258 +            rank[3 + y * dst->pitch] ^= rank[3 + (dst->h - y - 1) * dst->pitch];
1259 +          case 3:
1260 +            rank[2 + y * dst->pitch] ^= rank[2 + (dst->h - y - 1) * dst->pitch];
1261 +            rank[2 + (dst->h - y - 1) * dst->pitch] ^= rank[2 + y * dst->pitch];
1262 +            rank[2 + y * dst->pitch] ^= rank[2 + (dst->h - y - 1) * dst->pitch];
1263 +          case 2:
1264 +            rank[1 + y * dst->pitch] ^= rank[1 + (dst->h - y - 1) * dst->pitch];
1265 +            rank[1 + (dst->h - y - 1) * dst->pitch] ^= rank[1 + y * dst->pitch];
1266 +            rank[1 + y * dst->pitch] ^= rank[1 + (dst->h - y - 1) * dst->pitch];
1267 +          case 1:
1268 +            rank[0 + y * dst->pitch] ^= rank[0 + (dst->h - y - 1) * dst->pitch];
1269 +            rank[0 + (dst->h - y - 1) * dst->pitch] ^= rank[0 + y * dst->pitch];
1270 +            rank[0 + y * dst->pitch] ^= rank[0 + (dst->h - y - 1) * dst->pitch];
1271 +        }
1272 +      }
1273 +    }
1274 +    return dst;
1275 +  }
1276  }
1277  
1278  void
1279  Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
1280 +#ifdef HAVE_OPENGL
1281                     float width, float height, float alpha,
1282 +#else
1283 +                   float width, float height, float,
1284 +#endif
1285                     DrawingEffect effect) const
1286  {
1287 -  float uv_width = uv_right - uv_left;
1288 -  float uv_height = uv_bottom - uv_top;
1289 +#ifdef HAVE_OPENGL
1290 +  if(use_opengl)
1291 +  {
1292 +    float uv_width = surface.opengl.uv_right - surface.opengl.uv_left;
1293 +    float uv_height = surface.opengl.uv_bottom - surface.opengl.uv_top;
1294  
1295 -  float uv_left = this->uv_left + (uv_width * src_x) / this->width;
1296 -  float uv_top = this->uv_top + (uv_height * src_y) / this->height;
1297 -  float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
1298 -  float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
1299 +    float uv_left = surface.opengl.uv_left + (uv_width * src_x) / surface.opengl.width;
1300 +    float uv_top = surface.opengl.uv_top + (uv_height * src_y) / surface.opengl.height;
1301 +    float uv_right = surface.opengl.uv_left + (uv_width * (src_x + width)) / surface.opengl.width;
1302 +    float uv_bottom = surface.opengl.uv_top + (uv_height * (src_y + height)) / surface.opengl.height;
1303  
1304 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1305 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1306 +    glColor4f(1, 1, 1, alpha);
1307 +    intern_draw(dst_x, dst_y,
1308 +                dst_x + width, dst_y + height,
1309 +                uv_left, uv_top, uv_right, uv_bottom, effect);
1310 +    glColor4f(1, 1, 1, 1);
1311 +  }
1312 +  else
1313 +#endif
1314 +  {
1315 +    //FIXME: support parameter "alpha"
1316
1317 +    // get and check SDL_Surface
1318 +    if (texture->get_surface() == 0) {
1319 +      std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
1320 +      return;
1321 +    }  
1322  
1323 -  glColor4f(1, 1, 1, alpha);
1324 -  intern_draw(dst_x, dst_y,
1325 -              dst_x + width, dst_y + height,
1326 -              uv_left, uv_top, uv_right, uv_bottom, effect);
1327 -  glColor4f(1, 1, 1, 1);
1328 +    if (surface.sdl.flipx) effect = HORIZONTAL_FLIP;
1329 +
1330 +    if(transforms[effect] == 0) {
1331 +      switch(effect) {
1332 +        case NO_EFFECT:
1333 +          transforms[NO_EFFECT] = texture->get_surface();
1334 +          transforms[NO_EFFECT]->refcount++;
1335 +          break;
1336 +        case HORIZONTAL_FLIP:
1337 +          transforms[HORIZONTAL_FLIP] = horz_flip(texture->get_surface());
1338 +          break;
1339 +        case VERTICAL_FLIP:
1340 +          transforms[VERTICAL_FLIP] = vert_flip(texture->get_surface());
1341 +          break;
1342 +        default:
1343 +          std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
1344 +          return;
1345 +      }
1346 +    }
1347 +
1348 +    int ox = surface.sdl.offsetx; if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(transforms[effect]->w) - (ox+static_cast<int>(width));
1349 +    int oy = surface.sdl.offsety; if (effect == VERTICAL_FLIP) oy = static_cast<int>(transforms[effect]->h) - (oy+static_cast<int>(height));
1350 +    // draw surface to screen
1351 +    SDL_Surface* screen = SDL_GetVideoSurface();
1352 +
1353 +    SDL_Rect srcRect;
1354 +    srcRect.x = static_cast<int>(ox+src_x);
1355 +    srcRect.y = static_cast<int>(oy+src_y);
1356 +    srcRect.w = static_cast<int>(width);
1357 +    srcRect.h = static_cast<int>(height);
1358 +
1359 +    SDL_Rect dstRect;
1360 +    dstRect.x = static_cast<int>(dst_x);
1361 +    dstRect.y = static_cast<int>(dst_y);
1362 +
1363 +    SDL_BlitSurface(transforms[effect], &srcRect, screen, &dstRect);
1364 +  }
1365  }
1366 Index: src/video/texture_manager.cpp
1367 ===================================================================
1368 --- src/video/texture_manager.cpp       (revision 5069)
1369 +++ src/video/texture_manager.cpp       (working copy)
1370 @@ -24,14 +24,13 @@
1371  #include <assert.h>
1372  #include <SDL.h>
1373  #include <SDL_image.h>
1374 -#include <GL/gl.h>
1375 -#include <GL/glext.h>
1376  #include <iostream>
1377  #include <sstream>
1378  #include <stdexcept>
1379  #include "physfs/physfs_sdl.hpp"
1380  #include "image_texture.hpp"
1381  #include "glutil.hpp"
1382 +#include "gameconfig.hpp"
1383  #include "file_system.hpp"
1384  #include "log.hpp"
1385  
1386 @@ -149,12 +148,16 @@
1387  void
1388  TextureManager::save_textures()
1389  {
1390 -  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1391 -  glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
1392 -  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1393 -  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1394 -  glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
1395 -  glPixelStorei(GL_PACK_ALIGNMENT, 1);
1396 +#ifdef HAVE_OPENGL
1397 +  if(config->use_opengl) {
1398 +    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1399 +    glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
1400 +    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1401 +    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1402 +    glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
1403 +    glPixelStorei(GL_PACK_ALIGNMENT, 1);
1404 +  }
1405 +#endif
1406    for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
1407      save_texture(*i);
1408    }
1409 @@ -169,74 +172,90 @@
1410  {
1411    SavedTexture saved_texture;
1412    saved_texture.texture = texture;
1413 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1414 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
1415 -                           &saved_texture.width);
1416 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
1417 -                           &saved_texture.height);
1418 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
1419 -                           &saved_texture.border);
1420 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1421 -                      &saved_texture.min_filter);
1422 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1423 -                      &saved_texture.mag_filter);
1424 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1425 -                      &saved_texture.wrap_s);
1426 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1427 -                      &saved_texture.wrap_t);
1428 +#ifdef HAVE_OPENGL
1429 +  if(config->use_opengl) {
1430 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1431 +    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
1432 +                             &saved_texture.width);
1433 +    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
1434 +                             &saved_texture.height);
1435 +    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
1436 +                             &saved_texture.border);
1437 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1438 +                        &saved_texture.min_filter);
1439 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1440 +                        &saved_texture.mag_filter);
1441 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1442 +                        &saved_texture.wrap_s);
1443 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1444 +                        &saved_texture.wrap_t);
1445 +  }
1446 +#endif
1447  
1448    size_t pixelssize = saved_texture.width * saved_texture.height * 4;
1449    saved_texture.pixels = new char[pixelssize];
1450  
1451 -  glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1452 -                saved_texture.pixels);
1453 +#ifdef HAVE_OPENGL
1454 +  if(config->use_opengl) {
1455 +    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1456 +                  saved_texture.pixels);
1457 +  }
1458 +#endif
1459  
1460    saved_textures.push_back(saved_texture);
1461  
1462 -  glDeleteTextures(1, &(texture->handle));
1463 -  texture->handle = 0;
1464 +#ifdef HAVE_OPENGL
1465 +  if(config->use_opengl) {
1466 +    glDeleteTextures(1, &(texture->get_handle()));
1467 +    texture->set_handle(0);
1468  
1469 -  assert_gl("retrieving texture for save");
1470 +    assert_gl("retrieving texture for save");
1471 +  }
1472 +#endif
1473  }
1474  
1475  void
1476  TextureManager::reload_textures()
1477  {
1478 -  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1479 -  glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1480 -  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1481 -  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1482 -  glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1483 -  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1484 +#ifdef HAVE_OPENGL
1485 +  if(config->use_opengl) {
1486 +    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1487 +    glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1488 +    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1489 +    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1490 +    glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1491 +    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1492  
1493 -  for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1494 -      i != saved_textures.end(); ++i) {
1495 -    SavedTexture& saved_texture = *i;
1496 +    for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1497 +        i != saved_textures.end(); ++i) {
1498 +      SavedTexture& saved_texture = *i;
1499  
1500 -    GLuint handle;
1501 -    glGenTextures(1, &handle);
1502 -    assert_gl("creating texture handle");
1503 +      GLuint handle;
1504 +      glGenTextures(1, &handle);
1505 +      assert_gl("creating texture handle");
1506  
1507 -    glBindTexture(GL_TEXTURE_2D, handle);
1508 -    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1509 -                 saved_texture.width, saved_texture.height,
1510 -                 saved_texture.border, GL_RGBA,
1511 -                 GL_UNSIGNED_BYTE, saved_texture.pixels);
1512 -    delete[] saved_texture.pixels;
1513 -    assert_gl("uploading texture pixel data");
1514 +      glBindTexture(GL_TEXTURE_2D, handle);
1515 +      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1516 +                   saved_texture.width, saved_texture.height,
1517 +                   saved_texture.border, GL_RGBA,
1518 +                   GL_UNSIGNED_BYTE, saved_texture.pixels);
1519 +      delete[] saved_texture.pixels;
1520 +      assert_gl("uploading texture pixel data");
1521  
1522 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1523 -                    saved_texture.min_filter);
1524 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1525 -                    saved_texture.mag_filter);
1526 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1527 -                    saved_texture.wrap_s);
1528 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1529 -                    saved_texture.wrap_t);
1530 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1531 +                      saved_texture.min_filter);
1532 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1533 +                      saved_texture.mag_filter);
1534 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1535 +                      saved_texture.wrap_s);
1536 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1537 +                      saved_texture.wrap_t);
1538  
1539 -    assert_gl("setting texture_params");
1540 -    saved_texture.texture->handle = handle;
1541 +      assert_gl("setting texture_params");
1542 +      saved_texture.texture->set_handle(handle);
1543 +    }
1544    }
1545 +#endif
1546  
1547    saved_textures.clear();
1548  }
1549 Index: src/video/surface.hpp
1550 ===================================================================
1551 --- src/video/surface.hpp       (revision 5069)
1552 +++ src/video/surface.hpp       (working copy)
1553 @@ -20,7 +20,11 @@
1554  #ifndef __SURFACE_HPP__
1555  #define __SURFACE_HPP__
1556  
1557 +#include <config.h>
1558 +
1559  #include <string>
1560 +#include <SDL.h>
1561 +#include "gameconfig.hpp"
1562  #include "math/vector.hpp"
1563  
1564  class Color;
1565 @@ -30,11 +34,12 @@
1566  /// bitset for drawing effects
1567  enum DrawingEffect {
1568    /** Don't apply anything */
1569 -  NO_EFFECT       = 0x0000,
1570 +  NO_EFFECT,
1571    /** Draw the Surface upside down */
1572 -  VERTICAL_FLIP     = 0x0001,
1573 +  VERTICAL_FLIP,
1574    /** Draw the Surface from left to down */
1575 -  HORIZONTAL_FLIP   = 0x0002,
1576 +  HORIZONTAL_FLIP,
1577 +  NUM_EFFECTS
1578  };
1579  
1580  /**
1581 @@ -47,21 +52,43 @@
1582  private:
1583    friend class DrawingContext;
1584    friend class Font;
1585 -  ImageTexture* texture;
1586  
1587 -  float uv_left;
1588 -  float uv_top;
1589 -  float uv_right;
1590 -  float uv_bottom;
1591 -
1592    void draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const;
1593    void draw(float x, float y, float alpha, DrawingEffect effect) const;
1594    void draw_part(float src_x, float src_y, float dst_x, float dst_y,
1595                   float width, float height,
1596                   float alpha, DrawingEffect effect) const;
1597  
1598 -  float width;
1599 -  float height;
1600 +  ImageTexture* texture;
1601 +#ifdef HAVE_OPENGL
1602 +  bool use_opengl;
1603 +  union
1604 +  {
1605 +    struct
1606 +    {
1607 +      float uv_left;
1608 +      float uv_top;
1609 +      float uv_right;
1610 +      float uv_bottom;
1611 +
1612 +      float width;
1613 +      float height;
1614 +    } opengl;
1615 +#else
1616 +  struct
1617 +  {
1618 +#endif
1619 +    struct
1620 +    {
1621 +      bool flipx;
1622 +      int offsetx; /**< Region in ::surface to be used for blitting */
1623 +      int offsety; /**< Region in ::surface to be used for blitting */
1624 +      int width;   /**< Region in ::surface to be used for blitting */
1625 +      int height;  /**< Region in ::surface to be used for blitting */
1626 +    } sdl;
1627 +  } surface;
1628 +  mutable SDL_Surface *transforms[NUM_EFFECTS]; /**< Cache for pre-transformed surfaces */
1629 +
1630  public:
1631    Surface(const std::string& file);
1632    Surface(const std::string& file, int x, int y, int w, int h);
1633 @@ -75,12 +102,30 @@
1634  
1635    float get_width() const
1636    {
1637 -    return width;
1638 +#ifdef HAVE_OPENGL
1639 +    if(use_opengl)
1640 +    {
1641 +      return surface.opengl.width;
1642 +    }
1643 +    else
1644 +#endif
1645 +    {
1646 +      return surface.sdl.width;
1647 +    }
1648    }
1649  
1650    float get_height() const
1651    {
1652 -    return height;
1653 +#ifdef HAVE_OPENGL
1654 +    if(use_opengl)
1655 +    {
1656 +      return surface.opengl.height;
1657 +    }
1658 +    else
1659 +#endif
1660 +    {
1661 +      return surface.sdl.height;
1662 +    }
1663    }
1664  
1665    /**
1666 Index: src/gameconfig.cpp
1667 ===================================================================
1668 --- src/gameconfig.cpp  (revision 5069)
1669 +++ src/gameconfig.cpp  (working copy)
1670 @@ -36,6 +36,9 @@
1671  Config::Config()
1672  {
1673    use_fullscreen = true;
1674 +#ifdef HAVE_OPENGL
1675 +  use_opengl = true;
1676 +#endif
1677    try_vsync = true;
1678    show_fps = false;
1679    sound_enabled = true;
1680 @@ -70,7 +73,10 @@
1681    const lisp::Lisp* config_video_lisp = config_lisp->get_lisp("video");
1682    if(config_video_lisp) {
1683      config_video_lisp->get("fullscreen", use_fullscreen);
1684 -       config_video_lisp->get("vsync", try_vsync);
1685 +#ifdef HAVE_OPENGL
1686 +    config_video_lisp->get("opengl", use_opengl);
1687 +#endif
1688 +    config_video_lisp->get("vsync", try_vsync);
1689      config_video_lisp->get("width", screenwidth);
1690      config_video_lisp->get("height", screenheight);
1691      config_video_lisp->get("aspect_ratio", aspect_ratio);
1692 @@ -100,6 +106,9 @@
1693  
1694    writer.start_list("video");
1695    writer.write_bool("fullscreen", use_fullscreen);
1696 +#ifdef HAVE_OPENGL
1697 +  writer.write_bool("opengl", use_opengl);
1698 +#endif
1699    writer.write_bool("vsync", try_vsync);
1700    writer.write_int("width", screenwidth);
1701    writer.write_int("height", screenheight);
1702 Index: src/main.cpp
1703 ===================================================================
1704 --- src/main.cpp        (revision 5069)
1705 +++ src/main.cpp        (working copy)
1706 @@ -33,7 +33,6 @@
1707  #include <physfs.h>
1708  #include <SDL.h>
1709  #include <SDL_image.h>
1710 -#include <GL/gl.h>
1711  
1712  #include "gameconfig.hpp"
1713  #include "resources.hpp"
1714 @@ -383,7 +382,11 @@
1715    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
1716    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
1717  
1718 -  int flags = SDL_OPENGL;
1719 +#ifdef HAVE_OPENGL
1720 +  int flags = config->use_opengl ? SDL_OPENGL : SDL_SWSURFACE;
1721 +#else
1722 +  int flags = SDL_SWSURFACE;
1723 +#endif
1724    if(config->use_fullscreen)
1725      flags |= SDL_FULLSCREEN;
1726    int width = config->screenwidth;
1727 @@ -437,23 +440,28 @@
1728  
1729    log_info << (config->use_fullscreen?"fullscreen ":"window ") << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << " Ratio: " << aspect_ratio << "\n";
1730  
1731 -  // setup opengl state and transform
1732 -  glDisable(GL_DEPTH_TEST);
1733 -  glDisable(GL_CULL_FACE);
1734 -  glEnable(GL_TEXTURE_2D);
1735 -  glEnable(GL_BLEND);
1736 -  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1737 +#ifdef HAVE_OPENGL
1738 +  if(config->use_opengl)
1739 +  {
1740 +    // setup opengl state and transform
1741 +    glDisable(GL_DEPTH_TEST);
1742 +    glDisable(GL_CULL_FACE);
1743 +    glEnable(GL_TEXTURE_2D);
1744 +    glEnable(GL_BLEND);
1745 +    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1746  
1747 -  glViewport(0, 0, screen->w, screen->h);
1748 -  glMatrixMode(GL_PROJECTION);
1749 -  glLoadIdentity();
1750 -  // logical resolution here not real monitor resolution
1751 -  glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
1752 -  glMatrixMode(GL_MODELVIEW);
1753 -  glLoadIdentity();
1754 -  glTranslatef(0, 0, 0);
1755 +    glViewport(0, 0, screen->w, screen->h);
1756 +    glMatrixMode(GL_PROJECTION);
1757 +    glLoadIdentity();
1758 +    // logical resolution here not real monitor resolution
1759 +    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
1760 +    glMatrixMode(GL_MODELVIEW);
1761 +    glLoadIdentity();
1762 +    glTranslatef(0, 0, 0);
1763  
1764 -  check_gl_error("Setting up view matrices");
1765 +    check_gl_error("Setting up view matrices");
1766 +  }
1767 +#endif
1768  
1769    if(texture_manager != NULL)
1770      texture_manager->reload_textures();
1771 Index: configure.ac
1772 ===================================================================
1773 --- configure.ac        (revision 5069)
1774 +++ configure.ac        (working copy)
1775 @@ -154,9 +154,15 @@
1776           [AC_MSG_ERROR([Please intall OpenAL])],
1777           [], [])
1778  
1779 -AX_CHECK_GL
1780 -if test "$no_gl" = "yes"; then
1781 -  AC_MSG_ERROR([Please install opengl libraries and headers])
1782 +AC_ARG_ENABLE(opengl,
1783 +              AC_HELP_STRING([--enable-opengl], [enable opengl support]),
1784 +              [enable_opengl=$enableval], [enable_opengl=yes])
1785 +
1786 +if test "$enable_opengl" = "yes"; then
1787 +  AX_CHECK_GL
1788 +  if test "$no_gl" != "yes"; then
1789 +    AC_DEFINE_UNQUOTED(HAVE_OPENGL, 1, Define if OpenGL is present on the system)
1790 +  fi
1791  fi
1792  
1793  dnl Checks for library functions.