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         /// Releases the OpenGL texture resource.
35         ~this()
36         {
37             if (_initialized)
38             {
39                 debug ensureNotInGC("GLTexture");
40                 glDeleteTextures(1, &_handle);
41                 _initialized = false;
42             }
43         }
44         deprecated("Use .destroy instead") void close(){}
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, f);
187             _gl.runtimeCheck();
188         }
189 
190         /// Gets the texture data.
191         /// Throws: $(D OpenGLException) on error.
192         final void getTexImage(int level, GLenum format, GLenum type, void* data)
193         {
194             bind();
195             glGetTexImage(_target, level, format, type, data);
196             _gl.runtimeCheck();
197         }
198 
199         /// Returns: Wrapped OpenGL resource handle.
200         GLuint handle() pure const nothrow
201         {
202           return _handle;
203         }
204 
205         GLuint target() pure const nothrow
206         {
207             return _target;
208         }
209 
210         /// Regenerates the mipmapped levels.
211         /// Throws: $(D OpenGLException) on error.
212         void generateMipmap()
213         {
214             bind();
215             glGenerateMipmap(_target);
216             _gl.runtimeCheck();
217         }
218     }
219 
220     package
221     {
222         GLuint _target;
223     }
224 
225     private
226     {
227         OpenGL _gl;
228         GLuint _handle;
229         bool _initialized;
230         int _textureUnit;
231 
232         void bind()
233         {
234             // Bind on whatever the current texture unit is!
235             glBindTexture(target, _handle);
236             _gl.runtimeCheck();
237         }
238     }
239 }
240 
241 /// Wrapper for 1D texture.
242 final class GLTexture1D : GLTexture
243 {
244     public
245     {
246         /// Creates a 1D texture.
247         /// Throws: $(D OpenGLException) on error.
248         this(OpenGL gl)
249         {
250             super(gl, GL_TEXTURE_1D);
251         }
252 
253         /// Sets texture content.
254         /// Throws: $(D OpenGLException) on error.
255         void setImage(int level, GLint internalFormat, int width, int border, GLenum format, GLenum type, void* data)
256         {
257             glTexImage1D(_target, level, internalFormat, width, border, format, type, data);
258             _gl.runtimeCheck();
259         }
260     }
261 
262 }
263 
264 /// Wrapper for 2D texture.
265 final class GLTexture2D : GLTexture
266 {
267     public
268     {
269         /// Creates a 2D texture.
270         /// Throws: $(D OpenGLException) on error.
271         this(OpenGL gl)
272         {
273             super(gl, GL_TEXTURE_2D);
274         }
275 
276         /// Sets texture content.
277         /// Throws: $(D OpenGLException) on error.
278         void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data)
279         {
280             glTexImage2D(_target, level, internalFormat, width, height, border, format, type, data);
281             _gl.runtimeCheck();
282         }
283     }
284 
285 }
286 
287 /// Wrapper for 3D texture.
288 final class GLTexture3D : GLTexture
289 {
290     public
291     {
292         /// Creates a 3D texture.
293         /// Throws: $(D OpenGLException) on error.
294         this(OpenGL gl)
295         {
296             super(gl, GL_TEXTURE_3D);
297         }
298 
299         /// Sets texture content.
300         /// Throws: $(D OpenGLException) on error.
301         void setImage(int level, GLint internalFormat, int width, int height, int depth, int border, GLenum format, GLenum type, void* data)
302         {
303             glTexImage3D(_target, level, internalFormat, width, height, depth, border, format, type, data);
304             _gl.runtimeCheck();
305         }
306     }
307 }
308 
309 /// Wrapper for 1D texture array.
310 final class GLTexture1DArray : GLTexture
311 {
312     public
313     {
314         /// Creates a 1D texture array.
315         /// Throws: $(D OpenGLException) on error.
316         this(OpenGL gl)
317         {
318             super(gl, GL_TEXTURE_1D_ARRAY);
319         }
320 
321         /// Sets texture content.
322         /// Throws: $(D OpenGLException) on error.
323         void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data)
324         {
325             glTexImage2D(_target, level, internalFormat, width, height, border, format, type, null);
326             _gl.runtimeCheck();
327         }
328     }
329 }
330 
331 /// Wrapper for 2D texture array.
332 final class GLTexture2DArray : GLTexture
333 {
334     public
335     {
336         /// Creates a 2D texture array.
337         /// Throws: $(D OpenGLException) on error.
338         this(OpenGL gl)
339         {
340             super(gl, GL_TEXTURE_2D_ARRAY);
341         }
342 
343         /// Sets texture content.
344         /// Throws: $(D OpenGLException) on error.
345         void setImage(int level, GLint internalFormat, int width, int height, int depth, int border, GLenum format, GLenum type, void* data)
346         {
347             glTexImage3D(_target, level, internalFormat, width, height, depth, border, format, type, data);
348             _gl.runtimeCheck();
349         }
350 
351         /// Sets partial texture content.
352         /// Throws: $(D OpenGLException) on error.
353         void setSubImage(int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, GLenum format, GLenum type, void* data)
354         {
355             glTexSubImage3D(_target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
356             _gl.runtimeCheck();
357         }
358     }
359 }
360 
361 /// Wrapper for texture rectangle.
362 final class GLTextureRectangle : GLTexture
363 {
364     public
365     {
366         /// Creates a texture rectangle.
367         /// Throws: $(D OpenGLException) on error.
368         this(OpenGL gl)
369         {
370             super(gl, GL_TEXTURE_RECTANGLE);
371         }
372 
373         /// Sets texture content.
374         /// Throws: $(D OpenGLException) on error.
375         void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data)
376         {
377             glTexImage2D(_target, level, internalFormat, width, height, border, format, type, null);
378             _gl.runtimeCheck();
379         }
380     }
381 }
382 
383 /// Wrapper for 2D multisampled texture.
384 final class GLTexture2DMultisample : GLTexture
385 {
386     public
387     {
388         /// Creates a 2D multisampled texture.
389         /// Throws: $(D OpenGLException) on error.
390         this(OpenGL gl)
391         {
392             super(gl, GL_TEXTURE_2D_MULTISAMPLE);
393         }
394 
395         /// Sets texture content.
396         /// Throws: $(D OpenGLException) on error.
397         void setImage(int level, int samples, GLint internalFormat, int width, int height, bool fixedsamplelocations)
398         {
399             glTexImage2DMultisample(_target, samples, internalFormat, width, height, fixedsamplelocations ? GL_TRUE : GL_FALSE);
400             _gl.runtimeCheck();
401         }
402     }
403 }
404 
405 /// Wrapper for 2D multisampled texture array.
406 final class GLTexture2DMultisampleArray : GLTexture
407 {
408     public
409     {
410         /// Creates a 2D multisampled texture array.
411         /// Throws: $(D OpenGLException) on error.
412         this(OpenGL gl)
413         {
414             super(gl, GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
415         }
416 
417         /// Sets texture content.
418         /// Throws: $(D OpenGLException) on error.
419         void setImage(int level, int samples, GLint internalFormat, int width, int height, int depth, bool fixedsamplelocations)
420         {
421             glTexImage3DMultisample(_target, samples, internalFormat, width, height, depth, fixedsamplelocations ? GL_TRUE : GL_FALSE);
422             _gl.runtimeCheck();
423         }
424     }
425 }
426 
427