prepare for the DOS port
[retroray] / libs / imago / src / imago_gl.c
1 /*
2 libimago - a multi-format image file input/output library.
3 Copyright (C) 2010-2021 John Tsiombikas <nuclear@member.fsf.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published
7 by the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "imago2.h"
19
20 #if defined(WIN32) || defined(__WIN32)
21 #include <windows.h>
22 #endif
23
24 #include <GL/gl.h>
25
26 #ifndef GL_GENERATE_MIPMAP_SGIS
27 #define GL_GENERATE_MIPMAP_SGIS 0x8191
28 #endif
29
30 #if 0
31 /* to avoid dependency to OpenGL, I'll define all the relevant GL macros manually */
32 #define GL_UNPACK_ALIGNMENT             0x0cf5
33
34 #define GL_UNSIGNED_BYTE                0x1401
35 #define GL_FLOAT                                0x1406
36
37 #define GL_LUMINANCE                    0x1909
38 #define GL_RGB                                  0x1907
39 #define GL_RGBA                                 0x1908
40
41 #define GL_SLUMINANCE                   0x8c46
42 #define GL_SRGB                                 0x8c40
43 #define GL_SRGB_ALPHA                   0x8c42
44
45 #define GL_RGBA32F                              0x8814
46 #define GL_RGB32F                               0x8815
47 #define GL_LUMINANCE32F                 0x8818
48
49 #define GL_TEXTURE_2D                   0x0de1
50 #define GL_TEXTURE_WRAP_S               0x2802
51 #define GL_TEXTURE_WRAP_T               0x2803
52 #define GL_TEXTURE_MAG_FILTER   0x2800
53 #define GL_TEXTURE_MIN_FILTER   0x2801
54 #define GL_LINEAR                               0x2601
55 #define GL_LINEAR_MIPMAP_LINEAR 0x2703
56 #define GL_REPEAT                               0x2901
57 #define GL_GENERATE_MIPMAP_SGIS 0x8191
58
59
60 typedef unsigned int GLenum;
61 typedef unsigned int GLuint;
62 typedef int GLint;
63 typedef int GLsizei;
64 typedef void GLvoid;
65
66 /* for the same reason I'll load GL functions dynamically */
67 #ifndef WIN32
68 typedef void (*gl_gen_textures_func)(GLsizei, GLuint*);
69 typedef void (*gl_bind_texture_func)(GLenum, GLuint);
70 typedef void (*gl_tex_parameteri_func)(GLenum, GLenum, GLint);
71 typedef void (*gl_tex_image2d_func)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*);
72 typedef void (*gl_generate_mipmap_func)(GLenum);
73 typedef GLenum (*gl_get_error_func)(void);
74 typedef void (*gl_pixel_storei_func)(GLenum, GLint);
75 #else
76 typedef void (__stdcall *gl_gen_textures_func)(GLsizei, GLuint*);
77 typedef void (__stdcall *gl_bind_texture_func)(GLenum, GLuint);
78 typedef void (__stdcall *gl_tex_parameteri_func)(GLenum, GLenum, GLint);
79 typedef void (__stdcall *gl_tex_image2d_func)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*);
80 typedef void (__stdcall *gl_generate_mipmap_func)(GLenum);
81 typedef GLenum (__stdcall *gl_get_error_func)(void);
82 typedef void (__stdcall *gl_pixel_storei_func)(GLenum, GLint);
83 #endif
84
85 static gl_gen_textures_func gl_gen_textures;
86 static gl_bind_texture_func gl_bind_texture;
87 static gl_tex_parameteri_func gl_tex_parameteri;
88 static gl_tex_image2d_func gl_tex_image2d;
89 static gl_generate_mipmap_func gl_generate_mipmap;
90 static gl_get_error_func gl_get_error;
91 static gl_pixel_storei_func gl_pixel_storei;
92
93 static int load_glfunc(void);
94 #endif
95
96 #ifndef GL_SRGB
97 #define GL_SLUMINANCE                   0x8c46
98 #define GL_SRGB                                 0x8c40
99 #define GL_SRGB_ALPHA                   0x8c42
100 #endif
101 #ifndef GL_RGBA32F
102 #define GL_RGBA32F                              0x8814
103 #define GL_RGB32F                               0x8815
104 #endif
105 #ifndef GL_LUMINANCE32F
106 #define GL_LUMINANCE32F                 0x8818
107 #endif
108
109 unsigned int img_fmt_glfmt(enum img_fmt fmt)
110 {
111         switch(fmt) {
112         case IMG_FMT_GREY8:
113         case IMG_FMT_GREYF:
114                 return GL_LUMINANCE;
115
116         case IMG_FMT_RGB24:
117         case IMG_FMT_RGBF:
118                 return GL_RGB;
119
120         case IMG_FMT_RGBA32:
121         case IMG_FMT_RGBAF:
122                 return GL_RGBA;
123
124         default:
125                 break;
126         }
127         return 0;
128 }
129
130 unsigned int img_fmt_gltype(enum img_fmt fmt)
131 {
132         switch(fmt) {
133         case IMG_FMT_GREY8:
134         case IMG_FMT_RGB24:
135         case IMG_FMT_RGBA32:
136                 return GL_UNSIGNED_BYTE;
137
138         case IMG_FMT_GREYF:
139         case IMG_FMT_RGBF:
140         case IMG_FMT_RGBAF:
141                 return GL_FLOAT;
142
143         default:
144                 break;
145         }
146         return 0;
147 }
148
149 unsigned int img_fmt_glintfmt(enum img_fmt fmt)
150 {
151         switch(fmt) {
152         case IMG_FMT_GREY8:
153                 return GL_LUMINANCE;
154         case IMG_FMT_RGB24:
155                 return GL_RGB;
156         case IMG_FMT_RGBA32:
157                 return GL_RGBA;
158         case IMG_FMT_GREYF:
159                 return GL_LUMINANCE32F;
160         case IMG_FMT_RGBF:
161                 return GL_RGB32F;
162         case IMG_FMT_RGBAF:
163                 return GL_RGBA32F;
164         default:
165                 break;
166         }
167         return 0;
168 }
169
170 unsigned int img_fmt_glintfmt_srgb(enum img_fmt fmt)
171 {
172         switch(fmt) {
173         case IMG_FMT_GREY8:
174                 return GL_SLUMINANCE;
175         case IMG_FMT_RGB24:
176                 return GL_SRGB;
177         case IMG_FMT_RGBA32:
178                 return GL_SRGB_ALPHA;
179         case IMG_FMT_GREYF:
180                 return GL_LUMINANCE32F;
181         case IMG_FMT_RGBF:
182                 return GL_RGB32F;
183         case IMG_FMT_RGBAF:
184                 return GL_RGBA32F;
185         default:
186                 break;
187         }
188         return 0;
189 }
190
191 unsigned int img_glfmt(struct img_pixmap *img)
192 {
193         return img_fmt_glfmt(img->fmt);
194 }
195
196 unsigned int img_gltype(struct img_pixmap *img)
197 {
198         return img_fmt_gltype(img->fmt);
199 }
200
201 unsigned int img_glintfmt(struct img_pixmap *img)
202 {
203         return img_fmt_glintfmt(img->fmt);
204 }
205
206 unsigned int img_glintfmt_srgb(struct img_pixmap *img)
207 {
208         return img_fmt_glintfmt_srgb(img->fmt);
209 }
210
211 #define gl_gen_textures glGenTextures
212 #define gl_bind_texture glBindTexture
213 #define gl_tex_parameteri glTexParameteri
214 #define gl_pixel_storei glPixelStorei
215 #define gl_tex_image2d glTexImage2D
216
217 unsigned int img_gltexture(struct img_pixmap *img)
218 {
219         unsigned int tex;
220         unsigned int intfmt, fmt, type;
221 /*
222         if(!gl_gen_textures) {
223                 if(load_glfunc() == -1) {
224                         fprintf(stderr, "imago: failed to initialize the OpenGL helpers\n");
225                         return 0;
226                 }
227         }
228 */
229         if(img->fmt == IMG_FMT_IDX8) {
230                 struct img_pixmap rgb;
231
232                 img_init(&rgb);
233                 if(img_copy(&rgb, img) == -1 || img_convert(&rgb, IMG_FMT_RGB24)) {
234                         return 0;
235                 }
236                 tex = img_gltexture(&rgb);
237                 img_destroy(&rgb);
238                 return tex;
239         }
240
241         intfmt = img_glintfmt(img);
242         fmt = img_glfmt(img);
243         type = img_gltype(img);
244
245         gl_gen_textures(1, &tex);
246         gl_bind_texture(GL_TEXTURE_2D, tex);
247         gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
248         gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
249         gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
250         gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
251         gl_pixel_storei(GL_UNPACK_ALIGNMENT, 1);
252         gl_tex_parameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, 1);
253         gl_tex_image2d(GL_TEXTURE_2D, 0, intfmt, img->width, img->height, 0, fmt, type, img->pixels);
254         return tex;
255 }
256
257 unsigned int img_gltexture_load(const char *fname)
258 {
259         struct img_pixmap img;
260         unsigned int tex;
261
262         img_init(&img);
263         if(img_load(&img, fname) == -1) {
264                 img_destroy(&img);
265                 return 0;
266         }
267
268         tex = img_gltexture(&img);
269         img_destroy(&img);
270         return tex;
271 }
272
273 unsigned int img_gltexture_read_file(FILE *fp)
274 {
275         struct img_pixmap img;
276         unsigned int tex;
277
278         img_init(&img);
279         if(img_read_file(&img, fp) == -1) {
280                 img_destroy(&img);
281                 return 0;
282         }
283
284         tex = img_gltexture(&img);
285         img_destroy(&img);
286         return tex;
287 }
288
289 unsigned int img_gltexture_read(struct img_io *io)
290 {
291         struct img_pixmap img;
292         unsigned int tex;
293
294         img_init(&img);
295         if(img_read(&img, io) == -1) {
296                 img_destroy(&img);
297                 return 0;
298         }
299
300         tex = img_gltexture(&img);
301         img_destroy(&img);
302         return tex;
303 }
304
305 #if 0
306 #if defined(__unix__) || defined(unix) || defined(__APPLE__)
307 #include <dlfcn.h>
308
309 #ifndef RTLD_DEFAULT
310 #define RTLD_DEFAULT    ((void*)0)
311 #endif
312
313 #endif
314 #ifdef _WIN32
315 #include <windows.h>
316 #endif
317
318 static int load_glfunc(void)
319 {
320 #if defined(__unix__) || defined(unix) || defined(__APPLE__)
321         gl_gen_textures = (gl_gen_textures_func)dlsym(RTLD_DEFAULT, "glGenTextures");
322         gl_bind_texture = (gl_bind_texture_func)dlsym(RTLD_DEFAULT, "glBindTexture");
323         gl_tex_parameteri = (gl_tex_parameteri_func)dlsym(RTLD_DEFAULT, "glTexParameteri");
324         gl_tex_image2d = (gl_tex_image2d_func)dlsym(RTLD_DEFAULT, "glTexImage2D");
325         gl_generate_mipmap = (gl_generate_mipmap_func)dlsym(RTLD_DEFAULT, "glGenerateMipmap");
326         gl_get_error = (gl_get_error_func)dlsym(RTLD_DEFAULT, "glGetError");
327         gl_pixel_storei = (gl_pixel_storei_func)dlsym(RTLD_DEFAULT, "glPixelStorei");
328 #endif
329
330 #ifdef _WIN32
331         HANDLE dll = LoadLibrary("opengl32.dll");
332         if(dll) {
333                 gl_gen_textures = (gl_gen_textures_func)GetProcAddress(dll, "glGenTextures");
334                 gl_bind_texture = (gl_bind_texture_func)GetProcAddress(dll, "glBindTexture");
335                 gl_tex_parameteri = (gl_tex_parameteri_func)GetProcAddress(dll, "glTexParameteri");
336                 gl_tex_image2d = (gl_tex_image2d_func)GetProcAddress(dll, "glTexImage2D");
337                 gl_generate_mipmap = (gl_generate_mipmap_func)GetProcAddress(dll, "glGenerateMipmap");
338                 gl_get_error = (gl_get_error_func)GetProcAddress(dll, "glGetError");
339                 gl_pixel_storei = (gl_pixel_storei_func)GetProcAddress(dll, "glPixelStorei");
340         }
341 #endif
342
343         return (gl_gen_textures && gl_bind_texture && gl_tex_parameteri && gl_tex_image2d && gl_get_error && gl_pixel_storei) ? 0 : -1;
344 }
345 #endif