nuclear@14: #include "imago2.h" nuclear@14: nuclear@14: /* to avoid dependency to OpenGL, I'll define all the relevant GL macros manually */ nuclear@14: #define GL_UNSIGNED_BYTE 0x1401 nuclear@14: #define GL_FLOAT 0x1406 nuclear@14: nuclear@14: #define GL_LUMINANCE 0x1909 nuclear@14: #define GL_RGB 0x1907 nuclear@14: #define GL_RGBA 0x1908 nuclear@14: nuclear@14: #define GL_RGBA32F 0x8814 nuclear@14: #define GL_RGB32F 0x8815 nuclear@14: #define GL_LUMINANCE32F 0x8818 nuclear@14: nuclear@14: #define GL_TEXTURE_2D 0x0de1 nuclear@14: #define GL_TEXTURE_WRAP_S 0x2802 nuclear@14: #define GL_TEXTURE_WRAP_T 0x2803 nuclear@14: #define GL_TEXTURE_MAG_FILTER 0x2800 nuclear@14: #define GL_TEXTURE_MIN_FILTER 0x2801 nuclear@14: #define GL_LINEAR 0x2601 nuclear@14: #define GL_REPEAT 0x2901 nuclear@14: nuclear@14: nuclear@14: typedef unsigned int GLenum; nuclear@14: typedef unsigned int GLuint; nuclear@14: typedef int GLint; nuclear@14: typedef int GLsizei; nuclear@14: typedef void GLvoid; nuclear@14: nuclear@14: /* for the same reason I'll load GL functions dynamically */ nuclear@14: #ifndef WIN32 nuclear@14: typedef void (*gl_gen_textures_func)(GLsizei, GLuint*); nuclear@14: typedef void (*gl_bind_texture_func)(GLenum, GLuint); nuclear@14: typedef void (*gl_tex_parameteri_func)(GLenum, GLenum, GLint); nuclear@14: typedef void (*gl_tex_image2d_func)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*); nuclear@14: #else nuclear@14: typedef void (__stdcall *gl_gen_textures_func)(GLsizei, GLuint*); nuclear@14: typedef void (__stdcall *gl_bind_texture_func)(GLenum, GLuint); nuclear@14: typedef void (__stdcall *gl_tex_parameteri_func)(GLenum, GLenum, GLint); nuclear@14: typedef void (__stdcall *gl_tex_image2d_func)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*); nuclear@14: #endif nuclear@14: nuclear@14: static gl_gen_textures_func gl_gen_textures; nuclear@14: static gl_bind_texture_func gl_bind_texture; nuclear@14: static gl_tex_parameteri_func gl_tex_parameteri; nuclear@14: static gl_tex_image2d_func gl_tex_image2d; nuclear@14: nuclear@14: static int load_glfunc(void); nuclear@14: nuclear@14: unsigned int img_fmt_glfmt(enum img_fmt fmt) nuclear@14: { nuclear@14: switch(fmt) { nuclear@14: case IMG_FMT_GREY8: nuclear@14: case IMG_FMT_GREYF: nuclear@14: return GL_LUMINANCE; nuclear@14: nuclear@14: case IMG_FMT_RGB24: nuclear@14: case IMG_FMT_RGBF: nuclear@14: return GL_RGB; nuclear@14: nuclear@14: case IMG_FMT_RGBA32: nuclear@14: case IMG_FMT_RGBAF: nuclear@14: return GL_RGBA; nuclear@14: nuclear@14: default: nuclear@14: break; nuclear@14: } nuclear@14: return 0; nuclear@14: } nuclear@14: nuclear@14: unsigned int img_fmt_gltype(enum img_fmt fmt) nuclear@14: { nuclear@14: switch(fmt) { nuclear@14: case IMG_FMT_GREY8: nuclear@14: case IMG_FMT_RGB24: nuclear@14: case IMG_FMT_RGBA32: nuclear@14: return GL_UNSIGNED_BYTE; nuclear@14: nuclear@14: case IMG_FMT_GREYF: nuclear@14: case IMG_FMT_RGBF: nuclear@14: case IMG_FMT_RGBAF: nuclear@14: return GL_FLOAT; nuclear@14: nuclear@14: default: nuclear@14: break; nuclear@14: } nuclear@14: return 0; nuclear@14: } nuclear@14: nuclear@14: unsigned int img_fmt_glintfmt(enum img_fmt fmt) nuclear@14: { nuclear@14: switch(fmt) { nuclear@14: case IMG_FMT_GREY8: nuclear@14: return GL_LUMINANCE; nuclear@14: case IMG_FMT_RGB24: nuclear@14: return GL_RGB; nuclear@14: case IMG_FMT_RGBA32: nuclear@14: return GL_RGBA; nuclear@14: case IMG_FMT_GREYF: nuclear@14: return GL_LUMINANCE32F; nuclear@14: case IMG_FMT_RGBF: nuclear@14: return GL_RGB32F; nuclear@14: case IMG_FMT_RGBAF: nuclear@14: return GL_RGBA32F; nuclear@14: default: nuclear@14: break; nuclear@14: } nuclear@14: return 0; nuclear@14: } nuclear@14: nuclear@14: unsigned int img_glfmt(struct img_pixmap *img) nuclear@14: { nuclear@14: return img_fmt_glfmt(img->fmt); nuclear@14: } nuclear@14: nuclear@14: unsigned int img_gltype(struct img_pixmap *img) nuclear@14: { nuclear@14: return img_fmt_gltype(img->fmt); nuclear@14: } nuclear@14: nuclear@14: unsigned int img_glintfmt(struct img_pixmap *img) nuclear@14: { nuclear@14: return img_fmt_glintfmt(img->fmt); nuclear@14: } nuclear@14: nuclear@14: unsigned int img_gltexture(struct img_pixmap *img) nuclear@14: { nuclear@14: unsigned int tex; nuclear@14: unsigned int intfmt, fmt, type; nuclear@14: nuclear@14: if(!gl_gen_textures) { nuclear@14: if(load_glfunc() == -1) { nuclear@14: fprintf(stderr, "imago: failed to initialize the OpenGL helpers\n"); nuclear@14: return 0; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: intfmt = img_glintfmt(img); nuclear@14: fmt = img_glfmt(img); nuclear@14: type = img_gltype(img); nuclear@14: nuclear@14: gl_gen_textures(1, &tex); nuclear@14: gl_bind_texture(GL_TEXTURE_2D, tex); nuclear@14: gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@14: gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@14: gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); nuclear@14: gl_tex_parameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); nuclear@14: gl_tex_image2d(GL_TEXTURE_2D, 0, intfmt, img->width, img->height, 0, fmt, type, img->pixels); nuclear@14: return tex; nuclear@14: } nuclear@14: nuclear@14: unsigned int img_gltexture_load(const char *fname) nuclear@14: { nuclear@14: struct img_pixmap img; nuclear@14: unsigned int tex; nuclear@14: nuclear@14: img_init(&img); nuclear@14: if(img_load(&img, fname) == -1) { nuclear@14: img_destroy(&img); nuclear@14: return 0; nuclear@14: } nuclear@14: nuclear@14: tex = img_gltexture(&img); nuclear@14: img_destroy(&img); nuclear@14: return tex; nuclear@14: } nuclear@14: nuclear@14: unsigned int img_gltexture_read_file(FILE *fp) nuclear@14: { nuclear@14: struct img_pixmap img; nuclear@14: unsigned int tex; nuclear@14: nuclear@14: img_init(&img); nuclear@14: if(img_read_file(&img, fp) == -1) { nuclear@14: img_destroy(&img); nuclear@14: return 0; nuclear@14: } nuclear@14: nuclear@14: tex = img_gltexture(&img); nuclear@14: img_destroy(&img); nuclear@14: return tex; nuclear@14: } nuclear@14: nuclear@14: unsigned int img_gltexture_read(struct img_io *io) nuclear@14: { nuclear@14: struct img_pixmap img; nuclear@14: unsigned int tex; nuclear@14: nuclear@14: img_init(&img); nuclear@14: if(img_read(&img, io) == -1) { nuclear@14: img_destroy(&img); nuclear@14: return 0; nuclear@14: } nuclear@14: nuclear@14: tex = img_gltexture(&img); nuclear@14: img_destroy(&img); nuclear@14: return tex; nuclear@14: } nuclear@14: nuclear@14: #if defined(__unix__) || defined(__APPLE__) nuclear@14: #ifndef __USE_GNU nuclear@14: #define __USE_GNU nuclear@14: #endif nuclear@14: nuclear@14: #include nuclear@14: #endif nuclear@14: #ifdef WIN32 nuclear@14: #include nuclear@14: #endif nuclear@14: nuclear@14: static int load_glfunc(void) nuclear@14: { nuclear@14: #if defined(__unix__) || defined(__APPLE__) nuclear@14: gl_gen_textures = (gl_gen_textures_func)dlsym(RTLD_DEFAULT, "glGenTextures"); nuclear@14: gl_bind_texture = (gl_bind_texture_func)dlsym(RTLD_DEFAULT, "glBindTexture"); nuclear@14: gl_tex_parameteri = (gl_tex_parameteri_func)dlsym(RTLD_DEFAULT, "glTexParameteri"); nuclear@14: gl_tex_image2d = (gl_tex_image2d_func)dlsym(RTLD_DEFAULT, "glTexImage2D"); nuclear@14: #endif nuclear@14: nuclear@14: #ifdef WIN32 nuclear@14: HANDLE dll = LoadLibrary("opengl32.dll"); nuclear@14: if(dll) { nuclear@14: gl_gen_textures = (gl_gen_textures_func)GetProcAddress(dll, "glGenTextures"); nuclear@14: gl_bind_texture = (gl_bind_texture_func)GetProcAddress(dll, "glBindTexture"); nuclear@14: gl_tex_parameteri = (gl_tex_parameteri_func)GetProcAddress(dll, "glTexParameteri"); nuclear@14: gl_tex_image2d = (gl_tex_image2d_func)GetProcAddress(dll, "glTexImage2D"); nuclear@14: } nuclear@14: #endif nuclear@14: nuclear@14: return (gl_gen_textures && gl_bind_texture && gl_tex_parameteri && gl_tex_image2d) ? 0 : -1; nuclear@14: }