1
0
Fork 0
forked from wry/wry

render: add support for explicit sync

This commit is contained in:
Julian Orth 2024-03-21 23:26:34 +01:00
parent 1b4492c670
commit 816315170f
22 changed files with 531 additions and 94 deletions

View file

@ -2,8 +2,8 @@ use {
crate::{
format::{Format, XRGB8888},
gfx_api::{
GfxApiOpt, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage, GfxTexture,
ResetStatus,
BufferResvUser, GfxApiOpt, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage,
GfxTexture, ResetStatus,
},
gfx_apis::gl::{
egl::{context::EglContext, display::EglDisplay, image::EglImage},
@ -65,6 +65,8 @@ pub(in crate::gfx_apis::gl) struct GlRenderContext {
pub(crate) gfx_ops: RefCell<Vec<GfxApiOpt>>,
pub(in crate::gfx_apis::gl) gl_state: RefCell<GfxGlState>,
pub(in crate::gfx_apis::gl) buffer_resv_user: BufferResvUser,
}
impl Debug for GlRenderContext {
@ -141,6 +143,8 @@ impl GlRenderContext {
gfx_ops: Default::default(),
gl_state: Default::default(),
buffer_resv_user: Default::default(),
})
}

View file

@ -1,7 +1,7 @@
use {
crate::{
format::Format,
gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer},
gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, SyncFile},
gfx_apis::gl::{
gl::{
frame_buffer::GlFrameBuffer,
@ -65,7 +65,11 @@ impl Framebuffer {
});
}
pub fn render(&self, ops: Vec<GfxApiOpt>, clear: Option<&Color>) -> Result<(), RenderError> {
pub fn render(
&self,
ops: Vec<GfxApiOpt>,
clear: Option<&Color>,
) -> Result<Option<SyncFile>, RenderError> {
let gles = self.ctx.ctx.dpy.gles;
let res = self.ctx.ctx.with_current(|| {
unsafe {
@ -77,11 +81,13 @@ impl Framebuffer {
}
(gles.glBlendFunc)(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
run_ops(self, &ops);
unsafe {
(gles.glFlush)();
let fd = run_ops(self, &ops);
if fd.is_none() {
unsafe {
(gles.glFlush)();
}
}
Ok(())
Ok(fd)
});
*self.ctx.gfx_ops.borrow_mut() = ops;
res
@ -103,7 +109,11 @@ impl GfxFramebuffer for Framebuffer {
(self.gl.width, self.gl.height)
}
fn render(&self, ops: Vec<GfxApiOpt>, clear: Option<&Color>) -> Result<(), GfxError> {
fn render(
&self,
ops: Vec<GfxApiOpt>,
clear: Option<&Color>,
) -> Result<Option<SyncFile>, GfxError> {
self.render(ops, clear).map_err(|e| e.into())
}

View file

@ -0,0 +1,107 @@
use {
crate::{
gfx_apis::gl::{
egl::context::EglContext,
sys::{
EGLBoolean, EGLSyncKHR, EGL_NONE, EGL_SYNC_NATIVE_FENCE_ANDROID,
EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_TRUE,
},
RenderError,
},
utils::errorfmt::ErrorFmt,
},
std::rc::Rc,
uapi::OwnedFd,
};
pub struct EglSync {
ctx: Rc<EglContext>,
sync: EGLSyncKHR,
}
impl EglContext {
pub fn export_sync_file(self: &Rc<Self>) -> Result<OwnedFd, RenderError> {
self.create_sync(None)?.export_sync_file()
}
pub fn create_sync(self: &Rc<Self>, file: Option<OwnedFd>) -> Result<EglSync, RenderError> {
let mut attribs = [EGL_NONE; 3];
if let Some(file) = &file {
attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID;
attribs[1] = file.raw();
}
self.with_current(|| unsafe {
let sync = self.dpy.procs.eglCreateSyncKHR(
self.dpy.dpy,
EGL_SYNC_NATIVE_FENCE_ANDROID,
attribs.as_ptr(),
);
if sync.is_null() {
Err(RenderError::CreateEglSync)
} else {
if let Some(file) = file {
file.unwrap();
}
Ok(EglSync {
ctx: self.clone(),
sync,
})
}
})
}
}
impl EglSync {
pub fn wait(&self) {
let res = self.ctx.with_current(|| unsafe {
let res = self
.ctx
.dpy
.procs
.eglWaitSyncKHR(self.ctx.dpy.dpy, self.sync, 0);
if res as EGLBoolean == EGL_TRUE {
Ok(())
} else {
Err(RenderError::WaitSync)
}
});
if let Err(e) = res {
log::warn!("Could not insert wait point: {}", ErrorFmt(e));
}
}
pub fn export_sync_file(&self) -> Result<OwnedFd, RenderError> {
self.ctx.with_current(|| unsafe {
let fd = self
.ctx
.dpy
.procs
.eglDupNativeFenceFDANDROID(self.ctx.dpy.dpy, self.sync);
if fd == -1 {
Err(RenderError::ExportSyncFile)
} else {
Ok(OwnedFd::new(fd))
}
})
}
}
impl Drop for EglSync {
fn drop(&mut self) {
let res = self.ctx.with_current(|| unsafe {
let res = self
.ctx
.dpy
.procs
.eglDestroySyncKHR(self.ctx.dpy.dpy, self.sync);
if res == EGL_TRUE {
Ok(())
} else {
Err(RenderError::DestroyEglSync)
}
});
if let Err(e) = res {
log::error!("{}", ErrorFmt(e));
}
}
}