// ===================================================================================================================== // glw, an open-source library that wraps OpenGL structures into classes. // Copyright (C) 2024 Medusa Slockbower // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // ===================================================================================================================== #ifndef GLW_DEBUG_H #define GLW_DEBUG_H #include "common.h" namespace glw::debug { /** * \brief OpenGL error codes */ enum error { error_invalid_enum = GL_INVALID_ENUM , error_invalid_value = GL_INVALID_VALUE , error_invalid_operation = GL_INVALID_OPERATION , error_stack_overflow = GL_STACK_OVERFLOW , error_stack_underflow = GL_STACK_UNDERFLOW , error_out_of_memory = GL_OUT_OF_MEMORY , error_invalid_framebuffer_operation = GL_INVALID_FRAMEBUFFER_OPERATION , error_context_lost = GL_CONTEXT_LOST , error_table_too_large = GL_TABLE_TOO_LARGE }; /** * \brief Converts an error code into a string representation * \param error The error code to translate * \return C string containing the string representation */ inline const char_t* translate_error(enum_t error) { switch(error) { case error_invalid_enum: return GLW_STRINGIFY(error_invalid_enum); case error_invalid_value: return GLW_STRINGIFY(error_invalid_value); case error_invalid_operation: return GLW_STRINGIFY(error_invalid_operation); case error_stack_overflow: return GLW_STRINGIFY(error_stack_overflow); case error_stack_underflow: return GLW_STRINGIFY(error_stack_underflow); case error_out_of_memory: return GLW_STRINGIFY(error_out_of_memory); case error_invalid_framebuffer_operation: return GLW_STRINGIFY(error_invalid_framebuffer_operation); case error_context_lost: return GLW_STRINGIFY(error_context_lost); case error_table_too_large: return GLW_STRINGIFY(error_table_too_large); default: return GLW_STRINGIFY(error_unknown); } } /** * \brief Get the last error thrown by OpenGL, it is preferable to use the callback handler for performance * \return Error code of the last error */ inline enum_t get_error() { return glGetError(); } /** * \brief Source ids of a debug message */ enum debug_source { source_api = GL_DEBUG_SOURCE_API , source_window_system = GL_DEBUG_SOURCE_WINDOW_SYSTEM , source_shader_compiler = GL_DEBUG_SOURCE_SHADER_COMPILER , source_third_party = GL_DEBUG_SOURCE_THIRD_PARTY , source_application = GL_DEBUG_SOURCE_APPLICATION , source_other = GL_DEBUG_SOURCE_OTHER }; /** * \brief Translate a debug message source into a string representation * \param source ID of the debug message source * \return C string containing the string representation */ inline const char_t* translate_source(enum_t source) { switch(source) { case source_api: return GLW_STRINGIFY(source_api); case source_window_system: return GLW_STRINGIFY(source_window_system); case source_shader_compiler: return GLW_STRINGIFY(source_shader_compiler); case source_third_party: return GLW_STRINGIFY(source_third_party); case source_application: return GLW_STRINGIFY(source_application); case source_other: return GLW_STRINGIFY(source_other); default: return GLW_STRINGIFY(source_unknown); } } /** * \brief Types of debug messages */ enum debug_type { type_error = GL_DEBUG_TYPE_ERROR , type_deprecated_behavior = GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR , type_undefined_behavior = GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR , type_portability = GL_DEBUG_TYPE_PORTABILITY , type_performance = GL_DEBUG_TYPE_PERFORMANCE , type_marker = GL_DEBUG_TYPE_MARKER , type_push_group = GL_DEBUG_TYPE_PUSH_GROUP , type_pop_group = GL_DEBUG_TYPE_POP_GROUP , type_other = GL_DEBUG_TYPE_OTHER }; inline void push_group(enum_t src, uint_t id, size_t len, const char_t* msg) { glPushDebugGroup(src, id, len, msg); } inline void pop_group() { glPopDebugGroup(); } inline void set_label(enum_t id, handle_t name, size_t len, const char_t* label) { glObjectLabel(id, name, len, label); } inline void set_label(void* ptr, size_t len, const char_t* label) { glObjectPtrLabel(ptr, len, label); } inline void get_label(enum_t id, handle_t name, size_t buf_size, size_t& length, char_t* buf) { glGetObjectLabel(id, name, buf_size, &length, buf); } inline void get_label(void* ptr, size_t buf_size, size_t& length, char_t* buf) { glGetObjectPtrLabel(ptr, buf_size, &length, buf); } inline const char_t* translate_type(enum_t source) { switch(source) { case type_error: return GLW_STRINGIFY(type_error); case type_deprecated_behavior: return GLW_STRINGIFY(type_deprecated_behavior); case type_undefined_behavior: return GLW_STRINGIFY(type_undefined_behavior); case type_portability: return GLW_STRINGIFY(type_portability); case type_performance: return GLW_STRINGIFY(type_performance); case type_marker: return GLW_STRINGIFY(type_marker); case type_push_group: return GLW_STRINGIFY(type_push_group); case type_pop_group: return GLW_STRINGIFY(type_pop_group); case type_other: return GLW_STRINGIFY(type_other); default: return GLW_STRINGIFY(type_unknown); } } enum debug_severity { severity_low = GL_DEBUG_SEVERITY_LOW , severity_medium = GL_DEBUG_SEVERITY_MEDIUM , severity_high = GL_DEBUG_SEVERITY_HIGH , severity_notification = GL_DEBUG_SEVERITY_NOTIFICATION }; inline const char_t* translate_severity(enum_t severity) { switch(severity) { case severity_low: return GLW_STRINGIFY(severity_low); case severity_medium: return GLW_STRINGIFY(severity_medium); case severity_high: return GLW_STRINGIFY(severity_high); case severity_notification: return GLW_STRINGIFY(severity_notification); default: return GLW_STRINGIFY(severity_unknown); } } inline void insert_message(enum_t source, enum_t type, uint_t id, enum_t severity, size_t length, const char_t* message) { glDebugMessageInsert(source, type, id, severity, length, message); } using debug_callback = GLDEBUGPROC; inline void set_debug_callback(debug_callback callback, void* user_data) { glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(callback, user_data); } } #endif //DEBUG_H