1 /// High level OpenGL D wrapper 2 module opengl.d; 3 4 public 5 { 6 import opengl.d.buffer; 7 import opengl.d.program; 8 import opengl.d.shader; 9 import opengl.d.vertexarray; 10 } 11 12 import opengl.gl4; 13 14 /// Generates a static OpenGL boolean property (glEnable/glDisable) 15 mixin template glBoolProperty(GLenum value, string name) 16 { 17 static bool enabled() 18 { 19 return glIsEnabled(value); 20 } 21 22 static bool enabled(bool val) 23 { 24 if (val) 25 glEnable(value); 26 else 27 glDisable(value); 28 return val; 29 } 30 } 31 32 /// Wrapper "namespace" containing properties and stateless functions 33 struct GL 34 { 35 @disable this(); 36 37 @nogc @system: 38 39 @property nothrow 40 { 41 mixin glBoolProperty!(GL_BLEND, "Blend") blend; 42 alias enableBlend = blend.enabled; /// 43 mixin glBoolProperty!(GL_COLOR_LOGIC_OP, "ColorLogicOperation") colorLogicOperation; 44 alias enableColorLogicOperation = colorLogicOperation.enabled; /// 45 mixin glBoolProperty!(GL_CULL_FACE, "CullFace") cullFace; 46 alias enableCullFace = cullFace.enabled; /// 47 mixin glBoolProperty!(GL_DEBUG_OUTPUT, "DebugOutput") debugOutput; 48 alias enableDebugOutput = debugOutput.enabled; /// 49 mixin glBoolProperty!(GL_DEBUG_OUTPUT_SYNCHRONOUS, "DebugOutputSync") debugOutputSync; 50 alias enableDebugOutputSync = debugOutputSync.enabled; /// 51 mixin glBoolProperty!(GL_DEPTH_CLAMP, "DepthClamp") depthClamp; 52 alias enableDepthClamp = depthClamp.enabled; /// 53 mixin glBoolProperty!(GL_DEPTH_TEST, "DepthTest") depthTest; 54 alias enableDepthTest = depthTest.enabled; /// 55 mixin glBoolProperty!(GL_DITHER, "Dither") dither; 56 alias enableDither = dither.enabled; /// 57 mixin glBoolProperty!(GL_FRAMEBUFFER_SRGB, "FramebufferSRGB") framebufferSRGB; 58 alias enableFramebufferSRGB = framebufferSRGB.enabled; /// 59 mixin glBoolProperty!(GL_LINE_SMOOTH, "LineSmooth") lineSmooth; 60 alias enableLineSmooth = lineSmooth.enabled; /// 61 mixin glBoolProperty!(GL_MULTISAMPLE, "Multisample") multisample; 62 alias enableMultisample = multisample.enabled; /// 63 mixin glBoolProperty!(GL_POLYGON_OFFSET_FILL, "PolygonOffsetFill") polygonOffsetFill; 64 alias enablePolygonOffsetFill = polygonOffsetFill.enabled; /// 65 mixin glBoolProperty!(GL_POLYGON_OFFSET_LINE, "PolygonOffsetLine") polygonOffsetLine; 66 alias enablePolygonOffsetLine = polygonOffsetLine.enabled; /// 67 mixin glBoolProperty!(GL_POLYGON_OFFSET_POINT, "PolygonOffsetPoint") polygonOffsetPoint; 68 alias enablePolygonOffsetPoint = polygonOffsetPoint.enabled; /// 69 mixin glBoolProperty!(GL_POLYGON_SMOOTH, "PolygonSmooth") polygonSmooth; 70 alias enablePolygonSmooth = polygonSmooth.enabled; /// 71 mixin glBoolProperty!(GL_PRIMITIVE_RESTART, "PrimitiveRestart") primitiveRestart; 72 alias enablePrimitiveRestart = primitiveRestart.enabled; /// 73 mixin glBoolProperty!(GL_PRIMITIVE_RESTART_FIXED_INDEX, "PrimitiveRestartFixedIndex") primitiveRestartFixedIndex; 74 alias enablePrimitiveRestartFixedIndex = primitiveRestartFixedIndex.enabled; /// 75 mixin glBoolProperty!(GL_RASTERIZER_DISCARD, "RasterizerDiscard") rasterizerDiscard; 76 alias enableRasterizerDiscard = rasterizerDiscard.enabled; /// 77 mixin glBoolProperty!(GL_SAMPLE_ALPHA_TO_COVERAGE, "SampleAlphaToCoverage") sampleAlphaToCoverage; 78 alias enableSampleAlphaToCoverage = sampleAlphaToCoverage.enabled; /// 79 mixin glBoolProperty!(GL_SAMPLE_ALPHA_TO_ONE, "SampleAlphaToOne") sampleAlphaToOne; 80 alias enableSampleAlphaToOne = sampleAlphaToOne.enabled; /// 81 mixin glBoolProperty!(GL_SAMPLE_COVERAGE, "SampleCoverage") bSampleCoverage; 82 alias enableSampleCoverage = bSampleCoverage.enabled; /// 83 mixin glBoolProperty!(GL_SAMPLE_SHADING, "SampleShading") sampleShading; 84 alias enableSampleShading = sampleShading.enabled; /// 85 mixin glBoolProperty!(GL_SCISSOR_TEST, "ScissorTest") scissorTest; 86 alias enableScissorTest = scissorTest.enabled; /// 87 mixin glBoolProperty!(GL_STENCIL_TEST, "StencilTest") stencilTest; 88 alias enableStencilTest = stencilTest.enabled; /// 89 mixin glBoolProperty!(GL_TEXTURE_CUBE_MAP_SEAMLESS, "TextureCubeMapSeamless") textureCubeMapSeamless; 90 alias enableTextureCubeMapSeamless = textureCubeMapSeamless.enabled; /// 91 mixin glBoolProperty!(GL_PROGRAM_POINT_SIZE, "ProgramPointSize") programPointSize; 92 alias enableProgramPointSize = programPointSize.enabled; /// 93 94 /// Returns the current cull face mode. 95 static CullFaceMode cullFaceMode() 96 { 97 int mode; 98 glGetIntegerv(GL_CULL_FACE_MODE, &mode); 99 return cast(CullFaceMode) mode; 100 } 101 /// Sets the current cull face mode. 102 static CullFaceMode cullFaceMode(CullFaceMode val) 103 { 104 glCullFace(val); 105 return val; 106 } 107 108 /// Returns the direction of front faces. 109 static FrontFaceDirection frontFace() 110 { 111 int dir; 112 glGetIntegerv(GL_FRONT_FACE, &dir); 113 return cast(FrontFaceDirection) dir; 114 } 115 /// Changes the front face direction. 116 static FrontFaceDirection frontFace(FrontFaceDirection val) 117 { 118 glFrontFace(val); 119 return val; 120 } 121 122 /// Sets a callback for debug messages 123 static DebugMessageCallback debugMessageCallback(DebugMessageCallback cb) 124 { 125 void* param = wrapDebugCallback(cb); 126 glDebugMessageCallback(&debugMessageCallbackWrapper, param); 127 return cb; 128 } 129 130 /// Returns the current depth function. 131 static DepthFunction depthFunc() 132 { 133 int func; 134 glGetIntegerv(GL_DEPTH_FUNC, &func); 135 return cast(DepthFunction) func; 136 } 137 /// Changes the current depth function. 138 static DepthFunction depthFunc(DepthFunction val) 139 { 140 glDepthFunc(val); 141 return val; 142 } 143 144 /// Returns the current line width. 145 static float lineWidth() 146 { 147 float width; 148 glGetFloatv(GL_LINE_WIDTH, &width); 149 return width; 150 } 151 /// Changes the current line width. 152 static float lineWidth(float val) 153 { 154 glLineWidth(val); 155 return val; 156 } 157 158 /// Returns the primitive restart index. 159 static uint primitiveRestartIndex() 160 { 161 int index; 162 glGetIntegerv(GL_PRIMITIVE_RESTART_INDEX, &index); 163 return cast(uint) index; 164 } 165 /// Changes the primitive restart index. 166 static uint primitiveRestartIndex(uint val) 167 { 168 glPrimitiveRestartIndex(val); 169 return val; 170 } 171 172 /// Returns the minimum rate at which sample shading takes place. 173 static float minSampleShading() 174 { 175 float width; 176 glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE, &width); 177 return width; 178 } 179 /// Changes the minimum rate at which sample shading takes place. 180 static float minSampleShading(float val) 181 { 182 glMinSampleShading(val); 183 return val; 184 } 185 186 /// Returns the current point size. 187 static float pointSize() 188 { 189 float size; 190 glGetFloatv(GL_POINT_SIZE, &size); 191 return size; 192 } 193 /// Changes the current point size. 194 static float pointSize(float val) 195 { 196 glPointSize(val); 197 return val; 198 } 199 200 /// Returns the logical pixel operation for rendering. 201 static LogicOp logicOp() 202 { 203 int op; 204 glGetIntegerv(GL_LOGIC_OP_MODE, &op); 205 return cast(LogicOp) op; 206 } 207 /// Changes the logical pixel operation for rendering. 208 static LogicOp logicOp(LogicOp val) 209 { 210 glLogicOp(val); 211 return val; 212 } 213 } 214 215 nothrow 216 { 217 /// 218 static void blendFunc(BlendingFactor sfactor, BlendingFactor dfactor) 219 { 220 glBlendFunc(sfactor, dfactor); 221 } 222 /// 223 static void blendFunc(uint buf, BlendingFactor sfactor, BlendingFactor dfactor) 224 { 225 glBlendFunci(buf, sfactor, dfactor); 226 } 227 /// 228 static void blendFunc(BlendingFactor srcRGB, BlendingFactor dstRGB, 229 BlendingFactor srcAlpha, BlendingFactor dstAlpha) 230 { 231 glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); 232 } 233 /// 234 static void blendFunc(uint buf, BlendingFactor srcRGB, BlendingFactor dstRGB, 235 BlendingFactor srcAlpha, BlendingFactor dstAlpha) 236 { 237 glBlendFuncSeparatei(buf, srcRGB, dstRGB, srcAlpha, dstAlpha); 238 } 239 240 /// 241 static void depthRange(float nearVal, float farVal) 242 { 243 glDepthRangef(nearVal, farVal); 244 } 245 /// 246 static void depthRange(double nearVal, double farVal) 247 { 248 glDepthRange(nearVal, farVal); 249 } 250 251 /// 252 static void sampleCoverage(float value, bool invert) 253 { 254 glSampleCoverage(value, invert); 255 } 256 257 /// 258 static void polygonOffset(float factor, float units) 259 { 260 glPolygonOffset(factor, units); 261 } 262 263 /// 264 static void scissor(int x, int y, uint width, uint height) 265 { 266 glScissor(x, y, width, height); 267 } 268 /// 269 static void scissorIndexed(uint index, int left, int bottom, uint width, uint height) 270 { 271 glScissorIndexed(index, left, bottom, width, height); 272 } 273 /// 274 static void scissorIndexed(uint index, int[4] v) 275 { 276 glScissorIndexedv(index, v.ptr); 277 } 278 /// 279 static void scissorArray(uint index, int[4][] v) 280 { 281 glScissorArrayv(index, cast(GLsizei) v.length, cast(int*) v.ptr); 282 } 283 284 /// 285 static void polygonMode(MaterialFace face, PolygonMode mode) 286 { 287 glPolygonMode(face, mode); 288 } 289 290 /// 291 static void stencilFunc(StencilFunction func, int ref_, uint mask) 292 { 293 glStencilFunc(func, ref_, mask); 294 } 295 296 /// 297 static void stencilOp(StencilOp sfail, StencilOp dpfail, StencilOp dppass) 298 { 299 glStencilOp(sfail, dpfail, dppass); 300 } 301 302 /// 303 static void clear(ClearBufferMask mask) 304 { 305 glClear(mask); 306 } 307 308 /// 309 static void debugMessageInsert(DebugSource source, DebugType type, uint id, 310 DebugSeverity severity, string msg) 311 { 312 glDebugMessageInsert(source, type, id, severity, 313 cast(GLsizei) msg.length, cast(char*) msg.ptr); 314 } 315 } 316 } 317 318 alias BlendingFactor = BlendingFactorDest; 319 320 /// 321 enum DebugSeverity 322 { 323 /// for any GL error, dangerous undefined behaviour, or any shader compiler and linker errors 324 high = GL_DEBUG_SEVERITY_HIGH, 325 /// for severe performance warnings, GLSL or other shader compiler and linker warnings, and use of currently deprecated behaviour 326 medium = GL_DEBUG_SEVERITY_MEDIUM, 327 /// for performance warnings from redundant state changes and trivial undefined behaviour 328 low = GL_DEBUG_SEVERITY_LOW, 329 /// for any message which is not an error or performance concern 330 notification = GL_DEBUG_SEVERITY_NOTIFICATION 331 } 332 333 /// 334 enum DebugType 335 { 336 /// for events that generated an error 337 error = GL_DEBUG_TYPE_ERROR, 338 /// for behaviour that has been marked for deprecation 339 deprecatedBehavior = GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, 340 /// for behaviour that is undefined according to the specification 341 undefinedBehavior = GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, 342 /// for implementation-dependent performance warnings 343 performance = GL_DEBUG_TYPE_PERFORMANCE, 344 /// for the use of extensions or shaders in a way that is highly vendor-specific 345 portability = GL_DEBUG_TYPE_PORTABILITY, 346 /// for annotation of the command stream 347 marker = GL_DEBUG_TYPE_MARKER, 348 /// for entering a debug group with glPushDebugGroup 349 pushGroup = GL_DEBUG_TYPE_PUSH_GROUP, 350 /// for leaving a debug group with glPopDebugGroup 351 popGroup = GL_DEBUG_TYPE_POP_GROUP, 352 /// for events that don't fit any of the ones listed above 353 other = GL_DEBUG_TYPE_OTHER 354 } 355 356 /// 357 enum DebugSource 358 { 359 /// for messages generated by the GL 360 api = GL_DEBUG_SOURCE_API, 361 /// for messages generated by the GLSL shader compiler of compilers for other extension-provided languages 362 compiler = GL_DEBUG_SOURCE_SHADER_COMPILER, 363 /// for messages generated by the window system, such as WGL or GLX 364 windowSystem = GL_DEBUG_SOURCE_WINDOW_SYSTEM, 365 /// for messages generated by external debuggers or third-party middle-ware libraries 366 thirdParty = GL_DEBUG_SOURCE_THIRD_PARTY, 367 /// for messages generated by the application, such as through glDebugMessageInsert 368 application = GL_DEBUG_SOURCE_APPLICATION, 369 /// for messages that do not fit to any of the other sources 370 other = GL_DEBUG_SOURCE_OTHER 371 } 372 373 alias DebugMessageCallback = void delegate(DebugSource source, DebugType type, 374 GLuint id, DebugSeverity severity, string message); 375 376 private extern (C) void debugMessageCallbackWrapper(GLenum source, GLenum type, 377 GLuint id, GLenum severity, GLsizei length, const(GLchar)* message, void* userParam) 378 { 379 DebugMessageCallback cb = unwrapDebugCallback(userParam); 380 string msg = message[0 .. length].idup; 381 cb(cast(DebugSource) source, cast(DebugType) type, id, cast(DebugSeverity) severity, msg); 382 } 383 384 private struct CallbackWrapper 385 { 386 void* ctx; 387 void* fn; 388 } 389 390 private __gshared CallbackWrapper debugCallback; 391 392 private void* wrapDebugCallback(DebugMessageCallback cb) @nogc @system nothrow 393 { 394 debugCallback = CallbackWrapper(cb.ptr, cast(void*) cb.funcptr); 395 return cast(void*)&debugCallback; 396 } 397 398 private DebugMessageCallback unwrapDebugCallback(void* data) @nogc @system nothrow 399 { 400 CallbackWrapper wrap = *(cast(CallbackWrapper*) data); 401 DebugMessageCallback ret; 402 ret.ptr = wrap.ctx; 403 ret.funcptr = cast(typeof(ret.funcptr)) wrap.fn; 404 return ret; 405 }