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         /// Releases the OpenGL renderbuffer resource.
70         ~this()
71         {
72             if (_initialized)
73             {
74                 debug ensureNotInGC("GLRenderer");
75                 _initialized = false;
76                 glDeleteRenderbuffers(1, &_handle);
77             }
78         }
79 
80         /// Binds this renderbuffer.
81         /// Throws: $(D OpenGLException) on error.
82         void use()
83         {
84             glBindRenderbuffer(GL_RENDERBUFFER, _handle);
85             _gl.runtimeCheck();
86         }
87 
88         /// Unbinds this renderbuffer.
89         /// Throws: $(D OpenGLException) on error.
90         void unuse()
91         {
92             glBindRenderbuffer(GL_RENDERBUFFER, 0);
93             _gl.runtimeCheck();
94         }
95 
96         /// Returns: Wrapped OpenGL resource handle.
97         GLuint handle() pure const nothrow
98         {
99             return _handle;
100         }
101     }
102 
103     package
104     {
105         GLuint _handle;
106     }
107 
108     private
109     {
110         OpenGL _gl;
111         GLenum _format;
112         GLenum _type;
113         bool _initialized;
114     }
115 }