opengl: move static vertex buffer variables to OpenGlContext

This commit is contained in:
Xaver Hugl 2024-02-27 22:47:02 +01:00
parent f98477e05b
commit bb0d1fc45e
10 changed files with 138 additions and 98 deletions

View file

@ -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<ShaderManager>())
, m_streamingBuffer(std::make_unique<GLVertexBuffer>(GLVertexBuffer::Stream))
, m_indexBuffer(std::make_unique<IndexBuffer>())
{
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);
}

View file

@ -32,6 +32,8 @@ private:
const GLXContext m_handle;
uint32_t m_vao = 0;
std::unique_ptr<ShaderManager> m_shaderManager;
std::unique_ptr<GLVertexBuffer> m_streamingBuffer;
std::unique_ptr<IndexBuffer> m_indexBuffer;
};
}

View file

@ -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<ShaderManager>())
, m_streamingBuffer(std::make_unique<GLVertexBuffer>(GLVertexBuffer::Stream))
, m_indexBuffer(std::make_unique<IndexBuffer>())
{
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);
}

View file

@ -46,6 +46,8 @@ private:
const ::EGLContext m_handle;
const EGLConfig m_config;
std::unique_ptr<ShaderManager> m_shaderManager;
std::unique_ptr<GLVertexBuffer> m_streamingBuffer;
std::unique_ptr<IndexBuffer> m_indexBuffer;
uint32_t m_vao = 0;
};

View file

@ -113,13 +113,10 @@ void initGL(const std::function<resolveFuncPtr(const char *)> &resolveFunction)
glResolveFunctions(resolveFunction);
initDebugOutput();
GLVertexBuffer::initStatic();
}
void cleanupGL()
{
GLVertexBuffer::cleanup();
GLPlatform::cleanup();
glExtensions.clear();

View file

@ -14,6 +14,7 @@
#include "glshader.h"
#include "glshadermanager.h"
#include "glutils.h"
#include "glvertexbuffer_p.h"
#include "utils/common.h"
#include <QVector4D>
@ -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<uint16_t> 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<GLVertexBuffer> 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<VertexAttrib, VertexAttributeCount> attrib;
size_t attribStride = 0;
std::bitset<32> enabledArrays;
static std::unique_ptr<IndexBuffer> s_indexBuffer;
};
bool GLVertexBufferPrivate::hasMapBufferRange = false;
bool GLVertexBufferPrivate::supportsIndexedQuads = false;
std::unique_ptr<GLVertexBuffer> GLVertexBufferPrivate::streamingBuffer;
bool GLVertexBufferPrivate::haveBufferStorage = false;
bool GLVertexBufferPrivate::haveSyncFences = false;
std::unique_ptr<IndexBuffer> 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 &region, GLenum primitiveMode, int first, int count, bool hardwareClipping)
{
if (primitiveMode == GL_QUADS) {
if (!GLVertexBufferPrivate::s_indexBuffer) {
GLVertexBufferPrivate::s_indexBuffer = std::make_unique<IndexBuffer>();
}
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 &region, 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>(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;
}
}

View file

@ -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

View file

@ -0,0 +1,35 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2006-2007 Rivo Laks <rivolaks@hot.ee>
SPDX-FileCopyrightText: 2010, 2011 Martin Gräßlin <mgraesslin@kde.org>
SPDX-FileCopyrightText: 2023 Xaver Hugl <xaver.hugl@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "kwin_export.h"
#include <epoxy/gl.h>
#include <vector>
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<uint16_t> m_data;
};
}

View file

@ -7,6 +7,7 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "openglcontext.h"
#include "glvertexbuffer.h"
#include <QByteArray>
#include <QList>
@ -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;

View file

@ -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;
};
}