Simplify and extend [E]GLCheck implementation

This commit is contained in:
Vittorio Romeo 2024-09-15 17:21:27 +02:00 committed by Chris Thrasher
parent 2dd72be036
commit e2ea1d8a7c
4 changed files with 113 additions and 189 deletions

View File

@ -31,81 +31,52 @@
#include <SFML/System/Err.hpp>
#include <ostream>
#include <string>
namespace sf::priv
{
////////////////////////////////////////////////////////////
void glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
bool glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
{
// Get the last error
const GLenum errorCode = glGetError();
if (errorCode != GL_NO_ERROR)
const auto logError = [&](const char* error, const char* description)
{
std::string error = "Unknown error";
std::string description = "No description";
// Decode the error code
switch (errorCode)
{
case GL_INVALID_ENUM:
{
error = "GL_INVALID_ENUM";
description = "An unacceptable value has been specified for an enumerated argument.";
break;
}
case GL_INVALID_VALUE:
{
error = "GL_INVALID_VALUE";
description = "A numeric argument is out of range.";
break;
}
case GL_INVALID_OPERATION:
{
error = "GL_INVALID_OPERATION";
description = "The specified operation is not allowed in the current state.";
break;
}
case GL_STACK_OVERFLOW:
{
error = "GL_STACK_OVERFLOW";
description = "This command would cause a stack overflow.";
break;
}
case GL_STACK_UNDERFLOW:
{
error = "GL_STACK_UNDERFLOW";
description = "This command would cause a stack underflow.";
break;
}
case GL_OUT_OF_MEMORY:
{
error = "GL_OUT_OF_MEMORY";
description = "There is not enough memory left to execute the command.";
break;
}
case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION:
{
error = "GL_INVALID_FRAMEBUFFER_OPERATION";
description = "The object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\".";
break;
}
}
// Log the error
err() << "An internal OpenGL call failed in " << file.filename() << "(" << line << ")."
<< "\nExpression:\n " << expression << "\nError description:\n " << error << "\n " << description << '\n'
<< std::endl;
}
}
return false;
};
switch (glGetError())
{
case GL_NO_ERROR:
return true;
case GL_INVALID_ENUM:
return logError("GL_INVALID_ENUM", "An unacceptable value has been specified for an enumerated argument.");
case GL_INVALID_VALUE:
return logError("GL_INVALID_VALUE", "A numeric argument is out of range.");
case GL_INVALID_OPERATION:
return logError("GL_INVALID_OPERATION", "The specified operation is not allowed in the current state.");
case GL_STACK_OVERFLOW:
return logError("GL_STACK_OVERFLOW", "This command would cause a stack overflow.");
case GL_STACK_UNDERFLOW:
return logError("GL_STACK_UNDERFLOW", "This command would cause a stack underflow.");
case GL_OUT_OF_MEMORY:
return logError("GL_OUT_OF_MEMORY", "There is not enough memory left to execute the command.");
case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION:
return logError("GL_INVALID_FRAMEBUFFER_OPERATION",
"The object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\".");
default:
return logError("Unknown error", "Unknown description");
}
}
} // namespace sf::priv

View File

@ -63,7 +63,9 @@ namespace sf::priv
/// \param line Line number of the source file where the call is located
/// \param expression The evaluated expression as a string
///
/// \return `false` if an error occurred, `true` otherwise
///
////////////////////////////////////////////////////////////
void glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
bool glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
} // namespace sf::priv

View File

