diff --git a/configure.ac b/configure.ac index e7f110bad..8146f1c31 100644 --- a/configure.ac +++ b/configure.ac @@ -91,7 +91,7 @@ WX_CONFIG_CHECK( is in LD_LIBRARY_PATH or equivalent variable and wxWidgets version is $wxVersion or above. ]) ], - [core], ) + [core], [--version=2.9]) CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS" CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY" diff --git a/libobs-opengl/gl-cocoa.m b/libobs-opengl/gl-cocoa.m index 143fb2b02..03ec771e1 100644 --- a/libobs-opengl/gl-cocoa.m +++ b/libobs-opengl/gl-cocoa.m @@ -97,11 +97,6 @@ static NSOpenGLContext *gl_context_create(struct gs_init_data *info) return context; } -static inline void required_extension_error(const char *extension) -{ - blog(LOG_ERROR, "OpenGL extension %s is required", extension); -} - static bool gl_init_extensions(device_t device) { glewExperimental=true; @@ -112,27 +107,6 @@ static bool gl_init_extensions(device_t device) return false; } - if(!GLEW_VERSION_2_1) { - blog(LOG_ERROR, "OpenGL 2.1 minimum required by the graphics " - "adapter"); - return false; - } - - if(!GLEW_ARB_framebuffer_object) { - required_extension_error("GL_ARB_framebuffer_object"); - return false; - } - - if(!GLEW_ARB_separate_shader_objects) { - required_extension_error("GL_ARB_separate_shader_objects"); - return false; - } - - //something inside glew produces error code 1280 (invalid enum) - glGetError(); - - device->copy_type = COPY_TYPE_FBO_BLIT; - return true; } diff --git a/libobs-opengl/gl-subsystem.c b/libobs-opengl/gl-subsystem.c index d72cb229d..d3ce4c0ab 100644 --- a/libobs-opengl/gl-subsystem.c +++ b/libobs-opengl/gl-subsystem.c @@ -18,6 +18,107 @@ #include #include "gl-subsystem.h" +#ifdef _DEBUG +/* Tables for OpenGL debug */ +static const char* debug_source_table[] = { + "API", + "Window System", + "Shader Compiler", + "Third Party" + "Application", + "Other" +}; + +static const char* debug_type_table[] = { + "Error", + "Deprecated Behavior", + "Undefined Behavior", + "Portability", + "Performance", + "Other" +}; + +static const char* debug_severity_table[] = { + "High", + "Medium", + "Low" +}; + +/* ARB and core values are the same. They'll always be linear so no hardcoding. */ +/* The values subtracted are the lowest value in the list of valid values. */ +#define GL_DEBUG_SOURCE_OFFSET(x) (x - GL_DEBUG_SOURCE_API_ARB) +#define GL_DEBUG_TYPE_OFFSET(x) (x - GL_DEBUG_TYPE_ERROR_ARB) +#define GL_DEBUG_SEVERITY_OFFSET(x) (x - GL_DEBUG_SEVERITY_HIGH_ARB) + +static APIENTRY void gl_debug_proc( + GLenum source, GLenum type, GLuint id, GLenum severity, + GLsizei length, const GLchar *message, GLvoid *data ) +{ + blog( LOG_DEBUG, + "[%s][%s]{%s}: %.*s", + debug_source_table[GL_DEBUG_SOURCE_OFFSET(source)], + debug_type_table[GL_DEBUG_TYPE_OFFSET(type)], + debug_severity_table[GL_DEBUG_SEVERITY_OFFSET(severity)], + length, message + ); +} + +static void gl_enable_debug() +{ + /* Perhaps we should create GLEW contexts? */ + + if (GLEW_VERSION_4_0) + glDebugMessageCallback(gl_debug_proc, NULL); + else if (GLEW_ARB_debug_output) + glDebugMessageCallbackARB(gl_debug_proc, NULL); + else { + blog(LOG_DEBUG, "Failed to set GL debug callback as it is not supported."); + return; + } + + gl_enable(GL_DEBUG_OUTPUT); +} +#else +static void gl_enable_debug() {} +#endif + +static inline void required_extension_error(const char *extension) +{ +} + +static bool gl_init_extensions(struct gs_device* device) +{ + if (!GLEW_VERSION_2_1) { + blog(LOG_ERROR, "obs-studio requires OpenGL version 2.1 or higher."); + return false; + } + + gl_enable_debug(); + + if (!GLEW_VERSION_3_0 && !GLEW_ARB_framebuffer_object) { + blog(LOG_ERROR, "OpenGL extension ARB_framebuffer_object is required."); + return false; + } + + if (GLEW_VERSION_3_1 || GLEW_ARB_seamless_cube_map) { + gl_enable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + } + + if (!GLEW_VERSION_4_1 && !GLEW_ARB_separate_shader_objects) { + blog(LOG_ERROR, "OpenGL extension ARB_separate_shader_objects is required."); + return false; + } + + if (GLEW_ARB_copy_image || GLEW_VERSION_4_2) + device->copy_type = COPY_TYPE_ARB; + else if (GLEW_NV_copy_image) + device->copy_type = COPY_TYPE_NV; + else + device->copy_type = COPY_TYPE_FBO_BLIT; /* ?? */ + + return true; +} + static void clear_textures(struct gs_device *device) { GLenum i; @@ -69,6 +170,11 @@ device_t device_create(struct gs_init_data *info) if (!device->plat) goto fail; + if (!gl_init_extensions(device)) + goto fail; + + gl_enable(GL_CULL_FACE); + glGenProgramPipelines(1, &device->pipeline); if (!gl_success("glGenProgramPipelines")) goto fail; @@ -77,14 +183,6 @@ device_t device_create(struct gs_init_data *info) if (!gl_success("glBindProgramPipeline")) goto fail; -#ifdef _DEBUG - glEnable(GL_DEBUG_OUTPUT); - if (glGetError() == GL_INVALID_ENUM) - blog(LOG_DEBUG, "OpenGL debug information not available"); -#endif - - gl_enable(GL_CULL_FACE); - device_leavecontext(device); device->cur_swap = gl_platform_getswap(device->plat); @@ -1045,7 +1143,7 @@ void device_frustum(device_t device, float left, float right, dst->x.x = nearx2 / rml; dst->z.x = (left+right) / rml; - + dst->y.y = nearx2 / tmb; dst->z.y = (bottom+top) / tmb; diff --git a/libobs-opengl/gl-windows.c b/libobs-opengl/gl-windows.c index dc92b524b..bd2e285f3 100644 --- a/libobs-opengl/gl-windows.c +++ b/libobs-opengl/gl-windows.c @@ -155,10 +155,9 @@ static inline HGLRC gl_init_basic_context(HDC hdc) static const int attribs[] = { - WGL_CONTEXT_MAJOR_VERSION_ARB, 3, - WGL_CONTEXT_MINOR_VERSION_ARB, 2, - WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB | - WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, +#ifdef _DEBUG + WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB, +#endif WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 0, 0 }; @@ -244,29 +243,11 @@ static bool gl_init_extensions(device_t device) return false; } - if (!GLEW_VERSION_2_1) { - blog(LOG_ERROR, "OpenGL 2.1 minimum required by the graphics " - "adapter"); - return false; - } - - if (!GLEW_ARB_framebuffer_object) { - required_extension_error("GL_ARB_framebuffer_object"); - return false; - } - if (!WGLEW_ARB_pixel_format) { required_extension_error("WGL_ARB_pixel_format"); return false; } - if (GLEW_ARB_copy_image) - device->copy_type = COPY_TYPE_ARB; - else if (GLEW_NV_copy_image) - device->copy_type = COPY_TYPE_NV; - else - device->copy_type = COPY_TYPE_FBO_BLIT; - return true; } @@ -377,19 +358,6 @@ static bool init_default_swap(struct gl_platform *plat, device_t device, return true; } -#ifdef _DEBUG -static void APIENTRY gl_debug_message_amd(GLuint id, - GLenum category, - GLenum severity, - GLsizei length, - const GLchar *msg, - void *param) -{ - OutputDebugStringA(msg); - OutputDebugStringA("\n"); -} -#endif - void gl_update(device_t device) { /* does nothing on windows */ @@ -425,19 +393,6 @@ struct gl_platform *gl_platform_create(device_t device, if (!plat->hrc) goto fail; - if (GLEW_ARB_seamless_cube_map) { - glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - gl_success("GL_TEXTURE_CUBE_MAP_SEAMLESS"); - } - -#ifdef _DEBUG - if (GLEW_AMD_debug_output) { - glDebugMessageEnableAMD(0, 0, 0, NULL, true); - glDebugMessageCallbackAMD(gl_debug_message_amd, device); - gl_success("glDebugMessageCallback"); - } -#endif - return plat; fail: diff --git a/libobs-opengl/gl-x11.c b/libobs-opengl/gl-x11.c index 223641ae1..d1eebd6c0 100644 --- a/libobs-opengl/gl-x11.c +++ b/libobs-opengl/gl-x11.c @@ -19,12 +19,11 @@ static const GLenum fb_attribs[] = { }; static const GLenum ctx_attribs[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 2, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB | - GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, +#ifdef _DEBUG + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, +#endif GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - 0, 0 + None, }; static const char* __GLX_error_table[] = { @@ -106,24 +105,14 @@ static void print_info_stuff(struct gs_init_data *info) struct gl_platform *gl_platform_create(device_t device, struct gs_init_data *info) { - /* X11 */ int num_configs = 0; int error_base = 0, event_base = 0; Display *display = XOpenDisplay(NULL); /* Open default screen */ - - /* OBS */ struct gl_platform *plat = bmalloc(sizeof(struct gl_platform)); - - /* GLX */ GLXFBConfig* configs; print_info_stuff(info); - if (!plat) { - blog(LOG_ERROR, "Out of memory"); - return NULL; - } - memset(plat, 0, sizeof(struct gl_platform)); if (!display) { @@ -139,6 +128,17 @@ struct gl_platform *gl_platform_create(device_t device, XSetErrorHandler(GLXErrorHandler); + /* We require glX version 1.4 */ + { + int major = 0, minor = 0; + + glXQueryVersion(display, &major, &minor); + if (major < 1 || minor < 4) { + blog(LOG_ERROR, "GLX version found: %i.%i\nRequired: 1.4", major, minor); + goto fail0; + } + } + glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress("glXCreateContextAttribsARB"); if (!glXCreateContextAttribsARB) { blog(LOG_ERROR, "ARB_GLX_create_context not supported!"); @@ -169,20 +169,18 @@ struct gl_platform *gl_platform_create(device_t device, goto fail2; } - blog(LOG_INFO, "OpenGL version: %s\n", glGetString(GL_VERSION)); - /* Initialize GLEW */ - { + { + glewExperimental = true; GLenum err = glewInit(); + if (GLEW_OK != err) { blog(LOG_ERROR, glewGetErrorString(err)); goto fail2; } } - glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - glEnable(GL_DEBUG_OUTPUT); - glEnable(GL_CULL_FACE); + blog(LOG_INFO, "OpenGL version: %s\n", glGetString(GL_VERSION)); plat->swap.device = device; plat->swap.info = *info; @@ -195,6 +193,7 @@ struct gl_platform *gl_platform_create(device_t device, return plat; fail2: + glXMakeCurrent(display, None, NULL); glXDestroyContext(display, plat->context); fail1: XFree(configs); @@ -236,6 +235,12 @@ void device_leavecontext(device_t device) blog(LOG_ERROR, "Failed to reset current context."); } } + +void gl_update(device_t device) +{ + /* I don't know of anything we can do here. */ +} + void device_load_swapchain(device_t device, swapchain_t swap) { if(!swap)