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         deprecated("Use .destroy instead") void close(){}
80 
81         /// Binds this renderbuffer.
82         /// Throws: $(D OpenGLException) on error.
83         void use()
84         {
85             glBindRenderbuffer(GL_RENDERBUFFER, _handle);
86             _gl.runtimeCheck();
87         }
88 
89         /// Unbinds this renderbuffer.
90         /// Throws: $(D OpenGLException) on error.
91         void unuse()
92         {
93             glBindRenderbuffer(GL_RENDERBUFFER, 0);
94             _gl.runtimeCheck();
95         }
96 
97         /// Returns: Wrapped OpenGL resource handle.
98         GLuint handle() pure const nothrow
99         {
100             return _handle;
101         }
102     }
103 
104     package
105     {
106         GLuint _handle;
107     }
108 
109     private
110     {
111         OpenGL _gl;
112         GLenum _format;
113         GLenum _type;
114         bool _initialized;
115     }
116 }