egl: EGLContext borrow native to circumvent RefCell runtime error
This commit is contained in:
parent
0ed69bf2da
commit
8abcc145d7
|
@ -1,6 +1,5 @@
|
||||||
use drm::control::{connector, crtc, Mode, ResourceHandles, ResourceInfo};
|
use drm::control::{connector, crtc, Mode, ResourceHandles, ResourceInfo};
|
||||||
use nix::libc::dev_t;
|
use nix::libc::dev_t;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -28,7 +27,7 @@ pub struct EglDevice<
|
||||||
> where
|
> where
|
||||||
<D as Device>::Surface: NativeSurface,
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
dev: Rc<RefCell<EGLContext<B, D>>>,
|
dev: Rc<EGLContext<B, D>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,9 +81,9 @@ where
|
||||||
debug!(log, "Creating egl context from device");
|
debug!(log, "Creating egl context from device");
|
||||||
Ok(EglDevice {
|
Ok(EglDevice {
|
||||||
// Open the gbm device from the drm device and create a context based on that
|
// Open the gbm device from the drm device and create a context based on that
|
||||||
dev: Rc::new(RefCell::new(
|
dev: Rc::new(
|
||||||
EGLContext::new(dev, attributes, Default::default(), log.clone()).map_err(Error::from)?,
|
EGLContext::new(dev, attributes, Default::default(), log.clone()).map_err(Error::from)?,
|
||||||
)),
|
),
|
||||||
logger: log,
|
logger: log,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -148,7 +147,6 @@ where
|
||||||
|
|
||||||
let surface = self
|
let surface = self
|
||||||
.dev
|
.dev
|
||||||
.borrow_mut()
|
|
||||||
.create_surface((crtc, mode, Vec::from_iter(connectors)).into())?;
|
.create_surface((crtc, mode, Vec::from_iter(connectors)).into())?;
|
||||||
|
|
||||||
Ok(EglSurface {
|
Ok(EglSurface {
|
||||||
|
@ -182,6 +180,6 @@ where
|
||||||
<D as Device>::Surface: NativeSurface,
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
|
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
|
||||||
self.dev.borrow().bind_wl_display(display)
|
self.dev.bind_wl_display(display)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ where
|
||||||
{
|
{
|
||||||
fn observer(&mut self) -> EglDeviceObserver<S> {
|
fn observer(&mut self) -> EglDeviceObserver<S> {
|
||||||
EglDeviceObserver {
|
EglDeviceObserver {
|
||||||
observer: (**self.dev.borrow_mut()).observer(),
|
observer: self.dev.borrow_mut().observer(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use drm::control::{connector, crtc, Mode};
|
use drm::control::{connector, crtc, Mode};
|
||||||
use nix::libc::c_void;
|
use nix::libc::c_void;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::error::*;
|
use super::error::*;
|
||||||
|
@ -19,7 +18,7 @@ pub struct EglSurface<
|
||||||
> where
|
> where
|
||||||
<D as Device>::Surface: NativeSurface,
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
pub(super) dev: Rc<RefCell<EGLContext<B, D>>>,
|
pub(super) dev: Rc<EGLContext<B, D>>,
|
||||||
pub(super) surface: EGLSurface<B::Surface>,
|
pub(super) surface: EGLSurface<B::Surface>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +104,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
|
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
|
||||||
self.dev.borrow().get_proc_address(symbol)
|
self.dev.get_proc_address(symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_framebuffer_dimensions(&self) -> (u32, u32) {
|
fn get_framebuffer_dimensions(&self) -> (u32, u32) {
|
||||||
|
@ -114,7 +113,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_current(&self) -> bool {
|
fn is_current(&self) -> bool {
|
||||||
self.dev.borrow().is_current() && self.surface.is_current()
|
self.dev.is_current() && self.surface.is_current()
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError> {
|
unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError> {
|
||||||
|
@ -122,6 +121,6 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pixel_format(&self) -> PixelFormat {
|
fn get_pixel_format(&self) -> PixelFormat {
|
||||||
self.dev.borrow().get_pixel_format()
|
self.dev.get_pixel_format()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,16 +73,17 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
|
||||||
};
|
};
|
||||||
self.next_buffer.set(Some(next_bo));
|
self.next_buffer.set(Some(next_bo));
|
||||||
|
|
||||||
trace!(self.logger, "Queueing Page flip");
|
|
||||||
if self.recreated.get() {
|
if self.recreated.get() {
|
||||||
|
debug!(self.logger, "Commiting new state");
|
||||||
self.crtc
|
self.crtc
|
||||||
.commit(fb.handle())
|
.commit(fb.handle())
|
||||||
.map_err(|_| SwapBuffersError::ContextLost)?;
|
.map_err(|_| SwapBuffersError::ContextLost)?;
|
||||||
self.recreated.set(false);
|
self.recreated.set(false);
|
||||||
} else {
|
|
||||||
self.crtc.page_flip(fb.handle())?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace!(self.logger, "Queueing Page flip");
|
||||||
|
self.crtc.page_flip(fb.handle())?;
|
||||||
|
|
||||||
self.current_frame_buffer.set(Some(fb));
|
self.current_frame_buffer.set(Some(fb));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -5,17 +5,16 @@ use backend::graphics::PixelFormat;
|
||||||
use nix::libc::{c_int, c_void};
|
use nix::libc::{c_int, c_void};
|
||||||
use slog;
|
use slog;
|
||||||
use std::{
|
use std::{
|
||||||
|
cell::{Ref, RefCell, RefMut},
|
||||||
ffi::{CStr, CString},
|
ffi::{CStr, CString},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
mem,
|
mem, ptr,
|
||||||
ops::{Deref, DerefMut},
|
|
||||||
ptr,
|
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 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>> {
|
||||||
native: N,
|
native: RefCell<N>,
|
||||||
pub(crate) context: Rc<ffi::egl::types::EGLContext>,
|
pub(crate) context: Rc<ffi::egl::types::EGLContext>,
|
||||||
pub(crate) display: Rc<ffi::egl::types::EGLDisplay>,
|
pub(crate) display: Rc<ffi::egl::types::EGLDisplay>,
|
||||||
pub(crate) config_id: ffi::egl::types::EGLConfig,
|
pub(crate) config_id: ffi::egl::types::EGLConfig,
|
||||||
|
@ -26,19 +25,6 @@ pub struct EGLContext<B: native::Backend, N: native::NativeDisplay<B>> {
|
||||||
_backend: PhantomData<B>,
|
_backend: PhantomData<B>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: native::Backend, N: native::NativeDisplay<B>> Deref for EGLContext<B, N> {
|
|
||||||
type Target = N;
|
|
||||||
fn deref(&self) -> &N {
|
|
||||||
&self.native
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<B: native::Backend, N: native::NativeDisplay<B>> DerefMut for EGLContext<B, N> {
|
|
||||||
fn deref_mut(&mut self) -> &mut N {
|
|
||||||
&mut self.native
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
/// Create a new `EGLContext` from a given `NativeDisplay`
|
/// Create a new `EGLContext` from a given `NativeDisplay`
|
||||||
pub fn new<L>(
|
pub fn new<L>(
|
||||||
|
@ -56,7 +42,7 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
unsafe { EGLContext::<B, N>::new_internal(ptr, attributes, reqs, log.clone()) }?;
|
unsafe { EGLContext::<B, N>::new_internal(ptr, attributes, reqs, log.clone()) }?;
|
||||||
|
|
||||||
Ok(EGLContext {
|
Ok(EGLContext {
|
||||||
native,
|
native: RefCell::new(native),
|
||||||
context,
|
context,
|
||||||
display,
|
display,
|
||||||
config_id,
|
config_id,
|
||||||
|
@ -429,10 +415,11 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a surface for rendering
|
/// Creates a surface for rendering
|
||||||
pub fn create_surface(&mut self, args: N::Arguments) -> Result<EGLSurface<B::Surface>> {
|
pub fn create_surface(&self, args: N::Arguments) -> Result<EGLSurface<B::Surface>> {
|
||||||
trace!(self.logger, "Creating EGL window surface.");
|
trace!(self.logger, "Creating EGL window surface.");
|
||||||
let surface = self
|
let surface = self
|
||||||
.native
|
.native
|
||||||
|
.borrow_mut()
|
||||||
.create_surface(args)
|
.create_surface(args)
|
||||||
.chain_err(|| ErrorKind::SurfaceCreationFailed)?;
|
.chain_err(|| ErrorKind::SurfaceCreationFailed)?;
|
||||||
EGLSurface::new(self, surface).map(|x| {
|
EGLSurface::new(self, surface).map(|x| {
|
||||||
|
@ -459,6 +446,25 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Borrow the underlying native display.
|
||||||
|
///
|
||||||
|
/// This follows the same semantics as `std::cell:RefCell`.
|
||||||
|
/// Multiple read-only borrows are possible. Borrowing the
|
||||||
|
/// backend while there is a mutable reference will panic.
|
||||||
|
pub fn borrow(&self) -> Ref<N> {
|
||||||
|
self.native.borrow()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Borrow the underlying native display mutably.
|
||||||
|
///
|
||||||
|
/// This follows the same semantics as `std::cell:RefCell`.
|
||||||
|
/// Holding any other borrow while trying to borrow the backend
|
||||||
|
/// mutably will panic. Note that EGL will borrow the display
|
||||||
|
/// mutably during surface creation.
|
||||||
|
pub fn borrow_mut(&self) -> RefMut<N> {
|
||||||
|
self.native.borrow_mut()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {}
|
||||||
|
|
|
@ -74,12 +74,11 @@ impl<N: native::NativeSurface> EGLSurface<N> {
|
||||||
err => return Err(SwapBuffersError::Unknown(err)),
|
err => return Err(SwapBuffersError::Unknown(err)),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return Ok(());
|
self.native.swap_buffers()?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(SwapBuffersError::ContextLost);
|
return Err(SwapBuffersError::ContextLost);
|
||||||
}
|
}
|
||||||
self.native.swap_buffers()?;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.native.needs_recreation() || surface.is_null() {
|
if self.native.needs_recreation() || surface.is_null() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use nix::libc::c_void;
|
use nix::libc::c_void;
|
||||||
|
|
||||||
use super::{SwapBuffersError, PixelFormat};
|
use super::{PixelFormat, SwapBuffersError};
|
||||||
|
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy))]
|
#[cfg_attr(feature = "cargo-clippy", allow(clippy))]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
|
|
@ -5,10 +5,7 @@ use backend::{
|
||||||
context::GlAttributes, error as egl_error, error::Result as EGLResult, native, EGLContext,
|
context::GlAttributes, error as egl_error, error::Result as EGLResult, native, EGLContext,
|
||||||
EGLDisplay, EGLGraphicsBackend, EGLSurface,
|
EGLDisplay, EGLGraphicsBackend, EGLSurface,
|
||||||
},
|
},
|
||||||
graphics::{
|
graphics::{gl::GLGraphicsBackend, CursorBackend, PixelFormat, SwapBuffersError},
|
||||||
gl::GLGraphicsBackend,
|
|
||||||
CursorBackend, SwapBuffersError, PixelFormat,
|
|
||||||
},
|
|
||||||
input::{
|
input::{
|
||||||
Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, KeyboardKeyEvent,
|
Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, KeyboardKeyEvent,
|
||||||
MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent,
|
MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent,
|
||||||
|
@ -17,7 +14,12 @@ use backend::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use nix::libc::c_void;
|
use nix::libc::c_void;
|
||||||
use std::{cell::RefCell, cmp, error, fmt, rc::Rc, time::Instant};
|
use std::{
|
||||||
|
cell::{Ref, RefCell},
|
||||||
|
cmp, error, fmt,
|
||||||
|
rc::Rc,
|
||||||
|
time::Instant,
|
||||||
|
};
|
||||||
use wayland_client::egl as wegl;
|
use wayland_client::egl as wegl;
|
||||||
use wayland_server::Display;
|
use wayland_server::Display;
|
||||||
use winit::{
|
use winit::{
|
||||||
|
@ -56,10 +58,10 @@ enum Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
fn window(&self) -> &WinitWindow {
|
fn window(&self) -> Ref<WinitWindow> {
|
||||||
match *self {
|
match *self {
|
||||||
Window::Wayland { ref context, .. } => &**context,
|
Window::Wayland { ref context, .. } => context.borrow(),
|
||||||
Window::X11 { ref context, .. } => &**context,
|
Window::X11 { ref context, .. } => context.borrow(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,7 +220,7 @@ pub trait WinitEventsHandler {
|
||||||
|
|
||||||
impl WinitGraphicsBackend {
|
impl WinitGraphicsBackend {
|
||||||
/// Get a reference to the internally used `winit::Window`
|
/// Get a reference to the internally used `winit::Window`
|
||||||
pub fn winit_window(&self) -> &WinitWindow {
|
pub fn winit_window(&self) -> Ref<WinitWindow> {
|
||||||
self.window.window()
|
self.window.window()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue