Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement priority hints for EGL #1700

Merged
merged 2 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Added `PossiblyCurrentContext::make_not_current_in_place(&self)` for when `Send` capability of `NotCurrentContext` is not required.
- Added workaround for EGL drivers reporting `EGL_KHR_platform_gbm` without EGL 1.5 client.
- **Breaking:** Added `make_current_surfaceless(self)` for `{Possibly,Not}CurrentGlContext`.
- Added `GlContext::priority`/`ContextAttributesBuilder::with_priority` to get/set context priority.

# Version 0.32.1

Expand Down
12 changes: 11 additions & 1 deletion glutin/src/api/cgl/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ use objc2_app_kit::{NSOpenGLCPSwapInterval, NSView};
use objc2_foundation::{run_on_main, MainThreadBound};

use crate::config::GetGlConfig;
use crate::context::{AsRawContext, ContextApi, ContextAttributes, RawContext, Robustness};
use crate::context::{
AsRawContext, ContextApi, ContextAttributes, Priority, RawContext, Robustness,
};
use crate::display::GetGlDisplay;
use crate::error::{ErrorKind, Result};
use crate::prelude::*;
Expand Down Expand Up @@ -113,6 +115,10 @@ impl GlContext for NotCurrentContext {
fn context_api(&self) -> ContextApi {
self.inner.context_api()
}

fn priority(&self) -> Priority {
Priority::Medium
}
}

