1 module polyplex.core.render.gl.gloo; 2 public import bindbc.opengl; 3 4 private __gshared Buffer[GLenum] boundBuffers; 5 private __gshared Texture[GLenum] boundTextures; 6 private __gshared Framebuffer[GLenum] boundFramebuffers; 7 private __gshared Sampler[GLenum] boundSamplers; 8 private __gshared Renderbuffer boundRenderbuffer; 9 private __gshared VertexArray boundVertexArray; 10 //private __gshared AsyncQuery[GLenum] boundAsyncQueries; 11 //private __gshared Pipeline[GLenum] boundPipelines; 12 //private __gshared TransformFeedback[GLenum] boundTransformFeedbacks; 13 14 public @nogc: 15 16 enum Capability : GLenum { 17 AlphaTesting = GL_ALPHA_TEST, 18 AutoNormal = GL_AUTO_NORMAL, 19 Blending = GL_BLEND, 20 ColorLogic = GL_COLOR_LOGIC_OP, 21 ColorMaterial = GL_COLOR_MATERIAL, 22 ColorSum = GL_COLOR_SUM, 23 ColorTable = GL_COLOR_TABLE, 24 Convolution1D = GL_CONVOLUTION_1D, 25 Convolution2D = GL_CONVOLUTION_2D, 26 CullFace = GL_CULL_FACE, 27 DepthTesting = GL_DEPTH_TEST, 28 Dithering = GL_DITHER, 29 Fog = GL_FOG, 30 Histogram = GL_HISTOGRAM, 31 IndexLogic = GL_INDEX_LOGIC_OP, 32 Lighting = GL_LIGHTING, 33 LineSmooth = GL_LINE_SMOOTH, 34 LineStipple = GL_LINE_STIPPLE, 35 // TODO: Add a bunch of GL_MAP stuff 36 37 MinMax = GL_MINMAX, 38 Multisample = GL_MULTISAMPLE, 39 Normalize = GL_NORMALIZE, 40 PointSmooth = GL_POINT_SMOOTH, 41 PointSprite = GL_POINT_SPRITE, 42 PolygonOffsetFill = GL_POLYGON_OFFSET_FILL, 43 PolygonOffsetLine = GL_POLYGON_OFFSET_LINE, 44 PolygonOffsetPoint = GL_POLYGON_OFFSET_POINT, 45 PolygonSmooth = GL_POLYGON_SMOOTH, 46 PolygonStipple = GL_POLYGON_STIPPLE, 47 48 ScissorTest = GL_SCISSOR_TEST, 49 StencilTest = GL_STENCIL_TEST 50 51 } 52 /** 53 Functions for OpenGL not attached to an object. 54 */ 55 class GL { 56 public: 57 enum : GLenum { 58 59 // Filters 60 Nearest = GL_NEAREST, 61 NearestMipmapNearest = GL_NEAREST_MIPMAP_NEAREST, 62 NearestMipmapLinear = GL_NEAREST_MIPMAP_LINEAR, 63 Linear = GL_LINEAR, 64 LinearMipmapNearest = GL_LINEAR_MIPMAP_NEAREST, 65 LinearMipmapLinear = GL_LINEAR_MIPMAP_LINEAR, 66 67 // Swizzle 68 Red = GL_RED, 69 Green = GL_GREEN, 70 Blue = GL_BLUE, 71 Alpha = GL_ALPHA, 72 73 // Wrap 74 ClampToEdge = GL_CLAMP_TO_EDGE, 75 ClampToBorder = GL_CLAMP_TO_BORDER, 76 MirroredRepeat = GL_MIRRORED_REPEAT, 77 Repeat = GL_REPEAT, 78 79 // Draw modes 80 Points = GL_POINTS, 81 LineStrip = GL_LINE_STRIP, 82 LineLoop = GL_LINE_LOOP, 83 Lines = GL_LINES, 84 LineStripAdjacency = GL_LINE_STRIP_ADJACENCY, 85 LinesAdjacency = GL_LINES_ADJACENCY, 86 TriangleStrip = GL_TRIANGLE_STRIP, 87 TriangleFan = GL_TRIANGLE_FAN, 88 Triangles = GL_TRIANGLES, 89 TriangleStripAdjacency = GL_TRIANGLE_STRIP_ADJACENCY, 90 TrianglesAdjacency = GL_TRIANGLES_ADJACENCY 91 92 } 93 94 95 static: 96 /** 97 Enables an OpenGL capability. 98 */ 99 void Enable(Capability cap) { 100 glEnable(cap); 101 } 102 103 /** 104 Disables an OpenGL capability 105 */ 106 void Disable(Capability cap) { 107 glDisable(cap); 108 } 109 110 void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) { 111 glViewport(x, y, width, height); 112 } 113 114 void DrawArrays(GLenum mode, GLint first, GLsizei count) { 115 glDrawArrays(mode, first, count); 116 } 117 118 /// 119 void SetTextureParameter(GLenum target, GLenum pname, GLint param) { 120 glTexParameteri(target, pname, param); 121 } 122 123 /// 124 void SetTextureParameter(GLenum target, GLenum pname, GLfloat param) { 125 glTexParameterf(target, pname, param); 126 } 127 128 /// 129 void SetTextureParameter(GLenum target, GLenum pname, GLint* param) { 130 glTexParameteriv(target, pname, param); 131 } 132 133 /// 134 void SetTextureParameter(GLenum target, GLenum pname, GLfloat* param) { 135 glTexParameterfv(target, pname, param); 136 } 137 138 /// 139 void SetTextureParameter(GLenum target, GLenum pname, const(GLint)* param) { 140 glTexParameterIiv(target, pname, param); 141 } 142 143 /// 144 void SetTextureParameter(GLenum target, GLenum pname, const(GLuint)* param) { 145 glTexParameterIuiv(target, pname, param); 146 } 147 148 /// 149 void BufferSubData(GLenum target, ptrdiff_t offset, ptrdiff_t size, void* data) { 150 glBufferSubData(target, offset, size, data); 151 } 152 153 /// 154 void BufferData(GLenum target, ptrdiff_t size, void* data, GLenum usage) { 155 glBufferData(target, size, data, usage); 156 } 157 158 /+ 159 Activating 160 +/ 161 162 void ActiveTexture(GLenum texture) { 163 glActiveTexture(texture); 164 } 165 166 /+ 167 Drawing 168 +/ 169 170 void DrawBuffers(GLsizei count, const(GLenum)* buffers) { 171 glDrawBuffers(count, buffers); 172 } 173 174 /+ 175 Binding 176 +/ 177 178 void BindBuffer(GLenum target, GLuint id) { 179 glBindBuffer(target, id); 180 } 181 182 void BindFramebuffer(GLenum target, GLuint id) { 183 glBindFramebuffer(target, id); 184 } 185 186 void BindRenderbuffer(GLenum target, GLuint id) { 187 glBindRenderbuffer(target, id); 188 } 189 190 void BindTexture(GLenum target, GLuint id) { 191 glBindTexture(target, id); 192 } 193 194 void BindVertexArray(GLuint id) { 195 glBindVertexArray(id); 196 } 197 } 198 199 200 enum ObjectClass { 201 Anything, 202 Data, 203 Texture 204 } 205 206 abstract class GLObject { 207 private: 208 GLuint id; 209 public: 210 GLuint Id() { 211 return id; 212 } 213 214 /// Binds the object with default type 215 abstract void Bind(); 216 217 /// Binds the object 218 abstract void Bind(GLenum target); 219 220 /// Unbinds the object 221 abstract void Unbind(); 222 } 223 224 /* 225 ------ BUFFERS ------ 226 */ 227 228 enum BufferUsage : GLenum { 229 StreamDraw = GL_STREAM_DRAW, 230 StreamRead = GL_STREAM_READ, 231 StreamCopy = GL_STREAM_COPY, 232 StaticDraw = GL_STATIC_DRAW, 233 StaticRead = GL_STATIC_READ, 234 StaticCopy = GL_STATIC_COPY, 235 DynamicDraw = GL_DYNAMIC_DRAW, 236 DynamicRead = GL_DYNAMIC_READ, 237 DynamicCopy = GL_DYNAMIC_COPY, 238 } 239 240 enum BufferType : GLenum { 241 /// Vertex Attributes 242 Vertex = GL_ARRAY_BUFFER, 243 244 /// Buffer Copy Source 245 CopyRead = GL_COPY_READ_BUFFER, 246 247 /// Buffer Copy Destination 248 CopyWrite = GL_COPY_WRITE_BUFFER, 249 250 /// Vertex Array Indices 251 ElementAray = GL_ELEMENT_ARRAY_BUFFER, 252 253 /// Pixel Read Target 254 PixelPack = GL_PIXEL_PACK_BUFFER, 255 256 /// Texture Data Source 257 PixelUnpack = GL_PIXEL_UNPACK_BUFFER, 258 259 /// Texture Data Buffer 260 Texture = GL_TEXTURE_BUFFER, 261 262 /// Uniform Block Storage 263 Uniform = GL_UNIFORM_BUFFER 264 } 265 266 class Buffer : GLObject { 267 private: 268 GLenum boundTarget; 269 270 public: 271 this() { 272 glGenBuffers(1, &id); 273 } 274 275 ~this() { 276 glDeleteBuffers(1, &id); 277 } 278 279 /// Binds the buffer with default type 280 override void Bind() { 281 Bind(BufferType.Vertex); 282 } 283 284 /// Binds the buffer 285 override void Bind(GLenum target) { 286 // We're already bound there, bail out. 287 if (target in boundBuffers && 288 boundBuffers[target] !is null && 289 boundBuffers[target].id == id) return; 290 291 // Unbind from old position if needed. 292 if (boundTarget != 0) Unbind(); 293 294 // Bind to new position. 295 boundTarget = target; 296 boundBuffers[boundTarget] = this; 297 GL.BindBuffer(target, id); 298 } 299 300 /// Unbinds the buffer (binds buffer 0) 301 override void Unbind() { 302 /// Skip unbinding if not bound in the first place. 303 if (boundTarget == 0) return; 304 305 /// If another buffer is bound there, bail out. 306 if (boundBuffers[boundTarget].id != id) return; 307 308 /// Unbind target. 309 GL.BindBuffer(boundTarget, 0); 310 boundBuffers[boundTarget] = null; 311 boundTarget = 0; 312 } 313 314 /// 315 void Data(ptrdiff_t size, void* data, GLenum usage) { 316 if (boundTarget == 0) return; 317 GL.BufferData(boundTarget, size, data, usage); 318 } 319 320 /// 321 void SubData(ptrdiff_t offset, ptrdiff_t size, void* data) { 322 if (boundTarget == 0) return; 323 GL.BufferSubData(boundTarget, offset, size, data); 324 } 325 326 /* 327 /// glBufferStorage. 328 void BufferStorage(GLenum target, ptrdiff_t size, void* data, GLbitfield flags) { 329 Bind(target); 330 glBufferStorage(target, size, data, flags); 331 } 332 333 /// Clear buffer data. 334 void ClearBufferData(GLenum target, GLenum internalFormat, GLenum format, GLenum type, void* data) { 335 Bind(target); 336 glClearBufferData(target, internalFormat, format, type, data); 337 } 338 339 /// Clear buffer sub data. 340 void ClearBufferSubData(GLenum target, GLenum internalFormat, ptrdiff_t offset, ptrdiff_t size, GLenum format, GLenum type, void* data) { 341 Bind(target); 342 glClearBufferSubData(target, internalFormat, offset, size, format, type, data); 343 } 344 345 /*void CopyBufferSubData(GLenum readtarget, GLenum writetarget, ptrdiff_t readoffset, ptrdiff_t writeoffset, ptrdiff_t size) { 346 Bind(readtarget); 347 CopyBufferSubData(readtarget, writetarget, readoffset, writeoffset, size); 348 }*/ 349 } 350 351 352 353 /* 354 ------ TEXTURES ------ 355 */ 356 357 enum TextureType : GLenum { 358 /// 1D Texture 359 Tex1D = GL_TEXTURE_1D, 360 361 /// 2D Texture 362 Tex2D = GL_TEXTURE_2D, 363 364 /// 3D Texture 365 Tex3D = GL_TEXTURE_3D, 366 367 /// Array of 1D Textures 368 Tex1DArray = GL_TEXTURE_1D_ARRAY, 369 370 /// Array of 2D Textures 371 Tex2DArray = GL_TEXTURE_2D_ARRAY, 372 373 /// Rectangle Texture 374 TexRectangle = GL_TEXTURE_RECTANGLE, 375 376 /// Cube Map 377 TexCubeMap = GL_TEXTURE_CUBE_MAP, 378 379 /// Buffer 380 TexBuffer = GL_TEXTURE_BUFFER, 381 382 /// Multisampled 2D Texture 383 Tex2DMultisample = GL_TEXTURE_2D_MULTISAMPLE, 384 385 /// Array of Multisampled 2D Textures 386 Tex2DMultisampleArray = GL_TEXTURE_2D_MULTISAMPLE_ARRAY 387 } 388 389 enum TextureParameter : GLenum { 390 391 /// 392 BaseLevel = GL_TEXTURE_BASE_LEVEL, 393 394 /// 395 CompareFunc = GL_TEXTURE_COMPARE_FUNC, 396 397 /// 398 CompareMode = GL_TEXTURE_COMPARE_MODE, 399 400 /// 401 LODBias = GL_TEXTURE_LOD_BIAS, 402 403 /// 404 MinFilter = GL_TEXTURE_MIN_FILTER, 405 406 /// 407 MagFilter = GL_TEXTURE_MAG_FILTER, 408 409 /// 410 MinLOD = GL_TEXTURE_MIN_LOD, 411 412 /// 413 MaxLOD = GL_TEXTURE_MAX_LOD, 414 415 /// 416 MaxLevel = GL_TEXTURE_MAX_LEVEL, 417 418 /// 419 SwizzleR = GL_TEXTURE_SWIZZLE_R, 420 421 /// 422 SwizzleG = GL_TEXTURE_SWIZZLE_G, 423 424 /// 425 SwizzleB = GL_TEXTURE_SWIZZLE_B, 426 427 /// 428 SwizzleA = GL_TEXTURE_SWIZZLE_A, 429 430 /// 431 WrapS = GL_TEXTURE_WRAP_S, 432 433 /// 434 WrapT = GL_TEXTURE_WRAP_T, 435 436 /// 437 WrapR = GL_TEXTURE_WRAP_R 438 } 439 440 class Texture : GLObject { 441 private: 442 GLenum boundTarget; 443 444 public: 445 this() { 446 glGenTextures(1, &id); 447 } 448 449 ~this() { 450 glDeleteTextures(1, &id); 451 } 452 453 /// Binds the texture with default type 454 override void Bind() { 455 Bind(TextureType.Tex2D); 456 } 457 458 /// Binds the texture 459 override void Bind(GLenum target) { 460 // We're already bound there, bail out. 461 if (target in boundTextures && 462 boundTextures[target] !is null && 463 boundTextures[target].id == id) return; 464 465 // Unbind from old position if needed. 466 if (boundTarget != 0) Unbind(); 467 468 // Bind to new position. 469 boundTarget = target; 470 boundTextures[boundTarget] = this; 471 GL.BindTexture(target, id); 472 } 473 474 /// Unbinds the texture (binds texture 0) 475 override void Unbind() { 476 /// Skip unbinding if not bound in the first place. 477 if (boundTarget == 0) return; 478 479 /// If another texture is bound there, bail out. 480 if (boundTarget in boundTextures && boundTextures[boundTarget] !is null && boundTextures[boundTarget].id != id) return; 481 482 /// Unbind target. 483 GL.BindTexture(boundTarget, 0); 484 boundTextures[boundTarget] = null; 485 boundTarget = 0; 486 } 487 488 /// 489 void AttachTo(GLenum textureid) { 490 GL.ActiveTexture(GL_TEXTURE0+textureid); 491 } 492 493 /// 494 void SetParameter(GLenum target, GLenum pname, GLint param) { 495 Bind(target); 496 GL.SetTextureParameter(target, pname, param); 497 } 498 499 /// 500 void SetParameter(GLenum target, GLenum pname, GLfloat param) { 501 Bind(target); 502 GL.SetTextureParameter(target, pname, param); 503 } 504 505 /// 506 void SetParameter(GLenum target, GLenum pname, GLint* param) { 507 Bind(target); 508 GL.SetTextureParameter(target, pname, param); 509 } 510 511 /// 512 void SetParameter(GLenum target, GLenum pname, GLfloat* param) { 513 Bind(target); 514 GL.SetTextureParameter(target, pname, param); 515 } 516 517 /// 518 void SetParameter(GLenum target, GLenum pname, const(GLint)* param) { 519 Bind(target); 520 GL.SetTextureParameter(target, pname, param); 521 } 522 523 /// 524 void SetParameter(GLenum target, GLenum pname, const(GLuint)* param) { 525 Bind(target); 526 GL.SetTextureParameter(target, pname, param); 527 } 528 529 /// 530 void Image1D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const(GLvoid)* data) { 531 glTexImage1D(target, level, internalFormat, width, border, format, type, data); 532 } 533 534 /// 535 void Image2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const(GLvoid)* data) { 536 glTexImage2D(target, level, internalFormat, width, height, border, format, type, data); 537 } 538 539 /// 540 void Image2DMultisample(GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations) { 541 glTexImage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations); 542 } 543 544 /// 545 void Image3D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const(GLvoid)* data) { 546 glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, data); 547 } 548 549 /// 550 void Image3DMultisample(GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations) { 551 glTexImage3DMultisample(target, samples, internalFormat, width, height, depth, fixedSampleLocations); 552 } 553 } 554 555 556 /* 557 ------ FRAMEBUFFERS ------ 558 */ 559 560 enum FramebufferType : GLenum { 561 /// A framebuffer which does multiple operations 562 Multi = GL_FRAMEBUFFER, 563 564 /// Framebuffer that can be drawn to 565 Drawing = GL_DRAW_FRAMEBUFFER, 566 567 /// Framebuffer that can be read from. 568 Reading = GL_READ_FRAMEBUFFER 569 } 570 571 class Framebuffer : GLObject { 572 private: 573 GLenum boundTarget; 574 575 public: 576 this() { 577 glGenFramebuffers(1, &id); 578 } 579 580 ~this() { 581 glDeleteFramebuffers(1, &id); 582 } 583 584 /// Binds the framebuffer with default type 585 override void Bind() { 586 Bind(FramebufferType.Multi); 587 } 588 589 /// Binds the framebuffer 590 override void Bind(GLenum target) { 591 // We're already bound there, bail out. 592 if (target in boundFramebuffers && 593 boundFramebuffers[target] !is null && 594 boundFramebuffers[target].id == id) return; 595 596 // Unbind from old position if needed. 597 if (boundTarget != 0) Unbind(); 598 599 // Bind to new position. 600 boundTarget = target; 601 boundFramebuffers[boundTarget] = this; 602 GL.BindFramebuffer(target, id); 603 } 604 605 /// Unbinds the framebuffer (binds framebuffer 0) 606 override void Unbind() { 607 /// Skip unbinding if not bound in the first place. 608 if (boundTarget == 0) return; 609 610 /// If another framebuffer is bound there, bail out. 611 if (boundFramebuffers[boundTarget].id != id) return; 612 613 /// Unbind target. 614 GL.BindFramebuffer(boundTarget, 0); 615 boundFramebuffers[boundTarget] = null; 616 boundTarget = 0; 617 } 618 619 /// 620 void Renderbuffer(GLenum target, GLenum attachment, GLenum source, GLuint buffer) { 621 Bind(target); 622 glFramebufferRenderbuffer(target, attachment, source, buffer); 623 } 624 625 /// 626 void Texture(GLenum target, GLenum attachment, GLuint texture, GLint level) { 627 Bind(target); 628 glFramebufferTexture(target, attachment, texture, level); 629 } 630 631 /// 632 void Texture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { 633 Bind(target); 634 glFramebufferTexture1D(target, attachment, textarget, texture, level); 635 } 636 637 /// 638 void Texture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { 639 Bind(target); 640 glFramebufferTexture2D(target, attachment, textarget, texture, level); 641 } 642 643 /// 644 void Texture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer) { 645 Bind(target); 646 glFramebufferTexture3D(target, attachment, textarget, texture, level, layer); 647 } 648 649 /// 650 void TextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) { 651 Bind(target); 652 glFramebufferTextureLayer(target, attachment, texture, level, layer); 653 } 654 } 655 656 /* 657 ------ RENDERBUFFERS ------ 658 */ 659 660 class Renderbuffer : GLObject { 661 public: 662 this() { 663 glGenRenderbuffers(1, &id); 664 } 665 666 ~this() { 667 glDeleteRenderbuffers(1, &id); 668 } 669 670 /// Binds the renderbuffer with default type 671 override void Bind() { 672 Bind(0); 673 } 674 675 /// Binds the renderbuffer 676 override void Bind(GLenum target) { 677 // We're already bound there, bail out. 678 if (boundRenderbuffer is this) return; 679 680 // Bind to new position. 681 boundRenderbuffer = this; 682 GL.BindRenderbuffer(GL_RENDERBUFFER, id); 683 } 684 685 /// Unbinds the renderbuffer (binds renderbuffer 0) 686 override void Unbind() { 687 /// Skip unbinding if not bound in the first place. 688 if (boundRenderbuffer is null) return; 689 690 /// If another renderbuffer is bound there, bail out. 691 if (boundRenderbuffer !is this) return; 692 693 /// Unbind target. 694 GL.BindRenderbuffer(GL_RENDERBUFFER, 0); 695 boundRenderbuffer = null; 696 } 697 698 /// 699 void Storage(GLenum internalFormat, GLsizei width, GLsizei height) { 700 glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height); 701 } 702 703 /// 704 void StorageMultisample(GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height) { 705 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalFormat, width, height); 706 } 707 } 708 709 710 /* 711 ------ VERTEX ARRAYS ------ 712 */ 713 714 class VertexArray : GLObject { 715 public: 716 this() { 717 glGenVertexArrays(1, &id); 718 } 719 720 ~this() { 721 glDeleteVertexArrays(1, &id); 722 } 723 724 /// Binds the vertex array 725 override void Bind() { 726 Bind(0); 727 } 728 729 /// Binds the vertex array 730 override void Bind(GLenum target) { 731 // We're already bound there, bail out. 732 if (boundVertexArray is this) return; 733 734 // Bind to new position. 735 boundVertexArray = this; 736 GL.BindVertexArray(id); 737 } 738 739 /// Unbinds the vertex array (binds vertex array 0) 740 override void Unbind() { 741 /// If another vertex array is bound there, bail out. 742 if (boundVertexArray !is this) return; 743 744 /// Unbind target. 745 GL.BindVertexArray(0); 746 boundVertexArray = null; 747 } 748 749 void EnableArray(GLuint index) { 750 glEnableVertexAttribArray(index); 751 } 752 753 void DisableArray(GLuint index) { 754 glDisableVertexAttribArray(index); 755 } 756 757 void AttribPointer(GLuint attribute, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const(GLvoid)* offset) { 758 glVertexAttribPointer(attribute, size, type, normalized, stride, offset); 759 } 760 761 void AttribIPointer(GLuint attribute, GLint size, GLenum type, GLsizei stride, const(GLvoid)* offset) { 762 glVertexAttribIPointer(attribute, size, type, stride, offset); 763 } 764 } 765 766 // TODO: Implement features from this. 767 768 class Sampler : GLObject { 769 private: 770 GLuint id; 771 GLenum boundTarget; 772 773 public: 774 this() { 775 glGenSamplers(1, &id); 776 } 777 778 /// Binds the sampler 779 override void Bind(GLenum target) { 780 // We're already bound there, bail out. 781 if (boundSamplers[target].id == id) return; 782 783 // Unbind from old position if needed. 784 if (boundTarget != 0) Unbind(); 785 786 // Bind to new position. 787 boundTarget = target; 788 boundSamplers[boundTarget] = this; 789 glBindSampler(target, id); 790 } 791 792 /// Unbinds the sampler (binds sampler 0) 793 override void Unbind() { 794 /// Skip unbinding if not bound in the first place. 795 if (boundTarget == 0) return; 796 797 /// If another sampler is bound there, bail out. 798 if (boundSamplers[boundTarget].id != id) return; 799 800 /// Unbind target. 801 glBindSampler(boundTarget, 0); 802 boundSamplers[boundTarget] = null; 803 boundTarget = 0; 804 } 805 } 806 807 // TODO: Implement these 808 /* 809 class AsyncQuery : GLObject { 810 private: 811 GLuint id; 812 GLenum boundTarget; 813 814 public: 815 this() { 816 glGenQueries(1, &id); 817 } 818 } 819 820 class Pipeline : GLObject { 821 private: 822 GLuint id; 823 GLenum boundTarget; 824 825 public: 826 this() { 827 glGenProgramPipelines(1, &id); 828 } 829 } 830 831 class TransformFeedback : GLObject { 832 private: 833 GLuint id; 834 GLenum boundTarget; 835 836 public: 837 this() { 838 glGenTransformFeedbacks(1, &id); 839 } 840 }*/