1111#include " src/logging.h"
1212#include " src/video.h"
1313
14+ // platform includes
15+ #if !defined(__FreeBSD__)
16+ #include < sys/capability.h>
17+ #endif
18+
1419extern " C" {
1520#include < libavutil/pixdesc.h>
1621}
@@ -387,6 +392,18 @@ namespace egl {
387392 }
388393
389394 std::optional<ctx_t > make_ctx (display_t ::pointer display) {
395+ bool nice_warning = false ;
396+ #if !defined(__FreeBSD__)
397+ cap_t caps = cap_get_proc ();
398+
399+ cap_value_t sys_nice = CAP_SYS_NICE;
400+ if (cap_set_flag (caps, CAP_EFFECTIVE, 1 , &sys_nice, CAP_SET) || cap_set_proc (caps)) {
401+ BOOST_LOG (debug) << " Failed to gain CAP_SYS_NICE" sv;
402+ nice_warning = true ;
403+ }
404+ cap_free (caps);
405+ #endif
406+
390407 constexpr int conf_attr[] {
391408 EGL_RENDERABLE_TYPE,
392409 EGL_OPENGL_BIT,
@@ -405,20 +422,48 @@ namespace egl {
405422 return std::nullopt ;
406423 }
407424
408- constexpr int attr[] {
409- EGL_CONTEXT_CLIENT_VERSION,
410- 3 ,
411- EGL_NONE
412- };
425+ const char *extension_st = eglQueryString (display, EGL_EXTENSIONS);
426+
427+ std::vector<EGLint> attr;
428+ attr.push_back (EGL_CONTEXT_CLIENT_VERSION);
429+ attr.push_back (3 );
430+
431+ // Only add the realtime/high priority attribute if the driver explicitly supports it
432+ if (extension_st && std::string_view (extension_st).contains (" EGL_NV_context_priority_realtime" sv)) {
433+ BOOST_LOG (debug) << " EGL: Realtime priority context supported" sv;
434+ attr.push_back (EGL_CONTEXT_PRIORITY_LEVEL_IMG);
435+ attr.push_back (EGL_CONTEXT_PRIORITY_REALTIME_NV);
436+ } else if (extension_st && std::string_view (extension_st).contains (" EGL_IMG_context_priority" sv)) {
437+ BOOST_LOG (debug) << " EGL: High priority context supported" sv;
438+ attr.push_back (EGL_CONTEXT_PRIORITY_LEVEL_IMG);
439+ attr.push_back (EGL_CONTEXT_PRIORITY_HIGH_IMG);
440+ }
441+ attr.push_back (EGL_NONE);
413442
414- ctx_t ctx {display, eglCreateContext (display, conf, EGL_NO_CONTEXT, attr)} ;
415- if (fail () ) {
443+ EGLContext raw_ctx = eglCreateContext (display, conf, EGL_NO_CONTEXT, attr. data ()) ;
444+ if (raw_ctx == EGL_NO_CONTEXT ) {
416445 BOOST_LOG (error) << " Couldn't create EGL context: [" sv << util::hex (eglGetError ()).to_string_view () << ' ]' ;
417446 return std::nullopt ;
418447 }
419448
420- TUPLE_EL_REF (ctx_p, 1 , ctx.el );
421- if (!eglMakeCurrent (display, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx_p)) {
449+ ctx_t ctx {display, raw_ctx};
450+
451+ EGLint actual_priority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
452+ std::string actual_priority_str = " MEDIUM" ;
453+ if (eglQueryContext (display, raw_ctx, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &actual_priority)) {
454+ if (actual_priority == EGL_CONTEXT_PRIORITY_REALTIME_NV) {
455+ actual_priority_str = " REALTIME" ;
456+ } else if (actual_priority == EGL_CONTEXT_PRIORITY_HIGH_IMG) {
457+ actual_priority_str = " HIGH" ;
458+ }
459+ if (nice_warning) {
460+ BOOST_LOG (warning) << " EGL: Context Priority set to " sv << actual_priority_str << " but CAP_SYS_NICE capability is missing" sv;
461+ } else {
462+ BOOST_LOG (info) << " EGL: Context Priority set to " sv << actual_priority_str;
463+ }
464+ }
465+
466+ if (!eglMakeCurrent (display, EGL_NO_SURFACE, EGL_NO_SURFACE, raw_ctx)) {
422467 BOOST_LOG (error) << " Couldn't make current display" sv;
423468 return std::nullopt ;
424469 }
@@ -453,6 +498,14 @@ namespace egl {
453498
454499 gl::ctx.PixelStorei (GL_UNPACK_ALIGNMENT, 1 );
455500
501+ #if !defined(__FreeBSD__)
502+ caps = cap_get_proc ();
503+ if (cap_set_flag (caps, CAP_EFFECTIVE, 1 , &sys_nice, CAP_CLEAR) || cap_set_proc (caps)) {
504+ BOOST_LOG (debug) << " Failed to drop CAP_SYS_NICE" sv;
505+ }
506+ cap_free (caps);
507+ #endif
508+
456509 return ctx;
457510 }
458511
0 commit comments