Skip to content
Draft
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
22 changes: 13 additions & 9 deletions examples/features/src/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,16 @@ impl SurfaceWrapper {
/// On wasm, we need to create the surface here, as the WebGL backend needs
/// a surface (and hence a canvas) to be present to create the adapter.
///
/// On Wayland our context creation (both inside the [`Instance`] and [`Adapter`]) requires
/// access to the `RawDisplayHandle`. Since this is currently not provided, a compatible
/// context is set up via the surface instead.
///
/// We cannot unconditionally create a surface here, as Android requires
/// us to wait until we receive the `Resumed` event to do so.
/// us to wait until we receive [`Event::Resumed`] to do so.
fn pre_adapter(&mut self, instance: &Instance, window: Arc<Window>) {
if cfg!(target_arch = "wasm32") {
// XXX: Also needed for EGL+Wayland!
// if cfg!(target_arch = "wasm32") {
if !cfg!(target_os = "android") {
self.surface = Some(instance.create_surface(window).unwrap());
}
}
Expand All @@ -153,6 +159,8 @@ impl SurfaceWrapper {
fn start_condition(e: &Event<()>) -> bool {
match e {
// On all other platforms, we can create the surface immediately.
// XXX: winit was improved to consistently emit a Resumed event on all platforms, which
// is the right place to create surfaces... Most platforms emit it right after Init.
Event::NewEvents(StartCause::Init) => !cfg!(target_os = "android"),
// On android we need to wait for a resumed event to create the surface.
Event::Resumed => cfg!(target_os = "android"),
Expand All @@ -174,13 +182,9 @@ impl SurfaceWrapper {
log::info!("Surface resume {window_size:?}");

// We didn't create the surface in pre_adapter, so we need to do so now.
if !cfg!(target_arch = "wasm32") {
self.surface = Some(context.instance.create_surface(window).unwrap());
}

// From here on, self.surface should be Some.

let surface = self.surface.as_ref().unwrap();
let surface = self
.surface
.get_or_insert_with(|| context.instance.create_surface(window).unwrap());

// Get the default configuration,
let mut config = surface
Expand Down
33 changes: 19 additions & 14 deletions examples/features/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,24 +203,29 @@ pub(crate) async fn get_adapter_with_capabilities_or_from_env(
);
adapter
} else {
let adapters = instance.enumerate_adapters(Backends::all());

let mut chosen_adapter = None;
for adapter in adapters {
if let Some(surface) = surface {
if !adapter.is_surface_supported(surface) {

if let Some(surface) = surface {
chosen_adapter = instance
.request_adapter(&wgpu::RequestAdapterOptionsBase {
compatible_surface: Some(surface),
..Default::default()
})
.await
.ok();
} else {
let adapters = instance.enumerate_adapters(Backends::all());

for adapter in adapters {
let required_features = *required_features;
let adapter_features = adapter.features();
if !adapter_features.contains(required_features) {
continue;
} else {
chosen_adapter = Some(adapter);
break;
}
}

let required_features = *required_features;
let adapter_features = adapter.features();
if !adapter_features.contains(required_features) {
continue;
} else {
chosen_adapter = Some(adapter);
break;
}
}

chosen_adapter.expect("No suitable GPU adapters found on the system!")
Expand Down
30 changes: 28 additions & 2 deletions wgpu-hal/src/gles/egl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,12 @@ struct EglContext {

impl EglContext {
fn make_current(&self) {
log::trace!(
"Make current on {:?} {:?} {:?}",
self.display,
self.pbuffer,
self.raw
);
self.instance
.make_current(self.display, self.pbuffer, self.pbuffer, Some(self.raw))
.unwrap();
Expand Down Expand Up @@ -697,6 +703,7 @@ impl Inner {
version,
supports_native_window,
config,
// Will in some scenarios be overwritten by the caller after this function returns.
wl_display: None,
srgb_kind,
force_gles_minor_version,
Expand Down Expand Up @@ -839,7 +846,10 @@ impl crate::Instance for Instance {

let (display, display_owner, wsi_kind) =
if let (Some(library), Some(egl)) = (wayland_library, egl1_5) {
log::info!("Using Wayland platform");
// XXX: Drop this code and convert `Inner` to an `Option` so that we can
// force-initialize this whenever the "RawDisplayHandle" is available (currently
// only via the surface)...
log::error!("Using Wayland platform, creating nonfunctional bogus display first");
let display_attributes = [khronos_egl::ATTRIB_NONE];
let display = unsafe {
egl.get_platform_display(
Expand Down Expand Up @@ -969,6 +979,7 @@ impl crate::Instance for Instance {
)
.unwrap();

// TODO: Why?
let ret = unsafe {
ndk_sys::ANativeWindow_setBuffersGeometry(
handle
Expand Down Expand Up @@ -1013,6 +1024,7 @@ impl crate::Instance for Instance {
.unwrap()
.get_platform_display(
EGL_PLATFORM_WAYLAND_KHR,
// khronos_egl::DEFAULT_DISPLAY,
display_handle.display.as_ptr(),
&display_attributes,
)
Expand Down Expand Up @@ -1056,9 +1068,22 @@ impl crate::Instance for Instance {

unsafe fn enumerate_adapters(
&self,
_surface_hint: Option<&Surface>,
surface_hint: Option<&Surface>,
) -> Vec<crate::ExposedAdapter<super::Api>> {
let inner = self.inner.lock();

if let Some(surface) = surface_hint {
assert_eq!(surface.egl.raw, inner.egl.raw);
} else
// if inner.??? == Wayland
{
// This is a trick from Web, but it's too restrictive and not needed if the user
// initializes in the right order.
// TODO: We can probably also allow the user through if inner.wl_surface is not NULL?
log::info!("Returning zero adapters on Wayland unless a surface is passed");
return vec![];
}

inner.egl.make_current();

let mut gl = unsafe {
Expand Down Expand Up @@ -1313,6 +1338,7 @@ impl crate::Surface for Surface {
let wl_egl_window_create: libloading::Symbol<WlEglWindowCreateFun> =
unsafe { library.get(c"wl_egl_window_create".to_bytes()) }.unwrap();
let window =
// XXX: Why hardcode a random size here, over using config.extent?
unsafe { wl_egl_window_create(handle.surface.as_ptr(), 640, 480) }
.cast();
wl_window = Some(window);
Expand Down
2 changes: 1 addition & 1 deletion wgpu-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ pub struct RequestAdapterOptions<S> {
pub force_fallback_adapter: bool,
/// Surface that is required to be presentable with the requested adapter. This does not
/// create the surface, only guarantees that the adapter can present to said surface.
/// For WebGL, this is strictly required, as an adapter can not be created without a surface.
/// For WebGL and Wayland, this is strictly required, as an adapter can not be created without a surface.
pub compatible_surface: Option<S>,
}

Expand Down