opengl: move static vertex buffer variables to OpenGlContext
This commit is contained in:
parent
f98477e05b
commit
bb0d1fc45e
10 changed files with 138 additions and 98 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 ®ion, 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 ®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>(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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
35
src/opengl/glvertexbuffer_p.h
Normal file
35
src/opengl/glvertexbuffer_p.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue