textures, overlay images, libimago
[demo_prior] / libs / imago2 / src / imago_gl.c
1 #include "imago2.h"
2
3 /* to avoid dependency to OpenGL, I'll define all the relevant GL macros manually */
4 #define GL_UNSIGNED_BYTE                0x1401
5 #define GL_FLOAT                                0x1406
6
7 #define GL_LUMINANCE                    0x1909
8 #define GL_RGB                                  0x1907
9 #define GL_RGBA                                 0x1908
10
11 #define GL_RGBA32F                              0x8814
12 #define GL_RGB32F                               0x8815
13 #define GL_LUMINANCE32F                 0x8818
14
15 #define GL_TEXTURE_2D                   0x0de1
16 #define GL_TEXTURE_WRAP_S               0x2802
17 #define GL_TEXTURE_WRAP_T               0x2803
18 #define GL_TEXTURE_MAG_FILTER   0x2800
19 #define GL_TEXTURE_MIN_FILTER   0x2801
20 #define GL_LINEAR                               0x2601
21 #define GL_LINEAR_MIPMAP_LINEAR 0x2703
22 #define GL_REPEAT                               0x2901
23 #define GL_GENERATE_MIPMAP_SGIS 0x8191
24
25
26 typedef unsigned int GLenum;
27 typedef unsigned int GLuint;
28 typedef int GLint;
29 typedef int GLsizei;
30 typedef void GLvoid;
31
32 /* for the same reason I'll load GL functions dynamically */
33 #ifndef WIN32
34 typedef void (*gl_gen_textures_func)(GLsizei, GLuint*);
35 typedef void (*gl_bind_texture_func)(GLenum, GLuint);
36 typedef void (*gl_tex_parameteri_func)(GLenum, GLenum, GLint);
37 typedef void (*gl_tex_image2d_func)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*);
38 typedef void (*gl_generate_mipmap_func)(GLenum);
39 typedef GLenum (*gl_get_error_func)(void);
40 #else
41 typedef void (__stdcall *gl_gen_textures_func)(GLsizei, GLuint*);
42 typedef void (__stdcall *gl_bind_texture_func)(GLenum, GLuint);
43 typedef void (__stdcall *gl_tex_parameteri_func)(GLenum, GLenum, GLint);
44 typedef void (__stdcall *gl_tex_image2d_func)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*);
45 typedef void (__stdcall *gl_generate_mipmap_func)(GLenum);
46 typedef GLenum (__stdcall *gl_get_error_func)(void);
47 #endif
48
49 static gl_gen_textures_func gl_gen_textures;
50 static gl_bind_texture_func gl_bind_texture;
51 static gl_tex_parameteri_func gl_tex_parameteri;
52 static gl_tex_image2d_func gl_tex_image2d;
53 static gl_generate_mipmap_func gl_generate_mipmap;
54 static gl_get_error_func gl_get_error;
55
56 static int load_glfunc(void);
57
58 unsigned int img_fmt_glfmt(enum img_fmt fmt)
59 {
60         switch(fmt) {
61         case IMG_FMT_GREY8:
62         case IMG_FMT_GREYF:
63                 return GL_LUMINANCE;
64
65         case IMG_FMT_RGB24:
66         case IMG_FMT_RGBF:
67                 return GL_RGB;
68
69         case IMG_FMT_RGBA32:
70         case IMG_FMT_RGBAF:
71                 return GL_RGBA;
72
73         default:
74                 break;
75         }
76         return 0;
77 }
78
79 unsigned int img_fmt_gltype(enum img_fmt fmt)
80 {
81         switch(fmt) {
82         case IMG_FMT_GREY8:
83         case IMG_FMT_RGB24:
84         case IMG_FMT_RGBA32:
85                 return GL_UNSIGNED_BYTE;
86
87         case IMG_FMT_GREYF:
88         case IMG_FMT_RGBF:
89         case IMG_FMT_RGBAF:
90                 return GL_FLOAT;
91
92         default:
93                 break;
94         }
95         return 0;
96 }
97
98 unsigned int img_fmt_glintfmt(enum img_fmt fmt)
99 {
100         switch(fmt) {
101         case IMG_FMT_GREY8:
102                 return GL_LUMINANCE;
103         case IMG_FMT_RGB24:
104                 return GL_RGB;
105         case IMG_FMT_RGBA32:
106                 return GL_RGBA;
107         case IMG_FMT_GREYF:
108                 return GL_LUMINANCE32F;
109         case IMG_FMT_RGBF:
110                 return GL_RGB32F;
111         case IMG_FMT_RGBAF:
112                 return GL_RGBA32F;
113         default:
114                 break;
115         }
116         return 0;
117 }
118
119 unsigned int img_glfmt(struct img_pixmap *img)
120 {
121         return img_fmt_glfmt(img->fmt);
122 }
123
124 unsigned int img_gltype(struct img_pixmap *img)
125 {
126         return img_fmt_gltype(img->fmt);
127 }
128
129 unsigned int img_glintfmt(struct img_pixmap *img)
130 {
131         return img_fmt_glintfmt(img->fmt);
132 }
133
134 unsigned int img_gltexture(struct img_pixmap *img)
135 {
136         unsigned int tex;
137         unsigned int intfmt, fmt, type;
138
139         if(!gl_gen_textures) {
140                 if(load_glfunc() == -1) {
141                         fprintf(stderr, "imago: failed to initialize the OpenGL helpers\n");
142                         return 0;
143                 }
144         }
145
146         intfmt = img_glintfmt(img);
147         fmt = img_glfmt(img);
148         type = img_gltype(img);
149
150         gl_gen_textures(1, &tex);
151         gl_bind_texture(GL_TEXTURE_2D, tex);
152         gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
153         gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
154         gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
155         gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
156         if(!gl_generate_mipmap) {
157                 gl_tex_parameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, 1);
158                 gl_get_error(); /* clear errors in case SGIS_generate_mipmap is not supported */
159         }
160         gl_tex_image2d(GL_TEXTURE_2D, 0, intfmt, img->width, img->height, 0, fmt, type, img->pixels);
161         if(gl_generate_mipmap) {
162                 gl_generate_mipmap(GL_TEXTURE_2D);
163         }
164         return tex;
165 }
166
167 unsigned int img_gltexture_load(const char *fname)
168 {
169         struct img_pixmap img;
170         unsigned int tex;
171
172         img_init(&img);
173         if(img_load(&img, fname) == -1) {
174                 img_destroy(&img);
175                 return 0;
176         }
177
178         tex = img_gltexture(&img);
179         img_destroy(&img);
180         return tex;
181 }
182
183 unsigned int img_gltexture_read_file(FILE *fp)
184 {
185         struct img_pixmap img;
186         unsigned int tex;
187
188         img_init(&img);
189         if(img_read_file(&img, fp) == -1) {
190                 img_destroy(&img);
191                 return 0;
192         }
193
194         tex = img_gltexture(&img);
195         img_destroy(&img);
196         return tex;
197 }
198
199 unsigned int img_gltexture_read(struct img_io *io)
200 {
201         struct img_pixmap img;
202         unsigned int tex;
203
204         img_init(&img);
205         if(img_read(&img, io) == -1) {
206                 img_destroy(&img);
207                 return 0;
208         }
209
210         tex = img_gltexture(&img);
211         img_destroy(&img);
212         return tex;
213 }
214
215 #if defined(__unix__) || defined(__APPLE__)
216 #include <dlfcn.h>
217
218 #ifndef RTLD_DEFAULT
219 #define RTLD_DEFAULT    ((void*)0)
220 #endif
221
222 #endif
223 #ifdef WIN32
224 #include <windows.h>
225 #endif
226
227 static int load_glfunc(void)
228 {
229 #if defined(__unix__) || defined(__APPLE__)
230         gl_gen_textures = (gl_gen_textures_func)dlsym(RTLD_DEFAULT, "glGenTextures");
231         gl_bind_texture = (gl_bind_texture_func)dlsym(RTLD_DEFAULT, "glBindTexture");
232         gl_tex_parameteri = (gl_tex_parameteri_func)dlsym(RTLD_DEFAULT, "glTexParameteri");
233         gl_tex_image2d = (gl_tex_image2d_func)dlsym(RTLD_DEFAULT, "glTexImage2D");
234         gl_generate_mipmap = (gl_generate_mipmap_func)dlsym(RTLD_DEFAULT, "glGenerateMipmap");
235         gl_get_error = (gl_get_error_func)dlsym(RTLD_DEFAULT, "glGetError");
236 #endif
237
238 #ifdef WIN32
239         HANDLE dll = LoadLibrary("opengl32.dll");
240         if(dll) {
241                 gl_gen_textures = (gl_gen_textures_func)GetProcAddress(dll, "glGenTextures");
242                 gl_bind_texture = (gl_bind_texture_func)GetProcAddress(dll, "glBindTexture");
243                 gl_tex_parameteri = (gl_tex_parameteri_func)GetProcAddress(dll, "glTexParameteri");
244                 gl_tex_image2d = (gl_tex_image2d_func)GetProcAddress(dll, "glTexImage2D");
245                 gl_generate_mipmap = (gl_generate_mipmap_func)GetProcAddress(dll, "glGenerateMipmap");
246                 gl_get_error = (gl_get_error_func)GetProcAddress(dll, "glGetError");
247         }
248 #endif
249
250         return (gl_gen_textures && gl_bind_texture && gl_tex_parameteri && gl_tex_image2d && gl_get_error) ? 0 : -1;
251 }