From bb0d1fc45eea926f6900253f2e029992dc7b3445 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Tue, 27 Feb 2024 22:47:02 +0100 Subject: [PATCH] opengl: move static vertex buffer variables to OpenGlContext --- src/backends/x11/standalone/glxcontext.cpp | 7 ++ src/backends/x11/standalone/glxcontext.h | 2 + src/opengl/eglcontext.cpp | 7 ++ src/opengl/eglcontext.h | 2 + src/opengl/glutils.cpp | 3 - src/opengl/glvertexbuffer.cpp | 92 +++------------------- src/opengl/glvertexbuffer.h | 15 +--- src/opengl/glvertexbuffer_p.h | 35 ++++++++ src/opengl/openglcontext.cpp | 58 ++++++++++++++ src/opengl/openglcontext.h | 15 ++++ 10 files changed, 138 insertions(+), 98 deletions(-) create mode 100644 src/opengl/glvertexbuffer_p.h diff --git a/src/backends/x11/standalone/glxcontext.cpp b/src/backends/x11/standalone/glxcontext.cpp index 376472d898..08886758fb 100644 --- a/src/backends/x11/standalone/glxcontext.cpp +++ b/src/backends/x11/standalone/glxcontext.cpp @@ -7,6 +7,7 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #include "glxcontext.h" +#include "opengl/glvertexbuffer_p.h" #include "x11_standalone_glx_context_attribute_builder.h" #include "x11_standalone_logging.h" @@ -21,8 +22,12 @@ GlxContext::GlxContext(::Display *display, GLXWindow window, GLXContext handle) , m_window(window) , m_handle(handle) , m_shaderManager(std::make_unique()) + , m_streamingBuffer(std::make_unique(GLVertexBuffer::Stream)) + , m_indexBuffer(std::make_unique()) { setShaderManager(m_shaderManager.get()); + setStreamingBuffer(m_streamingBuffer.get()); + setIndexBuffer(m_indexBuffer.get()); // It is not legal to not have a vertex array object bound in a core context // to make code handling old and new OpenGL versions easier, bind a dummy vao that's used for everything if (!isOpenglES() && hasOpenglExtension(QByteArrayLiteral("GL_ARB_vertex_array_object"))) { @@ -38,6 +43,8 @@ GlxContext::~GlxContext() glDeleteVertexArrays(1, &m_vao); } m_shaderManager.reset(); + m_streamingBuffer.reset(); + m_indexBuffer.reset(); glXDestroyContext(m_display, m_handle); } diff --git a/src/backends/x11/standalone/glxcontext.h b/src/backends/x11/standalone/glxcontext.h index 82f12ef585..a1748fb57a 100644 --- a/src/backends/x11/standalone/glxcontext.h +++ b/src/backends/x11/standalone/glxcontext.h @@ -32,6 +32,8 @@ private: const GLXContext m_handle; uint32_t m_vao = 0; std::unique_ptr m_shaderManager; + std::unique_ptr m_streamingBuffer; + std::unique_ptr m_indexBuffer; }; } diff --git a/src/opengl/eglcontext.cpp b/src/opengl/eglcontext.cpp index bf57273f60..2305e0650f 100644 --- a/src/opengl/eglcontext.cpp +++ b/src/opengl/eglcontext.cpp @@ -10,6 +10,7 @@ #include "core/graphicsbuffer.h" #include "egldisplay.h" #include "eglimagetexture.h" +#include "glvertexbuffer_p.h" #include "opengl/egl_context_attribute_builder.h" #include "opengl/eglutils_p.h" #include "opengl/glutils.h" @@ -45,8 +46,12 @@ EglContext::EglContext(EglDisplay *display, EGLConfig config, ::EGLContext conte , m_handle(context) , m_config(config) , m_shaderManager(std::make_unique()) + , m_streamingBuffer(std::make_unique(GLVertexBuffer::Stream)) + , m_indexBuffer(std::make_unique()) { setShaderManager(m_shaderManager.get()); + setStreamingBuffer(m_streamingBuffer.get()); + setIndexBuffer(m_indexBuffer.get()); // It is not legal to not have a vertex array object bound in a core context // to make code handling old and new OpenGL versions easier, bind a dummy vao that's used for everything if (!isOpenglES() && hasOpenglExtension(QByteArrayLiteral("GL_ARB_vertex_array_object"))) { @@ -62,6 +67,8 @@ EglContext::~EglContext() glDeleteVertexArrays(1, &m_vao); } m_shaderManager.reset(); + m_streamingBuffer.reset(); + m_indexBuffer.reset(); doneCurrent(); eglDestroyContext(m_display->handle(), m_handle); } diff --git a/src/opengl/eglcontext.h b/src/opengl/eglcontext.h index 1a17b7158d..39701b81e8 100644 --- a/src/opengl/eglcontext.h +++ b/src/opengl/eglcontext.h @@ -46,6 +46,8 @@ private: const ::EGLContext m_handle; const EGLConfig m_config; std::unique_ptr m_shaderManager; + std::unique_ptr m_streamingBuffer; + std::unique_ptr m_indexBuffer; uint32_t m_vao = 0; }; diff --git a/src/opengl/glutils.cpp b/src/opengl/glutils.cpp index ffcbe52905..51865c9ce4 100644 --- a/src/opengl/glutils.cpp +++ b/src/opengl/glutils.cpp @@ -113,13 +113,10 @@ void initGL(const std::function &resolveFunction) glResolveFunctions(resolveFunction); initDebugOutput(); - - GLVertexBuffer::initStatic(); } void cleanupGL() { - GLVertexBuffer::cleanup(); GLPlatform::cleanup(); glExtensions.clear(); diff --git a/src/opengl/glvertexbuffer.cpp b/src/opengl/glvertexbuffer.cpp index 5c4f67a7bf..f752712c1b 100644 --- a/src/opengl/glvertexbuffer.cpp +++ b/src/opengl/glvertexbuffer.cpp @@ -14,6 +14,7 @@ #include "glshader.h" #include "glshadermanager.h" #include "glutils.h" +#include "glvertexbuffer_p.h" #include "utils/common.h" #include @@ -32,21 +33,6 @@ T align(T value, int bytes) return (value + bytes - 1) & ~T(bytes - 1); } -class IndexBuffer -{ -public: - IndexBuffer(); - ~IndexBuffer(); - - void accommodate(size_t count); - void bind(); - -private: - GLuint m_buffer; - size_t m_count = 0; - std::vector m_data; -}; - IndexBuffer::IndexBuffer() { // The maximum number of quads we can render with 16 bit indices is 16,384. @@ -205,11 +191,6 @@ public: GLuint buffer; GLenum usage; int vertexCount; - static std::unique_ptr streamingBuffer; - static bool haveBufferStorage; - static bool haveSyncFences; - static bool hasMapBufferRange; - static bool supportsIndexedQuads; QByteArray dataStore; bool persistent; size_t bufferSize; @@ -224,16 +205,8 @@ public: std::array attrib; size_t attribStride = 0; std::bitset<32> enabledArrays; - static std::unique_ptr s_indexBuffer; }; -bool GLVertexBufferPrivate::hasMapBufferRange = false; -bool GLVertexBufferPrivate::supportsIndexedQuads = false; -std::unique_ptr GLVertexBufferPrivate::streamingBuffer; -bool GLVertexBufferPrivate::haveBufferStorage = false; -bool GLVertexBufferPrivate::haveSyncFences = false; -std::unique_ptr GLVertexBufferPrivate::s_indexBuffer; - void GLVertexBufferPrivate::bindArrays() { glBindBuffer(GL_ARRAY_BUFFER, buffer); @@ -410,7 +383,7 @@ GLvoid *GLVertexBuffer::map(size_t size) bool preferBufferSubData = GLPlatform::instance()->preferBufferSubData(); - if (GLVertexBufferPrivate::hasMapBufferRange && !preferBufferSubData) { + if (OpenGlContext::currentContext()->hasMapBufferRange() && !preferBufferSubData) { return (GLvoid *)d->mapNextFreeRange(size); } @@ -435,7 +408,7 @@ void GLVertexBuffer::unmap() bool preferBufferSubData = GLPlatform::instance()->preferBufferSubData(); - if (GLVertexBufferPrivate::hasMapBufferRange && !preferBufferSubData) { + if (OpenGlContext::currentContext()->hasMapBufferRange() && !preferBufferSubData) { glUnmapBuffer(GL_ARRAY_BUFFER); d->baseAddress = d->nextOffset; @@ -514,12 +487,8 @@ void GLVertexBuffer::draw(GLenum primitiveMode, int first, int count) void GLVertexBuffer::draw(const QRegion ®ion, GLenum primitiveMode, int first, int count, bool hardwareClipping) { if (primitiveMode == GL_QUADS) { - if (!GLVertexBufferPrivate::s_indexBuffer) { - GLVertexBufferPrivate::s_indexBuffer = std::make_unique(); - } - - GLVertexBufferPrivate::s_indexBuffer->bind(); - GLVertexBufferPrivate::s_indexBuffer->accommodate(count / 4); + OpenGlContext::currentContext()->indexBuffer()->bind(); + OpenGlContext::currentContext()->indexBuffer()->accommodate(count / 4); count = count * 6 / 4; @@ -548,11 +517,6 @@ void GLVertexBuffer::draw(const QRegion ®ion, GLenum primitiveMode, int first } } -bool GLVertexBuffer::supportsIndexedQuads() -{ - return GLVertexBufferPrivate::supportsIndexedQuads; -} - void GLVertexBuffer::reset() { d->vertexCount = 0; @@ -605,48 +569,14 @@ void GLVertexBuffer::beginFrame() } } -void GLVertexBuffer::initStatic() -{ - if (GLPlatform::instance()->isGLES()) { - bool haveBaseVertex = hasGLExtension(QByteArrayLiteral("GL_OES_draw_elements_base_vertex")); - bool haveCopyBuffer = hasGLVersion(3, 0); - bool haveMapBufferRange = hasGLExtension(QByteArrayLiteral("GL_EXT_map_buffer_range")); - - GLVertexBufferPrivate::hasMapBufferRange = haveMapBufferRange; - GLVertexBufferPrivate::supportsIndexedQuads = haveBaseVertex && haveCopyBuffer && haveMapBufferRange; - GLVertexBufferPrivate::haveBufferStorage = hasGLExtension("GL_EXT_buffer_storage"); - GLVertexBufferPrivate::haveSyncFences = hasGLVersion(3, 0); - } else { - bool haveBaseVertex = hasGLVersion(3, 2) || hasGLExtension(QByteArrayLiteral("GL_ARB_draw_elements_base_vertex")); - bool haveCopyBuffer = hasGLVersion(3, 1) || hasGLExtension(QByteArrayLiteral("GL_ARB_copy_buffer")); - bool haveMapBufferRange = hasGLVersion(3, 0) || hasGLExtension(QByteArrayLiteral("GL_ARB_map_buffer_range")); - - GLVertexBufferPrivate::hasMapBufferRange = haveMapBufferRange; - GLVertexBufferPrivate::supportsIndexedQuads = haveBaseVertex && haveCopyBuffer && haveMapBufferRange; - GLVertexBufferPrivate::haveBufferStorage = hasGLVersion(4, 4) || hasGLExtension("GL_ARB_buffer_storage"); - GLVertexBufferPrivate::haveSyncFences = hasGLVersion(3, 2) || hasGLExtension("GL_ARB_sync"); - } - GLVertexBufferPrivate::s_indexBuffer.reset(); - GLVertexBufferPrivate::streamingBuffer = std::make_unique(GLVertexBuffer::Stream); - - if (GLVertexBufferPrivate::haveBufferStorage && GLVertexBufferPrivate::haveSyncFences) { - if (qgetenv("KWIN_PERSISTENT_VBO") != QByteArrayLiteral("0")) { - GLVertexBufferPrivate::streamingBuffer->d->persistent = true; - } - } -} - -void GLVertexBuffer::cleanup() -{ - GLVertexBufferPrivate::s_indexBuffer.reset(); - GLVertexBufferPrivate::hasMapBufferRange = false; - GLVertexBufferPrivate::supportsIndexedQuads = false; - GLVertexBufferPrivate::streamingBuffer.reset(); -} - GLVertexBuffer *GLVertexBuffer::streamingBuffer() { - return GLVertexBufferPrivate::streamingBuffer.get(); + return OpenGlContext::currentContext()->streamingVbo(); +} + +void GLVertexBuffer::setPersistent() +{ + d->persistent = true; } } diff --git a/src/opengl/glvertexbuffer.h b/src/opengl/glvertexbuffer.h index 5698298166..204fb0738d 100644 --- a/src/opengl/glvertexbuffer.h +++ b/src/opengl/glvertexbuffer.h @@ -241,20 +241,7 @@ public: */ void beginFrame(); - /** - * @internal - */ - static void initStatic(); - - /** - * @internal - */ - static void cleanup(); - - /** - * Returns true if indexed quad mode is supported, and false otherwise. - */ - static bool supportsIndexedQuads(); + void setPersistent(); /** * @return A shared VBO for streaming data diff --git a/src/opengl/glvertexbuffer_p.h b/src/opengl/glvertexbuffer_p.h new file mode 100644 index 0000000000..dd3641ca83 --- /dev/null +++ b/src/opengl/glvertexbuffer_p.h @@ -0,0 +1,35 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2006-2007 Rivo Laks + SPDX-FileCopyrightText: 2010, 2011 Martin Gräßlin + SPDX-FileCopyrightText: 2023 Xaver Hugl + + SPDX-License-Identifier: GPL-2.0-or-later +*/ +#pragma once +#include "kwin_export.h" + +#include +#include + +namespace KWin +{ + +class KWIN_EXPORT IndexBuffer +{ +public: + explicit IndexBuffer(); + ~IndexBuffer(); + + void accommodate(size_t count); + void bind(); + +private: + GLuint m_buffer; + size_t m_count = 0; + std::vector m_data; +}; + +} diff --git a/src/opengl/openglcontext.cpp b/src/opengl/openglcontext.cpp index 750d768459..d6aa5dbe7a 100644 --- a/src/opengl/openglcontext.cpp +++ b/src/opengl/openglcontext.cpp @@ -7,6 +7,7 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #include "openglcontext.h" +#include "glvertexbuffer.h" #include #include @@ -55,6 +56,19 @@ static bool checkTextureStorageSupport(OpenGlContext *context) } } +static bool checkIndexedQuads(OpenGlContext *context) +{ + if (context->isOpenglES()) { + const bool haveBaseVertex = context->hasOpenglExtension(QByteArrayLiteral("GL_OES_draw_elements_base_vertex")); + const bool haveCopyBuffer = context->hasVersion(Version(3, 0)); + return haveBaseVertex && haveCopyBuffer && context->hasMapBufferRange(); + } else { + bool haveBaseVertex = context->hasVersion(Version(3, 2)) || context->hasOpenglExtension(QByteArrayLiteral("GL_ARB_draw_elements_base_vertex")); + bool haveCopyBuffer = context->hasVersion(Version(3, 1)) || context->hasOpenglExtension(QByteArrayLiteral("GL_ARB_copy_buffer")); + return haveBaseVertex && haveCopyBuffer && context->hasMapBufferRange(); + } +} + OpenGlContext::OpenGlContext() : m_versionString((const char *)glGetString(GL_VERSION)) , m_version(Version::parseString(m_versionString)) @@ -72,6 +86,10 @@ OpenGlContext::OpenGlContext() , m_supportsBlits(!m_isOpenglES || hasVersion(Version(3, 0))) , m_supportsPackedDepthStencil(hasVersion(Version(3, 0)) || hasOpenglExtension(QByteArrayLiteral("GL_OES_packed_depth_stencil")) || hasOpenglExtension(QByteArrayLiteral("GL_ARB_framebuffer_object")) || hasOpenglExtension(QByteArrayLiteral("GL_EXT_packed_depth_stencil"))) , m_supportsGLES24BitDepthBuffers(m_isOpenglES && (hasVersion(Version(3, 0)) || hasOpenglExtension(QByteArrayLiteral("GL_OES_depth24")))) + , m_hasMapBufferRange((!m_isOpenglES && hasVersion(Version(3, 0))) || hasOpenglExtension(QByteArrayLiteral("GL_EXT_map_buffer_range")) || hasOpenglExtension(QByteArrayLiteral("GL_ARB_map_buffer_range"))) + , m_haveBufferStorage((!m_isOpenglES || hasVersion(Version(4, 4))) || hasOpenglExtension(QByteArrayLiteral("GL_ARB_buffer_storage")) || hasOpenglExtension(QByteArrayLiteral("GL_EXT_buffer_storage"))) + , m_haveSyncFences((m_isOpenglES && hasVersion(Version(3, 0))) || (!m_isOpenglES && hasVersion(Version(3, 2))) || hasOpenglExtension(QByteArrayLiteral("GL_ARB_sync"))) + , m_supportsIndexedQuads(checkIndexedQuads(this)) { } @@ -176,11 +194,36 @@ bool OpenGlContext::supportsGLES24BitDepthBuffers() const return m_supportsGLES24BitDepthBuffers; } +bool OpenGlContext::haveBufferStorage() const +{ + return m_haveBufferStorage; +} + +bool OpenGlContext::hasMapBufferRange() const +{ + return m_hasMapBufferRange; +} + +bool OpenGlContext::haveSyncFences() const +{ + return m_haveSyncFences; +} + ShaderManager *OpenGlContext::shaderManager() const { return m_shaderManager; } +GLVertexBuffer *OpenGlContext::streamingVbo() const +{ + return m_streamingBuffer; +} + +IndexBuffer *OpenGlContext::indexBuffer() const +{ + return m_indexBuffer; +} + bool OpenGlContext::checkSupported() const { const bool supportsGLSL = m_isOpenglES || (hasOpenglExtension("GL_ARB_shader_objects") && hasOpenglExtension("GL_ARB_fragment_shader") && hasOpenglExtension("GL_ARB_vertex_shader")); @@ -195,6 +238,21 @@ void OpenGlContext::setShaderManager(ShaderManager *manager) m_shaderManager = manager; } +void OpenGlContext::setStreamingBuffer(GLVertexBuffer *vbo) +{ + m_streamingBuffer = vbo; + if (haveBufferStorage() && haveSyncFences()) { + if (qgetenv("KWIN_PERSISTENT_VBO") != QByteArrayLiteral("0")) { + vbo->setPersistent(); + } + } +} + +void OpenGlContext::setIndexBuffer(IndexBuffer *buffer) +{ + m_indexBuffer = buffer; +} + OpenGlContext *OpenGlContext::currentContext() { return s_currentContext; diff --git a/src/opengl/openglcontext.h b/src/opengl/openglcontext.h index 6494e2f0ed..26e44cff96 100644 --- a/src/opengl/openglcontext.h +++ b/src/opengl/openglcontext.h @@ -21,6 +21,8 @@ namespace KWin class ShaderManager; class GLFramebuffer; +class GLVertexBuffer; +class IndexBuffer; class KWIN_EXPORT OpenGlContext { @@ -46,7 +48,12 @@ public: bool supports16BitTextures() const; bool supportsBlits() const; bool supportsGLES24BitDepthBuffers() const; + bool hasMapBufferRange() const; + bool haveBufferStorage() const; + bool haveSyncFences() const; ShaderManager *shaderManager() const; + GLVertexBuffer *streamingVbo() const; + IndexBuffer *indexBuffer() const; /** * checks whether or not this context supports all the features that KWin requires @@ -58,6 +65,8 @@ public: protected: bool checkTimerQuerySupport() const; void setShaderManager(ShaderManager *manager); + void setStreamingBuffer(GLVertexBuffer *vbo); + void setIndexBuffer(IndexBuffer *buffer); static OpenGlContext *s_currentContext; @@ -77,7 +86,13 @@ protected: const bool m_supportsBlits; const bool m_supportsPackedDepthStencil; const bool m_supportsGLES24BitDepthBuffers; + const bool m_hasMapBufferRange; + const bool m_haveBufferStorage; + const bool m_haveSyncFences; + const bool m_supportsIndexedQuads; ShaderManager *m_shaderManager = nullptr; + GLVertexBuffer *m_streamingBuffer = nullptr; + IndexBuffer *m_indexBuffer = nullptr; }; }