impl GetGlConfig for NotCurrentContext {
Expand Down Expand Up @@ -190,6 +196,10 @@ impl GlContext for PossiblyCurrentContext {
fn context_api(&self) -> ContextApi {
self.inner.context_api()
}

fn priority(&self) -> Priority {
Priority::Medium
}
}

impl GetGlConfig for PossiblyCurrentContext {
Expand Down
53 changes: 52 additions & 1 deletion glutin/src/api/egl/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use glutin_egl_sys::{egl, EGLContext};

use crate::config::{Api, GetGlConfig};
use crate::context::{
self, AsRawContext, ContextApi, ContextAttributes, GlProfile, RawContext, Robustness, Version,
self, AsRawContext, ContextApi, ContextAttributes, GlProfile, Priority, RawContext, Robustness,
Version,
};
use crate::display::{DisplayFeatures, GetGlDisplay};
use crate::error::{ErrorKind, Result};
Expand Down Expand Up @@ -126,6 +127,38 @@ impl Display {
}
}

if let Some(priority) = context_attributes.priority.filter(|_| {
let extensions = &self.inner.display_extensions;

// Some android versions don't report support for this extension, even though
// it's supported.
//
// https://github.com/googlevr/gvr-android-sdk/issues/330
#[cfg(android_platform)]
let android = extensions.contains("EGL_ANDROID_front_buffer_auto_refresh")
&& extensions.contains("EGL_ANDROID_create_native_client_buffer");
#[cfg(not(android_platform))]
let android = false;
Comment on lines +137 to +141
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We wanted less #[cfg] conditional compilation, perhaps this could have been let android = cfg!(android_platform) && ...;?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that, and decided to do it that way for now, since we already do things like that...


extensions.contains("EGL_IMG_context_priority") || android
}) {
let priority = match priority {
Priority::Low => egl::CONTEXT_PRIORITY_LOW_IMG,
Priority::Medium => egl::CONTEXT_PRIORITY_MEDIUM_IMG,
Priority::High => egl::CONTEXT_PRIORITY_HIGH_IMG,
Priority::Realtime => {
if self.inner.display_extensions.contains("EGL_NV_context_priority_realtime") {
egl::CONTEXT_PRIORITY_REALTIME_NV
} else {
egl::CONTEXT_PRIORITY_HIGH_IMG
}
},
};

attrs.push(egl::CONTEXT_PRIORITY_LEVEL_IMG as EGLint);
attrs.push(priority as EGLint);
}

attrs.push(egl::NONE as EGLint);

let shared_context = if let Some(shared_context) =
Expand Down Expand Up @@ -212,6 +245,10 @@ impl GlContext for NotCurrentContext {
fn context_api(&self) -> ContextApi {
self.inner.context_api()
}

fn priority(&self) -> Priority {
self.inner.priority()
}
}

impl GetGlConfig for NotCurrentContext {
Expand Down Expand Up @@ -286,6 +323,10 @@ impl GlContext for PossiblyCurrentContext {
fn context_api(&self) -> ContextApi {
self.inner.context_api()
}

fn priority(&self) -> Priority {
self.inner.priority()
}
}

impl GetGlConfig for PossiblyCurrentContext {
Expand Down Expand Up @@ -380,6 +421,16 @@ impl ContextInner {
}
}

fn priority(&self) -> Priority {
match self.query_attribute(egl::CONTEXT_PRIORITY_LEVEL_IMG as EGLint).map(|a| a as EGLenum)
{
Some(egl::CONTEXT_PRIORITY_LOW_IMG) => Priority::Low,
Some(egl::CONTEXT_PRIORITY_HIGH_IMG) => Priority::High,
Some(egl::CONTEXT_PRIORITY_REALTIME_NV) => Priority::Realtime,
_ => Priority::Medium,
}
}

/// Query the context attribute.
fn query_attribute(&self, attribute: EGLint) -> Option<EGLint> {
unsafe {
Expand Down
12 changes: 10 additions & 2 deletions glutin/src/api/glx/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use glutin_glx_sys::{glx, glx_extra};

use crate::config::GetGlConfig;
use crate::context::{
self, AsRawContext, ContextApi, ContextAttributes, GlProfile, RawContext, ReleaseBehavior,
Robustness, Version,
self, AsRawContext, ContextApi, ContextAttributes, GlProfile, Priority, RawContext,
ReleaseBehavior, Robustness, Version,
};
use crate::display::{DisplayFeatures, GetGlDisplay};
use crate::error::{ErrorKind, Result};
Expand Down Expand Up @@ -281,6 +281,10 @@ impl GlContext for NotCurrentContext {
fn context_api(&self) -> ContextApi {
self.inner.context_api()
}

fn priority(&self) -> Priority {
Priority::Medium
}
}

impl GetGlConfig for NotCurrentContext {
Expand Down Expand Up @@ -353,6 +357,10 @@ impl GlContext for PossiblyCurrentContext {
fn context_api(&self) -> ContextApi {
self.inner.context_api()
}

fn priority(&self) -> Priority {
Priority::Medium
}
}

impl GetGlConfig for PossiblyCurrentContext {
Expand Down
12 changes: 10 additions & 2 deletions glutin/src/api/wgl/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use windows_sys::Win32::Graphics::Gdi::{self as gdi, HDC};

use crate::config::GetGlConfig;
use crate::context::{
self, AsRawContext, ContextApi, ContextAttributes, GlProfile, RawContext, ReleaseBehavior,
Robustness, Version,
self, AsRawContext, ContextApi, ContextAttributes, GlProfile, Priority, RawContext,
ReleaseBehavior, Robustness, Version,
};
use crate::display::{DisplayFeatures, GetGlDisplay};
use crate::error::{ErrorKind, Result};
Expand Down Expand Up @@ -268,6 +268,10 @@ impl GlContext for NotCurrentContext {
fn context_api(&self) -> ContextApi {
self.inner.context_api()
}

fn priority(&self) -> Priority {
Priority::Medium
}
}

impl GetGlDisplay for NotCurrentContext {
Expand Down Expand Up @@ -364,6 +368,10 @@ impl GlContext for PossiblyCurrentContext {
fn context_api(&self) -> ContextApi {
self.inner.context_api()
}

fn priority(&self) -> Priority {
Priority::Medium
}
}

impl AsRawContext for PossiblyCurrentContext {
Expand Down
50 changes: 50 additions & 0 deletions glutin/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ pub trait GlContext: Sealed {
///
/// The returned value's [`Version`] will always be `None`.
fn context_api(&self) -> ContextApi;

/// Get the [`Priority`] used by the context.
fn priority(&self) -> Priority;
}

/// A trait to group common not current operations.
Expand Down Expand Up @@ -224,6 +227,24 @@ impl ContextAttributesBuilder {
self
}

/// Set the priority hint, which might not be honored if the API does not
/// support it, if there are constraints on the number of high priority
/// contexts available in the system, or system policy limits access to
/// high priority contexts to appropriate system privilege level the
/// context creation may fail.
///
/// By default no priority is specified, which corresponds to
/// [`Priority::Medium`].
///
/// # Api specific
///
/// - **WGL/GLX:** not implemented.
/// - **CGL:** not supported.
pub fn with_priority(mut self, priority: Priority) -> Self {
self.attributes.priority = Some(priority);
self
}

/// Build the context attributes.
///
/// The `raw_window_handle` isn't required and here for WGL compatibility.
Expand Down Expand Up @@ -251,6 +272,8 @@ pub struct ContextAttributes {

pub(crate) api: Option<ContextApi>,

pub(crate) priority: Option<Priority>,

pub(crate) shared_context: Option<RawContext>,

pub(crate) raw_window_handle: Option<RawWindowHandle>,
Expand Down Expand Up @@ -471,6 +494,10 @@ impl GlContext for NotCurrentContext {
fn context_api(&self) -> ContextApi {
gl_api_dispatch!(self; Self(context) => context.context_api())
}

fn priority(&self) -> Priority {
gl_api_dispatch!(self; Self(context) => context.priority())
}
}

impl GetGlConfig for NotCurrentContext {
Expand Down Expand Up @@ -599,6 +626,10 @@ impl GlContext for PossiblyCurrentContext {
fn context_api(&self) -> ContextApi {
gl_api_dispatch!(self; Self(context) => context.context_api())
}

fn priority(&self) -> Priority {
gl_api_dispatch!(self; Self(context) => context.priority())
}
}

impl GetGlConfig for PossiblyCurrentContext {
Expand Down Expand Up @@ -645,6 +676,25 @@ pub enum RawContext {
Cgl(*const ffi::c_void),
}

/// Priority hint
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
pub enum Priority {
/// Lowest priority, contexts using this priority give way for most other
/// contexts.
Low,
/// Default priority.
#[default]
Medium,
/// High priority is usually required for VR applications.
High,
/// Realtime priority contexts are executed immediately and preempt any
/// current context running.
///
/// When such context is not supported, [`Priority::High`] will be requested
/// instead.
Realtime,
}

/// Pick `GlProfile` and `Version` based on the provided params.
#[cfg(any(egl_backend, glx_backend, wgl_backend))]
pub(crate) fn pick_profile(
Expand Down
2 changes: 2 additions & 0 deletions glutin_egl_sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ fn main() {
"EGL_EXT_platform_wayland",
"EGL_EXT_platform_x11",
"EGL_EXT_swap_buffers_with_damage",
"EGL_IMG_context_priority",
"EGL_KHR_create_context",
"EGL_KHR_create_context_no_error",
"EGL_KHR_display_reference",
Expand All @@ -47,6 +48,7 @@ fn main() {
"EGL_KHR_swap_buffers_with_damage",
"EGL_KHR_wait_sync",
"EGL_MESA_platform_gbm",
"EGL_NV_context_priority_realtime",
]);

if target.contains("ios") {
Expand Down
Loading