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