1+ #pragma once
2+ #include < utility>
3+ #include < stdexcept>
4+
5+ #include " Bindable.hpp"
6+ #include " VertexBuffer.h"
7+
8+ #define GLDR_HAS_DSA
9+
10+ namespace gldr {
11+
12+ enum class VertexAttributeType : GLenum {
13+ Float = gl::FLOAT,
14+ HalfFloat = gl::HALF_FLOAT,
15+ Byte = gl::BYTE,
16+ Short = gl::SHORT,
17+ UShort = gl::UNSIGNED_SHORT,
18+ Int = gl::INT,
19+ UInt = gl::UNSIGNED_INT,
20+ UByte = gl::UNSIGNED_BYTE
21+ };
22+
23+ enum class VertexAttributeIntegerType : GLenum {
24+ Byte = gl::BYTE,
25+ Short = gl::SHORT,
26+ UShort = gl::UNSIGNED_SHORT,
27+ Int = gl::INT,
28+ UInt = gl::UNSIGNED_INT,
29+ UByte = gl::UNSIGNED_BYTE
30+ };
31+
32+ class VertexAttributeArray : public Bindable <VertexAttributeArray> {
33+
34+ public:
35+ // creation and destruction
36+ static GLuint create () {
37+ GLuint id = 0 ;
38+ gl::GenVertexArrays (1 , &id);
39+ if (!id)
40+ throw std::runtime_error (" Problem creating a vertex array" );
41+ return id;
42+ }
43+
44+ static void destroy (GLuint id) {
45+ gl::DeleteVertexArrays (1 , &id);
46+ }
47+
48+ static void bindObject (GLuint id) {
49+ gl::BindVertexArray (id);
50+ }
51+
52+ static GLuint getCurrentlyBound () {
53+ GLint current;
54+ gl::GetIntegerv (gl::VERTEX_ARRAY_BINDING, ¤t);
55+ return current;
56+ }
57+
58+ void directVertexAttribOffset (unsigned buffer, unsigned index, int size, VertexAttributeType type, bool normalized, unsigned stride, int offset) {
59+ #ifdef GLDR_HAS_DSA
60+ gl::VertexArrayVertexAttribOffsetEXT (id.get (), buffer, index, size, static_cast <GLenum>(type), normalized, stride, offset);
61+ #else
62+ auto vaoScope = scopedBind ();
63+ auto vboScope = VertexBuffer<VertexBufferType::ARRAY_BUFFER>::createRebindToCurrent ();
64+
65+ gl::BindBuffer (gl::ARRAY_BUFFER, buffer);
66+ gl::VertexAttribPointer (index, size, static_cast <GLenum>(type), normalized, stride, reinterpret_cast <void *>(offset));
67+ #endif
68+ }
69+
70+ void directVertexAttribIntegerOffset (unsigned buffer, unsigned index, int size, VertexAttributeIntegerType type, unsigned stride, int offset) {
71+ #ifdef GLDR_HAS_DSA
72+ gl::VertexArrayVertexAttribIOffsetEXT (id.get (), buffer, index, size, static_cast <GLenum>(type), stride, offset);
73+ #else
74+ auto vaoScope = scopedBind ();
75+ auto vboScope = VertexBuffer<VertexBufferType::ARRAY_BUFFER>::createRebindToCurrent ();
76+
77+ gl::BindBuffer (gl::ARRAY_BUFFER, buffer);
78+ gl::VertexAttribIPointer (index, size, static_cast <GLenum>(type), stride, reinterpret_cast <void *>(offset));
79+ #endif
80+ }
81+
82+ void VertexAttributeArray::enableAttributeArray (unsigned index) {
83+ #ifdef GLDR_HAS_DSA
84+ gl::EnableVertexArrayAttribEXT (id.get (), index);
85+ #else
86+ auto scope = scopedBind ();
87+ gl::EnableVertexAttribArray (index);
88+ #endif
89+ }
90+
91+ // static state queries
92+ // TODO: MAX_VERTEX_ATTRIB_BINDINGS is a part of buffer specification, not VAO?
93+ // Spec 4.3, 10.3.1-10.3.3
94+ // TODO: is this too much of utility?
95+ static unsigned getMaxVertexAttributes () {
96+ GLint count;
97+ gl::GetIntegerv (gl::MAX_VERTEX_ATTRIBS, &count);
98+ return count;
99+ }
100+ };
101+
102+ } // namespace gldr
0 commit comments