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 5068. It may break for later revisions.
34 # -----------------------------------------------------------------------------
35 Index: src/gameconfig.hpp
36 ===================================================================
37 --- src/gameconfig.hpp (revision 5067)
38 +++ src/gameconfig.hpp (working copy)
47 Index: src/video/drawing_context.cpp
48 ===================================================================
49 --- src/video/drawing_context.cpp (revision 5067)
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 @@ -644,36 +728,42 @@
317 // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it?
319 - // create surface to hold screenshot
320 - #if SDL_BYTEORDER == SDL_BIG_ENDIAN
321 - SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
323 - SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
326 - log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
329 + SDL_Surface *shot_surf;
330 + if(config->use_opengl) {
331 + // create surface to hold screenshot
332 + #if SDL_BYTEORDER == SDL_BIG_ENDIAN
333 + shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
335 + shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
338 + log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
342 - // read pixels into array
343 - char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
345 - log_warning << "Could not allocate memory to store screenshot" << std::endl;
346 - SDL_FreeSurface(shot_surf);
349 - glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
350 + // read pixels into array
351 + char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
353 + log_warning << "Could not allocate memory to store screenshot" << std::endl;
354 + SDL_FreeSurface(shot_surf);
357 + glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
359 - // copy array line-by-line
360 - for (int i = 0; i < SCREEN_HEIGHT; i++) {
361 - char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
362 - char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
363 - memcpy(dst, src, 3 * SCREEN_WIDTH);
364 + // copy array line-by-line
365 + for (int i = 0; i < SCREEN_HEIGHT; i++) {
366 + char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
367 + char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
368 + memcpy(dst, src, 3 * SCREEN_WIDTH);
374 + shot_surf = SDL_GetVideoSurface();
375 + shot_surf->refcount++;
382 static const std::string writeDir = PHYSFS_getWriteDir();
383 static const std::string dirSep = PHYSFS_getDirSeparator();
384 Index: src/video/texture.cpp
385 ===================================================================
386 --- src/video/texture.cpp (revision 5067)
387 +++ src/video/texture.cpp (working copy)
391 #include "texture.hpp"
392 +#include "gameconfig.hpp"
398 assert(is_power_of_2(w));
399 assert(is_power_of_2(h));
400 + use_opengl = config->use_opengl;
406 + surface.opengl.width = w;
407 + surface.opengl.height = h;
409 - assert_gl("before creating texture");
410 - glGenTextures(1, &handle);
411 + assert_gl("before creating texture");
412 + glGenTextures(1, &surface.opengl.handle);
415 - glBindTexture(GL_TEXTURE_2D, handle);
417 + glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
419 - glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
420 - GL_UNSIGNED_BYTE, 0);
421 + glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
422 + surface.opengl.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
424 - set_texture_params();
426 - glDeleteTextures(1, &handle);
428 + set_texture_params();
430 + glDeleteTextures(1, &surface.opengl.handle);
440 Texture::Texture(SDL_Surface* image, GLenum glformat)
442 throw std::runtime_error("image has no power of 2 size");
443 if(format->BitsPerPixel != 24 && format->BitsPerPixel != 32)
444 throw std::runtime_error("image has no 24 or 32 bit color depth");
445 + use_opengl = config->use_opengl;
447 - this->width = image->w;
448 - this->height = image->h;
451 + surface.opengl.width = image->w;
452 + surface.opengl.height = image->h;
454 - assert_gl("before creating texture");
455 - glGenTextures(1, &handle);
456 + assert_gl("before creating texture");
457 + glGenTextures(1, &surface.opengl.handle);
461 - if(format->BytesPerPixel == 3)
462 - sdl_format = GL_RGB;
463 - else if(format->BytesPerPixel == 4)
464 - sdl_format = GL_RGBA;
469 + if(format->BytesPerPixel == 3)
470 + sdl_format = GL_RGB;
471 + else if(format->BytesPerPixel == 4)
472 + sdl_format = GL_RGBA;
476 - glBindTexture(GL_TEXTURE_2D, handle);
477 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
478 - glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
479 - glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
480 - GL_UNSIGNED_BYTE, image->pixels);
481 + glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
482 + glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
483 + glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
484 + glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
485 + surface.opengl.height, 0, sdl_format,
486 + GL_UNSIGNED_BYTE, image->pixels);
488 - assert_gl("creating texture");
489 + assert_gl("creating texture");
491 - set_texture_params();
493 - glDeleteTextures(1, &handle);
495 + set_texture_params();
497 + glDeleteTextures(1, &surface.opengl.handle);
501 + surface.sdl = SDL_DisplayFormatAlpha(image);
507 - glDeleteTextures(1, &handle);
509 + glDeleteTextures(1, &surface.opengl.handle);
511 + SDL_FreeSurface(surface.sdl);
516 Texture::set_texture_params()
518 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
519 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
520 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
521 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
523 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
524 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
525 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
526 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
528 - assert_gl("set texture params");
529 + assert_gl("set texture params");
532 Index: src/video/texture.hpp
533 ===================================================================
534 --- src/video/texture.hpp (revision 5067)
535 +++ src/video/texture.hpp (working copy)
537 #ifndef __TEXTURE_HPP__
538 #define __TEXTURE_HPP__
545 +#include "gameconfig.hpp"
548 * This class is a wrapper around a texture handle. It stores the texture width
549 * and height and provides convenience functions for uploading SDL_Surfaces
554 - friend class TextureManager;
556 - unsigned int width;
557 - unsigned int height;
562 + unsigned int width;
563 + unsigned int height;
569 Texture(unsigned int width, unsigned int height, GLenum glformat);
570 - Texture(SDL_Surface* surface, GLenum glformat);
571 + Texture(SDL_Surface* sdlsurface, GLenum glformat);
574 - GLuint get_handle() const
577 + const GLuint &get_handle() const {
578 + assert(use_opengl);
579 + return surface.opengl.handle;
582 + void set_handle(GLuint handle) {
583 + assert(use_opengl);
584 + surface.opengl.handle = handle;
587 + SDL_Surface *get_surface() const {
588 + assert(!use_opengl);
589 + return surface.sdl;
592 + void set_surface(SDL_Surface *sdlsurface) {
593 + assert(!use_opengl);
594 + surface.sdl = sdlsurface;
597 unsigned int get_width() const
601 + return surface.opengl.width;
603 + return surface.sdl->w;
607 unsigned int get_height() const
611 + return surface.opengl.height;
613 + return surface.sdl->h;
618 Index: src/video/surface.cpp
619 ===================================================================
620 --- src/video/surface.cpp (revision 5067)
621 +++ src/video/surface.cpp (working copy)
624 texture = texture_manager->get(file);
628 - uv_right = texture->get_uv_right();
629 - uv_bottom = texture->get_uv_bottom();
631 - width = texture->get_image_width();
632 - height = texture->get_image_height();
633 + use_opengl = config->use_opengl;
636 + surface.opengl.uv_left = 0;
637 + surface.opengl.uv_top = 0;
638 + surface.opengl.uv_right = texture->get_uv_right();
639 + surface.opengl.uv_bottom = texture->get_uv_bottom();
641 + surface.opengl.width = texture->get_image_width();
642 + surface.opengl.height = texture->get_image_height();
644 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
646 + surface.sdl.offsetx = 0;
647 + surface.sdl.offsety = 0;
648 + surface.sdl.width = static_cast<int>(texture->get_image_width());
649 + surface.sdl.height = static_cast<int>(texture->get_image_height());
651 + surface.sdl.flipx = false;
655 Surface::Surface(const std::string& file, int x, int y, int w, int h)
657 texture = texture_manager->get(file);
660 - float tex_w = static_cast<float> (texture->get_width());
661 - float tex_h = static_cast<float> (texture->get_height());
662 - uv_left = static_cast<float>(x) / tex_w;
663 - uv_top = static_cast<float>(y) / tex_h;
664 - uv_right = static_cast<float>(x+w) / tex_w;
665 - uv_bottom = static_cast<float>(y+h) / tex_h;
666 + use_opengl = config->use_opengl;
671 + float tex_w = static_cast<float> (texture->get_width());
672 + float tex_h = static_cast<float> (texture->get_height());
673 + surface.opengl.uv_left = static_cast<float>(x) / tex_w;
674 + surface.opengl.uv_top = static_cast<float>(y) / tex_h;
675 + surface.opengl.uv_right = static_cast<float>(x+w) / tex_w;
676 + surface.opengl.uv_bottom = static_cast<float>(y+h) / tex_h;
678 + surface.opengl.width = w;
679 + surface.opengl.height = h;
681 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
683 + surface.sdl.offsetx = x;
684 + surface.sdl.offsety = y;
685 + surface.sdl.width = w;
686 + surface.sdl.height = h;
688 + surface.sdl.flipx = false;
692 Surface::Surface(const Surface& other)
694 texture = other.texture;
697 - uv_left = other.uv_left;
698 - uv_top = other.uv_top;
699 - uv_right = other.uv_right;
700 - uv_bottom = other.uv_bottom;
701 - width = other.width;
702 - height = other.height;
703 + use_opengl = config->use_opengl;
706 + surface.opengl.uv_left = other.surface.opengl.uv_left;
707 + surface.opengl.uv_top = other.surface.opengl.uv_top;
708 + surface.opengl.uv_right = other.surface.opengl.uv_right;
709 + surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
710 + surface.opengl.width = other.surface.opengl.width;
711 + surface.opengl.height = other.surface.opengl.height;
713 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
715 + surface.sdl.offsetx = other.surface.sdl.offsetx;
716 + surface.sdl.offsety = other.surface.sdl.offsety;
717 + surface.sdl.width = other.surface.sdl.width;
718 + surface.sdl.height = other.surface.sdl.height;
720 + surface.sdl.flipx = other.surface.sdl.flipx;
727 texture = other.texture;
729 - uv_left = other.uv_left;
730 - uv_top = other.uv_top;
731 - uv_right = other.uv_right;
732 - uv_bottom = other.uv_bottom;
733 - width = other.width;
734 - height = other.height;
735 + use_opengl = config->use_opengl;
738 + surface.opengl.uv_left = other.surface.opengl.uv_left;
739 + surface.opengl.uv_top = other.surface.opengl.uv_top;
740 + surface.opengl.uv_right = other.surface.opengl.uv_right;
741 + surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
742 + surface.opengl.width = other.surface.opengl.width;
743 + surface.opengl.height = other.surface.opengl.height;
745 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
747 + surface.sdl.offsetx = other.surface.sdl.offsetx;
748 + surface.sdl.offsety = other.surface.sdl.offsety;
749 + surface.sdl.width = other.surface.sdl.width;
750 + surface.sdl.height = other.surface.sdl.height;
752 + surface.sdl.flipx = other.surface.sdl.flipx;
763 + std::for_each(transforms, transforms + NUM_EFFECTS, SDL_FreeSurface);
770 - std::swap(uv_left, uv_right);
772 + std::swap(surface.opengl.uv_left, surface.opengl.uv_right);
774 + surface.sdl.flipx = !surface.sdl.flipx;
778 static inline void intern_draw(float left, float top, float right, float bottom, float uv_left, float uv_top,
779 @@ -186,28 +247,99 @@
781 Surface::draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const
783 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
786 - x + width, y + height,
787 - uv_left, uv_top, uv_right, uv_bottom,
794 + glBindTexture(GL_TEXTURE_2D, texture->get_handle());
796 + x + surface.opengl.width, y + surface.opengl.height,
797 + surface.opengl.uv_left, surface.opengl.uv_top,
798 + surface.opengl.uv_right, surface.opengl.uv_bottom,
805 + draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
810 Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
812 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
814 + glBindTexture(GL_TEXTURE_2D, texture->get_handle());
815 + glColor4f(1, 1, 1, alpha);
817 + x + surface.opengl.width, y + surface.opengl.height,
818 + surface.opengl.uv_left, surface.opengl.uv_top,
819 + surface.opengl.uv_right, surface.opengl.uv_bottom, effect);
820 + glColor4f(1, 1, 1, 1);
822 + draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
826 - glColor4f(1, 1, 1, alpha);
828 - x + width, y + height,
829 - uv_left, uv_top, uv_right, uv_bottom, effect);
830 - glColor4f(1, 1, 1, 1);
833 + SDL_Surface *horz_flip(SDL_Surface *src)
835 + SDL_Surface *dst = SDL_ConvertSurface(src, src->format, src->flags);
836 + int bpp = dst->format->BytesPerPixel;
837 + for(int y = 0;y < dst->h;y++) {
838 + Uint8 *line = (Uint8 *) dst->pixels + y * dst->pitch;
839 + for(int x = 0;x < (dst->w / 2);x++) {
842 + line[3 + x * bpp] ^= line[3 + (dst->w - x - 1) * bpp];
843 + line[3 + (dst->w - x - 1) * bpp] ^= line[3 + x * bpp];
844 + line[3 + x * bpp] ^= line[3 + (dst->w - x - 1) * bpp];
846 + line[2 + x * bpp] ^= line[2 + (dst->w - x - 1) * bpp];
847 + line[2 + (dst->w - x - 1) * bpp] ^= line[2 + x * bpp];
848 + line[2 + x * bpp] ^= line[2 + (dst->w - x - 1) * bpp];
850 + line[1 + x * bpp] ^= line[1 + (dst->w - x - 1) * bpp];
851 + line[1 + (dst->w - x - 1) * bpp] ^= line[1 + x * bpp];
852 + line[1 + x * bpp] ^= line[1 + (dst->w - x - 1) * bpp];
854 + line[0 + x * bpp] ^= line[0 + (dst->w - x - 1) * bpp];
855 + line[0 + (dst->w - x - 1) * bpp] ^= line[0 + x * bpp];
856 + line[0 + x * bpp] ^= line[0 + (dst->w - x - 1) * bpp];
863 + SDL_Surface *vert_flip(SDL_Surface *src)
865 + SDL_Surface *dst = SDL_ConvertSurface(src, src->format, src->flags);
866 + int bpp = dst->format->BytesPerPixel;
867 + for(int x = 0;x < dst->w;x++) {
868 + Uint8 *rank = (Uint8 *) dst->pixels + x * bpp;
869 + for(int y = 0;y < (dst->h / 2);y++) {
872 + rank[3 + y * dst->pitch] ^= rank[3 + (dst->h - y - 1) * dst->pitch];
873 + rank[3 + (dst->h - y - 1) * dst->pitch] ^= rank[3 + y * dst->pitch];
874 + rank[3 + y * dst->pitch] ^= rank[3 + (dst->h - y - 1) * dst->pitch];
876 + rank[2 + y * dst->pitch] ^= rank[2 + (dst->h - y - 1) * dst->pitch];
877 + rank[2 + (dst->h - y - 1) * dst->pitch] ^= rank[2 + y * dst->pitch];
878 + rank[2 + y * dst->pitch] ^= rank[2 + (dst->h - y - 1) * dst->pitch];
880 + rank[1 + y * dst->pitch] ^= rank[1 + (dst->h - y - 1) * dst->pitch];
881 + rank[1 + (dst->h - y - 1) * dst->pitch] ^= rank[1 + y * dst->pitch];
882 + rank[1 + y * dst->pitch] ^= rank[1 + (dst->h - y - 1) * dst->pitch];
884 + rank[0 + y * dst->pitch] ^= rank[0 + (dst->h - y - 1) * dst->pitch];
885 + rank[0 + (dst->h - y - 1) * dst->pitch] ^= rank[0 + y * dst->pitch];
886 + rank[0 + y * dst->pitch] ^= rank[0 + (dst->h - y - 1) * dst->pitch];
895 @@ -215,19 +347,65 @@
896 float width, float height, float alpha,
897 DrawingEffect effect) const
899 - float uv_width = uv_right - uv_left;
900 - float uv_height = uv_bottom - uv_top;
902 + float uv_width = surface.opengl.uv_right - surface.opengl.uv_left;
903 + float uv_height = surface.opengl.uv_bottom - surface.opengl.uv_top;
905 - float uv_left = this->uv_left + (uv_width * src_x) / this->width;
906 - float uv_top = this->uv_top + (uv_height * src_y) / this->height;
907 - float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
908 - float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
909 + float uv_left = surface.opengl.uv_left + (uv_width * src_x) / surface.opengl.width;
910 + float uv_top = surface.opengl.uv_top + (uv_height * src_y) / surface.opengl.height;
911 + float uv_right = surface.opengl.uv_left + (uv_width * (src_x + width)) / surface.opengl.width;
912 + float uv_bottom = surface.opengl.uv_top + (uv_height * (src_y + height)) / surface.opengl.height;
914 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
915 + glBindTexture(GL_TEXTURE_2D, texture->get_handle());
916 + glColor4f(1, 1, 1, alpha);
917 + intern_draw(dst_x, dst_y,
918 + dst_x + width, dst_y + height,
919 + uv_left, uv_top, uv_right, uv_bottom, effect);
920 + glColor4f(1, 1, 1, 1);
922 + //FIXME: support parameter "alpha"
924 + // get and check SDL_Surface
925 + if (texture->get_surface() == 0) {
926 + std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
930 - glColor4f(1, 1, 1, alpha);
931 - intern_draw(dst_x, dst_y,
932 - dst_x + width, dst_y + height,
933 - uv_left, uv_top, uv_right, uv_bottom, effect);
934 - glColor4f(1, 1, 1, 1);
935 + if (surface.sdl.flipx) effect = HORIZONTAL_FLIP;
937 + if(transforms[effect] == 0) {
940 + transforms[NO_EFFECT] = texture->get_surface();
941 + transforms[NO_EFFECT]->refcount++;
943 + case HORIZONTAL_FLIP:
944 + transforms[HORIZONTAL_FLIP] = horz_flip(texture->get_surface());
946 + case VERTICAL_FLIP:
947 + transforms[VERTICAL_FLIP] = vert_flip(texture->get_surface());
950 + std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
955 + int ox = surface.sdl.offsetx; if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(transforms[effect]->w) - (ox+static_cast<int>(width));
956 + int oy = surface.sdl.offsety; if (effect == VERTICAL_FLIP) oy = static_cast<int>(transforms[effect]->h) - (oy+static_cast<int>(height));
957 + // draw surface to screen
958 + SDL_Surface* screen = SDL_GetVideoSurface();
961 + srcRect.x = static_cast<int>(ox+src_x);
962 + srcRect.y = static_cast<int>(oy+src_y);
963 + srcRect.w = static_cast<int>(width);
964 + srcRect.h = static_cast<int>(height);
967 + dstRect.x = static_cast<int>(dst_x);
968 + dstRect.y = static_cast<int>(dst_y);
970 + SDL_BlitSurface(transforms[effect], &srcRect, screen, &dstRect);
973 Index: src/video/texture_manager.cpp
974 ===================================================================
975 --- src/video/texture_manager.cpp (revision 5067)
976 +++ src/video/texture_manager.cpp (working copy)
978 #include "physfs/physfs_sdl.hpp"
979 #include "image_texture.hpp"
980 #include "glutil.hpp"
981 +#include "gameconfig.hpp"
982 #include "file_system.hpp"
985 @@ -149,12 +150,14 @@
987 TextureManager::save_textures()
989 - glPixelStorei(GL_PACK_ROW_LENGTH, 0);
990 - glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
991 - glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
992 - glPixelStorei(GL_PACK_SKIP_ROWS, 0);
993 - glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
994 - glPixelStorei(GL_PACK_ALIGNMENT, 1);
995 + if(config->use_opengl) {
996 + glPixelStorei(GL_PACK_ROW_LENGTH, 0);
997 + glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
998 + glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
999 + glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1000 + glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
1001 + glPixelStorei(GL_PACK_ALIGNMENT, 1);
1003 for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
1006 @@ -169,73 +172,81 @@
1008 SavedTexture saved_texture;
1009 saved_texture.texture = texture;
1010 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1011 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
1012 - &saved_texture.width);
1013 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
1014 - &saved_texture.height);
1015 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
1016 - &saved_texture.border);
1017 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1018 - &saved_texture.min_filter);
1019 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1020 - &saved_texture.mag_filter);
1021 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1022 - &saved_texture.wrap_s);
1023 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1024 - &saved_texture.wrap_t);
1025 + if(config->use_opengl) {
1026 + glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1027 + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
1028 + &saved_texture.width);
1029 + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
1030 + &saved_texture.height);
1031 + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
1032 + &saved_texture.border);
1033 + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1034 + &saved_texture.min_filter);
1035 + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1036 + &saved_texture.mag_filter);
1037 + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1038 + &saved_texture.wrap_s);
1039 + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1040 + &saved_texture.wrap_t);
1043 size_t pixelssize = saved_texture.width * saved_texture.height * 4;
1044 saved_texture.pixels = new char[pixelssize];
1046 - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1047 - saved_texture.pixels);
1048 + if(config->use_opengl) {
1049 + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1050 + saved_texture.pixels);
1053 saved_textures.push_back(saved_texture);
1055 - glDeleteTextures(1, &(texture->handle));
1056 - texture->handle = 0;
1057 + if(config->use_opengl) {
1058 + glDeleteTextures(1, &(texture->get_handle()));
1059 + texture->set_handle(0);
1061 - assert_gl("retrieving texture for save");
1062 + assert_gl("retrieving texture for save");
1067 TextureManager::reload_textures()
1069 - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1070 - glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1071 - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1072 - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1073 - glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1074 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1075 + if(config->use_opengl) {
1076 + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1077 + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1078 + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1079 + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1080 + glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1081 + glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1083 - for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1084 - i != saved_textures.end(); ++i) {
1085 - SavedTexture& saved_texture = *i;
1086 + for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1087 + i != saved_textures.end(); ++i) {
1088 + SavedTexture& saved_texture = *i;
1091 - glGenTextures(1, &handle);
1092 - assert_gl("creating texture handle");
1094 + glGenTextures(1, &handle);
1095 + assert_gl("creating texture handle");
1097 - glBindTexture(GL_TEXTURE_2D, handle);
1098 - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1099 - saved_texture.width, saved_texture.height,
1100 - saved_texture.border, GL_RGBA,
1101 - GL_UNSIGNED_BYTE, saved_texture.pixels);
1102 - delete[] saved_texture.pixels;
1103 - assert_gl("uploading texture pixel data");
1104 + glBindTexture(GL_TEXTURE_2D, handle);
1105 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1106 + saved_texture.width, saved_texture.height,
1107 + saved_texture.border, GL_RGBA,
1108 + GL_UNSIGNED_BYTE, saved_texture.pixels);
1109 + delete[] saved_texture.pixels;
1110 + assert_gl("uploading texture pixel data");
1112 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1113 - saved_texture.min_filter);
1114 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1115 - saved_texture.mag_filter);
1116 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1117 - saved_texture.wrap_s);
1118 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1119 - saved_texture.wrap_t);
1120 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1121 + saved_texture.min_filter);
1122 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1123 + saved_texture.mag_filter);
1124 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1125 + saved_texture.wrap_s);
1126 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1127 + saved_texture.wrap_t);
1129 - assert_gl("setting texture_params");
1130 - saved_texture.texture->handle = handle;
1131 + assert_gl("setting texture_params");
1132 + saved_texture.texture->set_handle(handle);
1136 saved_textures.clear();
1137 Index: src/video/surface.hpp
1138 ===================================================================
1139 --- src/video/surface.hpp (revision 5067)
1140 +++ src/video/surface.hpp (working copy)
1142 #define __SURFACE_HPP__
1146 +#include "gameconfig.hpp"
1147 #include "math/vector.hpp"
1151 /// bitset for drawing effects
1152 enum DrawingEffect {
1153 /** Don't apply anything */
1154 - NO_EFFECT = 0x0000,
1156 /** Draw the Surface upside down */
1157 - VERTICAL_FLIP = 0x0001,
1159 /** Draw the Surface from left to down */
1160 - HORIZONTAL_FLIP = 0x0002,
1168 friend class DrawingContext;
1170 - ImageTexture* texture;
1177 void draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const;
1178 void draw(float x, float y, float alpha, DrawingEffect effect) const;
1179 void draw_part(float src_x, float src_y, float dst_x, float dst_y,
1180 float width, float height,
1181 float alpha, DrawingEffect effect) const;
1185 + ImageTexture* texture;
1202 + int offsetx; /**< Region in ::surface to be used for blitting */
1203 + int offsety; /**< Region in ::surface to be used for blitting */
1204 + int width; /**< Region in ::surface to be used for blitting */
1205 + int height; /**< Region in ::surface to be used for blitting */
1208 + mutable SDL_Surface *transforms[NUM_EFFECTS]; /**< Cache for pre-transformed surfaces */
1211 Surface(const std::string& file);
1212 Surface(const std::string& file, int x, int y, int w, int h);
1215 float get_width() const
1219 + return surface.opengl.width;
1221 + return surface.sdl.width;
1225 float get_height() const
1229 + return surface.opengl.height;
1231 + return surface.sdl.height;
1236 Index: src/gameconfig.cpp
1237 ===================================================================
1238 --- src/gameconfig.cpp (revision 5067)
1239 +++ src/gameconfig.cpp (working copy)
1243 use_fullscreen = true;
1244 + use_opengl = true;
1247 sound_enabled = true;
1249 const lisp::Lisp* config_video_lisp = config_lisp->get_lisp("video");
1250 if(config_video_lisp) {
1251 config_video_lisp->get("fullscreen", use_fullscreen);
1252 - config_video_lisp->get("vsync", try_vsync);
1253 + config_video_lisp->get("opengl", use_opengl);
1254 + config_video_lisp->get("vsync", try_vsync);
1255 config_video_lisp->get("width", screenwidth);
1256 config_video_lisp->get("height", screenheight);
1257 config_video_lisp->get("aspect_ratio", aspect_ratio);
1260 writer.start_list("video");
1261 writer.write_bool("fullscreen", use_fullscreen);
1262 + writer.write_bool("opengl", use_opengl);
1263 writer.write_bool("vsync", try_vsync);
1264 writer.write_int("width", screenwidth);
1265 writer.write_int("height", screenheight);
1267 ===================================================================
1268 --- src/main.cpp (revision 5067)
1269 +++ src/main.cpp (working copy)
1271 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
1272 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
1274 - int flags = SDL_OPENGL;
1275 + int flags = config->use_opengl ? SDL_OPENGL : SDL_SWSURFACE;
1276 if(config->use_fullscreen)
1277 flags |= SDL_FULLSCREEN;
1278 int width = config->screenwidth;
1279 @@ -437,23 +437,26 @@
1281 log_info << (config->use_fullscreen?"fullscreen ":"window ") << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << " Ratio: " << aspect_ratio << "\n";
1283 - // setup opengl state and transform
1284 - glDisable(GL_DEPTH_TEST);
1285 - glDisable(GL_CULL_FACE);
1286 - glEnable(GL_TEXTURE_2D);
1287 - glEnable(GL_BLEND);
1288 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1289 + if(config->use_opengl)
1291 + // setup opengl state and transform
1292 + glDisable(GL_DEPTH_TEST);
1293 + glDisable(GL_CULL_FACE);
1294 + glEnable(GL_TEXTURE_2D);
1295 + glEnable(GL_BLEND);
1296 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1298 - glViewport(0, 0, screen->w, screen->h);
1299 - glMatrixMode(GL_PROJECTION);
1301 - // logical resolution here not real monitor resolution
1302 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
1303 - glMatrixMode(GL_MODELVIEW);
1305 - glTranslatef(0, 0, 0);
1306 + glViewport(0, 0, screen->w, screen->h);
1307 + glMatrixMode(GL_PROJECTION);
1309 + // logical resolution here not real monitor resolution
1310 + glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
1311 + glMatrixMode(GL_MODELVIEW);
1313 + glTranslatef(0, 0, 0);
1315 - check_gl_error("Setting up view matrices");
1316 + check_gl_error("Setting up view matrices");
1319 if(texture_manager != NULL)
1320 texture_manager->reload_textures();