@ -33,139 +33,88 @@
#include <glad/egl.h>
#include <ostream>
#include <string>
namespace sf::priv
{
////////////////////////////////////////////////////////////
void eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
bool eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
{
// Obtain information about the success or failure of the most recent EGL
// function called in the current thread
const EGLint errorCode = eglGetError();
if (errorCode != EGL_SUCCESS)
const auto logError = [&](const char* error, const char* description)
{
std::string error = "unknown error";
std::string description = "no description";
// Decode the error code returned
switch (errorCode)
{
case EGL_NOT_INITIALIZED:
{
error = "EGL_NOT_INITIALIZED";
description = "EGL is not initialized, or could not be initialized, for the specified display";
break;
}
case EGL_BAD_ACCESS:
{
error = "EGL_BAD_ACCESS";
description =
"EGL cannot access a requested resource (for example, a context is bound in another thread)";
break;
}
case EGL_BAD_ALLOC:
{
error = "EGL_BAD_ALLOC";
description = "EGL failed to allocate resources for the requested operation";
break;
}
case EGL_BAD_ATTRIBUTE:
{
error = "EGL_BAD_ATTRIBUTE";
description = "an unrecognized attribute or attribute value was passed in an attribute list";
break;
}
case EGL_BAD_CONTEXT:
{
error = "EGL_BAD_CONTEXT";
description = "an EGLContext argument does not name a valid EGLContext";
break;
}
case EGL_BAD_CONFIG:
{
error = "EGL_BAD_CONFIG";
description = "an EGLConfig argument does not name a valid EGLConfig";
break;
}
case EGL_BAD_CURRENT_SURFACE:
{
error = "EGL_BAD_CURRENT_SURFACE";
description =
"the current surface of the calling thread is a window, pbuffer, or pixmap that is no longer valid";
break;
}
case EGL_BAD_DISPLAY:
{
error = "EGL_BAD_DISPLAY";
description =
"an EGLDisplay argument does not name a valid EGLDisplay; or, EGL is not initialized on the "
"specified EGLDisplay";
break;
}
case EGL_BAD_SURFACE:
{
error = "EGL_BAD_SURFACE";
description =
"an EGLSurface argument does not name a valid surface (window, pbuffer, or pixmap) configured for "
"rendering";
break;
}
case EGL_BAD_MATCH:
{
error = "EGL_BAD_MATCH";
description =
"arguments are inconsistent; for example, an otherwise valid context requires buffers (e.g. depth "
"or stencil) not allocated by an otherwise valid surface";
break;
}
case EGL_BAD_PARAMETER:
{
error = "EGL_BAD_PARAMETER";
description = "one or more argument values are invalid";
break;
}
case EGL_BAD_NATIVE_PIXMAP:
{
error = "EGL_BAD_NATIVE_PIXMAP";
description = "an EGLNativePixmapType argument does not refer to a valid native pixmap";
break;
}
case EGL_BAD_NATIVE_WINDOW:
{
error = "EGL_BAD_NATIVE_WINDOW";
description = "an EGLNativeWindowType argument does not refer to a valid native window";
break;
}
case EGL_CONTEXT_LOST:
{
error = "EGL_CONTEXT_LOST";
description =
"a power management event has occurred. The application must destroy all contexts and reinitialize "
"client API state and objects to continue rendering";
break;
}
}
// Log the error
err() << "An internal EGL call failed in " << file.filename() << " (" << line << ") : "
<< "\nExpression:\n " << expression << "\nError description:\n " << error << "\n " << description << '\n'
<< std::endl;
return false;
};
switch (eglGetError())
{
case EGL_SUCCESS:
return true;
case EGL_NOT_INITIALIZED:
return logError("EGL_NOT_INITIALIZED",
"EGL is not initialized, or could not be initialized, for the specified display");
case EGL_BAD_ACCESS:
return logError("EGL_BAD_ACCESS",
"EGL cannot access a requested resource (for example, a context is bound in another "
"thread)");
case EGL_BAD_ALLOC:
return logError("EGL_BAD_ALLOC", "EGL failed to allocate resources for the requested operation");
case EGL_BAD_ATTRIBUTE:
return logError("EGL_BAD_ATTRIBUTE",
"an unrecognized attribute or attribute value was passed in an attribute list");
case EGL_BAD_CONTEXT:
return logError("EGL_BAD_CONTEXT", "an EGLContext argument does not name a valid EGLContext");
case EGL_BAD_CONFIG:
return logError("EGL_BAD_CONFIG", "an EGLConfig argument does not name a valid EGLConfig");
case EGL_BAD_CURRENT_SURFACE:
return logError("EGL_BAD_CURRENT_SURFACE",
"the current surface of the calling thread is a window, pbuffer, or pixmap that is no "
"longer valid");
case EGL_BAD_DISPLAY:
return logError("EGL_BAD_DISPLAY",
"an EGLDisplay argument does not name a valid EGLDisplay; or, EGL is not initialized on "
"the specified EGLDisplay");
case EGL_BAD_SURFACE:
return logError("EGL_BAD_SURFACE",
"an EGLSurface argument does not name a valid surface (window, pbuffer, or pixmap) "
"configured for rendering");
case EGL_BAD_MATCH:
return logError("EGL_BAD_MATCH",
"arguments are inconsistent; for example, an otherwise valid context requires buffers "
"(e.g. depth or stencil) not allocated by an otherwise valid surface");
case EGL_BAD_PARAMETER:
return logError("EGL_BAD_PARAMETER", "one or more argument values are invalid");
case EGL_BAD_NATIVE_PIXMAP:
return logError("EGL_BAD_NATIVE_PIXMAP",
"an EGLNativePixmapType argument does not refer to a valid native pixmap");
case EGL_BAD_NATIVE_WINDOW:
return logError("EGL_BAD_NATIVE_WINDOW",
"an EGLNativeWindowType argument does not refer to a valid native window");
case EGL_CONTEXT_LOST:
return logError("EGL_CONTEXT_LOST",
"a power management event has occurred. The application must destroy all contexts and "
"reinitialize client API state and objects to continue rendering");
default:
return logError("Unknown error", "Unknown description");
}
}

View File

@ -63,7 +63,9 @@ namespace sf::priv
/// \param line Line number of the source file where the call is located
/// \param expression The evaluated expression as a string
///
/// \return `false` if an error occurred, `true` otherwise
///
////////////////////////////////////////////////////////////
void eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
bool eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
} // namespace sf::priv