1 module gfm.opengl.renderbuffer; 2 3 import std.string; 4 5 import bindbc.opengl; 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(GLenum internalFormat, int width, int height, int samples = 0) 20 { 21 glGenRenderbuffers(1, &_handle); 22 runtimeCheck(); 23 24 use(); 25 scope(exit) unuse(); 26 if (samples > 1) 27 { 28 // fallback to non multisampled 29 if (glRenderbufferStorageMultisample is null) 30 { 31 if (_logger) 32 _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 if (_logger) 46 _logger.warningf(format("implementation does not support %s samples, fallback to %s samples", samples, newSamples)); 47 samples = newSamples; 48 } 49 50 try 51 { 52 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalFormat, width, height); 53 } 54 catch(OpenGLException e) 55 { 56 if (_logger) 57 _logger.warning(e.msg); 58 goto non_mutisampled; // fallback to non multisampled 59 } 60 } 61 else 62 { 63 non_mutisampled: 64 glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height); 65 runtimeCheck(); 66 } 67 68 _initialized = true; 69 } 70 71 /// Releases the OpenGL renderbuffer resource. 72 ~this() 73 { 74 if (_initialized) 75 { 76 debug ensureNotInGC("GLRenderer"); 77 _initialized = false; 78 glDeleteRenderbuffers(1, &_handle); 79 } 80 } 81 82 /// Binds this renderbuffer. 83 /// Throws: $(D OpenGLException) on error. 84 void use() 85 { 86 glBindRenderbuffer(GL_RENDERBUFFER, _handle); 87 runtimeCheck(); 88 } 89 90 /// Unbinds this renderbuffer. 91 /// Throws: $(D OpenGLException) on error. 92 void unuse() 93 { 94 glBindRenderbuffer(GL_RENDERBUFFER, 0); 95 runtimeCheck(); 96 } 97 98 /// Returns: Wrapped OpenGL resource handle. 99 GLuint handle() pure const nothrow 100 { 101 return _handle; 102 } 103 104 /// Sets a logger for the program. That allows additional output 105 /// besides error reporting. 106 void logger(Logger l) pure nothrow { _logger = l; } 107 } 108 109 package 110 { 111 GLuint _handle; 112 } 113 114 private 115 { 116 import std.experimental.logger : Logger; 117 118 GLenum _format; 119 GLenum _type; 120 bool _initialized; 121 Logger _logger; 122 } 123 }