00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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 }
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
00132
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 {
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 {
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