Mercurial > hg > openttd
changeset 20541:6e216d3bc4df draft
-Codechange: [OpenGL] Use a vertex array object to store the vertex state for the video buffer.
author | Michael Lutz <michi@icosahedron.de> |
---|---|
date | Sat, 01 Jun 2013 21:48:34 +0200 |
parents | adbcc8c10688 |
children | b6097f4fe3be |
files | src/video/opengl.cpp src/video/opengl.h |
diffstat | 2 files changed, 40 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -42,6 +42,10 @@ static PFNGLMAPBUFFERPROC _glMapBuffer; static PFNGLUNMAPBUFFERPROC _glUnmapBuffer; +static PFNGLGENVERTEXARRAYSPROC _glGenVertexArrays; +static PFNGLDELETEVERTEXARRAYSPROC _glDeleteVertexArrays; +static PFNGLBINDVERTEXARRAYPROC _glBindVertexArray; + /** A simple 2D vertex with just position and texture. */ struct Simple2DVertex { float x, y; @@ -169,6 +173,25 @@ return _glGenBuffers != NULL && _glDeleteBuffers != NULL && _glBindBuffer != NULL && _glBufferData != NULL && _glMapBuffer != NULL && _glUnmapBuffer != NULL; } +/** Bind vertex array object extension functions. */ +static bool BindVBAExtension() +{ + /* The APPLE and ARB variants have different semantics (that don't matter for us). + * Successfully getting pointers to one variant doesn't mean it is supported for + * the current context. Always check the extension strings as well. */ + if (IsOpenGLVersionAtLeast(3, 0) || IsOpenGLExtensionSupported("GL_ARB_vertex_array_object")) { + _glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)GetOGLProcAddress("glGenVertexArrays"); + _glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)GetOGLProcAddress("glDeleteVertexArrays"); + _glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)GetOGLProcAddress("glBindVertexArray"); + } else { + _glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)GetOGLProcAddress("glGenVertexArraysAPPLE"); + _glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)GetOGLProcAddress("glDeleteVertexArraysAPPLE"); + _glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)GetOGLProcAddress("glBindVertexArrayAPPLE"); + } + + return _glGenVertexArrays != NULL && _glDeleteVertexArrays != NULL && _glBindVertexArray != NULL; +} + /** * Construct OpenGL back-end class. @@ -182,6 +205,7 @@ */ OpenGLBackend::~OpenGLBackend() { + _glDeleteVertexArrays(1, &this->vao_quad); _glDeleteBuffers(1, &this->vbo_quad); glDeleteTextures(1, &this->vid_texture); free(this->vid_buffer); @@ -208,6 +232,9 @@ /* 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"; + /* Check for vertex array objects. */ + if (!IsOpenGLVersionAtLeast(3, 0) && (!IsOpenGLExtensionSupported("GL_ARB_vertex_array_object") || !IsOpenGLExtensionSupported("GL_APPLE_vertex_array_object"))) return "Vertex array objects not supported"; + if (!BindVBAExtension()) return "Failed to bind VBA extension functions"; /* Setup video buffer texture. */ glGenTextures(1, &this->vid_texture); @@ -220,7 +247,8 @@ glBindTexture(GL_TEXTURE_2D, 0); if (glGetError() != GL_NO_ERROR) return "Can't generate video buffer texture"; - /* Prime vertex buffer with a full-screen quad. */ + /* Prime vertex buffer with a full-screen quad and store + * the corresponding state in a vertex array object. */ static const Simple2DVertex vert_array[] = { // x y u v { 1.f, -1.f, 1.f, 1.f }, @@ -229,13 +257,21 @@ { -1.f, 1.f, 0.f, 0.f }, }; + /* Create VAO. */ + _glGenVertexArrays(1, &this->vao_quad); + _glBindVertexArray(this->vao_quad); + + /* Create and fill VBO. */ _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"; - + /* Set vertex state. */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FLOAT, sizeof(Simple2DVertex), (GLvoid *)offsetof(Simple2DVertex, x)); + glTexCoordPointer(2, GL_FLOAT, sizeof(Simple2DVertex), (GLvoid *)offsetof(Simple2DVertex, u)); + _glBindVertexArray(0); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glDisable(GL_DEPTH_TEST); @@ -291,9 +327,7 @@ } /* 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)); + _glBindVertexArray(this->vao_quad); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glFlush();
--- a/src/video/opengl.h +++ b/src/video/opengl.h @@ -23,6 +23,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 vao_quad; ///< Vertex array object storing the rendering state for the fullscreen quad. GLuint vbo_quad; ///< Vertex buffer with a fullscreen quad. public: