cargo fmt

This commit is contained in:
Victor Brekenfeld 2021-05-15 18:17:43 +02:00
parent b4f216d7b8
commit 149c923876
14 changed files with 184 additions and 123 deletions

View File

@ -9,7 +9,10 @@ use smithay::{
renderer::{Renderer, Texture, Transform}, renderer::{Renderer, Texture, Transform},
SwapBuffersError, SwapBuffersError,
}, },
reexports::{calloop::LoopHandle, wayland_server::protocol::{wl_buffer,wl_surface}}, reexports::{
calloop::LoopHandle,
wayland_server::protocol::{wl_buffer, wl_surface},
},
utils::Rectangle, utils::Rectangle,
wayland::{ wayland::{
compositor::{roles::Role, SubsurfaceRole, TraversalAction}, compositor::{roles::Role, SubsurfaceRole, TraversalAction},
@ -54,14 +57,7 @@ where
(0, 0) (0, 0)
} }
}; };
draw_surface_tree( draw_surface_tree(renderer, surface, egl_buffer_reader, (x - dx, y - dy), token, log)
renderer,
surface,
egl_buffer_reader,
(x - dx, y - dy),
token,
log,
)
} }
fn draw_surface_tree<R, E, T>( fn draw_surface_tree<R, E, T>(
@ -89,7 +85,10 @@ where
if data.texture.is_none() { if data.texture.is_none() {
if let Some(buffer) = data.current_state.buffer.take() { if let Some(buffer) = data.current_state.buffer.take() {
match renderer.import_buffer(&buffer, egl_buffer_reader) { match renderer.import_buffer(&buffer, egl_buffer_reader) {
Ok(m) => data.texture = Some(Box::new(BufferTextures { buffer, texture: m }) as Box<dyn std::any::Any + 'static>), Ok(m) => {
data.texture = Some(Box::new(BufferTextures { buffer, texture: m })
as Box<dyn std::any::Any + 'static>)
}
// there was an error reading the buffer, release it, we // there was an error reading the buffer, release it, we
// already logged the error // already logged the error
Err(err) => { Err(err) => {
@ -154,9 +153,12 @@ where
x += sub_x; x += sub_x;
y += sub_y; y += sub_y;
} }
if let Err(err) = if let Err(err) = renderer.render_texture_at(
renderer.render_texture_at(&texture.texture, (x, y), Transform::Normal /* TODO */, 1.0) &texture.texture,
{ (x, y),
Transform::Normal, /* TODO */
1.0,
) {
result = Err(err.into()); result = Err(err.into());
} }
} }
@ -229,14 +231,7 @@ where
"Trying to display as a dnd icon a surface that does not have the DndIcon role." "Trying to display as a dnd icon a surface that does not have the DndIcon role."
); );
} }
draw_surface_tree( draw_surface_tree(renderer, surface, egl_buffer_reader, (x, y), token, log)
renderer,
surface,
egl_buffer_reader,
(x, y),
token,
log,
)
} }
pub fn schedule_initial_render<R: Renderer + 'static, Data: 'static>( pub fn schedule_initial_render<R: Renderer + 'static, Data: 'static>(

View File

@ -4,6 +4,8 @@ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
#[cfg(feature = "egl")]
use smithay::backend::egl::display::EGLBufferReader;
use smithay::{ use smithay::{
backend::renderer::buffer_dimensions, backend::renderer::buffer_dimensions,
reexports::{ reexports::{
@ -33,8 +35,6 @@ use smithay::{
Serial, Serial,
}, },
}; };
#[cfg(feature = "egl")]
use smithay::backend::egl::display::EGLBufferReader;
use crate::window_map::{Kind as SurfaceKind, WindowMap}; use crate::window_map::{Kind as SurfaceKind, WindowMap};
@ -310,9 +310,8 @@ pub struct ShellHandles {
pub fn init_shell( pub fn init_shell(
display: &mut Display, display: &mut Display,
#[cfg(feature = "egl")] #[cfg(feature = "egl")] egl_reader: Rc<RefCell<Option<EGLBufferReader>>>,
egl_reader: Rc<RefCell<Option<EGLBufferReader>>>, log: ::slog::Logger,
log: ::slog::Logger
) -> ShellHandles { ) -> ShellHandles {
// TODO: this is awkward... // TODO: this is awkward...
let almost_window_map = Rc::new(RefCell::new(None::<Rc<RefCell<MyWindowMap>>>)); let almost_window_map = Rc::new(RefCell::new(None::<Rc<RefCell<MyWindowMap>>>));
@ -794,8 +793,7 @@ impl SurfaceData {
fn surface_commit( fn surface_commit(
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
token: CompositorToken<Roles>, token: CompositorToken<Roles>,
#[cfg(feature = "egl")] #[cfg(feature = "egl")] egl_reader: Option<&EGLBufferReader>,
egl_reader: Option<&EGLBufferReader>,
window_map: &RefCell<MyWindowMap>, window_map: &RefCell<MyWindowMap>,
) { ) {
#[cfg(feature = "xwayland")] #[cfg(feature = "xwayland")]

View File

@ -23,18 +23,18 @@ use smithay::{
}, },
}; };
#[cfg(feature = "egl")]
use smithay::backend::egl::display::EGLBufferReader;
#[cfg(feature = "udev")] #[cfg(feature = "udev")]
use smithay::backend::session::{auto::AutoSession, Session}; use smithay::backend::session::{auto::AutoSession, Session};
#[cfg(feature = "xwayland")] #[cfg(feature = "xwayland")]
use smithay::xwayland::XWayland; use smithay::xwayland::XWayland;
#[cfg(feature = "egl")]
use smithay::backend::egl::display::EGLBufferReader;
use crate::shell::init_shell;
#[cfg(feature = "udev")] #[cfg(feature = "udev")]
use crate::udev::MyOutput; use crate::udev::MyOutput;
#[cfg(feature = "xwayland")] #[cfg(feature = "xwayland")]
use crate::xwayland::XWm; use crate::xwayland::XWm;
use crate::shell::init_shell;
pub struct AnvilState { pub struct AnvilState {
pub socket_name: String, pub socket_name: String,

View File

@ -12,6 +12,8 @@ use std::{
use image::{ImageBuffer, Rgba}; use image::{ImageBuffer, Rgba};
use slog::Logger; use slog::Logger;
#[cfg(feature = "egl")]
use smithay::backend::{drm::DevPath, egl::display::EGLBufferReader, udev::primary_gpu};
use smithay::{ use smithay::{
backend::{ backend::{
drm::{device_bind, DeviceHandler, DrmDevice, DrmError, DrmRenderSurface}, drm::{device_bind, DeviceHandler, DrmDevice, DrmError, DrmRenderSurface},
@ -56,10 +58,6 @@ use smithay::{
seat::CursorImageStatus, seat::CursorImageStatus,
}, },
}; };
#[cfg(feature = "egl")]
use smithay::{
backend::{drm::DevPath, egl::display::EGLBufferReader, udev::primary_gpu},
};
use crate::drawing::*; use crate::drawing::*;
use crate::shell::{MyWindowMap, Roles}; use crate::shell::{MyWindowMap, Roles};
@ -501,7 +499,11 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
let renderer = Rc::new(DrmRenderer { let renderer = Rc::new(DrmRenderer {
device_id, device_id,
#[cfg(feature = "egl")] #[cfg(feature = "egl")]
egl_buffer_reader: if is_primary { self.egl_buffer_reader.borrow().clone() } else { None }, egl_buffer_reader: if is_primary {
self.egl_buffer_reader.borrow().clone()
} else {
None
},
compositor_token: self.compositor_token, compositor_token: self.compositor_token,
backends: backends.clone(), backends: backends.clone(),
window_map: self.window_map.clone(), window_map: self.window_map.clone(),
@ -741,8 +743,7 @@ impl DrmRenderer {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn render_surface( fn render_surface(
surface: &mut RenderSurface, surface: &mut RenderSurface,
#[cfg(feature = "egl")] #[cfg(feature = "egl")] egl_buffer_reader: Option<&EGLBufferReader>,
egl_buffer_reader: Option<&EGLBufferReader>,
device_id: dev_t, device_id: dev_t,
crtc: crtc::Handle, crtc: crtc::Handle,
window_map: &mut MyWindowMap, window_map: &mut MyWindowMap,

View File

@ -132,8 +132,7 @@ fn main() {
} }
pub struct DrmHandlerImpl { pub struct DrmHandlerImpl {
swapchain: swapchain: Swapchain<DrmDevice<FdWrapper>, DumbBuffer<FdWrapper>, framebuffer::Handle>,
Swapchain<DrmDevice<FdWrapper>, DumbBuffer<FdWrapper>, framebuffer::Handle>,
current: Slot<DumbBuffer<FdWrapper>, framebuffer::Handle>, current: Slot<DumbBuffer<FdWrapper>, framebuffer::Handle>,
surface: Rc<DrmSurface<FdWrapper>>, surface: Rc<DrmSurface<FdWrapper>>,
} }

View File

@ -20,9 +20,9 @@ pub struct DumbBuffer<A: AsRawFd + 'static> {
impl<A: AsRawFd + 'static> fmt::Debug for DumbBuffer<A> { impl<A: AsRawFd + 'static> fmt::Debug for DumbBuffer<A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DumbBuffer") f.debug_struct("DumbBuffer")
.field("handle", &self.handle) .field("handle", &self.handle)
.field("format", &self.format) .field("format", &self.format)
.finish() .finish()
} }
} }

View File

@ -1,6 +1,9 @@
//! Module for Buffers created using [libgbm](reexports::gbm) //! Module for Buffers created using [libgbm](reexports::gbm)
use super::{dmabuf::{AsDmabuf, Dmabuf}, Allocator, Buffer, Format, Fourcc, Modifier}; use super::{
dmabuf::{AsDmabuf, Dmabuf},
Allocator, Buffer, Format, Fourcc, Modifier,
};
use gbm::{BufferObject as GbmBuffer, BufferObjectFlags, Device as GbmDevice}; use gbm::{BufferObject as GbmBuffer, BufferObjectFlags, Device as GbmDevice};
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;

View File

@ -132,10 +132,11 @@ where
pub fn acquire(&mut self) -> Result<Option<Slot<B, U>>, A::Error> { pub fn acquire(&mut self) -> Result<Option<Slot<B, U>>, A::Error> {
if let Some(free_slot) = self.slots.iter_mut().find(|s| !s.acquired.load(Ordering::SeqCst)) { if let Some(free_slot) = self.slots.iter_mut().find(|s| !s.acquired.load(Ordering::SeqCst)) {
if free_slot.buffer.is_none() { if free_slot.buffer.is_none() {
free_slot.buffer = Arc::new(Some( free_slot.buffer = Arc::new(Some(self.allocator.create_buffer(
self.allocator self.width,
.create_buffer(self.width, self.height, self.format)? self.height,
)); self.format,
)?));
} }
assert!(free_slot.buffer.is_some()); assert!(free_slot.buffer.is_some());

View File

@ -10,12 +10,15 @@ use gbm::{BufferObject, BufferObjectFlags, Device as GbmDevice};
use wayland_server::protocol::{wl_buffer, wl_shm}; use wayland_server::protocol::{wl_buffer, wl_shm};
use super::{device::DevPath, surface::DrmSurfaceInternal, DrmError, DrmSurface}; use super::{device::DevPath, surface::DrmSurfaceInternal, DrmError, DrmSurface};
use crate::backend::{
allocator::{dmabuf::{AsDmabuf, Dmabuf}, Allocator, Buffer, Format, Fourcc, Modifier, Slot, Swapchain},
egl::display::EGLBufferReader,
};
use crate::backend::renderer::{Bind, Renderer, Texture, Transform}; use crate::backend::renderer::{Bind, Renderer, Texture, Transform};
use crate::backend::SwapBuffersError; use crate::backend::SwapBuffersError;
use crate::backend::{
allocator::{
dmabuf::{AsDmabuf, Dmabuf},
Allocator, Buffer, Format, Fourcc, Modifier, Slot, Swapchain,
},
egl::display::EGLBufferReader,
};
/// Simplified by limited abstraction to link single [`DrmSurface`]s to renderers. /// Simplified by limited abstraction to link single [`DrmSurface`]s to renderers.
/// ///
@ -24,12 +27,7 @@ use crate::backend::SwapBuffersError;
/// In some scenarios it might be enough to use of a drm-surface as the one and only target /// In some scenarios it might be enough to use of a drm-surface as the one and only target
/// of a single renderer. In these cases `DrmRenderSurface` provides a way to quickly /// of a single renderer. In these cases `DrmRenderSurface` provides a way to quickly
/// get up and running without manually handling and binding buffers. /// get up and running without manually handling and binding buffers.
pub struct DrmRenderSurface< pub struct DrmRenderSurface<D: AsRawFd + 'static, A: Allocator<B>, R: Bind<Dmabuf>, B: Buffer> {
D: AsRawFd + 'static,
A: Allocator<B>,
R: Bind<Dmabuf>,
B: Buffer,
> {
_format: Format, _format: Format,
buffers: Buffers<D, B>, buffers: Buffers<D, B>,
current_buffer: Option<(Slot<B, (Dmabuf, BufferObject<FbHandle<D>>)>, Dmabuf)>, current_buffer: Option<(Slot<B, (Dmabuf, BufferObject<FbHandle<D>>)>, Dmabuf)>,
@ -42,7 +40,7 @@ impl<D, A, B, R, E1, E2, E3> DrmRenderSurface<D, A, R, B>
where where
D: AsRawFd + 'static, D: AsRawFd + 'static,
A: Allocator<B, Error = E1>, A: Allocator<B, Error = E1>,
B: Buffer + AsDmabuf<Error=E2>, B: Buffer + AsDmabuf<Error = E2>,
R: Bind<Dmabuf> + Renderer<Error = E3>, R: Bind<Dmabuf> + Renderer<Error = E3>,
E1: std::error::Error + 'static, E1: std::error::Error + 'static,
E2: std::error::Error + 'static, E2: std::error::Error + 'static,
@ -328,7 +326,7 @@ impl<D, A, B, T, R, E1, E2, E3> Renderer for DrmRenderSurface<D, A, R, B>
where where
D: AsRawFd + 'static, D: AsRawFd + 'static,
A: Allocator<B, Error = E1>, A: Allocator<B, Error = E1>,
B: Buffer + AsDmabuf<Error=E2>, B: Buffer + AsDmabuf<Error = E2>,
R: Bind<Dmabuf> + Renderer<Error = E3, TextureId = T>, R: Bind<Dmabuf> + Renderer<Error = E3, TextureId = T>,
T: Texture, T: Texture,
E1: std::error::Error + 'static, E1: std::error::Error + 'static,
@ -352,19 +350,29 @@ where
} }
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
fn import_buffer(&mut self, buffer: &wl_buffer::WlBuffer, egl: Option<&EGLBufferReader>) -> Result<Self::TextureId, Self::Error> { fn import_buffer(
self.renderer.import_buffer(buffer, egl).map_err(Error::RenderError) &mut self,
buffer: &wl_buffer::WlBuffer,
egl: Option<&EGLBufferReader>,
) -> Result<Self::TextureId, Self::Error> {
self.renderer
.import_buffer(buffer, egl)
.map_err(Error::RenderError)
} }
fn begin(&mut self, width: u32, height: u32, _transform: Transform) -> Result<(), Error<E1, E2, E3>> { fn begin(&mut self, width: u32, height: u32, _transform: Transform) -> Result<(), Error<E1, E2, E3>> {
if self.current_buffer.is_some() { if self.current_buffer.is_some() {
return Ok(()); return Ok(());
} }
let slot = self.swapchain.acquire().map_err(Error::SwapchainError)?.ok_or(Error::NoFreeSlotsError)?; let slot = self
.swapchain
.acquire()
.map_err(Error::SwapchainError)?
.ok_or(Error::NoFreeSlotsError)?;
let dmabuf = match &*slot.userdata() { let dmabuf = match &*slot.userdata() {
Some((buf, _)) => buf.clone(), Some((buf, _)) => buf.clone(),
None => (*slot).export().map_err(Error::AsDmabufError)?, None => (*slot).export().map_err(Error::AsDmabufError)?,
}; };
self.renderer.bind(dmabuf.clone()).map_err(Error::RenderError)?; self.renderer.bind(dmabuf.clone()).map_err(Error::RenderError)?;
self.current_buffer = Some((slot, dmabuf)); self.current_buffer = Some((slot, dmabuf));
@ -396,10 +404,7 @@ where
let result = self.renderer.finish(); let result = self.renderer.finish();
if result.is_ok() { if result.is_ok() {
let (slot, dmabuf) = self.current_buffer.take().unwrap(); let (slot, dmabuf) = self.current_buffer.take().unwrap();
match self match self.buffers.queue::<E1, E2, E3>(slot, dmabuf) {
.buffers
.queue::<E1, E2, E3>(slot, dmabuf)
{
Ok(()) => {} Ok(()) => {}
Err(Error::DrmError(drm)) => return Err(drm.into()), Err(Error::DrmError(drm)) => return Err(drm.into()),
Err(Error::GbmError(err)) => return Err(SwapBuffersError::ContextLost(Box::new(err))), Err(Error::GbmError(err)) => return Err(SwapBuffersError::ContextLost(Box::new(err))),
@ -454,7 +459,7 @@ where
dmabuf: Dmabuf, dmabuf: Dmabuf,
) -> Result<(), Error<E1, E2, E3>> ) -> Result<(), Error<E1, E2, E3>>
where where
B: AsDmabuf<Error=E2>, B: AsDmabuf<Error = E2>,
E1: std::error::Error + 'static, E1: std::error::Error + 'static,
E2: std::error::Error + 'static, E2: std::error::Error + 'static,
E3: std::error::Error + 'static, E3: std::error::Error + 'static,
@ -497,7 +502,15 @@ where
{ {
// yes it does not look like it, but both of these lines should be safe in all cases. // yes it does not look like it, but both of these lines should be safe in all cases.
let slot = self.queued_fb.take().unwrap(); let slot = self.queued_fb.take().unwrap();
let fb = slot.userdata().as_ref().unwrap().1.userdata().unwrap().unwrap().fb; let fb = slot
.userdata()
.as_ref()
.unwrap()
.1
.userdata()
.unwrap()
.unwrap()
.fb;
let flip = if self.drm.commit_pending() { let flip = if self.drm.commit_pending() {
self.drm.commit(fb, true) self.drm.commit(fb, true)

View File

@ -617,7 +617,10 @@ pub struct EGLBufferReader {
#[cfg(feature = "use_system_lib")] #[cfg(feature = "use_system_lib")]
impl EGLBufferReader { impl EGLBufferReader {
fn new(display: Arc<EGLDisplayHandle>, wayland: *mut wl_display) -> Self { fn new(display: Arc<EGLDisplayHandle>, wayland: *mut wl_display) -> Self {
Self { display, wayland: Some(Arc::new(wayland)) } Self {
display,
wayland: Some(Arc::new(wayland)),
}
} }
/// Try to receive [`EGLImages`] from a given [`WlBuffer`]. /// Try to receive [`EGLImages`] from a given [`WlBuffer`].

View File

@ -29,14 +29,14 @@ pub struct EGLSurface {
impl fmt::Debug for EGLSurface { impl fmt::Debug for EGLSurface {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EGLSurface") f.debug_struct("EGLSurface")
.field("display", &self.display) .field("display", &self.display)
// native does not necessarily implement Debug // native does not necessarily implement Debug
.field("surface", &self.surface) .field("surface", &self.surface)
.field("config_id", &self.config_id) .field("config_id", &self.config_id)
.field("pixel_format", &self.pixel_format) .field("pixel_format", &self.pixel_format)
.field("surface_attributes", &self.surface_attributes) .field("surface_attributes", &self.surface_attributes)
.field("logger", &self.logger) .field("logger", &self.logger)
.finish() .finish()
} }
} }

View File

@ -1,15 +1,15 @@
//! Implementation of the rendering traits using OpenGL ES 2 //! Implementation of the rendering traits using OpenGL ES 2
use std::{collections::HashSet, os::raw::c_char};
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt;
use std::ffi::CStr; use std::ffi::CStr;
use std::fmt;
use std::ptr; use std::ptr;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{ use std::sync::{
atomic::{Ordering, AtomicUsize}, atomic::{AtomicUsize, Ordering},
mpsc::{Sender, Receiver, channel} mpsc::{channel, Receiver, Sender},
}; };
use std::{collections::HashSet, os::raw::c_char};
use cgmath::{prelude::*, Matrix3}; use cgmath::{prelude::*, Matrix3};
@ -20,7 +20,8 @@ use crate::backend::allocator::{
Format, Format,
}; };
use crate::backend::egl::{ use crate::backend::egl::{
ffi::egl::types::EGLImage, EGLBuffer, EGLContext, EGLSurface, Format as EGLFormat, MakeCurrentError, display::EGLBufferReader, display::EGLBufferReader, ffi::egl::types::EGLImage, EGLBuffer, EGLContext, EGLSurface,
Format as EGLFormat, MakeCurrentError,
}; };
use crate::backend::SwapBuffersError; use crate::backend::SwapBuffersError;
@ -109,17 +110,17 @@ pub struct Gles2Renderer {
impl fmt::Debug for Gles2Renderer { impl fmt::Debug for Gles2Renderer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Gles2Renderer") f.debug_struct("Gles2Renderer")
.field("id", &self.id) .field("id", &self.id)
.field("buffers", &self.buffers) .field("buffers", &self.buffers)
.field("target_buffer", &self.target_buffer) .field("target_buffer", &self.target_buffer)
.field("target_surface", &self.target_surface) .field("target_surface", &self.target_surface)
.field("current_projection", &self.current_projection) .field("current_projection", &self.current_projection)
.field("extensions", &self.extensions) .field("extensions", &self.extensions)
.field("programs", &self.programs) .field("programs", &self.programs)
// ffi::Gles2 does not implement Debug // ffi::Gles2 does not implement Debug
.field("egl", &self.egl) .field("egl", &self.egl)
.field("logger", &self.logger) .field("logger", &self.logger)
.finish() .finish()
} }
} }
@ -409,8 +410,8 @@ struct BufferCache {
} }
enum BufferCacheVariant { enum BufferCacheVariant {
Egl(Option<EglCache>), Egl(Option<EglCache>),
Shm(Option<ShmCache>), Shm(Option<ShmCache>),
} }
struct EglCache { struct EglCache {
@ -424,7 +425,11 @@ struct ShmCache {
impl Gles2Renderer { impl Gles2Renderer {
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
fn import_shm(&mut self, buffer: &wl_buffer::WlBuffer, cache: &mut Option<ShmCache>) -> Result<Gles2Texture, Gles2Error> { fn import_shm(
&mut self,
buffer: &wl_buffer::WlBuffer,
cache: &mut Option<ShmCache>,
) -> Result<Gles2Texture, Gles2Error> {
use crate::wayland::shm::with_buffer_contents; use crate::wayland::shm::with_buffer_contents;
with_buffer_contents(&buffer, |slice, data| { with_buffer_contents(&buffer, |slice, data| {
@ -500,22 +505,34 @@ impl Gles2Renderer {
} }
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
fn import_egl(&mut self, buffer: &wl_buffer::WlBuffer, reader: &EGLBufferReader, cache: &mut Option<EglCache>) -> Result<Gles2Texture, Gles2Error> { fn import_egl(
&mut self,
buffer: &wl_buffer::WlBuffer,
reader: &EGLBufferReader,
cache: &mut Option<EglCache>,
) -> Result<Gles2Texture, Gles2Error> {
if !self.extensions.iter().any(|ext| ext == "GL_OES_EGL_image") { if !self.extensions.iter().any(|ext| ext == "GL_OES_EGL_image") {
return Err(Gles2Error::GLExtensionNotSupported(&["GL_OES_EGL_image"])); return Err(Gles2Error::GLExtensionNotSupported(&["GL_OES_EGL_image"]));
} }
self.make_current()?; self.make_current()?;
let egl_buffer = cache.as_mut().and_then(|x| x.buf.take()).map(Ok).unwrap_or_else(|| { let egl_buffer = cache
reader.egl_buffer_contents(&buffer) .as_mut()
}).map_err(Gles2Error::EGLBufferAccessError)?; .and_then(|x| x.buf.take())
.map(Ok)
.unwrap_or_else(|| reader.egl_buffer_contents(&buffer))
.map_err(Gles2Error::EGLBufferAccessError)?;
// we do not need to re-import external textures // we do not need to re-import external textures
if egl_buffer.format == EGLFormat::External && cache.is_some() { if egl_buffer.format == EGLFormat::External && cache.is_some() {
return Ok(cache.as_ref().map(|x| x.texture.clone()).unwrap()); return Ok(cache.as_ref().map(|x| x.texture.clone()).unwrap());
} }
let tex = self.import_egl_image(egl_buffer.image(0).unwrap(), egl_buffer.format == EGLFormat::External, cache.as_ref().map(|x| x.texture.0.texture))?; let tex = self.import_egl_image(
egl_buffer.image(0).unwrap(),
egl_buffer.format == EGLFormat::External,
cache.as_ref().map(|x| x.texture.0.texture),
)?;
let texture = cache.as_ref().map(|x| x.texture.clone()).unwrap_or_else(|| { let texture = cache.as_ref().map(|x| x.texture.clone()).unwrap_or_else(|| {
Gles2Texture(Rc::new(Gles2TextureInternal { Gles2Texture(Rc::new(Gles2TextureInternal {
texture: tex, texture: tex,
@ -542,7 +559,12 @@ impl Gles2Renderer {
Ok(texture) Ok(texture)
} }
fn import_egl_image(&self, image: EGLImage, is_external: bool, tex: Option<u32>) -> Result<u32, Gles2Error> { fn import_egl_image(
&self,
image: EGLImage,
is_external: bool,
tex: Option<u32>,
) -> Result<u32, Gles2Error> {
let tex = tex.unwrap_or_else(|| unsafe { let tex = tex.unwrap_or_else(|| unsafe {
let mut tex = 0; let mut tex = 0;
self.gl.GenTextures(1, &mut tex); self.gl.GenTextures(1, &mut tex);
@ -556,8 +578,7 @@ impl Gles2Renderer {
unsafe { unsafe {
self.gl.BindTexture(target, tex); self.gl.BindTexture(target, tex);
self.gl self.gl.EGLImageTargetTexture2DOES(target, image);
.EGLImageTargetTexture2DOES(target, image);
} }
Ok(tex) Ok(tex)
@ -593,7 +614,13 @@ impl Bind<Dmabuf> for Gles2Renderer {
let buffer = self let buffer = self
.buffers .buffers
.iter() .iter()
.find(|buffer| if let Some(dma) = buffer.dmabuf.upgrade() { dma == dmabuf } else { false }) .find(|buffer| {
if let Some(dma) = buffer.dmabuf.upgrade() {
dma == dmabuf
} else {
false
}
})
.map(|buf| { .map(|buf| {
let dmabuf = buf let dmabuf = buf
.dmabuf .dmabuf
@ -773,15 +800,18 @@ impl Renderer for Gles2Renderer {
Ok(texture) Ok(texture)
} }
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
fn import_buffer(&mut self, buffer: &wl_buffer::WlBuffer, egl: Option<&EGLBufferReader>) -> Result<Self::TextureId, Self::Error> { fn import_buffer(
&mut self,
buffer: &wl_buffer::WlBuffer,
egl: Option<&EGLBufferReader>,
) -> Result<Self::TextureId, Self::Error> {
// init cache if not existing // init cache if not existing
let cache_cell = match buffer.as_ref().user_data().get::<Rc<RefCell<BufferCache>>>() { let cache_cell = match buffer.as_ref().user_data().get::<Rc<RefCell<BufferCache>>>() {
Some(cache) => cache.clone(), Some(cache) => cache.clone(),
None => { None => {
let cache = BufferCache { let cache = BufferCache {
cache: Vec::with_capacity(self.id+1), cache: Vec::with_capacity(self.id + 1),
}; };
let data: Rc<RefCell<BufferCache>> = Rc::new(RefCell::new(cache)); let data: Rc<RefCell<BufferCache>> = Rc::new(RefCell::new(cache));
@ -790,7 +820,7 @@ impl Renderer for Gles2Renderer {
result result
} }
}; };
// init cache // init cache
let mut cache = cache_cell.borrow_mut(); let mut cache = cache_cell.borrow_mut();
while cache.cache.len() < self.id { while cache.cache.len() < self.id {
@ -805,10 +835,10 @@ impl Renderer for Gles2Renderer {
BufferCacheVariant::Shm(None) BufferCacheVariant::Shm(None)
} else { } else {
unreachable!("Completely unknown buffer format. How did we got here?"); unreachable!("Completely unknown buffer format. How did we got here?");
} },
)); ));
} }
// delegate for different buffer types // delegate for different buffer types
match cache.cache[self.id].as_mut() { match cache.cache[self.id].as_mut() {
Some(BufferCacheVariant::Egl(cache)) => self.import_egl(&buffer, egl.unwrap(), cache), Some(BufferCacheVariant::Egl(cache)) => self.import_egl(&buffer, egl.unwrap(), cache),
@ -889,7 +919,8 @@ impl Renderer for Gles2Renderer {
.TexParameteri(target, ffi::TEXTURE_MIN_FILTER, ffi::LINEAR as i32); .TexParameteri(target, ffi::TEXTURE_MIN_FILTER, ffi::LINEAR as i32);
self.gl.UseProgram(self.programs[tex.0.texture_kind].program); self.gl.UseProgram(self.programs[tex.0.texture_kind].program);
self.gl.Uniform1i(self.programs[tex.0.texture_kind].uniform_tex, 0); self.gl
.Uniform1i(self.programs[tex.0.texture_kind].uniform_tex, 0);
self.gl.UniformMatrix3fv( self.gl.UniformMatrix3fv(
self.programs[tex.0.texture_kind].uniform_matrix, self.programs[tex.0.texture_kind].uniform_matrix,
1, 1,

View File

@ -164,7 +164,6 @@ pub trait Renderer {
&[wl_shm::Format::Argb8888, wl_shm::Format::Xrgb8888] &[wl_shm::Format::Argb8888, wl_shm::Format::Xrgb8888]
} }
/// Import a given buffer into the renderer. /// Import a given buffer into the renderer.
/// ///
/// Returns a texture_id, which can be used with `render_texture(_at)` or implementation-specific functions. /// Returns a texture_id, which can be used with `render_texture(_at)` or implementation-specific functions.
@ -176,7 +175,11 @@ pub trait Renderer {
/// The implementation defines, if the id keeps being valid, if the buffer is released, /// The implementation defines, if the id keeps being valid, if the buffer is released,
/// to avoid relying on implementation details, keep the buffer alive, until you destroyed this texture again. /// to avoid relying on implementation details, keep the buffer alive, until you destroyed this texture again.
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
fn import_buffer(&mut self, buffer: &wl_buffer::WlBuffer, egl: Option<&EGLBufferReader>) -> Result<Self::TextureId, Self::Error>; fn import_buffer(
&mut self,
buffer: &wl_buffer::WlBuffer,
egl: Option<&EGLBufferReader>,
) -> Result<Self::TextureId, Self::Error>;
/// Initialize a rendering context on the current rendering target with given dimensions and transformation. /// Initialize a rendering context on the current rendering target with given dimensions and transformation.
/// ///
@ -248,10 +251,18 @@ pub trait Renderer {
/// Returns the dimensions of a wl_buffer /// Returns the dimensions of a wl_buffer
#[cfg(all(feature = "wayland_frontend", feature = "backend_egl"))] #[cfg(all(feature = "wayland_frontend", feature = "backend_egl"))]
pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer, egl_buffer_reader: Option<&EGLBufferReader>) -> Option<(i32, i32)> { pub fn buffer_dimensions(
if let Some((w, h)) = egl_buffer_reader.as_ref().and_then(|x| x.egl_buffer_dimensions(&buffer)) { buffer: &wl_buffer::WlBuffer,
egl_buffer_reader: Option<&EGLBufferReader>,
) -> Option<(i32, i32)> {
if let Some((w, h)) = egl_buffer_reader
.as_ref()
.and_then(|x| x.egl_buffer_dimensions(&buffer))
{
Some((w, h)) Some((w, h))
} else if let Ok((w, h)) = crate::wayland::shm::with_buffer_contents(&buffer, |_, data| (data.width, data.height)) { } else if let Ok((w, h)) =
crate::wayland::shm::with_buffer_contents(&buffer, |_, data| (data.width, data.height))
{
Some((w, h)) Some((w, h))
} else { } else {
None None
@ -263,9 +274,11 @@ pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer, egl_buffer_reader: Option
pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer) -> Option<(i32, i32)> { pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer) -> Option<(i32, i32)> {
use crate::backend::allocator::Buffer; use crate::backend::allocator::Buffer;
if let Ok((w, h)) = crate::wayland::shm::with_buffer_contents(&buffer, |_, data| (data.width, data.height)) { if let Ok((w, h)) =
crate::wayland::shm::with_buffer_contents(&buffer, |_, data| (data.width, data.height))
{
Some((w, h)) Some((w, h))
} else { } else {
None None
} }
} }

View File

@ -291,7 +291,11 @@ impl Renderer for WinitGraphicsBackend {
} }
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
fn import_buffer(&mut self, buffer: &wl_buffer::WlBuffer, egl: Option<&EGLBufferReader>) -> Result<Self::TextureId, Self::Error> { fn import_buffer(
&mut self,
buffer: &wl_buffer::WlBuffer,
egl: Option<&EGLBufferReader>,
) -> Result<Self::TextureId, Self::Error> {
self.renderer.import_buffer(buffer, egl) self.renderer.import_buffer(buffer, egl)
} }