1 /// This module defines one texture type for each sort of OpenGL texture.
2 module gfm.opengl.texture;
3 
4 import std..string;
5 
6 import derelict.opengl;
7 
8 import gfm.opengl.opengl;
9 import gfm.math.vector;
10 
11 /// OpenGL Texture wrapper.
12 ///
13 /// TODO:
14 /// $(UL
15 ///     $(LI Support partial updates.)
16 ///     $(LI Support glStorage through pseudo-code given in OpenGL specification.)
17 ///  )
18 class GLTexture
19 {
20     public
21     {
22         /// Creates a texture. You should create a child class instead of calling
23         /// this constructor directly.
24         /// Throws: $(D OpenGLException) on error.
25         this(OpenGL gl, GLuint target)
26         {
27             _gl = gl;
28             _target = target;
29             glGenTextures(1, &_handle);
30             _gl.runtimeCheck();
31             _initialized = true;
32             _textureUnit = -1;
33         }
34 
35         /// Releases the OpenGL texture resource.
36         ~this()
37         {
38             if (_initialized)
39             {
40                 debug ensureNotInGC("GLTexture");
41                 glDeleteTextures(1, &_handle);
42                 _initialized = false;
43             }
44         }
45 
46         /// Use this texture, binding it to a texture unit.
47         /// Params:
48         ///     textureUnit = Index of the texture unit to use.
49         final void use(int textureUnit = 0)
50         {
51             _gl.setActiveTexture(textureUnit);
52             bind();
53         }
54 
55         /// Unuse this texture.
56         final void unuse()
57         {
58           // do nothing: texture unit binding is as needed
59         }
60 
61         /// Returns: Requested texture parameter.
62         /// Throws: $(D OpenGLException) on error.
63         /// Warning: Calling $(D glGetTexParameteriv) is generally not recommended
64         ///          since it could stall the OpenGL pipeline.
65         final int getParam(GLenum paramName)
66         {
67             int res;
68             bind();
69             glGetTexParameteriv(_target, paramName, &res);
70             _gl.runtimeCheck();
71             return res;
72         }
73 
74         /// Returns: Requested texture level parameter.
75         /// Throws: $(D OpenGLException) on error.
76         /// Warning: Calling $(D glGetTexLevelParameteriv) is generally not recommended
77         ///          since it could stall the OpenGL pipeline.
78         final int getLevelParam(GLenum paramName, int level)
79         {
80             int res;
81             bind();
82             glGetTexLevelParameteriv(_target, level, paramName, &res);
83             _gl.runtimeCheck();
84             return res;
85         }
86 
87         /// Sets the texture base level.
88         /// Throws: $(D OpenGLException) on error.
89         final void setBaseLevel(int level)
90         {
91             bind();
92             glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, level);
93             _gl.runtimeCheck();
94         }
95 
96         /// Sets the texture maximum level.
97         /// Throws: $(D OpenGLException) on error.
98         final void setMaxLevel(int level)
99         {
100             bind();
101             glTexParameteri(_target, GL_TEXTURE_MAX_LEVEL, level);
102             _gl.runtimeCheck();
103         }
104 
105         // Texture "sampler" parameters which are now in Sampler Objects too
106         // but are also here for legacy cards.
107 
108         /// Sets the texture minimum LOD.
109         /// Throws: $(D OpenGLException) on error.
110         final void setMinLOD(float lod)
111         {
112             bind();
113             glTexParameterf(_target, GL_TEXTURE_MIN_LOD, lod);
114             _gl.runtimeCheck();
115         }
116 
117         /// Sets the texture maximum LOD.
118         /// Throws: $(D OpenGLException) on error.
119         final void setMaxLOD(float lod)
120         {
121             bind();
122             glTexParameterf(_target, GL_TEXTURE_MAX_LOD, lod);
123             _gl.runtimeCheck();
124         }
125 
126         /// Sets the texture LOD bias.
127         /// Throws: $(D OpenGLException) on error.
128         final void setLODBias(float lodBias)
129         {
130             bind();
131             glTexParameterf(_target, GL_TEXTURE_LOD_BIAS, lodBias);
132             _gl.runtimeCheck();
133         }
134 
135         /// Sets the wrap mode for 1st texture coordinate.
136         /// Throws: $(D OpenGLException) on error.
137         final void setWrapS(GLenum wrapS)
138         {
139             bind();
140             glTexParameteri(_target, GL_TEXTURE_WRAP_S, wrapS);
141             _gl.runtimeCheck();
142         }
143 
144         /// Sets the wrap mode for 2nd texture coordinate.
145         /// Throws: $(D OpenGLException) on error.
146         final void setWrapT(GLenum wrapT)
147         {
148             bind();
149             glTexParameteri(_target, GL_TEXTURE_WRAP_T, wrapT);
150             _gl.runtimeCheck();
151         }
152 
153         /// Sets the wrap mode for 3rd texture coordinate.
154         /// Throws: $(D OpenGLException) on error.
155         final void setWrapR(GLenum wrapR)
156         {
157             bind();
158             glTexParameteri(_target, GL_TEXTURE_WRAP_R, wrapR);
159             _gl.runtimeCheck();
160         }
161 
162         /// Sets the texture minification filter mode.
163         /// Throws: $(D OpenGLException) on error.
164         final void setMinFilter(GLenum minFilter)
165         {
166             bind();
167             glTexParameteri(_target, GL_TEXTURE_MIN_FILTER, minFilter);
168             _gl.runtimeCheck();
169         }
170 
171         /// Sets the texture magnification filter mode.
172         /// Throws: $(D OpenGLException) on error.
173         final void setMagFilter(GLenum magFilter)
174         {
175             bind();
176             glTexParameteri(_target, GL_TEXTURE_MAG_FILTER, magFilter);
177             _gl.runtimeCheck();
178         }
179 
180         /// Sets the texture anisotropic filter level.
181         /// If texture anisotropy isn't supported, fail silently.
182         /// Throws: $(D OpenGLException) on error.
183         final void setMaxAnisotropy(float f)
184         {
185             bind();
186             glTexParameterf(_target, /* GL_TEXTURE_MAX_ANISOTROPY_EXT */ 0x84FE, f);
187             _gl.runtimeCheck();
188         }
189 
190         /// Sets the texture border color.
191         /// Throws: $(D OpenGLException) on error.
192         final void setBorderColor(vec4f color)
193         {
194             bind();
195             glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, color.ptr);
196             _gl.runtimeCheck();
197         }
198 
199         /// Sets the texture compare mode.
200         /// Throws: $(D OpenGLException) on error.
201         final void setCompareMode(GLenum compareMode)
202         {
203             bind();
204             glTexParameteri(_target, GL_TEXTURE_COMPARE_MODE, compareMode);
205             _gl.runtimeCheck();
206         }
207 
208         /// Sets the texture compare mode.
209         /// Throws: $(D OpenGLException) on error.
210         final void setCompareFunc(GLenum compareFunc)
211         {
212             bind();
213             glTexParameteri(_target, GL_TEXTURE_COMPARE_FUNC, compareFunc);
214             _gl.runtimeCheck();
215         }
216 
217         /// Gets the texture data.
218         /// Throws: $(D OpenGLException) on error.
219         final void getTexImage(int level, GLenum format, GLenum type, void* data)
220         {
221             bind();
222             glGetTexImage(_target, level, format, type, data);
223             _gl.runtimeCheck();
224         }
225 
226         /// Returns: Wrapped OpenGL resource handle.
227         GLuint handle() pure const nothrow
228         {
229           return _handle;
230         }
231 
232         GLuint target() pure const nothrow
233         {
234             return _target;
235         }
236 
237         /// Regenerates the mipmapped levels.
238         /// Throws: $(D OpenGLException) on error.
239         void generateMipmap()
240         {
241             bind();
242             glGenerateMipmap(_target);
243             _gl.runtimeCheck();
244         }
245     }
246 
247     package
248     {
249         GLuint _target;
250     }
251 
252     private
253     {
254         OpenGL _gl;
255         GLuint _handle;
256         bool _initialized;
257         int _textureUnit;
258 
259         void bind()
260         {
261             // Bind on whatever the current texture unit is!
262             glBindTexture(target, _handle);
263             _gl.runtimeCheck();
264         }
265     }
266 }
267 
268 /// Wrapper for 1D texture.
269 final class GLTexture1D : GLTexture
270 {
271     public
272     {
273         /// Creates a 1D texture.
274         /// Throws: $(D OpenGLException) on error.
275         this(OpenGL gl)
276         {
277             super(gl, GL_TEXTURE_1D);
278         }
279 
280         /// Sets texture content.
281         /// Throws: $(D OpenGLException) on error.
282         void setImage(int level, GLint internalFormat, int width, int border, GLenum format, GLenum type, void* data)
283         {
284             glTexImage1D(_target, level, internalFormat, width, border, format, type, data);
285             _gl.runtimeCheck();
286         }
287     }
288 
289 }
290 
291 /// Wrapper for 2D texture.
292 final class GLTexture2D : GLTexture
293 {
294     public
295     {
296         /// Creates a 2D texture.
297         /// Throws: $(D OpenGLException) on error.
298         this(OpenGL gl)
299         {
300             super(gl, GL_TEXTURE_2D);
301         }
302 
303         /// Sets texture content.
304         /// Throws: $(D OpenGLException) on error.
305         void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data)
306         {
307             glTexImage2D(_target, level, internalFormat, width, height, border, format, type, data);
308             _gl.runtimeCheck();
309         }
310     }
311 
312 }
313 
314 /// Wrapper for 3D texture.
315 final class GLTexture3D : GLTexture
316 {
317     public
318     {
319         /// Creates a 3D texture.
320         /// Throws: $(D OpenGLException) on error.
321         this(OpenGL gl)
322         {
323             super(gl, GL_TEXTURE_3D);
324         }
325 
326         /// Sets texture content.
327         /// Throws: $(D OpenGLException) on error.
328         void setImage(int level, GLint internalFormat, int width, int height, int depth, int border, GLenum format, GLenum type, void* data)
329         {
330             glTexImage3D(_target, level, internalFormat, width, height, depth, border, format, type, data);
331             _gl.runtimeCheck();
332         }
333     }
334 }
335 
336 /// Wrapper for 1D texture array.
337 final class GLTexture1DArray : GLTexture
338 {
339     public
340     {
341         /// Creates a 1D texture array.
342         /// Throws: $(D OpenGLException) on error.
343         this(OpenGL gl)
344         {
345             super(gl, GL_TEXTURE_1D_ARRAY);
346         }
347 
348         /// Sets texture content.
349         /// Throws: $(D OpenGLException) on error.
350         void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data)
351         {
352             glTexImage2D(_target, level, internalFormat, width, height, border, format, type, null);
353             _gl.runtimeCheck();
354         }
355     }
356 }
357 
358 /// Wrapper for 2D texture array.
359 final class GLTexture2DArray : GLTexture
360 {
361     public
362     {
363         /// Creates a 2D texture array.
364         /// Throws: $(D OpenGLException) on error.
365         this(OpenGL gl)
366         {
367             super(gl, GL_TEXTURE_2D_ARRAY);
368         }
369 
370         /// Sets texture content.
371         /// Throws: $(D OpenGLException) on error.
372         void setImage(int level, GLint internalFormat, int width, int height, int depth, int border, GLenum format, GLenum type, void* data)
373         {
374             glTexImage3D(_target, level, internalFormat, width, height, depth, border, format, type, data);
375             _gl.runtimeCheck();
376         }
377 
378         /// Sets partial texture content.
379         /// Throws: $(D OpenGLException) on error.
380         void setSubImage(int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, GLenum format, GLenum type, void* data)
381         {
382             glTexSubImage3D(_target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
383             _gl.runtimeCheck();
384         }
385     }
386 }
387 
388 /// Wrapper for texture rectangle.
389 final class GLTextureRectangle : GLTexture
390 {
391     public
392     {
393         /// Creates a texture rectangle.
394         /// Throws: $(D OpenGLException) on error.
395         this(OpenGL gl)
396         {
397             super(gl, GL_TEXTURE_RECTANGLE);
398         }
399 
400         /// Sets texture content.
401         /// Throws: $(D OpenGLException) on error.
402         void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data)
403         {
404             glTexImage2D(_target, level, internalFormat, width, height, border, format, type, null);
405             _gl.runtimeCheck();
406         }
407     }
408 }
409 
410 /// Wrapper for 2D multisampled texture.
411 final class GLTexture2DMultisample : GLTexture
412 {
413     public
414     {
415         /// Creates a 2D multisampled texture.
416         /// Throws: $(D OpenGLException) on error.
417         this(OpenGL gl)
418         {
419             super(gl, GL_TEXTURE_2D_MULTISAMPLE);
420         }
421 
422         /// Sets texture content.
423         /// Throws: $(D OpenGLException) on error.
424         void setImage(int level, int samples, GLint internalFormat, int width, int height, bool fixedsamplelocations)
425         {
426             glTexImage2DMultisample(_target, samples, internalFormat, width, height, fixedsamplelocations ? GL_TRUE : GL_FALSE);
427             _gl.runtimeCheck();
428         }
429     }
430 }
431 
432 /// Wrapper for 2D multisampled texture array.
433 final class GLTexture2DMultisampleArray : GLTexture
434 {
435     public
436     {
437         /// Creates a 2D multisampled texture array.
438         /// Throws: $(D OpenGLException) on error.
439         this(OpenGL gl)
440         {
441             super(gl, GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
442         }
443 
444         /// Sets texture content.
445         /// Throws: $(D OpenGLException) on error.
446         void setImage(int level, int samples, GLint internalFormat, int width, int height, int depth, bool fixedsamplelocations)
447         {
448             glTexImage3DMultisample(_target, samples, internalFormat, width, height, depth, fixedsamplelocations ? GL_TRUE : GL_FALSE);
449             _gl.runtimeCheck();
450         }
451     }
452 }
453 
454