Fix all warnings
This commit is contained in:
parent
715a3c612a
commit
6cff1a49d2
1
TODO
1
TODO
@ -60,7 +60,6 @@ Intel is a bit weird with monitor capture and multiple monitors. If one of the m
|
|||||||
How about if multiple monitors are rotated?
|
How about if multiple monitors are rotated?
|
||||||
|
|
||||||
When using multiple monitors kms grab the target monitor instead of the whole screen.
|
When using multiple monitors kms grab the target monitor instead of the whole screen.
|
||||||
Enable opus/flac again. It's broken right now when merging audio inputs. The audio gets a lot of static noise!
|
|
||||||
|
|
||||||
Support vp8/vp9/av1. This is especially important on amd which on some distros (such as Manjaro) where hardware accelerated h264/hevc is disabled in the mesa package.
|
Support vp8/vp9/av1. This is especially important on amd which on some distros (such as Manjaro) where hardware accelerated h264/hevc is disabled in the mesa package.
|
||||||
|
|
||||||
|
9
build.sh
9
build.sh
@ -1,19 +1,20 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
opts="-O2 -g0 -DNDEBUG -Wall -Wextra -Werror -s"
|
||||||
|
[ -n "$DEBUG" ] && opts="-O0 -g3 -Wall -Wextra -Werror";
|
||||||
|
|
||||||
build_gsr_kms_server() {
|
build_gsr_kms_server() {
|
||||||
dependencies="libdrm"
|
dependencies="libdrm"
|
||||||
includes="$(pkg-config --cflags $dependencies)"
|
includes="$(pkg-config --cflags $dependencies)"
|
||||||
libs="$(pkg-config --libs $dependencies) -ldl"
|
libs="$(pkg-config --libs $dependencies) -ldl"
|
||||||
opts="-O2 -g0 -DNDEBUG"
|
|
||||||
gcc -c kms/server/kms_server.c $opts $includes
|
gcc -c kms/server/kms_server.c $opts $includes
|
||||||
gcc -o gsr-kms-server -O2 kms_server.o -s $libs
|
gcc -o gsr-kms-server -O2 kms_server.o $libs $opts
|
||||||
}
|
}
|
||||||
|
|
||||||
build_gsr() {
|
build_gsr() {
|
||||||
dependencies="libavcodec libavformat libavutil x11 xcomposite xrandr xfixes libpulse libswresample libavfilter libva libcap"
|
dependencies="libavcodec libavformat libavutil x11 xcomposite xrandr xfixes libpulse libswresample libavfilter libva libcap"
|
||||||
includes="$(pkg-config --cflags $dependencies)"
|
includes="$(pkg-config --cflags $dependencies)"
|
||||||
libs="$(pkg-config --libs $dependencies) -ldl -pthread -lm"
|
libs="$(pkg-config --libs $dependencies) -ldl -pthread -lm"
|
||||||
opts="-O2 -g0 -DNDEBUG"
|
|
||||||
gcc -c src/capture/capture.c $opts $includes
|
gcc -c src/capture/capture.c $opts $includes
|
||||||
gcc -c src/capture/nvfbc.c $opts $includes
|
gcc -c src/capture/nvfbc.c $opts $includes
|
||||||
gcc -c src/capture/xcomposite_cuda.c $opts $includes
|
gcc -c src/capture/xcomposite_cuda.c $opts $includes
|
||||||
@ -32,7 +33,7 @@ build_gsr() {
|
|||||||
gcc -c src/library_loader.c $opts $includes
|
gcc -c src/library_loader.c $opts $includes
|
||||||
g++ -c src/sound.cpp $opts $includes
|
g++ -c src/sound.cpp $opts $includes
|
||||||
g++ -c src/main.cpp $opts $includes
|
g++ -c src/main.cpp $opts $includes
|
||||||
g++ -o gpu-screen-recorder -O2 capture.o nvfbc.o kms_client.o egl.o cuda.o xnvctrl.o overclock.o window_texture.o shader.o color_conversion.o cursor.o utils.o library_loader.o xcomposite_cuda.o xcomposite_vaapi.o kms_vaapi.o sound.o main.o -s $libs
|
g++ -o gpu-screen-recorder -O2 capture.o nvfbc.o kms_client.o egl.o cuda.o xnvctrl.o overclock.o window_texture.o shader.o color_conversion.o cursor.o utils.o library_loader.o xcomposite_cuda.o xcomposite_vaapi.o kms_vaapi.o sound.o main.o $libs $opts
|
||||||
}
|
}
|
||||||
|
|
||||||
build_gsr_kms_server
|
build_gsr_kms_server
|
||||||
|
@ -90,6 +90,10 @@ typedef void (*__eglMustCastToProperFunctionPointerType)(void);
|
|||||||
#define GL_COMPILE_STATUS 0x8B81
|
#define GL_COMPILE_STATUS 0x8B81
|
||||||
#define GL_LINK_STATUS 0x8B82
|
#define GL_LINK_STATUS 0x8B82
|
||||||
|
|
||||||
|
typedef unsigned int (*FUNC_eglExportDMABUFImageQueryMESA)(EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, uint64_t *modifiers);
|
||||||
|
typedef unsigned int (*FUNC_eglExportDMABUFImageMESA)(EGLDisplay dpy, EGLImageKHR image, int *fds, int32_t *strides, int32_t *offsets);
|
||||||
|
typedef void (*FUNC_glEGLImageTargetTexture2DOES)(unsigned int target, GLeglImageOES image);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *egl_library;
|
void *egl_library;
|
||||||
void *gl_library;
|
void *gl_library;
|
||||||
@ -115,9 +119,9 @@ typedef struct {
|
|||||||
unsigned int (*eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
unsigned int (*eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
||||||
__eglMustCastToProperFunctionPointerType (*eglGetProcAddress)(const char *procname);
|
__eglMustCastToProperFunctionPointerType (*eglGetProcAddress)(const char *procname);
|
||||||
|
|
||||||
unsigned int (*eglExportDMABUFImageQueryMESA)(EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, uint64_t *modifiers);
|
FUNC_eglExportDMABUFImageQueryMESA eglExportDMABUFImageQueryMESA;
|
||||||
unsigned int (*eglExportDMABUFImageMESA)(EGLDisplay dpy, EGLImageKHR image, int *fds, int32_t *strides, int32_t *offsets);
|
FUNC_eglExportDMABUFImageMESA eglExportDMABUFImageMESA;
|
||||||
void (*glEGLImageTargetTexture2DOES)(unsigned int target, GLeglImageOES image);
|
FUNC_glEGLImageTargetTexture2DOES glEGLImageTargetTexture2DOES;
|
||||||
|
|
||||||
unsigned int (*glGetError)(void);
|
unsigned int (*glGetError)(void);
|
||||||
const unsigned char* (*glGetString)(unsigned int name);
|
const unsigned char* (*glGetString)(unsigned int name);
|
||||||
|
@ -96,6 +96,15 @@ static bool create_socket_path(char *output_path, size_t output_path_size) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void strncpy_safe(char *dst, const char *src, int len) {
|
||||||
|
int src_len = strlen(src);
|
||||||
|
int min_len = src_len;
|
||||||
|
if(len - 1 < min_len)
|
||||||
|
min_len = len - 1;
|
||||||
|
memcpy(dst, src, min_len);
|
||||||
|
dst[min_len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
int gsr_kms_client_init(gsr_kms_client *self, const char *card_path) {
|
int gsr_kms_client_init(gsr_kms_client *self, const char *card_path) {
|
||||||
self->kms_server_pid = -1;
|
self->kms_server_pid = -1;
|
||||||
self->socket_fd = -1;
|
self->socket_fd = -1;
|
||||||
@ -152,7 +161,7 @@ int gsr_kms_client_init(gsr_kms_client *self, const char *card_path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local_addr.sun_family = AF_UNIX;
|
local_addr.sun_family = AF_UNIX;
|
||||||
strncpy(local_addr.sun_path, self->socket_path, sizeof(local_addr.sun_path));
|
strncpy_safe(local_addr.sun_path, self->socket_path, sizeof(local_addr.sun_path));
|
||||||
if(bind(self->socket_fd, (struct sockaddr*)&local_addr, sizeof(local_addr.sun_family) + strlen(local_addr.sun_path)) == -1) {
|
if(bind(self->socket_fd, (struct sockaddr*)&local_addr, sizeof(local_addr.sun_family) + strlen(local_addr.sun_path)) == -1) {
|
||||||
fprintf(stderr, "gsr error: gsr_kms_client_init: failed to bind socket, error: %s\n", strerror(errno));
|
fprintf(stderr, "gsr error: gsr_kms_client_init: failed to bind socket, error: %s\n", strerror(errno));
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -294,6 +294,15 @@ static double clock_get_monotonic_seconds(void) {
|
|||||||
return (double)ts.tv_sec + (double)ts.tv_nsec * 0.000000001;
|
return (double)ts.tv_sec + (double)ts.tv_nsec * 0.000000001;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void strncpy_safe(char *dst, const char *src, int len) {
|
||||||
|
int src_len = strlen(src);
|
||||||
|
int min_len = src_len;
|
||||||
|
if(len - 1 < min_len)
|
||||||
|
min_len = len - 1;
|
||||||
|
memcpy(dst, src, min_len);
|
||||||
|
dst[min_len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if(argc != 3) {
|
if(argc != 3) {
|
||||||
fprintf(stderr, "usage: kms_server <domain_socket_path> <card_path>\n");
|
fprintf(stderr, "usage: kms_server <domain_socket_path> <card_path>\n");
|
||||||
@ -329,7 +338,7 @@ int main(int argc, char **argv) {
|
|||||||
while(clock_get_monotonic_seconds() - start_time < connect_timeout_sec) {
|
while(clock_get_monotonic_seconds() - start_time < connect_timeout_sec) {
|
||||||
struct sockaddr_un remote_addr = {0};
|
struct sockaddr_un remote_addr = {0};
|
||||||
remote_addr.sun_family = AF_UNIX;
|
remote_addr.sun_family = AF_UNIX;
|
||||||
strncpy(remote_addr.sun_path, domain_socket_path, sizeof(remote_addr.sun_path));
|
strncpy_safe(remote_addr.sun_path, domain_socket_path, sizeof(remote_addr.sun_path));
|
||||||
// TODO: Check if parent disconnected
|
// TODO: Check if parent disconnected
|
||||||
if(connect(socket_fd, (struct sockaddr*)&remote_addr, sizeof(remote_addr.sun_family) + strlen(remote_addr.sun_path)) == -1) {
|
if(connect(socket_fd, (struct sockaddr*)&remote_addr, sizeof(remote_addr.sun_family) + strlen(remote_addr.sun_path)) == -1) {
|
||||||
if(errno == ECONNREFUSED || errno == ENOENT) {
|
if(errno == ECONNREFUSED || errno == ENOENT) {
|
||||||
|
@ -4,5 +4,8 @@ type = "executable"
|
|||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
platforms = ["posix"]
|
platforms = ["posix"]
|
||||||
|
|
||||||
|
[config]
|
||||||
|
error_on_warning = "true"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libdrm = ">=2"
|
libdrm = ">=2"
|
||||||
|
@ -6,6 +6,7 @@ platforms = ["posix"]
|
|||||||
|
|
||||||
[config]
|
[config]
|
||||||
ignore_dirs = ["kms/server"]
|
ignore_dirs = ["kms/server"]
|
||||||
|
error_on_warning = "true"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libavcodec = ">=58"
|
libavcodec = ">=58"
|
||||||
|
@ -135,6 +135,7 @@ static bool properties_has_atom(Atom *props, int nprop, Atom atom) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void monitor_callback(const XRROutputInfo *output_info, const XRRCrtcInfo *crt_info, const XRRModeInfo *mode_info, void *userdata) {
|
static void monitor_callback(const XRROutputInfo *output_info, const XRRCrtcInfo *crt_info, const XRRModeInfo *mode_info, void *userdata) {
|
||||||
|
(void)mode_info;
|
||||||
MonitorCallbackUserdata *monitor_callback_userdata = userdata;
|
MonitorCallbackUserdata *monitor_callback_userdata = userdata;
|
||||||
++monitor_callback_userdata->num_monitors;
|
++monitor_callback_userdata->num_monitors;
|
||||||
|
|
||||||
@ -436,6 +437,7 @@ static gsr_kms_response_fd* find_largest_drm(gsr_kms_response *kms_response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int gsr_capture_kms_vaapi_capture(gsr_capture *cap, AVFrame *frame) {
|
static int gsr_capture_kms_vaapi_capture(gsr_capture *cap, AVFrame *frame) {
|
||||||
|
(void)frame;
|
||||||
gsr_capture_kms_vaapi *cap_kms = cap->priv;
|
gsr_capture_kms_vaapi *cap_kms = cap->priv;
|
||||||
|
|
||||||
for(int i = 0; i < cap_kms->kms_response.num_fds; ++i) {
|
for(int i = 0; i < cap_kms->kms_response.num_fds; ++i) {
|
||||||
|
@ -95,6 +95,10 @@ static bool version_less_than(int major, int minor, int expected_major, int expe
|
|||||||
return major < expected_major || (major == expected_major && minor < expected_minor);
|
return major < expected_major || (major == expected_major && minor < expected_minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_func_ptr(void **dst, void *src) {
|
||||||
|
*dst = src;
|
||||||
|
}
|
||||||
|
|
||||||
static bool gsr_capture_nvfbc_load_library(gsr_capture *cap) {
|
static bool gsr_capture_nvfbc_load_library(gsr_capture *cap) {
|
||||||
gsr_capture_nvfbc *cap_nvfbc = cap->priv;
|
gsr_capture_nvfbc *cap_nvfbc = cap->priv;
|
||||||
|
|
||||||
@ -105,7 +109,7 @@ static bool gsr_capture_nvfbc_load_library(gsr_capture *cap) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cap_nvfbc->nv_fbc_create_instance = (PNVFBCCREATEINSTANCE)dlsym(lib, "NvFBCCreateInstance");
|
set_func_ptr((void**)&cap_nvfbc->nv_fbc_create_instance, dlsym(lib, "NvFBCCreateInstance"));
|
||||||
if(!cap_nvfbc->nv_fbc_create_instance) {
|
if(!cap_nvfbc->nv_fbc_create_instance) {
|
||||||
fprintf(stderr, "gsr error: unable to resolve symbol 'NvFBCCreateInstance'\n");
|
fprintf(stderr, "gsr error: unable to resolve symbol 'NvFBCCreateInstance'\n");
|
||||||
dlclose(lib);
|
dlclose(lib);
|
||||||
|
@ -477,7 +477,6 @@ static int gsr_capture_xcomposite_cuda_capture(gsr_capture *cap, AVFrame *frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void gsr_capture_xcomposite_cuda_destroy(gsr_capture *cap, AVCodecContext *video_codec_context) {
|
static void gsr_capture_xcomposite_cuda_destroy(gsr_capture *cap, AVCodecContext *video_codec_context) {
|
||||||
gsr_capture_xcomposite_cuda *cap_xcomp = cap->priv;
|
|
||||||
if(cap->priv) {
|
if(cap->priv) {
|
||||||
gsr_capture_xcomposite_cuda_stop(cap, video_codec_context);
|
gsr_capture_xcomposite_cuda_stop(cap, video_codec_context);
|
||||||
free(cap->priv);
|
free(cap->priv);
|
||||||
|
@ -606,7 +606,6 @@ static void gsr_capture_xcomposite_vaapi_stop(gsr_capture *cap, AVCodecContext *
|
|||||||
|
|
||||||
static void gsr_capture_xcomposite_vaapi_destroy(gsr_capture *cap, AVCodecContext *video_codec_context) {
|
static void gsr_capture_xcomposite_vaapi_destroy(gsr_capture *cap, AVCodecContext *video_codec_context) {
|
||||||
(void)video_codec_context;
|
(void)video_codec_context;
|
||||||
gsr_capture_xcomposite_vaapi *cap_xcomp = cap->priv;
|
|
||||||
if(cap->priv) {
|
if(cap->priv) {
|
||||||
gsr_capture_xcomposite_vaapi_stop(cap, video_codec_context);
|
gsr_capture_xcomposite_vaapi_stop(cap, video_codec_context);
|
||||||
free(cap->priv);
|
free(cap->priv);
|
||||||
|
@ -112,9 +112,9 @@ static bool gsr_egl_load_egl(gsr_egl *self, void *library) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool gsr_egl_proc_load_egl(gsr_egl *self) {
|
static bool gsr_egl_proc_load_egl(gsr_egl *self) {
|
||||||
self->eglExportDMABUFImageQueryMESA = self->eglGetProcAddress("eglExportDMABUFImageQueryMESA");
|
self->eglExportDMABUFImageQueryMESA = (FUNC_eglExportDMABUFImageQueryMESA)self->eglGetProcAddress("eglExportDMABUFImageQueryMESA");
|
||||||
self->eglExportDMABUFImageMESA = self->eglGetProcAddress("eglExportDMABUFImageMESA");
|
self->eglExportDMABUFImageMESA = (FUNC_eglExportDMABUFImageMESA)self->eglGetProcAddress("eglExportDMABUFImageMESA");
|
||||||
self->glEGLImageTargetTexture2DOES = self->eglGetProcAddress("glEGLImageTargetTexture2DOES");
|
self->glEGLImageTargetTexture2DOES = (FUNC_glEGLImageTargetTexture2DOES)self->eglGetProcAddress("glEGLImageTargetTexture2DOES");
|
||||||
|
|
||||||
if(!self->glEGLImageTargetTexture2DOES) {
|
if(!self->glEGLImageTargetTexture2DOES) {
|
||||||
fprintf(stderr, "gsr error: gsr_egl_load failed: could not find glEGLImageTargetTexture2DOES\n");
|
fprintf(stderr, "gsr error: gsr_egl_load failed: could not find glEGLImageTargetTexture2DOES\n");
|
||||||
|
10
src/main.cpp
10
src/main.cpp
@ -46,6 +46,8 @@ static const int VIDEO_STREAM_INDEX = 0;
|
|||||||
static thread_local char av_error_buffer[AV_ERROR_MAX_STRING_SIZE];
|
static thread_local char av_error_buffer[AV_ERROR_MAX_STRING_SIZE];
|
||||||
|
|
||||||
static void monitor_output_callback_print(const XRROutputInfo *output_info, const XRRCrtcInfo *crt_info, const XRRModeInfo *mode_info, void *userdata) {
|
static void monitor_output_callback_print(const XRROutputInfo *output_info, const XRRCrtcInfo *crt_info, const XRRModeInfo *mode_info, void *userdata) {
|
||||||
|
(void)mode_info;
|
||||||
|
(void)userdata;
|
||||||
fprintf(stderr, " \"%.*s\" (%dx%d+%d+%d)\n", output_info->nameLen, output_info->name, (int)crt_info->width, (int)crt_info->height, crt_info->x, crt_info->y);
|
fprintf(stderr, " \"%.*s\" (%dx%d+%d+%d)\n", output_info->nameLen, output_info->name, (int)crt_info->width, (int)crt_info->height, crt_info->x, crt_info->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,11 +85,11 @@ enum class FramerateMode {
|
|||||||
VARIABLE
|
VARIABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
static int x11_error_handler(Display *dpy, XErrorEvent *ev) {
|
static int x11_error_handler(Display*, XErrorEvent*) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int x11_io_error_handler(Display *dpy) {
|
static int x11_io_error_handler(Display*) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +238,7 @@ static AVSampleFormat audio_format_to_sample_format(const AudioFormat audio_form
|
|||||||
return AV_SAMPLE_FMT_S16;
|
return AV_SAMPLE_FMT_S16;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AVCodecContext* create_audio_codec_context(int fps, AudioCodec audio_codec, FramerateMode framerate_mode) {
|
static AVCodecContext* create_audio_codec_context(int fps, AudioCodec audio_codec) {
|
||||||
const AVCodec *codec = avcodec_find_encoder(audio_codec_get_id(audio_codec));
|
const AVCodec *codec = avcodec_find_encoder(audio_codec_get_id(audio_codec));
|
||||||
if (!codec) {
|
if (!codec) {
|
||||||
fprintf(stderr, "Error: Could not find %s audio encoder\n", audio_codec_get_name(audio_codec));
|
fprintf(stderr, "Error: Could not find %s audio encoder\n", audio_codec_get_name(audio_codec));
|
||||||
@ -1615,7 +1617,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
int audio_stream_index = VIDEO_STREAM_INDEX + 1;
|
int audio_stream_index = VIDEO_STREAM_INDEX + 1;
|
||||||
for(const MergedAudioInputs &merged_audio_inputs : requested_audio_inputs) {
|
for(const MergedAudioInputs &merged_audio_inputs : requested_audio_inputs) {
|
||||||
AVCodecContext *audio_codec_context = create_audio_codec_context(fps, audio_codec, framerate_mode);
|
AVCodecContext *audio_codec_context = create_audio_codec_context(fps, audio_codec);
|
||||||
|
|
||||||
AVStream *audio_stream = nullptr;
|
AVStream *audio_stream = nullptr;
|
||||||
if(replay_buffer_size_secs == -1)
|
if(replay_buffer_size_secs == -1)
|
||||||
|
@ -309,6 +309,7 @@ static void pa_state_cb(pa_context *c, void *userdata) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void pa_sourcelist_cb(pa_context *ctx, const pa_source_info *source_info, int eol, void *userdata) {
|
static void pa_sourcelist_cb(pa_context *ctx, const pa_source_info *source_info, int eol, void *userdata) {
|
||||||
|
(void)ctx;
|
||||||
if(eol > 0)
|
if(eol > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ void for_each_active_monitor_output(Display *display, active_monitor_callback ca
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void get_monitor_by_name_callback(const XRROutputInfo *output_info, const XRRCrtcInfo *crt_info, const XRRModeInfo *mode_info, void *userdata) {
|
static void get_monitor_by_name_callback(const XRROutputInfo *output_info, const XRRCrtcInfo *crt_info, const XRRModeInfo *mode_info, void *userdata) {
|
||||||
|
(void)mode_info;
|
||||||
get_monitor_by_name_userdata *data = (get_monitor_by_name_userdata*)userdata;
|
get_monitor_by_name_userdata *data = (get_monitor_by_name_userdata*)userdata;
|
||||||
if(!data->found_monitor && data->name_len == output_info->nameLen && memcmp(data->name, output_info->name, data->name_len) == 0) {
|
if(!data->found_monitor && data->name_len == output_info->nameLen && memcmp(data->name, output_info->name, data->name_len) == 0) {
|
||||||
data->monitor->pos = (vec2i){ .x = crt_info->x, .y = crt_info->y };
|
data->monitor->pos = (vec2i){ .x = crt_info->x, .y = crt_info->y };
|
||||||
|
Loading…
Reference in New Issue
Block a user