3 # Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
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.
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.
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.
19 # -----------------------------------------------------------------------------
21 # This patch allows running the game on systems without OpenGL support.
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.
27 # Installing the patch should be pretty straightforward. Simply run the
28 # following command prior to running autogen.sh and configure:
30 # patch -p0 < contrib/supertux-nogl.diff
32 # This patch works for revision 5065. It may break for later revisions.
34 # -----------------------------------------------------------------------------
35 Index: src/gameconfig.hpp
36 ===================================================================
37 --- src/gameconfig.hpp (revision 5066)
38 +++ src/gameconfig.hpp (working copy)
47 Index: src/video/drawing_context.cpp
48 ===================================================================
49 --- src/video/drawing_context.cpp (revision 5066)
50 +++ src/video/drawing_context.cpp (working copy)
53 DrawingContext::get_light(const Vector& position, Color* color)
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);
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);
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);
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);
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);
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);
93 + i += 1; i &= 0xFFFF;
95 + *color = Color(0.0f, 0.0f, 0.0f);
97 + *color = Color(1.0f, 1.0f, 1.0f);
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);
109 @@ -370,16 +380,47 @@
110 const Color& top = gradientrequest->top;
111 const Color& bottom = gradientrequest->bottom;
113 - glDisable(GL_TEXTURE_2D);
115 - glColor4f(top.red, top.green, top.blue, top.alpha);
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);
122 - glEnable(GL_TEXTURE_2D);
123 + if(config->use_opengl)
125 + glDisable(GL_TEXTURE_2D);
127 + glColor4f(top.red, top.green, top.blue, top.alpha);
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);
134 + glEnable(GL_TEXTURE_2D);
138 + for(int y = 0;y < screen->h;++y)
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);
149 + rect.w = screen->w;
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);
157 + SDL_FillRect(temp, 0, color);
158 + SDL_SetAlpha(temp, SDL_SRCALPHA, a);
159 + SDL_BlitSurface(temp, 0, screen, &rect);
160 + SDL_FreeSurface(temp);
164 glColor4f(1, 1, 1, 1);
167 @@ -398,22 +439,48 @@
168 const FillRectRequest* fillrectrequest
169 = (FillRectRequest*) request.request_data;
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)
177 + float x = request.pos.x;
178 + float y = request.pos.y;
179 + float w = fillrectrequest->size.x;
180 + float h = fillrectrequest->size.y;
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);
191 - glVertex2f(x+w, y);
192 - glVertex2f(x+w, y+h);
193 - glVertex2f(x, y+h);
195 - glEnable(GL_TEXTURE_2D);
198 + glVertex2f(x+w, y);
199 + glVertex2f(x+w, y+h);
200 + glVertex2f(x, y+h);
202 + glEnable(GL_TEXTURE_2D);
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);
221 + SDL_FillRect(temp, 0, color);
222 + SDL_SetAlpha(temp, SDL_SRCALPHA, a);
223 + SDL_BlitSurface(temp, 0, screen, &rect);
224 + SDL_FreeSurface(temp);
228 glColor4f(1, 1, 1, 1);
230 @@ -462,29 +529,36 @@
232 // PART1: create lightmap
234 - glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
235 - glMatrixMode(GL_PROJECTION);
237 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
238 - glMatrixMode(GL_MODELVIEW);
240 + if(config->use_opengl)
242 + glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
243 + glMatrixMode(GL_PROJECTION);
245 + glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
246 + glMatrixMode(GL_MODELVIEW);
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();
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);
265 - glViewport(0, 0, screen->w, screen->h);
266 - glMatrixMode(GL_PROJECTION);
268 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
269 - glMatrixMode(GL_MODELVIEW);
271 - glEnable(GL_BLEND);
272 + glViewport(0, 0, screen->w, screen->h);
273 + glMatrixMode(GL_PROJECTION);
275 + glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
276 + glMatrixMode(GL_MODELVIEW);
278 + glEnable(GL_BLEND);
282 + // FIXME: SDL alternative
285 // add a lightmap drawing request into the queue
286 DrawingRequest* request = new(obst) DrawingRequest();
288 drawing_requests.clear();
289 obstack_free(&obst, NULL);
291 - assert_gl("drawing");
292 + if(config->use_opengl)
294 + assert_gl("drawing");
297 // if a screenshot was requested, take one
298 if (screenshot_requested) {
300 screenshot_requested = false;
303 - SDL_GL_SwapBuffers();
304 + if(config->use_opengl)
306 + SDL_GL_SwapBuffers();
314 class RequestPtrCompare
315 Index: src/video/texture.cpp
316 ===================================================================
317 --- src/video/texture.cpp (revision 5066)
318 +++ src/video/texture.cpp (working copy)
322 #include "texture.hpp"
323 +#include "gameconfig.hpp"
329 assert(is_power_of_2(w));
330 assert(is_power_of_2(h));
331 + use_opengl = config->use_opengl;
337 + surface.opengl.width = w;
338 + surface.opengl.height = h;
340 - assert_gl("before creating texture");
341 - glGenTextures(1, &handle);
342 + assert_gl("before creating texture");
343 + glGenTextures(1, &surface.opengl.handle);
346 - glBindTexture(GL_TEXTURE_2D, handle);
348 + glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
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);
355 - set_texture_params();
357 - glDeleteTextures(1, &handle);
359 + set_texture_params();
361 + glDeleteTextures(1, &surface.opengl.handle);
371 Texture::Texture(SDL_Surface* image, GLenum glformat)
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;
378 - this->width = image->w;
379 - this->height = image->h;
382 + surface.opengl.width = image->w;
383 + surface.opengl.height = image->h;
385 - assert_gl("before creating texture");
386 - glGenTextures(1, &handle);
387 + assert_gl("before creating texture");
388 + glGenTextures(1, &surface.opengl.handle);
392 - if(format->BytesPerPixel == 3)
393 - sdl_format = GL_RGB;
394 - else if(format->BytesPerPixel == 4)
395 - sdl_format = GL_RGBA;
400 + if(format->BytesPerPixel == 3)
401 + sdl_format = GL_RGB;
402 + else if(format->BytesPerPixel == 4)
403 + sdl_format = GL_RGBA;
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);
419 - assert_gl("creating texture");
420 + assert_gl("creating texture");
422 - set_texture_params();
424 - glDeleteTextures(1, &handle);
426 + set_texture_params();
428 + glDeleteTextures(1, &surface.opengl.handle);
432 + surface.sdl = SDL_DisplayFormatAlpha(image);
438 - glDeleteTextures(1, &handle);
440 + glDeleteTextures(1, &surface.opengl.handle);
442 + SDL_FreeSurface(surface.sdl);
447 Texture::set_texture_params()
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);
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);
459 - assert_gl("set texture params");
460 + assert_gl("set texture params");
463 Index: src/video/texture.hpp
464 ===================================================================
465 --- src/video/texture.hpp (revision 5066)
466 +++ src/video/texture.hpp (working copy)
468 #ifndef __TEXTURE_HPP__
469 #define __TEXTURE_HPP__
476 +#include "gameconfig.hpp"
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
485 - friend class TextureManager;
487 - unsigned int width;
488 - unsigned int height;
493 + unsigned int width;
494 + unsigned int height;
500 Texture(unsigned int width, unsigned int height, GLenum glformat);
501 - Texture(SDL_Surface* surface, GLenum glformat);
502 + Texture(SDL_Surface* sdlsurface, GLenum glformat);
505 - GLuint get_handle() const
508 + const GLuint &get_handle() const {
509 + assert(use_opengl);
510 + return surface.opengl.handle;
513 + void set_handle(GLuint handle) {
514 + assert(use_opengl);
515 + surface.opengl.handle = handle;
518 + SDL_Surface *get_surface() const {
519 + assert(!use_opengl);
520 + return surface.sdl;
523 + void set_surface(SDL_Surface *sdlsurface) {
524 + assert(!use_opengl);
525 + surface.sdl = sdlsurface;
528 unsigned int get_width() const
532 + return surface.opengl.width;
534 + return surface.sdl->w;
538 unsigned int get_height() const
542 + return surface.opengl.height;
544 + return surface.sdl->h;
549 Index: src/video/surface.cpp
550 ===================================================================
551 --- src/video/surface.cpp (revision 5066)
552 +++ src/video/surface.cpp (working copy)
555 texture = texture_manager->get(file);
559 - uv_right = texture->get_uv_right();
560 - uv_bottom = texture->get_uv_bottom();
562 - width = texture->get_image_width();
563 - height = texture->get_image_height();
564 + use_opengl = config->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();
572 + surface.opengl.width = texture->get_image_width();
573 + surface.opengl.height = texture->get_image_height();
575 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
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());
582 + surface.sdl.flipx = false;
586 Surface::Surface(const std::string& file, int x, int y, int w, int h)
588 texture = texture_manager->get(file);
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;
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;
609 + surface.opengl.width = w;
610 + surface.opengl.height = h;
612 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
614 + surface.sdl.offsetx = x;
615 + surface.sdl.offsety = y;
616 + surface.sdl.width = w;
617 + surface.sdl.height = h;
619 + surface.sdl.flipx = false;
623 Surface::Surface(const Surface& other)
625 texture = other.texture;
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;
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;
644 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
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;
651 + surface.sdl.flipx = other.surface.sdl.flipx;
658 texture = other.texture;
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;
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;
676 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
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;
683 + surface.sdl.flipx = other.surface.sdl.flipx;
694 + std::for_each(transforms, transforms + NUM_EFFECTS, SDL_FreeSurface);
701 - std::swap(uv_left, uv_right);
703 + std::swap(surface.opengl.uv_left, surface.opengl.uv_right);
705 + surface.sdl.flipx = !surface.sdl.flipx;
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 @@
712 Surface::draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const
714 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
717 - x + width, y + height,
718 - uv_left, uv_top, uv_right, uv_bottom,
725 + glBindTexture(GL_TEXTURE_2D, texture->get_handle());
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,
736 + draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
741 Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
743 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
745 + glBindTexture(GL_TEXTURE_2D, texture->get_handle());
746 + glColor4f(1, 1, 1, alpha);
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);
753 + draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
757 - glColor4f(1, 1, 1, alpha);
759 - x + width, y + height,
760 - uv_left, uv_top, uv_right, uv_bottom, effect);
761 - glColor4f(1, 1, 1, 1);
764 + SDL_Surface *horz_flip(SDL_Surface *src)
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++) {
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];
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];
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];
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];
794 + SDL_Surface *vert_flip(SDL_Surface *src)
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++) {
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];
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];
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];
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];
826 @@ -215,19 +347,65 @@
827 float width, float height, float alpha,
828 DrawingEffect effect) const
830 - float uv_width = uv_right - uv_left;
831 - float uv_height = uv_bottom - uv_top;
833 + float uv_width = surface.opengl.uv_right - surface.opengl.uv_left;
834 + float uv_height = surface.opengl.uv_bottom - surface.opengl.uv_top;
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;
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);
853 + //FIXME: support parameter "alpha"
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;
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;
868 + if(transforms[effect] == 0) {
871 + transforms[NO_EFFECT] = texture->get_surface();
872 + transforms[NO_EFFECT]->refcount++;
874 + case HORIZONTAL_FLIP:
875 + transforms[HORIZONTAL_FLIP] = horz_flip(texture->get_surface());
877 + case VERTICAL_FLIP:
878 + transforms[VERTICAL_FLIP] = vert_flip(texture->get_surface());
881 + std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
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();
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);
898 + dstRect.x = static_cast<int>(dst_x);
899 + dstRect.y = static_cast<int>(dst_y);
901 + SDL_BlitSurface(transforms[effect], &srcRect, screen, &dstRect);
904 Index: src/video/texture_manager.cpp
905 ===================================================================
906 --- src/video/texture_manager.cpp (revision 5066)
907 +++ src/video/texture_manager.cpp (working copy)
909 #include "physfs/physfs_sdl.hpp"
910 #include "image_texture.hpp"
911 #include "glutil.hpp"
912 +#include "gameconfig.hpp"
913 #include "file_system.hpp"
916 @@ -149,12 +150,14 @@
918 TextureManager::save_textures()
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);
934 for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
937 @@ -169,73 +172,81 @@
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);
974 size_t pixelssize = saved_texture.width * saved_texture.height * 4;
975 saved_texture.pixels = new char[pixelssize];
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);
984 saved_textures.push_back(saved_texture);
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);
992 - assert_gl("retrieving texture for save");
993 + assert_gl("retrieving texture for save");
998 TextureManager::reload_textures()
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);
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;
1022 - glGenTextures(1, &handle);
1023 - assert_gl("creating texture handle");
1025 + glGenTextures(1, &handle);
1026 + assert_gl("creating texture handle");
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");
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);
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);
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)
1073 #define __SURFACE_HPP__
1077 +#include "gameconfig.hpp"
1078 #include "math/vector.hpp"
1082 /// bitset for drawing effects
1083 enum DrawingEffect {
1084 /** Don't apply anything */
1085 - NO_EFFECT = 0x0000,
1087 /** Draw the Surface upside down */
1088 - VERTICAL_FLIP = 0x0001,
1090 /** Draw the Surface from left to down */
1091 - HORIZONTAL_FLIP = 0x0002,
1099 friend class DrawingContext;
1101 - ImageTexture* texture;
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;
1116 + ImageTexture* texture;
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 */
1139 + mutable SDL_Surface *transforms[NUM_EFFECTS]; /**< Cache for pre-transformed surfaces */
1142 Surface(const std::string& file);
1143 Surface(const std::string& file, int x, int y, int w, int h);
1146 float get_width() const
1150 + return surface.opengl.width;
1152 + return surface.sdl.width;
1156 float get_height() const
1160 + return surface.opengl.height;
1162 + return surface.sdl.height;
1167 Index: src/gameconfig.cpp
1168 ===================================================================
1169 --- src/gameconfig.cpp (revision 5066)
1170 +++ src/gameconfig.cpp (working copy)
1174 use_fullscreen = true;
1175 + use_opengl = true;
1178 sound_enabled = true;
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);
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);
1198 ===================================================================
1199 --- src/main.cpp (revision 5066)
1200 +++ src/main.cpp (working copy)
1202 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
1203 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
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 @@
1212 log_info << (config->use_fullscreen?"fullscreen ":"window ") << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << " Ratio: " << aspect_ratio << "\n";
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)
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);
1229 - glViewport(0, 0, screen->w, screen->h);
1230 - glMatrixMode(GL_PROJECTION);
1232 - // logical resolution here not real monitor resolution
1233 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
1234 - glMatrixMode(GL_MODELVIEW);
1236 - glTranslatef(0, 0, 0);
1237 + glViewport(0, 0, screen->w, screen->h);
1238 + glMatrixMode(GL_PROJECTION);
1240 + // logical resolution here not real monitor resolution
1241 + glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
1242 + glMatrixMode(GL_MODELVIEW);
1244 + glTranslatef(0, 0, 0);
1246 - check_gl_error("Setting up view matrices");
1247 + check_gl_error("Setting up view matrices");
1250 if(texture_manager != NULL)
1251 texture_manager->reload_textures();