mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-04-10 15:41:28 +03:00
linux x11 rgb565 capture (#8580)
Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
@@ -17,7 +17,7 @@ impl Capturer {
|
||||
pub fn new(display: Display) -> io::Result<Capturer> {
|
||||
// Calculate dimensions.
|
||||
|
||||
let pixel_width = 4;
|
||||
let pixel_width = display.pixfmt().bytes_per_pixel();
|
||||
let rect = display.rect();
|
||||
let size = (rect.w as usize) * (rect.h as usize) * pixel_width;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ use std::rc::Rc;
|
||||
|
||||
use super::ffi::*;
|
||||
use super::Server;
|
||||
use crate::Pixfmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Display {
|
||||
@@ -10,6 +11,7 @@ pub struct Display {
|
||||
rect: Rect,
|
||||
root: xcb_window_t,
|
||||
name: String,
|
||||
pixfmt: Pixfmt,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
@@ -27,6 +29,7 @@ impl Display {
|
||||
rect: Rect,
|
||||
root: xcb_window_t,
|
||||
name: String,
|
||||
pixfmt: Pixfmt,
|
||||
) -> Display {
|
||||
Display {
|
||||
server,
|
||||
@@ -34,6 +37,7 @@ impl Display {
|
||||
rect,
|
||||
root,
|
||||
name,
|
||||
pixfmt,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,4 +63,8 @@ impl Display {
|
||||
pub fn name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
pub fn pixfmt(&self) -> Pixfmt {
|
||||
self.pixfmt
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,12 +82,24 @@ extern "C" {
|
||||
pub fn xcb_get_atom_name_name_length(reply: *const xcb_get_atom_name_reply_t) -> i32;
|
||||
|
||||
pub fn xcb_shm_query_version(c: *mut xcb_connection_t) -> xcb_shm_query_version_cookie_t;
|
||||
|
||||
|
||||
pub fn xcb_shm_query_version_reply(
|
||||
c: *mut xcb_connection_t,
|
||||
cookie: xcb_shm_query_version_cookie_t,
|
||||
e: *mut *mut xcb_generic_error_t,
|
||||
) -> *const xcb_shm_query_version_reply_t;
|
||||
|
||||
pub fn xcb_get_geometry_unchecked(
|
||||
c: *mut xcb_connection_t,
|
||||
drawable: xcb_drawable_t,
|
||||
) -> xcb_get_geometry_cookie_t;
|
||||
|
||||
pub fn xcb_get_geometry_reply(
|
||||
c: *mut xcb_connection_t,
|
||||
cookie: xcb_get_geometry_cookie_t,
|
||||
e: *mut *mut xcb_generic_error_t,
|
||||
) -> *mut xcb_get_geometry_reply_t;
|
||||
|
||||
}
|
||||
|
||||
pub const XCB_IMAGE_FORMAT_Z_PIXMAP: u8 = 2;
|
||||
@@ -195,6 +207,12 @@ pub struct xcb_void_cookie_t {
|
||||
pub sequence: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct xcb_get_geometry_cookie_t {
|
||||
pub sequence: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct xcb_generic_error_t {
|
||||
pub response_type: u8,
|
||||
@@ -248,3 +266,18 @@ pub struct xcb_shm_query_version_reply_t {
|
||||
pub pixmap_format: u8,
|
||||
pub pad0: [u8; 15],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct xcb_get_geometry_reply_t {
|
||||
pub response_type: u8,
|
||||
pub depth: u8,
|
||||
pub sequence: u16,
|
||||
pub length: u32,
|
||||
pub root: xcb_window_t,
|
||||
pub x: i16,
|
||||
pub y: i16,
|
||||
pub width: u16,
|
||||
pub height: u16,
|
||||
pub border_width: u16,
|
||||
pub pad0: [u8; 2],
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use std::ffi::CString;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::Pixfmt;
|
||||
use hbb_common::libc;
|
||||
|
||||
use super::ffi::*;
|
||||
@@ -66,7 +67,7 @@ impl Iterator for DisplayIter {
|
||||
unsafe {
|
||||
let data = &*inner.data;
|
||||
let name = get_atom_name(self.server.raw(), data.name);
|
||||
|
||||
let pixfmt = get_pixfmt(self.server.raw(), root).unwrap_or(Pixfmt::BGRA);
|
||||
let display = Display::new(
|
||||
self.server.clone(),
|
||||
data.primary != 0,
|
||||
@@ -78,6 +79,7 @@ impl Iterator for DisplayIter {
|
||||
},
|
||||
root,
|
||||
name,
|
||||
pixfmt,
|
||||
);
|
||||
|
||||
xcb_randr_monitor_info_next(inner);
|
||||
@@ -102,11 +104,7 @@ fn get_atom_name(conn: *mut xcb_connection_t, atom: xcb_atom_t) -> String {
|
||||
}
|
||||
unsafe {
|
||||
let mut e: *mut xcb_generic_error_t = std::ptr::null_mut();
|
||||
let reply = xcb_get_atom_name_reply(
|
||||
conn,
|
||||
xcb_get_atom_name(conn, atom),
|
||||
&mut e as _,
|
||||
);
|
||||
let reply = xcb_get_atom_name_reply(conn, xcb_get_atom_name(conn, atom), &mut e as _);
|
||||
if reply == std::ptr::null() {
|
||||
return empty;
|
||||
}
|
||||
@@ -121,3 +119,20 @@ fn get_atom_name(conn: *mut xcb_connection_t, atom: xcb_atom_t) -> String {
|
||||
empty
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn get_pixfmt(conn: *mut xcb_connection_t, root: xcb_window_t) -> Option<Pixfmt> {
|
||||
let geo_cookie = xcb_get_geometry_unchecked(conn, root);
|
||||
let geo = xcb_get_geometry_reply(conn, geo_cookie, ptr::null_mut());
|
||||
if geo.is_null() {
|
||||
return None;
|
||||
}
|
||||
let depth = (*geo).depth;
|
||||
libc::free(geo as _);
|
||||
// now only support little endian
|
||||
// https://github.com/FFmpeg/FFmpeg/blob/a9c05eb657d0d05f3ac79fe9973581a41b265a5e/libavdevice/xcbgrab.c#L519
|
||||
match depth {
|
||||
16 => Some(Pixfmt::RGB565LE),
|
||||
32 => Some(Pixfmt::BGRA),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user