From 50b00832692876ec676463707d5c572e8900ecc0 Mon Sep 17 00:00:00 2001 From: Victor Brekenfeld Date: Mon, 26 Apr 2021 21:43:30 +0200 Subject: [PATCH] renderer: Implement import_egl for wl_drm --- src/backend/drm/render.rs | 6 +++++ src/backend/egl/mod.rs | 2 +- src/backend/renderer/gles2/mod.rs | 43 +++++++++++++++++++++++++++++-- src/backend/renderer/mod.rs | 6 ++++- src/backend/winit.rs | 9 +++++-- 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/backend/drm/render.rs b/src/backend/drm/render.rs index e58e381..0d94f98 100644 --- a/src/backend/drm/render.rs +++ b/src/backend/drm/render.rs @@ -13,6 +13,7 @@ use wayland_server::protocol::{wl_shm, wl_buffer}; use crate::backend::SwapBuffersError; use crate::backend::allocator::{Allocator, Format, Fourcc, Modifier, Swapchain, SwapchainError, Slot, Buffer, dmabuf::Dmabuf}; use crate::backend::renderer::{Renderer, Bind, Transform, Texture}; +use crate::backend::egl::EGLBuffer; use super::{DrmSurface, DrmError, device::DevPath, surface::DrmSurfaceInternal}; pub struct DrmRenderSurface< @@ -246,6 +247,11 @@ where self.renderer.import_shm(buffer).map_err(Error::RenderError) } + #[cfg(feature = "wayland_frontend")] + fn import_egl(&mut self, buffer: &EGLBuffer) -> Result { + self.renderer.import_egl(buffer).map_err(Error::RenderError) + } + fn begin(&mut self, width: u32, height: u32, transform: Transform) -> Result<(), Error> { if self.current_buffer.is_some() { return Ok(()); diff --git a/src/backend/egl/mod.rs b/src/backend/egl/mod.rs index fd8a987..257b278 100644 --- a/src/backend/egl/mod.rs +++ b/src/backend/egl/mod.rs @@ -212,7 +212,7 @@ pub enum TextureCreationError { /// Texture format types #[repr(i32)] #[allow(non_camel_case_types)] -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] pub enum Format { /// RGB format RGB = ffi::egl::TEXTURE_RGB as i32, diff --git a/src/backend/renderer/gles2/mod.rs b/src/backend/renderer/gles2/mod.rs index e448a88..a9bb672 100644 --- a/src/backend/renderer/gles2/mod.rs +++ b/src/backend/renderer/gles2/mod.rs @@ -8,7 +8,7 @@ use cgmath::{prelude::*, Matrix3, Vector2}; mod shaders; use crate::backend::SwapBuffersError; use crate::backend::allocator::{dmabuf::{Dmabuf, WeakDmabuf}, Format}; -use crate::backend::egl::{EGLContext, EGLSurface, ffi::egl::types::EGLImage, MakeCurrentError}; +use crate::backend::egl::{EGLContext, EGLSurface, EGLBuffer, Format as EGLFormat, ffi::egl::types::EGLImage, MakeCurrentError}; use super::{Renderer, Bind, Unbind, Transform, Texture}; #[cfg(feature = "wayland_frontend")] @@ -461,7 +461,7 @@ impl Renderer for Gles2Renderer { height: image.height(), }; self.egl.unbind()?; - + Ok(texture) } @@ -521,6 +521,45 @@ impl Renderer for Gles2Renderer { }).map_err(Gles2Error::BufferAccessError)? } + #[cfg(feature = "wayland_frontend")] + fn import_egl(&mut self, buffer: &EGLBuffer) -> Result { + if !self.extensions.iter().any(|ext| ext == "GL_OES_EGL_image") { + return Err(Gles2Error::GLExtensionNotSupported(&["GL_OES_EGL_image"])); + } + + self.make_current()?; + + let mut tex = 0; + let target = if buffer.format == EGLFormat::External { ffi::TEXTURE_EXTERNAL_OES } else { ffi::TEXTURE_2D }; + unsafe { + self.gl.GenTextures(1, &mut tex); + self.gl.BindTexture(target, tex); + + self.gl.EGLImageTargetTexture2DOES( + target, + buffer.image(0).unwrap(), + ); + } + + let texture = Gles2Texture { + texture: tex, + texture_kind: match buffer.format { + EGLFormat::RGB => 3, + EGLFormat::RGBA => 2, + EGLFormat::External => 4, + _ => unreachable!("EGLBuffer currenly does not expose multi-planar buffers to us"), + }, + is_external: buffer.format == EGLFormat::External, + y_inverted: buffer.y_inverted, + width: buffer.width, + height: buffer.height, + }; + self.egl.unbind()?; + + Ok(texture) + } + + fn begin(&mut self, width: u32, height: u32, transform: Transform) -> Result<(), Gles2Error> { self.make_current()?; unsafe { diff --git a/src/backend/renderer/mod.rs b/src/backend/renderer/mod.rs index 72dab5b..f9bd9fe 100644 --- a/src/backend/renderer/mod.rs +++ b/src/backend/renderer/mod.rs @@ -8,6 +8,8 @@ use wayland_server::protocol::{wl_shm, wl_buffer}; use crate::backend::SwapBuffersError; #[cfg(feature = "renderer_gl")] pub mod gles2; +#[cfg(feature = "wayland_frontend")] +use crate::backend::egl::EGLBuffer; #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] pub enum Transform { @@ -143,7 +145,9 @@ pub trait Renderer { } #[cfg(feature = "wayland_frontend")] fn import_shm(&mut self, buffer: &wl_buffer::WlBuffer) -> Result; - + #[cfg(feature = "wayland_frontend")] + fn import_egl(&mut self, buffer: &EGLBuffer) -> Result; + fn begin(&mut self, width: u32, height: u32, transform: Transform) -> Result<(), ::Error>; fn finish(&mut self) -> Result<(), SwapBuffersError>; diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 6e31082..9f9a739 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -2,7 +2,7 @@ use crate::backend::egl::display::EGLDisplay; use crate::backend::{ - egl::{context::GlAttributes, native, EGLContext, EGLSurface, Error as EGLError}, + egl::{context::GlAttributes, native, EGLContext, EGLSurface, EGLBuffer, Error as EGLError}, renderer::{ Renderer, Bind, Transform, gles2::{Gles2Renderer, Gles2Error, Gles2Texture}, @@ -259,7 +259,7 @@ impl WinitGraphicsBackend { impl Renderer for WinitGraphicsBackend { type Error = Gles2Error; type Texture = Gles2Texture; - + #[cfg(feature = "image")] fn import_bitmap>(&mut self, image: &image::ImageBuffer, C>) -> Result { self.renderer.import_bitmap(image) @@ -274,6 +274,11 @@ impl Renderer for WinitGraphicsBackend { fn import_shm(&mut self, buffer: &wl_buffer::WlBuffer) -> Result { self.renderer.import_shm(buffer) } + + #[cfg(feature = "wayland_frontend")] + fn import_egl(&mut self, buffer: &EGLBuffer) -> Result { + self.renderer.import_egl(buffer) + } fn begin(&mut self, width: u32, height: u32, transform: Transform) -> Result<(), ::Error> { self.renderer.bind(self.egl.clone())?;