Rework egl image api
This commit is contained in:
parent
5d7e96103d
commit
726991367d
|
@ -18,7 +18,6 @@ use std::mem;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
#[cfg(feature = "backend_drm")]
|
#[cfg(feature = "backend_drm")]
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use wayland_server::Display;
|
|
||||||
|
|
||||||
/// EGL context for rendering
|
/// EGL context for rendering
|
||||||
pub struct EGLContext<B: native::Backend, N: native::NativeDisplay<B>> {
|
pub struct EGLContext<B: native::Backend, N: native::NativeDisplay<B>> {
|
||||||
|
@ -28,8 +27,8 @@ pub struct EGLContext<B: native::Backend, N: native::NativeDisplay<B>> {
|
||||||
pub(crate) config_id: ffi::egl::types::EGLConfig,
|
pub(crate) config_id: ffi::egl::types::EGLConfig,
|
||||||
pub(crate) surface_attributes: Vec<c_int>,
|
pub(crate) surface_attributes: Vec<c_int>,
|
||||||
pixel_format: PixelFormat,
|
pixel_format: PixelFormat,
|
||||||
wl_drm_support: bool,
|
pub(crate) wl_drm_support: bool,
|
||||||
egl_to_texture_support: bool,
|
pub(crate) egl_to_texture_support: bool,
|
||||||
logger: slog::Logger,
|
logger: slog::Logger,
|
||||||
_backend: PhantomData<B>,
|
_backend: PhantomData<B>,
|
||||||
}
|
}
|
||||||
|
@ -474,68 +473,6 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
pub fn get_pixel_format(&self) -> PixelFormat {
|
pub fn get_pixel_format(&self) -> PixelFormat {
|
||||||
self.pixel_format
|
self.pixel_format
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Binds this EGL context to the given Wayland display.
|
|
||||||
///
|
|
||||||
/// This will allow clients to utilize EGL to create hardware-accelerated
|
|
||||||
/// surfaces. The server will need to be able to handle egl-wl_buffers.
|
|
||||||
/// See the `wayland::drm` module.
|
|
||||||
///
|
|
||||||
/// ## Errors
|
|
||||||
///
|
|
||||||
/// This might return `WlExtensionNotSupported` if binding is not supported
|
|
||||||
/// by the EGL implementation.
|
|
||||||
///
|
|
||||||
/// This might return `OtherEGLDisplayAlreadyBound` if called for the same
|
|
||||||
/// `Display` multiple times, as only one context may be bound at any given time.
|
|
||||||
pub fn bind_wl_display(&self, display: &Display) -> Result<()> {
|
|
||||||
if !self.wl_drm_support {
|
|
||||||
bail!(ErrorKind::EglExtensionNotSupported(&["EGL_WL_bind_wayland_display"]));
|
|
||||||
}
|
|
||||||
let res = unsafe { ffi::egl::BindWaylandDisplayWL(*self.display, display.ptr() as *mut _) };
|
|
||||||
if res == 0 {
|
|
||||||
bail!(ErrorKind::OtherEGLDisplayAlreadyBound);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Unbinds this EGL context from the given Wayland display.
|
|
||||||
///
|
|
||||||
/// This will stop clients from using previously available extensions
|
|
||||||
/// to utilize hardware-accelerated surface via EGL.
|
|
||||||
///
|
|
||||||
/// ## Errors
|
|
||||||
///
|
|
||||||
/// This might return `WlExtensionNotSupported` if binding is not supported
|
|
||||||
/// by the EGL implementation.
|
|
||||||
///
|
|
||||||
/// This might return `OtherEGLDisplayAlreadyBound` if called for the same
|
|
||||||
/// `Display` multiple times, as only one context may be bound at any given time.
|
|
||||||
pub fn unbind_wl_display(&self, display: &Display) -> Result<()> {
|
|
||||||
if !self.wl_drm_support {
|
|
||||||
bail!(ErrorKind::EglExtensionNotSupported(&["EGL_WL_bind_wayland_display"]));
|
|
||||||
}
|
|
||||||
let res = unsafe { ffi::egl::UnbindWaylandDisplayWL(*self.display, display.ptr() as *mut _) };
|
|
||||||
if res == 0 {
|
|
||||||
bail!(ErrorKind::NoEGLDisplayBound);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
pub unsafe fn egl_image_to_texture(&self, image: ffi::egl::types::EGLImage, tex_id: c_uint) -> Result<()> {
|
|
||||||
if !self.egl_to_texture_support {
|
|
||||||
bail!(ErrorKind::EglExtensionNotSupported(&["EGL_OES_image", "EGL_OES_image_base"]));
|
|
||||||
}
|
|
||||||
ffi::gl::EGLImageTargetTexture2DOES(tex_id, image);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn destroy_egl_image(&self, image: ffi::egl::types::EGLImage, tex_id: c_uint) -> Result<()> {
|
|
||||||
ffi::gl::DestroyImageKHR(self.display, image);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<B: native::Backend, N: native::NativeDisplay<B> + Send> Send for EGLContext<B, N> {}
|
unsafe impl<B: native::Backend, N: native::NativeDisplay<B> + Send> Send for EGLContext<B, N> {}
|
||||||
|
|
|
@ -47,6 +47,11 @@ error_chain! {
|
||||||
description("Failed to create a new EGLSurface")
|
description("Failed to create a new EGLSurface")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc = "The OpenGL context has been lost and needs to be recreated"]
|
||||||
|
ContextLost {
|
||||||
|
description("The OpenGL context has been lost and needs to be recreated")
|
||||||
|
}
|
||||||
|
|
||||||
#[doc = "The required EGL extension is not supported by the underlying EGL implementation"]
|
#[doc = "The required EGL extension is not supported by the underlying EGL implementation"]
|
||||||
EglExtensionNotSupported(extensions: &'static [&'static str]) {
|
EglExtensionNotSupported(extensions: &'static [&'static str]) {
|
||||||
description("The required EGL extension is not supported by the underlying EGL implementation"),
|
description("The required EGL extension is not supported by the underlying EGL implementation"),
|
||||||
|
@ -64,6 +69,21 @@ error_chain! {
|
||||||
description("No EGLDisplay is currently bound to this WlDisplay")
|
description("No EGLDisplay is currently bound to this WlDisplay")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc = "Index of plane is out of bounds for EGLImages"]
|
||||||
|
PlaneIndexOutOfBounds {
|
||||||
|
description("Index of plane is out of bounds for EGLImages")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = "This buffer is not mananged by EGL"]
|
||||||
|
BufferNotManaged {
|
||||||
|
description("This buffer is not mananged by EGL")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = "Failed to create EGLImages from the buffer"]
|
||||||
|
EGLImageCreationFailed {
|
||||||
|
description("Failed to create EGLImages from the buffer")
|
||||||
|
}
|
||||||
|
|
||||||
#[doc = "The reason of failure could not be determined"]
|
#[doc = "The reason of failure could not be determined"]
|
||||||
Unknown(err_no: u32)
|
Unknown(err_no: u32)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ pub mod ffi;
|
||||||
pub mod native;
|
pub mod native;
|
||||||
pub mod surface;
|
pub mod surface;
|
||||||
pub use self::surface::EGLSurface;
|
pub use self::surface::EGLSurface;
|
||||||
|
pub mod wayland;
|
||||||
|
|
||||||
/// Error that can happen when swapping buffers.
|
/// Error that can happen when swapping buffers.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -166,6 +167,7 @@ pub trait EGLGraphicsBackend: GraphicsBackend {
|
||||||
/// This might return `OtherEGLDisplayAlreadyBound` if called for the same
|
/// This might return `OtherEGLDisplayAlreadyBound` if called for the same
|
||||||
/// `Display` multiple times, as only one context may be bound at any given time.
|
/// `Display` multiple times, as only one context may be bound at any given time.
|
||||||
fn bind_wl_display(&self, display: &Display) -> ::std::result::Result<(), EglExtensionNotSupportedError>;
|
fn bind_wl_display(&self, display: &Display) -> ::std::result::Result<(), EglExtensionNotSupportedError>;
|
||||||
|
|
||||||
/// Unbinds this EGL context from the given Wayland display.
|
/// Unbinds this EGL context from the given Wayland display.
|
||||||
///
|
///
|
||||||
/// This will stop clients from using previously available extensions
|
/// This will stop clients from using previously available extensions
|
||||||
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
use backend::graphics::egl::{EGLContext, EGLImage, ffi, native};
|
||||||
|
use backend::graphics::egl::error::*;
|
||||||
|
use nix::libc::{c_uint};
|
||||||
|
use std::rc::{Rc, Weak};
|
||||||
|
use wayland_server::{Display, Resource};
|
||||||
|
use wayland_server::protocol::wl_buffer::WlBuffer;
|
||||||
|
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum Format {
|
||||||
|
RGB = ffi::egl::TEXTURE_RGB as i32,
|
||||||
|
RGBA = ffi::egl::TEXTURE_RGBA as i32,
|
||||||
|
External = ffi::egl::TEXTURE_EXTERNAL_WL,
|
||||||
|
Y_UV = ffi::egl::TEXTURE_Y_UV_WL,
|
||||||
|
Y_U_V = ffi::egl::TEXTURE_Y_U_V_WL,
|
||||||
|
Y_XUXV = ffi::egl::TEXTURE_Y_XUXV_WL,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format {
|
||||||
|
pub fn num_planes(&self) -> usize {
|
||||||
|
match *self {
|
||||||
|
Format::RGB | Format::RGBA | Format::External => 1,
|
||||||
|
Format::Y_UV | Format::Y_XUXV => 2,
|
||||||
|
Format::Y_U_V => 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EGLImages {
|
||||||
|
display: Weak<ffi::egl::types::EGLDisplay>,
|
||||||
|
pub width: u32,
|
||||||
|
pub height: u32,
|
||||||
|
pub y_inverted: bool,
|
||||||
|
pub format: Format,
|
||||||
|
images: Vec<EGLImage>,
|
||||||
|
buffer: WlBuffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EGLImages {
|
||||||
|
pub fn num_planes(&self) -> usize {
|
||||||
|
self.format.num_planes()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn bind_to_tex(&self, plane: usize, tex_id: c_uint) -> Result<()> {
|
||||||
|
if self.display.upgrade().is_some() {
|
||||||
|
ffi::gl::EGLImageTargetTexture2DOES(tex_id, *self.images.get(plane).chain_err(|| ErrorKind::PlaneIndexOutOfBounds)?);
|
||||||
|
match ffi::egl::GetError() as u32 {
|
||||||
|
ffi::gl::NO_ERROR => Ok(()),
|
||||||
|
err => bail!(ErrorKind::Unknown(err)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bail!(ErrorKind::ContextLost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for EGLImages {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(display) = self.display.upgrade() {
|
||||||
|
for image in self.images.drain(..) {
|
||||||
|
unsafe { ffi::egl::DestroyImageKHR(*display, image); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
|
/// Binds this EGL context to the given Wayland display.
|
||||||
|
///
|
||||||
|
/// This will allow clients to utilize EGL to create hardware-accelerated
|
||||||
|
/// surfaces. The server will need to be able to handle egl-wl_buffers.
|
||||||
|
/// See the `wayland::drm` module.
|
||||||
|
///
|
||||||
|
/// ## Errors
|
||||||
|
///
|
||||||
|
/// This might return `WlExtensionNotSupported` if binding is not supported
|
||||||
|
/// by the EGL implementation.
|
||||||
|
///
|
||||||
|
/// This might return `OtherEGLDisplayAlreadyBound` if called for the same
|
||||||
|
/// `Display` multiple times, as only one context may be bound at any given time.
|
||||||
|
pub fn bind_wl_display(&self, display: &Display) -> Result<()> {
|
||||||
|
if !self.wl_drm_support {
|
||||||
|
bail!(ErrorKind::EglExtensionNotSupported(&["EGL_WL_bind_wayland_display"]));
|
||||||
|
}
|
||||||
|
let res = unsafe { ffi::egl::BindWaylandDisplayWL(*self.display, display.ptr() as *mut _) };
|
||||||
|
if res == 0 {
|
||||||
|
bail!(ErrorKind::OtherEGLDisplayAlreadyBound);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unbinds this EGL context from the given Wayland display.
|
||||||
|
///
|
||||||
|
/// This will stop clients from using previously available extensions
|
||||||
|
/// to utilize hardware-accelerated surface via EGL.
|
||||||
|
///
|
||||||
|
/// ## Errors
|
||||||
|
///
|
||||||
|
/// This might return `WlExtensionNotSupported` if binding is not supported
|
||||||
|
/// by the EGL implementation.
|
||||||
|
///
|
||||||
|
/// This might return `OtherEGLDisplayAlreadyBound` if called for the same
|
||||||
|
/// `Display` multiple times, as only one context may be bound at any given time.
|
||||||
|
pub fn unbind_wl_display(&self, display: &Display) -> Result<()> {
|
||||||
|
if !self.wl_drm_support {
|
||||||
|
bail!(ErrorKind::EglExtensionNotSupported(&["EGL_WL_bind_wayland_display"]));
|
||||||
|
}
|
||||||
|
let res = unsafe { ffi::egl::UnbindWaylandDisplayWL(*self.display, display.ptr() as *mut _) };
|
||||||
|
if res == 0 {
|
||||||
|
bail!(ErrorKind::NoEGLDisplayBound);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn egl_buffer_contents<T: native::NativeSurface>(&self, buffer: WlBuffer) -> Result<EGLImages> {
|
||||||
|
if !self.egl_to_texture_support {
|
||||||
|
bail!(ErrorKind::EglExtensionNotSupported(&["GL_OES_EGL_image"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut format: i32 = 0;
|
||||||
|
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::EGL_TEXTURE_FORMAT, &mut format as *mut _) == 0 } {
|
||||||
|
bail!(ErrorKind::BufferNotManaged);
|
||||||
|
}
|
||||||
|
let format = match format {
|
||||||
|
x if x == ffi::egl::TEXTURE_RGB as i32 => Format::RGB,
|
||||||
|
x if x == ffi::egl::TEXTURE_RGBA as i32 => Format::RGBA,
|
||||||
|
ffi::egl::TEXTURE_EXTERNAL_WL => Format::External,
|
||||||
|
ffi::egl::TEXTURE_Y_UV_WL => Format::Y_UV,
|
||||||
|
ffi::egl::TEXTURE_Y_U_V_WL => Format::Y_U_V,
|
||||||
|
ffi::egl::TEXTURE_Y_XUXV_WL => Format::Y_XUXV,
|
||||||
|
_ => panic!("EGL returned invalid texture type"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut width: i32 = 0;
|
||||||
|
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::WIDTH as i32, &mut width as *mut _) == 0 } {
|
||||||
|
bail!(ErrorKind::BufferNotManaged);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut height: i32 = 0;
|
||||||
|
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::HEIGHT as i32, &mut height as *mut _) == 0 } {
|
||||||
|
bail!(ErrorKind::BufferNotManaged);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut inverted: i32 = 0;
|
||||||
|
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::WAYLAND_Y_INVERTED_WL, &mut inverted as *mut _) == 0 } {
|
||||||
|
inverted = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut images = Vec::with_capacity(format.num_planes());
|
||||||
|
for i in 0..format.num_planes() {
|
||||||
|
let mut out = Vec::with_capacity(3);
|
||||||
|
out.push(ffi::egl::WAYLAND_PLANE_WL as i32);
|
||||||
|
out.push(i as i32);
|
||||||
|
out.push(ffi::egl::NONE as i32);
|
||||||
|
|
||||||
|
images.push({
|
||||||
|
let image =
|
||||||
|
unsafe { ffi::egl::CreateImageKHR(
|
||||||
|
*self.display,
|
||||||
|
ffi::egl::NO_CONTEXT,
|
||||||
|
ffi::egl::WAYLAND_BUFFER_WL,
|
||||||
|
buffer.ptr() as *mut _,
|
||||||
|
out.as_ptr(),
|
||||||
|
) };
|
||||||
|
if image == ffi::egl::NO_IMAGE_KHR {
|
||||||
|
bail!(ErrorKind::EGLImageCreationFailed);
|
||||||
|
} else {
|
||||||
|
image
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(EGLImages {
|
||||||
|
display: Rc::downgrade(&self.display),
|
||||||
|
width: width as u32,
|
||||||
|
height: height as u32,
|
||||||
|
y_inverted: inverted != 0,
|
||||||
|
format,
|
||||||
|
images,
|
||||||
|
buffer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -87,7 +87,7 @@ impl<
|
||||||
.into_iter()
|
.into_iter()
|
||||||
// Create devices
|
// Create devices
|
||||||
.flat_map(|path| {
|
.flat_map(|path| {
|
||||||
match unsafe { DrmDevice::new(
|
match DrmDevice::new(
|
||||||
{
|
{
|
||||||
match session.open(&path, fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY | fcntl::O_NONBLOCK) {
|
match session.open(&path, fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY | fcntl::O_NONBLOCK) {
|
||||||
Ok(fd) => SessionFdDrmDevice(fd),
|
Ok(fd) => SessionFdDrmDevice(fd),
|
||||||
|
@ -97,7 +97,7 @@ impl<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, logger.clone()
|
}, logger.clone()
|
||||||
) } {
|
) {
|
||||||
// Call the handler, which might add it to the runloop
|
// Call the handler, which might add it to the runloop
|
||||||
Ok(mut device) => match handler.device_added(&mut evlh.state().as_proxy(), &mut device) {
|
Ok(mut device) => match handler.device_added(&mut evlh.state().as_proxy(), &mut device) {
|
||||||
// fstat them
|
// fstat them
|
||||||
|
@ -253,25 +253,23 @@ where
|
||||||
info!(evlh.state().get(token).logger, "Device Added");
|
info!(evlh.state().get(token).logger, "Device Added");
|
||||||
if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) {
|
if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) {
|
||||||
let mut device = {
|
let mut device = {
|
||||||
match unsafe {
|
match DrmDevice::new(
|
||||||
DrmDevice::new(
|
{
|
||||||
{
|
let logger = evlh.state().get(token).logger.clone();
|
||||||
let logger = evlh.state().get(token).logger.clone();
|
match evlh.state().get_mut(token).session.open(
|
||||||
match evlh.state().get_mut(token).session.open(
|
path,
|
||||||
path,
|
fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY
|
||||||
fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY
|
| fcntl::O_NONBLOCK,
|
||||||
| fcntl::O_NONBLOCK,
|
) {
|
||||||
) {
|
Ok(fd) => SessionFdDrmDevice(fd),
|
||||||
Ok(fd) => SessionFdDrmDevice(fd),
|
Err(err) => {
|
||||||
Err(err) => {
|
warn!(logger, "Unable to open drm device {:?}, Error: {:?}. Skipping", path, err);
|
||||||
warn!(logger, "Unable to open drm device {:?}, Error: {:?}. Skipping", path, err);
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
evlh.state().get(token).logger.clone(),
|
},
|
||||||
)
|
evlh.state().get(token).logger.clone(),
|
||||||
} {
|
) {
|
||||||
Ok(dev) => dev,
|
Ok(dev) => dev,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(
|
warn!(
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
use ::backend::graphics::egl::ffi;
|
|
||||||
use ::backend::graphics::egl::{EGLContext, NativeSurface};
|
|
||||||
use ::backend::graphics::egl::EGLImage;
|
|
||||||
use wayland_server::protocol::wl_buffer::WlBuffer;
|
|
||||||
use wayland_server::Resource;
|
|
||||||
|
|
||||||
/// Error that can occur when accessing an EGL buffer
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum BufferAccessError {
|
|
||||||
/// This buffer is not managed by EGL
|
|
||||||
NotManaged,
|
|
||||||
/// Failed to create EGLImages from the buffer
|
|
||||||
FailedToCreateEGLImage,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(i32)]
|
|
||||||
pub enum Format {
|
|
||||||
RGB = ffi::egl::TEXTURE_RGB as i32,
|
|
||||||
RGBA = ffi::egl::TEXTURE_RGBA as i32,
|
|
||||||
External = ffi::egl::TEXTURE_EXTERNAL_WL,
|
|
||||||
Y_UV = ffi::egl::TEXTURE_Y_UV_WL,
|
|
||||||
Y_U_V = ffi::egl::TEXTURE_Y_U_V_WL,
|
|
||||||
Y_XUXV = ffi::egl::TEXTURE_Y_XUXV_WL,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Format {
|
|
||||||
pub fn num_planes(&self) -> u32 {
|
|
||||||
match *self {
|
|
||||||
Format::RGB | Format::RGBA | Format::External => 1,
|
|
||||||
Format::Y_UV | Format::Y_XUXV => 2,
|
|
||||||
Format::Y_U_V => 3,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EGLImages {
|
|
||||||
pub width: u32,
|
|
||||||
pub height: u32,
|
|
||||||
pub y_inverted: bool,
|
|
||||||
pub format: Format,
|
|
||||||
images: Vec<EGLImage>,
|
|
||||||
buffer: WlBuffer,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn buffer_contents<T: NativeSurface>(buffer: WlBuffer, context: &EGLContext<T>) -> Result<(Vec<EGLImages>, attributes: Attributes), BufferAccessError>
|
|
||||||
where
|
|
||||||
{
|
|
||||||
let mut format: i32 = 0;
|
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(context.display, buffer.ptr() as *mut _, ffi::egl::EGL_TEXTURE_FORMAT, &mut format as *mut _) == 0 } {
|
|
||||||
return Err(BufferAccessError::NotManaged);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut width: i32 = 0;
|
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(context.display, buffer.ptr() as *mut _, ffi::egl::WIDTH as i32, &mut width as *mut _) == 0 } {
|
|
||||||
return Err(BufferAccessError::NotManaged);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut height: i32 = 0;
|
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(context.display, buffer.ptr() as *mut _, ffi::egl::HEIGHT as i32, &mut height as *mut _) == 0 } {
|
|
||||||
return Err(BufferAccessError::NotManaged);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut inverted: i32 = 0;
|
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(context.display, buffer.ptr() as *mut _, ffi::egl::WAYLAND_Y_INVERTED_WL, &mut inverted as *mut _) == 0 } {
|
|
||||||
inverted = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut images = Vec::with_capacity(attributes.format.num_planes() as usize);
|
|
||||||
for i in 0..attributes.format.num_planes() {
|
|
||||||
let mut out = Vec::with_capacity(3);
|
|
||||||
out.push(ffi::egl::WAYLAND_PLANE_WL as i32);
|
|
||||||
out.push(i as i32);
|
|
||||||
out.push(ffi::egl::NONE as i32);
|
|
||||||
|
|
||||||
images.push({
|
|
||||||
let image =
|
|
||||||
unsafe { ffi::egl::CreateImageKHR(
|
|
||||||
context.display,
|
|
||||||
ffi::egl::NO_CONTEXT,
|
|
||||||
ffi::egl::WAYLAND_BUFFER_WL,
|
|
||||||
buffer.ptr() as *mut _,
|
|
||||||
out.as_ptr(),
|
|
||||||
) };
|
|
||||||
if image == ffi::egl::NO_IMAGE_KHR {
|
|
||||||
return Err(BufferAccessError::FailedToCreateEGLImage);
|
|
||||||
} else {
|
|
||||||
image
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = EGLImages {
|
|
||||||
width: width as u32,
|
|
||||||
height: height as u32,
|
|
||||||
y_inverted: inverted != 0,
|
|
||||||
format: match format {
|
|
||||||
x if x == ffi::egl::TEXTURE_RGB as i32 => Format::RGB,
|
|
||||||
x if x == ffi::egl::TEXTURE_RGBA as i32 => Format::RGBA,
|
|
||||||
ffi::egl::TEXTURE_EXTERNAL_WL => Format::External,
|
|
||||||
ffi::egl::TEXTURE_Y_UV_WL => Format::Y_UV,
|
|
||||||
ffi::egl::TEXTURE_Y_U_V_WL => Format::Y_U_V,
|
|
||||||
ffi::egl::TEXTURE_Y_XUXV_WL => Format::Y_XUXV,
|
|
||||||
_ => panic!("EGL returned invalid texture type"),
|
|
||||||
},
|
|
||||||
images,
|
|
||||||
buffer,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
|
@ -19,7 +19,6 @@
|
||||||
//! quickly encounter a panic.
|
//! quickly encounter a panic.
|
||||||
|
|
||||||
pub mod compositor;
|
pub mod compositor;
|
||||||
//pub mod drm;
|
|
||||||
pub mod output;
|
pub mod output;
|
||||||
pub mod seat;
|
pub mod seat;
|
||||||
pub mod shm;
|
pub mod shm;
|
||||||
|
|
Loading…
Reference in New Issue