Initial integration, lots of broken stuff
[supertux.git] / src / unison / src / video / opengl / Renderer.cpp
1 //          Copyright Timothy Goya 2007.
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5
6 #include "Renderer.hpp"
7 #include "Texture.hpp"
8 #include "Window.hpp"
9 #include <unison/video/Surface.hpp>
10 #include <unison/video/Window.hpp>
11 #include <unison/video/sdl/Blitters.hpp>
12 #include <unison/video/backend/Texture.hpp>
13 #include <unison/vfs/sdl/Utils.hpp>
14
15 #include <assert.h>
16
17 #include "SDL.h"
18 #include "SDL_image.h"
19
20 namespace Unison
21 {
22    namespace Video
23    {
24       namespace OpenGL
25       {
26          Renderer::Renderer()
27          {
28          }
29
30          Renderer::~Renderer()
31          {
32          }
33
34          void Renderer::init()
35          {
36             SDL_InitSubSystem(SDL_INIT_VIDEO);
37
38             glLoad(0);
39          }
40
41          void Renderer::quit()
42          {
43             SDL_QuitSubSystem(SDL_INIT_VIDEO);
44          }
45
46          std::string Renderer::get_name()
47          {
48             return "opengl";
49          }
50
51          bool Renderer::is_usable()
52          {
53             SDL_InitSubSystem(SDL_INIT_VIDEO);
54
55             if(SDL_GL_LoadLibrary(0))
56             {
57                SDL_QuitSubSystem(SDL_INIT_VIDEO);
58                return false;
59             }
60
61             if(!SDL_ListModes(0, SDL_OPENGL))
62             {
63                SDL_QuitSubSystem(SDL_INIT_VIDEO);
64                return false;
65             }
66
67             /*const SDL_VideoInfo *info = SDL_GetVideoInfo();
68             if(SDL_VideoModeOK(info->current_w, info->current_h, 0, SDL_OPENGL | SDL_FULLSCREEN))
69             {
70                SDL_QuitSubSystem(SDL_INIT_VIDEO);
71                return false;
72             }*/
73
74             SDL_QuitSubSystem(SDL_INIT_VIDEO);
75
76             return true;
77          }
78
79          Surface Renderer::load_surface(const std::string &filename)
80          {
81             SDL_Surface *image = IMG_Load_RW(VFS::SDL::Utils::open_physfs_in(filename), 1);
82             assert(image);
83             Surface surface = Surface(Area(image->w, image->h));
84             SDL_Surface *sdl_surface = SDL::Blitters::create_sdl_surface_from(surface);
85             assert(sdl_surface);
86             SDL::Blitters::blit_blend_none(image, Rect(), sdl_surface, Point());
87             SDL_FreeSurface(sdl_surface);
88             return surface;
89          }
90
91          Surface Renderer::load_surface(const std::string &filename, const Color &colorkey)
92          {
93             SDL_Surface *image = IMG_Load_RW(VFS::SDL::Utils::open_physfs_in(filename), 1);
94             assert(image);
95             Surface surface = Surface(Area(image->w, image->h));
96             SDL_Surface *sdl_surface = SDL::Blitters::create_sdl_surface_from(surface);
97             assert(sdl_surface);
98             SDL_SetColorKey(image, SDL_SRCCOLORKEY, SDL_MapRGB(image->format, colorkey.red, colorkey.blue, colorkey.alpha));
99             SDL::Blitters::blit_blend_none(image, Rect(), sdl_surface, Point());
100             SDL_FreeSurface(sdl_surface);
101             return surface;
102          }
103
104          void Renderer::save_surface(const Surface &surface, const std::string &filename)
105          {
106             SDL_Surface *sdl_surface = SDL::Blitters::create_sdl_surface_from(surface);
107             assert(sdl_surface);
108             SDL_SaveBMP(sdl_surface, filename.c_str());
109             SDL_FreeSurface(sdl_surface);
110          }
111
112          void Renderer::blit(const Surface &src, const Rect &src_rect, Surface &dst, const Point &dst_pos, const RenderOptions &options)
113          {
114             Surface fragment;
115             if(src_rect.pos == Point() && (src_rect.size == Area() || src_rect.size == src.get_size()))
116             {
117                fragment = src;
118             }
119             else
120             {
121                fragment = Surface(src_rect.size);
122                Blitters::blit_blend_none(src, src_rect, fragment, Point());
123             }
124             if(options.h_flip)
125             {
126                fragment = fragment.h_flip();
127             }
128             if(options.v_flip)
129             {
130                fragment = fragment.v_flip();
131             }
132             SDL_Surface *src_surface = SDL::Blitters::create_sdl_surface_from(fragment.modulate(options.color).modulate(options.alpha));
133             assert(src_surface);
134
135             SDL_Surface *dst_surface = SDL::Blitters::create_sdl_surface_from(dst);
136             assert(dst_surface);
137
138
139             SDL::Blitters::blit_blend(src_surface, Rect(Point(), fragment.get_size()), dst_surface, dst_pos, options.blend);
140
141             SDL_FreeSurface(dst_surface);
142             SDL_FreeSurface(src_surface);
143          }
144
145          void Renderer::blit(Backend::Texture *src, const Rect &src_rect, Surface &dst, const Point &dst_pos, const RenderOptions &options)
146          {
147             assert(src);
148             assert(dst.get_size() != Area());
149
150             blit(src->get_surface(), src_rect, dst, dst_pos, options);
151          }
152
153          void Renderer::fill(Surface &dst, const Color &color, const Rect &rect)
154          {
155             SDL_Surface *dst_surface = SDL::Blitters::create_sdl_surface_from(dst);
156             assert(dst_surface);
157
158             Uint32 mapped = SDL_MapRGBA(dst_surface->format, color.red, color.green, color.blue, color.alpha);
159             SDL_FillRect(dst_surface, &rect, mapped);
160          }
161
162          void Renderer::fill_blend(Surface &dst, const Color &color, const Rect &rect)
163          {
164             SDL_Surface *dst_surface = SDL::Blitters::create_sdl_surface_from(dst);
165             assert(dst_surface);
166
167             Uint32 mapped = SDL_MapRGBA(dst_surface->format, color.red, color.green, color.blue, color.alpha);
168             if(color.alpha == 0xff)
169             {
170                SDL_FillRect(dst_surface, &rect, mapped);
171             }
172             else if(color.alpha != 0x00)
173             {
174                SDL_Surface *temp = SDL_CreateRGBSurface(dst_surface->flags, rect.size.x, rect.size.y, dst_surface->format->BitsPerPixel, dst_surface->format->Rmask, dst_surface->format->Gmask, dst_surface->format->Bmask, dst_surface->format->Amask);
175
176                SDL_FillRect(temp, 0, mapped);
177                SDL_SetAlpha(temp, SDL_SRCALPHA | SDL_RLEACCEL, color.alpha);
178                SDL_BlitSurface(temp, 0, dst_surface, &rect);
179                SDL_FreeSurface(temp);
180             }
181          }
182
183          Backend::Window *Renderer::create_window(const Area &size, const Area &logical_size, bool fullscreen)
184          {
185             return new Window(size, logical_size, fullscreen);
186          }
187
188          Backend::Texture *Renderer::create_texture(const Surface &surface)
189          {
190             return new Texture(surface);
191          }
192       }
193    }
194 }