diff --git a/server.c b/server.c index 02e33f8..c373216 100644 --- a/server.c +++ b/server.c @@ -62,10 +62,24 @@ static void convert_bgrx_to_rgb(const char* in, int width, int height, char* buf char *kms_convert_buf = NULL; size_t kms_convert_buf_len = 0; +char *kms_cpy_tmp_buf = NULL; +size_t kms_cpy_tmp_buf_len = 0; static inline void convert_kmsbuf(const int XSTRIPE, const int YSTRIPE, const char* in, int width, int height, char* buff) { if (width % XSTRIPE) { return; } + if (height % YSTRIPE) { + int sno = (width / XSTRIPE) + (height / YSTRIPE) * (width / XSTRIPE); + int ord = (width % XSTRIPE) + (height % YSTRIPE) * XSTRIPE; + int max_offset = sno * XSTRIPE * YSTRIPE + ord; + if (kms_cpy_tmp_buf_len < max_offset*4+4) { + if (kms_cpy_tmp_buf) free(kms_convert_buf); + kms_cpy_tmp_buf = malloc(max_offset*4+4); + kms_cpy_tmp_buf_len = max_offset*4+4; + } + memcpy(kms_cpy_tmp_buf, in, max_offset*4+4); + in = (const char*) kms_cpy_tmp_buf; + } if (kms_convert_buf_len < width * height * 4) { if (kms_convert_buf) free(kms_convert_buf); kms_convert_buf = malloc(width * height * 4); @@ -77,9 +91,7 @@ static inline void convert_kmsbuf(const int XSTRIPE, const int YSTRIPE, const ch int sno = (x / XSTRIPE) + (y / YSTRIPE) * (width / XSTRIPE); int ord = (x % XSTRIPE) + (y % YSTRIPE) * XSTRIPE; int offset = sno * XSTRIPE * YSTRIPE + ord; - if (offset < height*width) { - memcpy(kms_convert_buf + (x+y*width)*4, in + offset*4, 4); - } + memcpy(kms_convert_buf + (x+y*width)*4, in + offset*4, 4); } } convert_bgrx_to_rgb(kms_convert_buf, width, height, buff); @@ -89,6 +101,7 @@ static inline void convert_kmsbuf(const int XSTRIPE, const int YSTRIPE, const ch #define YSTRIPE_INTEL 8 #define XSTRIPE_NVIDIA 16 #define YSTRIPE_NVIDIA 128 + static void convert_nvidia_kmsbuf(const char* in, int width, int height, char* buff) { convert_kmsbuf(XSTRIPE_NVIDIA, YSTRIPE_NVIDIA, in, width, height, buff); } @@ -456,15 +469,40 @@ int main(int argc, const char **argv) } mmap_size = open_arg.size; mmap_offset = mmap_arg.out.addr_ptr; + mmap_fd = drmfd; } else if (strcmp(drm_ver->name, "nvidia-drm") == 0) { // quirky and slow funcs.convert = &convert_nvidia_kmsbuf; + + struct drm_gem_flink flink; + flink.handle = fb->handle; + if (ioctl_err = drmIoctl(drmfd, DRM_IOCTL_GEM_FLINK, &flink)) { + fprintf(stderr, "DRM ioctl error %d on line %d\n", ioctl_err, __LINE__); + goto cleanup; + } + struct drm_gem_open open_arg; + open_arg.name = flink.name; + printf("global name = %d\n", flink.name); + if (ioctl_err = drmIoctl(drmfd, DRM_IOCTL_GEM_OPEN, &open_arg)) { + fprintf(stderr, "DRM ioctl error %d on line %d\n", ioctl_err, __LINE__); + goto cleanup; + } + struct drm_mode_map_dumb mreq; + memset(&mreq, 0, sizeof(mreq)); + mreq.handle = open_arg.handle; + if (ioctl_err = drmIoctl(drmfd, DRM_IOCTL_MODE_MAP_DUMB, &mreq)) { + fprintf(stderr, "DRM ioctl error %d on line %d\n", ioctl_err, __LINE__); + goto cleanup; + } + mmap_size = open_arg.size; + mmap_offset = mreq.offset; + mmap_fd = drmfd; + funcs.sync_start = &drm_sync_noop; + funcs.sync_end = &drm_sync_noop; } else if (strcmp(drm_ver->name, "vmwgfx") == 0 || strcmp(drm_ver->name, "vboxvideo") == 0 || strcmp(drm_ver->name, "virtio_gpu") == 0) { // virgl does not work - //funcs.sync_start = &drm_sync_noop; - //funcs.sync_end = &drm_sync_noop; } else { fprintf(stderr, "Untested drm driver, use at your own risk!\n");