textures
[nexus3d] / src / gl / tex_gl.c
1 #include "nexus3d_impl.h"
2 #include "gfx_gl.h"
3 #include "opengl.h"
4
5 static unsigned int gltextype(enum nex_tex_type type);
6 static unsigned int glpixfmt(enum nex_pixfmt fmt);
7 static unsigned int glformat(enum nex_pixfmt fmt);
8 static unsigned int gltype(enum nex_pixfmt fmt);
9 /*static unsigned int glcubeface(enum nex_cube_face face);*/
10 static unsigned int miplevels(int x, int y, int z);
11
12 nex_texture *nex_alloc_texture(enum nex_tex_type type)
13 {
14         nex_texture *tex;
15
16         if(!(tex = calloc(1, sizeof *tex))) {
17                 return 0;
18         }
19         tex->type = type;
20         glCreateTextures(gltextype(type), 1, &tex->tex);
21         return tex;
22 }
23
24 void nex_free_texture(nex_texture *tex)
25 {
26         if(!tex) return;
27
28         glDeleteTextures(1, &tex->tex);
29         free(tex);
30 }
31
32
33 void nex_tex_storage1d(nex_texture *tex, int sz, enum nex_pixfmt fmt)
34 {
35         glTextureStorage1D(tex->tex, miplevels(sz, 0, 0), glpixfmt(fmt), sz);
36 }
37
38 void nex_tex_storage2d(nex_texture *tex, int xsz, int ysz, enum nex_pixfmt fmt)
39 {
40         int levels = miplevels(xsz, ysz, 0);
41         glTextureStorage2D(tex->tex, levels, glpixfmt(fmt), xsz, ysz);
42 }
43
44 void nex_tex_storage3d(nex_texture *tex, int xsz, int ysz, int zsz, enum nex_pixfmt fmt)
45 {
46         int levels = miplevels(xsz, ysz, zsz);
47         glTextureStorage3D(tex->tex, levels, glpixfmt(fmt), xsz, ysz, zsz);
48 }
49
50 void nex_tex_storagecube(nex_texture *tex, int xsz, int ysz, enum nex_pixfmt fmt)
51 {
52         nex_tex_storage2d(tex, xsz, ysz, fmt);
53 }
54
55
56 void nex_tex_update1d(nex_texture *tex, int lvl, int x, int width,
57                 enum nex_pixfmt pixfmt, void *data, long pitch)
58 {
59         int fmt = glformat(pixfmt);
60         int type = gltype(pixfmt);
61         glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch);
62         glTextureSubImage1D(tex->tex, lvl, x, width, fmt, type, data);
63         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
64 }
65
66 void nex_tex_update2d(nex_texture *tex, int lvl, int x, int y, int width, int height,
67                 enum nex_pixfmt pixfmt, void *data, long pitch)
68 {
69         int fmt = glformat(pixfmt);
70         int type = gltype(pixfmt);
71         glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch);
72         glTextureSubImage2D(tex->tex, lvl, x, y, width, height, fmt, type, data);
73         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
74 }
75
76 void nex_tex_update3d(nex_texture *tex, int lvl, int x, int y, int z, int width,
77                 int height, int depth, enum nex_pixfmt pixfmt, void *data, long pitch)
78 {
79         int fmt = glformat(pixfmt);
80         int type = gltype(pixfmt);
81         glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch);
82         glTextureSubImage3D(tex->tex, lvl, x, y, z, width, height, depth, fmt, type,
83                         data);
84         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
85 }
86
87
88 void nex_tex_updatecube(nex_texture *tex, int lvl, enum nex_cube_face face,
89                 int x, int y, int width, int height, enum nex_pixfmt pixfmt, void *data,
90                 long pitch)
91 {
92         int fmt = glformat(pixfmt);
93         int type = gltype(pixfmt);
94         glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch);
95         glTextureSubImage3D(tex->tex, lvl, x, y, face, width, height, 1, fmt, type,
96                         data);
97         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
98 }
99
100 void bind_texture(int tunit, nex_texture *tex)
101 {
102         glBindTextureUnit(tunit, tex->tex);
103 }
104
105
106 static unsigned int gltextype(enum nex_tex_type type)
107 {
108         switch(type) {
109         case NEX_TEX1D:
110                 return GL_TEXTURE_1D;
111         case NEX_TEX2D:
112                 return GL_TEXTURE_2D;
113         case NEX_TEX3D:
114                 return GL_TEXTURE_3D;
115         case NEX_TEXCUBE:
116                 return GL_TEXTURE_CUBE_MAP;
117         default:
118                 break;
119         }
120         return 0;
121 }
122
123 static unsigned int glpixfmt(enum nex_pixfmt fmt)
124 {
125         switch(fmt) {
126         case NEX_GREY8:
127                 return GL_LUMINANCE;
128         case NEX_RGB24:
129                 return GL_RGB;
130         case NEX_RGBA32:
131                 return GL_RGBA;
132         case NEX_SRGB:
133                 return GL_SRGB;
134         case NEX_SRGBA:
135                 return GL_SRGB_ALPHA;
136         case NEX_GREYF:
137                 return GL_LUMINANCE16F_ARB;
138         case NEX_RGBF:
139                 return GL_RGB16F;
140         case NEX_RGBAF:
141                 return GL_RGBA16F;
142         default:
143                 break;
144         }
145         return 0;
146 }
147
148 /*
149 static unsigned int glcubeface(enum nex_cube_face face)
150 {
151         switch(face) {
152         case NEX_CUBE_PX:
153                 return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
154         case NEX_CUBE_NX:
155                 return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
156         case NEX_CUBE_PY:
157                 return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
158         case NEX_CUBE_NY:
159                 return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
160         case NEX_CUBE_PZ:
161                 return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
162         case NEX_CUBE_NZ:
163                 return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
164         default:
165                 break;
166         }
167         return 0;
168 }
169 */
170
171 static unsigned int glformat(enum nex_pixfmt fmt)
172 {
173         switch(fmt) {
174         case NEX_GREY8:
175         case NEX_GREYF:
176                 return GL_LUMINANCE;
177         case NEX_RGB24:
178         case NEX_SRGB:
179         case NEX_RGBF:
180                 return GL_RGB;
181         case NEX_RGBA32:
182         case NEX_SRGBA:
183         case NEX_RGBAF:
184                 return GL_RGBA;
185         default:
186                 break;
187         }
188         return 0;
189 }
190
191 static unsigned int gltype(enum nex_pixfmt fmt)
192 {
193         if(fmt == NEX_GREYF || fmt == NEX_RGBF || fmt == NEX_RGBAF) {
194                 return GL_FLOAT;
195         }
196         return GL_UNSIGNED_BYTE;
197 }
198
199 static unsigned int miplevels(int x, int y, int z)
200 {
201         int lvl = 0;
202         if(y > x) x = y;
203         if(z > x) x = z;
204
205         while(x > 0) {
206                 lvl++;
207                 x >>= 1;
208         }
209         return lvl;
210 }