12 static list_t
*listStorage
;
14 static bool_t isImageDataInit
= FALSE
;
16 bool_t
image_is_inicialized()
18 return isImageDataInit
;
22 * Initialization of global list of images
26 assert(interface_is_inicialized() == TRUE
);
28 debug("Initializing image database");
30 listStorage
= storage_new();
31 isImageDataInit
= TRUE
;
34 static SDL_Surface
*loadImage(const char *filename
, int alpha
)
39 char str
[STR_PATH_SIZE
];
41 if (isFillPath(filename
)) {
42 strcpy(str
, filename
);
44 sprintf(str
, PATH_IMAGE
"%s", filename
);
49 if ((tmp
= IMG_Load(str
)) == NULL
) {
50 error("SDL: %s", SDL_GetError());
54 if ((ret
= (alpha
) ? SDL_DisplayFormatAlpha(tmp
) : SDL_DisplayFormat(tmp
)) == NULL
) {
55 error("SDL: %s", SDL_GetError());
65 image_t
*image_new_sdl(SDL_Surface
*surface
)
69 assert(surface
!= NULL
);
71 new = malloc(sizeof(image_t
));
81 * returns closest bigger power of 2 to i
83 unsigned int closestpoweroftwo(unsigned int i
)
94 /* convert from SDL_Surface to image_t
95 * WARNING: image_new is indestructive to surface, caller is responsible for freeing surface
96 * surface is not needed for image_t after execution of image_new
99 image_t
*image_new_opengl(SDL_Surface
*surface
)
102 Uint32 rmask
, gmask
, bmask
, amask
;
103 SDL_Surface
*sdl_rgba_surface
;
106 /* it is unoptimal to blit to buffer surface before actual loading to opengl texture but it is safer and simpler to implement */
107 /* it is unoptimal to always use RGBA texture */
109 /* we set properties of our buffer sdl_rgba_surface */
114 bpp
= 32; /* bits per pixel */
116 assert(surface
!= NULL
);
118 new = malloc(sizeof(image_t
));
122 /* because some older hw is really slow when using textures with width and height which is not a power of two */
123 new->tw
= closestpoweroftwo(new->w
);
124 new->th
= closestpoweroftwo(new->h
);
126 sdl_rgba_surface
= SDL_CreateRGBSurface(SDL_SWSURFACE
, new->tw
, new->th
, bpp
, rmask
, gmask
, bmask
, amask
);
128 SDL_SetAlpha(surface
, 0, SDL_ALPHA_OPAQUE
); /* we unset SDL_SRCALPHA to preserve alpha channel of original image */
129 SDL_BlitSurface(surface
, 0, sdl_rgba_surface
, 0);
131 SDL_LockSurface(sdl_rgba_surface
); /* we ensure that we can read pixels from sdl_rgba_surface */
134 glGenTextures(1, &tid
); /* we ask for free texture id */
135 glBindTexture(GL_TEXTURE_2D
, tid
);
136 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
); /* scale linearly when image bigger than texture */
137 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
); /* scale linearly when image smalled than texture */
138 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, new->tw
, new->th
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, sdl_rgba_surface
->pixels
);
139 SDL_UnlockSurface(sdl_rgba_surface
);
140 SDL_FreeSurface(sdl_rgba_surface
);
144 SDL_FreeSurface(surface
);
148 #endif /* SUPPORT_OPENGL */
150 image_t
*image_new(SDL_Surface
*surface
)
152 #ifdef SUPPORT_OPENGL
153 if (interface_is_use_open_gl()) {
154 return image_new_opengl(surface
);
156 return image_new_sdl(surface
);
158 #else /* SUPPORT_OPENGL */
159 return image_new_sdl(surface
);
160 #endif /* SUPPORT_OPENGL */
163 void image_destroy(image_t
*p
)
167 #ifndef SUPPORT_OPENGL
168 SDL_FreeSurface((SDL_Surface
*) p
->image
);
169 #else /* SUPPORT_OPENGL */
170 if (interface_is_use_open_gl()) {
171 glDeleteTextures(1, &p
->tex_id
);
173 SDL_FreeSurface((SDL_Surface
*) p
->image
);
175 #endif /* SUPPORT_OPENGL */
181 * Adds an image to the global image list
182 * *file - name of the image file
183 * *name - name of the image (is used for searching in the list)
184 * alpha - [0] without alpha channel; [1] with alpha channel
186 image_t
*image_add(char *file
, int alpha
, char *name
, char *group
)
188 SDL_Surface
*surface
;
191 assert(file
!= NULL
);
192 assert(name
!= NULL
);
193 assert(group
!= NULL
);
195 surface
= loadImage(file
, alpha
);
196 new = image_new(surface
);
198 storage_add(listStorage
, group
, name
, new);
200 debug("Loading image [%s]", file
);
206 * Returns pointer to image with name *name in the global image list
208 image_t
*image_get(char *group
, char *name
)
210 assert(group
!= NULL
);
211 assert(name
!= NULL
);
213 return storage_get(listStorage
, group
, name
);
216 void image_del(char *group
, char *name
)
218 assert(group
!= NULL
);
219 assert(name
!= NULL
);
221 storage_del(listStorage
, group
, name
, image_destroy
);
224 void image_del_all_image_in_group(char *group
)
226 assert(group
!= NULL
);
228 storage_del_all(listStorage
, group
, image_destroy
);
231 void image_draw_sdl(image_t
*p
, int x
, int y
, int px
, int py
, int w
, int h
)
233 static SDL_Surface
*screen
= NULL
;
234 SDL_Rect dst_rect
, src_rect
;
236 if (screen
== NULL
) {
237 screen
= interface_get_screen();
248 SDL_BlitSurface(p
->image
, &src_rect
, screen
, &dst_rect
);
251 #ifdef SUPPORT_OPENGL
253 * Draws image on screen at [x,y], with width w and height h, top-left corner on image is at [px,py]
255 void image_draw_opengl(image_t
*image
, int x
,int y
, int px
, int py
, int w
, int h
)
257 /* x - coordinate of left border; xx - coordinate of right border
258 * y - coordinate of top border; yy - coordinate of bottom border
259 * t - texture space; d - screen space
261 float t_x
, t_y
, t_xx
, t_yy
;
262 float d_x
, d_y
, d_xx
, d_yy
;
270 /* texture space (remember that texture space is from 0.0 to 1.0) */
271 t_x
= px
/ (float) image
->tw
;
272 t_y
= py
/ (float) image
->th
;
273 t_xx
= (px
+w
) / (float) image
->tw
;
274 t_yy
= (py
+h
) / (float) image
->th
;
276 glBindTexture(GL_TEXTURE_2D
, image
->tex_id
);
284 glBegin(GL_TRIANGLE_STRIP
);
286 glTexCoord2f(t_x
,t_yy
);
287 glVertex2f(d_x
, d_yy
);
289 glTexCoord2f(t_x
, t_y
);
290 glVertex2f(d_x
, d_y
);
292 glTexCoord2f(t_xx
, t_yy
);
293 glVertex2f(d_xx
, d_yy
);
295 glTexCoord2f(t_xx
,t_y
);
296 glVertex2f(d_xx
, d_y
);
299 #endif /* SUPPORT_OPENGL */
301 void image_draw(image_t
*image
, int x
,int y
, int px
, int py
, int w
, int h
)
303 #ifdef SUPPORT_OPENGL
304 if (interface_is_use_open_gl()) {
305 image_draw_opengl(image
, x
, y
, px
, py
, w
, h
);
307 image_draw_sdl(image
, x
, y
, px
, py
, w
, h
);
309 #else /* SUPPORT_OPENGL */
310 image_draw_sdl(image
, x
, y
, px
, py
, w
, h
);
311 #endif /* SUPPORT_OPENGL */
315 * Frees global image list
319 debug("Shutting down image database");
321 storage_destroy(listStorage
, image_destroy
);
322 isImageDataInit
= FALSE
;