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