vulkan: implement software rendering
This commit is contained in:
parent
bb29303c98
commit
0a5ee8fa36
10 changed files with 140 additions and 31 deletions
|
|
@ -5,7 +5,7 @@ use {
|
|||
gfx_apis::gl::{
|
||||
RenderError,
|
||||
egl::{
|
||||
PROCS,
|
||||
EXTS, PROCS,
|
||||
context::EglContext,
|
||||
image::EglImage,
|
||||
sys::{
|
||||
|
|
@ -26,9 +26,10 @@ use {
|
|||
},
|
||||
ext::{
|
||||
ANDROID_NATIVE_FENCE_SYNC, DisplayExt, EXT_CREATE_CONTEXT_ROBUSTNESS,
|
||||
EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS, GL_OES_EGL_IMAGE, GL_OES_EGL_IMAGE_EXTERNAL,
|
||||
GlExt, KHR_FENCE_SYNC, KHR_IMAGE_BASE, KHR_NO_CONFIG_CONTEXT,
|
||||
KHR_SURFACELESS_CONTEXT, KHR_WAIT_SYNC, MESA_CONFIGLESS_CONTEXT, get_display_ext,
|
||||
EXT_DEVICE_QUERY, EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS, GL_OES_EGL_IMAGE,
|
||||
GL_OES_EGL_IMAGE_EXTERNAL, GlExt, KHR_FENCE_SYNC, KHR_IMAGE_BASE,
|
||||
KHR_NO_CONFIG_CONTEXT, KHR_SURFACELESS_CONTEXT, KHR_WAIT_SYNC,
|
||||
MESA_CONFIGLESS_CONTEXT, MESA_DEVICE_SOFTWARE, get_device_ext, get_display_ext,
|
||||
get_gl_ext,
|
||||
},
|
||||
proc::ExtProc,
|
||||
|
|
@ -70,7 +71,10 @@ pub struct EglDisplay {
|
|||
}
|
||||
|
||||
impl EglDisplay {
|
||||
pub(in crate::gfx_apis::gl) fn create(drm: &Drm) -> Result<Rc<Self>, RenderError> {
|
||||
pub(in crate::gfx_apis::gl) fn create(
|
||||
drm: &Drm,
|
||||
software: bool,
|
||||
) -> Result<Rc<Self>, RenderError> {
|
||||
unsafe {
|
||||
let Some(egl) = EGL.as_ref() else {
|
||||
return Err(RenderError::LoadEgl);
|
||||
|
|
@ -108,6 +112,11 @@ impl EglDisplay {
|
|||
if (egl.eglInitialize)(dpy.dpy, &mut major, &mut minor) != EGL_TRUE {
|
||||
return Err(RenderError::Initialize);
|
||||
}
|
||||
if !software && EXTS.contains(EXT_DEVICE_QUERY) {
|
||||
if get_device_ext(procs, dpy.dpy)?.contains(MESA_DEVICE_SOFTWARE) {
|
||||
return Err(RenderError::NoHardwareRenderer);
|
||||
}
|
||||
}
|
||||
dpy.exts = get_display_ext(dpy.dpy);
|
||||
if !dpy.exts.intersects(KHR_IMAGE_BASE) {
|
||||
return Err(RenderError::ImageBase);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ egl_transparent!(EGLImageKHR);
|
|||
egl_transparent!(EGLContext);
|
||||
egl_transparent!(EGLClientBuffer);
|
||||
egl_transparent!(EGLLabelKHR);
|
||||
egl_transparent!(EGLDeviceEXT);
|
||||
|
||||
pub type EGLDEBUGPROCKHR = unsafe extern "C" fn(
|
||||
error: EGLenum,
|
||||
|
|
@ -53,6 +54,7 @@ pub const EGL_PLATFORM_GBM_KHR: EGLint = 0x31D7;
|
|||
pub const EGL_CONTEXT_CLIENT_VERSION: EGLint = 0x3098;
|
||||
pub const EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: EGLint = 0x3138;
|
||||
pub const EGL_LOSE_CONTEXT_ON_RESET_EXT: EGLint = 0x31BF;
|
||||
pub const EGL_DEVICE_EXT: EGLint = 0x322C;
|
||||
|
||||
pub const GL_GUILTY_CONTEXT_RESET_ARB: GLenum = 0x8253;
|
||||
pub const GL_INNOCENT_CONTEXT_RESET_ARB: GLenum = 0x8254;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ use {
|
|||
RenderError,
|
||||
egl::sys::{EGL_EXTENSIONS, EGLDisplay},
|
||||
gl::sys::GL_EXTENSIONS,
|
||||
sys::{EGL, GLESV2},
|
||||
proc::ExtProc,
|
||||
sys::{EGL, EGL_DEVICE_EXT, EGL_TRUE, EGLDeviceEXT, GLESV2},
|
||||
},
|
||||
ahash::AHashSet,
|
||||
bstr::ByteSlice,
|
||||
|
|
@ -53,6 +54,7 @@ bitflags! {
|
|||
EXT_PLATFORM_BASE = 1 << 1,
|
||||
KHR_PLATFORM_GBM = 1 << 2,
|
||||
KHR_DEBUG = 1 << 3,
|
||||
EXT_DEVICE_QUERY = 1 << 4,
|
||||
}
|
||||
|
||||
pub fn get_client_ext() -> ClientExt {
|
||||
|
|
@ -60,6 +62,7 @@ pub fn get_client_ext() -> ClientExt {
|
|||
("EGL_EXT_platform_base", EXT_PLATFORM_BASE),
|
||||
("EGL_KHR_platform_gbm", KHR_PLATFORM_GBM),
|
||||
("EGL_KHR_debug", KHR_DEBUG),
|
||||
("EGL_EXT_device_query", EXT_DEVICE_QUERY),
|
||||
];
|
||||
match unsafe { get_dpy_extensions(EGLDisplay::none()) } {
|
||||
Some(exts) => get_typed_ext(&exts, EXT_CLIENT_EXTENSION, &map),
|
||||
|
|
@ -127,3 +130,24 @@ pub fn get_gl_ext() -> Result<GlExt, RenderError> {
|
|||
_ => Ok(GlExt::none()),
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
DevExt: u32;
|
||||
MESA_DEVICE_SOFTWARE = 1 << 0,
|
||||
}
|
||||
|
||||
pub fn get_device_ext(procs: &ExtProc, dpy: EGLDisplay) -> Result<DevExt, RenderError> {
|
||||
let map = [("EGL_MESA_device_software", MESA_DEVICE_SOFTWARE)];
|
||||
unsafe {
|
||||
let mut device = 0;
|
||||
if procs.eglQueryDisplayAttribEXT(dpy, EGL_DEVICE_EXT, &mut device) != EGL_TRUE {
|
||||
return Err(RenderError::QueryDisplayDevice);
|
||||
}
|
||||
let device = EGLDeviceEXT(device as _);
|
||||
let ext = procs.eglQueryDeviceStringEXT(device, EGL_EXTENSIONS);
|
||||
match get_extensions(ext) {
|
||||
Some(exts) => Ok(get_typed_ext(&exts, DevExt::none(), &map)),
|
||||
_ => Ok(DevExt::none()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,12 +102,15 @@ impl GlRenderContext {
|
|||
self.ctx.reset_status()
|
||||
}
|
||||
|
||||
pub(in crate::gfx_apis::gl) fn from_drm_device(drm: &Drm) -> Result<Self, RenderError> {
|
||||
pub(in crate::gfx_apis::gl) fn from_drm_device(
|
||||
drm: &Drm,
|
||||
software: bool,
|
||||
) -> Result<Self, RenderError> {
|
||||
let node = drm
|
||||
.get_render_node()?
|
||||
.ok_or(RenderError::NoRenderNode)
|
||||
.map(Rc::new)?;
|
||||
let dpy = EglDisplay::create(drm)?;
|
||||
let dpy = EglDisplay::create(drm, software)?;
|
||||
if !dpy.formats.contains_key(&XRGB8888.drm) {
|
||||
return Err(RenderError::XRGB888);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue