This commit is contained in:
JerryXiao 2023-04-25 20:50:52 +08:00
parent 642b1f9903
commit 00d252c958
Signed by: Jerry
GPG key ID: 22618F758B5BE2E5

View file

@ -13,6 +13,17 @@
#include <math.h> #include <math.h>
struct drm_nvidia_gem_map_offset_params {
uint32_t handle; /* IN Handle to gem object */
uint32_t __pad;
uint64_t offset; /* OUT Fake offset */
};
#define DRM_NVIDIA_GEM_MAP_OFFSET 0x0a
#define DRM_IOCTL_NVIDIA_GEM_MAP_OFFSET \
DRM_IOWR((DRM_COMMAND_BASE + DRM_NVIDIA_GEM_MAP_OFFSET), \
struct drm_nvidia_gem_map_offset_params)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
/* 10 frames per second (if we can) */ /* 10 frames per second (if we can) */
#define PICTURE_TIMEOUT (1.0/10.0) #define PICTURE_TIMEOUT (1.0/10.0)
@ -55,6 +66,30 @@ static void convert_bgrx_to_rgb(const char* in, int width, int height, char* buf
} }
} }
#define XSTRIPE 16
#define YSTRIPE 128
char *nv_stripe_buf = NULL;
static void convert_nv_stripe(const char* in, int width, int height, char* buff) {
if (width % XSTRIPE) {
return;
}
if (!nv_stripe_buf) nv_stripe_buf = malloc(width * height * 4);
convert_bgrx_to_rgb(in, width, height, nv_stripe_buf);
for (int i = 0; i < height*width; i++)
{
int sno = i / (XSTRIPE * YSTRIPE);
int ord = i % (XSTRIPE * YSTRIPE);
int base_x = sno % (width / XSTRIPE) * XSTRIPE;
int base_y = sno / (width / XSTRIPE) * YSTRIPE;
int sx = ord % XSTRIPE + base_x;
int sy = ord / XSTRIPE + base_y;
int offset = sy * width + sx;
if (offset < height*width) {
memcpy(buff + offset*4, nv_stripe_buf + i*4, 4);
}
}
}
struct vnc_xkb { struct vnc_xkb {
struct xkb_context *ctx; struct xkb_context *ctx;
struct xkb_keymap *map; struct xkb_keymap *map;
@ -258,6 +293,8 @@ static void rfb_ptr_hook(int mask, int screen_x, int screen_y, rfbClientPtr cl)
} }
static void drm_wait_vblank_noop(int x) {
}
static void drm_wait_vblank(int drmfd) { static void drm_wait_vblank(int drmfd) {
int ioctl_err; int ioctl_err;
union drm_wait_vblank vbl; union drm_wait_vblank vbl;
@ -373,6 +410,8 @@ int main(int argc, const char **argv)
size_t mmap_size = 0; size_t mmap_size = 0;
printf("drm driver is %s\n", drm_ver->name); printf("drm driver is %s\n", drm_ver->name);
char *mapped = NULL; char *mapped = NULL;
void (*convert_func)(const char*, int, int, char*) = &convert_bgrx_to_rgb;
void (*vblank_func)(int) = &drm_wait_vblank;
if (strcmp(drm_ver->name, "i915") == 0) { if (strcmp(drm_ver->name, "i915") == 0) {
struct drm_i915_gem_mmap_gtt mmap_arg; struct drm_i915_gem_mmap_gtt mmap_arg;
mmap_arg.handle = open_arg.handle; mmap_arg.handle = open_arg.handle;
@ -394,16 +433,18 @@ int main(int argc, const char **argv)
mmap_size = open_arg.size; mmap_size = open_arg.size;
mmap_offset = mmap_arg.out.addr_ptr; mmap_offset = mmap_arg.out.addr_ptr;
} }
else if (strcmp(drm_ver->name, "nothing") == 0) { else if (strcmp(drm_ver->name, "nvidia-drm") == 0) {
struct drm_mode_map_dumb mreq; convert_func = &convert_nv_stripe;
memset(&mreq, 0, sizeof(mreq)); vblank_func = &drm_wait_vblank_noop;
mreq.handle = open_arg.handle; struct drm_nvidia_gem_map_offset_params mmap_arg;
if (ioctl_err = drmIoctl(drmfd, DRM_IOCTL_MODE_MAP_DUMB, &mreq)) { memset(&mmap_arg, 0, sizeof(mmap_arg));
mmap_arg.handle = open_arg.handle;
if (ioctl_err = drmIoctl(drmfd, DRM_IOCTL_NVIDIA_GEM_MAP_OFFSET, &mmap_arg)) {
fprintf(stderr, "DRM ioctl error %d on line %d\n", ioctl_err, __LINE__); fprintf(stderr, "DRM ioctl error %d on line %d\n", ioctl_err, __LINE__);
goto cleanup; goto cleanup;
} }
mmap_size = open_arg.size; mmap_size = open_arg.size;
mmap_offset = mreq.offset; mmap_offset = mmap_arg.offset;
} }
else { else {
fprintf(stderr, "Unimplemented drm driver\n"); fprintf(stderr, "Unimplemented drm driver\n");
@ -442,10 +483,10 @@ int main(int argc, const char **argv)
long usec; long usec;
while (rfbIsActive(server)) { while (rfbIsActive(server)) {
if (server->clientHead && TimeToTakePicture()) { if (server->clientHead && TimeToTakePicture()) {
drm_wait_vblank(drmfd); vblank_func(drmfd);
// still tearing // still tearing
memcpy(buf2, mapped, buflen); memcpy(buf2, mapped, buflen);
convert_bgrx_to_rgb(buf2, fb->width, fb->height, buf); convert_func(buf2, fb->width, fb->height, buf);
rfbMarkRectAsModified(server, 0, 0, fb->width, fb->height); rfbMarkRectAsModified(server, 0, 0, fb->width, fb->height);
} }
usec = server->deferUpdateTime*1000; usec = server->deferUpdateTime*1000;