Merge pull request #276 from cmeissl/renderer/v4-fix-egl-drm-rendering
disable texture cache for egl imports
This commit is contained in:
commit
e5a1afd306
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::convert::TryFrom;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -25,20 +25,17 @@ use crate::backend::allocator::{
|
||||||
Format,
|
Format,
|
||||||
};
|
};
|
||||||
use crate::backend::egl::{
|
use crate::backend::egl::{
|
||||||
ffi::egl::{self as ffi_egl, types::EGLImage}, EGLContext, EGLSurface,
|
ffi::egl::{self as ffi_egl, types::EGLImage},
|
||||||
Format as EGLFormat, MakeCurrentError,
|
EGLContext, EGLSurface, Format as EGLFormat, MakeCurrentError,
|
||||||
};
|
};
|
||||||
use crate::backend::SwapBuffersError;
|
use crate::backend::SwapBuffersError;
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use crate::{
|
use crate::{backend::egl::display::EGLBufferReader, wayland::compositor::Damage};
|
||||||
backend::egl::display::EGLBufferReader,
|
|
||||||
wayland::compositor::Damage,
|
|
||||||
};
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
|
||||||
use wayland_server::protocol::{wl_buffer, wl_shm};
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use wayland_commons::user_data::UserDataMap;
|
use wayland_commons::user_data::UserDataMap;
|
||||||
|
#[cfg(feature = "wayland_frontend")]
|
||||||
|
use wayland_server::protocol::{wl_buffer, wl_shm};
|
||||||
|
|
||||||
#[allow(clippy::all, missing_docs)]
|
#[allow(clippy::all, missing_docs)]
|
||||||
pub mod ffi {
|
pub mod ffi {
|
||||||
|
@ -78,10 +75,14 @@ struct Gles2TextureInternal {
|
||||||
|
|
||||||
impl Drop for Gles2TextureInternal {
|
impl Drop for Gles2TextureInternal {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let _ = self.destruction_callback_sender.send(CleanupResource::Texture(self.texture));
|
let _ = self
|
||||||
|
.destruction_callback_sender
|
||||||
|
.send(CleanupResource::Texture(self.texture));
|
||||||
if let Some(images) = self.egl_images.take() {
|
if let Some(images) = self.egl_images.take() {
|
||||||
for image in images {
|
for image in images {
|
||||||
let _ = self.destruction_callback_sender.send(CleanupResource::EGLImage(image));
|
let _ = self
|
||||||
|
.destruction_callback_sender
|
||||||
|
.send(CleanupResource::EGLImage(image));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,8 +246,9 @@ impl From<Gles2Error> for SwapBuffersError {
|
||||||
| x @ Gles2Error::GLExtensionNotSupported(_)
|
| x @ Gles2Error::GLExtensionNotSupported(_)
|
||||||
| x @ Gles2Error::UnconstraintRenderingOperation => SwapBuffersError::ContextLost(Box::new(x)),
|
| x @ Gles2Error::UnconstraintRenderingOperation => SwapBuffersError::ContextLost(Box::new(x)),
|
||||||
Gles2Error::ContextActivationError(err) => err.into(),
|
Gles2Error::ContextActivationError(err) => err.into(),
|
||||||
x @ Gles2Error::FramebufferBindingError
|
x @ Gles2Error::FramebufferBindingError | x @ Gles2Error::BindBufferEGLError(_) => {
|
||||||
| x @ Gles2Error::BindBufferEGLError(_) => SwapBuffersError::TemporaryFailure(Box::new(x)),
|
SwapBuffersError::TemporaryFailure(Box::new(x))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -471,7 +473,8 @@ impl Gles2Renderer {
|
||||||
fn cleanup(&mut self) -> Result<(), Gles2Error> {
|
fn cleanup(&mut self) -> Result<(), Gles2Error> {
|
||||||
self.make_current()?;
|
self.make_current()?;
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
self.textures.retain(|entry, tex| entry.buffer.as_ref().is_alive());
|
self.textures
|
||||||
|
.retain(|entry, _tex| entry.buffer.as_ref().is_alive());
|
||||||
for resource in self.destruction_callback.try_iter() {
|
for resource in self.destruction_callback.try_iter() {
|
||||||
match resource {
|
match resource {
|
||||||
CleanupResource::Texture(texture) => unsafe {
|
CleanupResource::Texture(texture) => unsafe {
|
||||||
|
@ -479,7 +482,7 @@ impl Gles2Renderer {
|
||||||
},
|
},
|
||||||
CleanupResource::EGLImage(image) => unsafe {
|
CleanupResource::EGLImage(image) => unsafe {
|
||||||
ffi_egl::DestroyImageKHR(**self.egl.display.display, image);
|
ffi_egl::DestroyImageKHR(**self.egl.display.display, image);
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -534,7 +537,13 @@ impl Gles2Renderer {
|
||||||
egl_images: None,
|
egl_images: None,
|
||||||
destruction_callback_sender: self.destruction_callback_sender.clone(),
|
destruction_callback_sender: self.destruction_callback_sender.clone(),
|
||||||
}));
|
}));
|
||||||
self.textures.insert(BufferEntry { id: buffer.as_ref().id(), buffer: buffer.clone() }, texture.clone());
|
self.textures.insert(
|
||||||
|
BufferEntry {
|
||||||
|
id: buffer.as_ref().id(),
|
||||||
|
buffer: buffer.clone(),
|
||||||
|
},
|
||||||
|
texture.clone(),
|
||||||
|
);
|
||||||
texture
|
texture
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -598,18 +607,18 @@ impl Gles2Renderer {
|
||||||
return Err(Gles2Error::GLExtensionNotSupported(&["GL_OES_EGL_image"]));
|
return Err(Gles2Error::GLExtensionNotSupported(&["GL_OES_EGL_image"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.existing_texture(buffer)?.map(Ok).unwrap_or_else(|| {
|
// We can not use the caching logic for textures here as the
|
||||||
|
// egl buffers a potentially managed external which will fail the
|
||||||
|
// clean up check if the buffer is still alive. For wl_drm the
|
||||||
|
// is_alive check will always return true and the cache entry
|
||||||
|
// will never be cleaned up.
|
||||||
self.make_current()?;
|
self.make_current()?;
|
||||||
|
|
||||||
let egl = reader
|
let egl = reader
|
||||||
.egl_buffer_contents(&buffer)
|
.egl_buffer_contents(&buffer)
|
||||||
.map_err(Gles2Error::EGLBufferAccessError)?;
|
.map_err(Gles2Error::EGLBufferAccessError)?;
|
||||||
|
|
||||||
let tex = self.import_egl_image(
|
let tex = self.import_egl_image(egl.image(0).unwrap(), egl.format == EGLFormat::External, None)?;
|
||||||
egl.image(0).unwrap(),
|
|
||||||
egl.format == EGLFormat::External,
|
|
||||||
None,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let texture = Gles2Texture(Rc::new(Gles2TextureInternal {
|
let texture = Gles2Texture(Rc::new(Gles2TextureInternal {
|
||||||
texture: tex,
|
texture: tex,
|
||||||
|
@ -629,22 +638,24 @@ impl Gles2Renderer {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
self.egl.unbind()?;
|
self.egl.unbind()?;
|
||||||
self.textures.insert(BufferEntry { id: buffer.as_ref().id(), buffer: buffer.clone() }, texture.clone());
|
|
||||||
Ok(texture)
|
Ok(texture)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
fn existing_texture(
|
fn existing_texture(&self, buffer: &wl_buffer::WlBuffer) -> Result<Option<Gles2Texture>, Gles2Error> {
|
||||||
&self,
|
let existing_texture = self
|
||||||
buffer: &wl_buffer::WlBuffer,
|
.textures
|
||||||
) -> Result<Option<Gles2Texture>, Gles2Error> {
|
.iter()
|
||||||
let existing_texture = self.textures.iter().find(|(old_buffer, _)| {
|
.find(|(old_buffer, _)| &old_buffer.buffer == buffer)
|
||||||
&old_buffer.buffer == buffer
|
.map(|(_, tex)| tex.clone());
|
||||||
}).map(|(_, tex)| tex.clone());
|
|
||||||
|
|
||||||
if let Some(texture) = existing_texture {
|
if let Some(texture) = existing_texture {
|
||||||
trace!(self.logger, "Re-using texture {:?} for {:?}", texture.0.texture, buffer);
|
trace!(
|
||||||
|
self.logger,
|
||||||
|
"Re-using texture {:?} for {:?}",
|
||||||
|
texture.0.texture,
|
||||||
|
buffer
|
||||||
|
);
|
||||||
if texture.0.is_external {
|
if texture.0.is_external {
|
||||||
Ok(Some(texture))
|
Ok(Some(texture))
|
||||||
} else {
|
} else {
|
||||||
|
@ -917,10 +928,13 @@ impl Renderer for Gles2Renderer {
|
||||||
let texture = if egl.and_then(|egl| egl.egl_buffer_dimensions(&buffer)).is_some() {
|
let texture = if egl.and_then(|egl| egl.egl_buffer_dimensions(&buffer)).is_some() {
|
||||||
self.import_egl(&buffer, egl.unwrap())
|
self.import_egl(&buffer, egl.unwrap())
|
||||||
} else if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() {
|
} else if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() {
|
||||||
self.import_shm(&buffer, damage.and_then(|damage| match damage {
|
self.import_shm(
|
||||||
|
&buffer,
|
||||||
|
damage.and_then(|damage| match damage {
|
||||||
Damage::Buffer(rect) => Some(*rect),
|
Damage::Buffer(rect) => Some(*rect),
|
||||||
_ => None
|
_ => None,
|
||||||
}))
|
}),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Err(Gles2Error::UnknownBufferType)
|
Err(Gles2Error::UnknownBufferType)
|
||||||
}?;
|
}?;
|
||||||
|
|
Loading…
Reference in New Issue