style: adjust clang-format rules (#2186)
Co-authored-by: Vithorio Polten <reach@vithor.io>
This commit is contained in:
@@ -2,61 +2,49 @@
|
||||
* @file src/platform/linux/x11grab.cpp
|
||||
* @brief Definitions for x11 capture.
|
||||
*/
|
||||
#include "src/platform/common.h"
|
||||
|
||||
// standard includes
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
|
||||
// plaform includes
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xcb/shm.h>
|
||||
#include <xcb/xfixes.h>
|
||||
|
||||
#include "src/config.h"
|
||||
#include "src/globals.h"
|
||||
#include "src/logging.h"
|
||||
#include "src/task_pool.h"
|
||||
#include "src/video.h"
|
||||
|
||||
// local includes
|
||||
#include "cuda.h"
|
||||
#include "graphics.h"
|
||||
#include "misc.h"
|
||||
#include "src/config.h"
|
||||
#include "src/globals.h"
|
||||
#include "src/logging.h"
|
||||
#include "src/platform/common.h"
|
||||
#include "src/task_pool.h"
|
||||
#include "src/video.h"
|
||||
#include "vaapi.h"
|
||||
#include "x11grab.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
namespace platf {
|
||||
int
|
||||
load_xcb();
|
||||
int
|
||||
load_x11();
|
||||
int load_xcb();
|
||||
int load_x11();
|
||||
|
||||
namespace x11 {
|
||||
#define _FN(x, ret, args) \
|
||||
#define _FN(x, ret, args) \
|
||||
typedef ret(*x##_fn) args; \
|
||||
static x##_fn x
|
||||
|
||||
_FN(GetImage, XImage *,
|
||||
(
|
||||
Display * display,
|
||||
Drawable d,
|
||||
int x, int y,
|
||||
unsigned int width, unsigned int height,
|
||||
unsigned long plane_mask,
|
||||
int format));
|
||||
_FN(GetImage, XImage *, (Display * display, Drawable d, int x, int y, unsigned int width, unsigned int height, unsigned long plane_mask, int format));
|
||||
|
||||
_FN(OpenDisplay, Display *, (_Xconst char *display_name));
|
||||
_FN(GetWindowAttributes, Status,
|
||||
(
|
||||
Display * display,
|
||||
Window w,
|
||||
XWindowAttributes *window_attributes_return));
|
||||
_FN(GetWindowAttributes, Status, (Display * display, Window w, XWindowAttributes *window_attributes_return));
|
||||
|
||||
_FN(CloseDisplay, int, (Display * display));
|
||||
_FN(Free, int, (void *data));
|
||||
@@ -70,27 +58,28 @@ namespace platf {
|
||||
_FN(FreeOutputInfo, void, (XRROutputInfo * outputInfo));
|
||||
_FN(FreeCrtcInfo, void, (XRRCrtcInfo * crtcInfo));
|
||||
|
||||
static int
|
||||
init() {
|
||||
static void *handle { nullptr };
|
||||
static int init() {
|
||||
static void *handle {nullptr};
|
||||
static bool funcs_loaded = false;
|
||||
|
||||
if (funcs_loaded) return 0;
|
||||
if (funcs_loaded) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!handle) {
|
||||
handle = dyn::handle({ "libXrandr.so.2", "libXrandr.so" });
|
||||
handle = dyn::handle({"libXrandr.so.2", "libXrandr.so"});
|
||||
if (!handle) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::tuple<dyn::apiproc *, const char *>> funcs {
|
||||
{ (dyn::apiproc *) &GetScreenResources, "XRRGetScreenResources" },
|
||||
{ (dyn::apiproc *) &GetOutputInfo, "XRRGetOutputInfo" },
|
||||
{ (dyn::apiproc *) &GetCrtcInfo, "XRRGetCrtcInfo" },
|
||||
{ (dyn::apiproc *) &FreeScreenResources, "XRRFreeScreenResources" },
|
||||
{ (dyn::apiproc *) &FreeOutputInfo, "XRRFreeOutputInfo" },
|
||||
{ (dyn::apiproc *) &FreeCrtcInfo, "XRRFreeCrtcInfo" },
|
||||
{(dyn::apiproc *) &GetScreenResources, "XRRGetScreenResources"},
|
||||
{(dyn::apiproc *) &GetOutputInfo, "XRRGetOutputInfo"},
|
||||
{(dyn::apiproc *) &GetCrtcInfo, "XRRGetCrtcInfo"},
|
||||
{(dyn::apiproc *) &FreeScreenResources, "XRRFreeScreenResources"},
|
||||
{(dyn::apiproc *) &FreeOutputInfo, "XRRFreeOutputInfo"},
|
||||
{(dyn::apiproc *) &FreeCrtcInfo, "XRRFreeCrtcInfo"},
|
||||
};
|
||||
|
||||
if (dyn::load(handle, funcs)) {
|
||||
@@ -102,25 +91,27 @@ namespace platf {
|
||||
}
|
||||
|
||||
} // namespace rr
|
||||
|
||||
namespace fix {
|
||||
_FN(GetCursorImage, XFixesCursorImage *, (Display * dpy));
|
||||
|
||||
static int
|
||||
init() {
|
||||
static void *handle { nullptr };
|
||||
static int init() {
|
||||
static void *handle {nullptr};
|
||||
static bool funcs_loaded = false;
|
||||
|
||||
if (funcs_loaded) return 0;
|
||||
if (funcs_loaded) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!handle) {
|
||||
handle = dyn::handle({ "libXfixes.so.3", "libXfixes.so" });
|
||||
handle = dyn::handle({"libXfixes.so.3", "libXfixes.so"});
|
||||
if (!handle) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::tuple<dyn::apiproc *, const char *>> funcs {
|
||||
{ (dyn::apiproc *) &GetCursorImage, "XFixesGetCursorImage" },
|
||||
{(dyn::apiproc *) &GetCursorImage, "XFixesGetCursorImage"},
|
||||
};
|
||||
|
||||
if (dyn::load(handle, funcs)) {
|
||||
@@ -132,27 +123,28 @@ namespace platf {
|
||||
}
|
||||
} // namespace fix
|
||||
|
||||
static int
|
||||
init() {
|
||||
static void *handle { nullptr };
|
||||
static int init() {
|
||||
static void *handle {nullptr};
|
||||
static bool funcs_loaded = false;
|
||||
|
||||
if (funcs_loaded) return 0;
|
||||
if (funcs_loaded) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!handle) {
|
||||
handle = dyn::handle({ "libX11.so.6", "libX11.so" });
|
||||
handle = dyn::handle({"libX11.so.6", "libX11.so"});
|
||||
if (!handle) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::tuple<dyn::apiproc *, const char *>> funcs {
|
||||
{ (dyn::apiproc *) &GetImage, "XGetImage" },
|
||||
{ (dyn::apiproc *) &OpenDisplay, "XOpenDisplay" },
|
||||
{ (dyn::apiproc *) &GetWindowAttributes, "XGetWindowAttributes" },
|
||||
{ (dyn::apiproc *) &Free, "XFree" },
|
||||
{ (dyn::apiproc *) &CloseDisplay, "XCloseDisplay" },
|
||||
{ (dyn::apiproc *) &InitThreads, "XInitThreads" },
|
||||
{(dyn::apiproc *) &GetImage, "XGetImage"},
|
||||
{(dyn::apiproc *) &OpenDisplay, "XOpenDisplay"},
|
||||
{(dyn::apiproc *) &GetWindowAttributes, "XGetWindowAttributes"},
|
||||
{(dyn::apiproc *) &Free, "XFree"},
|
||||
{(dyn::apiproc *) &CloseDisplay, "XCloseDisplay"},
|
||||
{(dyn::apiproc *) &InitThreads, "XInitThreads"},
|
||||
};
|
||||
|
||||
if (dyn::load(handle, funcs)) {
|
||||
@@ -167,31 +159,13 @@ namespace platf {
|
||||
namespace xcb {
|
||||
static xcb_extension_t *shm_id;
|
||||
|
||||
_FN(shm_get_image_reply, xcb_shm_get_image_reply_t *,
|
||||
(
|
||||
xcb_connection_t * c,
|
||||
xcb_shm_get_image_cookie_t cookie,
|
||||
xcb_generic_error_t **e));
|
||||
_FN(shm_get_image_reply, xcb_shm_get_image_reply_t *, (xcb_connection_t * c, xcb_shm_get_image_cookie_t cookie, xcb_generic_error_t **e));
|
||||
|
||||
_FN(shm_get_image_unchecked, xcb_shm_get_image_cookie_t,
|
||||
(
|
||||
xcb_connection_t * c,
|
||||
xcb_drawable_t drawable,
|
||||
int16_t x, int16_t y,
|
||||
uint16_t width, uint16_t height,
|
||||
uint32_t plane_mask,
|
||||
uint8_t format,
|
||||
xcb_shm_seg_t shmseg,
|
||||
uint32_t offset));
|
||||
_FN(shm_get_image_unchecked, xcb_shm_get_image_cookie_t, (xcb_connection_t * c, xcb_drawable_t drawable, int16_t x, int16_t y, uint16_t width, uint16_t height, uint32_t plane_mask, uint8_t format, xcb_shm_seg_t shmseg, uint32_t offset));
|
||||
|
||||
_FN(shm_attach, xcb_void_cookie_t,
|
||||
(xcb_connection_t * c,
|
||||
xcb_shm_seg_t shmseg,
|
||||
uint32_t shmid,
|
||||
uint8_t read_only));
|
||||
_FN(shm_attach, xcb_void_cookie_t, (xcb_connection_t * c, xcb_shm_seg_t shmseg, uint32_t shmid, uint8_t read_only));
|
||||
|
||||
_FN(get_extension_data, xcb_query_extension_reply_t *,
|
||||
(xcb_connection_t * c, xcb_extension_t *ext));
|
||||
_FN(get_extension_data, xcb_query_extension_reply_t *, (xcb_connection_t * c, xcb_extension_t *ext));
|
||||
|
||||
_FN(get_setup, xcb_setup_t *, (xcb_connection_t * c));
|
||||
_FN(disconnect, void, (xcb_connection_t * c));
|
||||
@@ -200,25 +174,26 @@ namespace platf {
|
||||
_FN(setup_roots_iterator, xcb_screen_iterator_t, (const xcb_setup_t *R));
|
||||
_FN(generate_id, std::uint32_t, (xcb_connection_t * c));
|
||||
|
||||
int
|
||||
init_shm() {
|
||||
static void *handle { nullptr };
|
||||
int init_shm() {
|
||||
static void *handle {nullptr};
|
||||
static bool funcs_loaded = false;
|
||||
|
||||
if (funcs_loaded) return 0;
|
||||
if (funcs_loaded) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!handle) {
|
||||
handle = dyn::handle({ "libxcb-shm.so.0", "libxcb-shm.so" });
|
||||
handle = dyn::handle({"libxcb-shm.so.0", "libxcb-shm.so"});
|
||||
if (!handle) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::tuple<dyn::apiproc *, const char *>> funcs {
|
||||
{ (dyn::apiproc *) &shm_id, "xcb_shm_id" },
|
||||
{ (dyn::apiproc *) &shm_get_image_reply, "xcb_shm_get_image_reply" },
|
||||
{ (dyn::apiproc *) &shm_get_image_unchecked, "xcb_shm_get_image_unchecked" },
|
||||
{ (dyn::apiproc *) &shm_attach, "xcb_shm_attach" },
|
||||
{(dyn::apiproc *) &shm_id, "xcb_shm_id"},
|
||||
{(dyn::apiproc *) &shm_get_image_reply, "xcb_shm_get_image_reply"},
|
||||
{(dyn::apiproc *) &shm_get_image_unchecked, "xcb_shm_get_image_unchecked"},
|
||||
{(dyn::apiproc *) &shm_attach, "xcb_shm_attach"},
|
||||
};
|
||||
|
||||
if (dyn::load(handle, funcs)) {
|
||||
@@ -229,28 +204,29 @@ namespace platf {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
init() {
|
||||
static void *handle { nullptr };
|
||||
int init() {
|
||||
static void *handle {nullptr};
|
||||
static bool funcs_loaded = false;
|
||||
|
||||
if (funcs_loaded) return 0;
|
||||
if (funcs_loaded) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!handle) {
|
||||
handle = dyn::handle({ "libxcb.so.1", "libxcb.so" });
|
||||
handle = dyn::handle({"libxcb.so.1", "libxcb.so"});
|
||||
if (!handle) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::tuple<dyn::apiproc *, const char *>> funcs {
|
||||
{ (dyn::apiproc *) &get_extension_data, "xcb_get_extension_data" },
|
||||
{ (dyn::apiproc *) &get_setup, "xcb_get_setup" },
|
||||
{ (dyn::apiproc *) &disconnect, "xcb_disconnect" },
|
||||
{ (dyn::apiproc *) &connection_has_error, "xcb_connection_has_error" },
|
||||
{ (dyn::apiproc *) &connect, "xcb_connect" },
|
||||
{ (dyn::apiproc *) &setup_roots_iterator, "xcb_setup_roots_iterator" },
|
||||
{ (dyn::apiproc *) &generate_id, "xcb_generate_id" },
|
||||
{(dyn::apiproc *) &get_extension_data, "xcb_get_extension_data"},
|
||||
{(dyn::apiproc *) &get_setup, "xcb_get_setup"},
|
||||
{(dyn::apiproc *) &disconnect, "xcb_disconnect"},
|
||||
{(dyn::apiproc *) &connection_has_error, "xcb_connection_has_error"},
|
||||
{(dyn::apiproc *) &connect, "xcb_connect"},
|
||||
{(dyn::apiproc *) &setup_roots_iterator, "xcb_setup_roots_iterator"},
|
||||
{(dyn::apiproc *) &generate_id, "xcb_generate_id"},
|
||||
};
|
||||
|
||||
if (dyn::load(handle, funcs)) {
|
||||
@@ -264,10 +240,8 @@ namespace platf {
|
||||
#undef _FN
|
||||
} // namespace xcb
|
||||
|
||||
void
|
||||
freeImage(XImage *);
|
||||
void
|
||||
freeX(XFixesCursorImage *);
|
||||
void freeImage(XImage *);
|
||||
void freeX(XFixesCursorImage *);
|
||||
|
||||
using xcb_connect_t = util::dyn_safe_ptr<xcb_connection_t, &xcb::disconnect>;
|
||||
using xcb_img_t = util::c_ptr<xcb_shm_get_image_reply_t>;
|
||||
@@ -282,9 +256,13 @@ namespace platf {
|
||||
class shm_id_t {
|
||||
public:
|
||||
shm_id_t():
|
||||
id { -1 } {}
|
||||
id {-1} {
|
||||
}
|
||||
|
||||
shm_id_t(int id):
|
||||
id { id } {}
|
||||
id {id} {
|
||||
}
|
||||
|
||||
shm_id_t(shm_id_t &&other) noexcept:
|
||||
id(other.id) {
|
||||
other.id = -1;
|
||||
@@ -296,15 +274,19 @@ namespace platf {
|
||||
id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int id;
|
||||
};
|
||||
|
||||
class shm_data_t {
|
||||
public:
|
||||
shm_data_t():
|
||||
data { (void *) -1 } {}
|
||||
data {(void *) -1} {
|
||||
}
|
||||
|
||||
shm_data_t(void *data):
|
||||
data { data } {}
|
||||
data {data} {
|
||||
}
|
||||
|
||||
shm_data_t(shm_data_t &&other) noexcept:
|
||||
data(other.data) {
|
||||
@@ -331,9 +313,8 @@ namespace platf {
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
blend_cursor(Display *display, img_t &img, int offsetX, int offsetY) {
|
||||
xcursor_t overlay { x11::fix::GetCursorImage(display) };
|
||||
static void blend_cursor(Display *display, img_t &img, int offsetX, int offsetY) {
|
||||
xcursor_t overlay {x11::fix::GetCursorImage(display)};
|
||||
|
||||
if (!overlay) {
|
||||
BOOST_LOG(error) << "Couldn't get cursor from XFixesGetCursorImage"sv;
|
||||
@@ -370,8 +351,7 @@ namespace platf {
|
||||
auto alpha = (*(uint *) pixel_p) >> 24u;
|
||||
if (alpha == 255) {
|
||||
*pixels_begin = *pixel_p;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
auto colors_out = (uint8_t *) pixel_p;
|
||||
colors_in[0] = colors_out[0] + (colors_in[0] * (255 - alpha) + 255 / 2) / 255;
|
||||
colors_in[1] = colors_out[1] + (colors_in[1] * (255 - alpha) + 255 / 2) / 255;
|
||||
@@ -398,18 +378,20 @@ namespace platf {
|
||||
// int env_width, env_height;
|
||||
|
||||
x11_attr_t(mem_type_e mem_type):
|
||||
xdisplay { x11::OpenDisplay(nullptr) }, xwindow {}, xattr {}, mem_type { mem_type } {
|
||||
xdisplay {x11::OpenDisplay(nullptr)},
|
||||
xwindow {},
|
||||
xattr {},
|
||||
mem_type {mem_type} {
|
||||
x11::InitThreads();
|
||||
}
|
||||
|
||||
int
|
||||
init(const std::string &display_name, const ::video::config_t &config) {
|
||||
int init(const std::string &display_name, const ::video::config_t &config) {
|
||||
if (!xdisplay) {
|
||||
BOOST_LOG(error) << "Could not open X11 display"sv;
|
||||
return -1;
|
||||
}
|
||||
|
||||
delay = std::chrono::nanoseconds { 1s } / config.framerate;
|
||||
delay = std::chrono::nanoseconds {1s} / config.framerate;
|
||||
|
||||
xwindow = DefaultRootWindow(xdisplay.get());
|
||||
|
||||
@@ -422,13 +404,13 @@ namespace platf {
|
||||
|
||||
if (streamedMonitor != -1) {
|
||||
BOOST_LOG(info) << "Configuring selected display ("sv << streamedMonitor << ") to stream"sv;
|
||||
screen_res_t screenr { x11::rr::GetScreenResources(xdisplay.get(), xwindow) };
|
||||
screen_res_t screenr {x11::rr::GetScreenResources(xdisplay.get(), xwindow)};
|
||||
int output = screenr->noutput;
|
||||
|
||||
output_info_t result;
|
||||
int monitor = 0;
|
||||
for (int x = 0; x < output; ++x) {
|
||||
output_info_t out_info { x11::rr::GetOutputInfo(xdisplay.get(), screenr.get(), screenr->outputs[x]) };
|
||||
output_info_t out_info {x11::rr::GetOutputInfo(xdisplay.get(), screenr.get(), screenr->outputs[x])};
|
||||
if (out_info) {
|
||||
if (monitor++ == streamedMonitor) {
|
||||
result = std::move(out_info);
|
||||
@@ -443,7 +425,7 @@ namespace platf {
|
||||
}
|
||||
|
||||
if (result->crtc) {
|
||||
crtc_info_t crt_info { x11::rr::GetCrtcInfo(xdisplay.get(), screenr.get(), result->crtc) };
|
||||
crtc_info_t crt_info {x11::rr::GetCrtcInfo(xdisplay.get(), screenr.get(), result->crtc)};
|
||||
BOOST_LOG(info)
|
||||
<< "Streaming display: "sv << result->name << " with res "sv << crt_info->width << 'x' << crt_info->height << " offset by "sv << crt_info->x << 'x' << crt_info->y;
|
||||
|
||||
@@ -451,14 +433,12 @@ namespace platf {
|
||||
height = crt_info->height;
|
||||
offset_x = crt_info->x;
|
||||
offset_y = crt_info->y;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
BOOST_LOG(warning) << "Couldn't get requested display info, defaulting to recording entire virtual desktop"sv;
|
||||
width = xattr.width;
|
||||
height = xattr.height;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
width = xattr.width;
|
||||
height = xattr.height;
|
||||
}
|
||||
@@ -472,13 +452,11 @@ namespace platf {
|
||||
/**
|
||||
* Called when the display attributes should change.
|
||||
*/
|
||||
void
|
||||
refresh() {
|
||||
void refresh() {
|
||||
x11::GetWindowAttributes(xdisplay.get(), xwindow, &xattr); // Update xattr's
|
||||
}
|
||||
|
||||
capture_e
|
||||
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
||||
capture_e capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
||||
auto next_frame = std::chrono::steady_clock::now();
|
||||
|
||||
sleep_overshoot_logger.reset();
|
||||
@@ -523,8 +501,7 @@ namespace platf {
|
||||
return capture_e::ok;
|
||||
}
|
||||
|
||||
capture_e
|
||||
snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor) {
|
||||
capture_e snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor) {
|
||||
refresh();
|
||||
|
||||
// The whole X server changed, so we must reinit everything
|
||||
@@ -538,7 +515,7 @@ namespace platf {
|
||||
}
|
||||
auto img = (x11_img_t *) img_out.get();
|
||||
|
||||
XImage *x_img { x11::GetImage(xdisplay.get(), xwindow, offset_x, offset_y, width, height, AllPlanes, ZPixmap) };
|
||||
XImage *x_img {x11::GetImage(xdisplay.get(), xwindow, offset_x, offset_y, width, height, AllPlanes, ZPixmap)};
|
||||
img->frame_timestamp = std::chrono::steady_clock::now();
|
||||
|
||||
img->width = x_img->width;
|
||||
@@ -555,13 +532,11 @@ namespace platf {
|
||||
return capture_e::ok;
|
||||
}
|
||||
|
||||
std::shared_ptr<img_t>
|
||||
alloc_img() override {
|
||||
std::shared_ptr<img_t> alloc_img() override {
|
||||
return std::make_shared<x11_img_t>();
|
||||
}
|
||||
|
||||
std::unique_ptr<avcodec_encode_device_t>
|
||||
make_avcodec_encode_device(pix_fmt_e pix_fmt) override {
|
||||
std::unique_ptr<avcodec_encode_device_t> make_avcodec_encode_device(pix_fmt_e pix_fmt) override {
|
||||
#ifdef SUNSHINE_BUILD_VAAPI
|
||||
if (mem_type == mem_type_e::vaapi) {
|
||||
return va::make_avcodec_encode_device(width, height, false);
|
||||
@@ -577,8 +552,7 @@ namespace platf {
|
||||
return std::make_unique<avcodec_encode_device_t>();
|
||||
}
|
||||
|
||||
int
|
||||
dummy_img(img_t *img) override {
|
||||
int dummy_img(img_t *img) override {
|
||||
// TODO: stop cheating and give black image
|
||||
if (!img) {
|
||||
return -1;
|
||||
@@ -605,15 +579,15 @@ namespace platf {
|
||||
|
||||
task_pool_util::TaskPool::task_id_t refresh_task_id;
|
||||
|
||||
void
|
||||
delayed_refresh() {
|
||||
void delayed_refresh() {
|
||||
refresh();
|
||||
|
||||
refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh, 2s, this).task_id;
|
||||
}
|
||||
|
||||
shm_attr_t(mem_type_e mem_type):
|
||||
x11_attr_t(mem_type), shm_xdisplay { x11::OpenDisplay(nullptr) } {
|
||||
x11_attr_t(mem_type),
|
||||
shm_xdisplay {x11::OpenDisplay(nullptr)} {
|
||||
refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh, 2s, this).task_id;
|
||||
}
|
||||
|
||||
@@ -621,8 +595,7 @@ namespace platf {
|
||||
while (!task_pool.cancel(refresh_task_id));
|
||||
}
|
||||
|
||||
capture_e
|
||||
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
||||
capture_e capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override {
|
||||
auto next_frame = std::chrono::steady_clock::now();
|
||||
|
||||
sleep_overshoot_logger.reset();
|
||||
@@ -667,18 +640,16 @@ namespace platf {
|
||||
return capture_e::ok;
|
||||
}
|
||||
|
||||
capture_e
|
||||
snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor) {
|
||||
capture_e snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor) {
|
||||
// The whole X server changed, so we must reinit everything
|
||||
if (xattr.width != env_width || xattr.height != env_height) {
|
||||
BOOST_LOG(warning) << "X dimensions changed in SHM mode, request reinit"sv;
|
||||
return capture_e::reinit;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
auto img_cookie = xcb::shm_get_image_unchecked(xcb.get(), display->root, offset_x, offset_y, width, height, ~0, XCB_IMAGE_FORMAT_Z_PIXMAP, seg, 0);
|
||||
auto frame_timestamp = std::chrono::steady_clock::now();
|
||||
|
||||
xcb_img_t img_reply { xcb::shm_get_image_reply(xcb.get(), img_cookie, nullptr) };
|
||||
xcb_img_t img_reply {xcb::shm_get_image_reply(xcb.get(), img_cookie, nullptr)};
|
||||
if (!img_reply) {
|
||||
BOOST_LOG(error) << "Could not get image reply"sv;
|
||||
return capture_e::reinit;
|
||||
@@ -699,8 +670,7 @@ namespace platf {
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<img_t>
|
||||
alloc_img() override {
|
||||
std::shared_ptr<img_t> alloc_img() override {
|
||||
auto img = std::make_shared<shm_img_t>();
|
||||
img->width = width;
|
||||
img->height = height;
|
||||
@@ -711,13 +681,11 @@ namespace platf {
|
||||
return img;
|
||||
}
|
||||
|
||||
int
|
||||
dummy_img(platf::img_t *img) override {
|
||||
int dummy_img(platf::img_t *img) override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
init(const std::string &display_name, const ::video::config_t &config) {
|
||||
int init(const std::string &display_name, const ::video::config_t &config) {
|
||||
if (x11_attr_t::init(display_name, config)) {
|
||||
return 1;
|
||||
}
|
||||
@@ -756,14 +724,12 @@ namespace platf {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
frame_size() {
|
||||
std::uint32_t frame_size() {
|
||||
return width * height * 4;
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<display_t>
|
||||
x11_display(platf::mem_type_e hwdevice_type, const std::string &display_name, const ::video::config_t &config) {
|
||||
std::shared_ptr<display_t> x11_display(platf::mem_type_e hwdevice_type, const std::string &display_name, const ::video::config_t &config) {
|
||||
if (hwdevice_type != platf::mem_type_e::system && hwdevice_type != platf::mem_type_e::vaapi && hwdevice_type != platf::mem_type_e::cuda) {
|
||||
BOOST_LOG(error) << "Could not initialize x11 display with the given hw device type"sv;
|
||||
return nullptr;
|
||||
@@ -797,8 +763,7 @@ namespace platf {
|
||||
return x11_disp;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
x11_display_names() {
|
||||
std::vector<std::string> x11_display_names() {
|
||||
if (load_x11() || load_xcb()) {
|
||||
BOOST_LOG(error) << "Couldn't init x11 libraries"sv;
|
||||
|
||||
@@ -807,18 +772,18 @@ namespace platf {
|
||||
|
||||
BOOST_LOG(info) << "Detecting displays"sv;
|
||||
|
||||
x11::xdisplay_t xdisplay { x11::OpenDisplay(nullptr) };
|
||||
x11::xdisplay_t xdisplay {x11::OpenDisplay(nullptr)};
|
||||
if (!xdisplay) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto xwindow = DefaultRootWindow(xdisplay.get());
|
||||
screen_res_t screenr { x11::rr::GetScreenResources(xdisplay.get(), xwindow) };
|
||||
screen_res_t screenr {x11::rr::GetScreenResources(xdisplay.get(), xwindow)};
|
||||
int output = screenr->noutput;
|
||||
|
||||
int monitor = 0;
|
||||
for (int x = 0; x < output; ++x) {
|
||||
output_info_t out_info { x11::rr::GetOutputInfo(xdisplay.get(), screenr.get(), screenr->outputs[x]) };
|
||||
output_info_t out_info {x11::rr::GetOutputInfo(xdisplay.get(), screenr.get(), screenr->outputs[x])};
|
||||
if (out_info) {
|
||||
BOOST_LOG(info) << "Detected display: "sv << out_info->name << " (id: "sv << monitor << ")"sv << out_info->name << " connected: "sv << (out_info->connection == RR_Connected);
|
||||
++monitor;
|
||||
@@ -835,25 +800,22 @@ namespace platf {
|
||||
return names;
|
||||
}
|
||||
|
||||
void
|
||||
freeImage(XImage *p) {
|
||||
void freeImage(XImage *p) {
|
||||
XDestroyImage(p);
|
||||
}
|
||||
void
|
||||
freeX(XFixesCursorImage *p) {
|
||||
|
||||
void freeX(XFixesCursorImage *p) {
|
||||
x11::Free(p);
|
||||
}
|
||||
|
||||
int
|
||||
load_xcb() {
|
||||
int load_xcb() {
|
||||
// This will be called once only
|
||||
static int xcb_status = xcb::init_shm() || xcb::init();
|
||||
|
||||
return xcb_status;
|
||||
}
|
||||
|
||||
int
|
||||
load_x11() {
|
||||
int load_x11() {
|
||||
// This will be called once only
|
||||
static int x11_status =
|
||||
window_system == window_system_e::NONE ||
|
||||
@@ -863,8 +825,7 @@ namespace platf {
|
||||
}
|
||||
|
||||
namespace x11 {
|
||||
std::optional<cursor_t>
|
||||
cursor_t::make() {
|
||||
std::optional<cursor_t> cursor_t::make() {
|
||||
if (load_x11()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -876,8 +837,7 @@ namespace platf {
|
||||
return cursor;
|
||||
}
|
||||
|
||||
void
|
||||
cursor_t::capture(egl::cursor_t &img) {
|
||||
void cursor_t::capture(egl::cursor_t &img) {
|
||||
auto display = (xdisplay_t::pointer) ctx.get();
|
||||
|
||||
xcursor_t xcursor = fix::GetCursorImage(display);
|
||||
@@ -904,23 +864,19 @@ namespace platf {
|
||||
img.serial = xcursor->cursor_serial;
|
||||
}
|
||||
|
||||
void
|
||||
cursor_t::blend(img_t &img, int offsetX, int offsetY) {
|
||||
void cursor_t::blend(img_t &img, int offsetX, int offsetY) {
|
||||
blend_cursor((xdisplay_t::pointer) ctx.get(), img, offsetX, offsetY);
|
||||
}
|
||||
|
||||
xdisplay_t
|
||||
make_display() {
|
||||
xdisplay_t make_display() {
|
||||
return OpenDisplay(nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
freeDisplay(_XDisplay *xdisplay) {
|
||||
void freeDisplay(_XDisplay *xdisplay) {
|
||||
CloseDisplay(xdisplay);
|
||||
}
|
||||
|
||||
void
|
||||
freeCursorCtx(cursor_ctx_t::pointer ctx) {
|
||||
void freeCursorCtx(cursor_ctx_t::pointer ctx) {
|
||||
CloseDisplay((xdisplay_t::pointer) ctx);
|
||||
}
|
||||
} // namespace x11
|
||||
|
||||
Reference in New Issue
Block a user