src/video/gl/gl_texture.cpp

Go to the documentation of this file.
00001 //  SuperTux
00002 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
00003 //
00004 //  This program is free software: you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation, either version 3 of the License, or
00007 //  (at your option) any later version.
00008 //
00009 //  This program is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 #include "supertux/gameconfig.hpp"
00018 #include "video/gl/gl_texture.hpp"
00019 
00020 namespace {
00021 
00022 inline bool is_power_of_2(int v)
00023 {
00024   return (v & (v-1)) == 0;
00025 }
00026 
00027 inline int next_power_of_two(int val)
00028 {
00029   int result = 1;
00030   while(result < val)
00031     result *= 2;
00032   return result;
00033 }
00034 
00035 } // namespace
00036 
00037 GLTexture::GLTexture(unsigned int width, unsigned int height) :
00038   handle(),
00039   texture_width(),
00040   texture_height(),
00041   image_width(),
00042   image_height()
00043 {
00044 #ifdef GL_VERSION_ES_CM_1_0
00045   assert(is_power_of_2(width));
00046   assert(is_power_of_2(height));
00047 #endif
00048   texture_width  = width;
00049   texture_height = height;
00050   image_width  = width;
00051   image_height = height;
00052 
00053   assert_gl("before creating texture");
00054   glGenTextures(1, &handle);
00055 
00056   try {
00057     glBindTexture(GL_TEXTURE_2D, handle);
00058 
00059     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_width,
00060                  texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
00061 
00062     set_texture_params();
00063   } catch(...) {
00064     glDeleteTextures(1, &handle);
00065     throw;
00066   }
00067 }
00068 
00069 GLTexture::GLTexture(SDL_Surface* image) :
00070   handle(),
00071   texture_width(),
00072   texture_height(),
00073   image_width(),
00074   image_height()
00075 {
00076 #ifdef GL_VERSION_ES_CM_1_0
00077   texture_width = next_power_of_two(image->w);
00078   texture_height = next_power_of_two(image->h);
00079 #else
00080   if (GLEW_ARB_texture_non_power_of_two)
00081   {
00082     texture_width  = image->w;
00083     texture_height = image->h;
00084   }
00085   else
00086   {
00087     texture_width = next_power_of_two(image->w);
00088     texture_height = next_power_of_two(image->h);
00089   }
00090 #endif
00091 
00092   image_width  = image->w;
00093   image_height = image->h;
00094 
00095 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00096   SDL_Surface* convert = SDL_CreateRGBSurface(SDL_SWSURFACE,
00097                                               texture_width, texture_height, 32,
00098                                               0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
00099 #else
00100   SDL_Surface* convert = SDL_CreateRGBSurface(SDL_SWSURFACE,
00101                                               texture_width, texture_height, 32,
00102                                               0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
00103 #endif
00104 
00105   if(convert == 0) {
00106     throw std::runtime_error("Couldn't create texture: out of memory");
00107   }
00108 
00109   SDL_SetAlpha(image, 0, 0);
00110   SDL_BlitSurface(image, 0, convert, 0);
00111 
00112   assert_gl("before creating texture");
00113   glGenTextures(1, &handle);
00114 
00115   try {
00116     GLenum sdl_format;
00117     if(convert->format->BytesPerPixel == 3)
00118       sdl_format = GL_RGB;
00119     else if(convert->format->BytesPerPixel == 4)
00120       sdl_format = GL_RGBA;
00121     else {
00122       sdl_format = GL_RGBA;
00123       assert(false);
00124     }
00125 
00126     glBindTexture(GL_TEXTURE_2D, handle);
00127     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00128 #ifdef GL_UNPACK_ROW_LENGTH
00129     glPixelStorei(GL_UNPACK_ROW_LENGTH, convert->pitch/convert->format->BytesPerPixel);
00130 #else
00131     /* OpenGL ES doesn't support UNPACK_ROW_LENGTH, let's hope SDL didn't add
00132      * padding bytes, otherwise we need some extra code here... */
00133     assert(convert->pitch == texture_width * convert->format->BytesPerPixel);
00134 #endif
00135 
00136     if(SDL_MUSTLOCK(convert))
00137     {
00138       SDL_LockSurface(convert);
00139     }
00140 
00141     if (true)
00142     { // no not use mipmaps
00143       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_width,
00144                  texture_height, 0, sdl_format,
00145                  GL_UNSIGNED_BYTE, convert->pixels);
00146     }
00147     else
00148     { // build mipmaps
00149       gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, texture_width,
00150                         texture_height, sdl_format,
00151                         GL_UNSIGNED_BYTE, convert->pixels);
00152     }
00153 
00154     if(SDL_MUSTLOCK(convert))
00155     {
00156       SDL_UnlockSurface(convert);
00157     }
00158 
00159     assert_gl("creating texture");
00160 
00161     set_texture_params();
00162   } catch(...) {
00163     glDeleteTextures(1, &handle);
00164     SDL_FreeSurface(convert);
00165     throw;
00166   }
00167   SDL_FreeSurface(convert);
00168 }
00169 
00170 GLTexture::~GLTexture()
00171 {
00172   glDeleteTextures(1, &handle);
00173 }
00174 
00175 void
00176 GLTexture::set_texture_params()
00177 {
00178   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00179   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00180 
00181   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00182   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00183 
00184   assert_gl("set texture params");
00185 }
00186 
00187 /* EOF */

Generated on Mon Jun 9 03:38:24 2014 for SuperTux by  doxygen 1.5.1