Compare commits
12 commits
test-blank
...
master
Author | SHA1 | Date | |
---|---|---|---|
f6310cdc91 | |||
516ecb4121 | |||
0bcb73c48d | |||
19e048b56a | |||
0d40834b17 | |||
4ba2de050e | |||
c9b056a3f5 | |||
586d14e848 | |||
843d79cb64 | |||
035ae36dad | |||
6340351c3b | |||
3586a776a4 |
11 changed files with 491 additions and 115 deletions
21
.drone.yml
21
.drone.yml
|
@ -1,21 +0,0 @@
|
|||
kind: pipeline
|
||||
type: docker
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: archlinux:latest
|
||||
commands:
|
||||
- pacman -Syu --noconfirm --needed base-devel libvncserver libxkbcommon libdrm libva git cmake
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- make
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
- dev
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
27
.forgejo/workflows/default.yml
Normal file
27
.forgejo/workflows/default.yml
Normal file
|
@ -0,0 +1,27 @@
|
|||
name: Build with gcc + clang
|
||||
on:
|
||||
push:
|
||||
branches: [dev]
|
||||
jobs:
|
||||
build:
|
||||
if: "github.event_name != 'push' || !contains(github.event.head_commit.message, '[skip ci]')"
|
||||
runs-on: docker
|
||||
container:
|
||||
image: archlinux:latest
|
||||
env:
|
||||
CFLAGS: "-pipe -fno-plt -fexceptions -fstack-clash-protection -fcf-protection -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security"
|
||||
steps:
|
||||
- name: Prepare dependencies
|
||||
run: |
|
||||
pacman -Syu --noconfirm --needed nodejs git \
|
||||
base-devel libvncserver libxkbcommon libdrm libva cmake clang
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Build with gcc
|
||||
run: |
|
||||
CC=gcc cmake -B gcc-out
|
||||
cmake --build gcc-out
|
||||
- name: Build with clang
|
||||
run: |
|
||||
CC=clang cmake -B clang-out
|
||||
cmake --build clang-out
|
|
@ -13,13 +13,37 @@ pkg_search_module(XKBCOMMON REQUIRED xkbcommon)
|
|||
pkg_search_module(LIBVA REQUIRED libva)
|
||||
pkg_search_module(LIBVA_DRM REQUIRED libva-drm)
|
||||
|
||||
add_executable(kmsvnc)
|
||||
set(kmsvnc_SOURCES kmsvnc.c drm.c input.c keymap.c va.c drm_master.c)
|
||||
|
||||
include(CheckIncludeFiles)
|
||||
CHECK_INCLUDE_FILES("linux/uinput.h;linux/dma-buf.h" HAVE_LINUX_API_HEADERS)
|
||||
IF(NOT HAVE_LINUX_API_HEADERS)
|
||||
message(FATAL_ERROR "linux-api-headers not found")
|
||||
ENDIF()
|
||||
|
||||
add_executable(kmsvnc kmsvnc.c drm.c input.c keymap.c va.c)
|
||||
include(CheckSymbolExists)
|
||||
check_symbol_exists(SYS_pidfd_getfd "sys/syscall.h" HAVE_LIBC_SYS_pidfd_getfd)
|
||||
IF(NOT HAVE_LIBC_SYS_pidfd_getfd)
|
||||
message(WARNING "pidfd_getfd syscall not found, the --screen-blank options will be disabled")
|
||||
target_compile_options(kmsvnc PUBLIC -DDISABLE_KMSVNC_SCREEN_BLANK)
|
||||
list(REMOVE_ITEM kmsvnc_SOURCES drm_master.c)
|
||||
ENDIF()
|
||||
include(CMakePushCheckState)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_INCLUDES ${LIBDRM_INCLUDEDIR}/libdrm) # can't do anything about that
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${LIBDRM_LIBRARIES})
|
||||
check_symbol_exists(drmGetFormatName "xf86drm.h" HAVE_LIBDRM_drmGetFormatName)
|
||||
cmake_pop_check_state()
|
||||
IF(NOT HAVE_LIBDRM_drmGetFormatName)
|
||||
message(WARNING "drmGetFormatName not found, format name printing will be disabled")
|
||||
target_compile_options(kmsvnc PUBLIC -DDISABLE_KMSVNC_drmGetFormatName)
|
||||
ENDIF()
|
||||
|
||||
|
||||
target_sources(kmsvnc PUBLIC
|
||||
${kmsvnc_SOURCES}
|
||||
)
|
||||
target_include_directories(kmsvnc PUBLIC
|
||||
${LIBDRM_INCLUDEDIR}
|
||||
${LIBDRM_INCLUDEDIR}/libdrm
|
||||
|
|
159
drm.c
159
drm.c
|
@ -11,6 +11,25 @@
|
|||
#include "drm.h"
|
||||
#include "va.h"
|
||||
|
||||
#ifndef DISABLE_KMSVNC_SCREEN_BLANK
|
||||
#include "drm_master.h"
|
||||
#endif
|
||||
|
||||
#ifndef fourcc_mod_is_vendor
|
||||
#define fourcc_mod_is_vendor(modifier, vendor) \
|
||||
(fourcc_mod_get_vendor(modifier) == DRM_FORMAT_MOD_VENDOR_## vendor)
|
||||
#endif
|
||||
#ifdef DISABLE_KMSVNC_drmGetFormatName
|
||||
static char* drmGetFormatName(uint32_t data) {
|
||||
char *name = "missing drmGetFormatName";
|
||||
char *out = malloc(strlen(name)+1);
|
||||
if (out) {
|
||||
memcpy(out, name, strlen(name)+1);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern struct kmsvnc_data *kmsvnc;
|
||||
|
||||
static int check_pixfmt_non_vaapi() {
|
||||
|
@ -26,14 +45,18 @@ static int check_pixfmt_non_vaapi() {
|
|||
|
||||
static void convert_copy(const char *in, int width, int height, char *buff)
|
||||
{
|
||||
memcpy(buff, in, width * height * BYTES_PER_PIXEL);
|
||||
if (likely(in != buff)) {
|
||||
memcpy(buff, in, width * height * BYTES_PER_PIXEL);
|
||||
}
|
||||
}
|
||||
|
||||
static void convert_bgra_to_rgba(const char *in, int width, int height, char *buff)
|
||||
{
|
||||
memcpy(buff, in, width * height * BYTES_PER_PIXEL);
|
||||
if (likely(in != buff)) {
|
||||
memcpy(buff, in, width * height * BYTES_PER_PIXEL);
|
||||
}
|
||||
for (int i = 0; i < width * height * BYTES_PER_PIXEL; i += BYTES_PER_PIXEL) {
|
||||
uint32_t pixdata = htonl(*((uint32_t*)(kmsvnc->drm->kms_convert_buf + i)));
|
||||
uint32_t pixdata = htonl(*((uint32_t*)(buff + i)));
|
||||
buff[i+0] = (pixdata & 0x0000ff00) >> 8;
|
||||
buff[i+2] = (pixdata & 0xff000000) >> 24;
|
||||
}
|
||||
|
@ -96,39 +119,45 @@ void convert_intel_x_tiled_kmsbuf(const char *in, int width, int height, char *b
|
|||
}
|
||||
|
||||
static void convert_vaapi(const char *in, int width, int height, char *buff) {
|
||||
if (KMSVNC_FOURCC_TO_INT('R','G','B', 0) & kmsvnc->va->image->format.fourcc == KMSVNC_FOURCC_TO_INT('R','G','B', 0)) {
|
||||
va_hwframe_to_vaapi(buff);
|
||||
}
|
||||
va_hwframe_to_vaapi(buff);
|
||||
if (
|
||||
(KMSVNC_FOURCC_TO_INT('R','G','B',0) & kmsvnc->va->selected_fmt->fourcc) == KMSVNC_FOURCC_TO_INT('R','G','B',0)
|
||||
) {}
|
||||
else {
|
||||
if (convert_buf_allocate(width * height * BYTES_PER_PIXEL)) return;
|
||||
va_hwframe_to_vaapi(kmsvnc->drm->kms_convert_buf);
|
||||
// is 30 depth?
|
||||
if (kmsvnc->va->image->format.depth == 30) {
|
||||
if (kmsvnc->va->selected_fmt->depth == 30) {
|
||||
for (int i = 0; i < width * height * BYTES_PER_PIXEL; i += BYTES_PER_PIXEL) {
|
||||
// ensure little endianess
|
||||
uint32_t pixdata = __builtin_bswap32(htonl(*((uint32_t*)(kmsvnc->drm->kms_convert_buf + i))));
|
||||
kmsvnc->drm->kms_convert_buf[i] = (pixdata & 0x3ff00000) >> 20 >> 2;
|
||||
kmsvnc->drm->kms_convert_buf[i+1] = (pixdata & 0xffc00) >> 10 >> 2;
|
||||
kmsvnc->drm->kms_convert_buf[i+2] = (pixdata & 0x3ff) >> 2;
|
||||
uint32_t pixdata = __builtin_bswap32(htonl(*((uint32_t*)(buff + i))));
|
||||
buff[i] = (pixdata & 0x3ff00000) >> 20 >> 2;
|
||||
buff[i+1] = (pixdata & 0xffc00) >> 10 >> 2;
|
||||
buff[i+2] = (pixdata & 0x3ff) >> 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// actually, does anyone use this?
|
||||
if (!kmsvnc->va->selected_fmt->byte_order) {
|
||||
for (int i = 0; i < width * height * BYTES_PER_PIXEL; i += BYTES_PER_PIXEL) {
|
||||
uint32_t *pixdata = (uint32_t*)(buff + i);
|
||||
*pixdata = __builtin_bswap32(*pixdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
// is xrgb?
|
||||
if ((kmsvnc->va->image->format.blue_mask | kmsvnc->va->image->format.red_mask) < 0x1000000) {
|
||||
if ((kmsvnc->va->selected_fmt->blue_mask | kmsvnc->va->selected_fmt->red_mask) < 0x1000000) {
|
||||
for (int i = 0; i < width * height * BYTES_PER_PIXEL; i += BYTES_PER_PIXEL) {
|
||||
uint32_t *pixdata = (uint32_t*)(kmsvnc->drm->kms_convert_buf + i);
|
||||
uint32_t *pixdata = (uint32_t*)(buff + i);
|
||||
*pixdata = ntohl(htonl(*pixdata) << 8);
|
||||
}
|
||||
}
|
||||
// is bgrx?
|
||||
if (kmsvnc->va->image->format.blue_mask > kmsvnc->va->image->format.red_mask) {
|
||||
if (kmsvnc->va->selected_fmt->blue_mask > kmsvnc->va->selected_fmt->red_mask) {
|
||||
for (int i = 0; i < width * height * BYTES_PER_PIXEL; i += BYTES_PER_PIXEL) {
|
||||
uint32_t pixdata = htonl(*((uint32_t*)(kmsvnc->drm->kms_convert_buf + i)));
|
||||
uint32_t pixdata = htonl(*((uint32_t*)(buff + i)));
|
||||
buff[i+0] = (pixdata & 0x0000ff00) >> 8;
|
||||
buff[i+2] = (pixdata & 0xff000000) >> 24;
|
||||
}
|
||||
}
|
||||
// rgbx now
|
||||
memcpy(buff, kmsvnc->drm->kms_convert_buf, width * height * BYTES_PER_PIXEL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,6 +183,19 @@ void drm_sync_noop(int drmfd)
|
|||
|
||||
void drm_cleanup() {
|
||||
if (kmsvnc->drm) {
|
||||
#ifndef DISABLE_KMSVNC_SCREEN_BLANK
|
||||
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 && 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;
|
||||
}
|
||||
#endif
|
||||
if (kmsvnc->drm->drm_ver) {
|
||||
drmFreeVersion(kmsvnc->drm->drm_ver);
|
||||
kmsvnc->drm->drm_ver = NULL;
|
||||
|
@ -202,6 +244,10 @@ void drm_cleanup() {
|
|||
close(kmsvnc->drm->drm_fd);
|
||||
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) {
|
||||
drmModeFreePlaneResources(kmsvnc->drm->plane_res);
|
||||
kmsvnc->drm->plane_res = NULL;
|
||||
|
@ -458,6 +504,19 @@ int drm_open() {
|
|||
{
|
||||
KMSVNC_FATAL("card %s open failed: %s\n", kmsvnc->card, strerror(errno));
|
||||
}
|
||||
if (!kmsvnc->screen_blank && drmIsMaster(drm->drm_fd)) {
|
||||
if (drmDropMaster(drm->drm_fd)) fprintf(stderr, "Failed to drop master");
|
||||
}
|
||||
#ifndef DISABLE_KMSVNC_SCREEN_BLANK
|
||||
if (kmsvnc->screen_blank && !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);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
drm->drm_ver = drmGetVersion(drm->drm_fd);
|
||||
printf("drm driver is %s\n", drm->drm_ver->name);
|
||||
|
||||
|
@ -469,6 +528,68 @@ int drm_open() {
|
|||
|
||||
if (drm_refresh_planes(1)) return 1;
|
||||
|
||||
#ifndef DISABLE_KMSVNC_SCREEN_BLANK
|
||||
if (kmsvnc->screen_blank) {
|
||||
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) {
|
||||
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;
|
||||
if (kmsvnc->screen_blank_restore) {
|
||||
int step = 0x10000 / drm->gamma->size;
|
||||
for (int i = 0; i < drm->gamma->size; i++) {
|
||||
drm->gamma->red[i] = drm->gamma->green[i] = drm->gamma->blue[i] = step * i;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 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]);
|
||||
}
|
||||
}
|
||||
uint16_t *new_gamma_red = malloc(drm->gamma->size*sizeof(uint16_t)*3);
|
||||
if (!new_gamma_red) {
|
||||
fprintf(stderr, "memory allocation error at %s:%d\n", __FILE__, __LINE__);
|
||||
fprintf(stderr, "not setting gamma.\n");
|
||||
}
|
||||
else {
|
||||
memset(new_gamma_red, 0, drm->gamma->size*sizeof(uint16_t)*3);
|
||||
uint16_t *new_gamma_green = new_gamma_red + drm->gamma->size;
|
||||
uint16_t *new_gamma_blue = new_gamma_red + drm->gamma->size*2;
|
||||
if (drmModeCrtcSetGamma(drm->drm_master_fd ?: drm->drm_fd, drm->plane->crtc_id, drm->gamma->size, new_gamma_red, new_gamma_green, new_gamma_blue)) perror("Failed to set gamma");
|
||||
}
|
||||
if (new_gamma_red) {
|
||||
free(new_gamma_red);
|
||||
new_gamma_red = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Did not get a crtc structure, not setting gamma.\n");
|
||||
}
|
||||
if (target_crtc) {
|
||||
drmModeFreeCrtc(target_crtc);
|
||||
target_crtc = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
drm->mfb = drmModeGetFB2(drm->drm_fd, drm->plane->fb_id);
|
||||
if (!drm->mfb) {
|
||||
KMSVNC_FATAL("Failed to get framebuffer %u: %s\n", drm->plane->fb_id, strerror(errno));
|
||||
|
|
6
drm.h
6
drm.h
|
@ -2,9 +2,9 @@
|
|||
|
||||
#include "kmsvnc.h"
|
||||
|
||||
#define DRM_IOCTL_MUST(...) do{ int e; if (e = drmIoctl(__VA_ARGS__)) KMSVNC_FATAL("DRM ioctl error %d on line %d\n", e, __LINE__); } while(0)
|
||||
#define DRM_IOCTL_MAY(...) do{ int e; if (e = drmIoctl(__VA_ARGS__)) fprintf(stderr, "DRM ioctl error %d on line %d\n", e, __LINE__); } while(0)
|
||||
#define DRM_R_IOCTL_MAY(...) do{ int e; if (e = ioctl(__VA_ARGS__)) fprintf(stderr, "DRM ioctl error %d on line %d\n", e, __LINE__); } while(0)
|
||||
#define DRM_IOCTL_MUST(...) do{ int e; if ((e = drmIoctl(__VA_ARGS__))) KMSVNC_FATAL("DRM ioctl error %d on line %d\n", e, __LINE__); } while(0)
|
||||
#define DRM_IOCTL_MAY(...) do{ int e; if ((e = drmIoctl(__VA_ARGS__))) fprintf(stderr, "DRM ioctl error %d on line %d\n", e, __LINE__); } while(0)
|
||||
#define DRM_R_IOCTL_MAY(...) do{ int e; if ((e = ioctl(__VA_ARGS__))) fprintf(stderr, "DRM ioctl error %d on line %d\n", e, __LINE__); } while(0)
|
||||
|
||||
|
||||
void drm_cleanup();
|
||||
|
|
110
drm_master.c
Normal file
110
drm_master.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
#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) {
|
||||
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];
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#pragma GCC diagnostic ignored "-Wunknown-warning-option"
|
||||
#pragma GCC diagnostic ignored "-Wformat-truncation"
|
||||
snprintf(link_pth, PATH_MAX+1, "%s/%s", path, fdlist[n]->d_name);
|
||||
#pragma GCC diagnostic pop
|
||||
memset(real_pth, 0, PATH_MAX+1);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
realpath(link_pth, real_pth);
|
||||
#pragma GCC diagnostic pop
|
||||
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 && drmIsMaster(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);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
realpath(kmsvnc->card, drm_pth);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
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();
|
4
input.h
4
input.h
|
@ -7,8 +7,8 @@
|
|||
#define UINPUT_ABS_MAX INT16_MAX
|
||||
#define UINPUT_MAX_KEY 256
|
||||
|
||||
#define INP_IOCTL_MUST(...) do{ int e; if (e = ioctl(__VA_ARGS__)) KMSVNC_FATAL("uinput ioctl error %d on line %d\n", e, __LINE__); } while(0)
|
||||
#define INP_IOCTL_MAY(...) do{ int e; if (e = ioctl(__VA_ARGS__)) fprintf(stderr, "uinput ioctl error %d on line %d\n", e, __LINE__); } while(0)
|
||||
#define INP_IOCTL_MUST(...) do{ int e; if ((e = ioctl(__VA_ARGS__))) KMSVNC_FATAL("uinput ioctl error %d on line %d\n", e, __LINE__); } while(0)
|
||||
#define INP_IOCTL_MAY(...) do{ int e; if ((e = ioctl(__VA_ARGS__))) fprintf(stderr, "uinput ioctl error %d on line %d\n", e, __LINE__); } while(0)
|
||||
|
||||
void uinput_cleanup();
|
||||
int uinput_init();
|
||||
|
|
113
kmsvnc.c
113
kmsvnc.c
|
@ -1,9 +1,12 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <argp.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
@ -127,7 +130,7 @@ static inline void update_vnc_cursor(char *data, int width, int height) {
|
|||
if (!kmsvnc->cursor_bitmap) return;
|
||||
kmsvnc->cursor_bitmap_len = rwidth * rheight * BYTES_PER_PIXEL;
|
||||
}
|
||||
char *rich_source = malloc(rwidth * rheight * BYTES_PER_PIXEL);
|
||||
unsigned char *rich_source = malloc(rwidth * rheight * BYTES_PER_PIXEL);
|
||||
if (!rich_source) return;
|
||||
char *maskString = malloc(rwidth * rheight);
|
||||
if (!maskString) {
|
||||
|
@ -208,6 +211,7 @@ static void cleanup() {
|
|||
}
|
||||
}
|
||||
|
||||
void signal_handler_noop(int signum){}
|
||||
void signal_handler(int signum){
|
||||
if (kmsvnc->shutdown) {
|
||||
return;
|
||||
|
@ -219,7 +223,7 @@ void signal_handler(int signum){
|
|||
}
|
||||
|
||||
static struct argp_option kmsvnc_main_options[] = {
|
||||
{"device", 'd', "/dev/dri/card0", 0, "DRM device"},
|
||||
{"device", 'd', "/dev/dri/cardX", 0, "DRM device"},
|
||||
{"source-plane", 0xfefc, "0", 0, "Use specific plane"},
|
||||
{"source-crtc", 0xfefd, "0", 0, "Use specific crtc (to list all crtcs and planes, set this to -1)"},
|
||||
{"force-driver", 0xfefe, "i915", 0, "force a certain driver (for debugging)"},
|
||||
|
@ -238,6 +242,11 @@ static struct argp_option kmsvnc_main_options[] = {
|
|||
{"input-height", 0xff07, "0", 0, "Explicitly set input height"},
|
||||
{"input-offx", 0xff08, "0", 0, "Set input offset of x axis on a multi display system"},
|
||||
{"input-offy", 0xff09, "0", 0, "Set input offset of y axis on a multi display system"},
|
||||
#ifndef DISABLE_KMSVNC_SCREEN_BLANK
|
||||
{"screen-blank", 0xff0a, 0, OPTION_ARG_OPTIONAL, "Blank screen with gamma set on crtc"},
|
||||
{"screen-blank-restore-linear", 0xff0b, 0, OPTION_ARG_OPTIONAL, "Restore linear values on exit in case of messed up gamma"},
|
||||
#endif
|
||||
{"va-byteorder-swap", 0xff0c, 0, OPTION_ARG_OPTIONAL, "Force swap vaapi image rgb byteorder"},
|
||||
{"wakeup", 'w', 0, OPTION_ARG_OPTIONAL, "Move mouse to wake the system up before start"},
|
||||
{"disable-input", 'i', 0, OPTION_ARG_OPTIONAL, "Disable uinput"},
|
||||
{"desktop-name", 'n', "kmsvnc", 0, "Specify vnc desktop name"},
|
||||
|
@ -269,24 +278,28 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
|||
kmsvnc->vnc_opt->bind6 = arg;
|
||||
break;
|
||||
case 'p':
|
||||
int port = atoi(arg);
|
||||
if (port > 0 && port < 65536) {
|
||||
kmsvnc->vnc_opt->port = port;
|
||||
}
|
||||
else {
|
||||
argp_error(state, "invalid port %s", arg);
|
||||
{
|
||||
int port = atoi(arg);
|
||||
if (port > 0 && port < 65536) {
|
||||
kmsvnc->vnc_opt->port = port;
|
||||
}
|
||||
else {
|
||||
argp_error(state, "invalid port %s", arg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '4':
|
||||
kmsvnc->vnc_opt->disable_ipv6 = 1;
|
||||
break;
|
||||
case 0xff00:
|
||||
int fps = atoi(arg);
|
||||
if (fps > 0 && fps < 1000) {
|
||||
kmsvnc->vnc_opt->sleep_ns = NS_IN_S / fps;
|
||||
}
|
||||
else {
|
||||
argp_error(state, "invalid fps %s", arg);
|
||||
{
|
||||
int fps = atoi(arg);
|
||||
if (fps > 0 && fps < 1000) {
|
||||
kmsvnc->vnc_opt->sleep_ns = NS_IN_S / fps;
|
||||
}
|
||||
else {
|
||||
argp_error(state, "invalid fps %s", arg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xff01:
|
||||
|
@ -314,29 +327,46 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
|||
kmsvnc->debug_enabled = 1;
|
||||
break;
|
||||
case 0xff06:
|
||||
int width = atoi(arg);
|
||||
if (width > 0) {
|
||||
kmsvnc->input_width = width;
|
||||
{
|
||||
int width = atoi(arg);
|
||||
if (width > 0) {
|
||||
kmsvnc->input_width = width;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xff07:
|
||||
int height = atoi(arg);
|
||||
if (height > 0) {
|
||||
kmsvnc->input_height = height;
|
||||
{
|
||||
int height = atoi(arg);
|
||||
if (height > 0) {
|
||||
kmsvnc->input_height = height;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xff08:
|
||||
int offset_x = atoi(arg);
|
||||
if (offset_x > 0) {
|
||||
kmsvnc->input_offx = offset_x;
|
||||
{
|
||||
int offset_x = atoi(arg);
|
||||
if (offset_x > 0) {
|
||||
kmsvnc->input_offx = offset_x;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xff09:
|
||||
int offset_y = atoi(arg);
|
||||
if (offset_y > 0) {
|
||||
kmsvnc->input_offy = offset_y;
|
||||
{
|
||||
int offset_y = atoi(arg);
|
||||
if (offset_y > 0) {
|
||||
kmsvnc->input_offy = offset_y;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xff0a:
|
||||
kmsvnc->screen_blank = 1;
|
||||
break;
|
||||
case 0xff0b:
|
||||
kmsvnc->screen_blank_restore = 1;
|
||||
break;
|
||||
case 0xff0c:
|
||||
kmsvnc->va_byteorder_swap = 1;
|
||||
break;
|
||||
case 'w':
|
||||
kmsvnc->input_wakeup = 1;
|
||||
break;
|
||||
|
@ -369,7 +399,10 @@ int main(int argc, char **argv)
|
|||
|
||||
kmsvnc->vnc_opt = vncopt;
|
||||
|
||||
kmsvnc->card = "/dev/dri/card0";
|
||||
#define DEVICE_EXAMPLE_MAX_SIZE 15
|
||||
#define DEVICE_EXAMPLE_FALLBACK "/dev/dri/card0"
|
||||
static char device_example[DEVICE_EXAMPLE_MAX_SIZE] = DEVICE_EXAMPLE_FALLBACK;
|
||||
kmsvnc->card = device_example;
|
||||
kmsvnc->va_derive_enabled = -1;
|
||||
kmsvnc->vnc_opt->bind = &(struct in_addr){0};
|
||||
kmsvnc->vnc_opt->always_shared = 1;
|
||||
|
@ -383,6 +416,18 @@ int main(int argc, char **argv)
|
|||
struct argp argp = {kmsvnc_main_options, parse_opt, args_doc, doc};
|
||||
argp_parse(&argp, argc, argv, 0, 0, NULL);
|
||||
|
||||
if (kmsvnc->card == device_example) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
snprintf(kmsvnc->card, DEVICE_EXAMPLE_MAX_SIZE, "/dev/dri/card%d", i);
|
||||
if (!access(kmsvnc->card, F_OK)) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
snprintf(kmsvnc->card, DEVICE_EXAMPLE_MAX_SIZE, DEVICE_EXAMPLE_FALLBACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!kmsvnc->disable_input) {
|
||||
const char* XKB_DEFAULT_LAYOUT = getenv("XKB_DEFAULT_LAYOUT");
|
||||
if (!XKB_DEFAULT_LAYOUT || strcmp(XKB_DEFAULT_LAYOUT, "") == 0) {
|
||||
|
@ -429,6 +474,20 @@ int main(int argc, char **argv)
|
|||
else {
|
||||
fprintf(stderr, "open file %s failed, %s\n", kmsvnc->debug_capture_fb, strerror(errno));
|
||||
}
|
||||
if (kmsvnc->screen_blank) {
|
||||
sigset_t signal_set;
|
||||
int sig;
|
||||
sigemptyset(&signal_set);
|
||||
signal(SIGHUP, &signal_handler_noop);
|
||||
signal(SIGINT, &signal_handler_noop);
|
||||
signal(SIGTERM, &signal_handler_noop);
|
||||
sigaddset(&signal_set, SIGHUP);
|
||||
sigaddset(&signal_set, SIGINT);
|
||||
sigaddset(&signal_set, SIGTERM);
|
||||
fprintf(stderr, "blanking screen...\n");
|
||||
sigwait(&signal_set, &sig);
|
||||
fprintf(stderr, "got sig %d\n", sig);
|
||||
}
|
||||
cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
|
21
kmsvnc.h
21
kmsvnc.h
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
#include <stdint.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
@ -42,6 +43,9 @@ struct kmsvnc_data
|
|||
int input_height;
|
||||
int input_offx;
|
||||
int input_offy;
|
||||
char screen_blank;
|
||||
char screen_blank_restore;
|
||||
char va_byteorder_swap;
|
||||
struct kmsvnc_drm_data *drm;
|
||||
struct kmsvnc_input_data *input;
|
||||
struct kmsvnc_keymap_data *keymap;
|
||||
|
@ -85,9 +89,18 @@ struct kmsvnc_drm_funcs
|
|||
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
|
||||
{
|
||||
int drm_fd;
|
||||
int drm_master_fd;
|
||||
drmVersionPtr drm_ver;
|
||||
int prime_fd;
|
||||
drmModePlane *plane;
|
||||
|
@ -95,7 +108,7 @@ struct kmsvnc_drm_data
|
|||
drmModePlaneRes *plane_res;
|
||||
drmModeFB2 *mfb;
|
||||
drmModeFB2 *cursor_mfb;
|
||||
u_int32_t plane_id;
|
||||
uint32_t plane_id;
|
||||
int mmap_fd;
|
||||
size_t mmap_size;
|
||||
off_t mmap_offset;
|
||||
|
@ -113,6 +126,7 @@ struct kmsvnc_drm_data
|
|||
size_t kms_cpy_tmp_buf_len;
|
||||
char *kms_cursor_buf;
|
||||
size_t kms_cursor_buf_len;
|
||||
struct kmsvnc_drm_gamma_data *gamma;
|
||||
};
|
||||
|
||||
struct kmsvnc_va_data
|
||||
|
@ -125,6 +139,8 @@ struct kmsvnc_va_data
|
|||
char derive_enabled;
|
||||
VAImageFormat* img_fmts;
|
||||
int img_fmt_count;
|
||||
VAImageFormat* selected_fmt;
|
||||
const char *vendor_string;
|
||||
};
|
||||
|
||||
#define KMSVNC_FATAL(...) do{ fprintf(stderr, __VA_ARGS__); return 1; } while(0)
|
||||
|
@ -133,3 +149,6 @@ struct kmsvnc_va_data
|
|||
#define KMSVNC_WRITE_MAY(fd,buf,count) do { ssize_t e = write((fd), (buf), (count)); if (e != (count)) fprintf(stderr, "should write %ld bytes, actually wrote %ld, on line %d\n", (count), e, __LINE__); } while (0)
|
||||
|
||||
#define KMSVNC_DEBUG(...) do{ if (kmsvnc->debug_enabled) fprintf(stdout, __VA_ARGS__); } while(0)
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
|
|
114
va.c
114
va.c
|
@ -1,6 +1,12 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <va/va.h>
|
||||
#include <va/va_drm.h>
|
||||
#include <va/va_drmcommon.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "va.h"
|
||||
#include "kmsvnc.h"
|
||||
|
@ -33,6 +39,9 @@ void va_cleanup() {
|
|||
VA_MAY(vaTerminate(kmsvnc->va->dpy));
|
||||
kmsvnc->va->dpy = NULL;
|
||||
}
|
||||
if (kmsvnc->va->vendor_string) {
|
||||
kmsvnc->va->vendor_string = NULL;
|
||||
}
|
||||
free(kmsvnc->va);
|
||||
kmsvnc->va = NULL;
|
||||
}
|
||||
|
@ -69,20 +78,41 @@ static const struct {
|
|||
{KMSVNC_FOURCC_TO_INT('A', 'R', '3', '0'), KMSVNC_FOURCC_TO_INT('A', 'R', '3', '0'), VA_RT_FORMAT_RGB32_10, 1},
|
||||
};
|
||||
|
||||
struct va_fmt_data {
|
||||
uint32_t va_fourcc;
|
||||
VAImageFormat *fmt;
|
||||
char is_alpha;
|
||||
uint32_t va_rt_format;
|
||||
uint32_t depth;
|
||||
};
|
||||
|
||||
static VAImageFormat* vaImgFmt_apply_quirks(struct va_fmt_data* data) {
|
||||
static VAImageFormat ret = {0};
|
||||
memcpy(&ret, data->fmt, sizeof(VAImageFormat));
|
||||
if ((kmsvnc->va_byteorder_swap ^ !strncmp(kmsvnc->va->vendor_string, "Mesa", 4)) && data->depth != 30) {
|
||||
printf("applying rgb mask byte order swap\n");
|
||||
ret.blue_mask = __builtin_bswap32(data->fmt->blue_mask);
|
||||
ret.green_mask = __builtin_bswap32(data->fmt->green_mask);
|
||||
ret.red_mask = __builtin_bswap32(data->fmt->red_mask);
|
||||
}
|
||||
return &ret;
|
||||
}
|
||||
|
||||
static void print_va_image_fmt(VAImageFormat *fmt) {
|
||||
printf("image fmt: fourcc %d, %s, byte_order %s, bpp %d, depth %d, blue_mask %#x, green_mask %#x, red_mask %#x, reserved %#x %#x %#x %#x\n", fmt->fourcc,
|
||||
fourcc_to_str(fmt->fourcc),
|
||||
fmt->byte_order == 1 ? "VA_LSB_FIRST" : "VA_MSB_FIRST",
|
||||
fmt->bits_per_pixel,
|
||||
fmt->depth,
|
||||
fmt->blue_mask,
|
||||
fmt->green_mask,
|
||||
fmt->red_mask,
|
||||
fmt->va_reserved[0],
|
||||
fmt->va_reserved[1],
|
||||
fmt->va_reserved[2],
|
||||
fmt->va_reserved[3]
|
||||
);
|
||||
printf("image fmt: fourcc %d, %s, byte_order %s, bpp %d, depth %d, blue_mask %#x, green_mask %#x, red_mask %#x, alpha_mask %#x, reserved %#x %#x %#x %#x\n", fmt->fourcc,
|
||||
fourcc_to_str(fmt->fourcc),
|
||||
fmt->byte_order == 1 ? "VA_LSB_FIRST" : "VA_MSB_FIRST",
|
||||
fmt->bits_per_pixel,
|
||||
fmt->depth,
|
||||
fmt->blue_mask,
|
||||
fmt->green_mask,
|
||||
fmt->red_mask,
|
||||
fmt->alpha_mask,
|
||||
fmt->va_reserved[0],
|
||||
fmt->va_reserved[1],
|
||||
fmt->va_reserved[2],
|
||||
fmt->va_reserved[3]
|
||||
);
|
||||
}
|
||||
|
||||
int va_init() {
|
||||
|
@ -91,6 +121,7 @@ int va_init() {
|
|||
}
|
||||
|
||||
setenv("DISPLAY", "", 1);
|
||||
setenv("WAYLAND_DISPLAY", "", 1);
|
||||
|
||||
struct kmsvnc_va_data *va = malloc(sizeof(struct kmsvnc_va_data));
|
||||
if (!va) KMSVNC_FATAL("memory allocation error at %s:%d\n", __FILE__, __LINE__);
|
||||
|
@ -99,7 +130,7 @@ int va_init() {
|
|||
|
||||
char* render_node;
|
||||
int effective_fd = 0;
|
||||
if (render_node = drmGetRenderDeviceNameFromFd(kmsvnc->drm->drm_fd)) {
|
||||
if ((render_node = drmGetRenderDeviceNameFromFd(kmsvnc->drm->drm_fd))) {
|
||||
va->render_node_fd = open(render_node, O_RDWR);
|
||||
free(render_node);
|
||||
}
|
||||
|
@ -126,8 +157,8 @@ int va_init() {
|
|||
VAStatus status;
|
||||
VA_MUST(vaInitialize(va->dpy, &major, &minor));
|
||||
|
||||
const char *vendor_string = vaQueryVendorString(va->dpy);
|
||||
printf("vaapi vendor %s\n", vendor_string);
|
||||
va->vendor_string = vaQueryVendorString(va->dpy);
|
||||
printf("vaapi vendor %s\n", va->vendor_string);
|
||||
|
||||
VADRMPRIMESurfaceDescriptor prime_desc;
|
||||
VASurfaceAttrib prime_attrs[2] = {
|
||||
|
@ -255,28 +286,26 @@ int va_init() {
|
|||
}
|
||||
}
|
||||
|
||||
struct fourcc_data {
|
||||
uint32_t va_fourcc;
|
||||
VAImageFormat *fmt;
|
||||
char is_alpha;
|
||||
uint32_t va_rt_format;
|
||||
};
|
||||
struct fourcc_data format_to_try[] = {
|
||||
{KMSVNC_FOURCC_TO_INT('R','G','B','X'), NULL, 0, VA_RT_FORMAT_RGB32},
|
||||
{KMSVNC_FOURCC_TO_INT('R','G','B','A'), NULL, 1, VA_RT_FORMAT_RGB32},
|
||||
{KMSVNC_FOURCC_TO_INT('X','R','G','B'), NULL, 0, VA_RT_FORMAT_RGB32},
|
||||
{KMSVNC_FOURCC_TO_INT('A','R','G','B'), NULL, 1, VA_RT_FORMAT_RGB32},
|
||||
struct va_fmt_data format_to_try[] = {
|
||||
{KMSVNC_FOURCC_TO_INT('R','G','B','X'), NULL, 0, VA_RT_FORMAT_RGB32, 24},
|
||||
{KMSVNC_FOURCC_TO_INT('R','G','B','A'), NULL, 1, VA_RT_FORMAT_RGB32, 32},
|
||||
|
||||
{KMSVNC_FOURCC_TO_INT('B','G','R','X'), NULL, 0, VA_RT_FORMAT_RGB32},
|
||||
{KMSVNC_FOURCC_TO_INT('B','G','R','A'), NULL, 1, VA_RT_FORMAT_RGB32},
|
||||
{KMSVNC_FOURCC_TO_INT('X','B','G','R'), NULL, 0, VA_RT_FORMAT_RGB32},
|
||||
{KMSVNC_FOURCC_TO_INT('A','B','G','R'), NULL, 1, VA_RT_FORMAT_RGB32},
|
||||
{KMSVNC_FOURCC_TO_INT('X','B','G','R'), NULL, 0, VA_RT_FORMAT_RGB32, 24},
|
||||
{KMSVNC_FOURCC_TO_INT('A','B','G','R'), NULL, 1, VA_RT_FORMAT_RGB32, 32},
|
||||
|
||||
{KMSVNC_FOURCC_TO_INT('X','R','3','0'), NULL, 0, VA_RT_FORMAT_RGB32_10},
|
||||
{KMSVNC_FOURCC_TO_INT('A','R','3','0'), NULL, 1, VA_RT_FORMAT_RGB32_10},
|
||||
{KMSVNC_FOURCC_TO_INT('X','B','3','0'), NULL, 0, VA_RT_FORMAT_RGB32_10},
|
||||
{KMSVNC_FOURCC_TO_INT('A','B','3','0'), NULL, 1, VA_RT_FORMAT_RGB32_10},
|
||||
{KMSVNC_FOURCC_TO_INT('X','R','G','B'), NULL, 0, VA_RT_FORMAT_RGB32, 24},
|
||||
{KMSVNC_FOURCC_TO_INT('A','R','G','B'), NULL, 1, VA_RT_FORMAT_RGB32, 32},
|
||||
|
||||
{KMSVNC_FOURCC_TO_INT('B','G','R','X'), NULL, 0, VA_RT_FORMAT_RGB32, 24},
|
||||
{KMSVNC_FOURCC_TO_INT('B','G','R','A'), NULL, 1, VA_RT_FORMAT_RGB32, 32},
|
||||
|
||||
|
||||
{KMSVNC_FOURCC_TO_INT('X','R','3','0'), NULL, 0, VA_RT_FORMAT_RGB32_10, 30},
|
||||
{KMSVNC_FOURCC_TO_INT('A','R','3','0'), NULL, 1, VA_RT_FORMAT_RGB32_10, 30},
|
||||
{KMSVNC_FOURCC_TO_INT('X','B','3','0'), NULL, 0, VA_RT_FORMAT_RGB32_10, 30},
|
||||
{KMSVNC_FOURCC_TO_INT('A','B','3','0'), NULL, 1, VA_RT_FORMAT_RGB32_10, 30},
|
||||
};
|
||||
|
||||
for (int i = 0; i < va->img_fmt_count; i++) {
|
||||
for (int j = 0; j < KMSVNC_ARRAY_ELEMENTS(format_to_try); j++) {
|
||||
if (va->img_fmts[i].fourcc == format_to_try[j].va_fourcc) {
|
||||
|
@ -292,14 +321,14 @@ int va_init() {
|
|||
va->derive_enabled = kmsvnc->va_derive_enabled < 0 ? va->derive_enabled : kmsvnc->va_derive_enabled != 0;
|
||||
if (va->derive_enabled) {
|
||||
if ((s = vaDeriveImage(va->dpy, va->surface_id, va->image)) == VA_STATUS_SUCCESS) {
|
||||
char found = 0;
|
||||
for (int i = 0; i < KMSVNC_ARRAY_ELEMENTS(format_to_try); i++) {
|
||||
if (format_to_try[i].fmt == NULL) continue;
|
||||
if (va->image->format.fourcc == format_to_try[i].fmt->fourcc) {
|
||||
found = 1;
|
||||
va->selected_fmt = vaImgFmt_apply_quirks(format_to_try + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (!va->selected_fmt) {
|
||||
va->derive_enabled = 0;
|
||||
printf("vaDeriveImage returned unknown fourcc %d %s\n", va->image->format.fourcc, fourcc_to_str(va->image->format.fourcc));
|
||||
VA_MAY(vaDestroyImage(kmsvnc->va->dpy, kmsvnc->va->image->image_id));
|
||||
|
@ -315,7 +344,6 @@ int va_init() {
|
|||
}
|
||||
}
|
||||
if (!va->derive_enabled) {
|
||||
char success = 0;
|
||||
for (int i = 0; i < KMSVNC_ARRAY_ELEMENTS(format_to_try); i++) {
|
||||
if (format_to_try[i].fmt == NULL) continue;
|
||||
if (!kmsvnc->debug_enabled && rt_format != format_to_try[i].va_rt_format) continue;
|
||||
|
@ -341,17 +369,21 @@ int va_init() {
|
|||
continue;
|
||||
}
|
||||
else {
|
||||
success = 1;
|
||||
va->selected_fmt = vaImgFmt_apply_quirks(format_to_try + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
if (!va->selected_fmt) {
|
||||
va->imgbuf = NULL;
|
||||
KMSVNC_FATAL("failed to get vaapi image\n");
|
||||
}
|
||||
}
|
||||
printf("got vaapi %simage:\n", va->derive_enabled ? "derive " : "");
|
||||
print_va_image_fmt(&va->image->format);
|
||||
if (kmsvnc->debug_enabled) {
|
||||
fprintf(stderr, "selected image format:\n");
|
||||
print_va_image_fmt(va->selected_fmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue