6#include <brenta/renderer/opengl/gl.hpp>
7#include <brenta/logger.hpp>
8#include <brenta/window.hpp>
12using namespace brenta;
18const std::string Gl::subsystem_name =
"gl";
20bool Gl::initialized =
false;
21const GLboolean Gl::True = GL_TRUE;
22const GLboolean Gl::False = GL_FALSE;
25void APIENTRY glDebugOutput([[maybe_unused]] GLenum source,
26 [[maybe_unused]] GLenum type,
27 [[maybe_unused]] GLuint
id,
28 [[maybe_unused]] GLenum severity,
29 [[maybe_unused]] GLsizei length,
30 [[maybe_unused]]
const GLchar *message,
31 [[maybe_unused]]
const void *userParam);
37std::expected<void, Subsystem::Error> Gl::initialize()
39 if (this->is_initialized())
return {};
41 GLADloadproc loadproc = (GLADloadproc) Window::get_proc_address();
42 if (!gladLoadGLLoader(loadproc))
44 ERROR(
"{}: failed to initialize GLAD", Gl::subsystem_name);
45 return std::unexpected(
"Failed to initialize GLAD");
48 int width = Window::get_width();
49 int height = Window::get_height();
51 glViewport(0, 0, width, height);
53 if (Gl::init_config.enable_depth_test)
55 glEnable(GL_DEPTH_TEST);
56 INFO(
"{}: enabled GL_DEPTH_TEST", Gl::subsystem_name);
59 if (Gl::init_config.enable_blending)
62 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
63 INFO(
"{}: enabled GL_BLEND (transparency)", Gl::subsystem_name);
66 if (Gl::init_config.enable_backface_culling)
68 glEnable(GL_CULL_FACE);
69 INFO(
"{}: enabled GL_CULL_FACE", Gl::subsystem_name);
72 if (Gl::init_config.enable_multisample)
74 glEnable(GL_MULTISAMPLE);
75 INFO(
"{}: enabled GL_MULTISAMPLE", Gl::subsystem_name);
79 glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
80 if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
83 glEnable(GL_DEBUG_OUTPUT);
84 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
85 glDebugMessageCallback(glDebugOutput,
nullptr);
86 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE,
88 INFO(
"{}: configured GL_DEBUG_OUTPUT", Gl::subsystem_name);
91 GLenum errcode = Gl::check_error();
92 if (errcode != GL_NO_ERROR)
94 return std::unexpected(
"GL error");
97 Gl::initialized =
true;
98 INFO(
"{}: initialized", Gl::subsystem_name);
102std::expected<void, Subsystem::Error> Gl::terminate()
104 if (!this->is_initialized())
return {};
106 Gl::initialized =
false;
107 INFO(
"{}: terminated", Gl::subsystem_name);
111std::string Gl::name()
113 return Gl::subsystem_name;
116bool Gl::is_initialized()
118 return Gl::initialized;
125void Gl::set_poligon_mode(GLboolean enable)
129 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
130 INFO(
"{}: enabled GL_POLYGON_MODE (wireframe)", Gl::subsystem_name);
134 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
135 INFO(
"{}: disabled GL_POLYGON_MODE (fill)", Gl::subsystem_name);
146int Gl::get_num_channels(GLenum color_format)
148 switch (color_format)
152 case GL_STENCIL_INDEX:
153 case GL_DEPTH_COMPONENT:
158 case GL_DEPTH_STENCIL:
169 case GL_RGBA_INTEGER:
170 case GL_BGRA_INTEGER:
178int Gl::get_bytes_per_channel(GLenum type)
182 case GL_UNSIGNED_BYTE:
186 case GL_UNSIGNED_SHORT:
191 case GL_UNSIGNED_INT:
199 case GL_UNSIGNED_INT_2_10_10_10_REV:
200 case GL_UNSIGNED_INT_10F_11F_11F_REV:
201 case GL_UNSIGNED_INT_24_8:
209void Gl::set_viewport(
int x,
int y,
int width,
int height)
211 glViewport(x, y, width, height);
215void Gl::set_color(
const Color &color)
217 glClearColor(color.r, color.g, color.b, color.a);
221void Gl::draw_arrays(GLenum mode,
int first,
int count)
223 glDrawArrays(mode, first, count);
227void Gl::draw_elements(GLenum mode,
int count, GLenum type,
const void *indices)
229 glDrawElements(mode, count, type, indices);
235 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
239GLenum Gl::_check_error(
const char *file,
int line)
242 while ((errorCode = glGetError()) != GL_NO_ERROR)
244 std::string error =
"";
247 case GL_INVALID_ENUM: error =
"invalid enum";
break;
248 case GL_INVALID_VALUE: error =
"invalid value";
break;
249 case GL_INVALID_OPERATION: error =
"invalid operation";
break;
250 case GL_STACK_OVERFLOW: error =
"stack overflow";
break;
251 case GL_STACK_UNDERFLOW: error =
"stack underflow";
break;
252 case GL_OUT_OF_MEMORY: error =
"out of memory";
break;
253 case GL_INVALID_FRAMEBUFFER_OPERATION:
254 error =
"invalid framebuffer operation";
break;
255 default: error =
"unknown error";
break;
258 error +=
" | " + std::string(file) +
" (" + std::to_string(line) +
")";
259 ERROR(
"{}: {}", Gl::subsystem_name, error);
268void APIENTRY glDebugOutput([[maybe_unused]] GLenum source,
269 [[maybe_unused]] GLenum type,
270 [[maybe_unused]] GLuint
id,
271 [[maybe_unused]] GLenum severity,
272 [[maybe_unused]] GLsizei length,
273 [[maybe_unused]]
const GLchar *message,
274 [[maybe_unused]]
const void *userParam)
277 if(
id == 131169 ||
id == 131185 ||
id == 131218 ||
id == 131204)
return;
279 std::stringstream out;
280 out <<
"Debug message (" <<
id <<
"): " << message << std::endl;
284 case GL_DEBUG_SOURCE_API:
285 out <<
"Source: API";
break;
286 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
287 out <<
"Source: Window System";
break;
288 case GL_DEBUG_SOURCE_SHADER_COMPILER:
289 out <<
"Source: Shader Compiler";
break;
290 case GL_DEBUG_SOURCE_THIRD_PARTY:
291 out <<
"Source: Third Party";
break;
292 case GL_DEBUG_SOURCE_APPLICATION:
293 out <<
"Source: Application";
break;
294 case GL_DEBUG_SOURCE_OTHER:
295 out <<
"Source: Other";
break;
300 case GL_DEBUG_TYPE_ERROR:
301 out <<
"Type: Error";
break;
302 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
303 out <<
"Type: Deprecated Behaviour";
break;
304 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
305 out <<
"Type: Undefined Behaviour";
break;
306 case GL_DEBUG_TYPE_PORTABILITY:
307 out <<
"Type: Portability";
break;
308 case GL_DEBUG_TYPE_PERFORMANCE:
309 out <<
"Type: Performance";
break;
310 case GL_DEBUG_TYPE_MARKER:
311 out <<
"Type: Marker";
break;
312 case GL_DEBUG_TYPE_PUSH_GROUP:
313 out <<
"Type: Push Group";
break;
314 case GL_DEBUG_TYPE_POP_GROUP:
315 out <<
"Type: Pop Group";
break;
316 case GL_DEBUG_TYPE_OTHER:
317 out <<
"Type: Other";
break;
322 case GL_DEBUG_SEVERITY_HIGH:
323 out <<
"Severity: high";
break;
324 case GL_DEBUG_SEVERITY_MEDIUM:
325 out <<
"Severity: medium";
break;
326 case GL_DEBUG_SEVERITY_LOW:
327 out <<
"Severity: low";
break;
328 case GL_DEBUG_SEVERITY_NOTIFICATION:
329 out <<
"Severity: notification";
break;
333 ERROR(
"{}: {}", Gl::subsystem_name, out.str());
342 this->conf.enable_blending =
true;
348 this->conf.enable_backface_culling =
true;
354 this->conf.enable_multisample =
true;
360 this->conf.enable_depth_test =
true;
366 Gl::init_config = this->conf;
367 return Gl::instance();