textures
[nexus3d] / src / gl / tex_gl.c
diff --git a/src/gl/tex_gl.c b/src/gl/tex_gl.c
new file mode 100644 (file)
index 0000000..6369a5c
--- /dev/null
@@ -0,0 +1,210 @@
+#include "nexus3d_impl.h"
+#include "gfx_gl.h"
+#include "opengl.h"
+
+static unsigned int gltextype(enum nex_tex_type type);
+static unsigned int glpixfmt(enum nex_pixfmt fmt);
+static unsigned int glformat(enum nex_pixfmt fmt);
+static unsigned int gltype(enum nex_pixfmt fmt);
+/*static unsigned int glcubeface(enum nex_cube_face face);*/
+static unsigned int miplevels(int x, int y, int z);
+
+nex_texture *nex_alloc_texture(enum nex_tex_type type)
+{
+       nex_texture *tex;
+
+       if(!(tex = calloc(1, sizeof *tex))) {
+               return 0;
+       }
+       tex->type = type;
+       glCreateTextures(gltextype(type), 1, &tex->tex);
+       return tex;
+}
+
+void nex_free_texture(nex_texture *tex)
+{
+       if(!tex) return;
+
+       glDeleteTextures(1, &tex->tex);
+       free(tex);
+}
+
+
+void nex_tex_storage1d(nex_texture *tex, int sz, enum nex_pixfmt fmt)
+{
+       glTextureStorage1D(tex->tex, miplevels(sz, 0, 0), glpixfmt(fmt), sz);
+}
+
+void nex_tex_storage2d(nex_texture *tex, int xsz, int ysz, enum nex_pixfmt fmt)
+{
+       int levels = miplevels(xsz, ysz, 0);
+       glTextureStorage2D(tex->tex, levels, glpixfmt(fmt), xsz, ysz);
+}
+
+void nex_tex_storage3d(nex_texture *tex, int xsz, int ysz, int zsz, enum nex_pixfmt fmt)
+{
+       int levels = miplevels(xsz, ysz, zsz);
+       glTextureStorage3D(tex->tex, levels, glpixfmt(fmt), xsz, ysz, zsz);
+}
+
+void nex_tex_storagecube(nex_texture *tex, int xsz, int ysz, enum nex_pixfmt fmt)
+{
+       nex_tex_storage2d(tex, xsz, ysz, fmt);
+}
+
+
+void nex_tex_update1d(nex_texture *tex, int lvl, int x, int width,
+               enum nex_pixfmt pixfmt, void *data, long pitch)
+{
+       int fmt = glformat(pixfmt);
+       int type = gltype(pixfmt);
+       glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch);
+       glTextureSubImage1D(tex->tex, lvl, x, width, fmt, type, data);
+       glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+}
+
+void nex_tex_update2d(nex_texture *tex, int lvl, int x, int y, int width, int height,
+               enum nex_pixfmt pixfmt, void *data, long pitch)
+{
+       int fmt = glformat(pixfmt);
+       int type = gltype(pixfmt);
+       glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch);
+       glTextureSubImage2D(tex->tex, lvl, x, y, width, height, fmt, type, data);
+       glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+}
+
+void nex_tex_update3d(nex_texture *tex, int lvl, int x, int y, int z, int width,
+               int height, int depth, enum nex_pixfmt pixfmt, void *data, long pitch)
+{
+       int fmt = glformat(pixfmt);
+       int type = gltype(pixfmt);
+       glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch);
+       glTextureSubImage3D(tex->tex, lvl, x, y, z, width, height, depth, fmt, type,
+                       data);
+       glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+}
+
+
+void nex_tex_updatecube(nex_texture *tex, int lvl, enum nex_cube_face face,
+               int x, int y, int width, int height, enum nex_pixfmt pixfmt, void *data,
+               long pitch)
+{
+       int fmt = glformat(pixfmt);
+       int type = gltype(pixfmt);
+       glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch);
+       glTextureSubImage3D(tex->tex, lvl, x, y, face, width, height, 1, fmt, type,
+                       data);
+       glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+}
+
+void bind_texture(int tunit, nex_texture *tex)
+{
+       glBindTextureUnit(tunit, tex->tex);
+}
+
+
+static unsigned int gltextype(enum nex_tex_type type)
+{
+       switch(type) {
+       case NEX_TEX1D:
+               return GL_TEXTURE_1D;
+       case NEX_TEX2D:
+               return GL_TEXTURE_2D;
+       case NEX_TEX3D:
+               return GL_TEXTURE_3D;
+       case NEX_TEXCUBE:
+               return GL_TEXTURE_CUBE_MAP;
+       default:
+               break;
+       }
+       return 0;
+}
+
+static unsigned int glpixfmt(enum nex_pixfmt fmt)
+{
+       switch(fmt) {
+       case NEX_GREY8:
+               return GL_LUMINANCE;
+       case NEX_RGB24:
+               return GL_RGB;
+       case NEX_RGBA32:
+               return GL_RGBA;
+       case NEX_SRGB:
+               return GL_SRGB;
+       case NEX_SRGBA:
+               return GL_SRGB_ALPHA;
+       case NEX_GREYF:
+               return GL_LUMINANCE16F_ARB;
+       case NEX_RGBF:
+               return GL_RGB16F;
+       case NEX_RGBAF:
+               return GL_RGBA16F;
+       default:
+               break;
+       }
+       return 0;
+}
+
+/*
+static unsigned int glcubeface(enum nex_cube_face face)
+{
+       switch(face) {
+       case NEX_CUBE_PX:
+               return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+       case NEX_CUBE_NX:
+               return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
+       case NEX_CUBE_PY:
+               return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
+       case NEX_CUBE_NY:
+               return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
+       case NEX_CUBE_PZ:
+               return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
+       case NEX_CUBE_NZ:
+               return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+       default:
+               break;
+       }
+       return 0;
+}
+*/
+
+static unsigned int glformat(enum nex_pixfmt fmt)
+{
+       switch(fmt) {
+       case NEX_GREY8:
+       case NEX_GREYF:
+               return GL_LUMINANCE;
+       case NEX_RGB24:
+       case NEX_SRGB:
+       case NEX_RGBF:
+               return GL_RGB;
+       case NEX_RGBA32:
+       case NEX_SRGBA:
+       case NEX_RGBAF:
+               return GL_RGBA;
+       default:
+               break;
+       }
+       return 0;
+}
+
+static unsigned int gltype(enum nex_pixfmt fmt)
+{
+       if(fmt == NEX_GREYF || fmt == NEX_RGBF || fmt == NEX_RGBAF) {
+               return GL_FLOAT;
+       }
+       return GL_UNSIGNED_BYTE;
+}
+
+static unsigned int miplevels(int x, int y, int z)
+{
+       int lvl = 0;
+       if(y > x) x = y;
+       if(z > x) x = z;
+
+       while(x > 0) {
+               lvl++;
+               x >>= 1;
+       }
+       return lvl;
+}