1 module gfm.opengl.renderbuffer;
2 
3 import std.string;
4 
5 import derelict.opengl3.gl3;
6 
7 import gfm.math.funcs,
8        gfm.opengl.opengl;
9 
10 /// OpenGL Renderbuffer wrapper.
11 final class GLRenderBuffer
12 {
13     public
14     {
15         /// <p>Creates an OpenGL renderbuffer.</p>
16         /// <p>If asking for a multisampled render buffer fails, 
17         /// a non multisampled buffer will be created instead.</p>
18         /// Throws: $(D OpenGLException) if creation failed.
19         this(OpenGL gl, GLenum internalFormat, int width, int height, int samples = 0)
20         {
21             _gl = gl;
22             glGenRenderbuffers(1, &_handle);
23             gl.runtimeCheck();
24             
25             use();
26             scope(exit) unuse();
27             if (samples > 1)
28             {
29                 // fallback to non multisampled
30                 if (glRenderbufferStorageMultisample is null)
31                 {
32                     gl._logger.warningf("render-buffer multisampling is not supported, fallback to non-multisampled");
33                     goto non_mutisampled;
34                 }
35                 
36                 int maxSamples;
37                 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
38                 if (maxSamples < 1)
39                     maxSamples = 1;
40 
41                 // limit samples to what is supported on this machine
42                 if (samples >= maxSamples)
43                 {
44                     int newSamples = clamp(samples, 0, maxSamples - 1);
45                     gl._logger.warningf(format("implementation does not support %s samples, fallback to %s samples", samples, newSamples));
46                     samples = newSamples;
47                 }
48 
49                 try
50                 {
51                     glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalFormat, width, height);
52                 }
53                 catch(OpenGLException e)
54                 {
55                     _gl._logger.warning(e.msg);
56                     goto non_mutisampled; // fallback to non multisampled
57                 }
58             }
59             else
60             {
61             non_mutisampled:
62                 glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height);
63                 gl.runtimeCheck();
64             }
65 
66             _initialized = true;
67         }
68 
69         ~this()
70         {
71             close();
72         }
73 
74         /// Releases the OpenGL renderbuffer resource.
75         void close()
76         {
77             if (_initialized)
78             {
79                 _initialized = false;
80                 glDeleteRenderbuffers(1, &_handle);
81             }
82         }
83 
84         /// Binds this renderbuffer.
85         /// Throws: $(D OpenGLException) on error.
86         void use()
87         {
88             glBindRenderbuffer(GL_RENDERBUFFER, _handle);
89             _gl.runtimeCheck();
90         }
91 
92         /// Unbinds this renderbuffer.
93         /// Throws: $(D OpenGLException) on error.
94         void unuse()
95         {
96             glBindRenderbuffer(GL_RENDERBUFFER, 0);
97             _gl.runtimeCheck();
98         }
99 
100         /// Returns: Wrapped OpenGL resource handle.
101         GLuint handle() pure const nothrow
102         {
103             return _handle;
104         }
105     }
106 
107     package
108     {
109         GLuint _handle;
110     }
111 
112     private
113     {
114         OpenGL _gl;
115         GLenum _format;
116         GLenum _type;
117         bool _initialized;
118     }
119 }