1 /************************************************************************
2 This file is part of NE.
4 NE is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 NE is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with NE. If not, see <http://www.gnu.org/licenses/>.
16 ************************************************************************/
26 #include <SDL/SDL_image.h>
28 /* Undefine the following if you're targeting
29 * hardware that supports non-power-of-2 textures.
30 * You'll save some video memory...
34 #define FAIL_ON_GLMEM \
36 if (glGetError() == GL_OUT_OF_MEMORY) { \
37 fprintf(stderr, "Out of memory!"); \
48 //glMatrixMode(GL_TEXTURE);
53 struct texture
*t_create()
55 struct texture
*t
= (struct texture
*)malloc(sizeof(struct texture
));
63 void t_destroy(struct texture
*t
)
69 int t_ready(struct texture
*t
)
74 static int nearest_pow2(int s
)
83 static SDL_Surface
*flip_fit_surf(SDL_Surface
*surf
)
89 int w
= nearest_pow2(surf
->w
);
90 int h
= nearest_pow2(surf
->h
);
94 if (w
!= surf
->w
|| h
!= surf
->h
) {
95 printf("DEBUG: resizing surface from %dx%d to %dx%d for GL\n",
96 surf
->w
, surf
->h
, w
, h
);
100 SDL_Surface
*n
= SDL_CreateRGBSurface(SDL_SWSURFACE
, w
, h
, 32,
101 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
116 Uint32 flags
= surf
->flags
&(SDL_SRCALPHA
|SDL_RLEACCELOK
);
117 Uint8 alpha
= surf
->format
->alpha
;
119 // turn off alpha for the blit
120 if (flags
&SDL_SRCALPHA
)
121 SDL_SetAlpha(surf
, 0, 0);
126 dest
.y
= h
- surf
->h
; // copy to the bottom of the pow2 texture
129 SDL_BlitSurface(surf
, &src
, n
, &dest
);
131 // turn alpha back on if we turned it off
132 if (flags
&SDL_SRCALPHA
)
133 SDL_SetAlpha(surf
, flags
, alpha
);
135 // now, flip the image
136 Uint8
*line
= malloc(n
->pitch
* sizeof(Uint8
));
138 Uint8
*pix
= (Uint8
*)n
->pixels
;
139 Uint16 pitch
= n
->pitch
;
143 for (i
=0; i
< n
->h
/2; i
++) {
144 int end
= n
->h
- i
- 1;
145 memcpy(line
, pix
+ pitch
*i
, pitch
); // save
146 memcpy(pix
+ pitch
*i
, pix
+ pitch
*end
, pitch
); // low to high
147 memcpy(pix
+ pitch
*end
, line
, pitch
); // saved to low
149 SDL_UnlockSurface(n
);
156 void t_load(struct texture
*t
, const char *filename
)
161 SDL_Surface
*img
= IMG_Load(filename
);
164 fprintf(stderr
, "Texture load error: %s\n", IMG_GetError());
168 if (img
->format
->BytesPerPixel
< 2) {
169 fprintf(stderr
, "Texture load error: %s is not true color\n", filename
);
173 SDL_Surface
*tmp
= flip_fit_surf(img
);
175 glGenTextures(1, &t
->gl_handle
);
176 glBindTexture(GL_TEXTURE_2D
, t
->gl_handle
);
181 t
->u
= (float)img
->w
/ tmp
->w
;
182 t
->v
= (float)img
->h
/ tmp
->h
;
184 SDL_FreeSurface(img
);
187 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
188 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
190 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
191 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
193 GLuint mode
= GL_RGB
;
194 if (img
->format
->BytesPerPixel
== 4) mode
= GL_RGBA
;
199 glTexImage2D(GL_TEXTURE_2D
, 0, img
->format
->BytesPerPixel
,
200 img
->w
, img
->h
, 0, mode
, GL_UNSIGNED_BYTE
, img
->pixels
);
203 glTexParameterf( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR_MIPMAP_LINEAR
);
204 gluBuild2DMipmaps(GL_TEXTURE_2D
, img
->format
->BytesPerPixel
, img
->w
, img
->h
,
205 mode
, GL_UNSIGNED_BYTE
, img
->pixels
);
208 SDL_FreeSurface(img
);
215 void t_unload(struct texture
*t
)
218 glDeleteTextures(1, &t
->gl_handle
);
222 void t_apply(struct texture
*t
)
225 glGetIntegerv(GL_MATRIX_MODE
, &lastmode
);
226 glMatrixMode(GL_TEXTURE
);
228 glScalef(t
->u
, t
->v
, 1.0);
229 glBindTexture(GL_TEXTURE_2D
, t
->gl_handle
);
230 glMatrixMode(lastmode
);
236 glGetIntegerv(GL_MATRIX_MODE
, &lastmode
);
237 glMatrixMode(GL_TEXTURE
);
239 glBindTexture(GL_TEXTURE_2D
, 0);
240 glMatrixMode(lastmode
);
243 void t_set(struct texture
*t
, GLuint name
, GLuint value
)
246 glTexParameteri(GL_TEXTURE_2D
,name
,value
);
249 struct texture
*t_screenshot()
251 struct texture
*t
= t_create();
253 glGenTextures(1, &t
->gl_handle
);
254 glBindTexture(GL_TEXTURE_2D
, t
->gl_handle
);
256 const struct video_info
* vi
= v_info();
262 int w
= nearest_pow2(vi
->width
);
263 int h
= nearest_pow2(vi
->height
);
266 t
->width
= vi
->width
;
267 t
->height
= vi
->height
;
270 if (w
!= vi
->width
|| h
!= vi
->height
) {
271 printf("DEBUG: resizing surface from %dx%d to %dx%d for GL\n",
272 vi
->width
, vi
->height
, w
, h
);
276 t
->u
= (float)t
->width
/ w
;
277 t
->v
= (float)t
->height
/ h
;
279 glCopyTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 0, 0, w
, h
, 0);
281 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
282 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
284 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
285 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);