62171f9a4dd7cead361b014bf0118c6a28b0ef4f
[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 /*FIXME: The texture isn't drawn to the correct x,y positions.*/
178
179   glBindTexture(GL_TEXTURE_2D, ptexture->gl_texture);
180
181   glEnable(GL_BLEND);
182   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
183
184   glColor4ub(255, 255, 255,255);
185
186   glEnable(GL_TEXTURE_2D);
187
188
189   glBegin(GL_QUADS);
190   glTexCoord2f(sx / (float)power_of_two(ptexture->w), sy / (float)power_of_two(ptexture->h));
191   glVertex2f(sx, sy);
192   glTexCoord2f((float)(sx + w) / (float)power_of_two(ptexture->w), sy / (float)power_of_two(ptexture->h));
193   glVertex2f(w+sx, sy);
194   glTexCoord2f((sx+w) / (float)power_of_two(ptexture->w), (sy+h) / (float)power_of_two(ptexture->h));
195   glVertex2f(w +sx, h+sy);
196   glTexCoord2f(sx / (float)power_of_two(ptexture->w), (float)(sy+h) / (float)power_of_two(ptexture->h));
197   glVertex2f(sx, h+sy);
198   glEnd();
199
200   glDisable(GL_BLEND);
201
202 }
203 #endif
204
205 void texture_load_sdl(texture_type* ptexture, char * file, int use_alpha)
206 {
207   SDL_Surface * temp;
208
209   temp = IMG_Load(file);
210
211   if (temp == NULL)
212     st_abort("Can't load", file);
213
214   ptexture->sdl_surface = SDL_DisplayFormatAlpha(temp);
215
216   if (ptexture->sdl_surface == NULL)
217     st_abort("Can't covert to display format", file);
218
219   if (use_alpha == IGNORE_ALPHA)
220     SDL_SetAlpha(ptexture->sdl_surface, 0, 0);
221
222   SDL_FreeSurface(temp);
223
224   ptexture->w = ptexture->sdl_surface->w;
225   ptexture->h = ptexture->sdl_surface->h;
226
227 }
228
229 void texture_load_part_sdl(texture_type* ptexture, char * file, int x, int y, int w, int h,  int use_alpha)
230 {
231
232   SDL_Rect src;
233   SDL_Surface * temp;
234   SDL_Surface * conv;
235
236   temp = IMG_Load(file);
237
238   if (temp == NULL)
239     st_abort("Can't load", file);
240
241   /* Set source rectangle for conv: */
242
243   src.x = x;
244   src.y = y;
245   src.w = w;
246   src.h = h;
247
248   conv = SDL_CreateRGBSurface(temp->flags, w, h, temp->format->BitsPerPixel,
249                               temp->format->Rmask,
250                               temp->format->Gmask,
251                               temp->format->Bmask,
252                               temp->format->Amask);
253
254   /* #if SDL_BYTEORDER == SDL_BIG_ENDIAN
255                                0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
256   #else
257
258                                0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
259   #endif*/
260
261   SDL_SetAlpha(temp,0,0);
262
263   SDL_BlitSurface(temp, &src, conv, NULL);
264   ptexture->sdl_surface = SDL_DisplayFormatAlpha(conv);
265
266   if (ptexture->sdl_surface == NULL)
267     st_abort("Can't covert to display format", file);
268
269   if (use_alpha == IGNORE_ALPHA)
270     SDL_SetAlpha(ptexture->sdl_surface, 0, 0);
271
272   SDL_FreeSurface(temp);
273   SDL_FreeSurface(conv);
274
275   ptexture->w = ptexture->sdl_surface->w;
276   ptexture->h = ptexture->sdl_surface->h;
277 }
278
279 void texture_from_sdl_surface(texture_type* ptexture, SDL_Surface* sdl_surf, int use_alpha)
280 {
281
282   /* SDL_Surface * temp;
283
284    temp = IMG_Load(file);
285
286    if (temp == NULL)
287      st_abort("Can't load", file);*/
288
289   ptexture->sdl_surface = SDL_DisplayFormatAlpha(sdl_surf);
290
291   if (ptexture->sdl_surface == NULL)
292     st_abort("Can't covert to display format", "SURFACE");
293
294   if (use_alpha == IGNORE_ALPHA)
295     SDL_SetAlpha(ptexture->sdl_surface, 0, 0);
296
297   ptexture->w = ptexture->sdl_surface->w;
298   ptexture->h = ptexture->sdl_surface->h;
299
300 #ifndef NOOPENGL
301
302   if(use_gl)
303     {
304       texture_create_gl(ptexture->sdl_surface,&ptexture->gl_texture);
305     }
306 #endif
307 }
308
309 void texture_draw_sdl(texture_type* ptexture, float x, float y, int update)
310 {
311   SDL_Rect dest;
312
313   dest.x = x;
314   dest.y = y;
315   dest.w = ptexture->w;
316   dest.h = ptexture->h;
317
318   SDL_BlitSurface(ptexture->sdl_surface, NULL, screen, &dest);
319
320   if (update == UPDATE)
321     SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
322 }
323
324
325 void texture_draw_bg_sdl(texture_type* ptexture, int update)
326 {
327   SDL_Rect dest;
328
329   dest.x = 0;
330   dest.y = 0;
331   dest.w = screen->w;
332   dest.h = screen->h;
333
334   SDL_BlitSurface(ptexture->sdl_surface, NULL, screen, &dest);
335
336   if (update == UPDATE)
337     SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
338 }
339
340 void texture_draw_part_sdl(texture_type* ptexture, float sx, float sy, float x, float y, float w, float h, int update)
341 {
342   SDL_Rect src, dest;
343
344   src.x = sx;
345   src.y = sy;
346   src.w = w;
347   src.h = h;
348
349   dest.x = x;
350   dest.y = y;
351   dest.w = w;
352   dest.h = h;
353
354
355   SDL_BlitSurface(ptexture->sdl_surface, &src, screen, &dest);
356
357   if (update == UPDATE)
358     update_rect(screen, dest.x, dest.y, dest.w, dest.h);
359 }
360
361 void texture_free_sdl(texture_type* ptexture)
362 {
363   SDL_FreeSurface(ptexture->sdl_surface);
364 }
365