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 # This patch works for revision 4186. It may break for later revisions.
37 # -----------------------------------------------------------------------------
38 diff -Naur supertux/INSTALL supertux-nogl/INSTALL
39 --- supertux/INSTALL 2006-03-03 21:49:07.000000000 +0100
40 +++ supertux-nogl/INSTALL 2006-04-07 04:13:00.000000000 +0200
42 - Install instructions for SuperTux -
43 http://supertux.berlios.de/
45 -Last update: October 11, 2005 by Ondra Hosek
46 +Last update: March 4, 2006 by Christoph Sommer
51 Download: ftp://ftp.perforce.com/pub/jam
52 Homepage: http://www.perforce.com/jam/jam.html
54 -* OpenGL headers and libraries
55 - opengl libraries and headers are specific to your graphics card. Make sure
56 - that you have hardware accelerated opengl drivers installed. Software
57 - renderers like Mesa will make supertux unplayable slow.
59 * SDL 1.2.5 or later (1.2.8 is recommended on MacOS/X)
62 * SDL_image (any version)
63 http://www.libsdl.org/projects/SDL_image
65 +* SDL_gfx (2.0.13 or later)
66 + http://www.ferzkopp.net/Software/SDL_gfx-2.0/
68 * PhysicsFS (1.0.0, the development branch 1.1.x is buggy and does not work,
69 1.2.0 and later should work when it is released)
70 http://www.icculus.org/physfs
71 diff -Naur supertux/README supertux-nogl/README
72 --- supertux/README 2006-03-03 20:43:38.000000000 +0100
73 +++ supertux-nogl/README 2006-04-07 04:13:00.000000000 +0200
75 - An introduction for SuperTux -
76 http://supertux.berlios.de/
78 -Last update: October 13, 2005
79 +Last update: March 4, 2006 by Christoph Sommer
84 Also, notice that SuperTux saves the options, so it's often enough to
87 - The game uses OpenGL to render the graphics. You will either need a CPU
88 - with about 10 GHz or an accelerated video card with the vendor's drivers.
89 - (On Linux, the team recommends using cards from NVidia with the proprietary
90 - drivers, but ATI or another verndor should do.)
91 + The game uses SDL to render the graphics. You will either need a CPU
92 + with about 1 GHz or go get the original version of SuperTux which uses
97 diff -Naur supertux/configure.ac supertux-nogl/configure.ac
98 --- supertux/configure.ac 2006-03-03 20:43:38.000000000 +0100
99 +++ supertux-nogl/configure.ac 2006-04-07 04:13:00.000000000 +0200
102 dnl Process this file with autoconf to produce a configure script.
104 -AC_INIT(supertux, 0.2-svn)
105 +AC_INIT(supertux, 0.2-nogl-svn)
106 AC_CONFIG_SRCDIR([src/main.cpp])
107 AC_CONFIG_AUX_DIR([mk/autoconf])
110 [AC_MSG_ERROR([Please install SDLImage >= 1.2.1])],
111 [$SDL_CFLAGS], [$SDL_LIBS])
113 +dnl FIXME: This is far from perfect
114 +NP_FINDLIB([SDLGFX], [SDL_gfx], [SDL_gfx >= 2.0.13],
115 + NP_LANG_PROGRAM([#include <SDL_rotozoom.h>], [0;]),
118 + [AC_MSG_ERROR([Please install SDL_gfx >= 2.0.13])],
119 + [$SDL_CFLAGS], [$SDL_LIBS])
121 NP_FINDLIB([PHYSFS], [physfs], [physfs >= 1.0.0],
125 [AC_MSG_ERROR([Please intall OpenAL])],
129 -if test "$no_gl" = "yes"; then
130 - AC_MSG_ERROR([Please install opengl libraries and headers])
133 dnl Checks for library functions.
134 AC_CHECK_FUNCS(mkdir strdup strstr)
136 diff -Naur supertux/src/Jamfile supertux-nogl/src/Jamfile
137 --- supertux/src/Jamfile 2006-03-03 20:34:49.000000000 +0100
138 +++ supertux-nogl/src/Jamfile 2006-04-07 04:11:50.000000000 +0200
140 Application supertux : $(sources) $(wrapper_objects) : linkerfile ;
141 C++Flags supertux : -DAPPDATADIR='\"$(appdatadir)\"' ;
142 LinkWith supertux : squirrel ;
143 -ExternalLibs supertux : SDL SDLIMAGE GL OPENAL VORBIS VORBISFILE OGG ICONV PHYSFS BINRELOC ;
144 +ExternalLibs supertux : SDL SDLIMAGE SDLGFX OPENAL VORBIS VORBISFILE OGG ICONV PHYSFS BINRELOC ;
145 Help supertux : "Build the supertux executable" ;
146 IncludeDir supertux : squirrel/include squirrel ;
148 diff -Naur supertux/src/main.cpp supertux-nogl/src/main.cpp
149 --- supertux/src/main.cpp 2006-04-07 03:32:14.000000000 +0200
150 +++ supertux-nogl/src/main.cpp 2006-04-07 04:11:50.000000000 +0200
154 #include <SDL_image.h>
157 #include "gameconfig.hpp"
158 #include "resources.hpp"
160 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
161 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
163 - int flags = SDL_OPENGL;
164 + int flags = SDL_SWSURFACE;
165 if(config->use_fullscreen)
166 flags |= SDL_FULLSCREEN;
167 int width = config->screenwidth;
172 - // setup opengl state and transform
173 - glDisable(GL_DEPTH_TEST);
174 - glDisable(GL_CULL_FACE);
175 - glEnable(GL_TEXTURE_2D);
176 - glEnable(GL_BLEND);
177 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
179 - glViewport(0, 0, screen->w, screen->h);
180 - glMatrixMode(GL_PROJECTION);
182 - // logical resolution here not real monitor resolution
183 - glOrtho(0, 800, 600, 0, -1.0, 1.0);
184 - glMatrixMode(GL_MODELVIEW);
186 - glTranslatef(0, 0, 0);
188 - check_gl_error("Setting up view matrices");
190 if(texture_manager != NULL)
191 texture_manager->reload_textures();
193 diff -aur supertux/src/video/drawing_context.cpp supertux-nogl/src/video/drawing_context.cpp
194 --- supertux/src/video/drawing_context.cpp 2006-07-03 02:00:48.000000000 +0200
195 +++ supertux-nogl/src/video/drawing_context.cpp 2006-07-03 02:00:29.000000000 +0200
199 #include <SDL_image.h>
202 #include "drawing_context.hpp"
203 #include "surface.hpp"
206 screen = SDL_GetVideoSurface();
208 - lightmap_width = screen->w / LIGHTMAP_DIV;
209 - lightmap_height = screen->h / LIGHTMAP_DIV;
210 - unsigned int width = next_po2(lightmap_width);
211 - unsigned int height = next_po2(lightmap_height);
213 - lightmap = new Texture(width, height, GL_RGB);
215 - lightmap_uv_right = static_cast<float>(lightmap_width) / static_cast<float>(width);
216 - lightmap_uv_bottom = static_cast<float>(lightmap_height) / static_cast<float>(height);
217 - texture_manager->register_texture(lightmap);
220 requests = &drawing_requests;
223 DrawingContext::~DrawingContext()
225 - texture_manager->remove_texture(lightmap);
231 float angle, const Color& color, const Blend& blend,
234 + if(target != NORMAL) return;
236 assert(surface != 0);
238 DrawingRequest request;
240 DrawingContext::draw_surface_part(const Surface* surface, const Vector& source,
241 const Vector& size, const Vector& dest, int layer)
243 + if(target != NORMAL) return;
245 assert(surface != 0);
247 DrawingRequest request;
249 DrawingContext::draw_text(const Font* font, const std::string& text,
250 const Vector& position, FontAlignment alignment, int layer)
252 + if(target != NORMAL) return;
254 DrawingRequest request;
258 DrawingContext::draw_center_text(const Font* font, const std::string& text,
259 const Vector& position, int layer)
261 + if(target != NORMAL) return;
263 draw_text(font, text, Vector(position.x + SCREEN_WIDTH/2, position.y),
264 CENTER_ALLIGN, layer);
268 DrawingContext::draw_gradient(const Color& top, const Color& bottom, int layer)
270 + if(target != NORMAL) return;
272 DrawingRequest request;
274 request.type = GRADIENT;
276 DrawingContext::draw_filled_rect(const Vector& topleft, const Vector& size,
277 const Color& color, int layer)
279 + if(target != NORMAL) return;
281 DrawingRequest request;
283 request.type = FILLRECT;
285 DrawingContext::draw_filled_rect(const Rect& rect, const Color& color,
288 + if(target != NORMAL) return;
290 DrawingRequest request;
292 request.type = FILLRECT;
293 @@ -238,39 +239,20 @@
297 -DrawingContext::get_light(const Vector& position, Color* color)
298 +DrawingContext::get_light(const Vector& , Color* color)
300 - if( ambient_color.red == 1.0f && ambient_color.green == 1.0f
301 - && ambient_color.blue == 1.0f ) {
302 - *color = Color( 1.0f, 1.0f, 1.0f);
305 + i += 1; i &= 0xFFFF;
307 + *color = Color(0.0f, 0.0f, 0.0f);
309 + *color = Color(1.0f, 1.0f, 1.0f);
311 - DrawingRequest request;
312 - request.type = GETLIGHT;
313 - request.pos = transform.apply(position);
314 - request.layer = LAYER_GUI; //make sure all get_light requests are handled last.
316 - GetLightRequest* getlightrequest = new GetLightRequest;
317 - getlightrequest->color_ptr = color;
318 - request.request_data = getlightrequest;
319 - lightmap_requests.push_back(request);
323 -DrawingContext::get_light(DrawingRequest& request)
324 +DrawingContext::get_light(DrawingRequest& )
326 - GetLightRequest* getlightrequest = (GetLightRequest*) request.request_data;
329 - for( int i = 0; i<3; i++)
330 - pixels[i] = 0.0f; //set to black
332 - //TODO: hacky. Make coordinate conversion more generic
333 - glReadPixels((GLint) request.pos.x / 4, 600-(GLint)request.pos.y / 4, 1, 1, GL_RGB, GL_FLOAT, pixels);
334 - *(getlightrequest->color_ptr) = Color( pixels[0], pixels[1], pixels[2]);
335 - //printf("get_light %f/%f r%f g%f b%f\n", request.pos.x, request.pos.y, pixels[0], pixels[1], pixels[2]);
337 - delete getlightrequest;
342 delete surfacepartrequest;
347 + void fillrect(SDL_Surface* screen, float x, float y, float w, float h, int r, int g, int b, int a)
358 + SDL_Rect src, rect;
359 + SDL_Surface *temp = NULL;
367 + temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
374 + SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, r, g, b));
375 + SDL_SetAlpha(temp, SDL_SRCALPHA, a);
376 + SDL_BlitSurface(temp,0,screen,&rect);
377 + SDL_FreeSurface(temp);
379 + SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
385 DrawingContext::draw_gradient(DrawingRequest& request)
388 const Color& top = gradientrequest->top;
389 const Color& bottom = gradientrequest->bottom;
391 - glDisable(GL_TEXTURE_2D);
393 - glColor4f(top.red, top.green, top.blue, top.alpha);
395 - glVertex2f(SCREEN_WIDTH, 0);
396 - glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
397 - glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
398 - glVertex2f(0, SCREEN_HEIGHT);
400 - glEnable(GL_TEXTURE_2D);
403 + 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);
405 delete gradientrequest;
407 @@ -330,47 +338,19 @@
408 float w = fillrectrequest->size.x;
409 float h = fillrectrequest->size.y;
411 - glDisable(GL_TEXTURE_2D);
412 - glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
413 - fillrectrequest->color.blue, fillrectrequest->color.alpha);
414 + int r = static_cast<int>(fillrectrequest->color.red);
415 + int g = static_cast<int>(fillrectrequest->color.green);
416 + int b = static_cast<int>(fillrectrequest->color.blue);
417 + int a = static_cast<int>(fillrectrequest->color.alpha);
421 - glVertex2f(x+w, y);
422 - glVertex2f(x+w, y+h);
423 - glVertex2f(x, y+h);
425 - glEnable(GL_TEXTURE_2D);
426 + ::fillrect(screen, x, y, w, h, r, g, b, a);
428 delete fillrectrequest;
432 -DrawingContext::draw_lightmap(DrawingRequest& request)
433 +DrawingContext::draw_lightmap(DrawingRequest& )
435 - const Texture* texture = reinterpret_cast<Texture*> (request.request_data);
437 - // multiple the lightmap with the framebuffer
438 - glBlendFunc(GL_DST_COLOR, GL_ZERO);
440 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
443 - glTexCoord2f(0, lightmap_uv_bottom);
446 - glTexCoord2f(lightmap_uv_right, lightmap_uv_bottom);
447 - glVertex2f(SCREEN_WIDTH, 0);
449 - glTexCoord2f(lightmap_uv_right, 0);
450 - glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
452 - glTexCoord2f(0, 0);
453 - glVertex2f(0, SCREEN_HEIGHT);
457 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
462 transformstack.clear();
463 target_stack.clear();
465 - //Use Lightmap if ambient color is not white.
466 - bool use_lightmap = ( ambient_color.red != 1.0f || ambient_color.green != 1.0f ||
467 - ambient_color.blue != 1.0f );
469 - // PART1: create lightmap
471 - glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
472 - glMatrixMode(GL_PROJECTION);
474 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
475 - glMatrixMode(GL_MODELVIEW);
478 - glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
479 - glClear(GL_COLOR_BUFFER_BIT);
480 - handle_drawing_requests(lightmap_requests);
481 - lightmap_requests.clear();
483 - glDisable(GL_BLEND);
484 - glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
485 - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
487 - glViewport(0, 0, screen->w, screen->h);
488 - glMatrixMode(GL_PROJECTION);
490 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
491 - glMatrixMode(GL_MODELVIEW);
493 - glEnable(GL_BLEND);
495 - // add a lightmap drawing request into the queue
496 - DrawingRequest request;
497 - request.type = LIGHTMAPREQUEST;
498 - request.layer = LAYER_HUD - 1;
499 - request.request_data = lightmap;
500 - requests->push_back(request);
503 - //glClear(GL_COLOR_BUFFER_BIT);
504 handle_drawing_requests(drawing_requests);
505 drawing_requests.clear();
506 - assert_gl("drawing");
508 - SDL_GL_SwapBuffers();
514 DrawingContext::set_target(Target target)
516 this->target = target;
517 - if(target == LIGHTMAP)
518 - requests = &lightmap_requests;
520 - requests = &drawing_requests;
524 diff -aur supertux/src/video/drawing_context.hpp supertux-nogl/src/video/drawing_context.hpp
525 --- supertux/src/video/drawing_context.hpp 2006-07-03 02:00:48.000000000 +0200
526 +++ supertux-nogl/src/video/drawing_context.hpp 2006-07-03 02:00:29.000000000 +0200
539 +#include "glutil.hpp"
544 // some constants for predefined layer values
546 @@ -225,18 +225,14 @@
547 void draw_filled_rect(DrawingRequest& request);
548 void draw_lightmap(DrawingRequest& request);
550 DrawingRequests drawing_requests;
551 - DrawingRequests lightmap_requests;
553 DrawingRequests* requests;
558 std::vector<Target> target_stack;
560 - int lightmap_width, lightmap_height;
561 - float lightmap_uv_right, lightmap_uv_bottom;
565 diff -aur supertux/src/video/glutil.hpp supertux-nogl/src/video/glutil.hpp
566 --- supertux/src/video/glutil.hpp 2006-07-03 02:00:48.000000000 +0200
567 +++ supertux-nogl/src/video/glutil.hpp 2006-07-03 02:00:29.000000000 +0200
574 -static inline void check_gl_error(const char* message)
577 - GLenum error = glGetError();
578 - if(error != GL_NO_ERROR) {
579 - std::ostringstream msg;
580 - msg << "OpenGLError while '" << message << "': ";
582 - case GL_INVALID_ENUM:
583 - msg << "INVALID_ENUM: An unacceptable value is specified for an "
584 - "enumerated argument.";
586 - case GL_INVALID_VALUE:
587 - msg << "INVALID_VALUE: A numeric argument is out of range.";
589 - case GL_INVALID_OPERATION:
590 - msg << "INVALID_OPERATION: The specified operation is not allowed "
591 - "in the current state.";
593 - case GL_STACK_OVERFLOW:
594 - msg << "STACK_OVERFLOW: This command would cause a stack overflow.";
596 - case GL_STACK_UNDERFLOW:
597 - msg << "STACK_UNDERFLOW: This command would cause a stack underflow.";
599 - case GL_OUT_OF_MEMORY:
600 - msg << "OUT_OF_MEMORY: There is not enough memory left to execute the "
603 -#ifdef GL_TABLE_TOO_LARGE
604 - case GL_TABLE_TOO_LARGE:
605 - msg << "TABLE_TOO_LARGE: table is too large";
609 - msg << "Unknown error (code " << error << ")";
612 - throw std::runtime_error(msg.str());
618 +#define GL_SRC_ALPHA 0
619 +#define GL_ONE_MINUS_SRC_ALPHA 1
623 -static inline void assert_gl(const char* message)
626 - check_gl_error(message);
633 diff -aur supertux/src/video/surface.cpp supertux-nogl/src/video/surface.cpp
634 --- supertux/src/video/surface.cpp 2006-07-03 02:00:48.000000000 +0200
635 +++ supertux-nogl/src/video/surface.cpp 2006-07-03 02:00:29.000000000 +0200
639 #include <SDL_image.h>
640 +#include <SDL_rotozoom.h>
642 #include "gameconfig.hpp"
643 #include "physfs/physfs_sdl.hpp"
646 texture = texture_manager->get(file);
650 - uv_right = texture->get_uv_right();
651 - uv_bottom = texture->get_uv_bottom();
653 - width = texture->get_image_width();
654 - height = texture->get_image_height();
657 + width = static_cast<int>(texture->get_image_width());
658 + height = static_cast<int>(texture->get_image_height());
663 Surface::Surface(const std::string& file, int x, int y, int w, int h)
665 texture = texture_manager->get(file);
668 - float tex_w = static_cast<float> (texture->get_width());
669 - float tex_h = static_cast<float> (texture->get_height());
670 - uv_left = static_cast<float>(x) / tex_w;
671 - uv_top = static_cast<float>(y) / tex_h;
672 - uv_right = static_cast<float>(x+w) / tex_w;
673 - uv_bottom = static_cast<float>(y+h) / tex_h;
683 Surface::Surface(const Surface& other)
685 texture = other.texture;
688 - uv_left = other.uv_left;
689 - uv_top = other.uv_top;
690 - uv_right = other.uv_right;
691 - uv_bottom = other.uv_bottom;
692 + offsetx = other.offsetx;
693 + offsety = other.offsety;
695 height = other.height;
697 + flipx = other.flipx;
703 texture = other.texture;
705 - uv_left = other.uv_left;
706 - uv_top = other.uv_top;
707 - uv_right = other.uv_right;
708 - uv_bottom = other.uv_bottom;
709 + offsetx = other.offsetx;
710 + offsety = other.offsety;
712 height = other.height;
714 + flipx = other.flipx;
723 + for (std::list<TransformedSurface*>::iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
724 + SDL_FreeSurface((*i)->surface);
732 - std::swap(uv_left, uv_right);
736 -static inline void intern_draw(float left, float top, float right, float bottom, float uv_left, float uv_top,
737 - float uv_right, float uv_bottom,
738 - DrawingEffect effect)
740 - if(effect & HORIZONTAL_FLIP)
741 - std::swap(uv_left, uv_right);
742 - if(effect & VERTICAL_FLIP) {
743 - std::swap(uv_top, uv_bottom);
747 - glTexCoord2f(uv_left, uv_top);
748 - glVertex2f(left, top);
750 - glTexCoord2f(uv_right, uv_top);
751 - glVertex2f(right, top);
753 - glTexCoord2f(uv_right, uv_bottom);
754 - glVertex2f(right, bottom);
756 - glTexCoord2f(uv_left, uv_bottom);
757 - glVertex2f(left, bottom);
762 static inline void intern_draw2(float left, float top, float right, float bottom,
763 float uv_left, float uv_top,
764 float uv_right, float uv_bottom,
765 @@ -182,50 +161,76 @@
766 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
767 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
772 -Surface::draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const
773 +Surface::draw(float x, float y, float alpha, float, const Color&, const Blend&, DrawingEffect effect) const
775 - glColor4f(1.0f, 1.0f, 1.0f, alpha);
776 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
779 - x + width, y + height,
780 - uv_left, uv_top, uv_right, uv_bottom,
785 + draw_part(0, 0, x, y, width, height, alpha, effect);
789 Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
791 - glColor4f(1.0f, 1.0f, 1.0f, alpha);
792 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
795 - x + width, y + height,
796 - uv_left, uv_top, uv_right, uv_bottom, effect);
797 + draw_part(0, 0, x, y, width, height, alpha, effect);
801 Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
802 - float width, float height, float alpha,
803 + float width, float height, float ,
804 DrawingEffect effect) const
806 - float uv_width = uv_right - uv_left;
807 - float uv_height = uv_bottom - uv_top;
808 + //FIXME: support parameter "alpha"
809 + SDL_Surface* surface = texture->getSurface();
811 - float uv_left = this->uv_left + (uv_width * src_x) / this->width;
812 - float uv_top = this->uv_top + (uv_height * src_y) / this->height;
813 - float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
814 - float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
815 + // get and check SDL_Surface
816 + if (surface == 0) {
817 + std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
821 - glColor4f(1.0f, 1.0f, 1.0f, alpha);
822 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
823 + SDL_Surface* transformedSurface = surface;
825 - intern_draw(dst_x, dst_y,
826 - dst_x + width, dst_y + height,
827 - uv_left, uv_top, uv_right, uv_bottom, effect);
828 + if (flipx) effect = HORIZONTAL_FLIP;
830 + if (effect != NO_EFFECT) {
831 + transformedSurface = 0;
833 + // check if we have this effect buffered
834 + for (std::list<TransformedSurface*>::const_iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
835 + if ((*i)->effect == effect) transformedSurface = (*i)->surface;
838 + // if not: transform and buffer
839 + if (!transformedSurface) {
840 + if (effect == HORIZONTAL_FLIP) transformedSurface = zoomSurface(surface, -1, 1, 0);
841 + if (effect == VERTICAL_FLIP) transformedSurface = zoomSurface(surface, 1, -1, 0);
842 + if (transformedSurface == 0) {
843 + std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
846 + TransformedSurface* su = new TransformedSurface();
847 + su->surface = transformedSurface;
848 + su->effect = effect;
850 + transformedSurfaces.push_front(su);
854 + int ox = offsetx; if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(surface->w) - (ox+static_cast<int>(width));
855 + int oy = offsety; if (effect == VERTICAL_FLIP) oy = static_cast<int>(surface->h) - (oy+static_cast<int>(height));
856 + // draw surface to screen
857 + SDL_Surface* screen = SDL_GetVideoSurface();
860 + srcRect.x = static_cast<int>(ox+src_x);
861 + srcRect.y = static_cast<int>(oy+src_y);
862 + srcRect.w = static_cast<int>(width);
863 + srcRect.h = static_cast<int>(height);
866 + dstRect.x = static_cast<int>(dst_x);
867 + dstRect.y = static_cast<int>(dst_y);
869 + SDL_BlitSurface(transformedSurface, &srcRect, screen, &dstRect);
871 diff -aur supertux/src/video/surface.hpp supertux-nogl/src/video/surface.hpp
872 --- supertux/src/video/surface.hpp 2006-07-03 02:00:48.000000000 +0200
873 +++ supertux-nogl/src/video/surface.hpp 2006-07-03 02:00:29.000000000 +0200
875 #ifndef __SURFACE_HPP__
876 #define __SURFACE_HPP__
878 +#include <SDL_image.h>
881 #include "math/vector.hpp"
888 + * Helper class to buffer a pre-transformed SDL_Surface
890 +class TransformedSurface {
892 + SDL_Surface* surface;
893 + DrawingEffect effect;
897 * A rectangular image.
898 * The class basically holds a reference to a texture with additional UV
899 * coordinates that specify a rectangular area on this texture
902 ImageTexture* texture;
910 + /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
911 void draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const;
913 + /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
914 void draw(float x, float y, float alpha, DrawingEffect effect) const;
916 + /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
917 void draw_part(float src_x, float src_y, float dst_x, float dst_y,
918 float width, float height,
919 float alpha, DrawingEffect effect) const;
923 + int offsetx; /**< Region in ::surface to be used for blitting */
924 + int offsety; /**< Region in ::surface to be used for blitting */
925 + int width; /**< Region in ::surface to be used for blitting */
926 + int height; /**< Region in ::surface to be used for blitting */
928 + mutable std::list<TransformedSurface*> transformedSurfaces; /**< Cache for pre-transformed surfaces */
931 Surface(const std::string& file);
932 Surface(const std::string& file, int x, int y, int w, int h);
933 diff -aur supertux/src/video/texture.cpp supertux-nogl/src/video/texture.cpp
934 --- supertux/src/video/texture.cpp 2006-07-03 02:00:48.000000000 +0200
935 +++ supertux-nogl/src/video/texture.cpp 2006-07-03 02:00:29.000000000 +0200
938 #include "texture.hpp"
942 #include "glutil.hpp"
945 return (v & (v-1)) == 0;
948 -Texture::Texture(unsigned int w, unsigned int h, GLenum glformat)
949 +Texture::Texture(unsigned int w, unsigned int h, GLenum)
951 assert(is_power_of_2(w));
952 assert(is_power_of_2(h));
957 - assert_gl("before creating texture");
958 - glGenTextures(1, &handle);
961 - glBindTexture(GL_TEXTURE_2D, handle);
963 - glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
964 - GL_UNSIGNED_BYTE, 0);
966 - set_texture_params();
968 - glDeleteTextures(1, &handle);
974 -Texture::Texture(SDL_Surface* image, GLenum glformat)
975 +Texture::Texture(SDL_Surface* image, GLenum)
977 const SDL_PixelFormat* format = image->format;
978 if(!is_power_of_2(image->w) || !is_power_of_2(image->h))
980 this->width = image->w;
981 this->height = image->h;
983 - assert_gl("before creating texture");
984 - glGenTextures(1, &handle);
988 - if(format->BytesPerPixel == 3)
989 - sdl_format = GL_RGB;
990 - else if(format->BytesPerPixel == 4)
991 - sdl_format = GL_RGBA;
995 - glBindTexture(GL_TEXTURE_2D, handle);
996 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
997 - glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
998 - glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
999 - GL_UNSIGNED_BYTE, image->pixels);
1001 - assert_gl("creating texture");
1003 - set_texture_params();
1005 - glDeleteTextures(1, &handle);
1008 + surface = SDL_DisplayFormatAlpha(image);
1013 - glDeleteTextures(1, &handle);
1017 Texture::set_texture_params()
1019 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1020 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1021 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1022 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1024 - assert_gl("set texture params");
1026 diff -aur supertux/src/video/texture.hpp supertux-nogl/src/video/texture.hpp
1027 --- supertux/src/video/texture.hpp 2006-07-03 02:00:48.000000000 +0200
1028 +++ supertux-nogl/src/video/texture.hpp 2006-07-03 02:00:29.000000000 +0200
1030 #define __TEXTURE_HPP__
1034 +#include "glutil.hpp"
1037 * This class is a wrapper around a texture handle. It stores the texture width
1042 + SDL_Surface* surface; /**< non-GL branch stores optimized surface */
1044 friend class TextureManager;
1047 unsigned int height;
1050 Texture(SDL_Surface* surface, GLenum glformat);
1053 - GLuint get_handle() const
1058 unsigned int get_width() const
1065 + SDL_Surface* getSurface() {
1069 + void setSurface(SDL_Surface* surface) {
1070 + this->surface = surface;
1074 void set_texture_params();
1076 diff -aur supertux/src/video/texture_manager.cpp supertux-nogl/src/video/texture_manager.cpp
1077 --- supertux/src/video/texture_manager.cpp 2006-07-03 02:00:48.000000000 +0200
1078 +++ supertux-nogl/src/video/texture_manager.cpp 2006-07-03 02:00:29.000000000 +0200
1082 #include <SDL_image.h>
1084 -#include <GL/glext.h>
1087 #include <stdexcept>
1088 @@ -145,12 +143,6 @@
1090 TextureManager::save_textures()
1092 - glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1093 - glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
1094 - glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1095 - glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1096 - glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
1097 - glPixelStorei(GL_PACK_ALIGNMENT, 1);
1098 for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
1101 @@ -165,74 +157,15 @@
1103 SavedTexture saved_texture;
1104 saved_texture.texture = texture;
1105 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1106 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
1107 - &saved_texture.width);
1108 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
1109 - &saved_texture.height);
1110 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
1111 - &saved_texture.border);
1112 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1113 - &saved_texture.min_filter);
1114 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1115 - &saved_texture.mag_filter);
1116 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1117 - &saved_texture.wrap_s);
1118 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1119 - &saved_texture.wrap_t);
1121 size_t pixelssize = saved_texture.width * saved_texture.height * 4;
1122 saved_texture.pixels = new char[pixelssize];
1124 - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1125 - saved_texture.pixels);
1127 saved_textures.push_back(saved_texture);
1129 - glDeleteTextures(1, &(texture->handle));
1130 - texture->handle = 0;
1132 - assert_gl("retrieving texture for save");
1136 TextureManager::reload_textures()
1138 - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1139 - glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1140 - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1141 - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1142 - glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1143 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1145 - for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1146 - i != saved_textures.end(); ++i) {
1147 - SavedTexture& saved_texture = *i;
1150 - glGenTextures(1, &handle);
1151 - assert_gl("creating texture handle");
1153 - glBindTexture(GL_TEXTURE_2D, handle);
1154 - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1155 - saved_texture.width, saved_texture.height,
1156 - saved_texture.border, GL_RGBA,
1157 - GL_UNSIGNED_BYTE, saved_texture.pixels);
1158 - delete[] saved_texture.pixels;
1159 - assert_gl("uploading texture pixel data");
1161 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1162 - saved_texture.min_filter);
1163 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1164 - saved_texture.mag_filter);
1165 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1166 - saved_texture.wrap_s);
1167 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1168 - saved_texture.wrap_t);
1170 - assert_gl("setting texture_params");
1171 - saved_texture.texture->handle = handle;
1174 saved_textures.clear();
1176 diff -aur supertux/src/video/texture_manager.hpp supertux-nogl/src/video/texture_manager.hpp
1177 --- supertux/src/video/texture_manager.hpp 2006-07-03 02:00:48.000000000 +0200
1178 +++ supertux-nogl/src/video/texture_manager.hpp 2006-07-03 02:00:29.000000000 +0200
1180 #ifndef __IMAGE_TEXTURE_MANAGER_HPP__
1181 #define __IMAGE_TEXTURE_MANAGER_HPP__
1184 +#include "video/glutil.hpp"