use crate::async_engine::AsyncEngine;
use crate::backend::DrmDeviceId;
use crate::eventfd_cache::EventfdCache;
use crate::gfx_api::GfxApi;
use crate::gfx_api::GfxContext;
use crate::gfx_api::GfxError;
use crate::io_uring::IoUring;
use crate::pr_caps::PrCapsThread;
use crate::utils::errorfmt::ErrorFmt;
use crate::video::drm::Drm;
use std::rc::Rc;
pub use vulkan::create_vulkan_allocator;
pub mod gl;
mod vulkan;
pub fn create_gfx_context(
eng: &Rc<AsyncEngine>,
ring: &Rc<IoUring>,
eventfd_cache: &Rc<EventfdCache>,
drm_device_id: Option<DrmDeviceId>,
drm: &Drm,
api: GfxApi,
caps_thread: Option<&PrCapsThread>,
) -> Result<Rc<dyn GfxContext>, GfxError> {
let mut apis = [GfxApi::OpenGl, GfxApi::Vulkan];
apis.sort_by_key(|&a| if a == api { -1 } else { a as i32 });
let mut last_err = None;
for software in [false, true] {
for api in apis {
let res = create_gfx_context_(
eng,
ring,
eventfd_cache,
drm_device_id,
drm,
api,
caps_thread,
software,
);
match res {
Ok(_) => {
log::info!("Created a {api:?} renderer");
if software {
log::warn!("Renderer uses software rendering");
}
return res;
}
Err(e) => {
log::warn!("Could not create {:?} API: {}", api, ErrorFmt(&e));
last_err = Some(e);
}
}
}
}
Err(last_err.unwrap())
}
fn create_gfx_context_(
eng: &Rc<AsyncEngine>,
ring: &Rc<IoUring>,
eventfd_cache: &Rc<EventfdCache>,
drm_device_id: Option<DrmDeviceId>,
drm: &Drm,
api: GfxApi,
caps_thread: Option<&PrCapsThread>,
software: bool,
) -> Result<Rc<dyn GfxContext>, GfxError> {
match api {
GfxApi::OpenGl => gl::create_gfx_context(drm_device_id, drm, software),
GfxApi::Vulkan => vulkan::create_graphics_context(
eng,
ring,
eventfd_cache,
drm_device_id,
drm,
caps_thread,
software,
),
}
}