20static QList<QByteArray> glExtensions;
24static void initDebugOutput()
26 const bool have_KHR_debug =
hasGLExtension(QByteArrayLiteral(
"GL_KHR_debug"));
27 const bool have_ARB_debug =
hasGLExtension(QByteArrayLiteral(
"GL_ARB_debug_output"));
28 if (!have_KHR_debug && !have_ARB_debug) {
32 if (!have_ARB_debug) {
45 glGetIntegerv(GL_CONTEXT_FLAGS, &value);
46 if (!(value & GL_CONTEXT_FLAG_DEBUG_BIT)) {
52 auto callback = [](GLenum source, GLenum
type, GLuint id,
53 GLenum severity, GLsizei length,
54 const GLchar *message,
55 const GLvoid *userParam) {
56 while (length && std::isspace(message[length - 1])) {
61 case GL_DEBUG_TYPE_ERROR:
62 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
63 qCWarning(KWIN_OPENGL,
"%#x: %.*s",
id, length, message);
66 case GL_DEBUG_TYPE_OTHER:
67 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
68 case GL_DEBUG_TYPE_PORTABILITY:
69 case GL_DEBUG_TYPE_PERFORMANCE:
71 qCDebug(KWIN_OPENGL,
"%#x: %.*s",
id, length, message);
76 glDebugMessageCallback(callback,
nullptr);
80 glEnable(GL_DEBUG_OUTPUT);
83 if (qEnvironmentVariableIntValue(
"KWIN_GL_DEBUG")) {
85 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0,
nullptr, GL_TRUE);
87 const QByteArray message = QByteArrayLiteral(
"OpenGL debug output initialized");
88 glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0,
89 GL_DEBUG_SEVERITY_LOW, message.length(), message.constData());
92 glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0,
nullptr, GL_TRUE);
93 glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, GL_DONT_CARE, 0,
nullptr, GL_TRUE);
102 glGetIntegerv(GL_NUM_EXTENSIONS, &count);
104 for (
int i = 0; i < count; i++) {
105 const QByteArray name = (
const char *)glGetStringi(GL_EXTENSIONS, i);
106 glExtensions << name;
109 glExtensions = QByteArray((
const char *)glGetString(GL_EXTENSIONS)).split(
' ');
125 GLTexturePrivate::cleanup();
126 GLFramebuffer::cleanup();
128 GLPlatform::cleanup();
130 glExtensions.clear();
140 return glExtensions.contains(extension);
148static QString formatGLError(GLenum err)
152 return QStringLiteral(
"GL_NO_ERROR");
153 case GL_INVALID_ENUM:
154 return QStringLiteral(
"GL_INVALID_ENUM");
155 case GL_INVALID_VALUE:
156 return QStringLiteral(
"GL_INVALID_VALUE");
157 case GL_INVALID_OPERATION:
158 return QStringLiteral(
"GL_INVALID_OPERATION");
159 case GL_STACK_OVERFLOW:
160 return QStringLiteral(
"GL_STACK_OVERFLOW");
161 case GL_STACK_UNDERFLOW:
162 return QStringLiteral(
"GL_STACK_UNDERFLOW");
163 case GL_OUT_OF_MEMORY:
164 return QStringLiteral(
"GL_OUT_OF_MEMORY");
166 return QLatin1String(
"0x") + QString::number(err, 16);
172 GLenum err = glGetError();
173 if (err == GL_CONTEXT_LOST) {
174 qCWarning(KWIN_OPENGL) <<
"GL error: context lost";
177 bool hasError =
false;
178 while (err != GL_NO_ERROR) {
179 qCWarning(KWIN_OPENGL) <<
"GL error (" << txt <<
"): " << formatGLError(err);
182 if (err == GL_CONTEXT_LOST) {
183 qCWarning(KWIN_OPENGL) <<
"GL error: context lost";
bool checkGLError(const char *txt)
void KWIN_EXPORT cleanupGL()
void initGL(const std::function< resolveFuncPtr(const char *)> &resolveFunction)
QList< QByteArray > openGLExtensions()
bool hasGLVersion(int major, int minor, int release)
bool hasGLExtension(const QByteArray &extension)
void glResolveFunctions(const std::function< resolveFuncPtr(const char *)> &resolveFunction)