3 # Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 # -----------------------------------------------------------------------------
21 # This patch allows running the game on systems without OpenGL support.
23 # It modifies the video portion of the SuperTux engine to render all graphics
24 # with SDL functions only. Many features are removed from the video engine,
25 # so don't expect much.
27 # Installing the patch should be pretty straightforward. Simply run the
28 # following command prior to running autogen.sh and configure:
30 # patch -p0 < contrib/supertux-nogl.diff
32 # This patch works for revision 5072. It may break for later revisions.
34 # -----------------------------------------------------------------------------
35 Index: src/gameconfig.hpp
36 ===================================================================
37 --- src/gameconfig.hpp (revision 5071)
38 +++ src/gameconfig.hpp (working copy)
40 #ifndef SUPERTUX_CONFIG_H
41 #define SUPERTUX_CONFIG_H
58 Index: src/video/drawing_context.cpp
59 ===================================================================
60 --- src/video/drawing_context.cpp (revision 5071)
61 +++ src/video/drawing_context.cpp (working copy)
65 #include <SDL_image.h>
71 +#include "glutil.hpp"
72 #include "drawing_context.hpp"
73 #include "surface.hpp"
76 #include "gameconfig.hpp"
77 -#include "glutil.hpp"
78 #include "texture.hpp"
79 #include "texture_manager.hpp"
80 #include "obstack/obstackpp.hpp"
83 screen = SDL_GetVideoSurface();
86 lightmap_width = screen->w / LIGHTMAP_DIV;
87 lightmap_height = screen->h / LIGHTMAP_DIV;
88 unsigned int width = next_po2(lightmap_width);
90 lightmap_uv_right = static_cast<float>(lightmap_width) / static_cast<float>(width);
91 lightmap_uv_bottom = static_cast<float>(lightmap_height) / static_cast<float>(height);
92 texture_manager->register_texture(lightmap);
95 requests = &drawing_requests;
99 obstack_free(&obst, NULL);
102 texture_manager->remove_texture(lightmap);
108 @@ -338,15 +341,31 @@
109 const GetLightRequest* getlightrequest
110 = (GetLightRequest*) request.request_data;
113 - for( int i = 0; i<3; i++)
114 - pixels[i] = 0.0f; //set to black
116 + if(config->use_opengl)
119 + for( int i = 0; i<3; i++)
120 + pixels[i] = 0.0f; //set to black
122 - float posX = request.pos.x * lightmap_width / SCREEN_WIDTH;
123 - float posY = screen->h - request.pos.y * lightmap_height / SCREEN_HEIGHT;
124 - glReadPixels((GLint) posX, (GLint) posY , 1, 1, GL_RGB, GL_FLOAT, pixels);
125 + float posX = request.pos.x * lightmap_width / SCREEN_WIDTH;
126 + float posY = screen->h - request.pos.y * lightmap_height / SCREEN_HEIGHT;
127 + glReadPixels((GLint) posX, (GLint) posY , 1, 1, GL_RGB, GL_FLOAT, pixels);
128 *(getlightrequest->color_ptr) = Color( pixels[0], pixels[1], pixels[2]);
129 - //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]);
130 + //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]);
135 + // FIXME: implement properly for SDL
137 + i += 1; i &= 0xFFFF;
139 + *(getlightrequest->color_ptr) = Color(0.0f, 0.0f, 0.0f);
141 + *(getlightrequest->color_ptr) = Color(1.0f, 1.0f, 1.0f);
147 @@ -370,17 +389,50 @@
148 const Color& top = gradientrequest->top;
149 const Color& bottom = gradientrequest->bottom;
151 - glDisable(GL_TEXTURE_2D);
153 - glColor4f(top.red, top.green, top.blue, top.alpha);
155 - glVertex2f(SCREEN_WIDTH, 0);
156 - glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
157 - glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
158 - glVertex2f(0, SCREEN_HEIGHT);
160 - glEnable(GL_TEXTURE_2D);
161 - glColor4f(1, 1, 1, 1);
163 + if(config->use_opengl)
165 + glDisable(GL_TEXTURE_2D);
167 + glColor4f(top.red, top.green, top.blue, top.alpha);
169 + glVertex2f(SCREEN_WIDTH, 0);
170 + glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
171 + glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
172 + glVertex2f(0, SCREEN_HEIGHT);
174 + glEnable(GL_TEXTURE_2D);
175 + glColor4f(1, 1, 1, 1);
180 + for(int y = 0;y < screen->h;++y)
182 + Uint8 r = (Uint8)((((float)(top.red-bottom.red)/(0-screen->h)) * y + top.red) * 255);
183 + Uint8 g = (Uint8)((((float)(top.green-bottom.green)/(0-screen->h)) * y + top.green) * 255);
184 + Uint8 b = (Uint8)((((float)(top.blue-bottom.blue)/(0-screen->h)) * y + top.blue) * 255);
185 + Uint8 a = (Uint8)((((float)(top.alpha-bottom.alpha)/(0-screen->h)) * y + top.alpha) * 255);
186 + Uint32 color = SDL_MapRGB(screen->format, r, g, b);
191 + rect.w = screen->w;
194 + if(a == SDL_ALPHA_OPAQUE) {
195 + SDL_FillRect(screen, &rect, color);
196 + } else if(a != SDL_ALPHA_TRANSPARENT) {
197 + SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
199 + SDL_FillRect(temp, 0, color);
200 + SDL_SetAlpha(temp, SDL_SRCALPHA, a);
201 + SDL_BlitSurface(temp, 0, screen, &rect);
202 + SDL_FreeSurface(temp);
209 @@ -398,29 +450,76 @@
210 const FillRectRequest* fillrectrequest
211 = (FillRectRequest*) request.request_data;
213 - float x = request.pos.x;
214 - float y = request.pos.y;
215 - float w = fillrectrequest->size.x;
216 - float h = fillrectrequest->size.y;
218 + if(config->use_opengl)
220 + float x = request.pos.x;
221 + float y = request.pos.y;
222 + float w = fillrectrequest->size.x;
223 + float h = fillrectrequest->size.y;
225 - glDisable(GL_TEXTURE_2D);
226 - glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
227 - fillrectrequest->color.blue, fillrectrequest->color.alpha);
228 + glDisable(GL_TEXTURE_2D);
229 + glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
230 + fillrectrequest->color.blue, fillrectrequest->color.alpha);
234 - glVertex2f(x+w, y);
235 - glVertex2f(x+w, y+h);
236 - glVertex2f(x, y+h);
238 - glEnable(GL_TEXTURE_2D);
240 - glColor4f(1, 1, 1, 1);
243 + glVertex2f(x+w, y);
244 + glVertex2f(x+w, y+h);
245 + glVertex2f(x, y+h);
247 + glEnable(GL_TEXTURE_2D);
248 + glColor4f(1, 1, 1, 1);
253 + float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
254 + float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
257 + if(xfactor < yfactor)
259 + numerator = config->screenwidth;
260 + denominator = SCREEN_WIDTH;
264 + numerator = config->screenheight;
265 + denominator = SCREEN_HEIGHT;
269 + rect.x = (Sint16)request.pos.x * numerator / denominator;
270 + rect.y = (Sint16)request.pos.y * numerator / denominator;
271 + rect.w = (Uint16)fillrectrequest->size.x * numerator / denominator;
272 + rect.h = (Uint16)fillrectrequest->size.y * numerator / denominator;
273 + Uint8 r = static_cast<Uint8>(fillrectrequest->color.red * 255);
274 + Uint8 g = static_cast<Uint8>(fillrectrequest->color.green * 255);
275 + Uint8 b = static_cast<Uint8>(fillrectrequest->color.blue * 255);
276 + Uint8 a = static_cast<Uint8>(fillrectrequest->color.alpha * 255);
277 + Uint32 color = SDL_MapRGB(screen->format, r, g, b);
278 + if(a == SDL_ALPHA_OPAQUE) {
279 + SDL_FillRect(screen, &rect, color);
280 + } else if(a != SDL_ALPHA_TRANSPARENT) {
281 + SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
283 + SDL_FillRect(temp, 0, color);
284 + SDL_SetAlpha(temp, SDL_SRCALPHA, a);
285 + SDL_BlitSurface(temp, 0, screen, &rect);
286 + SDL_FreeSurface(temp);
293 DrawingContext::draw_lightmap(const DrawingRequest& request) const
295 +DrawingContext::draw_lightmap(const DrawingRequest&) const
299 const Texture* texture = reinterpret_cast<Texture*> (request.request_data);
301 // multiple the lightmap with the framebuffer
305 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
310 @@ -462,29 +562,38 @@
312 // PART1: create lightmap
314 - glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
315 - glMatrixMode(GL_PROJECTION);
317 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
318 - glMatrixMode(GL_MODELVIEW);
321 + if(config->use_opengl)
323 + glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
324 + glMatrixMode(GL_PROJECTION);
326 + glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
327 + glMatrixMode(GL_MODELVIEW);
330 - glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
331 - glClear(GL_COLOR_BUFFER_BIT);
332 - handle_drawing_requests(lightmap_requests);
333 - lightmap_requests.clear();
334 + glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
335 + glClear(GL_COLOR_BUFFER_BIT);
336 + handle_drawing_requests(lightmap_requests);
337 + lightmap_requests.clear();
339 - glDisable(GL_BLEND);
340 - glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
341 - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
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);
353 + glViewport(0, 0, screen->w, screen->h);
354 + glMatrixMode(GL_PROJECTION);
356 + glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
357 + glMatrixMode(GL_MODELVIEW);
359 + glEnable(GL_BLEND);
364 + // FIXME: SDL alternative
367 // add a lightmap drawing request into the queue
368 DrawingRequest* request = new(obst) DrawingRequest();
370 drawing_requests.clear();
371 obstack_free(&obst, NULL);
373 - assert_gl("drawing");
375 + if(config->use_opengl)
377 + assert_gl("drawing");
381 // if a screenshot was requested, take one
382 if (screenshot_requested) {
384 screenshot_requested = false;
387 - SDL_GL_SwapBuffers();
389 + if(config->use_opengl)
391 + SDL_GL_SwapBuffers();
400 class RequestPtrCompare
401 @@ -644,36 +767,47 @@
403 // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it?
405 - // create surface to hold screenshot
406 - #if SDL_BYTEORDER == SDL_BIG_ENDIAN
407 - SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
409 - SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
412 - log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
415 + SDL_Surface *shot_surf;
417 + if(config->use_opengl)
419 + // create surface to hold screenshot
420 + #if SDL_BYTEORDER == SDL_BIG_ENDIAN
421 + shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
423 + shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
426 + log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
430 - // read pixels into array
431 - char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
433 - log_warning << "Could not allocate memory to store screenshot" << std::endl;
434 - SDL_FreeSurface(shot_surf);
437 - glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
438 + // read pixels into array
439 + char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
441 + log_warning << "Could not allocate memory to store screenshot" << std::endl;
442 + SDL_FreeSurface(shot_surf);
445 + glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
447 - // copy array line-by-line
448 - for (int i = 0; i < SCREEN_HEIGHT; i++) {
449 - char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
450 - char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
451 - memcpy(dst, src, 3 * SCREEN_WIDTH);
452 + // copy array line-by-line
453 + for (int i = 0; i < SCREEN_HEIGHT; i++) {
454 + char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
455 + char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
456 + memcpy(dst, src, 3 * SCREEN_WIDTH);
465 + shot_surf = SDL_GetVideoSurface();
466 + shot_surf->refcount++;
473 static const std::string writeDir = PHYSFS_getWriteDir();
474 static const std::string dirSep = PHYSFS_getDirSeparator();
475 Index: src/video/texture_manager.hpp
476 ===================================================================
477 --- src/video/texture_manager.hpp (revision 5071)
478 +++ src/video/texture_manager.hpp (working copy)
480 #ifndef __IMAGE_TEXTURE_MANAGER_HPP__
481 #define __IMAGE_TEXTURE_MANAGER_HPP__
484 +#include "glutil.hpp"
488 Index: src/video/texture.cpp
489 ===================================================================
490 --- src/video/texture.cpp (revision 5071)
491 +++ src/video/texture.cpp (working copy)
495 #include "texture.hpp"
496 +#include "gameconfig.hpp"
497 +#include "glutil.hpp"
501 -#include "glutil.hpp"
502 +#include <stdexcept>
504 static inline bool is_power_of_2(int v)
506 return (v & (v-1)) == 0;
510 Texture::Texture(unsigned int w, unsigned int h, GLenum glformat)
512 +Texture::Texture(unsigned int w, unsigned int h, GLenum)
515 assert(is_power_of_2(w));
516 assert(is_power_of_2(h));
518 + use_opengl = config->use_opengl;
524 + surface.opengl.width = w;
525 + surface.opengl.height = h;
527 - assert_gl("before creating texture");
528 - glGenTextures(1, &handle);
529 + assert_gl("before creating texture");
530 + glGenTextures(1, &surface.opengl.handle);
533 - glBindTexture(GL_TEXTURE_2D, handle);
535 + glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
537 - glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA,
538 - GL_UNSIGNED_BYTE, 0);
539 + glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
540 + surface.opengl.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
542 - set_texture_params();
544 - glDeleteTextures(1, &handle);
546 + set_texture_params();
548 + glDeleteTextures(1, &surface.opengl.handle);
560 Texture::Texture(SDL_Surface* image, GLenum glformat)
562 +Texture::Texture(SDL_Surface* image, GLenum)
565 const SDL_PixelFormat* format = image->format;
566 if(!is_power_of_2(image->w) || !is_power_of_2(image->h))
567 - throw std::runtime_error("image has no power of 2 size");
568 + throw std::runtime_error("image does not have power of 2 size");
569 if(format->BitsPerPixel != 24 && format->BitsPerPixel != 32)
570 - throw std::runtime_error("image has no 24 or 32 bit color depth");
571 + throw std::runtime_error("image does not have 24 or 32 bit color depth");
573 + use_opengl = config->use_opengl;
575 - this->width = image->w;
576 - this->height = image->h;
579 + surface.opengl.width = image->w;
580 + surface.opengl.height = image->h;
582 - assert_gl("before creating texture");
583 - glGenTextures(1, &handle);
584 + assert_gl("before creating texture");
585 + glGenTextures(1, &surface.opengl.handle);
589 - if(format->BytesPerPixel == 3)
590 - sdl_format = GL_RGB;
591 - else if(format->BytesPerPixel == 4)
592 - sdl_format = GL_RGBA;
597 + if(format->BytesPerPixel == 3)
598 + sdl_format = GL_RGB;
599 + else if(format->BytesPerPixel == 4)
600 + sdl_format = GL_RGBA;
604 - glBindTexture(GL_TEXTURE_2D, handle);
605 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
606 - glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
607 - glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, sdl_format,
608 - GL_UNSIGNED_BYTE, image->pixels);
609 + glBindTexture(GL_TEXTURE_2D, surface.opengl.handle);
610 + glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
611 + glPixelStorei(GL_UNPACK_ROW_LENGTH, image->pitch/format->BytesPerPixel);
612 + glTexImage2D(GL_TEXTURE_2D, 0, glformat, surface.opengl.width,
613 + surface.opengl.height, 0, sdl_format,
614 + GL_UNSIGNED_BYTE, image->pixels);
616 - assert_gl("creating texture");
617 + assert_gl("creating texture");
619 - set_texture_params();
621 - glDeleteTextures(1, &handle);
623 + set_texture_params();
625 + glDeleteTextures(1, &surface.opengl.handle);
632 + surface.sdl = SDL_DisplayFormatAlpha(image);
638 - glDeleteTextures(1, &handle);
642 + glDeleteTextures(1, &surface.opengl.handle);
647 + SDL_FreeSurface(surface.sdl);
652 Texture::set_texture_params()
654 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
655 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
656 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
657 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
661 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
662 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
663 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
664 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
666 - assert_gl("set texture params");
667 + assert_gl("set texture params");
671 Index: src/video/drawing_context.hpp
672 ===================================================================
673 --- src/video/drawing_context.hpp (revision 5071)
674 +++ src/video/drawing_context.hpp (working copy)
680 #include <SDL_video.h>
682 +#include "glutil.hpp"
683 #include "obstack/obstack.h"
684 #include "math/vector.hpp"
685 #include "math/rect.hpp"
686 Index: src/video/glutil.hpp
687 ===================================================================
688 --- src/video/glutil.hpp (revision 5071)
689 +++ src/video/glutil.hpp (working copy)
691 #ifndef __GLUTIL_HPP__
692 #define __GLUTIL_HPP__
701 +#include <GL/glext.h>
703 static inline void check_gl_error(const char* message)
713 +#define GL_SRC_ALPHA 0
714 +#define GL_ONE_MINUS_SRC_ALPHA 1
721 Index: src/video/texture.hpp
722 ===================================================================
723 --- src/video/texture.hpp (revision 5071)
724 +++ src/video/texture.hpp (working copy)
726 #ifndef __TEXTURE_HPP__
727 #define __TEXTURE_HPP__
736 +#include "gameconfig.hpp"
737 +#include "glutil.hpp"
740 * This class is a wrapper around a texture handle. It stores the texture width
741 * and height and provides convenience functions for uploading SDL_Surfaces
746 - friend class TextureManager;
748 - unsigned int width;
749 - unsigned int height;
757 + unsigned int width;
758 + unsigned int height;
768 Texture(unsigned int width, unsigned int height, GLenum glformat);
769 - Texture(SDL_Surface* surface, GLenum glformat);
770 + Texture(SDL_Surface* sdlsurface, GLenum glformat);
773 - GLuint get_handle() const
775 + const GLuint &get_handle() const {
776 + assert(use_opengl);
777 + return surface.opengl.handle;
780 + void set_handle(GLuint handle) {
781 + assert(use_opengl);
782 + surface.opengl.handle = handle;
786 + SDL_Surface *get_surface() const
790 + assert(!use_opengl);
792 + return surface.sdl;
795 + void set_surface(SDL_Surface *sdlsurface)
798 + assert(!use_opengl);
800 + surface.sdl = sdlsurface;
803 unsigned int get_width() const
809 + return surface.opengl.width;
814 + return surface.sdl->w;
818 unsigned int get_height() const
824 + return surface.opengl.height;
829 + return surface.sdl->h;
834 Index: src/video/surface.cpp
835 ===================================================================
836 --- src/video/surface.cpp (revision 5071)
837 +++ src/video/surface.cpp (working copy)
840 #include <SDL_image.h>
843 #include "gameconfig.hpp"
844 #include "physfs/physfs_sdl.hpp"
845 #include "video/surface.hpp"
848 texture = texture_manager->get(file);
852 - uv_right = texture->get_uv_right();
853 - uv_bottom = texture->get_uv_bottom();
855 - width = texture->get_image_width();
856 - height = texture->get_image_height();
858 + use_opengl = config->use_opengl;
862 + surface.opengl.uv_left = 0;
863 + surface.opengl.uv_top = 0;
864 + surface.opengl.uv_right = texture->get_uv_right();
865 + surface.opengl.uv_bottom = texture->get_uv_bottom();
867 + surface.opengl.width = texture->get_image_width();
868 + surface.opengl.height = texture->get_image_height();
873 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
875 + surface.sdl.offsetx = 0;
876 + surface.sdl.offsety = 0;
877 + surface.sdl.width = static_cast<int>(texture->get_image_width());
878 + surface.sdl.height = static_cast<int>(texture->get_image_height());
880 + surface.sdl.flipx = false;
884 Surface::Surface(const std::string& file, int x, int y, int w, int h)
886 texture = texture_manager->get(file);
889 - float tex_w = static_cast<float> (texture->get_width());
890 - float tex_h = static_cast<float> (texture->get_height());
891 - uv_left = static_cast<float>(x) / tex_w;
892 - uv_top = static_cast<float>(y) / tex_h;
893 - uv_right = static_cast<float>(x+w) / tex_w;
894 - uv_bottom = static_cast<float>(y+h) / tex_h;
896 + use_opengl = config->use_opengl;
902 + float tex_w = static_cast<float> (texture->get_width());
903 + float tex_h = static_cast<float> (texture->get_height());
904 + surface.opengl.uv_left = static_cast<float>(x) / tex_w;
905 + surface.opengl.uv_top = static_cast<float>(y) / tex_h;
906 + surface.opengl.uv_right = static_cast<float>(x+w) / tex_w;
907 + surface.opengl.uv_bottom = static_cast<float>(y+h) / tex_h;
909 + surface.opengl.width = w;
910 + surface.opengl.height = h;
915 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
917 + surface.sdl.offsetx = x;
918 + surface.sdl.offsety = y;
919 + surface.sdl.width = w;
920 + surface.sdl.height = h;
922 + surface.sdl.flipx = false;
926 Surface::Surface(const Surface& other)
928 texture = other.texture;
931 - uv_left = other.uv_left;
932 - uv_top = other.uv_top;
933 - uv_right = other.uv_right;
934 - uv_bottom = other.uv_bottom;
935 - width = other.width;
936 - height = other.height;
938 + use_opengl = config->use_opengl;
942 + surface.opengl.uv_left = other.surface.opengl.uv_left;
943 + surface.opengl.uv_top = other.surface.opengl.uv_top;
944 + surface.opengl.uv_right = other.surface.opengl.uv_right;
945 + surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
946 + surface.opengl.width = other.surface.opengl.width;
947 + surface.opengl.height = other.surface.opengl.height;
952 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
954 + surface.sdl.offsetx = other.surface.sdl.offsetx;
955 + surface.sdl.offsety = other.surface.sdl.offsety;
956 + surface.sdl.width = other.surface.sdl.width;
957 + surface.sdl.height = other.surface.sdl.height;
959 + surface.sdl.flipx = other.surface.sdl.flipx;
964 @@ -86,148 +142,584 @@
966 texture = other.texture;
968 - uv_left = other.uv_left;
969 - uv_top = other.uv_top;
970 - uv_right = other.uv_right;
971 - uv_bottom = other.uv_bottom;
972 - width = other.width;
973 - height = other.height;
975 + use_opengl = config->use_opengl;
979 + surface.opengl.uv_left = other.surface.opengl.uv_left;
980 + surface.opengl.uv_top = other.surface.opengl.uv_top;
981 + surface.opengl.uv_right = other.surface.opengl.uv_right;
982 + surface.opengl.uv_bottom = other.surface.opengl.uv_bottom;
983 + surface.opengl.width = other.surface.opengl.width;
984 + surface.opengl.height = other.surface.opengl.height;
989 + memset(transforms, 0, NUM_EFFECTS * sizeof(SDL_Surface *));
991 + surface.sdl.offsetx = other.surface.sdl.offsetx;
992 + surface.sdl.offsety = other.surface.sdl.offsety;
993 + surface.sdl.width = other.surface.sdl.width;
994 + surface.sdl.height = other.surface.sdl.height;
996 + surface.sdl.flipx = other.surface.sdl.flipx;
1010 + std::for_each(transforms, transforms + NUM_EFFECTS, SDL_FreeSurface);
1017 - std::swap(uv_left, uv_right);
1021 + std::swap(surface.opengl.uv_left, surface.opengl.uv_right);
1026 + surface.sdl.flipx = !surface.sdl.flipx;
1030 -static inline void intern_draw(float left, float top, float right, float bottom, float uv_left, float uv_top,
1031 - float uv_right, float uv_bottom,
1032 - DrawingEffect effect)
1036 - if(effect & HORIZONTAL_FLIP)
1037 - std::swap(uv_left, uv_right);
1038 - if(effect & VERTICAL_FLIP) {
1039 - std::swap(uv_top, uv_bottom);
1041 + inline void intern_draw(float left, float top, float right, float bottom, float uv_left, float uv_top,
1042 + float uv_right, float uv_bottom,
1043 + DrawingEffect effect)
1045 + if(effect & HORIZONTAL_FLIP)
1046 + std::swap(uv_left, uv_right);
1047 + if(effect & VERTICAL_FLIP) {
1048 + std::swap(uv_top, uv_bottom);
1051 - glBegin(GL_QUADS);
1052 - glTexCoord2f(uv_left, uv_top);
1053 - glVertex2f(left, top);
1054 + glBegin(GL_QUADS);
1055 + glTexCoord2f(uv_left, uv_top);
1056 + glVertex2f(left, top);
1058 - glTexCoord2f(uv_right, uv_top);
1059 - glVertex2f(right, top);
1060 + glTexCoord2f(uv_right, uv_top);
1061 + glVertex2f(right, top);
1063 - glTexCoord2f(uv_right, uv_bottom);
1064 - glVertex2f(right, bottom);
1065 + glTexCoord2f(uv_right, uv_bottom);
1066 + glVertex2f(right, bottom);
1068 - glTexCoord2f(uv_left, uv_bottom);
1069 - glVertex2f(left, bottom);
1073 -static inline void intern_draw2(float left, float top, float right, float bottom,
1074 - float uv_left, float uv_top,
1075 - float uv_right, float uv_bottom,
1076 - float angle, float alpha,
1077 - const Color& color,
1078 - const Blend& blend,
1079 - DrawingEffect effect)
1081 - if(effect & HORIZONTAL_FLIP)
1082 - std::swap(uv_left, uv_right);
1083 - if(effect & VERTICAL_FLIP) {
1084 - std::swap(uv_top, uv_bottom);
1085 + glTexCoord2f(uv_left, uv_bottom);
1086 + glVertex2f(left, bottom);
1090 - float center_x = (left + right) / 2;
1091 - float center_y = (top + bottom) / 2;
1092 + inline void intern_draw2(float left, float top, float right, float bottom,
1093 + float uv_left, float uv_top,
1094 + float uv_right, float uv_bottom,
1095 + float angle, float alpha,
1096 + const Color& color,
1097 + const Blend& blend,
1098 + DrawingEffect effect)
1100 + if(effect & HORIZONTAL_FLIP)
1101 + std::swap(uv_left, uv_right);
1102 + if(effect & VERTICAL_FLIP) {
1103 + std::swap(uv_top, uv_bottom);
1106 - float sa = sinf(angle/180.0f*M_PI);
1107 - float ca = cosf(angle/180.0f*M_PI);
1108 + float center_x = (left + right) / 2;
1109 + float center_y = (top + bottom) / 2;
1112 - right -= center_x;
1113 + float sa = sinf(angle/180.0f*M_PI);
1114 + float ca = cosf(angle/180.0f*M_PI);
1117 - bottom -= center_y;
1119 + right -= center_x;
1121 - glBlendFunc(blend.sfactor, blend.dfactor);
1122 - glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
1123 - glBegin(GL_QUADS);
1124 - glTexCoord2f(uv_left, uv_top);
1125 - glVertex2f(left*ca - top*sa + center_x,
1126 - left*sa + top*ca + center_y);
1128 + bottom -= center_y;
1130 - glTexCoord2f(uv_right, uv_top);
1131 - glVertex2f(right*ca - top*sa + center_x,
1132 - right*sa + top*ca + center_y);
1133 + glBlendFunc(blend.sfactor, blend.dfactor);
1134 + glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
1135 + glBegin(GL_QUADS);
1136 + glTexCoord2f(uv_left, uv_top);
1137 + glVertex2f(left*ca - top*sa + center_x,
1138 + left*sa + top*ca + center_y);
1140 - glTexCoord2f(uv_right, uv_bottom);
1141 - glVertex2f(right*ca - bottom*sa + center_x,
1142 - right*sa + bottom*ca + center_y);
1143 + glTexCoord2f(uv_right, uv_top);
1144 + glVertex2f(right*ca - top*sa + center_x,
1145 + right*sa + top*ca + center_y);
1147 - glTexCoord2f(uv_left, uv_bottom);
1148 - glVertex2f(left*ca - bottom*sa + center_x,
1149 - left*sa + bottom*ca + center_y);
1151 + glTexCoord2f(uv_right, uv_bottom);
1152 + glVertex2f(right*ca - bottom*sa + center_x,
1153 + right*sa + bottom*ca + center_y);
1155 - // FIXME: find a better way to restore the blend mode
1156 - glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1157 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1158 + glTexCoord2f(uv_left, uv_bottom);
1159 + glVertex2f(left*ca - bottom*sa + center_x,
1160 + left*sa + bottom*ca + center_y);
1163 + // FIXME: find a better way to restore the blend mode
1164 + glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1165 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1171 -Surface::draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const
1172 +Surface::draw(float x, float y, float alpha,
1174 + float angle, const Color& color, const Blend& blend,
1176 + float, const Color&, const Blend&,
1178 + DrawingEffect effect) const
1180 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1182 - intern_draw2(x, y,
1183 - x + width, y + height,
1184 - uv_left, uv_top, uv_right, uv_bottom,
1193 + glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1194 + intern_draw2(x, y,
1195 + x + surface.opengl.width, y + surface.opengl.height,
1196 + surface.opengl.uv_left, surface.opengl.uv_top,
1197 + surface.opengl.uv_right, surface.opengl.uv_bottom,
1207 + draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
1212 Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
1214 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1218 + glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1219 + glColor4f(1, 1, 1, alpha);
1221 + x + surface.opengl.width, y + surface.opengl.height,
1222 + surface.opengl.uv_left, surface.opengl.uv_top,
1223 + surface.opengl.uv_right, surface.opengl.uv_bottom, effect);
1224 + glColor4f(1, 1, 1, 1);
1229 + draw_part(0, 0, x, y, surface.sdl.width, surface.sdl.height, alpha, effect);
1233 - glColor4f(1, 1, 1, alpha);
1235 - x + width, y + height,
1236 - uv_left, uv_top, uv_right, uv_bottom, effect);
1237 - glColor4f(1, 1, 1, 1);
1243 + SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
1245 + if(numerator == denominator)
1252 + SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask);
1253 + int bpp = dst->format->BytesPerPixel;
1254 + for(int y = 0;y < dst->h;y++) {
1255 + for(int x = 0;x < dst->w;x++) {
1256 + Uint8 *srcpixel = (Uint8 *) src->pixels + (y * denominator / numerator) * src->pitch + (x * denominator / numerator) * bpp;
1257 + Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
1260 + dstpixel[3] = srcpixel[3];
1262 + dstpixel[2] = srcpixel[2];
1264 + dstpixel[1] = srcpixel[1];
1266 + dstpixel[0] = srcpixel[0];
1276 + void getpixel(SDL_Surface *src, int srcx, int srcy, Uint8 color[4])
1278 + int bpp = src->format->BytesPerPixel;
1279 + Uint8 *srcpixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp;
1280 + Uint32 mapped = 0;
1283 + mapped = *srcpixel;
1286 + mapped = *(Uint16 *)srcpixel;
1289 +#if SDL_BYTEORDER == SDL_BIG_ENDIAN
1290 + mapped |= srcpixel[0] << 16;
1291 + mapped |= srcpixel[1] << 8;
1292 + mapped |= srcpixel[2] << 0;
1294 + mapped |= srcpixel[0] << 0;
1295 + mapped |= srcpixel[1] << 8;
1296 + mapped |= srcpixel[2] << 16;
1300 + mapped = *(Uint32 *)srcpixel;
1303 + SDL_GetRGBA(mapped, src->format, &color[0], &color[1], &color[2], &color[3]);
1306 + void merge(Uint8 color[4], Uint8 color0[4], Uint8 color1[4], int rem, int total)
1308 + color[0] = (color0[0] * (total - rem) + color1[0] * rem) / total;
1309 + color[1] = (color0[1] * (total - rem) + color1[1] * rem) / total;
1310 + color[2] = (color0[2] * (total - rem) + color1[2] * rem) / total;
1311 + color[3] = (color0[3] * (total - rem) + color1[3] * rem) / total;
1314 + SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
1316 + if(numerator == denominator)
1323 + SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask);
1324 + int bpp = dst->format->BytesPerPixel;
1325 + for(int y = 0;y < dst->h;y++) {
1326 + for(int x = 0;x < dst->w;x++) {
1327 + int srcx = x * denominator / numerator;
1328 + int srcy = y * denominator / numerator;
1329 + Uint8 color00[4], color01[4], color10[4], color11[4];
1330 + getpixel(src, srcx, srcy, color00);
1331 + getpixel(src, srcx + 1, srcy, color01);
1332 + getpixel(src, srcx, srcy + 1, color10);
1333 + getpixel(src, srcx + 1, srcy + 1, color11);
1334 + Uint8 color0[4], color1[4], color[4];
1335 + int remx = x * denominator % numerator;
1336 + merge(color0, color00, color01, remx, numerator);
1337 + merge(color1, color10, color11, remx, numerator);
1338 + int remy = y * denominator % numerator;
1339 + merge(color, color0, color1, remy, numerator);
1340 + Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
1341 + Uint32 mapped = SDL_MapRGBA(dst->format, color[0], color[1], color[2], color[3]);
1344 + *dstpixel = mapped;
1347 + *(Uint16 *)dstpixel = mapped;
1350 +#if SDL_BYTEORDER == SDL_BIG_ENDIAN
1351 + dstpixel[0] = (mapped >> 16) & 0xff;
1352 + dstpixel[1] = (mapped >> 8) & 0xff;
1353 + dstpixel[2] = (mapped >> 0) & 0xff;
1355 + dstpixel[0] = (mapped >> 0) & 0xff;
1356 + dstpixel[1] = (mapped >> 8) & 0xff;
1357 + dstpixel[2] = (mapped >> 16) & 0xff;
1361 + *(Uint32 *)dstpixel = mapped;
1371 + // FIXME: Horizontal and vertical line problem
1373 + void accumulate(SDL_Surface *src, int srcx, int srcy, int color[4], int weight)
1375 + if(srcx < 0 || srcy < 0 || weight == 0) {
1378 + int bpp = src->format->BytesPerPixel;
1379 + Uint8 *srcpixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp;
1380 + Uint32 mapped = 0;
1383 + mapped = *srcpixel;
1386 + mapped = *(Uint16 *)srcpixel;
1389 +#if SDL_BYTEORDER == SDL_BIG_ENDIAN
1390 + mapped |= srcpixel[0] << 16;
1391 + mapped |= srcpixel[1] << 8;
1392 + mapped |= srcpixel[2] << 0;
1394 + mapped |= srcpixel[0] << 0;
1395 + mapped |= srcpixel[1] << 8;
1396 + mapped |= srcpixel[2] << 16;
1400 + mapped = *(Uint32 *)srcpixel;
1403 + Uint8 red, green, blue, alpha;
1404 + SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
1405 + color[0] += red * weight;
1406 + color[1] += green * weight;
1407 + color[2] += blue * weight;
1408 + color[3] += alpha * weight;
1411 + void accumulate_line(SDL_Surface *src, int srcy, int line[][4], int linesize, int weight, int numerator, int denominator)
1413 + int intpart = denominator / numerator;
1414 + int fractpart = denominator % numerator;
1415 + for(int x = 0, xe = 0, srcx = 0;x < linesize;x++) {
1416 + accumulate(src, srcx, srcy, line[x], (numerator - xe) * weight);
1418 + for(int i = 0;i < intpart - 1;i++) {
1419 + accumulate(src, srcx, srcy, line[x], numerator * weight);
1423 + if(xe >= numerator) {
1427 + accumulate(src, srcx, srcy, line[x], xe * weight);
1431 + SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
1433 + if(numerator == denominator)
1440 + SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask);
1441 + int bpp = dst->format->BytesPerPixel;
1442 + int intpart = denominator / numerator;
1443 + int fractpart = denominator % numerator;
1444 + for(int y = 0, ye = 0, srcy = 0;y < dst->h;y++) {
1445 + int line[dst->w][4];
1446 + memset(line, 0, sizeof(int) * dst->w * 4);
1447 + accumulate_line(src, srcy, line, dst->w, numerator - ye, numerator, denominator);
1449 + for(int i = 0;i < intpart - 1;i++) {
1450 + accumulate_line(src, srcy, line, dst->w, numerator, numerator, denominator);
1454 + if(ye >= numerator) {
1458 + accumulate_line(src, srcy, line, dst->w, ye, numerator, denominator);
1459 + for(int x = 0;x < dst->w;x++) {
1460 + Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
1461 + Uint32 mapped = SDL_MapRGBA(dst->format, line[x][0] / (denominator * denominator), line[x][1] / (denominator * denominator), line[x][2] / (denominator * denominator), line[x][3] / (denominator * denominator));
1464 + *dstpixel = mapped;
1467 + *(Uint16 *)dstpixel = mapped;
1470 +#if SDL_BYTEORDER == SDL_BIG_ENDIAN
1471 + dstpixel[0] = (mapped >> 16) & 0xff;
1472 + dstpixel[1] = (mapped >> 8) & 0xff;
1473 + dstpixel[2] = (mapped >> 0) & 0xff;
1475 + dstpixel[0] = (mapped >> 0) & 0xff;
1476 + dstpixel[1] = (mapped >> 8) & 0xff;
1477 + dstpixel[2] = (mapped >> 16) & 0xff;
1481 + *(Uint32 *)dstpixel = mapped;
1491 + SDL_Surface *horz_flip(SDL_Surface *src)
1493 + SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask);
1494 + int bpp = dst->format->BytesPerPixel;
1495 + for(int y = 0;y < dst->h;y++) {
1496 + for(int x = 0;x < dst->w;x++) {
1497 + Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
1498 + Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + (dst->w - x - 1) * bpp;
1501 + dstpixel[3] = srcpixel[3];
1503 + dstpixel[2] = srcpixel[2];
1505 + dstpixel[1] = srcpixel[1];
1507 + dstpixel[0] = srcpixel[0];
1514 + SDL_Surface *vert_flip(SDL_Surface *src)
1516 + SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask);
1517 + int bpp = dst->format->BytesPerPixel;
1518 + for(int y = 0;y < dst->h;y++) {
1519 + for(int x = 0;x < dst->w;x++) {
1520 + Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
1521 + Uint8 *dstpixel = (Uint8 *) dst->pixels + (dst->h - y - 1) * dst->pitch + x * bpp;
1524 + dstpixel[3] = srcpixel[3];
1526 + dstpixel[2] = srcpixel[2];
1528 + dstpixel[1] = srcpixel[1];
1530 + dstpixel[0] = srcpixel[0];
1539 Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
1541 float width, float height, float alpha,
1543 + float width, float height, float,
1545 DrawingEffect effect) const
1547 - float uv_width = uv_right - uv_left;
1548 - float uv_height = uv_bottom - uv_top;
1552 + float uv_width = surface.opengl.uv_right - surface.opengl.uv_left;
1553 + float uv_height = surface.opengl.uv_bottom - surface.opengl.uv_top;
1555 - float uv_left = this->uv_left + (uv_width * src_x) / this->width;
1556 - float uv_top = this->uv_top + (uv_height * src_y) / this->height;
1557 - float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
1558 - float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
1559 + float uv_left = surface.opengl.uv_left + (uv_width * src_x) / surface.opengl.width;
1560 + float uv_top = surface.opengl.uv_top + (uv_height * src_y) / surface.opengl.height;
1561 + float uv_right = surface.opengl.uv_left + (uv_width * (src_x + width)) / surface.opengl.width;
1562 + float uv_bottom = surface.opengl.uv_top + (uv_height * (src_y + height)) / surface.opengl.height;
1564 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1565 + glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1566 + glColor4f(1, 1, 1, alpha);
1567 + intern_draw(dst_x, dst_y,
1568 + dst_x + width, dst_y + height,
1569 + uv_left, uv_top, uv_right, uv_bottom, effect);
1570 + glColor4f(1, 1, 1, 1);
1575 + //FIXME: support parameter "alpha"
1577 + // get and check SDL_Surface
1578 + if (texture->get_surface() == 0) {
1579 + std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl;
1583 - glColor4f(1, 1, 1, alpha);
1584 - intern_draw(dst_x, dst_y,
1585 - dst_x + width, dst_y + height,
1586 - uv_left, uv_top, uv_right, uv_bottom, effect);
1587 - glColor4f(1, 1, 1, 1);
1588 + if (surface.sdl.flipx) effect = HORIZONTAL_FLIP;
1590 + float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
1591 + float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
1594 + if(xfactor < yfactor)
1596 + numerator = config->screenwidth;
1597 + denominator = SCREEN_WIDTH;
1601 + numerator = config->screenheight;
1602 + denominator = SCREEN_HEIGHT;
1605 + if(transforms[effect] == 0) {
1606 + if(transforms[NO_EFFECT] == 0) {
1607 + transforms[NO_EFFECT] = scale(texture->get_surface(), numerator, denominator);
1612 + case HORIZONTAL_FLIP:
1613 + transforms[HORIZONTAL_FLIP] = horz_flip(transforms[NO_EFFECT]);
1615 + case VERTICAL_FLIP:
1616 + transforms[VERTICAL_FLIP] = vert_flip(transforms[NO_EFFECT]);
1619 + std::cerr << "Warning: No known transformation applies to surface, skipped draw" << std::endl;
1624 + int ox = surface.sdl.offsetx;
1625 + if (effect == HORIZONTAL_FLIP) ox = static_cast<int>(texture->get_surface()->w) - (ox+static_cast<int>(width));
1626 + int oy = surface.sdl.offsety;
1627 + if (effect == VERTICAL_FLIP) oy = static_cast<int>(texture->get_surface()->h) - (oy+static_cast<int>(height));
1628 + // draw surface to screen
1629 + SDL_Surface* screen = SDL_GetVideoSurface();
1632 + srcRect.x = static_cast<int>((ox + src_x) * numerator / denominator);
1633 + srcRect.y = static_cast<int>((oy + src_y) * numerator / denominator);
1634 + srcRect.w = static_cast<int>(width * numerator / denominator);
1635 + srcRect.h = static_cast<int>(height * numerator / denominator);
1638 + dstRect.x = static_cast<int>(dst_x * numerator / denominator);
1639 + dstRect.y = static_cast<int>(dst_y * numerator / denominator);
1641 + SDL_BlitSurface(transforms[effect], &srcRect, screen, &dstRect);
1644 Index: src/video/texture_manager.cpp
1645 ===================================================================
1646 --- src/video/texture_manager.cpp (revision 5071)
1647 +++ src/video/texture_manager.cpp (working copy)
1651 #include <SDL_image.h>
1653 -#include <GL/glext.h>
1656 #include <stdexcept>
1657 #include "physfs/physfs_sdl.hpp"
1658 #include "image_texture.hpp"
1659 #include "glutil.hpp"
1660 +#include "gameconfig.hpp"
1661 #include "file_system.hpp"
1664 @@ -149,12 +148,16 @@
1666 TextureManager::save_textures()
1668 - glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1669 - glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
1670 - glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1671 - glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1672 - glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
1673 - glPixelStorei(GL_PACK_ALIGNMENT, 1);
1675 + if(config->use_opengl) {
1676 + glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1677 + glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
1678 + glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1679 + glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1680 + glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
1681 + glPixelStorei(GL_PACK_ALIGNMENT, 1);
1684 for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
1687 @@ -169,74 +172,90 @@
1689 SavedTexture saved_texture;
1690 saved_texture.texture = texture;
1691 - glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1692 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
1693 - &saved_texture.width);
1694 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
1695 - &saved_texture.height);
1696 - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
1697 - &saved_texture.border);
1698 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1699 - &saved_texture.min_filter);
1700 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1701 - &saved_texture.mag_filter);
1702 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1703 - &saved_texture.wrap_s);
1704 - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1705 - &saved_texture.wrap_t);
1707 + if(config->use_opengl) {
1708 + glBindTexture(GL_TEXTURE_2D, texture->get_handle());
1709 + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
1710 + &saved_texture.width);
1711 + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
1712 + &saved_texture.height);
1713 + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
1714 + &saved_texture.border);
1715 + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1716 + &saved_texture.min_filter);
1717 + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1718 + &saved_texture.mag_filter);
1719 + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1720 + &saved_texture.wrap_s);
1721 + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1722 + &saved_texture.wrap_t);
1726 size_t pixelssize = saved_texture.width * saved_texture.height * 4;
1727 saved_texture.pixels = new char[pixelssize];
1729 - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1730 - saved_texture.pixels);
1732 + if(config->use_opengl) {
1733 + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1734 + saved_texture.pixels);
1738 saved_textures.push_back(saved_texture);
1740 - glDeleteTextures(1, &(texture->handle));
1741 - texture->handle = 0;
1743 + if(config->use_opengl) {
1744 + glDeleteTextures(1, &(texture->get_handle()));
1745 + texture->set_handle(0);
1747 - assert_gl("retrieving texture for save");
1748 + assert_gl("retrieving texture for save");
1754 TextureManager::reload_textures()
1756 - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1757 - glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1758 - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1759 - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1760 - glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1761 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1763 + if(config->use_opengl) {
1764 + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1765 + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1766 + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1767 + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1768 + glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
1769 + glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1771 - for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1772 - i != saved_textures.end(); ++i) {
1773 - SavedTexture& saved_texture = *i;
1774 + for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
1775 + i != saved_textures.end(); ++i) {
1776 + SavedTexture& saved_texture = *i;
1779 - glGenTextures(1, &handle);
1780 - assert_gl("creating texture handle");
1782 + glGenTextures(1, &handle);
1783 + assert_gl("creating texture handle");
1785 - glBindTexture(GL_TEXTURE_2D, handle);
1786 - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1787 - saved_texture.width, saved_texture.height,
1788 - saved_texture.border, GL_RGBA,
1789 - GL_UNSIGNED_BYTE, saved_texture.pixels);
1790 - delete[] saved_texture.pixels;
1791 - assert_gl("uploading texture pixel data");
1792 + glBindTexture(GL_TEXTURE_2D, handle);
1793 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1794 + saved_texture.width, saved_texture.height,
1795 + saved_texture.border, GL_RGBA,
1796 + GL_UNSIGNED_BYTE, saved_texture.pixels);
1797 + delete[] saved_texture.pixels;
1798 + assert_gl("uploading texture pixel data");
1800 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1801 - saved_texture.min_filter);
1802 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1803 - saved_texture.mag_filter);
1804 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1805 - saved_texture.wrap_s);
1806 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1807 - saved_texture.wrap_t);
1808 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1809 + saved_texture.min_filter);
1810 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1811 + saved_texture.mag_filter);
1812 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1813 + saved_texture.wrap_s);
1814 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1815 + saved_texture.wrap_t);
1817 - assert_gl("setting texture_params");
1818 - saved_texture.texture->handle = handle;
1819 + assert_gl("setting texture_params");
1820 + saved_texture.texture->set_handle(handle);
1825 saved_textures.clear();
1827 Index: src/video/surface.hpp
1828 ===================================================================
1829 --- src/video/surface.hpp (revision 5071)
1830 +++ src/video/surface.hpp (working copy)
1832 #ifndef __SURFACE_HPP__
1833 #define __SURFACE_HPP__
1835 +#include <config.h>
1839 +#include "gameconfig.hpp"
1840 #include "math/vector.hpp"
1844 /// bitset for drawing effects
1845 enum DrawingEffect {
1846 /** Don't apply anything */
1847 - NO_EFFECT = 0x0000,
1849 /** Draw the Surface upside down */
1850 - VERTICAL_FLIP = 0x0001,
1852 /** Draw the Surface from left to down */
1853 - HORIZONTAL_FLIP = 0x0002,
1861 friend class DrawingContext;
1863 - ImageTexture* texture;
1870 void draw(float x, float y, float alpha, float angle, const Color& color, const Blend& blend, DrawingEffect effect) const;
1871 void draw(float x, float y, float alpha, DrawingEffect effect) const;
1872 void draw_part(float src_x, float src_y, float dst_x, float dst_y,
1873 float width, float height,
1874 float alpha, DrawingEffect effect) const;
1878 + ImageTexture* texture;
1900 + int offsetx; /**< Region in ::surface to be used for blitting */
1901 + int offsety; /**< Region in ::surface to be used for blitting */
1902 + int width; /**< Region in ::surface to be used for blitting */
1903 + int height; /**< Region in ::surface to be used for blitting */
1906 + mutable SDL_Surface *transforms[NUM_EFFECTS]; /**< Cache for pre-transformed surfaces */
1909 Surface(const std::string& file);
1910 Surface(const std::string& file, int x, int y, int w, int h);
1911 @@ -75,12 +102,30 @@
1913 float get_width() const
1919 + return surface.opengl.width;
1924 + return surface.sdl.width;
1928 float get_height() const
1934 + return surface.opengl.height;
1939 + return surface.sdl.height;
1944 Index: src/gameconfig.cpp
1945 ===================================================================
1946 --- src/gameconfig.cpp (revision 5071)
1947 +++ src/gameconfig.cpp (working copy)
1951 use_fullscreen = true;
1953 + use_opengl = true;
1957 sound_enabled = true;
1959 const lisp::Lisp* config_video_lisp = config_lisp->get_lisp("video");
1960 if(config_video_lisp) {
1961 config_video_lisp->get("fullscreen", use_fullscreen);
1962 - config_video_lisp->get("vsync", try_vsync);
1964 + config_video_lisp->get("opengl", use_opengl);
1966 + config_video_lisp->get("vsync", try_vsync);
1967 config_video_lisp->get("width", screenwidth);
1968 config_video_lisp->get("height", screenheight);
1969 config_video_lisp->get("aspect_ratio", aspect_ratio);
1972 writer.start_list("video");
1973 writer.write_bool("fullscreen", use_fullscreen);
1975 + writer.write_bool("opengl", use_opengl);
1977 writer.write_bool("vsync", try_vsync);
1978 writer.write_int("width", screenwidth);
1979 writer.write_int("height", screenheight);
1981 ===================================================================
1982 --- src/main.cpp (revision 5071)
1983 +++ src/main.cpp (working copy)
1987 #include <SDL_image.h>
1990 #include "gameconfig.hpp"
1991 #include "resources.hpp"
1992 @@ -383,7 +382,11 @@
1993 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
1994 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
1996 - int flags = SDL_OPENGL;
1998 + int flags = config->use_opengl ? SDL_OPENGL : SDL_SWSURFACE;
2000 + int flags = SDL_SWSURFACE;
2002 if(config->use_fullscreen)
2003 flags |= SDL_FULLSCREEN;
2004 int width = config->screenwidth;
2005 @@ -437,23 +440,28 @@
2007 log_info << (config->use_fullscreen?"fullscreen ":"window ") << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << " Ratio: " << aspect_ratio << "\n";
2009 - // setup opengl state and transform
2010 - glDisable(GL_DEPTH_TEST);
2011 - glDisable(GL_CULL_FACE);
2012 - glEnable(GL_TEXTURE_2D);
2013 - glEnable(GL_BLEND);
2014 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2016 + if(config->use_opengl)
2018 + // setup opengl state and transform
2019 + glDisable(GL_DEPTH_TEST);
2020 + glDisable(GL_CULL_FACE);
2021 + glEnable(GL_TEXTURE_2D);
2022 + glEnable(GL_BLEND);
2023 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2025 - glViewport(0, 0, screen->w, screen->h);
2026 - glMatrixMode(GL_PROJECTION);
2028 - // logical resolution here not real monitor resolution
2029 - glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
2030 - glMatrixMode(GL_MODELVIEW);
2032 - glTranslatef(0, 0, 0);
2033 + glViewport(0, 0, screen->w, screen->h);
2034 + glMatrixMode(GL_PROJECTION);
2036 + // logical resolution here not real monitor resolution
2037 + glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
2038 + glMatrixMode(GL_MODELVIEW);
2040 + glTranslatef(0, 0, 0);
2042 - check_gl_error("Setting up view matrices");
2043 + check_gl_error("Setting up view matrices");
2047 if(texture_manager != NULL)
2048 texture_manager->reload_textures();
2050 ===================================================================
2051 --- configure.ac (revision 5071)
2052 +++ configure.ac (working copy)
2053 @@ -154,9 +154,15 @@
2054 [AC_MSG_ERROR([Please intall OpenAL])],
2058 -if test "$no_gl" = "yes"; then
2059 - AC_MSG_ERROR([Please install opengl libraries and headers])
2060 +AC_ARG_ENABLE(opengl,
2061 + AC_HELP_STRING([--enable-opengl], [enable opengl support]),
2062 + [enable_opengl=$enableval], [enable_opengl=yes])
2064 +if test "$enable_opengl" = "yes"; then
2066 + if test "$no_gl" != "yes"; then
2067 + AC_DEFINE_UNQUOTED(HAVE_OPENGL, 1, Define if OpenGL is present on the system)
2071 dnl Checks for library functions.