render: add support for explicit sync
This commit is contained in:
parent
1b4492c670
commit
816315170f
22 changed files with 531 additions and 94 deletions
|
|
@ -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(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
|||
107
src/gfx_apis/gl/renderer/sync.rs
Normal file
107
src/gfx_apis/gl/renderer/sync.rs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue