Updated nogl patch. Side-by-side with OpenGL version, No SDL_gfx requirement, faster...
[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 5065. It may break for later revisions.
33 #
34 # -----------------------------------------------------------------------------
35 Index: src/gameconfig.hpp
36 ===================================================================
37 --- src/gameconfig.hpp  (revision 5066)
38 +++ src/gameconfig.hpp  (working copy)
39 @@ -39,6 +39,7 @@
40    float aspect_ratio;
41  
42    bool use_fullscreen;
43 +  bool use_opengl;
44    bool try_vsync;
45    bool show_fps;
46    bool sound_enabled;
47 Index: src/video/drawing_context.cpp
48 ===================================================================
49 --- src/video/drawing_context.cpp       (revision 5066)
50 +++ src/video/drawing_context.cpp       (working copy)
51 @@ -308,28 +308,38 @@
52  void
53  DrawingContext::get_light(const Vector& position, Color* color)
54  {
55 -  if( ambient_color.red == 1.0f && ambient_color.green == 1.0f
56 -      && ambient_color.blue  == 1.0f ) {
57 -    *color = Color( 1.0f, 1.0f, 1.0f);
58 -    return;
59 -  }
60 +  if(config->use_opengl) {
61 +    if( ambient_color.red == 1.0f && ambient_color.green == 1.0f
62 +        && ambient_color.blue  == 1.0f ) {
63 +      *color = Color( 1.0f, 1.0f, 1.0f);
64 +      return;
65 +    }
66  
67 -  DrawingRequest* request = new(obst) DrawingRequest();
68 -  request->type = GETLIGHT;
69 -  request->pos = transform.apply(position);
70 +    DrawingRequest* request = new(obst) DrawingRequest();
71 +    request->type = GETLIGHT;
72 +    request->pos = transform.apply(position);
73  
74 -  //There is no light offscreen.
75 -  if(request->pos.x >= SCREEN_WIDTH || request->pos.y >= SCREEN_HEIGHT
76 -      || request->pos.x < 0 || request->pos.y < 0){
77 -    *color = Color( 0, 0, 0);
78 -    return;
79 +    //There is no light offscreen.
80 +    if(request->pos.x >= SCREEN_WIDTH || request->pos.y >= SCREEN_HEIGHT
81 +        || request->pos.x < 0 || request->pos.y < 0){
82 +      *color = Color( 0, 0, 0);
83 +      return;
84 +    }
85 +
86 +    request->layer = LAYER_GUI; //make sure all get_light requests are handled last.
87 +    GetLightRequest* getlightrequest = new(obst) GetLightRequest();
88 +    getlightrequest->color_ptr = color;
89 +    request->request_data = getlightrequest;
90 +    lightmap_requests.push_back(request);
91 +  } else {
92 +    static int i = 0;
93 +    i += 1; i &= 0xFFFF;
94 +    if (i & 0x8000) {
95 +      *color = Color(0.0f, 0.0f, 0.0f);
96 +    } else {
97 +      *color = Color(1.0f, 1.0f, 1.0f);
98 +    }
99    }
100 -
101 -  request->layer = LAYER_GUI; //make sure all get_light requests are handled last.
102 -  GetLightRequest* getlightrequest = new(obst) GetLightRequest();
103 -  getlightrequest->color_ptr = color;
104 -  request->request_data = getlightrequest;
105 -  lightmap_requests.push_back(request);
106  }
107  
108  void
109 @@ -370,16 +380,47 @@
110    const Color& top = gradientrequest->top;
111    const Color& bottom = gradientrequest->bottom;
112  
113 -  glDisable(GL_TEXTURE_2D);
114 -  glBegin(GL_QUADS);
115 -  glColor4f(top.red, top.green, top.blue, top.alpha);
116 -  glVertex2f(0, 0);
117 -  glVertex2f(SCREEN_WIDTH, 0);
118 -  glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
119 -  glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
120 -  glVertex2f(0, SCREEN_HEIGHT);
121 -  glEnd();
122 -  glEnable(GL_TEXTURE_2D);
123 +  if(config->use_opengl)
124 +  {
125 +    glDisable(GL_TEXTURE_2D);
126 +    glBegin(GL_QUADS);
127 +    glColor4f(top.red, top.green, top.blue, top.alpha);
128 +    glVertex2f(0, 0);
129 +    glVertex2f(SCREEN_WIDTH, 0);
130 +    glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
131 +    glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
132 +    glVertex2f(0, SCREEN_HEIGHT);
133 +    glEnd();
134 +    glEnable(GL_TEXTURE_2D);
135 +  }
136 +  else
137 +  {
138 +    for(int y = 0;y < screen->h;++y)
139 +    {
140 +      Uint8 r = (Uint8)((((float)(top.red-bottom.red)/(0-screen->h)) * y + top.red) * 255);
141 +      Uint8 g = (Uint8)((((float)(top.green-bottom.green)/(0-screen->h)) * y + top.green) * 255);
142 +      Uint8 b = (Uint8)((((float)(top.blue-bottom.blue)/(0-screen->h)) * y + top.blue) * 255);
143 +      Uint8 a = (Uint8)((((float)(top.alpha-bottom.alpha)/(0-screen->h)) * y + top.alpha) * 255);
144 +      Uint32 color = SDL_MapRGB(screen->format, r, g, b);
145 +
146 +      SDL_Rect rect;
147 +      rect.x = 0;
148 +      rect.y = y;
149 +      rect.w = screen->w;
150 +      rect.h = 1;
151 +
152 +      if(a == SDL_ALPHA_OPAQUE) {
153 +        SDL_FillRect(screen, &rect, color);
154 +      } else if(a != SDL_ALPHA_TRANSPARENT) {
155 +        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);
156 +
157 +        SDL_FillRect(temp, 0, color);
158 +        SDL_SetAlpha(temp, SDL_SRCALPHA, a);
159 +        SDL_BlitSurface(temp, 0, screen, &rect);
160 +        SDL_FreeSurface(temp);
161 +      }
162 +    }
163 +  }
164    glColor4f(1, 1, 1, 1);
165  }
166  
167 @@ -398,22 +439,48 @@
168    const FillRectRequest* fillrectrequest
169      = (FillRectRequest*) request.request_data;
170  
171 -  float x = request.pos.x;
172 -  float y = request.pos.y;
173 -  float w = fillrectrequest->size.x;
174 -  float h = fillrectrequest->size.y;
175 +  if(config->use_opengl)
176 +  {
177 +    float x = request.pos.x;
178 +    float y = request.pos.y;
179 +    float w = fillrectrequest->size.x;
180 +    float h = fillrectrequest->size.y;
181  
182 -  glDisable(GL_TEXTURE_2D);
183 -  glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
184 -            fillrectrequest->color.blue, fillrectrequest->color.alpha);
185 +    glDisable(GL_TEXTURE_2D);
186 +    glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
187 +              fillrectrequest->color.blue, fillrectrequest->color.alpha);
188  
189 -  glBegin(GL_QUADS);
190 -  glVertex2f(x, y);
191 -  glVertex2f(x+w, y);
192 -  glVertex2f(x+w, y+h);
193 -  glVertex2f(x, y+h);
194 -  glEnd();
195 -  glEnable(GL_TEXTURE_2D);
196 +    glBegin(GL_QUADS);
197 +    glVertex2f(x, y);
198 +    glVertex2f(x+w, y);
199 +    glVertex2f(x+w, y+h);
200 +    glVertex2f(x, y+h);
201 +    glEnd();
202 +    glEnable(GL_TEXTURE_2D);
203 +  }
204 +  else
205 +  {
206 +    SDL_Rect rect;
207 +    rect.x = (Sint16)request.pos.x;
208 +    rect.y = (Sint16)request.pos.y;
209 +    rect.w = (Uint16)fillrectrequest->size.x;
210 +    rect.h = (Uint16)fillrectrequest->size.y;
211 +    Uint8 r = static_cast<Uint8>(fillrectrequest->color.red * 255);
212 +    Uint8 g = static_cast<Uint8>(fillrectrequest->color.green * 255);
213 +    Uint8 b = static_cast<Uint8>(fillrectrequest->color.blue * 255);
214 +    Uint8 a = static_cast<Uint8>(fillrectrequest->color.alpha * 255);
215 +    Uint32 color = SDL_MapRGB(screen->format, r, g, b);
216 +    if(a == SDL_ALPHA_OPAQUE) {
217 +      SDL_FillRect(screen, &rect, color);
218 +    } else if(a != SDL_ALPHA_TRANSPARENT) {
219 +      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);
220 +
221 +      SDL_FillRect(temp, 0, color);
222 +      SDL_SetAlpha(temp, SDL_SRCALPHA, a);
223 +      SDL_BlitSurface(temp, 0, screen, &rect);
224 +      SDL_FreeSurface(temp);
225 +    }
226 +  }
227    
228    glColor4f(1, 1, 1, 1);
229  }
230 @@ -462,29 +529,36 @@
231  
232    // PART1: create lightmap
233    if(use_lightmap) {
234 -    glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
235 -    glMatrixMode(GL_PROJECTION);
236 -    glLoadIdentity();
237 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
238 -    glMatrixMode(GL_MODELVIEW);
239 -    glLoadIdentity();
240 +    if(config->use_opengl)
241 +    {
242 +      glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
243 +      glMatrixMode(GL_PROJECTION);
244 +      glLoadIdentity();
245 +      glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
246 +      glMatrixMode(GL_MODELVIEW);
247 +      glLoadIdentity();
248  
249 -    glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
250 -    glClear(GL_COLOR_BUFFER_BIT);
251 -    handle_drawing_requests(lightmap_requests);
252 -    lightmap_requests.clear();
253 +      glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
254 +      glClear(GL_COLOR_BUFFER_BIT);
255 +      handle_drawing_requests(lightmap_requests);
256 +      lightmap_requests.clear();
257  
258 -    glDisable(GL_BLEND);
259 -    glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
260 -    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
261 +      glDisable(GL_BLEND);
262 +      glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
263 +      glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
264  
265 -    glViewport(0, 0, screen->w, screen->h);
266 -    glMatrixMode(GL_PROJECTION);
267 -    glLoadIdentity();
268 -    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
269 -    glMatrixMode(GL_MODELVIEW);
270 -    glLoadIdentity();
271 -    glEnable(GL_BLEND);
272 +      glViewport(0, 0, screen->w, screen->h);
273 +      glMatrixMode(GL_PROJECTION);
274 +      glLoadIdentity();
275 +      glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
276 +      glMatrixMode(GL_MODELVIEW);
277 +      glLoadIdentity();
278 +      glEnable(GL_BLEND);
279 +    }
280 +    else
281 +    {
282 +      // FIXME: SDL alternative
283 +    }
284  
285      // add a lightmap drawing request into the queue
286      DrawingRequest* request = new(obst) DrawingRequest();
287 @@ -499,7 +573,10 @@
288    drawing_requests.clear();
289    obstack_free(&obst, NULL);
290    obstack_init(&obst);
291 -  assert_gl("drawing");
292 +  if(config->use_opengl)
293 +  {
294 +    assert_gl("drawing");
295 +  }
296  
297    // if a screenshot was requested, take one
298    if (screenshot_requested) {
299 @@ -507,7 +584,14 @@
300      screenshot_requested = false;
301    }
302  
303 -  SDL_GL_SwapBuffers();
304 +  if(config->use_opengl)
305 +  {
306 +    SDL_GL_SwapBuffers();
307 +  }
308 +  else
309 +  {
310 +    SDL_Flip(screen);
311 +  }
312  }
313  
314  class RequestPtrCompare
315 Index: src/video/texture.cpp
316 ===================================================================
317 --- src/video/texture.cpp       (revision 5066)
318 +++ src/video/texture.cpp       (working copy)
319 @@ -20,6 +20,7 @@
320  #include <config.h>
321  
322  #include "texture.hpp"
323 +#include "gameconfig.hpp"
324  
325  #include <GL/gl.h>
326  #include <assert.h>
327 @@ -34,24 +35,32 @@
328  {
329    assert(is_power_of_2(w));
330    assert(is_power_of_2(h));
331 +  use_opengl = config->use_opengl;
332  
333 -  this->width = w;
334 -  this->height = h;
335 +  if(use_opengl)
336 +  {
337 +    surface.opengl.width = w;
338 +    surface.opengl.height = h;
339  
340 -  assert_gl("before creating texture");
341 -  glGenTextures(1, &handle);
342 +    assert_gl("before creating texture");
343 +    glGenTextures(1, &surface.opengl.handle);
344  
345 -  try {
346 -    glBindTexture(GL_TEXTURE_2D, handle);
347 +    try {
348 +      glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
349  
350 -    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
351 -                 GL_UNSIGNED_BYTE, 0);
352 +      glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
353 +                   surface.opengl.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
354  
355 -    set_texture_params();
356 -  } catch(...) {
357 -    glDeleteTextures(1, &handle);
358 -    throw;
359 +      set_texture_params();
360 +    } catch(...) {
361 +      glDeleteTextures(1, &surface.opengl.handle);
362 +      throw;
363 +    }
364    }
365 +  else
366 +  {
367 +    surface.sdl = 0;
368 +  }
369  }
370  
371  Texture::Texture(SDL_Surface* image, GLenum glformat)
372 @@ -61,49 +70,62 @@
373      throw std::runtime_error("image has no power of 2 size");
374    if(format->BitsPerPixel != 24 && format->BitsPerPixel != 32)
375      throw std::runtime_error("image has no 24 or 32 bit color depth");
376 +  use_opengl = config->use_opengl;
377  
378 -  this->width = image->w;
379 -  this->height = image->h;
380 +  if(use_opengl)
381 +  {
382 +    surface.opengl.width = image->w;
383 +    surface.opengl.height = image->h;
384  
385 -  assert_gl("before creating texture");
386 -  glGenTextures(1, &handle);
387 +    assert_gl("before creating texture");
388 +    glGenTextures(1, &surface.opengl.handle);
389  
390 -  try {
391 -    GLenum sdl_format;
392 -    if(format->BytesPerPixel == 3)
393 -      sdl_format = GL_RGB;
394 -    else if(format->BytesPerPixel == 4)
395 -      sdl_format = GL_RGBA;
396 -    else
397 -      assert(false);
398 +    try {
399 +      GLenum sdl_format;
400 +      if(format->BytesPerPixel == 3)
401 +        sdl_format = GL_RGB;
402 +      else if(format->BytesPerPixel == 4)
403 +        sdl_format = GL_RGBA;
404 +      else
405 +        assert(false);
406  
407 -    glBindTexture(GL_TEXTURE_2D, handle);
408 -    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
409 -    glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
410 -    glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
411 -            GL_UNSIGNED_BYTE, image->pixels);
412 +      glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
413 +      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
414 +      glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
415 +      glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
416 +              surface.opengl.height, 0, sdl_format,
417 +              GL_UNSIGNED_BYTE, image->pixels);
418  
419 -    assert_gl("creating texture");
420 +      assert_gl("creating texture");
421  
422 -    set_texture_params();
423 -  } catch(...) {
424 -    glDeleteTextures(1, &handle);
425 -    throw;
426 +      set_texture_params();
427 +    } catch(...) {
428 +      glDeleteTextures(1, &surface.opengl.handle);
429 +      throw;
430 +    }
431 +  } else {
432 +    surface.sdl = SDL_DisplayFormatAlpha(image);
433    }
434  }
435  
436  Texture::~Texture()
437  {
438 -  glDeleteTextures(1, &handle);
439 +  if(use_opengl) {
440 +    glDeleteTextures(1, &surface.opengl.handle);
441 +  } else {
442 +    SDL_FreeSurface(surface.sdl);
443 +  }
444  }
445  
446  void
447  Texture::set_texture_params()
448  {
449 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
450 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
451 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
452 -  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
453 +  if(use_opengl) {
454 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
455 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
456 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
457 +    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
458  
459 -  assert_gl("set texture params");
460 +    assert_gl("set texture params");
461 +  }
462  }
463 Index: src/video/texture.hpp
464 ===================================================================
465 --- src/video/texture.hpp       (revision 5066)
466 +++ src/video/texture.hpp       (working copy)
467 @@ -20,9 +20,13 @@
468  #ifndef __TEXTURE_HPP__
469  #define __TEXTURE_HPP__
470  
471 +#include <assert.h>
472 +
473  #include <SDL.h>
474  #include <GL/gl.h>
475  
476 +#include "gameconfig.hpp"
477 +
478  /**
479   * This class is a wrapper around a texture handle. It stores the texture width
480   * and height and provides convenience functions for uploading SDL_Surfaces
481 @@ -31,29 +35,57 @@
482  class Texture
483  {
484  protected:
485 -  friend class TextureManager;
486 -  GLuint handle;
487 -  unsigned int width;
488 -  unsigned int height;
489 +  bool use_opengl;
490 +  union {
491 +    struct {
492 +      GLuint handle;
493 +      unsigned int width;
494 +      unsigned int height;
495 +    } opengl;
496 +    SDL_Surface *sdl;
497 +  } surface;
498  
499  public:
500    Texture(unsigned int width, unsigned int height, GLenum glformat);
501 -  Texture(SDL_Surface* surface, GLenum glformat);
502 +  Texture(SDL_Surface* sdlsurface, GLenum glformat);
503    virtual ~Texture();
504  
505 -  GLuint get_handle() const
506 -  {
507 -    return handle;
508 +  const GLuint &get_handle() const {
509 +    assert(use_opengl);
510 +    return surface.opengl.handle;
511    }
512  
513 +  void set_handle(GLuint handle) {
514 +    assert(use_opengl);
515 +    surface.opengl.handle = handle;
516 +  }
517 +
518 +  SDL_Surface *get_surface() const {
519 +    assert(!use_opengl);
520 +    return surface.sdl;
521 +  }
522 +
523 +  void set_surface(SDL_Surface *sdlsurface) {
524 +    assert(!use_opengl);
525 +    surface.sdl = sdlsurface;
526 +  }
527 +
528    unsigned int get_width() const
529    {
530 -    return width;
531 +    if(use_opengl) {
532 +      return surface.opengl.width;
533 +    } else {
534 +      return surface.sdl->w;
535 +    }
536    }
537  
538    unsigned int get_height() const
539    {
540 -    return height;
541 +    if(use_opengl) {
542 +      return surface.opengl.height;
543 +    } else {
544 +      return surface.sdl->h;
545 +    }
546    }
547  
548  private:
549 Index: src/video/surface.cpp
550 ===================================================================
551 --- src/video/surface.cpp       (revision 5066)
552 +++ src/video/surface.cpp       (working copy)
553 @@ -41,13 +41,27 @@
554  {
555    texture = texture_manager->get(file);
556    texture->ref();
557 -  uv_left = 0;
558 -  uv_top = 0;
559 -  uv_right = texture->get_uv_right();
560 -  uv_bottom = texture->get_uv_bottom();
561  
562 -  width = texture->get_image_width();
563 -  height = texture->get_image_height();
564 +  use_opengl = config->use_opengl;
565 +
566 +  if(use_opengl) {
567 +    surface.opengl.uv_left = 0;
568 +    surface.opengl.uv_top = 0;
569 +    surface.opengl.uv_right = texture->get_uv_right();
570 +    surface.opengl.uv_bottom = texture->get_uv_bottom();
571 +
572 +    surface.opengl.width = texture->get_image_width();
573 +    surface.opengl.height = texture->get_image_height();
574 +  } else {
575 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
576 +
577 +    surface.sdl.offsetx = 0;
578 +    surface.sdl.offsety = 0;
579 +    surface.sdl.width = static_cast<int>(texture->get_image_width());
580 +    surface.sdl.height = static_cast<int>(texture->get_image_height());
581 +
582 +    surface.sdl.flipx = false;
583 +  }
584  }
585  
586  Surface::Surface(const std::string& file, int x, int y, int w, int h)
587 @@ -55,15 +69,28 @@
588    texture = texture_manager->get(file);
589    texture->ref();
590  
591 -  float tex_w = static_cast<float> (texture->get_width());
592 -  float tex_h = static_cast<float> (texture->get_height());
593 -  uv_left = static_cast<float>(x) / tex_w;
594 -  uv_top = static_cast<float>(y) / tex_h;
595 -  uv_right = static_cast<float>(x+w) / tex_w;
596 -  uv_bottom = static_cast<float>(y+h) / tex_h;
597 +  use_opengl = config->use_opengl;
598  
599 -  width = w;
600 -  height = h;
601 +  if(use_opengl) {
602 +    float tex_w = static_cast<float> (texture->get_width());
603 +    float tex_h = static_cast<float> (texture->get_height());
604 +    surface.opengl.uv_left = static_cast<float>(x) / tex_w;
605 +    surface.opengl.uv_top = static_cast<float>(y) / tex_h;
606 +    surface.opengl.uv_right = static_cast<float>(x+w) / tex_w;
607 +    surface.opengl.uv_bottom = static_cast<float>(y+h) / tex_h;
608 +
609 +    surface.opengl.width = w;
610 +    surface.opengl.height = h;
611 +  } else {
612 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
613 +
614 +    surface.sdl.offsetx = x;
615 +    surface.sdl.offsety = y;
616 +    surface.sdl.width = w;
617 +    surface.sdl.height = h;
618 +
619 +    surface.sdl.flipx = false;
620 +  }
621  }
622  
623  Surface::Surface(const Surface& other)
624 @@ -71,12 +98,25 @@
625    texture = other.texture;
626    texture->ref();
627  
628 -  uv_left = other.uv_left;
629 -  uv_top = other.uv_top;
630 -  uv_right = other.uv_right;
631 -  uv_bottom = other.uv_bottom;
632 -  width = other.width;
633 -  height = other.height;
634 +  use_opengl = config->use_opengl;
635 +
636 +  if(use_opengl) {
637 +    surface.opengl.uv_left = other.surface.opengl.uv_left;
638 +    surface.opengl.uv_top = other.surface.opengl.uv_top;
639 +    surface.opengl.uv_right = other.surface.opengl.uv_right;
640 +    surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
641 +    surface.opengl.width = other.surface.opengl.width;
642 +    surface.opengl.height = other.surface.opengl.height;
643 +  } else {
644 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
645 +
646 +    surface.sdl.offsetx = other.surface.sdl.offsetx;
647 +    surface.sdl.offsety = other.surface.sdl.offsety;
648 +    surface.sdl.width = other.surface.sdl.width;
649 +    surface.sdl.height = other.surface.sdl.height;
650 +
651 +    surface.sdl.flipx = other.surface.sdl.flipx;
652 +  }
653  }
654  
655  const Surface&
656 @@ -86,25 +126,46 @@
657    texture->unref();
658    texture = other.texture;
659  
660 -  uv_left = other.uv_left;
661 -  uv_top = other.uv_top;
662 -  uv_right = other.uv_right;
663 -  uv_bottom = other.uv_bottom;
664 -  width = other.width;
665 -  height = other.height;
666 +  use_opengl = config->use_opengl;
667  
668 +  if(use_opengl) {
669 +    surface.opengl.uv_left = other.surface.opengl.uv_left;
670 +    surface.opengl.uv_top = other.surface.opengl.uv_top;
671 +    surface.opengl.uv_right = other.surface.opengl.uv_right;
672 +    surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
673 +    surface.opengl.width = other.surface.opengl.width;
674 +    surface.opengl.height = other.surface.opengl.height;
675 +  } else {
676 +    memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
677 +
678 +    surface.sdl.offsetx = other.surface.sdl.offsetx;
679 +    surface.sdl.offsety = other.surface.sdl.offsety;
680 +    surface.sdl.width = other.surface.sdl.width;
681 +    surface.sdl.height = other.surface.sdl.height;
682 +
683 +    surface.sdl.flipx = other.surface.sdl.flipx;
684 +  }
685 +
686    return *this;
687  }
688  
689  Surface::~Surface()
690  {
691    texture->unref();
692 +
693 +  if(!use_opengl) {
694 +    std::for_each(transforms, transforms + NUM_EFFECTS, SDL_FreeSurface);
695 +  }
696  }
697  
698  void
699  Surface::hflip()
700  {
701 -  std::swap(uv_left, uv_right);
702 +  if(use_opengl) {
703 +    std::swap(surface.opengl.uv_left, surface.opengl.uv_right);
704 +  } else {
705 +    surface.sdl.flipx = !surface.sdl.flipx;
706 +  }
707  }
708  
709  static inline void intern_draw(float left, float top, float right, float bottom,                               float uv_left, float uv_top,
710 @@ -186,28 +247,99 @@
711  void
712  Surface::draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const
713  {
714 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
715 -
716 -  intern_draw2(x, y,
717 -               x + width, y + height,
718 -               uv_left, uv_top, uv_right, uv_bottom,
719 -               angle,
720 -               alpha,
721 -               color,
722 -               blend,
723 -               effect);
724 +  if(use_opengl) {
725 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
726 +    intern_draw2(x, y,
727 +                 x + surface.opengl.width, y + surface.opengl.height,
728 +                 surface.opengl.uv_left, surface.opengl.uv_top,
729 +                 surface.opengl.uv_right, surface.opengl.uv_bottom,
730 +                 angle,
731 +                 alpha,
732 +                 color,
733 +                 blend,
734 +                 effect);
735 +  } else {
736 +    draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
737 +  }
738  }
739  
740  void
741  Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
742  {
743 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
744 +  if(use_opengl) {
745 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
746 +    glColor4f(1, 1, 1, alpha);
747 +    intern_draw(x, y,
748 +                x + surface.opengl.width, y + surface.opengl.height,
749 +                surface.opengl.uv_left, surface.opengl.uv_top,
750 +                surface.opengl.uv_right, surface.opengl.uv_bottom, effect);
751 +    glColor4f(1, 1, 1, 1);
752 +  } else {
753 +    draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
754 +  }
755 +}
756  
757 -  glColor4f(1, 1, 1, alpha);
758 -  intern_draw(x, y,
759 -              x + width, y + height,
760 -              uv_left, uv_top, uv_right, uv_bottom, effect);
761 -  glColor4f(1, 1, 1, 1);
762 +namespace
763 +{
764 +  SDL_Surface *horz_flip(SDL_Surface *src)
765 +  {
766 +    SDL_Surface *dst = SDL_ConvertSurface(src, src->format, src->flags);
767 +    int bpp = dst->format->BytesPerPixel;
768 +    for(int y = 0;y < dst->h;y++) {
769 +      Uint8 *line = (Uint8 *) dst->pixels + y * dst->pitch;
770 +      for(int x = 0;x < (dst->w / 2);x++) {
771 +        switch(bpp) {
772 +          case 4:
773 +            line[3 + x * bpp] ^= line[3 + (dst->w - x - 1) * bpp];
774 +            line[3 + (dst->w - x - 1) * bpp] ^= line[3 + x * bpp];
775 +            line[3 + x * bpp] ^= line[3 + (dst->w - x - 1) * bpp];
776 +          case 3:
777 +            line[2 + x * bpp] ^= line[2 + (dst->w - x - 1) * bpp];
778 +            line[2 + (dst->w - x - 1) * bpp] ^= line[2 + x * bpp];
779 +            line[2 + x * bpp] ^= line[2 + (dst->w - x - 1) * bpp];
780 +          case 2:
781 +            line[1 + x * bpp] ^= line[1 + (dst->w - x - 1) * bpp];
782 +            line[1 + (dst->w - x - 1) * bpp] ^= line[1 + x * bpp];
783 +            line[1 + x * bpp] ^= line[1 + (dst->w - x - 1) * bpp];
784 +          case 1:
785 +            line[0 + x * bpp] ^= line[0 + (dst->w - x - 1) * bpp];
786 +            line[0 + (dst->w - x - 1) * bpp] ^= line[0 + x * bpp];
787 +            line[0 + x * bpp] ^= line[0 + (dst->w - x - 1) * bpp];
788 +        }
789 +      }
790 +    }
791 +    return dst;
792 +  }
793 +
794 +  SDL_Surface *vert_flip(SDL_Surface *src)
795 +  {
796 +    SDL_Surface *dst = SDL_ConvertSurface(src, src->format, src->flags);
797 +    int bpp = dst->format->BytesPerPixel;
798 +    for(int x = 0;x < dst->w;x++) {
799 +      Uint8 *rank = (Uint8 *) dst->pixels + x * bpp;
800 +      for(int y = 0;y < (dst->h / 2);y++) {
801 +        switch(bpp) {
802 +          case 4:
803 +            rank[3 + y * dst->pitch] ^= rank[3 + (dst->h - y - 1) * dst->pitch];
804 +            rank[3 + (dst->h - y - 1) * dst->pitch] ^= rank[3 + y * dst->pitch];
805 +            rank[3 + y * dst->pitch] ^= rank[3 + (dst->h - y - 1) * dst->pitch];
806 +          case 3:
807 +            rank[2 + y * dst->pitch] ^= rank[2 + (dst->h - y - 1) * dst->pitch];
808 +            rank[2 + (dst->h - y - 1) * dst->pitch] ^= rank[2 + y * dst->pitch];
809 +            rank[2 + y * dst->pitch] ^= rank[2 + (dst->h - y - 1) * dst->pitch];
810 +          case 2:
811 +            rank[1 + y * dst->pitch] ^= rank[1 + (dst->h - y - 1) * dst->pitch];
812 +            rank[1 + (dst->h - y - 1) * dst->pitch] ^= rank[1 + y * dst->pitch];
813 +            rank[1 + y * dst->pitch] ^= rank[1 + (dst->h - y - 1) * dst->pitch];
814 +          case 1:
815 +            rank[0 + y * dst->pitch] ^= rank[0 + (dst->h - y - 1) * dst->pitch];
816 +            rank[0 + (dst->h - y - 1) * dst->pitch] ^= rank[0 + y * dst->pitch];
817 +            rank[0 + y * dst->pitch] ^= rank[0 + (dst->h - y - 1) * dst->pitch];
818 +        }
819 +      }
820 +    }
821 +    return dst;
822 +  }
823  }
824  
825  void
826 @@ -215,19 +347,65 @@
827                     float width, float height, float alpha,
828                     DrawingEffect effect) const
829  {
830 -  float uv_width = uv_right - uv_left;
831 -  float uv_height = uv_bottom - uv_top;
832 +  if(use_opengl) {
833 +    float uv_width = surface.opengl.uv_right - surface.opengl.uv_left;
834 +    float uv_height = surface.opengl.uv_bottom - surface.opengl.uv_top;
835  
836 -  float uv_left = this->uv_left + (uv_width * src_x) / this->width;
837 -  float uv_top = this->uv_top + (uv_height * src_y) / this->height;
838 -  float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
839 -  float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
840 +    float uv_left = surface.opengl.uv_left + (uv_width * src_x) / surface.opengl.width;
841 +    float uv_top = surface.opengl.uv_top + (uv_height * src_y) / surface.opengl.height;
842 +    float uv_right = surface.opengl.uv_left + (uv_width * (src_x + width)) / surface.opengl.width;
843 +    float uv_bottom = surface.opengl.uv_top + (uv_height * (src_y + height)) / surface.opengl.height;
844  
845 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
846 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
847 +    glColor4f(1, 1, 1, alpha);
848 +    intern_draw(dst_x, dst_y,
849 +                dst_x + width, dst_y + height,
850 +                uv_left, uv_top, uv_right, uv_bottom, effect);
851 +    glColor4f(1, 1, 1, 1);
852 +  } else {
853 +    //FIXME: support parameter "alpha"
854
855 +    // get and check SDL_Surface
856 +    if (texture->get_surface() == 0) {
857 +      std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
858 +      return;
859 +    }  
860  
861 -  glColor4f(1, 1, 1, alpha);
862 -  intern_draw(dst_x, dst_y,
863 -              dst_x + width, dst_y + height,
864 -              uv_left, uv_top, uv_right, uv_bottom, effect);
865 -  glColor4f(1, 1, 1, 1);
866 +    if (surface.sdl.flipx) effect = HORIZONTAL_FLIP;
867 +
868 +    if(transforms[effect] == 0) {
869 +      switch(effect) {
870 +        case NO_EFFECT:
871 +          transforms[NO_EFFECT] = texture->get_surface();
872 +          transforms[NO_EFFECT]->refcount++;
873 +          break;
874 +        case HORIZONTAL_FLIP:
875 +          transforms[HORIZONTAL_FLIP] = horz_flip(texture->get_surface());
876 +          break;
877 +        case VERTICAL_FLIP:
878 +          transforms[VERTICAL_FLIP] = vert_flip(texture->get_surface());
879 +          break;
880 +        default:
881 +          std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
882 +          return;
883 +      }
884 +    }
885 +
886 +    int ox = surface.sdl.offsetx; if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(transforms[effect]->w) - (ox+static_cast<int>(width));
887 +    int oy = surface.sdl.offsety; if (effect == VERTICAL_FLIP) oy = static_cast<int>(transforms[effect]->h) - (oy+static_cast<int>(height));
888 +    // draw surface to screen
889 +    SDL_Surface* screen = SDL_GetVideoSurface();
890 +
891 +    SDL_Rect srcRect;
892 +    srcRect.x = static_cast<int>(ox+src_x);
893 +    srcRect.y = static_cast<int>(oy+src_y);
894 +    srcRect.w = static_cast<int>(width);
895 +    srcRect.h = static_cast<int>(height);
896 +
897 +    SDL_Rect dstRect;
898 +    dstRect.x = static_cast<int>(dst_x);
899 +    dstRect.y = static_cast<int>(dst_y);
900 +
901 +    SDL_BlitSurface(transforms[effect], &srcRect, screen, &dstRect);
902 +  }
903  }
904 Index: src/video/texture_manager.cpp
905 ===================================================================
906 --- src/video/texture_manager.cpp       (revision 5066)
907 +++ src/video/texture_manager.cpp       (working copy)
908 @@ -32,6 +32,7 @@
909  #include "physfs/physfs_sdl.hpp"
910  #include "image_texture.hpp"
911  #include "glutil.hpp"
912 +#include "gameconfig.hpp"
913  #include "file_system.hpp"
914  #include "log.hpp"
915  
916 @@ -149,12 +150,14 @@
917  void
918  TextureManager::save_textures()
919  {
920 -  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
921 -  glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
922 -  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
923 -  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
924 -  glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
925 -  glPixelStorei(GL_PACK_ALIGNMENT, 1);
926 +  if(config->use_opengl) {
927 +    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
928 +    glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
929 +    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
930 +    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
931 +    glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
932 +    glPixelStorei(GL_PACK_ALIGNMENT, 1);
933 +  }
934    for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
935      save_texture(*i);
936    }
937 @@ -169,73 +172,81 @@
938  {
939    SavedTexture saved_texture;
940    saved_texture.texture = texture;
941 -  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
942 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
943 -                           &saved_texture.width);
944 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
945 -                           &saved_texture.height);
946 -  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
947 -                           &saved_texture.border);
948 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
949 -                      &saved_texture.min_filter);
950 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
951 -                      &saved_texture.mag_filter);
952 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
953 -                      &saved_texture.wrap_s);
954 -  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
955 -                      &saved_texture.wrap_t);
956 +  if(config->use_opengl) {
957 +    glBindTexture(GL_TEXTURE_2D, texture->get_handle());
958 +    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
959 +                             &saved_texture.width);
960 +    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
961 +                             &saved_texture.height);
962 +    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
963 +                             &saved_texture.border);
964 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
965 +                        &saved_texture.min_filter);
966 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
967 +                        &saved_texture.mag_filter);
968 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
969 +                        &saved_texture.wrap_s);
970 +    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
971 +                        &saved_texture.wrap_t);
972 +  }
973  
974    size_t pixelssize = saved_texture.width * saved_texture.height * 4;
975    saved_texture.pixels = new char[pixelssize];
976  
977 -  glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
978 -                saved_texture.pixels);
979 +  if(config->use_opengl) {
980 +    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
981 +                  saved_texture.pixels);
982 +  }
983  
984    saved_textures.push_back(saved_texture);
985  
986 -  glDeleteTextures(1, &(texture->handle));
987 -  texture->handle = 0;
988 +  if(config->use_opengl) {
989 +    glDeleteTextures(1, &(texture->get_handle()));
990 +    texture->set_handle(0);
991  
992 -  assert_gl("retrieving texture for save");
993 +    assert_gl("retrieving texture for save");
994 +  }
995  }
996  
997  void
998  TextureManager::reload_textures()
999  {
1000 -  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1001 -  glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1002 -  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1003 -  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1004 -  glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1005 -  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1006 +  if(config->use_opengl) {
1007 +    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1008 +    glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1009 +    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1010 +    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1011 +    glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1012 +    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1013  
1014 -  for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1015 -      i != saved_textures.end(); ++i) {
1016 -    SavedTexture& saved_texture = *i;
1017 +    for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1018 +        i != saved_textures.end(); ++i) {
1019 +      SavedTexture& saved_texture = *i;
1020  
1021 -    GLuint handle;
1022 -    glGenTextures(1, &handle);
1023 -    assert_gl("creating texture handle");
1024 +      GLuint handle;
1025 +      glGenTextures(1, &handle);
1026 +      assert_gl("creating texture handle");
1027  
1028 -    glBindTexture(GL_TEXTURE_2D, handle);
1029 -    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1030 -                 saved_texture.width, saved_texture.height,
1031 -                 saved_texture.border, GL_RGBA,
1032 -                 GL_UNSIGNED_BYTE, saved_texture.pixels);
1033 -    delete[] saved_texture.pixels;
1034 -    assert_gl("uploading texture pixel data");
1035 +      glBindTexture(GL_TEXTURE_2D, handle);
1036 +      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1037 +                   saved_texture.width, saved_texture.height,
1038 +                   saved_texture.border, GL_RGBA,
1039 +                   GL_UNSIGNED_BYTE, saved_texture.pixels);
1040 +      delete[] saved_texture.pixels;
1041 +      assert_gl("uploading texture pixel data");
1042  
1043 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1044 -                    saved_texture.min_filter);
1045 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1046 -                    saved_texture.mag_filter);
1047 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1048 -                    saved_texture.wrap_s);
1049 -    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1050 -                    saved_texture.wrap_t);
1051 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1052 +                      saved_texture.min_filter);
1053 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1054 +                      saved_texture.mag_filter);
1055 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1056 +                      saved_texture.wrap_s);
1057 +      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1058 +                      saved_texture.wrap_t);
1059  
1060 -    assert_gl("setting texture_params");
1061 -    saved_texture.texture->handle = handle;
1062 +      assert_gl("setting texture_params");
1063 +      saved_texture.texture->set_handle(handle);
1064 +    }
1065    }
1066  
1067    saved_textures.clear();
1068 Index: src/video/surface.hpp
1069 ===================================================================
1070 --- src/video/surface.hpp       (revision 5066)
1071 +++ src/video/surface.hpp       (working copy)
1072 @@ -21,6 +21,8 @@
1073  #define __SURFACE_HPP__
1074  
1075  #include <string>
1076 +#include <SDL.h>
1077 +#include "gameconfig.hpp"
1078  #include "math/vector.hpp"
1079  
1080  class Color;
1081 @@ -30,11 +32,12 @@
1082  /// bitset for drawing effects
1083  enum DrawingEffect {
1084    /** Don't apply anything */
1085 -  NO_EFFECT       = 0x0000,
1086 +  NO_EFFECT,
1087    /** Draw the Surface upside down */
1088 -  VERTICAL_FLIP     = 0x0001,
1089 +  VERTICAL_FLIP,
1090    /** Draw the Surface from left to down */
1091 -  HORIZONTAL_FLIP   = 0x0002,
1092 +  HORIZONTAL_FLIP,
1093 +  NUM_EFFECTS
1094  };
1095  
1096  /**
1097 @@ -47,21 +50,38 @@
1098  private:
1099    friend class DrawingContext;
1100    friend class Font;
1101 -  ImageTexture* texture;
1102  
1103 -  float uv_left;
1104 -  float uv_top;
1105 -  float uv_right;
1106 -  float uv_bottom;
1107 -
1108    void draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const;
1109    void draw(float x, float y, float alpha, DrawingEffect effect) const;
1110    void draw_part(float src_x, float src_y, float dst_x, float dst_y,
1111                   float width, float height,
1112                   float alpha, DrawingEffect effect) const;
1113  
1114 -  float width;
1115 -  float height;
1116 +  ImageTexture* texture;
1117 +  bool use_opengl;
1118 +  union
1119 +  {
1120 +    struct
1121 +    {
1122 +      float uv_left;
1123 +      float uv_top;
1124 +      float uv_right;
1125 +      float uv_bottom;
1126 +
1127 +      float width;
1128 +      float height;
1129 +    } opengl;
1130 +    struct
1131 +    {
1132 +      bool flipx;
1133 +      int offsetx; /**< Region in ::surface to be used for blitting */
1134 +      int offsety; /**< Region in ::surface to be used for blitting */
1135 +      int width;   /**< Region in ::surface to be used for blitting */
1136 +      int height;  /**< Region in ::surface to be used for blitting */
1137 +    } sdl;
1138 +  } surface;
1139 +  mutable SDL_Surface *transforms[NUM_EFFECTS]; /**< Cache for pre-transformed surfaces */
1140 +
1141  public:
1142    Surface(const std::string& file);
1143    Surface(const std::string& file, int x, int y, int w, int h);
1144 @@ -75,12 +95,20 @@
1145  
1146    float get_width() const
1147    {
1148 -    return width;
1149 +    if(use_opengl) {
1150 +      return surface.opengl.width;
1151 +    } else {
1152 +      return surface.sdl.width;
1153 +    }
1154    }
1155  
1156    float get_height() const
1157    {
1158 -    return height;
1159 +    if(use_opengl) {
1160 +      return surface.opengl.height;
1161 +    } else {
1162 +      return surface.sdl.height;
1163 +    }
1164    }
1165  
1166    /**
1167 Index: src/gameconfig.cpp
1168 ===================================================================
1169 --- src/gameconfig.cpp  (revision 5066)
1170 +++ src/gameconfig.cpp  (working copy)
1171 @@ -36,6 +36,7 @@
1172  Config::Config()
1173  {
1174    use_fullscreen = true;
1175 +  use_opengl = true;
1176    try_vsync = true;
1177    show_fps = false;
1178    sound_enabled = true;
1179 @@ -70,7 +71,8 @@
1180    const lisp::Lisp* config_video_lisp = config_lisp->get_lisp("video");
1181    if(config_video_lisp) {
1182      config_video_lisp->get("fullscreen", use_fullscreen);
1183 -       config_video_lisp->get("vsync", try_vsync);
1184 +    config_video_lisp->get("opengl", use_opengl);
1185 +    config_video_lisp->get("vsync", try_vsync);
1186      config_video_lisp->get("width", screenwidth);
1187      config_video_lisp->get("height", screenheight);
1188      config_video_lisp->get("aspect_ratio", aspect_ratio);
1189 @@ -100,6 +102,7 @@
1190  
1191    writer.start_list("video");
1192    writer.write_bool("fullscreen", use_fullscreen);
1193 +  writer.write_bool("opengl", use_opengl);
1194    writer.write_bool("vsync", try_vsync);
1195    writer.write_int("width", screenwidth);
1196    writer.write_int("height", screenheight);
1197 Index: src/main.cpp
1198 ===================================================================
1199 --- src/main.cpp        (revision 5066)
1200 +++ src/main.cpp        (working copy)
1201 @@ -383,7 +383,7 @@
1202    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
1203    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
1204  
1205 -  int flags = SDL_OPENGL;
1206 +  int flags = config->use_opengl ? SDL_OPENGL : SDL_SWSURFACE;
1207    if(config->use_fullscreen)
1208      flags |= SDL_FULLSCREEN;
1209    int width = config->screenwidth;
1210 @@ -437,23 +437,26 @@
1211  
1212    log_info << (config->use_fullscreen?"fullscreen ":"window ") << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << " Ratio: " << aspect_ratio << "\n";
1213  
1214 -  // setup opengl state and transform
1215 -  glDisable(GL_DEPTH_TEST);
1216 -  glDisable(GL_CULL_FACE);
1217 -  glEnable(GL_TEXTURE_2D);
1218 -  glEnable(GL_BLEND);
1219 -  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1220 +  if(config->use_opengl)
1221 +  {
1222 +    // setup opengl state and transform
1223 +    glDisable(GL_DEPTH_TEST);
1224 +    glDisable(GL_CULL_FACE);
1225 +    glEnable(GL_TEXTURE_2D);
1226 +    glEnable(GL_BLEND);
1227 +    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1228  
1229 -  glViewport(0, 0, screen->w, screen->h);
1230 -  glMatrixMode(GL_PROJECTION);
1231 -  glLoadIdentity();
1232 -  // logical resolution here not real monitor resolution
1233 -  glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
1234 -  glMatrixMode(GL_MODELVIEW);
1235 -  glLoadIdentity();
1236 -  glTranslatef(0, 0, 0);
1237 +    glViewport(0, 0, screen->w, screen->h);
1238 +    glMatrixMode(GL_PROJECTION);
1239 +    glLoadIdentity();
1240 +    // logical resolution here not real monitor resolution
1241 +    glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
1242 +    glMatrixMode(GL_MODELVIEW);
1243 +    glLoadIdentity();
1244 +    glTranslatef(0, 0, 0);
1245  
1246 -  check_gl_error("Setting up view matrices");
1247 +    check_gl_error("Setting up view matrices");
1248 +  }
1249  
1250    if(texture_manager != NULL)
1251      texture_manager->reload_textures();