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 -p0 < contrib/supertux-nogl.diff
35 # This patch works for revision 5051. It may break for later revisions.
37 # -----------------------------------------------------------------------------
38 Index: src/video/drawing_context.cpp
39 ===================================================================
40 --- src/video/drawing_context.cpp (revision 5051)
41 +++ src/video/drawing_context.cpp (working copy)
45 #include <SDL_image.h>
53 screen = SDL_GetVideoSurface();
55 - lightmap_width = screen->w / LIGHTMAP_DIV;
56 - lightmap_height = screen->h / LIGHTMAP_DIV;
57 - unsigned int width = next_po2(lightmap_width);
58 - unsigned int height = next_po2(lightmap_height);
60 - lightmap = new Texture(width, height, GL_RGB);
62 - lightmap_uv_right = static_cast<float>(lightmap_width) / static_cast<float>(width);
63 - lightmap_uv_bottom = static_cast<float>(lightmap_height) / static_cast<float>(height);
64 - texture_manager->register_texture(lightmap);
67 requests = &drawing_requests;
71 DrawingContext::~DrawingContext()
73 obstack_free(&obst, NULL);
75 - texture_manager->remove_texture(lightmap);
81 float angle, const Color& color, const Blend& blend,
84 + if(target != NORMAL) return;
88 DrawingRequest* request = new(obst) DrawingRequest();
90 DrawingContext::draw_surface_part(const Surface* surface, const Vector& source,
91 const Vector& size, const Vector& dest, int layer)
93 + if(target != NORMAL) return;
97 DrawingRequest* request = new(obst) DrawingRequest();
99 DrawingContext::draw_text(const Font* font, const std::string& text,
100 const Vector& position, FontAlignment alignment, int layer)
102 + if(target != NORMAL) return;
104 DrawingRequest* request = new(obst) DrawingRequest();
106 request->type = TEXT;
108 DrawingContext::draw_center_text(const Font* font, const std::string& text,
109 const Vector& position, int layer)
111 + if(target != NORMAL) return;
113 draw_text(font, text, Vector(position.x + SCREEN_WIDTH/2, position.y),
114 ALIGN_CENTER, layer);
118 DrawingContext::draw_gradient(const Color& top, const Color& bottom, int layer)
120 + if(target != NORMAL) return;
122 DrawingRequest* request = new(obst) DrawingRequest();
124 request->type = GRADIENT;
126 DrawingContext::draw_filled_rect(const Vector& topleft, const Vector& size,
127 const Color& color, int layer)
129 + if(target != NORMAL) return;
131 DrawingRequest* request = new(obst) DrawingRequest();
133 request->type = FILLRECT;
135 DrawingContext::draw_filled_rect(const Rect& rect, const Color& color,
138 + if(target != NORMAL) return;
140 DrawingRequest* request = new(obst) DrawingRequest();
142 request->type = FILLRECT;
143 @@ -306,47 +307,20 @@
147 -DrawingContext::get_light(const Vector& position, Color* color)
148 +DrawingContext::get_light(const Vector& , Color* color)
150 - if( ambient_color.red == 1.0f && ambient_color.green == 1.0f
151 - && ambient_color.blue == 1.0f ) {
152 - *color = Color( 1.0f, 1.0f, 1.0f);
156 - DrawingRequest* request = new(obst) DrawingRequest();
157 - request->type = GETLIGHT;
158 - request->pos = transform.apply(position);
160 - //There is no light offscreen.
161 - if(request->pos.x >= SCREEN_WIDTH || request->pos.y >= SCREEN_HEIGHT
162 - || request->pos.x < 0 || request->pos.y < 0){
163 - *color = Color( 0, 0, 0);
167 - request->layer = LAYER_GUI; //make sure all get_light requests are handled last.
168 - GetLightRequest* getlightrequest = new(obst) GetLightRequest();
169 - getlightrequest->color_ptr = color;
170 - request->request_data = getlightrequest;
171 - lightmap_requests.push_back(request);
173 + i += 1; i &= 0xFFFF;
175 + *color = Color(0.0f, 0.0f, 0.0f);
177 + *color = Color(1.0f, 1.0f, 1.0f);
182 -DrawingContext::get_light(const DrawingRequest& request) const
183 +DrawingContext::get_light(const DrawingRequest& ) const
185 - const GetLightRequest* getlightrequest
186 - = (GetLightRequest*) request.request_data;
189 - for( int i = 0; i<3; i++)
190 - pixels[i] = 0.0f; //set to black
192 - float posX = request.pos.x * lightmap_width / SCREEN_WIDTH;
193 - float posY = screen->h - request.pos.y * lightmap_height / SCREEN_HEIGHT;
194 - glReadPixels((GLint) posX, (GLint) posY , 1, 1, GL_RGB, GL_FLOAT, pixels);
195 - *(getlightrequest->color_ptr) = Color( pixels[0], pixels[1], pixels[2]);
196 - //printf("get_light %f/%f =>%f/%f r%f g%f b%f\n", request.pos.x, request.pos.y, posX, posY, pixels[0], pixels[1], pixels[2]);
201 request.alpha, request.drawing_effect);
206 + void fillrect(SDL_Surface* screen, float x, float y, float w, float h, int r, int g, int b, int a)
217 + SDL_Rect src, rect;
218 + SDL_Surface *temp = NULL;
226 + temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
233 + SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, r, g, b));
234 + SDL_SetAlpha(temp, SDL_SRCALPHA, a);
235 + SDL_BlitSurface(temp,0,screen,&rect);
236 + SDL_FreeSurface(temp);
238 + SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
244 DrawingContext::draw_gradient(const DrawingRequest& request) const
246 @@ -370,16 +383,10 @@
247 const Color& top = gradientrequest->top;
248 const Color& bottom = gradientrequest->bottom;
250 - glDisable(GL_TEXTURE_2D);
252 - glColor4f(top.red, top.green, top.blue, top.alpha);
254 - glVertex2f(SCREEN_WIDTH, 0);
255 - glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
256 - glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
257 - glVertex2f(0, SCREEN_HEIGHT);
259 - glEnable(GL_TEXTURE_2D);
262 + 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);
267 @@ -402,45 +409,17 @@
268 float w = fillrectrequest->size.x;
269 float h = fillrectrequest->size.y;
271 - glDisable(GL_TEXTURE_2D);
272 - glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
273 - fillrectrequest->color.blue, fillrectrequest->color.alpha);
277 - glVertex2f(x+w, y);
278 - glVertex2f(x+w, y+h);
279 - glVertex2f(x, y+h);
281 - glEnable(GL_TEXTURE_2D);
282 + int r = static_cast<int>(fillrectrequest->color.red);
283 + int g = static_cast<int>(fillrectrequest->color.green);
284 + int b = static_cast<int>(fillrectrequest->color.blue);
285 + int a = static_cast<int>(fillrectrequest->color.alpha);
287 + ::fillrect(screen, x, y, w, h, r, g, b, a);
291 -DrawingContext::draw_lightmap(const DrawingRequest& request) const
292 +DrawingContext::draw_lightmap(const DrawingRequest& ) const
294 - const Texture* texture = reinterpret_cast<Texture*> (request.request_data);
296 - // multiple the lightmap with the framebuffer
297 - glBlendFunc(GL_DST_COLOR, GL_ZERO);
299 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
302 - glTexCoord2f(0, lightmap_uv_bottom);
305 - glTexCoord2f(lightmap_uv_right, lightmap_uv_bottom);
306 - glVertex2f(SCREEN_WIDTH, 0);
308 - glTexCoord2f(lightmap_uv_right, 0);
309 - glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
311 - glTexCoord2f(0, 0);
312 - glVertex2f(0, SCREEN_HEIGHT);
316 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
320 @@ -453,50 +432,12 @@
321 transformstack.clear();
322 target_stack.clear();
324 - //Use Lightmap if ambient color is not white.
325 - bool use_lightmap = ( ambient_color.red != 1.0f || ambient_color.green != 1.0f ||
326 - ambient_color.blue != 1.0f );
328 - // PART1: create lightmap
330 - glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
331 - glMatrixMode(GL_PROJECTION);
333 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
334 - glMatrixMode(GL_MODELVIEW);
337 - glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
338 - glClear(GL_COLOR_BUFFER_BIT);
339 - handle_drawing_requests(lightmap_requests);
340 - lightmap_requests.clear();
342 - glDisable(GL_BLEND);
343 - glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
344 - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
346 - glViewport(0, 0, screen->w, screen->h);
347 - glMatrixMode(GL_PROJECTION);
349 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
350 - glMatrixMode(GL_MODELVIEW);
352 - glEnable(GL_BLEND);
354 - // add a lightmap drawing request into the queue
355 - DrawingRequest* request = new(obst) DrawingRequest();
356 - request->type = LIGHTMAPREQUEST;
357 - request->layer = LAYER_HUD - 1;
358 - request->request_data = lightmap;
359 - requests->push_back(request);
362 - //glClear(GL_COLOR_BUFFER_BIT);
363 handle_drawing_requests(drawing_requests);
364 drawing_requests.clear();
365 obstack_free(&obst, NULL);
367 - assert_gl("drawing");
371 // if a screenshot was requested, take one
372 if (screenshot_requested) {
374 DrawingContext::set_target(Target target)
376 this->target = target;
377 - if(target == LIGHTMAP) {
378 - requests = &lightmap_requests;
380 - assert(target == NORMAL);
381 - requests = &drawing_requests;
387 SDL_FreeSurface(shot_surf);
390 - glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
391 + //glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels); //TODO: Screenshot
393 // copy array line-by-line
394 for (int i = 0; i < SCREEN_HEIGHT; i++) {
395 Index: src/video/texture_manager.hpp
396 ===================================================================
397 --- src/video/texture_manager.hpp (revision 5051)
398 +++ src/video/texture_manager.hpp (working copy)
400 #ifndef __IMAGE_TEXTURE_MANAGER_HPP__
401 #define __IMAGE_TEXTURE_MANAGER_HPP__
404 +#include "video/glutil.hpp"
408 Index: src/video/texture.cpp
409 ===================================================================
410 --- src/video/texture.cpp (revision 5051)
411 +++ src/video/texture.cpp (working copy)
414 #include "texture.hpp"
418 #include "glutil.hpp"
421 return (v & (v-1)) == 0;
424 -Texture::Texture(unsigned int w, unsigned int h, GLenum glformat)
425 +Texture::Texture(unsigned int w, unsigned int h, GLenum)
427 assert(is_power_of_2(w));
428 assert(is_power_of_2(h));
433 - assert_gl("before creating texture");
434 - glGenTextures(1, &handle);
437 - glBindTexture(GL_TEXTURE_2D, handle);
439 - glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
440 - GL_UNSIGNED_BYTE, 0);
442 - set_texture_params();
444 - glDeleteTextures(1, &handle);
450 -Texture::Texture(SDL_Surface* image, GLenum glformat)
451 +Texture::Texture(SDL_Surface* image, GLenum)
453 const SDL_PixelFormat* format = image->format;
454 if(!is_power_of_2(image->w) || !is_power_of_2(image->h))
456 this->width = image->w;
457 this->height = image->h;
459 - assert_gl("before creating texture");
460 - glGenTextures(1, &handle);
464 - if(format->BytesPerPixel == 3)
465 - sdl_format = GL_RGB;
466 - else if(format->BytesPerPixel == 4)
467 - sdl_format = GL_RGBA;
471 - glBindTexture(GL_TEXTURE_2D, handle);
472 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
473 - glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
474 - glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
475 - GL_UNSIGNED_BYTE, image->pixels);
477 - assert_gl("creating texture");
479 - set_texture_params();
481 - glDeleteTextures(1, &handle);
484 + surface = SDL_DisplayFormatAlpha(image);
489 - glDeleteTextures(1, &handle);
493 Texture::set_texture_params()
495 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
496 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
497 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
498 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
500 - assert_gl("set texture params");
502 Index: src/video/drawing_context.hpp
503 ===================================================================
504 --- src/video/drawing_context.hpp (revision 5051)
505 +++ src/video/drawing_context.hpp (working copy)
511 #include <SDL_video.h>
513 #include "obstack/obstack.h"
518 +#include "glutil.hpp"
522 struct DrawingRequest;
524 // some constants for predefined layer values
526 void do_take_screenshot();
528 DrawingRequests drawing_requests;
529 - DrawingRequests lightmap_requests;
531 DrawingRequests* requests;
536 std::vector<Target> target_stack;
538 - int lightmap_width, lightmap_height;
539 - float lightmap_uv_right, lightmap_uv_bottom;
541 /* obstack holding the memory of the drawing requests */
543 Index: src/video/glutil.hpp
544 ===================================================================
545 --- src/video/glutil.hpp (revision 5051)
546 +++ src/video/glutil.hpp (working copy)
553 -static inline void check_gl_error(const char* message)
556 - GLenum error = glGetError();
557 - if(error != GL_NO_ERROR) {
558 - std::ostringstream msg;
559 - msg << "OpenGLError while '" << message << "': ";
561 - case GL_INVALID_ENUM:
562 - msg << "INVALID_ENUM: An unacceptable value is specified for an "
563 - "enumerated argument.";
565 - case GL_INVALID_VALUE:
566 - msg << "INVALID_VALUE: A numeric argument is out of range.";
568 - case GL_INVALID_OPERATION:
569 - msg << "INVALID_OPERATION: The specified operation is not allowed "
570 - "in the current state.";
572 - case GL_STACK_OVERFLOW:
573 - msg << "STACK_OVERFLOW: This command would cause a stack overflow.";
575 - case GL_STACK_UNDERFLOW:
576 - msg << "STACK_UNDERFLOW: This command would cause a stack underflow.";
578 - case GL_OUT_OF_MEMORY:
579 - msg << "OUT_OF_MEMORY: There is not enough memory left to execute the "
582 -#ifdef GL_TABLE_TOO_LARGE
583 - case GL_TABLE_TOO_LARGE:
584 - msg << "TABLE_TOO_LARGE: table is too large";
588 - msg << "Unknown error (code " << error << ")";
591 - throw std::runtime_error(msg.str());
600 +#define GL_SRC_ALPHA 0
601 +#define GL_ONE_MINUS_SRC_ALPHA 1
605 static inline void assert_gl(const char* message)
608 - check_gl_error(message);
615 Index: src/video/texture.hpp
616 ===================================================================
617 --- src/video/texture.hpp (revision 5051)
618 +++ src/video/texture.hpp (working copy)
620 #define __TEXTURE_HPP__
624 +#include "glutil.hpp"
627 * This class is a wrapper around a texture handle. It stores the texture width
632 + SDL_Surface* surface; /**< non-GL branch stores optimized surface */
634 friend class TextureManager;
640 Texture(SDL_Surface* surface, GLenum glformat);
643 - GLuint get_handle() const
648 unsigned int get_width() const
655 + SDL_Surface* getSurface() {
659 + void setSurface(SDL_Surface* surface) {
660 + this->surface = surface;
664 void set_texture_params();
666 Index: src/video/surface.cpp
667 ===================================================================
668 --- src/video/surface.cpp (revision 5051)
669 +++ src/video/surface.cpp (working copy)
673 #include <SDL_image.h>
674 +#include <SDL_rotozoom.h>
676 #include "gameconfig.hpp"
677 #include "physfs/physfs_sdl.hpp"
680 texture = texture_manager->get(file);
684 - uv_right = texture->get_uv_right();
685 - uv_bottom = texture->get_uv_bottom();
687 - width = texture->get_image_width();
688 - height = texture->get_image_height();
691 + width = static_cast<int>(texture->get_image_width());
692 + height = static_cast<int>(texture->get_image_height());
697 Surface::Surface(const std::string& file, int x, int y, int w, int h)
699 texture = texture_manager->get(file);
702 - float tex_w = static_cast<float> (texture->get_width());
703 - float tex_h = static_cast<float> (texture->get_height());
704 - uv_left = static_cast<float>(x) / tex_w;
705 - uv_top = static_cast<float>(y) / tex_h;
706 - uv_right = static_cast<float>(x+w) / tex_w;
707 - uv_bottom = static_cast<float>(y+h) / tex_h;
717 Surface::Surface(const Surface& other)
719 texture = other.texture;
722 - uv_left = other.uv_left;
723 - uv_top = other.uv_top;
724 - uv_right = other.uv_right;
725 - uv_bottom = other.uv_bottom;
726 + offsetx = other.offsetx;
727 + offsety = other.offsety;
729 height = other.height;
731 + flipx = other.flipx;
737 texture = other.texture;
739 - uv_left = other.uv_left;
740 - uv_top = other.uv_top;
741 - uv_right = other.uv_right;
742 - uv_bottom = other.uv_bottom;
743 + offsetx = other.offsetx;
744 + offsety = other.offsety;
746 height = other.height;
748 + flipx = other.flipx;
757 + for (std::list<TransformedSurface*>::iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
758 + SDL_FreeSurface((*i)->surface);
766 - std::swap(uv_left, uv_right);
770 -static inline void intern_draw(float left, float top, float right, float bottom, float uv_left, float uv_top,
771 - float uv_right, float uv_bottom,
772 - DrawingEffect effect)
774 - if(effect & HORIZONTAL_FLIP)
775 - std::swap(uv_left, uv_right);
776 - if(effect & VERTICAL_FLIP) {
777 - std::swap(uv_top, uv_bottom);
781 - glTexCoord2f(uv_left, uv_top);
782 - glVertex2f(left, top);
784 - glTexCoord2f(uv_right, uv_top);
785 - glVertex2f(right, top);
787 - glTexCoord2f(uv_right, uv_bottom);
788 - glVertex2f(right, bottom);
790 - glTexCoord2f(uv_left, uv_bottom);
791 - glVertex2f(left, bottom);
796 static inline void intern_draw2(float left, float top, float right, float bottom,
797 float uv_left, float uv_top,
798 float uv_right, float uv_bottom,
799 @@ -182,50 +161,76 @@
800 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
801 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
806 -Surface::draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const
807 +Surface::draw(float x, float y, float alpha, float, const Color&, const Blend&, DrawingEffect effect) const
809 - glColor4f(1.0f, 1.0f, 1.0f, alpha);
810 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
813 - x + width, y + height,
814 - uv_left, uv_top, uv_right, uv_bottom,
819 + draw_part(0, 0, x, y, width, height, alpha, effect);
823 Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
825 - glColor4f(1.0f, 1.0f, 1.0f, alpha);
826 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
829 - x + width, y + height,
830 - uv_left, uv_top, uv_right, uv_bottom, effect);
831 + draw_part(0, 0, x, y, width, height, alpha, effect);
835 Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
836 - float width, float height, float alpha,
837 + float width, float height, float ,
838 DrawingEffect effect) const
840 - float uv_width = uv_right - uv_left;
841 - float uv_height = uv_bottom - uv_top;
842 + //FIXME: support parameter "alpha"
843 + SDL_Surface* surface = texture->getSurface();
845 - float uv_left = this->uv_left + (uv_width * src_x) / this->width;
846 - float uv_top = this->uv_top + (uv_height * src_y) / this->height;
847 - float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
848 - float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
849 + // get and check SDL_Surface
850 + if (surface == 0) {
851 + std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
855 - glColor4f(1.0f, 1.0f, 1.0f, alpha);
856 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
857 + SDL_Surface* transformedSurface = surface;
859 - intern_draw(dst_x, dst_y,
860 - dst_x + width, dst_y + height,
861 - uv_left, uv_top, uv_right, uv_bottom, effect);
862 + if (flipx) effect = HORIZONTAL_FLIP;
864 + if (effect != NO_EFFECT) {
865 + transformedSurface = 0;
867 + // check if we have this effect buffered
868 + for (std::list<TransformedSurface*>::const_iterator i = transformedSurfaces.begin(); i != transformedSurfaces.end(); i++) {
869 + if ((*i)->effect == effect) transformedSurface = (*i)->surface;
872 + // if not: transform and buffer
873 + if (!transformedSurface) {
874 + if (effect == HORIZONTAL_FLIP) transformedSurface = zoomSurface(surface, -1, 1, 0);
875 + if (effect == VERTICAL_FLIP) transformedSurface = zoomSurface(surface, 1, -1, 0);
876 + if (transformedSurface == 0) {
877 + std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
880 + TransformedSurface* su = new TransformedSurface();
881 + su->surface = transformedSurface;
882 + su->effect = effect;
884 + transformedSurfaces.push_front(su);
888 + int ox = offsetx; if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(surface->w) - (ox+static_cast<int>(width));
889 + int oy = offsety; if (effect == VERTICAL_FLIP) oy = static_cast<int>(surface->h) - (oy+static_cast<int>(height));
890 + // draw surface to screen
891 + SDL_Surface* screen = SDL_GetVideoSurface();
894 + srcRect.x = static_cast<int>(ox+src_x);
895 + srcRect.y = static_cast<int>(oy+src_y);
896 + srcRect.w = static_cast<int>(width);
897 + srcRect.h = static_cast<int>(height);
900 + dstRect.x = static_cast<int>(dst_x);
901 + dstRect.y = static_cast<int>(dst_y);
903 + SDL_BlitSurface(transformedSurface, &srcRect, screen, &dstRect);
905 Index: src/video/texture_manager.cpp
906 ===================================================================
907 --- src/video/texture_manager.cpp (revision 5051)
908 +++ src/video/texture_manager.cpp (working copy)
912 #include <SDL_image.h>
914 -#include <GL/glext.h>
920 TextureManager::save_textures()
922 - glPixelStorei(GL_PACK_ROW_LENGTH, 0);
923 - glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
924 - glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
925 - glPixelStorei(GL_PACK_SKIP_ROWS, 0);
926 - glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
927 - glPixelStorei(GL_PACK_ALIGNMENT, 1);
928 for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
931 @@ -169,74 +161,15 @@
933 SavedTexture saved_texture;
934 saved_texture.texture = texture;
935 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
936 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
937 - &saved_texture.width);
938 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
939 - &saved_texture.height);
940 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
941 - &saved_texture.border);
942 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
943 - &saved_texture.min_filter);
944 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
945 - &saved_texture.mag_filter);
946 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
947 - &saved_texture.wrap_s);
948 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
949 - &saved_texture.wrap_t);
951 size_t pixelssize = saved_texture.width * saved_texture.height * 4;
952 saved_texture.pixels = new char[pixelssize];
954 - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
955 - saved_texture.pixels);
957 saved_textures.push_back(saved_texture);
959 - glDeleteTextures(1, &(texture->handle));
960 - texture->handle = 0;
962 - assert_gl("retrieving texture for save");
966 TextureManager::reload_textures()
968 - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
969 - glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
970 - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
971 - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
972 - glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
973 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
975 - for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
976 - i != saved_textures.end(); ++i) {
977 - SavedTexture& saved_texture = *i;
980 - glGenTextures(1, &handle);
981 - assert_gl("creating texture handle");
983 - glBindTexture(GL_TEXTURE_2D, handle);
984 - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
985 - saved_texture.width, saved_texture.height,
986 - saved_texture.border, GL_RGBA,
987 - GL_UNSIGNED_BYTE, saved_texture.pixels);
988 - delete[] saved_texture.pixels;
989 - assert_gl("uploading texture pixel data");
991 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
992 - saved_texture.min_filter);
993 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
994 - saved_texture.mag_filter);
995 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
996 - saved_texture.wrap_s);
997 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
998 - saved_texture.wrap_t);
1000 - assert_gl("setting texture_params");
1001 - saved_texture.texture->handle = handle;
1004 saved_textures.clear();
1006 Index: src/video/surface.hpp
1007 ===================================================================
1008 --- src/video/surface.hpp (revision 5051)
1009 +++ src/video/surface.hpp (working copy)
1011 #ifndef __SURFACE_HPP__
1012 #define __SURFACE_HPP__
1014 +#include <SDL_image.h>
1017 #include "math/vector.hpp"
1024 + * Helper class to buffer a pre-transformed SDL_Surface
1026 +class TransformedSurface {
1028 + SDL_Surface* surface;
1029 + DrawingEffect effect;
1033 * A rectangular image.
1034 * The class basically holds a reference to a texture with additional UV
1035 * coordinates that specify a rectangular area on this texture
1038 ImageTexture* texture;
1046 + /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
1047 void draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const;
1049 + /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
1050 void draw(float x, float y, float alpha, DrawingEffect effect) const;
1052 + /** draw the surface on the screen, applying a ::DrawingEffect on-the-fly. Transformed Surfaces will be cached in ::transformedSurfaces */
1053 void draw_part(float src_x, float src_y, float dst_x, float dst_y,
1054 float width, float height,
1055 float alpha, DrawingEffect effect) const;
1059 + int offsetx; /**< Region in ::surface to be used for blitting */
1060 + int offsety; /**< Region in ::surface to be used for blitting */
1061 + int width; /**< Region in ::surface to be used for blitting */
1062 + int height; /**< Region in ::surface to be used for blitting */
1064 + mutable std::list<TransformedSurface*> transformedSurfaces; /**< Cache for pre-transformed surfaces */
1067 Surface(const std::string& file);
1068 Surface(const std::string& file, int x, int y, int w, int h);
1070 ===================================================================
1071 --- src/main.cpp (revision 5051)
1072 +++ src/main.cpp (working copy)
1076 #include <SDL_image.h>
1079 #include "gameconfig.hpp"
1080 #include "resources.hpp"
1082 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
1083 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
1085 - int flags = SDL_OPENGL;
1086 + int flags = SDL_SWSURFACE;
1087 if(config->use_fullscreen)
1088 flags |= SDL_FULLSCREEN;
1089 int width = config->screenwidth;
1090 @@ -437,24 +436,6 @@
1092 log_info << (config->use_fullscreen?"fullscreen ":"window ") << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << " Ratio: " << aspect_ratio << "\n";
1094 - // setup opengl state and transform
1095 - glDisable(GL_DEPTH_TEST);
1096 - glDisable(GL_CULL_FACE);
1097 - glEnable(GL_TEXTURE_2D);
1098 - glEnable(GL_BLEND);
1099 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1101 - glViewport(0, 0, screen->w, screen->h);
1102 - glMatrixMode(GL_PROJECTION);
1104 - // logical resolution here not real monitor resolution
1105 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
1106 - glMatrixMode(GL_MODELVIEW);
1108 - glTranslatef(0, 0, 0);
1110 - check_gl_error("Setting up view matrices");
1112 if(texture_manager != NULL)
1113 texture_manager->reload_textures();
1116 ===================================================================
1117 --- src/Jamfile (revision 5051)
1118 +++ src/Jamfile (working copy)
1120 Application supertux2 : $(sources) $(wrapper_objects) : linkerfile ;
1121 C++Flags supertux2 : -DAPPDATADIR=\'\"$(appdatadir)\"\' ;
1122 LinkWith supertux2 : squirrel ;
1123 -ExternalLibs supertux2 : SDL SDLIMAGE GL OPENAL VORBIS VORBISFILE OGG ICONV PHYSFS BINRELOC LIBCURL ;
1124 +ExternalLibs supertux2 : SDL SDLIMAGE SDLGFX OPENAL VORBIS VORBISFILE OGG ICONV PHYSFS BINRELOC LIBCURL ;
1125 Help supertux2 : "Build the supertux2 executable" ;
1126 IncludeDir supertux2 : squirrel/include squirrel ;
1127 Package [ Wildcard scripting : *.cpp *.hpp ] ;
1129 ===================================================================
1130 --- README (revision 5051)
1131 +++ README (working copy)
1133 - An introduction for SuperTux -
1134 http://supertux.lethargik.org/
1136 -Last update: December 17, 2006
1137 +Last update: May 27, 2007
1138 +using -nogl patch by Christoph Sommer
1143 Also, notice that SuperTux saves the options, so it's often enough to
1146 - The game uses OpenGL to render the graphics. You will either need a CPU
1147 - with about 10 GHz or an accelerated video card with the vendor's drivers.
1148 - (On Linux, the team recommends using cards from NVidia with the proprietary
1149 - drivers, but ATI or another vendor should do.)
1150 + The game uses SDL to render the graphics. You will either need a CPU
1151 + with about 1 GHz or go get the original version of SuperTux which uses
1159 ===================================================================
1160 --- configure.ac (revision 5051)
1161 +++ configure.ac (working copy)
1164 dnl Process this file with autoconf to produce a configure script.
1166 -AC_INIT(supertux2, 0.3.0-SVN)
1167 +AC_INIT(supertux2, 0.3.0-nogl-SVN)
1168 AC_CONFIG_SRCDIR([src/main.cpp])
1169 AC_CONFIG_AUX_DIR([mk/autoconf])
1171 @@ -129,6 +129,14 @@
1172 [AC_MSG_ERROR([Please install SDLImage >= 1.2.1])],
1173 [$SDL_CFLAGS], [$SDL_LIBS])
1175 +dnl FIXME: This is far from perfect
1176 +NP_FINDLIB([SDLGFX], [SDL_gfx], [SDL_gfx >= 2.0.13],
1177 + NP_LANG_PROGRAM([#include <SDL_rotozoom.h>], [0;]),
1180 + [AC_MSG_ERROR([Please install SDL_gfx >= 2.0.13])],
1181 + [$SDL_CFLAGS], [$SDL_LIBS])
1183 NP_FINDLIB([PHYSFS], [physfs], [physfs >= 1.0.0],
1186 @@ -154,11 +162,6 @@
1187 [AC_MSG_ERROR([Please intall OpenAL])],
1191 -if test "$no_gl" = "yes"; then
1192 - AC_MSG_ERROR([Please install opengl libraries and headers])
1195 dnl Checks for library functions.
1196 AC_CHECK_FUNCS(mkdir strdup strstr)
1199 ===================================================================
1200 --- INSTALL (revision 5051)
1201 +++ INSTALL (working copy)
1203 - Install instructions for SuperTux -
1204 http://supertux.lethargik.org/
1206 -Last update: October 11, 2005 by Ondra Hosek
1207 +Last update: March 4, 2006 by Christoph Sommer
1212 Download: ftp://ftp.perforce.com/pub/jam
1213 Homepage: http://www.perforce.com/jam/jam.html
1215 -* OpenGL headers and libraries
1216 - opengl libraries and headers are specific to your graphics card. Make sure
1217 - that you have hardware accelerated opengl drivers installed. Software
1218 - renderers like Mesa will make supertux unplayable slow.
1220 * SDL 1.2.5 or later (1.2.8 is recommended on MacOS/X)
1221 http://www.libsdl.org
1223 * SDL_image (any version)
1224 http://www.libsdl.org/projects/SDL_image
1226 +* SDL_gfx (2.0.13 or later)
1227 + http://www.ferzkopp.net/Software/SDL_gfx-2.0/
1229 * PhysicsFS (1.0.0, the development branch 1.1.x is buggy and does not work,
1230 1.2.0 and later should work when it is released)
1231 http://www.icculus.org/physfs