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