New grow and skid sounds from remaxim
[supertux.git] / src / video / gl_texture.cpp
1 //  $Id: gl_texture.cpp 4063 2006-07-21 21:05:23Z anmaster $
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #include <config.h>
21
22 #ifdef HAVE_OPENGL
23
24 #include "gl_texture.hpp"
25 #include "gameconfig.hpp"
26 #include "glutil.hpp"
27 #include "log.hpp"
28
29 #include <assert.h>
30 #include <stdexcept>
31
32 namespace
33 {
34   inline bool is_power_of_2(int v)
35   {
36     return (v & (v-1)) == 0;
37   }
38
39   inline int next_power_of_two(int val)
40   {
41     int result = 1;
42     while(result < val)
43       result *= 2;
44     return result;
45   }
46 }
47
48 namespace GL
49 {
50   Texture::Texture(unsigned int width, unsigned int height)
51   {
52     assert(is_power_of_2(width));
53     assert(is_power_of_2(height));
54     texture_width = width;
55     texture_height = height;
56     image_width = width;
57     image_height = height;
58
59     assert_gl("before creating texture");
60     glGenTextures(1, &handle);
61
62     try {
63       glBindTexture(GL_TEXTURE_2D, handle);
64
65       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_width,
66                    texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
67
68       set_texture_params();
69     } catch(...) {
70       glDeleteTextures(1, &handle);
71       throw;
72     }
73   }
74
75   Texture::Texture(SDL_Surface* image)
76   {
77     texture_width = next_power_of_two(image->w);
78     texture_height = next_power_of_two(image->h);
79     image_width = image->w;
80     image_height = image->h;
81
82 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
83     SDL_Surface* convert = SDL_CreateRGBSurface(SDL_SWSURFACE,
84         texture_width, texture_height, 32,
85         0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
86 #else
87     SDL_Surface* convert = SDL_CreateRGBSurface(SDL_SWSURFACE,
88         texture_width, texture_height, 32,
89         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
90 #endif
91
92     if(convert == 0) {
93       throw std::runtime_error("Couldn't create texture: out of memory");
94     }
95
96     SDL_SetAlpha(image, 0, 0);
97     SDL_BlitSurface(image, 0, convert, 0);
98
99     assert_gl("before creating texture");
100     glGenTextures(1, &handle);
101
102     try {
103       GLenum sdl_format;
104       if(convert->format->BytesPerPixel == 3)
105         sdl_format = GL_RGB;
106       else if(convert->format->BytesPerPixel == 4)
107         sdl_format = GL_RGBA;
108       else
109         assert(false);
110
111       glBindTexture(GL_TEXTURE_2D, handle);
112       glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
113 #ifdef GL_UNPACK_ROW_LENGTH
114       glPixelStorei(GL_UNPACK_ROW_LENGTH, convert->pitch/convert->format->BytesPerPixel);
115 #else
116       /* OpenGL ES doesn't support UNPACK_ROW_LENGTH, let's hope SDL didn't add
117        * padding bytes, otherwise we need some extra code here... */
118       assert(convert->pitch == texture_width * convert->format->BytesPerPixel);
119 #endif
120
121       if(SDL_MUSTLOCK(convert))
122       {
123         SDL_LockSurface(convert);
124       }
125       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_width,
126               texture_height, 0, sdl_format,
127               GL_UNSIGNED_BYTE, convert->pixels);
128       if(SDL_MUSTLOCK(convert))
129       {
130         SDL_UnlockSurface(convert);
131       }
132
133       assert_gl("creating texture");
134
135       set_texture_params();
136     } catch(...) {
137       glDeleteTextures(1, &handle);
138       SDL_FreeSurface(convert);
139       throw;
140     }
141     SDL_FreeSurface(convert);
142   }
143
144   Texture::~Texture()
145   {
146     glDeleteTextures(1, &handle);
147   }
148
149   void
150   Texture::set_texture_params()
151   {
152     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
153     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
154 #ifdef GL_CLAMP
155     /* OpenGL ES doesn't support it */
156     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
157     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
158 #endif
159
160     assert_gl("set texture params");
161   }
162 }
163
164 #endif