Skip to content

Commit 9e2cd8d

Browse files
committed
gl: add GlClientApi option to override automatic API selection
On desktop Linux (Mesa), EGL reports both OpenGL and OpenGL ES as available client APIs. wgpu-hal automatically prefers desktop OpenGL, which prevents GLES-only features (e.g. EXTERNAL_TEXTURE / GL_OES_EGL_image_external_essl3) from being advertised by the adapter. Add a `GlClientApi` enum and a `client_api` field to `GlBackendOptions` so callers can explicitly request `OpenGlEs` (or `OpenGl`) instead of relying on the auto-detection heuristic.
1 parent bd49dbb commit 9e2cd8d

3 files changed

Lines changed: 43 additions & 5 deletions

File tree

wgpu-hal/src/gles/egl.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ impl Inner {
395395
flags: wgt::InstanceFlags,
396396
egl: Arc<EglInstance>,
397397
display: khronos_egl::Display,
398+
client_api: wgt::GlClientApi,
398399
force_gles_minor_version: wgt::Gles3MinorVersion,
399400
) -> Result<Self, crate::InstanceError> {
400401
let version = initialize_display(&egl, display)
@@ -456,6 +457,14 @@ impl Inner {
456457
false
457458
};
458459

460+
let use_opengl = match client_api {
461+
wgt::GlClientApi::Auto | wgt::GlClientApi::OpenGl => supports_opengl,
462+
wgt::GlClientApi::OpenGlEs => {
463+
log::debug!("GlClientApi::OpenGlEs: skipping desktop OpenGL, forcing GLES");
464+
false
465+
}
466+
};
467+
459468
let mut khr_context_flags = 0;
460469
let supports_khr_context = display_extensions.contains("EGL_KHR_create_context");
461470

@@ -466,7 +475,7 @@ impl Inner {
466475
gl_context_attributes.push(3);
467476
gl_context_attributes.push(khronos_egl::CONTEXT_MINOR_VERSION);
468477
gl_context_attributes.push(3);
469-
if supports_opengl && force_gles_minor_version != wgt::Gles3MinorVersion::Automatic {
478+
if use_opengl && force_gles_minor_version != wgt::Gles3MinorVersion::Automatic {
470479
log::warn!("Ignoring specified GLES minor version as OpenGL is used");
471480
}
472481
gles_context_attributes.push(khronos_egl::CONTEXT_MAJOR_VERSION);
@@ -582,7 +591,7 @@ impl Inner {
582591
}
583592
};
584593

585-
let result = if supports_opengl {
594+
let result = if use_opengl {
586595
create_context(khronos_egl::OPENGL_API, &gl_context_attributes).or_else(
587596
|gl_error| {
588597
log::debug!("Failed to create desktop OpenGL context: {gl_error}, falling back to OpenGL ES");
@@ -899,6 +908,7 @@ impl crate::Instance for Instance {
899908
desc.flags,
900909
egl,
901910
display,
911+
desc.backend_options.gl.client_api,
902912
desc.backend_options.gl.gles_minor_version,
903913
)?;
904914

wgpu-types/src/backend.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,14 @@ impl BackendOptions {
248248
/// Part of [`BackendOptions`].
249249
#[derive(Clone, Debug, Default)]
250250
pub struct GlBackendOptions {
251+
/// Which EGL client API to use when creating the context.
252+
///
253+
/// Defaults to [`GlClientApi::Auto`], which prefers desktop OpenGL when
254+
/// the EGL display advertises it and falls back to OpenGL ES otherwise.
255+
/// Set to [`GlClientApi::OpenGlEs`] to force OpenGL ES even on machines
256+
/// that also support desktop OpenGL (required for GLES-only features such
257+
/// as `EXTERNAL_TEXTURE`).
258+
pub client_api: GlClientApi,
251259
/// Which OpenGL ES 3 minor version to request, if using OpenGL ES.
252260
pub gles_minor_version: Gles3MinorVersion,
253261
/// Behavior of OpenGL fences. Affects how `on_completed_work_done` and `device.poll` behave.
@@ -277,6 +285,7 @@ impl GlBackendOptions {
277285
let gles_minor_version = Gles3MinorVersion::from_env().unwrap_or_default();
278286
let debug_fns = GlDebugFns::from_env().unwrap_or_default();
279287
Self {
288+
client_api: GlClientApi::Auto,
280289
gles_minor_version,
281290
fence_behavior: GlFenceBehavior::Normal,
282291
debug_fns,
@@ -292,6 +301,7 @@ impl GlBackendOptions {
292301
let fence_behavior = self.fence_behavior.with_env();
293302
let debug_fns = self.debug_fns.with_env();
294303
Self {
304+
client_api: self.client_api,
295305
gles_minor_version,
296306
fence_behavior,
297307
debug_fns,
@@ -1018,3 +1028,21 @@ impl GlFenceBehavior {
10181028
}
10191029
}
10201030
}
1031+
1032+
/// Selects which EGL client API is used when creating the OpenGL context.
1033+
///
1034+
/// Used in [`GlBackendOptions::client_api`].
1035+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1036+
pub enum GlClientApi {
1037+
/// Prefer desktop OpenGL when the EGL display advertises it; fall back to
1038+
/// OpenGL ES otherwise. This is the default behaviour.
1039+
#[default]
1040+
Auto,
1041+
/// Always request a desktop OpenGL context.
1042+
///
1043+
/// Falls back to OpenGL ES if the EGL display does not support desktop GL.
1044+
OpenGl,
1045+
/// Always request an OpenGL ES context, even when desktop OpenGL is
1046+
/// available.
1047+
OpenGlEs,
1048+
}

wgpu/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ pub use wgt::{
138138
DownlevelLimits, Dx12BackendOptions, Dx12Compiler, Dx12SwapchainKind,
139139
Dx12UseFrameLatencyWaitableObject, DxcShaderModel, DynamicOffset, ExperimentalFeatures,
140140
Extent3d, ExternalTextureFormat, ExternalTextureTransferFunction, Face, Features, FeaturesWGPU,
141-
FeaturesWebGPU, FilterMode, ForceShaderModelToken, FrontFace, GlBackendOptions, GlDebugFns,
142-
GlFenceBehavior, Gles3MinorVersion, HalCounters, ImageSubresourceRange, IndexFormat,
143-
InstanceDescriptor, InstanceFlags, InternalCounters, Limits, LoadOpDontCare,
141+
FeaturesWebGPU, FilterMode, ForceShaderModelToken, FrontFace, GlBackendOptions, GlClientApi,
142+
GlDebugFns, GlFenceBehavior, Gles3MinorVersion, HalCounters, ImageSubresourceRange,
143+
IndexFormat, InstanceDescriptor, InstanceFlags, InternalCounters, Limits, LoadOpDontCare,
144144
MemoryBudgetThresholds, MemoryHints, MipmapFilterMode, MultisampleState, NoopBackendOptions,
145145
Origin2d, Origin3d, PassthroughShaderEntryPoint, PipelineStatisticsTypes, PollError,
146146
PollStatus, PolygonMode, PowerPreference, PredefinedColorSpace, PresentMode,

0 commit comments

Comments
 (0)