diff options
-rw-r--r-- | src/video/opengl.cpp | 62 | ||||
-rw-r--r-- | src/video/opengl.h | 1 |
2 files changed, 58 insertions, 5 deletions
diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index 7fc9c33b0..ff4689b94 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -34,6 +34,19 @@ static PFNGLDEBUGMESSAGECONTROLPROC _glDebugMessageControl; static PFNGLDEBUGMESSAGECALLBACKPROC _glDebugMessageCallback; +static PFNGLGENBUFFERSPROC _glGenBuffers; +static PFNGLDELETEBUFFERSPROC _glDeleteBuffers; +static PFNGLBINDBUFFERPROC _glBindBuffer; +static PFNGLBUFFERDATAPROC _glBufferData; +static PFNGLMAPBUFFERPROC _glMapBuffer; +static PFNGLUNMAPBUFFERPROC _glUnmapBuffer; + +/** A simple 2D vertex with just position and texture. */ +struct Simple2DVertex { + float x, y; + float u, v; +}; + /* static */ OpenGLBackend *OpenGLBackend::instance = nullptr; GetOGLProcAddressProc GetOGLProcAddress; @@ -113,6 +126,28 @@ bool IsOpenGLVersionAtLeast(byte major, byte minor) return (_gl_major_ver > major) || (_gl_major_ver == major && _gl_minor_ver >= minor); } +/** Bind vertex buffer object extension functions. */ +static bool BindVBOExtension() +{ + if (IsOpenGLVersionAtLeast(1, 5)) { + _glGenBuffers = (PFNGLGENBUFFERSPROC)GetOGLProcAddress("glGenBuffers"); + _glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)GetOGLProcAddress("glDeleteBuffers"); + _glBindBuffer = (PFNGLBINDBUFFERPROC)GetOGLProcAddress("glBindBuffer"); + _glBufferData = (PFNGLBUFFERDATAPROC)GetOGLProcAddress("glBufferData"); + _glMapBuffer = (PFNGLMAPBUFFERPROC)GetOGLProcAddress("glMapBuffer"); + _glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)GetOGLProcAddress("glUnmapBuffer"); + } else { + _glGenBuffers = (PFNGLGENBUFFERSPROC)GetOGLProcAddress("glGenBuffersARB"); + _glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)GetOGLProcAddress("glDeleteBuffersARB"); + _glBindBuffer = (PFNGLBINDBUFFERPROC)GetOGLProcAddress("glBindBufferARB"); + _glBufferData = (PFNGLBUFFERDATAPROC)GetOGLProcAddress("glBufferDataARB"); + _glMapBuffer = (PFNGLMAPBUFFERPROC)GetOGLProcAddress("glMapBufferARB"); + _glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)GetOGLProcAddress("glUnmapBufferARB"); + } + + return _glGenBuffers != nullptr && _glDeleteBuffers != nullptr && _glBindBuffer != nullptr && _glBufferData != nullptr && _glMapBuffer != nullptr && _glUnmapBuffer != nullptr; +} + /** Callback to receive OpenGL debug messages. */ void APIENTRY DebugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam) { @@ -203,6 +238,9 @@ OpenGLBackend::OpenGLBackend() */ OpenGLBackend::~OpenGLBackend() { + if (_glDeleteBuffers != nullptr) { + _glDeleteBuffers(1, &this->vbo_quad); + } glDeleteTextures(1, &this->vid_texture); free(this->vid_buffer); } @@ -232,6 +270,9 @@ const char *OpenGLBackend::Init() if (!IsOpenGLVersionAtLeast(1, 3)) return "OpenGL version >= 1.3 required"; /* Check for non-power-of-two texture support. */ if (!IsOpenGLVersionAtLeast(2, 0) && !IsOpenGLExtensionSupported("GL_ARB_texture_non_power_of_two")) return "Non-power-of-two textures not supported"; + /* Check for vertex buffer objects. */ + if (!IsOpenGLVersionAtLeast(1, 5) && !IsOpenGLExtensionSupported("ARB_vertex_buffer_object")) return "Vertex buffer objects not supported"; + if (!BindVBOExtension()) return "Failed to bind VBO extension functions"; /* Setup video buffer texture. */ glGenTextures(1, &this->vid_texture); @@ -244,12 +285,20 @@ const char *OpenGLBackend::Init() glBindTexture(GL_TEXTURE_2D, 0); if (glGetError() != GL_NO_ERROR) return "Can't generate video buffer texture"; - /* Prime vertex array with a full-screen quad. */ - static const float vert_array[] = { 1.f, -1.f, 1.f, 1.f, -1.f, -1.f, -1.f, 1.f }; - static const float tex_array[] = { 1.f, 1.f, 1.f, 0.f, 0.f, 1.f, 0.f, 0.f }; + /* Prime vertex buffer with a full-screen quad. */ + static const Simple2DVertex vert_array[] = { + // x y u v + { 1.f, -1.f, 1.f, 1.f }, + { 1.f, 1.f, 1.f, 0.f }, + { -1.f, -1.f, 0.f, 1.f }, + { -1.f, 1.f, 0.f, 0.f }, + }; + + _glGenBuffers(1, &this->vbo_quad); + _glBindBuffer(GL_ARRAY_BUFFER, this->vbo_quad); + _glBufferData(GL_ARRAY_BUFFER, sizeof(vert_array), vert_array, GL_STATIC_DRAW); + if (glGetError() != GL_NO_ERROR) return "Can't generate VBO for fullscreen quad"; - glVertexPointer(2, GL_FLOAT, 0, vert_array); - glTexCoordPointer(2, GL_FLOAT, 0, tex_array); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -309,6 +358,9 @@ void OpenGLBackend::Paint(Rect update_rect) } /* Blit video buffer to screen. */ + _glBindBuffer(GL_ARRAY_BUFFER, this->vbo_quad); + glVertexPointer(2, GL_FLOAT, sizeof(Simple2DVertex), (GLvoid *)offsetof(Simple2DVertex, x)); + glTexCoordPointer(2, GL_FLOAT, sizeof(Simple2DVertex), (GLvoid *)offsetof(Simple2DVertex, u)); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } diff --git a/src/video/opengl.h b/src/video/opengl.h index 80555ca0b..15dc390b7 100644 --- a/src/video/opengl.h +++ b/src/video/opengl.h @@ -27,6 +27,7 @@ private: void *vid_buffer; ///< Pointer to the memory used for the video driver to draw to. GLuint vid_texture; ///< Texture handle for the video buffer texture. + GLuint vbo_quad; ///< Vertex buffer with a fullscreen quad. OpenGLBackend(); ~OpenGLBackend(); |