fixed FIXME
[supertux.git] / src / texture.c
1 //
2 // C Implementation: texture
3 //
4 // Description:
5 //
6 //
7 // Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12
13 #include <SDL/SDL.h>
14 #include <SDL/SDL_image.h>
15 #include "globals.h"
16 #include "screen.h"
17 #include "setup.h"
18 #include "texture.h"
19
20 void texture_setup(void)
21 {
22 #ifdef NOOPENGL
23   texture_load = texture_load_sdl;
24   texture_load_part = texture_load_part_sdl;
25   texture_free = texture_free_sdl;
26   texture_draw = texture_draw_sdl;
27   texture_draw_bg = texture_draw_bg_sdl;
28   texture_draw_part = texture_draw_part_sdl;
29 #else
30
31   if(use_gl)
32     {
33       texture_load = texture_load_gl;
34       texture_load_part = texture_load_part_gl;
35       texture_free = texture_free_gl;
36       texture_draw = texture_draw_gl;
37       texture_draw_bg = texture_draw_bg_gl;
38       texture_draw_part = texture_draw_part_gl;
39     }
40   else
41     {
42       texture_load = texture_load_sdl;
43       texture_load_part = texture_load_part_sdl;
44       texture_free = texture_free_sdl;
45       texture_draw = texture_draw_sdl;
46       texture_draw_bg = texture_draw_bg_sdl;
47       texture_draw_part = texture_draw_part_sdl;
48     }
49 #endif
50 }
51
52 #ifndef NOOPENGL
53 void texture_load_gl(texture_type* ptexture, char * file, int use_alpha)
54 {
55   texture_load_sdl(ptexture,file,use_alpha);
56   texture_create_gl(ptexture->sdl_surface,&ptexture->gl_texture);
57 }
58
59 void texture_load_part_gl(texture_type* ptexture, char * file, int x, int y, int w, int h, int use_alpha)
60 {
61   texture_load_part_sdl(ptexture,file,x,y,w,h,use_alpha);
62   texture_create_gl(ptexture->sdl_surface,&ptexture->gl_texture);
63 }
64
65 /* Quick utility function for texture creation */
66 static int power_of_two(int input)
67 {
68         int value = 1;
69
70         while ( value < input ) {
71                 value <<= 1;
72         }
73         return value;
74 }
75
76 void texture_create_gl(SDL_Surface * surf, GLint * tex)
77 {
78   Uint32 saved_flags;
79   Uint8  saved_alpha;
80   int w, h;
81   SDL_Surface *conv;
82  
83   w = power_of_two(surf->w);
84   h = power_of_two(surf->h),
85   conv = SDL_CreateRGBSurface(surf->flags, w, h, surf->format->BitsPerPixel,
86 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
87                               0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
88 #else
89
90                               0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
91 #endif
92
93   /* Save the alpha blending attributes */
94   saved_flags = surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
95   saved_alpha = surf->format->alpha;
96   if ( (saved_flags & SDL_SRCALPHA)
97        == SDL_SRCALPHA )
98     {
99       SDL_SetAlpha(surf, 0, 0);
100     }
101
102   SDL_BlitSurface(surf, 0, conv, 0);
103
104   /* Restore the alpha blending attributes */
105   if ( (saved_flags & SDL_SRCALPHA)
106        == SDL_SRCALPHA )
107     {
108       SDL_SetAlpha(surf, saved_flags, saved_alpha);
109     }
110
111
112   glGenTextures(1, &*tex);
113
114   glBindTexture(GL_TEXTURE_2D , *tex);
115   glEnable(GL_TEXTURE_2D);
116   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
117   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
118   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
119   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
120   glPixelStorei(GL_UNPACK_ROW_LENGTH, conv->pitch / conv->format->BytesPerPixel);
121   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, conv->pixels);
122   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
123   SDL_FreeSurface(conv);
124 }
125
126 void texture_free_gl(texture_type* ptexture)
127 {
128   SDL_FreeSurface(ptexture->sdl_surface);
129   glDeleteTextures(1, &ptexture->gl_texture);
130 }
131
132 void texture_draw_gl(texture_type* ptexture, float x, float y, int update)
133 {
134
135
136   glEnable(GL_BLEND);
137   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
138
139   glColor4ub(255, 255, 255,255);
140
141   glBindTexture(GL_TEXTURE_2D, ptexture->gl_texture);
142
143   glBegin(GL_QUADS);
144   glTexCoord2f(0, 0);
145   glVertex2f(x, y);
146   glTexCoord2f((float)ptexture->w / (float)power_of_two(ptexture->w), 0);
147   glVertex2f((float)ptexture->w+x, y);
148   glTexCoord2f((float)ptexture->w / (float)power_of_two(ptexture->w), (float)ptexture->h / (float)power_of_two(ptexture->h));  glVertex2f((float)ptexture->w+x, (float)ptexture->h+y);
149   glTexCoord2f(0, (float)ptexture->h / (float)power_of_two(ptexture->h));
150   glVertex2f(x, (float)ptexture->h+y);
151   glEnd();
152
153   glDisable(GL_BLEND);
154 }
155
156 void texture_draw_bg_gl(texture_type* ptexture, int update)
157 {
158   glColor3ub(255, 255, 255);
159
160   glEnable(GL_TEXTURE_2D);
161   glBindTexture(GL_TEXTURE_2D, ptexture->gl_texture);
162
163   glBegin(GL_QUADS);
164   glTexCoord2f(0, 0);
165   glVertex2f(0, 0);
166   glTexCoord2f((float)ptexture->w / (float)power_of_two(ptexture->w), 0);
167   glVertex2f(screen->w, 0);
168   glTexCoord2f((float)ptexture->w / (float)power_of_two(ptexture->w), (float)ptexture->h / power_of_two(ptexture->h));
169   glVertex2f(screen->w, screen->h);
170   glTexCoord2f(0, (float)ptexture->h / (float)power_of_two(ptexture->h));
171   glVertex2f(0, screen->h);
172   glEnd();
173 }
174
175 void texture_draw_part_gl(texture_type* ptexture,float sx, float sy, float x, float y, float w, float h, int update)
176 {
177
178   glBindTexture(GL_TEXTURE_2D, ptexture->gl_texture);
179
180   glEnable(GL_BLEND);
181   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
182
183   glColor4ub(255, 255, 255,255);
184
185   glEnable(GL_TEXTURE_2D);
186
187
188   glBegin(GL_QUADS);
189   glTexCoord2f(sx / (float)power_of_two(ptexture->w), sy / (float)power_of_two(ptexture->h));
190   glVertex2f(x, y);
191   glTexCoord2f((float)(sx + w) / (float)power_of_two(ptexture->w), sy / (float)power_of_two(ptexture->h));
192   glVertex2f(w+x, y);
193   glTexCoord2f((sx+w) / (float)power_of_two(ptexture->w), (sy+h) / (float)power_of_two(ptexture->h));
194   glVertex2f(w +x, h+y);
195   glTexCoord2f(sx / (float)power_of_two(ptexture->w), (float)(sy+h) / (float)power_of_two(ptexture->h));
196   glVertex2f(x, h+y);
197   glEnd();
198
199   glDisable(GL_BLEND);
200
201 }
202 #endif
203
204 void texture_load_sdl(texture_type* ptexture, char * file, int use_alpha)
205 {
206   SDL_Surface * temp;
207
208   temp = IMG_Load(file);
209
210   if (temp == NULL)
211     st_abort("Can't load", file);
212
213   ptexture->sdl_surface = SDL_DisplayFormatAlpha(temp);
214
215   if (ptexture->sdl_surface == NULL)
216     st_abort("Can't covert to display format", file);
217
218   if (use_alpha == IGNORE_ALPHA)
219     SDL_SetAlpha(ptexture->sdl_surface, 0, 0);
220
221   SDL_FreeSurface(temp);
222
223   ptexture->w = ptexture->sdl_surface->w;
224   ptexture->h = ptexture->sdl_surface->h;
225
226 }
227
228 void texture_load_part_sdl(texture_type* ptexture, char * file, int x, int y, int w, int h,  int use_alpha)
229 {
230
231   SDL_Rect src;
232   SDL_Surface * temp;
233   SDL_Surface * conv;
234
235   temp = IMG_Load(file);
236
237   if (temp == NULL)
238     st_abort("Can't load", file);
239
240   /* Set source rectangle for conv: */
241
242   src.x = x;
243   src.y = y;
244   src.w = w;
245   src.h = h;
246
247   conv = SDL_CreateRGBSurface(temp->flags, w, h, temp->format->BitsPerPixel,
248                               temp->format->Rmask,
249                               temp->format->Gmask,
250                               temp->format->Bmask,
251                               temp->format->Amask);
252
253   /* #if SDL_BYTEORDER == SDL_BIG_ENDIAN
254                                0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
255   #else
256
257                                0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
258   #endif*/
259
260   SDL_SetAlpha(temp,0,0);
261
262   SDL_BlitSurface(temp, &src, conv, NULL);
263   ptexture->sdl_surface = SDL_DisplayFormatAlpha(conv);
264
265   if (ptexture->sdl_surface == NULL)
266     st_abort("Can't covert to display format", file);
267
268   if (use_alpha == IGNORE_ALPHA)
269     SDL_SetAlpha(ptexture->sdl_surface, 0, 0);
270
271   SDL_FreeSurface(temp);
272   SDL_FreeSurface(conv);
273
274   ptexture->w = ptexture->sdl_surface->w;
275   ptexture->h = ptexture->sdl_surface->h;
276 }
277
278 void texture_from_sdl_surface(texture_type* ptexture, SDL_Surface* sdl_surf, int use_alpha)
279 {
280
281   /* SDL_Surface * temp;
282
283    temp = IMG_Load(file);
284
285    if (temp == NULL)
286      st_abort("Can't load", file);*/
287
288   ptexture->sdl_surface = SDL_DisplayFormatAlpha(sdl_surf);
289
290   if (ptexture->sdl_surface == NULL)
291     st_abort("Can't covert to display format", "SURFACE");
292
293   if (use_alpha == IGNORE_ALPHA)
294     SDL_SetAlpha(ptexture->sdl_surface, 0, 0);
295
296   ptexture->w = ptexture->sdl_surface->w;
297   ptexture->h = ptexture->sdl_surface->h;
298
299 #ifndef NOOPENGL
300
301   if(use_gl)
302     {
303       texture_create_gl(ptexture->sdl_surface,&ptexture->gl_texture);
304     }
305 #endif
306 }
307
308 void texture_draw_sdl(texture_type* ptexture, float x, float y, int update)
309 {
310   SDL_Rect dest;
311
312   dest.x = x;
313   dest.y = y;
314   dest.w = ptexture->w;
315   dest.h = ptexture->h;
316
317   SDL_BlitSurface(ptexture->sdl_surface, NULL, screen, &dest);
318
319   if (update == UPDATE)
320     SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
321 }
322
323
324 void texture_draw_bg_sdl(texture_type* ptexture, int update)
325 {
326   SDL_Rect dest;
327
328   dest.x = 0;
329   dest.y = 0;
330   dest.w = screen->w;
331   dest.h = screen->h;
332
333   SDL_BlitSurface(ptexture->sdl_surface, NULL, screen, &dest);
334
335   if (update == UPDATE)
336     SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
337 }
338
339 void texture_draw_part_sdl(texture_type* ptexture, float sx, float sy, float x, float y, float w, float h, int update)
340 {
341   SDL_Rect src, dest;
342
343   src.x = sx;
344   src.y = sy;
345   src.w = w;
346   src.h = h;
347
348   dest.x = x;
349   dest.y = y;
350   dest.w = w;
351   dest.h = h;
352
353
354   SDL_BlitSurface(ptexture->sdl_surface, &src, screen, &dest);
355
356   if (update == UPDATE)
357     update_rect(screen, dest.x, dest.y, dest.w, dest.h);
358 }
359
360 void texture_free_sdl(texture_type* ptexture)
361 {
362   SDL_FreeSurface(ptexture->sdl_surface);
363 }
364