Cogs.Core
GLContext.cpp
1#include "GLContext.h"
2
3#include "GLFuncPointers.h"
4#include "Foundation/Logging/Logger.h"
5#include "Foundation/Platform/DebugUtils.h"
6
7
8namespace {
9#ifndef __EMSCRIPTEN__
10 Cogs::Logging::Log logger = Cogs::Logging::getLogger("GLContext");
11#endif
12
13#if 0
14 oid CALLBACK DebugCallback(GLenum source,
15 GLenum type,
16 GLuint id,
17 GLenum /*severity*/,
18 GLsizei /*length*/,
19 const GLchar* message,
20 const void* /*userParam*/) {
21 switch (type) {
22 case GL_DEBUG_TYPE_OTHER:
23 if ((source != GL_DEBUG_SOURCE_APPLICATION) || (id != 1)) {
24 break;
25 }
26 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: // Yes, we know.
27 case GL_DEBUG_TYPE_MARKER:
28 case GL_DEBUG_TYPE_PUSH_GROUP:
29 case GL_DEBUG_TYPE_POP_GROUP:
30 return;
31 default:
32 break;
33 }
34
35 // Suppress some useless warnings
36 switch (id) {
37 case 131154: // NVIDIA: "Pixel-path performance warning: Pixel transfer is synchronized with 3D rendering."
38 case 131218: // NVIDIA: "Shader will be recompiled due to GL state mismatches"
39 case 131184: // NVIDIA: "Buffer detailed info"
40 case 131185: // NVIDIA: "Buffer detailed info: Buffer object 1 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations."
41 return;
42 case 131204: // NVIDIA: Texture state usage warning: Texture 0 is base level inconsistent. Check texture size.
43 //NOTE: This message shows up for unknown reasons regarding texture 0, which is the default texture id.
44 if (std::strstr(message, "Texture 0") || std::strstr(message, "texture object (0)")) {
45 return;
46 }
47 default:
48 break;
49 }
50
51 LOG_DEBUG(logger, "%d %d(%d) %s", source, type, id, message);
52 }
53#endif
54
55#ifndef __EMSCRIPTEN__
56
57// Handle missing WIN32 define on non-WIN32
58#ifndef CALLBACK
59#define CALLBACK
60#endif
61
62 // Compatible with glDebugMessageCallback and glDebugMessageCallbackKHR
63 void CALLBACK debugCallback(GLenum source,
64 GLenum type,
65 GLuint id,
66 GLenum severity,
67 GLsizei /*length*/,
68 const char* message,
69 const void* userParam)
70 {
71 const char* contextName = static_cast<const char*>(userParam);
72
73 Cogs::Logging::Category category = Cogs::Logging::Category::Debug;
74 switch (severity) {
75 case GL_DEBUG_SEVERITY_HIGH:
76 category = Cogs::Logging::Category::Error;
77 break;
78 case GL_DEBUG_SEVERITY_MEDIUM:
79 category = Cogs::Logging::Category::Warning;
80 break;
81 case GL_DEBUG_SEVERITY_LOW:
82 category = Cogs::Logging::Category::Debug;
83 break;
84 case GL_DEBUG_SEVERITY_NOTIFICATION:
85 category = Cogs::Logging::Category::Trace;
86 break;
87 default:
88 break;
89 }
90
91 switch (type)
92 {
93 case GL_DEBUG_TYPE_ERROR: [[fallthrough]];
94 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: [[fallthrough]];
95 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: [[fallthrough]];
96 case GL_DEBUG_TYPE_PORTABILITY: [[fallthrough]];
97 case GL_DEBUG_TYPE_PERFORMANCE:
98 break;
99 case GL_DEBUG_TYPE_MARKER: [[fallthrough]];
100 case GL_DEBUG_TYPE_PUSH_GROUP: [[fallthrough]];
101 case GL_DEBUG_TYPE_POP_GROUP:
102 return;
103 case GL_DEBUG_TYPE_OTHER:
104 if (strstr(message, "object (0)")) {
105 return;
106 }
107 switch (id) {
108 case 0x00020071: //Buffer detailed info : Buffer object 1 (boun...
109 return;
110 case 0x00020043: //Rasterization quality warning: A non-fullscreen clear caused a fallback from CSAA to MSAA.
111 return;
112 case 0x00020044: // Rasterization usage warning: Dithering is enabled, but is not supported for integer framebuffers.
113 return;
114 case 0x00020070: //Buffer info: Total VBO memory usage in the system...
115 return;
116 default:
117 break;
118 }
119 break;
120 default:
121 break;
122 }
123
124 if (contextName) {
125 logger.logFileLine(__FILE__, __LINE__, category, Cogs::Logging::ErrorGroup::Unspecified, "%s: %d %d(%d) %s", contextName, source, type, id, message);
126 }
127 else {
128 logger.logFileLine(__FILE__, __LINE__, category, Cogs::Logging::ErrorGroup::Unspecified, "%d %d(%d) %s", source, type, id, message);
129 }
130
131//#ifdef COGSRENDERING_GFX_BREAK
132// if (Cogs::isBeingDebugged()) {
133// static bool always = false;
134// char c = '\0';
135// while (c != 'y' && !always) {
136// printf("Continue y/n/a: ");
137// c = getc(stdin);
138// if (c == 'n') abort();
139// if (c == 'a') always = true;
140// }
141// }
142//#endif
143
144 }
145
146#endif
147
148}
149
150
151bool Cogs::setUpGLDebugging(const char* contextName, GLContextBase::Platform platform)
152{
153#ifdef __EMSCRIPTEN__
154 (void)contextName;
155 (void)platform;
156 return false;
157#else
158
159 int major = 0;
160 int minor = 0;
161 glGetIntegerv(GL_MAJOR_VERSION, &major);
162 glGetIntegerv(GL_MINOR_VERSION, &minor);
163 if (4 < major || (major == 4 && 3 <= minor)) {
164#ifndef __APPLE__
165 glDebugMessageCallback(debugCallback, contextName);
166 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, true);
167 glEnable(GL_DEBUG_OUTPUT);
168 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
169 glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION,
170 GL_DEBUG_TYPE_OTHER,
171 0,
172 GL_DEBUG_SEVERITY_LOW, -1, "Initialized OpenGL debug output.");
173 goto success;
174#endif
175 }
176 else if(3 <= major) {
177 int numExtensions = 0;
178 glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
179 for (int i = 0; i < numExtensions; i++) {
180
181 switch (Cogs::hash(Cogs::StringView((const char*)glGetStringi(GL_EXTENSIONS, i)))) {
182
183 case Cogs::hash("GL_KHR_debug"):
184 // According to GL_KHR_debug extension specification, in an ES context, the extension API funcs have KHR suffices, but not in a GL context
185 switch (platform) {
186
187#ifdef COGS_OPENGL20
188 case GLContextBase::Platform::GL:
189 glDebugMessageCallback(debugCallback, contextName);
190 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, true);
191 glEnable(GL_DEBUG_OUTPUT);
192 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
193 glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION,
194 GL_DEBUG_TYPE_OTHER,
195 0,
196 GL_DEBUG_SEVERITY_LOW, -1, "Initialized OpenGL debug output.");
197 break;
198#endif
199
200#if defined(COGS_OPENGLES30)
201 case GLContextBase::Platform::ES3:
202 glDebugMessageCallbackKHR(debugCallback, contextName);
203 glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, true);
204 glEnable(GL_DEBUG_OUTPUT_KHR);
205 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);
206 glDebugMessageInsertKHR(GL_DEBUG_SOURCE_APPLICATION_KHR,
207 GL_DEBUG_TYPE_OTHER_KHR,
208 0,
209 GL_DEBUG_SEVERITY_LOW_KHR, -1, "Initialized OpenGL debug output.");
210 break;
211#endif
212 default:
213 break;
214 }
215 goto success;
216
217 default:
218 break;
219 }
220 }
221 }
222
223 LOG_INFO(logger, "No supported debug extension available");
224 return false;
225
226success:
227
228#if 0
229#ifdef __linux__
230#include "Foundation/Platform/X11Module.h"
231#endif
232
233#if defined(__linux__)
234 // Sync to ensure any errors generated are processed.
235 X11Module::instance().XSync(settings.windowData->display, false);
236#endif
237#endif
238
239 return true;
240#endif
241}
Log implementation class.
Definition: LogManager.h:139
void logFileLine(const char *file, const int line, const Category category, uint32_t errorNumber, _Printf_format_string_ const char *fmt,...) const VALIDATE_ARGS(6)
Log a formatted message with file/line information.
Definition: LogManager.h:147
Provides a weakly referenced view over the contents of a string.
Definition: StringView.h:24
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
@ Unspecified
The default error number for legacy logger usage.
Definition: LogManager.h:49
Category
Logging categories used to filter log messages.
Definition: LogManager.h:31
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
Definition: HashFunctions.h:62