Skip to content

Commit

Permalink
Hacky Gbm backend
Browse files Browse the repository at this point in the history
  • Loading branch information
kosyak committed May 17, 2019
1 parent cd5caf6 commit e5ab8e5
Show file tree
Hide file tree
Showing 9 changed files with 1,059 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ rls/
.vscode/
*~
#*#
._.DS_Store
._DS_Store
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,5 @@ smithay-client-toolkit = "0.4.3"
x11-dl = "2.18.3"
parking_lot = "0.7"
percent-encoding = "1.0"
gbm = { git = "https://github.com/kosyak/gbm.rs", default-features = false, features = ["drm-support", "import-egl", "gen"] }
drm = { git = "https://github.com/kosyak/drm-rs", branch = "master" }
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ extern crate parking_lot;
extern crate percent_encoding;
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
extern crate smithay_client_toolkit as sctk;
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
extern crate drm;
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
extern crate gbm;

pub(crate) use dpi::*; // TODO: Actually change the imports throughout the codebase.
pub use events::*;
Expand Down
60 changes: 59 additions & 1 deletion src/os/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ pub trait EventsLoopExt {
/// True if the `EventsLoop` uses X11.
fn is_x11(&self) -> bool;

/// True if the `EventsLoop` uses Gbm.
fn is_gbm(&self) -> bool;

#[doc(hidden)]
fn get_xlib_xconnection(&self) -> Option<Arc<XConnection>>;

Expand All @@ -120,6 +123,8 @@ pub trait EventsLoopExt {
///
/// The pointer will become invalid when the glutin `EventsLoop` is destroyed.
fn get_wayland_display(&self) -> Option<*mut raw::c_void>;

fn get_gbm_display(&self) -> Option<*mut raw::c_void>;
}

impl EventsLoopExt for EventsLoop {
Expand Down Expand Up @@ -151,7 +156,12 @@ impl EventsLoopExt for EventsLoop {

#[inline]
fn is_x11(&self) -> bool {
!self.events_loop.is_wayland()
!self.events_loop.is_wayland() && !self.events_loop.is_gbm()
}

#[inline]
fn is_gbm(&self) -> bool {
self.events_loop.is_gbm()
}

#[inline]
Expand All @@ -167,6 +177,15 @@ impl EventsLoopExt for EventsLoop {
_ => None
}
}

#[inline]
fn get_gbm_display(&self) -> Option<*mut raw::c_void> {
use gbm::AsRaw;
match self.events_loop {
LinuxEventsLoop::Gbm(ref e) => Some(e.get_display().as_raw() as *mut _),
_ => None
}
}
}

/// Additional methods on `Window` that are specific to Unix.
Expand Down Expand Up @@ -205,13 +224,20 @@ pub trait WindowExt {
/// The pointer will become invalid when the glutin `Window` is destroyed.
fn get_wayland_surface(&self) -> Option<*mut raw::c_void>;

fn get_gbm_surface(&self) -> Option<*mut raw::c_void>;

/// Returns a pointer to the `wl_display` object of wayland that is used by this window.
///
/// Returns `None` if the window doesn't use wayland (if it uses xlib for example).
///
/// The pointer will become invalid when the glutin `Window` is destroyed.
fn get_wayland_display(&self) -> Option<*mut raw::c_void>;

fn get_gbm_display(&self) -> Option<*mut raw::c_void>;

fn gbm_set_crtc(&self);
fn gbm_page_flip(&self);

/// Sets the color theme of the client side window decorations on wayland
fn set_wayland_theme(&self, theme: WaylandTheme);

Expand Down Expand Up @@ -282,6 +308,15 @@ impl WindowExt for Window {
}
}

#[inline]
fn get_gbm_surface(&self) -> Option<*mut raw::c_void> {
use gbm::AsRaw;
match self.window {
LinuxWindow::Gbm(ref w) => Some(w.get_surface().as_raw() as *mut _),
_ => None
}
}

#[inline]
fn get_wayland_display(&self) -> Option<*mut raw::c_void> {
match self.window {
Expand All @@ -290,6 +325,29 @@ impl WindowExt for Window {
}
}

#[inline]
fn get_gbm_display(&self) -> Option<*mut raw::c_void> {
use gbm::AsRaw;
match self.window {
LinuxWindow::Gbm(ref w) => Some(w.get_display().as_raw() as *mut _),
_ => None
}
}

fn gbm_set_crtc(&self) {
match self.window {
LinuxWindow::Gbm(ref w) => w.set_crtc(),
_ => {}
}
}

fn gbm_page_flip(&self) {
match self.window {
LinuxWindow::Gbm(ref w) => w.page_flip(),
_ => {}
}
}

#[inline]
fn set_wayland_theme(&self, theme: WaylandTheme) {
match self.window {
Expand Down
80 changes: 80 additions & 0 deletions src/platform/linux/gbm/card.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use drm::control::{Device as ControlDevice, connector::Info as ConnectorInfo, Mode, ResourceInfo,
encoder::Info as EncoderInfo, crtc::Info as CrtcInfo};

use std::fs::{File, OpenOptions};
use std::os::unix::io::{AsRawFd, RawFd};

#[derive(Debug)]
// This is our customized struct that implements the traits in drm.
pub struct Card(File);

// Need to implement AsRawFd before we can implement drm::Device
impl AsRawFd for Card {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}

impl drm::Device for Card {}
impl ControlDevice for Card {}

impl Card {
pub fn open(path: &str) -> Self {
let mut options = OpenOptions::new();
options.read(true);
options.write(true);
Card(options.open(path).unwrap())
}

pub fn open_global() -> Self {
Self::open("/dev/dri/card0")
}

// fn open_control() -> Self {
// Self::open("/dev/dri/controlD64")
// }

pub fn try_clone(&self) -> std::io::Result<Self> {
let file = self.0.try_clone()?;
Ok(Card(file))
}

pub fn get_resources(&self) -> (ConnectorInfo, Mode, EncoderInfo, CrtcInfo) {
let resources = self.resource_handles().unwrap();

let connector = resources.connectors().iter().find_map(|&c| {
if let Ok(c) = ConnectorInfo::load_from_device(self, c) {
if c.connection_state() == drm::control::connector::State::Connected &&
c.size().0 > 0 && c.size().1 > 0
{
return Some(c);
}
}

None
}).unwrap();

let connector_clone = connector.clone();
let modes = connector_clone.modes();
let modes = &mut modes.to_owned();
modes.sort_by(|a, b| {
/*if a.is_preferred() != b.is_preferred() {
a.is_preferred().cmp(&b.is_preferred()).reverse()
} else*/ if a.size().0 as u32 * a.size().1 as u32 != b.size().0 as u32 * b.size().1 as u32 {
(a.size().0 as u32 * a.size().1 as u32).cmp(&(b.size().0 as u32 * b.size().1 as u32)).reverse()
} else {
a.vrefresh().cmp(&b.vrefresh()).reverse()
}
});

let mode = modes.iter().next().unwrap();

let encoder =
EncoderInfo::load_from_device(self, connector.current_encoder().unwrap()).unwrap();

let ctrc_handle = encoder.current_crtc().unwrap();
let crtc = CrtcInfo::load_from_device(self, ctrc_handle).unwrap();

(connector, *mode, encoder, crtc)
}
}
Loading

0 comments on commit e5ab8e5

Please sign in to comment.