test blank
This commit is contained in:
parent
e7b8b59156
commit
6e14c5aa36
5 changed files with 193 additions and 2 deletions
|
@ -19,7 +19,7 @@ IF(NOT HAVE_LINUX_API_HEADERS)
|
||||||
message(FATAL_ERROR "linux-api-headers not found")
|
message(FATAL_ERROR "linux-api-headers not found")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
add_executable(kmsvnc kmsvnc.c drm.c input.c keymap.c va.c)
|
add_executable(kmsvnc kmsvnc.c drm.c input.c keymap.c va.c drm_master.c)
|
||||||
target_include_directories(kmsvnc PUBLIC
|
target_include_directories(kmsvnc PUBLIC
|
||||||
${LIBDRM_INCLUDEDIR}
|
${LIBDRM_INCLUDEDIR}
|
||||||
${LIBDRM_INCLUDEDIR}/libdrm
|
${LIBDRM_INCLUDEDIR}/libdrm
|
||||||
|
|
77
drm.c
77
drm.c
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "drm.h"
|
#include "drm.h"
|
||||||
#include "va.h"
|
#include "va.h"
|
||||||
|
#include "drm_master.h"
|
||||||
|
|
||||||
extern struct kmsvnc_data *kmsvnc;
|
extern struct kmsvnc_data *kmsvnc;
|
||||||
|
|
||||||
|
@ -154,6 +155,17 @@ void drm_sync_noop(int drmfd)
|
||||||
|
|
||||||
void drm_cleanup() {
|
void drm_cleanup() {
|
||||||
if (kmsvnc->drm) {
|
if (kmsvnc->drm) {
|
||||||
|
if (kmsvnc->drm->gamma && kmsvnc->drm->gamma->size && kmsvnc->drm->gamma->red && kmsvnc->drm->gamma->green && kmsvnc->drm->gamma->blue) {
|
||||||
|
if (drmModeCrtcSetGamma(kmsvnc->drm->drm_master_fd ?: kmsvnc->drm->drm_fd, kmsvnc->drm->plane->crtc_id, kmsvnc->drm->gamma->size, kmsvnc->drm->gamma->red, kmsvnc->drm->gamma->green, kmsvnc->drm->gamma->blue)) perror("Failed to restore gamma");
|
||||||
|
}
|
||||||
|
if (kmsvnc->drm->gamma->red) {
|
||||||
|
free(kmsvnc->drm->gamma->red);
|
||||||
|
kmsvnc->drm->gamma->red = kmsvnc->drm->gamma->green = kmsvnc->drm->gamma->blue = NULL;
|
||||||
|
}
|
||||||
|
if (kmsvnc->drm->gamma) {
|
||||||
|
free(kmsvnc->drm->gamma);
|
||||||
|
kmsvnc->drm->gamma = NULL;
|
||||||
|
}
|
||||||
if (kmsvnc->drm->drm_ver) {
|
if (kmsvnc->drm->drm_ver) {
|
||||||
drmFreeVersion(kmsvnc->drm->drm_ver);
|
drmFreeVersion(kmsvnc->drm->drm_ver);
|
||||||
kmsvnc->drm->drm_ver = NULL;
|
kmsvnc->drm->drm_ver = NULL;
|
||||||
|
@ -202,6 +214,10 @@ void drm_cleanup() {
|
||||||
close(kmsvnc->drm->drm_fd);
|
close(kmsvnc->drm->drm_fd);
|
||||||
kmsvnc->drm->drm_fd = 0;
|
kmsvnc->drm->drm_fd = 0;
|
||||||
}
|
}
|
||||||
|
if (kmsvnc->drm->drm_master_fd > 0) {
|
||||||
|
close(kmsvnc->drm->drm_master_fd);
|
||||||
|
kmsvnc->drm->drm_master_fd = 0;
|
||||||
|
}
|
||||||
if (kmsvnc->drm->plane_res) {
|
if (kmsvnc->drm->plane_res) {
|
||||||
drmModeFreePlaneResources(kmsvnc->drm->plane_res);
|
drmModeFreePlaneResources(kmsvnc->drm->plane_res);
|
||||||
kmsvnc->drm->plane_res = NULL;
|
kmsvnc->drm->plane_res = NULL;
|
||||||
|
@ -469,6 +485,67 @@ int drm_open() {
|
||||||
|
|
||||||
if (drm_refresh_planes(1)) return 1;
|
if (drm_refresh_planes(1)) return 1;
|
||||||
|
|
||||||
|
drm->gamma = malloc(sizeof(struct kmsvnc_drm_gamma_data));
|
||||||
|
if (!drm->gamma) KMSVNC_FATAL("memory allocation error at %s:%d\n", __FILE__, __LINE__);
|
||||||
|
memset(drm->gamma, 0, sizeof(struct kmsvnc_drm_gamma_data));
|
||||||
|
drmModeCrtc *target_crtc = drmModeGetCrtc(drm->drm_fd, drm->plane->crtc_id);
|
||||||
|
if (target_crtc) {
|
||||||
|
if (!drmIsMaster(drm->drm_fd)) {
|
||||||
|
drm->drm_master_fd = drm_get_master_fd();
|
||||||
|
drm->drm_master_fd = drm->drm_master_fd > 0 ? drm->drm_master_fd : 0;
|
||||||
|
if (kmsvnc->debug_enabled) {
|
||||||
|
fprintf(stderr, "not master client, master fd %d\n", drm->drm_master_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drm->gamma->size = (uint32_t)target_crtc->gamma_size;
|
||||||
|
drm->gamma->red = malloc(drm->gamma->size*sizeof(uint16_t)*3);
|
||||||
|
if (!drm->gamma->size) {
|
||||||
|
fprintf(stderr, "drm->gamma->size = %u, not setting gamma.\n", drm->gamma->size);
|
||||||
|
}
|
||||||
|
else if (!drm->gamma->red) {
|
||||||
|
fprintf(stderr, "memory allocation error at %s:%d\n", __FILE__, __LINE__);
|
||||||
|
fprintf(stderr, "not setting gamma.\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memset(drm->gamma->red, 0, drm->gamma->size*sizeof(uint16_t)*3);
|
||||||
|
drm->gamma->green = drm->gamma->red + drm->gamma->size;
|
||||||
|
drm->gamma->blue = drm->gamma->red + drm->gamma->size*2;
|
||||||
|
// legacy api, but weston also uses this, so whatever
|
||||||
|
drmModeCrtcGetGamma(drm->drm_fd, drm->plane->crtc_id, drm->gamma->size, drm->gamma->red, drm->gamma->green, drm->gamma->blue);
|
||||||
|
if (kmsvnc->debug_enabled) {
|
||||||
|
for (int i = 0; i < drm->gamma->size; i++) {
|
||||||
|
fprintf(stderr, "gamma: %05d %05hu %05hu %05hu\n", i, drm->gamma->red[i], drm->gamma->green[i], drm->gamma->blue[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t new_gamma_size = drm->gamma->size;
|
||||||
|
uint16_t *new_gammas = malloc(new_gamma_size*sizeof(uint16_t)*3);
|
||||||
|
if (!new_gammas) {
|
||||||
|
fprintf(stderr, "memory allocation error at %s:%d\n", __FILE__, __LINE__);
|
||||||
|
fprintf(stderr, "not setting gamma.\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memset(new_gammas, 0, new_gamma_size*sizeof(uint16_t)*3);
|
||||||
|
if (drmModeCrtcSetGamma(drm->drm_master_fd ?: drm->drm_fd, drm->plane->crtc_id, new_gamma_size, new_gammas, new_gammas+new_gamma_size*sizeof(uint16_t), new_gammas+new_gamma_size*sizeof(uint16_t)*2)) perror("Failed to set gamma");
|
||||||
|
if (kmsvnc->debug_enabled) {
|
||||||
|
for (int i = 0; i < new_gamma_size; i++) {
|
||||||
|
fprintf(stderr, "new gamma: %05d %05hu %05hu %05hu\n", i, new_gammas[i], new_gammas[i+new_gamma_size], new_gammas[i+new_gamma_size*2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (new_gammas) {
|
||||||
|
free(new_gammas);
|
||||||
|
new_gammas = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "Did not get a crtc structure, not setting gamma.\n");
|
||||||
|
}
|
||||||
|
if (target_crtc) {
|
||||||
|
drmModeFreeCrtc(target_crtc);
|
||||||
|
target_crtc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
drm->mfb = drmModeGetFB2(drm->drm_fd, drm->plane->fb_id);
|
drm->mfb = drmModeGetFB2(drm->drm_fd, drm->plane->fb_id);
|
||||||
if (!drm->mfb) {
|
if (!drm->mfb) {
|
||||||
KMSVNC_FATAL("Failed to get framebuffer %u: %s\n", drm->plane->fb_id, strerror(errno));
|
KMSVNC_FATAL("Failed to get framebuffer %u: %s\n", drm->plane->fb_id, strerror(errno));
|
||||||
|
|
99
drm_master.c
Normal file
99
drm_master.c
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "drm_master.h"
|
||||||
|
|
||||||
|
extern struct kmsvnc_data *kmsvnc;
|
||||||
|
|
||||||
|
|
||||||
|
static inline int clone_fd(pid_t pid, int target_fd) {
|
||||||
|
int pidfd = syscall(SYS_pidfd_open, pid, 0);
|
||||||
|
if (pidfd <= 0) {
|
||||||
|
perror("pidfd_open");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int cloned = syscall(SYS_pidfd_getfd, pidfd, target_fd, 0);
|
||||||
|
if (cloned <= 0) {
|
||||||
|
perror("pidfd_getfd");
|
||||||
|
}
|
||||||
|
close(pidfd);
|
||||||
|
return cloned;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cmp_fds(pid_t pid, const char *drm_pth) {
|
||||||
|
if (pid == 1) return -1;
|
||||||
|
char path[PATH_MAX+1];
|
||||||
|
snprintf(path, PATH_MAX+1, "/proc/%d/fd", pid);
|
||||||
|
|
||||||
|
struct dirent **fdlist;
|
||||||
|
int count = scandir(path, &fdlist, NULL, versionsort);
|
||||||
|
int ret = -1;
|
||||||
|
if (count >= 0) {
|
||||||
|
for (int n = 0; n < count; n++) {
|
||||||
|
if (ret == -1 && fdlist[n]->d_type == DT_LNK) {
|
||||||
|
char link_pth[PATH_MAX+1];
|
||||||
|
char real_pth[PATH_MAX+1];
|
||||||
|
snprintf(link_pth, PATH_MAX+1, "%s/%s", path, fdlist[n]->d_name);
|
||||||
|
memset(real_pth, 0, PATH_MAX+1);
|
||||||
|
realpath(link_pth, real_pth);
|
||||||
|
if (!strncmp(real_pth, drm_pth, PATH_MAX)) {
|
||||||
|
int fd = atoi(fdlist[n]->d_name);
|
||||||
|
if (fd > 0) {
|
||||||
|
int cloned = clone_fd(pid, fd);
|
||||||
|
if (cloned > 0 && !drmSetMaster(cloned)) {
|
||||||
|
ret = cloned;
|
||||||
|
//if (kmsvnc->debug_enabled) {
|
||||||
|
fprintf(stderr, "found drm master pid=%d, fd=%d, cloned=%d\n", pid, fd, cloned);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (cloned > 0) close(cloned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(fdlist[n]);
|
||||||
|
fdlist[n] = NULL;
|
||||||
|
}
|
||||||
|
free(fdlist);
|
||||||
|
fdlist = NULL;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int drm_get_master_fd() {
|
||||||
|
char drm_pth[PATH_MAX+1];
|
||||||
|
memset(drm_pth, 0, PATH_MAX+1);
|
||||||
|
realpath(kmsvnc->card, drm_pth);
|
||||||
|
|
||||||
|
struct dirent **proclist;
|
||||||
|
int count = scandir("/proc", &proclist, NULL, versionsort);
|
||||||
|
int ret = -1;
|
||||||
|
if (count >= 0) {
|
||||||
|
for (int n = 0; n < count; n++) {
|
||||||
|
if (ret == -1 && proclist[n]->d_type == DT_DIR) {
|
||||||
|
pid_t pid = (pid_t)atoi(proclist[n]->d_name);
|
||||||
|
if (pid > 0) {
|
||||||
|
int cloned = cmp_fds(pid, drm_pth);
|
||||||
|
if (cloned > 0) {
|
||||||
|
ret = cloned;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(proclist[n]);
|
||||||
|
proclist[n] = NULL;
|
||||||
|
}
|
||||||
|
free(proclist);
|
||||||
|
proclist = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
perror("open /proc");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
5
drm_master.h
Normal file
5
drm_master.h
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "kmsvnc.h"
|
||||||
|
|
||||||
|
int drm_get_master_fd();
|
12
kmsvnc.h
12
kmsvnc.h
|
@ -85,9 +85,18 @@ struct kmsvnc_drm_funcs
|
||||||
void (*convert)(const char *, int, int, char *);
|
void (*convert)(const char *, int, int, char *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct kmsvnc_drm_gamma_data
|
||||||
|
{
|
||||||
|
uint32_t size;
|
||||||
|
uint16_t *red;
|
||||||
|
uint16_t *green;
|
||||||
|
uint16_t *blue;
|
||||||
|
};
|
||||||
|
|
||||||
struct kmsvnc_drm_data
|
struct kmsvnc_drm_data
|
||||||
{
|
{
|
||||||
int drm_fd;
|
int drm_fd;
|
||||||
|
int drm_master_fd;
|
||||||
drmVersionPtr drm_ver;
|
drmVersionPtr drm_ver;
|
||||||
int prime_fd;
|
int prime_fd;
|
||||||
drmModePlane *plane;
|
drmModePlane *plane;
|
||||||
|
@ -95,7 +104,7 @@ struct kmsvnc_drm_data
|
||||||
drmModePlaneRes *plane_res;
|
drmModePlaneRes *plane_res;
|
||||||
drmModeFB2 *mfb;
|
drmModeFB2 *mfb;
|
||||||
drmModeFB2 *cursor_mfb;
|
drmModeFB2 *cursor_mfb;
|
||||||
u_int32_t plane_id;
|
uint32_t plane_id;
|
||||||
int mmap_fd;
|
int mmap_fd;
|
||||||
size_t mmap_size;
|
size_t mmap_size;
|
||||||
off_t mmap_offset;
|
off_t mmap_offset;
|
||||||
|
@ -113,6 +122,7 @@ struct kmsvnc_drm_data
|
||||||
size_t kms_cpy_tmp_buf_len;
|
size_t kms_cpy_tmp_buf_len;
|
||||||
char *kms_cursor_buf;
|
char *kms_cursor_buf;
|
||||||
size_t kms_cursor_buf_len;
|
size_t kms_cursor_buf_len;
|
||||||
|
struct kmsvnc_drm_gamma_data *gamma;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kmsvnc_va_data
|
struct kmsvnc_va_data
|
||||||
|
|
Loading…
Reference in a new issue