Changeset View
Changeset View
Standalone View
Standalone View
source/lib/ogl.cpp
/* Copyright (C) 2017 Wildfire Games. | /* Copyright (C) 2019 Wildfire Games. | ||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
* "Software"), to deal in the Software without restriction, including | * "Software"), to deal in the Software without restriction, including | ||||
* without limitation the rights to use, copy, modify, merge, publish, | * without limitation the rights to use, copy, modify, merge, publish, | ||||
* distribute, sublicense, and/or sell copies of the Software, and to | * distribute, sublicense, and/or sell copies of the Software, and to | ||||
* permit persons to whom the Software is furnished to do so, subject to | * permit persons to whom the Software is furnished to do so, subject to | ||||
* the following conditions: | * the following conditions: | ||||
▲ Show 20 Lines • Show All 406 Lines • ▼ Show 20 Lines | for(;;) | ||||
error_enountered = true; | error_enountered = true; | ||||
dump_gl_error(err); | dump_gl_error(err); | ||||
} | } | ||||
if(error_enountered) | if(error_enountered) | ||||
debug_printf("%s:%d: OpenGL error(s) occurred: %s (%04x)\n", file, line, ogl_GetErrorName(first_error), (unsigned int)first_error); | debug_printf("%s:%d: OpenGL error(s) occurred: %s (%04x)\n", file, line, ogl_GetErrorName(first_error), (unsigned int)first_error); | ||||
} | } | ||||
void ogl_OnDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei UNUSED(length), const GLchar* message, const void* UNUSED(user_param)) | |||||
{ | |||||
std::string str_source = "unknown"; | |||||
std::string str_type = "unknown"; | |||||
std::string str_severity = "unknown"; | |||||
switch (source) | |||||
{ | |||||
case GL_DEBUG_SOURCE_API: | |||||
str_source = "the API"; | |||||
break; | |||||
case GL_DEBUG_SOURCE_WINDOW_SYSTEM: | |||||
str_source = "the window system"; | |||||
break; | |||||
case GL_DEBUG_SOURCE_SHADER_COMPILER: | |||||
str_source = "the shader compiler"; | |||||
break; | |||||
case GL_DEBUG_SOURCE_THIRD_PARTY: | |||||
str_source = "a third party"; | |||||
break; | |||||
case GL_DEBUG_SOURCE_APPLICATION: | |||||
str_source = "the application"; | |||||
break; | |||||
case GL_DEBUG_SOURCE_OTHER: | |||||
str_source = "somewhere"; | |||||
break; | |||||
} | |||||
switch (type) | |||||
{ | |||||
case GL_DEBUG_TYPE_ERROR: | |||||
str_type = "error"; | |||||
break; | |||||
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: | |||||
str_type = "deprecated behaviour"; | |||||
break; | |||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: | |||||
str_type = "undefined behaviour"; | |||||
break; | |||||
case GL_DEBUG_TYPE_PORTABILITY: | |||||
str_type = "portability"; | |||||
break; | |||||
case GL_DEBUG_TYPE_PERFORMANCE: | |||||
str_type = "performance"; | |||||
break; | |||||
case GL_DEBUG_TYPE_OTHER: | |||||
str_type = "other"; | |||||
break; | |||||
case GL_DEBUG_TYPE_MARKER: | |||||
str_type = "marker"; | |||||
break; | |||||
case GL_DEBUG_TYPE_PUSH_GROUP: | |||||
str_type = "push group"; | |||||
break; | |||||
case GL_DEBUG_TYPE_POP_GROUP: | |||||
str_type = "pop group"; | |||||
break; | |||||
} | |||||
switch (severity) | |||||
{ | |||||
case GL_DEBUG_SEVERITY_HIGH: | |||||
str_severity = "high"; | |||||
break; | |||||
case GL_DEBUG_SEVERITY_MEDIUM: | |||||
str_severity = "medium"; | |||||
break; | |||||
case GL_DEBUG_SEVERITY_LOW: | |||||
str_severity = "low"; | |||||
break; | |||||
case GL_DEBUG_SEVERITY_NOTIFICATION: | |||||
str_severity = "notification"; | |||||
break; | |||||
} | |||||
debug_printf("OpenGL %s of severity %s from %s id %d: %s\n", str_type.c_str(), str_severity.c_str(), str_source.c_str(), id, message); | |||||
} | |||||
// ignore and reset the specified error (as returned by glGetError). | // ignore and reset the specified error (as returned by glGetError). | ||||
vladislavbelov: Space. | |||||
// any other errors that have occurred are reported as ogl_WarnIfError would. | // any other errors that have occurred are reported as ogl_WarnIfError would. | ||||
// | // | ||||
// this is useful for suppressing annoying error messages, e.g. | // this is useful for suppressing annoying error messages, e.g. | ||||
// "invalid enum" for GL_CLAMP_TO_EDGE even though we've already | // "invalid enum" for GL_CLAMP_TO_EDGE even though we've already | ||||
Not Done Inline ActionsMaybe CC, Idr snake case for lib? vladislavbelov: Maybe CC, Idr snake case for `lib`? | |||||
// warned the user that their OpenGL implementation is too old. | // warned the user that their OpenGL implementation is too old. | ||||
bool ogl_SquelchError(GLenum err_to_ignore) | bool ogl_SquelchError(GLenum err_to_ignore) | ||||
{ | { | ||||
// glGetError may return multiple errors, so we poll it in a loop. | // glGetError may return multiple errors, so we poll it in a loop. | ||||
// the debug_printf should only happen once (if this is set), though. | // the debug_printf should only happen once (if this is set), though. | ||||
bool error_enountered = false; | bool error_enountered = false; | ||||
bool error_ignored = false; | bool error_ignored = false; | ||||
GLenum first_error = 0; | GLenum first_error = 0; | ||||
for(;;) | for(;;) | ||||
{ | { | ||||
GLenum err = glGetError(); | GLenum err = glGetError(); | ||||
if(err == GL_NO_ERROR) | if(err == GL_NO_ERROR) | ||||
break; | break; | ||||
if(err == err_to_ignore) | if(err == err_to_ignore) | ||||
{ | { | ||||
error_ignored = true; | error_ignored = true; | ||||
continue; | continue; | ||||
} | } | ||||
if(!error_enountered) | if(!error_enountered) | ||||
first_error = err; | first_error = err; | ||||
error_enountered = true; | error_enountered = true; | ||||
dump_gl_error(err); | dump_gl_error(err); | ||||
} | } | ||||
if(error_enountered) | if(error_enountered) | ||||
debug_printf("OpenGL error(s) occurred: %04x\n", (unsigned int)first_error); | debug_printf("OpenGL error(s) occurred: %04x\n", (unsigned int)first_error); | ||||
return error_ignored; | return error_ignored; | ||||
} | } | ||||
//---------------------------------------------------------------------------- | //---------------------------------------------------------------------------- | ||||
// feature and limit detect | // feature and limit detect | ||||
//---------------------------------------------------------------------------- | //---------------------------------------------------------------------------- | ||||
GLint ogl_max_tex_size = -1; // [pixels] | GLint ogl_max_tex_size = -1; // [pixels] | ||||
GLint ogl_max_tex_units = -1; // limit on GL_TEXTUREn | GLint ogl_max_tex_units = -1; // limit on GL_TEXTUREn | ||||
// call after each video mode change, since thereafter extension functions | // call after each video mode change, since thereafter extension functions | ||||
// may have changed [address]. | // may have changed [address]. | ||||
void ogl_Init() | void ogl_Init() | ||||
{ | { | ||||
// cache extension list and versions for oglHave*. | // cache extension list and versions for oglHave*. | ||||
// note: this is less about performance (since the above are not | // note: this is less about performance (since the above are not | ||||
// time-critical) than centralizing the 'OpenGL is ready' check. | // time-critical) than centralizing the 'OpenGL is ready' check. | ||||
exts = (const char*)glGetString(GL_EXTENSIONS); | exts = (const char*)glGetString(GL_EXTENSIONS); | ||||
ENSURE(exts); // else: called before OpenGL is ready for use | ENSURE(exts); // else: called before OpenGL is ready for use | ||||
have_12 = ogl_HaveVersion("1.2"); | have_12 = ogl_HaveVersion("1.2"); | ||||
have_13 = ogl_HaveVersion("1.3"); | have_13 = ogl_HaveVersion("1.3"); | ||||
have_14 = ogl_HaveVersion("1.4"); | have_14 = ogl_HaveVersion("1.4"); | ||||
have_15 = ogl_HaveVersion("1.5"); | have_15 = ogl_HaveVersion("1.5"); | ||||
have_20 = ogl_HaveVersion("2.0"); | have_20 = ogl_HaveVersion("2.0"); | ||||
have_21 = ogl_HaveVersion("2.1"); | have_21 = ogl_HaveVersion("2.1"); | ||||
have_30 = ogl_HaveVersion("3.0"); | have_30 = ogl_HaveVersion("3.0"); | ||||
importExtensionFunctions(); | importExtensionFunctions(); | ||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &ogl_max_tex_size); | glGetIntegerv(GL_MAX_TEXTURE_SIZE, &ogl_max_tex_size); | ||||
#if !CONFIG2_GLES | #if !CONFIG2_GLES | ||||
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &ogl_max_tex_units); | glGetIntegerv(GL_MAX_TEXTURE_UNITS, &ogl_max_tex_units); | ||||
#endif | #endif | ||||
#ifndef NDEBUG | |||||
#if CONFIG2_GLES | |||||
bool is_core = ogl_HaveVersion("3.2"); | |||||
Not Done Inline ActionsMight use a macro to reduce the code duplication. vladislavbelov: Might use a macro to reduce the code duplication. | |||||
#else | |||||
bool is_core = ogl_HaveVersion("4.3"); | |||||
Not Done Inline ActionsI suppose it won't be visible on Windows. But I might fix it later. vladislavbelov: I suppose it won't be visible on Windows. But I might fix it later. | |||||
#endif | |||||
if (is_core || ogl_HaveExtension("GL_KHR_debug")) | |||||
{ | |||||
glEnable(GL_DEBUG_OUTPUT); | |||||
pglDebugMessageCallbackKHR(ogl_OnDebugMessage, nullptr); | |||||
// Filter out our own debug group messages | |||||
GLuint id = 0x0ad; | |||||
pglDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, GL_DONT_CARE, 1, &id, GL_FALSE); | |||||
pglDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, GL_DONT_CARE, 1, &id, GL_FALSE); | |||||
} | |||||
#endif | |||||
} | } |
Wildfire Games · Phabricator
Space.