From 1aebe8af0314c4da7cd6bd01bae13cc34dde102c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Kapu=C5=9Bci=C5=84ski?= Date: Fri, 24 Oct 2014 00:29:26 +0200 Subject: Added support for VBO in OpenGL older than 1.5 if ARB extension is present --- src/graphics/opengl/gldevice.cpp | 146 ++++++++++++++++++++++++++++++--------- src/graphics/opengl/gldevice.h | 14 ++++ 2 files changed, 129 insertions(+), 31 deletions(-) diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 0ae6f88..032fa24 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -68,6 +68,7 @@ CGLDevice::CGLDevice(const GLDeviceConfig &config) m_lastVboId = 0; m_multitextureAvailable = false; m_vboAvailable = false; + m_vertexBufferType = VBT_DISPLAY_LIST; } @@ -207,12 +208,12 @@ bool CGLDevice::Create() if (m_config.vboMode == VBO_MODE_ENABLE) { GetLogger()->Info("VBO enabled by override - using VBOs\n"); - m_vboAvailable = true; + SetVertexBufferType(VBT_VBO_CORE); } else if (m_config.vboMode == VBO_MODE_DISABLE) { GetLogger()->Info("VBO disabled by override - using display lists\n"); - m_vboAvailable = false; + SetVertexBufferType(VBT_DISPLAY_LIST); } else { @@ -223,18 +224,26 @@ bool CGLDevice::Create() int major = 0, minor = 0; sscanf(version, "%d.%d", &major, &minor); + + // detecting VBO ARB extension + bool vboARB = glewIsSupported("GL_ARB_vertex_buffer_object"); // VBO is core OpenGL feature since 1.5 // everything below 1.5 means no VBO support if(major > 1 || minor > 4) { GetLogger()->Info("OpenGL %d.%d, VBO supported\n", major, minor); - m_vboAvailable = true; + SetVertexBufferType(VBT_VBO_CORE); } - else + else if(vboARB) // VBO ARB extension available + { + GetLogger()->Info("OpenGL %d.%d with GL_ARB_vertex_buffer_object, VBO supported\n", major, minor); + SetVertexBufferType(VBT_VBO_ARB); + } + else // no VBO support { - GetLogger()->Info("OpenGL %d.%d, VBO not supported\n", major, minor); - m_vboAvailable = false; + GetLogger()->Info("OpenGL %d.%d without GL_ARB_vertex_buffer_object, VBO not supported\n", major, minor); + SetVertexBufferType(VBT_DISPLAY_LIST); } } } @@ -304,6 +313,13 @@ void CGLDevice::ConfigChanged(const GLDeviceConfig& newConfig) void CGLDevice::SetUseVbo(bool vboAvailable) { m_vboAvailable = vboAvailable; + m_vertexBufferType = vboAvailable ? VBT_VBO_CORE : VBT_DISPLAY_LIST; +} + +void CGLDevice::SetVertexBufferType(VertexBufferType type) +{ + m_vertexBufferType = type; + m_vboAvailable = (type != VBT_DISPLAY_LIST); } void CGLDevice::BeginScene() @@ -1046,10 +1062,20 @@ unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Ve info.vertexCount = vertexCount; info.bufferId = 0; - glGenBuffers(1, &info.bufferId); - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + { + glGenBuffers(1, &info.bufferId); + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glGenBuffersARB(1, &info.bufferId); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } m_vboObjects[id] = info; } @@ -1080,10 +1106,20 @@ unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Ve info.vertexCount = vertexCount; info.bufferId = 0; - glGenBuffers(1, &info.bufferId); - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + { + glGenBuffers(1, &info.bufferId); + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glGenBuffersARB(1, &info.bufferId); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } m_vboObjects[id] = info; } @@ -1113,11 +1149,21 @@ unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Ve info.vertexType = VERTEX_TYPE_COL; info.vertexCount = vertexCount; info.bufferId = 0; - - glGenBuffers(1, &info.bufferId); - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + + if(m_vertexBufferType == VBT_VBO_CORE) + { + glGenBuffers(1, &info.bufferId); + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glGenBuffersARB(1, &info.bufferId); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } m_vboObjects[id] = info; } @@ -1148,9 +1194,18 @@ void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiv info.vertexType = VERTEX_TYPE_NORMAL; info.vertexCount = vertexCount; - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + { + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } } else { @@ -1175,9 +1230,18 @@ void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiv info.vertexType = VERTEX_TYPE_TEX2; info.vertexCount = vertexCount; - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + { + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } } else { @@ -1202,9 +1266,18 @@ void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiv info.vertexType = VERTEX_TYPE_COL; info.vertexCount = vertexCount; - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + { + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } } else { @@ -1225,7 +1298,11 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) return; glEnable(GL_VERTEX_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, (*it).second.bufferId); + + if(m_vertexBufferType == VBT_VBO_CORE) + glBindBuffer(GL_ARRAY_BUFFER, (*it).second.bufferId); + else + glBindBufferARB(GL_ARRAY_BUFFER_ARB, (*it).second.bufferId); if ((*it).second.vertexType == VERTEX_TYPE_NORMAL) { @@ -1297,7 +1374,11 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) glDisableClientState(GL_COLOR_ARRAY); } - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + glBindBuffer(GL_ARRAY_BUFFER, 0); + else + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + glDisable(GL_VERTEX_ARRAY); } else @@ -1314,7 +1395,10 @@ void CGLDevice::DestroyStaticBuffer(unsigned int bufferId) if (it == m_vboObjects.end()) return; - glDeleteBuffers(1, &(*it).second.bufferId); + if(m_vertexBufferType == VBT_VBO_CORE) + glDeleteBuffers(1, &(*it).second.bufferId); + else + glDeleteBuffersARB(1, &(*it).second.bufferId); m_vboObjects.erase(it); } diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index 723b0f2..1174367 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -47,6 +47,17 @@ enum VBOMode VBO_MODE_AUTO //! < autodetect }; +/** + \enum VertexBufferType + \brief Specifies type of vertex buffer to use + */ +enum VertexBufferType +{ + VBT_DISPLAY_LIST, //! use display lists + VBT_VBO_CORE, //! use core OpenGL 1.5 VBOs + VBT_VBO_ARB //! use ARB extension VBOs +}; + /** \struct GLDeviceConfig \brief Additional config with OpenGL-specific settings */ @@ -104,6 +115,7 @@ public: void ConfigChanged(const GLDeviceConfig &newConfig); void SetUseVbo(bool useVbo); + void SetVertexBufferType(VertexBufferType type); virtual void BeginScene() override; virtual void EndScene() override; @@ -235,6 +247,8 @@ private: bool m_multitextureAvailable; //! Whether to use VBOs or display lists bool m_vboAvailable; + //! Which vertex buffer type to use + VertexBufferType m_vertexBufferType; //! Map of saved VBO objects std::map m_vboObjects; //! Last ID of VBO object -- cgit v1.2.3-1-g7c22