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 # Note that the patched sources will need an additional library, SDL_gfx, to
30 # Installing the patch should be pretty straightforward. Simply run the
31 # following command prior to running autogen.sh and configure:
33 # patch -p1 < contrib/supertux-nogl.diff
35 # -----------------------------------------------------------------------------
36 diff -Naur -x .svn -x build -x doxygen supertux/INSTALL supertux-nogl/INSTALL
37 --- supertux/INSTALL 2006-03-03 21:49:07.000000000 +0100
38 +++ supertux-nogl/INSTALL 2006-04-07 04:13:00.000000000 +0200
40 - Install instructions for SuperTux -
41 http://supertux.berlios.de/
43 -Last update: October 11, 2005 by Ondra Hosek
44 +Last update: March 4, 2006 by Christoph Sommer
49 Download: ftp://ftp.perforce.com/pub/jam
50 Homepage: http://www.perforce.com/jam/jam.html
52 -* OpenGL headers and libraries
53 - opengl libraries and headers are specific to your graphics card. Make sure
54 - that you have hardware accelerated opengl drivers installed. Software
55 - renderers like Mesa will make supertux unplayable slow.
57 * SDL 1.2.5 or later (1.2.8 is recommended on MacOS/X)
60 * SDL_image (any version)
61 http://www.libsdl.org/projects/SDL_image
63 +* SDL_gfx (2.0.13 or later)
64 + http://www.ferzkopp.net/Software/SDL_gfx-2.0/
66 * PhysicsFS (1.0.0, the development branch 1.1.x is buggy and does not work,
67 1.2.0 and later should work when it is released)
68 http://www.icculus.org/physfs
69 diff -Naur -x .svn -x build -x doxygen supertux/README supertux-nogl/README
70 --- supertux/README 2006-03-03 20:43:38.000000000 +0100
71 +++ supertux-nogl/README 2006-04-07 04:13:00.000000000 +0200
73 - An introduction for SuperTux -
74 http://supertux.berlios.de/
76 -Last update: October 13, 2005
77 +Last update: March 4, 2006 by Christoph Sommer
82 Also, notice that SuperTux saves the options, so it's often enough to
85 - The game uses OpenGL to render the graphics. You will either need a CPU
86 - with about 10 GHz or an accelerated video card with the vendor's drivers.
87 - (On Linux, the team recommends using cards from NVidia with the proprietary
88 - drivers, but ATI or another verndor should do.)
89 + The game uses SDL to render the graphics. You will either need a CPU
90 + with about 1 GHz or go get the original version of SuperTux which uses
95 diff -Naur -x .svn -x build -x doxygen supertux/configure.ac supertux-nogl/configure.ac
96 --- supertux/configure.ac 2006-03-03 20:43:38.000000000 +0100
97 +++ supertux-nogl/configure.ac 2006-04-07 04:13:00.000000000 +0200
100 dnl Process this file with autoconf to produce a configure script.
102 -AC_INIT(supertux, 0.2-svn)
103 +AC_INIT(supertux, 0.2-nogl-svn)
104 AC_CONFIG_SRCDIR([src/main.cpp])
105 AC_CONFIG_AUX_DIR([mk/autoconf])
108 [AC_MSG_ERROR([Please install SDLImage >= 1.2.1])],
109 [$SDL_CFLAGS], [$SDL_LIBS])
111 +dnl FIXME: This is far from perfect
112 +NP_FINDLIB([SDLGFX], [SDL_gfx], [SDL_gfx >= 2.0.13],
113 + NP_LANG_PROGRAM([#include <SDL_rotozoom.h>], [0;]),
116 + [AC_MSG_ERROR([Please install SDL_gfx >= 2.0.13])],
117 + [$SDL_CFLAGS], [$SDL_LIBS])
119 NP_FINDLIB([PHYSFS], [physfs], [physfs >= 1.0.0],
123 [AC_MSG_ERROR([Please intall OpenAL])],
127 -if test "$no_gl" = "yes"; then
128 - AC_MSG_ERROR([Please install opengl libraries and headers])
131 dnl Checks for library functions.
132 AC_CHECK_FUNCS(mkdir strdup strstr)
134 diff -Naur -x .svn -x build -x doxygen supertux/src/Jamfile supertux-nogl/src/Jamfile
135 --- supertux/src/Jamfile 2006-03-03 20:34:49.000000000 +0100
136 +++ supertux-nogl/src/Jamfile 2006-04-07 04:11:50.000000000 +0200
138 Application supertux : $(sources) $(wrapper_objects) ;
139 C++Flags supertux : -DAPPDATADIR='\"$(appdatadir)\"' ;
140 LinkWith supertux : squirrel ;
141 -ExternalLibs supertux : SDL SDLIMAGE GL OPENAL VORBIS VORBISFILE OGG ICONV PHYSFS BINRELOC ;
142 +ExternalLibs supertux : SDL SDLIMAGE SDLGFX OPENAL VORBIS VORBISFILE OGG ICONV PHYSFS BINRELOC ;
143 Help supertux : "Build the supertux executable" ;
144 IncludeDir supertux : squirrel/include ;
146 diff -Naur -x .svn -x build -x doxygen supertux/src/main.cpp supertux-nogl/src/main.cpp
147 --- supertux/src/main.cpp 2006-04-07 03:32:14.000000000 +0200
148 +++ supertux-nogl/src/main.cpp 2006-04-07 04:11:50.000000000 +0200
152 #include <SDL_image.h>
153 -#include <SDL_opengl.h>
155 #include "gameconfig.hpp"
156 #include "resources.hpp"
161 -static void check_gl_error()
163 - GLenum glerror = glGetError();
164 - std::string errormsg;
166 - if(glerror != GL_NO_ERROR) {
168 - case GL_INVALID_ENUM:
169 - errormsg = "Invalid enumeration value";
171 - case GL_INVALID_VALUE:
172 - errormsg = "Numeric argzment out of range";
174 - case GL_INVALID_OPERATION:
175 - errormsg = "Invalid operation";
177 - case GL_STACK_OVERFLOW:
178 - errormsg = "stack overflow";
180 - case GL_STACK_UNDERFLOW:
181 - errormsg = "stack underflow";
183 - case GL_OUT_OF_MEMORY:
184 - errormsg = "out of memory";
186 - case GL_TABLE_TOO_LARGE:
187 - errormsg = "table too large";
190 - errormsg = "unknown error number";
193 - std::stringstream msg;
194 - msg << "OpenGL Error: " << errormsg;
195 - throw std::runtime_error(msg.str());
201 if(texture_manager != NULL)
203 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
204 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
206 - int flags = SDL_OPENGL;
207 + int flags = SDL_SWSURFACE;
208 if(config->use_fullscreen)
209 flags |= SDL_FULLSCREEN;
210 int width = config->screenwidth;
215 - // setup opengl state and transform
216 - glDisable(GL_DEPTH_TEST);
217 - glDisable(GL_CULL_FACE);
218 - glEnable(GL_TEXTURE_2D);
219 - glEnable(GL_BLEND);
220 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
222 - glViewport(0, 0, screen->w, screen->h);
223 - glMatrixMode(GL_PROJECTION);
225 - // logical resolution here not real monitor resolution
226 - glOrtho(0, 800, 600, 0, -1.0, 1.0);
227 - glMatrixMode(GL_MODELVIEW);
229 - glTranslatef(0, 0, 0);
233 if(texture_manager != NULL)
234 texture_manager->reload_textures();
236 diff -Naur -x .svn -x build -x doxygen supertux/src/video/drawing_context.cpp supertux-nogl/src/video/drawing_context.cpp
237 --- supertux/src/video/drawing_context.cpp 2006-03-31 04:18:01.000000000 +0200
238 +++ supertux-nogl/src/video/drawing_context.cpp 2006-04-07 04:11:49.000000000 +0200
242 #include <SDL_image.h>
246 #include "drawing_context.hpp"
247 #include "surface.hpp"
250 screen = SDL_GetVideoSurface();
252 - lightmap_width = screen->w / LIGHTMAP_DIV;
253 - lightmap_height = screen->h / LIGHTMAP_DIV;
254 - unsigned int width = next_po2(lightmap_width);
255 - unsigned int height = next_po2(lightmap_height);
257 - lightmap = new Texture(width, height, GL_RGB);
259 - lightmap_uv_right = static_cast<float>(lightmap_width) / static_cast<float>(width);
260 - lightmap_uv_bottom = static_cast<float>(lightmap_height) / static_cast<float>(height);
261 - texture_manager->register_texture(lightmap);
264 requests = &drawing_requests;
267 DrawingContext::~DrawingContext()
269 - texture_manager->remove_texture(lightmap);
274 DrawingContext::draw_surface(const Surface* surface, const Vector& position,
277 + if(target != NORMAL) return;
279 assert(surface != 0);
281 DrawingRequest request;
283 DrawingContext::draw_surface_part(const Surface* surface, const Vector& source,
284 const Vector& size, const Vector& dest, int layer)
286 + if(target != NORMAL) return;
288 assert(surface != 0);
290 DrawingRequest request;
292 DrawingContext::draw_text(const Font* font, const std::string& text,
293 const Vector& position, FontAlignment alignment, int layer)
295 + if(target != NORMAL) return;
297 DrawingRequest request;
301 DrawingContext::draw_center_text(const Font* font, const std::string& text,
302 const Vector& position, int layer)
304 + if(target != NORMAL) return;
306 draw_text(font, text, Vector(position.x + SCREEN_WIDTH/2, position.y),
307 CENTER_ALLIGN, layer);
311 DrawingContext::draw_gradient(const Color& top, const Color& bottom, int layer)
313 + if(target != NORMAL) return;
315 DrawingRequest request;
317 request.type = GRADIENT;
319 DrawingContext::draw_filled_rect(const Vector& topleft, const Vector& size,
320 const Color& color, int layer)
322 + if(target != NORMAL) return;
324 DrawingRequest request;
326 request.type = FILLRECT;
327 @@ -218,23 +216,55 @@
328 delete surfacepartrequest;
333 + void fillrect(SDL_Surface* screen, float x, float y, float w, float h, int r, int g, int b, int a)
344 + SDL_Rect src, rect;
345 + SDL_Surface *temp = NULL;
353 + temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
360 + SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, r, g, b));
361 + SDL_SetAlpha(temp, SDL_SRCALPHA, a);
362 + SDL_BlitSurface(temp,0,screen,&rect);
363 + SDL_FreeSurface(temp);
365 + SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
371 DrawingContext::draw_gradient(DrawingRequest& request)
373 GradientRequest* gradientrequest = (GradientRequest*) request.request_data;
374 const Color& top = gradientrequest->top;
375 const Color& bottom = gradientrequest->bottom;
377 - glDisable(GL_TEXTURE_2D);
379 - glColor4f(top.red, top.green, top.blue, top.alpha);
381 - glVertex2f(SCREEN_WIDTH, 0);
382 - glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
383 - glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
384 - glVertex2f(0, SCREEN_HEIGHT);
386 - glEnable(GL_TEXTURE_2D);
390 + for(float y = 0; y < height; y += 2) ::fillrect(screen, 0, (int)y, width, 2, (int)(((float)(top.red-bottom.red)/(0-height)) * y + top.red), (int)(((float)(top.green-bottom.green)/(0-height)) * y + top.green), (int)(((float)(top.blue-bottom.blue)/(0-height)) * y + top.blue), 255);
392 delete gradientrequest;
394 @@ -260,17 +290,12 @@
395 float w = fillrectrequest->size.x;
396 float h = fillrectrequest->size.y;
398 - glDisable(GL_TEXTURE_2D);
399 - glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
400 - fillrectrequest->color.blue, fillrectrequest->color.alpha);
404 - glVertex2f(x+w, y);
405 - glVertex2f(x+w, y+h);
406 - glVertex2f(x, y+h);
408 - glEnable(GL_TEXTURE_2D);
409 + int r = static_cast<int>(fillrectrequest->color.red);
410 + int g = static_cast<int>(fillrectrequest->color.green);
411 + int b = static_cast<int>(fillrectrequest->color.blue);
412 + int a = static_cast<int>(fillrectrequest->color.alpha);
414 + ::fillrect(screen, x, y, w, h, r, g, b, a);
416 delete fillrectrequest;
418 @@ -285,66 +310,10 @@
419 transformstack.clear();
420 target_stack.clear();
422 - bool use_lightmap = lightmap_requests.size() != 0;
424 - // PART1: create lightmap
426 - glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
427 - glMatrixMode(GL_PROJECTION);
429 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
430 - glMatrixMode(GL_MODELVIEW);
433 - //glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
434 - glClearColor(0, 0, 0, 1);
435 - glClear(GL_COLOR_BUFFER_BIT);
436 - handle_drawing_requests(lightmap_requests);
437 - lightmap_requests.clear();
439 - glDisable(GL_BLEND);
440 - glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
441 - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
443 - glViewport(0, 0, screen->w, screen->h);
444 - glMatrixMode(GL_PROJECTION);
446 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
447 - glMatrixMode(GL_MODELVIEW);
449 - glEnable(GL_BLEND);
452 - //glClear(GL_COLOR_BUFFER_BIT);
453 handle_drawing_requests(drawing_requests);
454 drawing_requests.clear();
457 - glBlendFunc(GL_SRC_ALPHA, GL_ONE);
459 - glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
462 - glTexCoord2f(0, lightmap_uv_bottom);
465 - glTexCoord2f(lightmap_uv_right, lightmap_uv_bottom);
466 - glVertex2f(SCREEN_WIDTH, 0);
468 - glTexCoord2f(lightmap_uv_right, 0);
469 - glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
471 - glTexCoord2f(0, 0);
472 - glVertex2f(0, SCREEN_HEIGHT);
476 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
479 - assert_gl("drawing");
481 - SDL_GL_SwapBuffers();
487 DrawingContext::set_target(Target target)
489 this->target = target;
490 - if(target == LIGHTMAP)
491 - requests = &lightmap_requests;
493 - requests = &drawing_requests;
496 diff -Naur -x .svn -x build -x doxygen supertux/src/video/drawing_context.hpp supertux-nogl/src/video/drawing_context.hpp
497 --- supertux/src/video/drawing_context.hpp 2006-03-03 20:34:27.000000000 +0100
498 +++ supertux-nogl/src/video/drawing_context.hpp 2006-04-07 04:11:49.000000000 +0200
511 +#include "glutil.hpp"
516 // some constants for predefined layer values
518 @@ -202,16 +202,12 @@
519 void draw_filled_rect(DrawingRequest& request);
521 DrawingRequests drawing_requests;
522 - DrawingRequests lightmap_requests;
524 DrawingRequests* requests;
528 std::vector<Target> target_stack;
530 - int lightmap_width, lightmap_height;
531 - float lightmap_uv_right, lightmap_uv_bottom;
535 diff -Naur -x .svn -x build -x doxygen supertux/src/video/glutil.hpp supertux-nogl/src/video/glutil.hpp
536 --- supertux/src/video/glutil.hpp 2006-03-21 16:13:11.000000000 +0100
537 +++ supertux-nogl/src/video/glutil.hpp 2006-04-07 04:11:49.000000000 +0200
544 -static inline void assert_gl(const char* message)
547 - GLenum error = glGetError();
548 - if(error != GL_NO_ERROR) {
549 - std::ostringstream msg;
550 - msg << "OpenGLError while '" << message << "': ";
552 - case GL_INVALID_ENUM:
553 - msg << "INVALID_ENUM: An unacceptable value is specified for an "
554 - "enumerated argument.";
556 - case GL_INVALID_VALUE:
557 - msg << "INVALID_VALUE: A numeric argument is out of range.";
559 - case GL_INVALID_OPERATION:
560 - msg << "INVALID_OPERATION: The specified operation is not allowed "
561 - "in the current state.";
563 - case GL_STACK_OVERFLOW:
564 - msg << "STACK_OVERFLOW: This command would cause a stack overflow.";
566 - case GL_STACK_UNDERFLOW:
567 - msg << "STACK_UNDERFLOW: This command would cause a stack underflow.";
569 - case GL_OUT_OF_MEMORY:
570 - msg << "OUT_OF_MEMORY: There is not enough memory left to execute the "
574 - msg << "Unknown error (code " << error << ")";
577 - throw std::runtime_error(msg.str());
582 +#define GL_SRC_ALPHA 0
583 +#define GL_ONE_MINUS_SRC_ALPHA 1
590 diff -Naur -x .svn -x build -x doxygen supertux/src/video/screen.cpp supertux-nogl/src/video/screen.cpp
591 --- supertux/src/video/screen.cpp 2006-04-07 03:32:13.000000000 +0200
592 +++ supertux-nogl/src/video/screen.cpp 2006-04-07 04:11:49.000000000 +0200
595 static const float LOOP_DELAY = 20.0;
597 -void fillrect(float x, float y, float w, float h, const Color& col)
608 - glColor4f(col.red, col.green, col.blue, col.alpha);
610 - glDisable(GL_TEXTURE_2D);
611 - glBegin(GL_POLYGON);
613 - glVertex2f(x+w, y);
614 - glVertex2f(x+w, y+h);
615 - glVertex2f(x, y+h);
617 - glEnable(GL_TEXTURE_2D);
619 - glColor4f(0, 0, 0, 1);
620 +void fillrect(float x, float y, float w, float h, int r, int g, int b, int a)
622 + SDL_Surface* screen = SDL_GetVideoSurface();
633 + SDL_Rect src, rect;
634 + SDL_Surface *temp = NULL;
642 + temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
649 + SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, r, g, b));
650 + SDL_SetAlpha(temp, SDL_SRCALPHA, a);
651 + SDL_BlitSurface(temp,0,screen,&rect);
652 + SDL_FreeSurface(temp);
655 + SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
658 void fadeout(float fade_time)
660 - float alpha_inc = LOOP_DELAY / fade_time;
661 - Color c(0, 0, 0, alpha_inc);
663 + float alpha_inc = 256 / (fade_time / LOOP_DELAY);
666 - while(alpha >= 0) {
669 - fillrect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, c);
671 + fillrect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0,0,0, (int)alpha_inc); // left side
673 - SDL_GL_SwapBuffers();
674 + SDL_Flip(SDL_GetVideoSurface());
675 sound_manager->update();
677 SDL_Delay(int(LOOP_DELAY));
678 - alpha -= alpha_inc;
681 - fillrect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, Color());
682 + fillrect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0, 255);
685 void shrink_fade(const Vector& point, float fade_time)
687 - float left_inc = point.x / (fade_time / LOOP_DELAY);
688 - float right_inc = (SCREEN_WIDTH - point.x) / (fade_time / LOOP_DELAY);
689 - float up_inc = point.y / (fade_time / LOOP_DELAY);
690 - float down_inc = (SCREEN_HEIGHT - point.y) / (fade_time / LOOP_DELAY);
691 + float left_inc = point.x / ((float)fade_time / LOOP_DELAY);
692 + float right_inc = (SCREEN_WIDTH - point.x) / ((float)fade_time / LOOP_DELAY);
693 + float up_inc = point.y / ((float)fade_time / LOOP_DELAY);
694 + float down_inc = (SCREEN_HEIGHT - point.y) / ((float)fade_time / LOOP_DELAY);
696 float left_cor = 0, right_cor = 0, up_cor = 0, down_cor = 0;
699 while(left_cor < point.x && right_cor < SCREEN_WIDTH - point.x &&
700 up_cor < point.y && down_cor < SCREEN_HEIGHT - point.y) {
701 @@ -101,15 +110,14 @@
703 down_cor += down_inc;
705 - fillrect(0, 0, left_cor, SCREEN_HEIGHT, c); // left side
706 - fillrect(SCREEN_WIDTH - right_cor, 0, right_cor, SCREEN_HEIGHT, c); // right side
707 - fillrect(0, 0, SCREEN_WIDTH, up_cor, c); // up side
708 - fillrect(0, SCREEN_HEIGHT - down_cor, SCREEN_WIDTH, down_cor+1, c); // down side
709 + fillrect(0, 0, left_cor, SCREEN_HEIGHT, 0,0,0, 255); // left side
710 + fillrect(SCREEN_WIDTH - right_cor, 0, right_cor, SCREEN_HEIGHT, 0,0,0, 255); // right side
711 + fillrect(0, 0, SCREEN_WIDTH, up_cor, 0,0,0, 255); // up side
712 + fillrect(0, SCREEN_HEIGHT - down_cor, SCREEN_WIDTH, down_cor+1, 0,0,0, 255); // down side
714 - SDL_GL_SwapBuffers();
715 + SDL_Flip(SDL_GetVideoSurface());
717 sound_manager->update();
718 SDL_Delay(int(LOOP_DELAY));
722 diff -Naur -x .svn -x build -x doxygen supertux/src/video/screen.hpp supertux-nogl/src/video/screen.hpp
723 --- supertux/src/video/screen.hpp 2006-04-07 03:32:13.000000000 +0200
724 +++ supertux-nogl/src/video/screen.hpp 2006-04-07 04:11:49.000000000 +0200
726 #define SUPERTUX_SCREEN_H
733 diff -Naur -x .svn -x build -x doxygen supertux/src/video/surface.cpp supertux-nogl/src/video/surface.cpp
734 --- supertux/src/video/surface.cpp 2006-03-25 01:16:31.000000000 +0100
735 +++ supertux-nogl/src/video/surface.cpp 2006-04-07 04:11:49.000000000 +0200
739 #include <SDL_image.h>
740 +#include <SDL_rotozoom.h>
742 #include "gameconfig.hpp"
743 #include "physfs/physfs_sdl.hpp"
746 texture = texture_manager->get(file);
750 - uv_right = texture->get_uv_right();
751 - uv_bottom = texture->get_uv_bottom();
753 - width = texture->get_image_width();
754 - height = texture->get_image_height();
757 + width = static_cast<int>(texture->get_image_width());
758 + height = static_cast<int>(texture->get_image_height());
763 Surface::Surface(const std::string& file, int x, int y, int w, int h)
765 texture = texture_manager->get(file);
768 - float tex_w = static_cast<float> (texture->get_width());
769 - float tex_h = static_cast<float> (texture->get_height());
770 - uv_left = static_cast<float>(x) / tex_w;
771 - uv_top = static_cast<float>(y) / tex_h;
772 - uv_right = static_cast<float>(x+w) / tex_w;
773 - uv_bottom = static_cast<float>(y+h) / tex_h;
783 Surface::Surface(const Surface& other)
785 texture = other.texture;
788 - uv_left = other.uv_left;
789 - uv_top = other.uv_top;
790 - uv_right = other.uv_right;
791 - uv_bottom = other.uv_bottom;
792 + offsetx = other.offsetx;
793 + offsety = other.offsety;
795 height = other.height;
797 + flipx = other.flipx;
803 texture = other.texture;
805 - uv_left = other.uv_left;
806 - uv_top = other.uv_top;
807 - uv_right = other.uv_right;
808 - uv_bottom = other.uv_bottom;
809 + offsetx = other.offsetx;
810 + offsety = other.offsety;
812 height = other.height;
814 + flipx = other.flipx;
823 + for (std::list<TransformedSurface*>::iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
824 + SDL_FreeSurface((*i)->surface);
832 - std::swap(uv_left, uv_right);
835 -static inline void intern_draw(float left, float top, float right, float bottom, float uv_left, float uv_top,
836 - float uv_right, float uv_bottom,
837 - DrawingEffect effect)
839 - if(effect & HORIZONTAL_FLIP)
840 - std::swap(uv_left, uv_right);
841 - if(effect & VERTICAL_FLIP) {
842 - std::swap(uv_top, uv_bottom);
846 - glTexCoord2f(uv_left, uv_top);
847 - glVertex2f(left, top);
849 - glTexCoord2f(uv_right, uv_top);
850 - glVertex2f(right, top);
852 - glTexCoord2f(uv_right, uv_bottom);
853 - glVertex2f(right, bottom);
855 - glTexCoord2f(uv_left, uv_bottom);
856 - glVertex2f(left, bottom);
862 Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
864 - glColor4f(1.0f, 1.0f, 1.0f, alpha);
865 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
868 - x + width, y + height,
869 - uv_left, uv_top, uv_right, uv_bottom, effect);
870 + draw_part(0, 0, x, y, width, height, alpha, effect);
874 Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
875 - float width, float height, float alpha,
876 + float width, float height, float,
877 DrawingEffect effect) const
879 - float uv_width = uv_right - uv_left;
880 - float uv_height = uv_bottom - uv_top;
882 - float uv_left = this->uv_left + (uv_width * src_x) / this->width;
883 - float uv_top = this->uv_top + (uv_height * src_y) / this->height;
884 - float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
885 - float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
887 - glColor4f(1.0f, 1.0f, 1.0f, alpha);
888 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
890 - intern_draw(dst_x, dst_y,
891 - dst_x + width, dst_y + height,
892 - uv_left, uv_top, uv_right, uv_bottom, effect);
893 + //FIXME: support parameter "alpha"
894 + SDL_Surface* surface = texture->getSurface();
896 + // get and check SDL_Surface
897 + if (surface == 0) {
898 + std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
902 + SDL_Surface* transformedSurface = surface;
904 + if (flipx) effect = HORIZONTAL_FLIP;
906 + if (effect != NO_EFFECT) {
907 + transformedSurface = 0;
909 + // check if we have this effect buffered
910 + for (std::list<TransformedSurface*>::const_iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
911 + if ((*i)->effect == effect) transformedSurface = (*i)->surface;
914 + // if not: transform and buffer
915 + if (!transformedSurface) {
916 + if (effect == HORIZONTAL_FLIP) transformedSurface = zoomSurface(surface, -1, 1, 0);
917 + if (effect == VERTICAL_FLIP) transformedSurface = zoomSurface(surface, 1, -1, 0);
918 + if (transformedSurface == 0) {
919 + std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
922 + TransformedSurface* su = new TransformedSurface();
923 + su->surface = transformedSurface;
924 + su->effect = effect;
926 + transformedSurfaces.push_front(su);
930 + int ox = offsetx; if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(surface->w) - (ox+static_cast<int>(width));
931 + int oy = offsety; if (effect == VERTICAL_FLIP) oy = static_cast<int>(surface->h) - (oy+static_cast<int>(height));
932 + // draw surface to screen
933 + SDL_Surface* screen = SDL_GetVideoSurface();
936 + srcRect.x = static_cast<int>(ox+src_x);
937 + srcRect.y = static_cast<int>(oy+src_y);
938 + srcRect.w = static_cast<int>(width);
939 + srcRect.h = static_cast<int>(height);
942 + dstRect.x = static_cast<int>(dst_x);
943 + dstRect.y = static_cast<int>(dst_y);
945 + SDL_BlitSurface(transformedSurface, &srcRect, screen, &dstRect);
948 diff -Naur -x .svn -x build -x doxygen supertux/src/video/surface.hpp supertux-nogl/src/video/surface.hpp
949 --- supertux/src/video/surface.hpp 2006-03-03 20:34:27.000000000 +0100
950 +++ supertux-nogl/src/video/surface.hpp 2006-04-07 04:11:49.000000000 +0200
952 #ifndef __SURFACE_HPP__
953 #define __SURFACE_HPP__
955 +#include <SDL_image.h>
965 + * Helper class to buffer a pre-transformed SDL_Surface
967 +class TransformedSurface {
969 + SDL_Surface* surface;
970 + DrawingEffect effect;
974 * A rectangular image.
975 * The class basically holds a reference to a texture with additional UV
976 * coordinates that specify a rectangular area on this texture
979 ImageTexture* texture;
987 + /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
988 void draw(float x, float y, float alpha, DrawingEffect effect) const;
990 + /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
991 void draw_part(float src_x, float src_y, float dst_x, float dst_y,
992 float width, float height,
993 float alpha, DrawingEffect effect) const;
997 + int offsetx; /**< Region in ::surface to be used for blitting */
998 + int offsety; /**< Region in ::surface to be used for blitting */
999 + int width; /**< Region in ::surface to be used for blitting */
1000 + int height; /**< Region in ::surface to be used for blitting */
1002 + mutable std::list<TransformedSurface*> transformedSurfaces; /**< Cache for pre-transformed surfaces */
1005 Surface(const std::string& file);
1006 Surface(const std::string& file, int x, int y, int w, int h);
1007 diff -Naur -x .svn -x build -x doxygen supertux/src/video/texture.cpp supertux-nogl/src/video/texture.cpp
1008 --- supertux/src/video/texture.cpp 2006-03-03 20:34:27.000000000 +0100
1009 +++ supertux-nogl/src/video/texture.cpp 2006-04-07 04:11:49.000000000 +0200
1012 #include "texture.hpp"
1016 #include "glutil.hpp"
1019 return (v & (v-1)) == 0;
1022 -Texture::Texture(unsigned int w, unsigned int h, GLenum glformat)
1023 +Texture::Texture(unsigned int w, unsigned int h, GLenum)
1025 assert(is_power_of_2(w));
1026 assert(is_power_of_2(h));
1031 - assert_gl("before creating texture");
1032 - glGenTextures(1, &handle);
1035 - glBindTexture(GL_TEXTURE_2D, handle);
1037 - glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
1038 - GL_UNSIGNED_BYTE, 0);
1040 - set_texture_params();
1042 - glDeleteTextures(1, &handle);
1049 -Texture::Texture(SDL_Surface* image, GLenum glformat)
1050 +Texture::Texture(SDL_Surface* image, GLenum)
1052 const SDL_PixelFormat* format = image->format;
1053 if(!is_power_of_2(image->w) || !is_power_of_2(image->h))
1054 throw std::runtime_error("image has no power of 2 size");
1055 if(format->BitsPerPixel != 24 && format->BitsPerPixel != 32)
1056 throw std::runtime_error("image has no 24 or 32 bit color depth");
1059 this->width = image->w;
1060 this->height = image->h;
1062 - assert_gl("before creating texture");
1063 - glGenTextures(1, &handle);
1066 - GLenum sdl_format;
1067 - if(format->BytesPerPixel == 3)
1068 - sdl_format = GL_RGB;
1069 - else if(format->BytesPerPixel == 4)
1070 - sdl_format = GL_RGBA;
1074 - glBindTexture(GL_TEXTURE_2D, handle);
1075 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1076 - glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
1077 - glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
1078 - GL_UNSIGNED_BYTE, image->pixels);
1080 - assert_gl("creating texture");
1082 - set_texture_params();
1084 - glDeleteTextures(1, &handle);
1087 + surface = SDL_DisplayFormatAlpha(image);
1092 - glDeleteTextures(1, &handle);
1096 Texture::set_texture_params()
1098 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1099 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1100 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1101 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1103 - assert_gl("set texture params");
1106 diff -Naur -x .svn -x build -x doxygen supertux/src/video/texture.hpp supertux-nogl/src/video/texture.hpp
1107 --- supertux/src/video/texture.hpp 2006-03-03 20:34:27.000000000 +0100
1108 +++ supertux-nogl/src/video/texture.hpp 2006-04-07 04:11:49.000000000 +0200
1110 #define __TEXTURE_HPP__
1114 +#include "glutil.hpp"
1117 * This class is a wrapper around a texture handle. It stores the texture width
1122 + SDL_Surface* surface; /**< non-GL branch stores optimized surface */
1124 friend class TextureManager;
1127 unsigned int height;
1130 Texture(SDL_Surface* surface, GLenum glformat);
1133 - GLuint get_handle() const
1138 unsigned int get_width() const
1145 + SDL_Surface* getSurface() {
1149 + void setSurface(SDL_Surface* surface) {
1150 + this->surface = surface;
1154 void set_texture_params();
1156 diff -Naur -x .svn -x build -x doxygen supertux/src/video/texture_manager.cpp supertux-nogl/src/video/texture_manager.cpp
1157 --- supertux/src/video/texture_manager.cpp 2006-04-07 03:32:13.000000000 +0200
1158 +++ supertux-nogl/src/video/texture_manager.cpp 2006-04-07 04:11:49.000000000 +0200
1162 #include <SDL_image.h>
1164 -#include <GL/glext.h>
1167 #include <stdexcept>
1168 @@ -126,12 +124,6 @@
1170 TextureManager::save_textures()
1172 - glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1173 - glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
1174 - glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1175 - glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1176 - glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
1177 - glPixelStorei(GL_PACK_ALIGNMENT, 1);
1178 for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
1181 @@ -146,75 +138,16 @@
1183 SavedTexture saved_texture;
1184 saved_texture.texture = texture;
1185 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1186 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
1187 - &saved_texture.width);
1188 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
1189 - &saved_texture.height);
1190 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
1191 - &saved_texture.border);
1192 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1193 - &saved_texture.min_filter);
1194 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1195 - &saved_texture.mag_filter);
1196 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1197 - &saved_texture.wrap_s);
1198 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1199 - &saved_texture.wrap_t);
1201 size_t pixelssize = saved_texture.width * saved_texture.height * 4;
1202 saved_texture.pixels = new char[pixelssize];
1204 - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1205 - saved_texture.pixels);
1207 saved_textures.push_back(saved_texture);
1209 - glDeleteTextures(1, &(texture->handle));
1210 - texture->handle = 0;
1212 - assert_gl("retrieving texture");
1216 TextureManager::reload_textures()
1218 - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1219 - glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1220 - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1221 - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1222 - glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1223 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1225 - for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1226 - i != saved_textures.end(); ++i) {
1227 - SavedTexture& saved_texture = *i;
1230 - glGenTextures(1, &handle);
1231 - assert_gl("creating texture handle");
1233 - glBindTexture(GL_TEXTURE_2D, handle);
1234 - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1235 - saved_texture.width, saved_texture.height,
1236 - saved_texture.border, GL_RGBA,
1237 - GL_UNSIGNED_BYTE, saved_texture.pixels);
1238 - delete[] saved_texture.pixels;
1239 - assert_gl("uploading texture pixel data");
1241 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1242 - saved_texture.min_filter);
1243 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1244 - saved_texture.mag_filter);
1245 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1246 - saved_texture.wrap_s);
1247 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1248 - saved_texture.wrap_t);
1250 - assert_gl("setting texture_params");
1251 - saved_texture.texture->handle = handle;
1254 saved_textures.clear();
1257 diff -Naur -x .svn -x build -x doxygen supertux/src/video/texture_manager.hpp supertux-nogl/src/video/texture_manager.hpp
1258 --- supertux/src/video/texture_manager.hpp 2006-03-03 20:34:27.000000000 +0100
1259 +++ supertux-nogl/src/video/texture_manager.hpp 2006-04-07 04:11:49.000000000 +0200
1261 #ifndef __IMAGE_TEXTURE_MANAGER_HPP__
1262 #define __IMAGE_TEXTURE_MANAGER_HPP__