disable texture cache for egl imports and...
...fix format in gles2 renderer
This commit is contained in:
parent
2843c5c374
commit
0493215c8e
|
@ -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,53 +607,55 @@ 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
|
||||||
self.make_current()?;
|
// 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()?;
|
||||||
|
|
||||||
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,
|
||||||
texture_kind: match egl.format {
|
texture_kind: match egl.format {
|
||||||
EGLFormat::RGB => 1,
|
EGLFormat::RGB => 1,
|
||||||
EGLFormat::RGBA => 0,
|
EGLFormat::RGBA => 0,
|
||||||
EGLFormat::External => 2,
|
EGLFormat::External => 2,
|
||||||
_ => unreachable!("EGLBuffer currenly does not expose multi-planar buffers to us"),
|
_ => unreachable!("EGLBuffer currenly does not expose multi-planar buffers to us"),
|
||||||
},
|
},
|
||||||
is_external: egl.format == EGLFormat::External,
|
is_external: egl.format == EGLFormat::External,
|
||||||
y_inverted: egl.y_inverted,
|
y_inverted: egl.y_inverted,
|
||||||
width: egl.width,
|
width: egl.width,
|
||||||
height: egl.height,
|
height: egl.height,
|
||||||
buffer: Some(buffer.clone()),
|
buffer: Some(buffer.clone()),
|
||||||
egl_images: Some(egl.into_images()),
|
egl_images: Some(egl.into_images()),
|
||||||
destruction_callback_sender: self.destruction_callback_sender.clone(),
|
destruction_callback_sender: self.destruction_callback_sender.clone(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
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(
|
||||||
Damage::Buffer(rect) => Some(*rect),
|
&buffer,
|
||||||
_ => None
|
damage.and_then(|damage| match damage {
|
||||||
}))
|
Damage::Buffer(rect) => Some(*rect),
|
||||||
|
_ => None,
|
||||||
|
}),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Err(Gles2Error::UnknownBufferType)
|
Err(Gles2Error::UnknownBufferType)
|
||||||
}?;
|
}?;
|
||||||
|
@ -1077,7 +1091,7 @@ impl Renderer for Gles2Renderer {
|
||||||
// In case of a drm atomic backend the fence could be supplied by using the
|
// In case of a drm atomic backend the fence could be supplied by using the
|
||||||
// IN_FENCE_FD property.
|
// IN_FENCE_FD property.
|
||||||
// See https://01.org/linuxgraphics/gfx-docs/drm/gpu/drm-kms.html#explicit-fencing-properties for
|
// See https://01.org/linuxgraphics/gfx-docs/drm/gpu/drm-kms.html#explicit-fencing-properties for
|
||||||
// the topic on submitting a IN_FENCE_FD and the mesa kmskube example
|
// the topic on submitting a IN_FENCE_FD and the mesa kmskube example
|
||||||
// https://gitlab.freedesktop.org/mesa/kmscube/-/blob/9f63f359fab1b5d8e862508e4e51c9dfe339ccb0/drm-atomic.c
|
// https://gitlab.freedesktop.org/mesa/kmscube/-/blob/9f63f359fab1b5d8e862508e4e51c9dfe339ccb0/drm-atomic.c
|
||||||
// especially here
|
// especially here
|
||||||
// https://gitlab.freedesktop.org/mesa/kmscube/-/blob/9f63f359fab1b5d8e862508e4e51c9dfe339ccb0/drm-atomic.c#L147
|
// https://gitlab.freedesktop.org/mesa/kmscube/-/blob/9f63f359fab1b5d8e862508e4e51c9dfe339ccb0/drm-atomic.c#L147
|
||||||
|
|
Loading…
Reference in New Issue