2 // C Implementation: texture
7 // Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
9 // Copyright: See COPYING file that comes with this distribution
14 #include "SDL_image.h"
19 /* Quick utility function for texture creation */
20 static int power_of_two(int input)
24 while ( value < input ) {
30 Surface::Surface(SDL_Surface* surf, int use_alpha)
33 impl = new SurfaceOpenGL(surf, use_alpha);
35 impl = new SurfaceSDL(surf, use_alpha);
41 Surface::Surface(const std::string& file, int use_alpha)
44 impl = new SurfaceOpenGL(file, use_alpha);
46 impl = new SurfaceSDL(file, use_alpha);
52 Surface::Surface(const std::string& file, int x, int y, int w, int h, int use_alpha)
55 impl = new SurfaceOpenGL(file, x, y, w, h, use_alpha);
57 impl = new SurfaceSDL(file, x, y, w, h, use_alpha);
69 Surface::draw(float x, float y, Uint8 alpha, bool update)
71 if (impl) impl->draw(x, y, alpha, update);
75 Surface::draw_bg(Uint8 alpha, bool update)
77 if (impl) impl->draw_bg(alpha, update);
81 Surface::draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, bool update)
83 if (impl) impl->draw_part(sx, sy, x, y, w, h, alpha, update);
87 sdl_surface_part_from_file(const std::string& file, int x, int y, int w, int h, int use_alpha)
90 SDL_Surface * sdl_surface;
94 temp = IMG_Load(file.c_str());
97 st_abort("Can't load", file);
99 /* Set source rectangle for conv: */
106 conv = SDL_CreateRGBSurface(temp->flags, w, h, temp->format->BitsPerPixel,
110 temp->format->Amask);
112 /* #if SDL_BYTEORDER == SDL_BIG_ENDIAN
113 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
116 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
119 SDL_SetAlpha(temp,0,0);
121 SDL_BlitSurface(temp, &src, conv, NULL);
122 if(use_alpha == IGNORE_ALPHA && !use_gl)
123 sdl_surface = SDL_DisplayFormat(conv);
125 sdl_surface = SDL_DisplayFormatAlpha(conv);
127 if (sdl_surface == NULL)
128 st_abort("Can't covert to display format", file);
130 if (use_alpha == IGNORE_ALPHA && !use_gl)
131 SDL_SetAlpha(sdl_surface, 0, 0);
133 SDL_FreeSurface(temp);
134 SDL_FreeSurface(conv);
140 sdl_surface_from_file(const std::string& file, int use_alpha)
142 SDL_Surface* sdl_surface;
145 temp = IMG_Load(file.c_str());
148 st_abort("Can't load", file);
150 if(use_alpha == IGNORE_ALPHA && !use_gl)
151 sdl_surface = SDL_DisplayFormat(temp);
153 sdl_surface = SDL_DisplayFormatAlpha(temp);
155 if (sdl_surface == NULL)
156 st_abort("Can't covert to display format", file);
158 if (use_alpha == IGNORE_ALPHA && !use_gl)
159 SDL_SetAlpha(sdl_surface, 0, 0);
161 SDL_FreeSurface(temp);
167 sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf, int use_alpha)
169 SDL_Surface* sdl_surface;
173 /* Save the alpha blending attributes */
174 saved_flags = sdl_surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
175 saved_alpha = sdl_surf->format->alpha;
176 if ( (saved_flags & SDL_SRCALPHA)
179 SDL_SetAlpha(sdl_surf, 0, 0);
182 if(use_alpha == IGNORE_ALPHA && !use_gl)
183 sdl_surface = SDL_DisplayFormat(sdl_surf);
185 sdl_surface = SDL_DisplayFormatAlpha(sdl_surf);
187 /* Restore the alpha blending attributes */
188 if ( (saved_flags & SDL_SRCALPHA)
191 SDL_SetAlpha(sdl_surface, saved_flags, saved_alpha);
194 if (sdl_surface == NULL)
195 st_abort("Can't covert to display format", "SURFACE");
197 if (use_alpha == IGNORE_ALPHA && !use_gl)
198 SDL_SetAlpha(sdl_surface, 0, 0);
204 SurfaceOpenGL::SurfaceOpenGL(SDL_Surface* surf, int use_alpha)
206 sdl_surface = sdl_surface_from_sdl_surface(surf, use_alpha);
207 create_gl(sdl_surface,&gl_texture);
213 SurfaceOpenGL::SurfaceOpenGL(const std::string& file, int use_alpha)
215 sdl_surface = sdl_surface_from_file(file, use_alpha);
216 create_gl(sdl_surface,&gl_texture);
222 SurfaceOpenGL::SurfaceOpenGL(const std::string& file, int x, int y, int w, int h, int use_alpha)
224 sdl_surface = sdl_surface_part_from_file(file,x,y,w,h,use_alpha);
225 create_gl(sdl_surface, &gl_texture);
231 SurfaceOpenGL::~SurfaceOpenGL()
233 SDL_FreeSurface(sdl_surface);
234 glDeleteTextures(1, &gl_texture);
238 SurfaceOpenGL::create_gl(SDL_Surface * surf, GLuint * tex)
245 w = power_of_two(surf->w);
246 h = power_of_two(surf->h),
248 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
249 conv = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surf->format->BitsPerPixel,
250 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
252 conv = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surf->format->BitsPerPixel,
253 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
256 /* Save the alpha blending attributes */
257 saved_flags = surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
258 saved_alpha = surf->format->alpha;
259 if ( (saved_flags & SDL_SRCALPHA)
262 SDL_SetAlpha(surf, 0, 0);
265 SDL_BlitSurface(surf, 0, conv, 0);
267 /* Restore the alpha blending attributes */
268 if ( (saved_flags & SDL_SRCALPHA)
271 SDL_SetAlpha(surf, saved_flags, saved_alpha);
274 glGenTextures(1, &*tex);
275 glBindTexture(GL_TEXTURE_2D , *tex);
276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
277 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
278 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
280 glPixelStorei(GL_UNPACK_ROW_LENGTH, conv->pitch / conv->format->BytesPerPixel);
281 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, conv->pixels);
282 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
284 SDL_FreeSurface(conv);
288 SurfaceOpenGL::draw(float x, float y, Uint8 alpha, bool update)
290 float pw = power_of_two(w);
291 float ph = power_of_two(h);
293 glEnable(GL_TEXTURE_2D);
295 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
297 glColor4ub(alpha, alpha, alpha, alpha);
299 glBindTexture(GL_TEXTURE_2D, gl_texture);
304 glTexCoord2f((float)w / pw, 0);
305 glVertex2f((float)w+x, y);
306 glTexCoord2f((float)w / pw, (float)h / ph); glVertex2f((float)w+x, (float)h+y);
307 glTexCoord2f(0, (float)h / ph);
308 glVertex2f(x, (float)h+y);
311 glDisable(GL_TEXTURE_2D);
314 /* Avoid compiler warnings */
320 SurfaceOpenGL::draw_bg(Uint8 alpha, bool update)
322 float pw = power_of_two(w);
323 float ph = power_of_two(h);
325 glColor3ub(alpha, alpha, alpha);
327 glEnable(GL_TEXTURE_2D);
328 glBindTexture(GL_TEXTURE_2D, gl_texture);
333 glTexCoord2f((float)w / pw, 0);
334 glVertex2f(screen->w, 0);
335 glTexCoord2f((float)w / pw, (float)h / ph);
336 glVertex2f(screen->w, screen->h);
337 glTexCoord2f(0, (float)h / ph);
338 glVertex2f(0, screen->h);
341 glDisable(GL_TEXTURE_2D);
343 /* Avoid compiler warnings */
349 SurfaceOpenGL::draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, bool update)
351 float pw = power_of_two(int(this->w));
352 float ph = power_of_two(int(this->h));
354 glBindTexture(GL_TEXTURE_2D, gl_texture);
357 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
359 glColor4ub(alpha, alpha, alpha, alpha);
361 glEnable(GL_TEXTURE_2D);
365 glTexCoord2f(sx / pw, sy / ph);
367 glTexCoord2f((float)(sx + w) / pw, sy / ph);
369 glTexCoord2f((sx+w) / pw, (sy+h) / ph);
370 glVertex2f(w +x, h+y);
371 glTexCoord2f(sx / pw, (float)(sy+h) / ph);
375 glDisable(GL_TEXTURE_2D);
378 /* Avoid compiler warnings */
384 SurfaceSDL::SurfaceSDL(SDL_Surface* surf, int use_alpha)
386 sdl_surface = sdl_surface_from_sdl_surface(surf, use_alpha);
391 SurfaceSDL::SurfaceSDL(const std::string& file, int use_alpha)
393 sdl_surface = sdl_surface_from_file(file, use_alpha);
398 SurfaceSDL::SurfaceSDL(const std::string& file, int x, int y, int w, int h, int use_alpha)
400 sdl_surface = sdl_surface_part_from_file(file, x, y, w, h, use_alpha);
406 SurfaceSDL::draw(float x, float y, Uint8 alpha, bool update)
415 if(alpha != 255) /* SDL isn't capable of this kind of alpha :( therefore we'll leave now. */
418 SDL_SetAlpha(sdl_surface ,SDL_SRCALPHA,alpha);
419 SDL_BlitSurface(sdl_surface, NULL, screen, &dest);
421 if (update == UPDATE)
422 SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
426 SurfaceSDL::draw_bg(Uint8 alpha, bool update)
436 SDL_SetAlpha(sdl_surface ,SDL_SRCALPHA,alpha);
437 SDL_SoftStretch(sdl_surface, NULL, screen, &dest);
439 if (update == UPDATE)
440 SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
444 SurfaceSDL::draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, bool update)
459 SDL_SetAlpha(sdl_surface ,SDL_SRCALPHA,alpha);
461 SDL_BlitSurface(sdl_surface, &src, screen, &dest);
463 if (update == UPDATE)
464 update_rect(screen, dest.x, dest.y, dest.w, dest.h);
467 SurfaceSDL::~SurfaceSDL()
469 SDL_FreeSurface(sdl_surface);