2 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
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.
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.
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/>.
17 #include "supertux/gameconfig.hpp"
18 #include "video/gl/gl_texture.hpp"
21 #include <glbinding/ContextInfo.h>
26 #ifdef GL_VERSION_ES_CM_1_0
27 inline bool is_power_of_2(int v)
29 return (v & (v-1)) == 0;
33 inline int next_power_of_two(int val)
43 GLTexture::GLTexture(unsigned int width, unsigned int height) :
50 #ifdef GL_VERSION_ES_CM_1_0
51 assert(is_power_of_2(width));
52 assert(is_power_of_2(height));
54 m_texture_width = width;
55 m_texture_height = height;
56 m_image_width = width;
57 m_image_height = height;
59 assert_gl("before creating texture");
60 glGenTextures(1, &m_handle);
63 glBindTexture(GL_TEXTURE_2D, m_handle);
65 glTexImage2D(GL_TEXTURE_2D, 0, static_cast<GLint>(GL_RGBA), m_texture_width,
66 m_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
70 glDeleteTextures(1, &m_handle);
75 GLTexture::GLTexture(SDL_Surface* image) :
82 #ifdef GL_VERSION_ES_CM_1_0
83 m_texture_width = next_power_of_two(image->w);
84 m_texture_height = next_power_of_two(image->h);
87 static auto extensions = glbinding::ContextInfo::extensions();
88 if (extensions.find(GLextension::GL_ARB_texture_non_power_of_two) != extensions.end())
90 m_texture_width = image->w;
91 m_texture_height = image->h;
94 if (GLEW_ARB_texture_non_power_of_two)
96 m_texture_width = image->w;
97 m_texture_height = image->h;
102 m_texture_width = next_power_of_two(image->w);
103 m_texture_height = next_power_of_two(image->h);
107 m_image_width = image->w;
108 m_image_height = image->h;
110 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
111 SDL_Surface* convert = SDL_CreateRGBSurface(0,
112 m_texture_width, m_texture_height, 32,
113 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
115 SDL_Surface* convert = SDL_CreateRGBSurface(0,
116 m_texture_width, m_texture_height, 32,
117 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
121 throw std::runtime_error("Couldn't create texture: out of memory");
124 SDL_SetSurfaceBlendMode(image, SDL_BLENDMODE_NONE);
125 SDL_BlitSurface(image, 0, convert, 0);
127 assert_gl("before creating texture");
128 glGenTextures(1, &m_handle);
132 if(convert->format->BytesPerPixel == 3)
134 else if(convert->format->BytesPerPixel == 4)
135 sdl_format = GL_RGBA;
137 sdl_format = GL_RGBA;
141 glBindTexture(GL_TEXTURE_2D, m_handle);
142 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
143 #if defined(GL_UNPACK_ROW_LENGTH) || defined(USE_GLBINDING)
144 glPixelStorei(GL_UNPACK_ROW_LENGTH, convert->pitch/convert->format->BytesPerPixel);
146 /* OpenGL ES doesn't support UNPACK_ROW_LENGTH, let's hope SDL didn't add
147 * padding bytes, otherwise we need some extra code here... */
148 assert(convert->pitch == m_texture_width * convert->format->BytesPerPixel);
151 if(SDL_MUSTLOCK(convert))
153 SDL_LockSurface(convert);
156 glTexImage2D(GL_TEXTURE_2D, 0, static_cast<GLint>(GL_RGBA),
157 m_texture_width, m_texture_height, 0, sdl_format,
158 GL_UNSIGNED_BYTE, convert->pixels);
160 // no not use mipmaps
163 glGenerateMipmap(GL_TEXTURE_2D);
166 if(SDL_MUSTLOCK(convert))
168 SDL_UnlockSurface(convert);
171 assert_gl("creating texture");
173 set_texture_params();
175 glDeleteTextures(1, &m_handle);
176 SDL_FreeSurface(convert);
179 SDL_FreeSurface(convert);
182 GLTexture::~GLTexture()
184 glDeleteTextures(1, &m_handle);
188 GLTexture::set_texture_params()
190 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, static_cast<GLint>(GL_LINEAR));
191 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, static_cast<GLint>(GL_LINEAR));
193 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast<GLint>(GL_CLAMP_TO_EDGE));
194 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, static_cast<GLint>(GL_CLAMP_TO_EDGE));
196 assert_gl("set texture params");