a3b093076d96a9b89a8dd96a9f06f2535e5f2ab3
[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 void texture_draw_gl(texture_type* ptexture, float x, float y, int update)
66 {
67
68
69   glEnable(GL_BLEND);
70   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
71
72   glColor4ub(255, 255, 255,255);
73
74   glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexture->gl_texture);
75
76   glBegin(GL_QUADS);
77   glTexCoord2f(0, 0);
78   glVertex2f(x, y);
79   glTexCoord2f((float)ptexture->w, 0);
80   glVertex2f((float)ptexture->w+x, y);
81   glTexCoord2f((float)ptexture->w, (float)ptexture->h);
82   glVertex2f((float)ptexture->w+x, (float)ptexture->h+y);
83   glTexCoord2f(0, (float)ptexture->h);
84   glVertex2f(x, (float)ptexture->h+y);
85   glEnd();
86
87   glDisable(GL_BLEND);
88 }
89
90 void texture_draw_bg_gl(texture_type* ptexture, int update)
91 {
92   glColor3ub(255, 255, 255);
93
94   glEnable(GL_TEXTURE_RECTANGLE_NV);
95   glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexture->gl_texture);
96
97   glBegin(GL_QUADS);
98   glTexCoord2f(0, 0);
99   glVertex2f(0, 0);
100   glTexCoord2f((float)ptexture->w, 0);
101   glVertex2f(screen->w, 0);
102   glTexCoord2f((float)ptexture->w, (float)ptexture->h);
103   glVertex2f(screen->w, screen->h);
104   glTexCoord2f(0, (float)ptexture->h);
105   glVertex2f(0, screen->h);
106   glEnd();
107 }
108
109 void texture_draw_part_gl(texture_type* ptexture,float sx, float sy, float x, float y, float w, float h, int update)
110 {
111
112   glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexture->gl_texture);
113
114   glEnable(GL_BLEND);
115   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
116
117   glColor4ub(255, 255, 255,255);
118
119   glEnable(GL_TEXTURE_RECTANGLE_NV);
120
121
122   glBegin(GL_QUADS);
123   glTexCoord2f(x, y);
124   glVertex2f(x, y);
125   glTexCoord2f(x+w, y);
126   glVertex2f(w+x, y);
127   glTexCoord2f(x+w, y+h);
128   glVertex2f(w+x, h+y);
129   glTexCoord2f(x, y+h);
130   glVertex2f(x, h+y);
131   glEnd();
132
133   glDisable(GL_BLEND);
134
135 }
136
137 void texture_create_gl(SDL_Surface * surf, GLint * tex)
138 {
139   Uint32 saved_flags;
140   Uint8  saved_alpha;
141
142   SDL_Surface *conv;
143   conv = SDL_CreateRGBSurface(surf->flags, surf->w, surf->h, surf->format->BitsPerPixel,
144 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
145                               0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
146 #else
147
148                               0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
149 #endif
150
151   /* Save the alpha blending attributes */
152   saved_flags = surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
153   saved_alpha = surf->format->alpha;
154   if ( (saved_flags & SDL_SRCALPHA)
155        == SDL_SRCALPHA )
156     {
157       SDL_SetAlpha(surf, 0, 0);
158     }
159
160   SDL_BlitSurface(surf, 0, conv, 0);
161
162   /* Restore the alpha blending attributes */
163   if ( (saved_flags & SDL_SRCALPHA)
164        == SDL_SRCALPHA )
165     {
166       SDL_SetAlpha(surf, saved_flags, saved_alpha);
167     }
168
169
170   glGenTextures(1, &*tex);
171
172   glBindTexture(GL_TEXTURE_RECTANGLE_NV , *tex);
173   glEnable(GL_TEXTURE_RECTANGLE_NV);
174   glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
175   glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
176   glPixelStorei(GL_UNPACK_ROW_LENGTH, conv->pitch / conv->format->BytesPerPixel);
177   glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB10_A2, conv->w, conv->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, conv->pixels);
178   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
179   SDL_FreeSurface(conv);
180 }
181
182 void texture_free_gl(texture_type* ptexture)
183 {
184   SDL_FreeSurface(ptexture->sdl_surface);
185   glDeleteTextures(1, &ptexture->gl_texture);
186 }
187 #endif
188
189 void texture_load_sdl(texture_type* ptexture, char * file, int use_alpha)
190 {
191   SDL_Surface * temp;
192
193   temp = IMG_Load(file);
194
195   if (temp == NULL)
196     st_abort("Can't load", file);
197
198   ptexture->sdl_surface = SDL_DisplayFormatAlpha(temp);
199
200   if (ptexture->sdl_surface == NULL)
201     st_abort("Can't covert to display format", file);
202
203   if (use_alpha == IGNORE_ALPHA)
204     SDL_SetAlpha(ptexture->sdl_surface, 0, 0);
205
206   SDL_FreeSurface(temp);
207
208   ptexture->w = ptexture->sdl_surface->w;
209   ptexture->h = ptexture->sdl_surface->h;
210
211 }
212
213 void texture_load_part_sdl(texture_type* ptexture, char * file, int x, int y, int w, int h,  int use_alpha)
214 {
215
216   SDL_Rect src;
217   SDL_Surface * temp;
218   SDL_Surface * conv;
219
220   temp = IMG_Load(file);
221
222   if (temp == NULL)
223     st_abort("Can't load", file);
224
225   /* Set source rectangle for conv: */
226
227   src.x = x;
228   src.y = y;
229   src.w = w;
230   src.h = h;
231
232   conv = SDL_CreateRGBSurface(temp->flags, w, h, temp->format->BitsPerPixel,
233                               temp->format->Rmask,
234                               temp->format->Gmask,
235                               temp->format->Bmask,
236                               temp->format->Amask);
237
238   /* #if SDL_BYTEORDER == SDL_BIG_ENDIAN
239                                0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
240   #else
241
242                                0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
243   #endif*/
244
245   SDL_SetAlpha(temp,0,0);
246
247   SDL_BlitSurface(temp, &src, conv, NULL);
248   ptexture->sdl_surface = SDL_DisplayFormatAlpha(conv);
249
250   if (ptexture->sdl_surface == NULL)
251     st_abort("Can't covert to display format", file);
252
253   if (use_alpha == IGNORE_ALPHA)
254     SDL_SetAlpha(ptexture->sdl_surface, 0, 0);
255
256   SDL_FreeSurface(temp);
257   SDL_FreeSurface(conv);
258
259   ptexture->w = ptexture->sdl_surface->w;
260   ptexture->h = ptexture->sdl_surface->h;
261 }
262
263 void texture_from_sdl_surface(texture_type* ptexture, SDL_Surface* sdl_surf, int use_alpha)
264 {
265
266   /* SDL_Surface * temp;
267
268    temp = IMG_Load(file);
269
270    if (temp == NULL)
271      st_abort("Can't load", file);*/
272
273   ptexture->sdl_surface = SDL_DisplayFormatAlpha(sdl_surf);
274
275   if (ptexture->sdl_surface == NULL)
276     st_abort("Can't covert to display format", "SURFACE");
277
278   if (use_alpha == IGNORE_ALPHA)
279     SDL_SetAlpha(ptexture->sdl_surface, 0, 0);
280
281   ptexture->w = ptexture->sdl_surface->w;
282   ptexture->h = ptexture->sdl_surface->h;
283
284 #ifndef NOOPENGL
285
286   if(use_gl)
287     {
288       texture_create_gl(ptexture->sdl_surface,&ptexture->gl_texture);
289     }
290 #endif
291 }
292
293 void texture_draw_sdl(texture_type* ptexture, float x, float y, int update)
294 {
295   SDL_Rect dest;
296
297   dest.x = x;
298   dest.y = y;
299   dest.w = ptexture->w;
300   dest.h = ptexture->h;
301
302   SDL_BlitSurface(ptexture->sdl_surface, NULL, screen, &dest);
303
304   if (update == UPDATE)
305     SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
306 }
307
308
309 void texture_draw_bg_sdl(texture_type* ptexture, int update)
310 {
311   SDL_Rect dest;
312
313   dest.x = 0;
314   dest.y = 0;
315   dest.w = screen->w;
316   dest.h = screen->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 void texture_draw_part_sdl(texture_type* ptexture, float sx, float sy, float x, float y, float w, float h, int update)
325 {
326   SDL_Rect src, dest;
327
328   src.x = sx;
329   src.y = sy;
330   src.w = w;
331   src.h = h;
332
333   dest.x = x;
334   dest.y = y;
335   dest.w = w;
336   dest.h = h;
337
338
339   SDL_BlitSurface(ptexture->sdl_surface, &src, screen, &dest);
340
341   if (update == UPDATE)
342     update_rect(screen, dest.x, dest.y, dest.w, dest.h);
343 }
344
345 void texture_free_sdl(texture_type* ptexture)
346 {
347   SDL_FreeSurface(ptexture->sdl_surface);
348 }
349