Merge branch 'feature/KASM-3806_hw3d' into 'master'
Resolve KASM-3806 "Feature/ hw3d" Closes KASM-3806 See merge request kasm-technologies/internal/KasmVNC!89release/1.1.0
						commit
						47bdc828c1
					
				@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					!/hw
 | 
				
			||||||
 | 
					/hw/*
 | 
				
			||||||
 | 
					!/hw/vnc
 | 
				
			||||||
@ -0,0 +1,284 @@
 | 
				
			|||||||
 | 
					/* Copyright (c) 2023 Kasm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining
 | 
				
			||||||
 | 
					a copy of this software and associated documentation files (the
 | 
				
			||||||
 | 
					"Software"), to deal in the Software without restriction, including
 | 
				
			||||||
 | 
					without limitation the rights to use, copy, modify, merge, publish,
 | 
				
			||||||
 | 
					distribute, sublicense, and/or sell copies of the Software, and to
 | 
				
			||||||
 | 
					permit persons to whom the Software is furnished to do so, subject to
 | 
				
			||||||
 | 
					the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included
 | 
				
			||||||
 | 
					in all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 | 
				
			||||||
 | 
					OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
				
			||||||
 | 
					MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 | 
				
			||||||
 | 
					IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
 | 
				
			||||||
 | 
					OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 | 
				
			||||||
 | 
					ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | 
				
			||||||
 | 
					OTHER DEALINGS IN THE SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Except as contained in this notice, the name of the X Consortium shall
 | 
				
			||||||
 | 
					not be used in advertising or otherwise to promote the sale, use or
 | 
				
			||||||
 | 
					other dealings in this Software without prior written authorization
 | 
				
			||||||
 | 
					from the X Consortium.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HAVE_DIX_CONFIG_H
 | 
				
			||||||
 | 
					#include <dix-config.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DRI3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/stat.h>
 | 
				
			||||||
 | 
					#include <sys/time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <X11/X.h>
 | 
				
			||||||
 | 
					#include <X11/Xmd.h>
 | 
				
			||||||
 | 
					#include <dri3.h>
 | 
				
			||||||
 | 
					#include <drm_fourcc.h>
 | 
				
			||||||
 | 
					#include <fb.h>
 | 
				
			||||||
 | 
					#include <gcstruct.h>
 | 
				
			||||||
 | 
					#include <gbm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const char *driNode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct priv_t {
 | 
				
			||||||
 | 
					    struct gbm_device *gbm;
 | 
				
			||||||
 | 
					    int fd;
 | 
				
			||||||
 | 
					} priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gbm_pixmap {
 | 
				
			||||||
 | 
					    struct gbm_bo *bo;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct gbm_pixmap gbm_pixmap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static DevPrivateKeyRec dri3_pixmap_private_key;
 | 
				
			||||||
 | 
					static struct timeval start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					xvnc_dri3_open_client(ClientPtr client,
 | 
				
			||||||
 | 
					                     ScreenPtr screen,
 | 
				
			||||||
 | 
					                     RRProviderPtr provider,
 | 
				
			||||||
 | 
					                     int *pfd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int fd = open(driNode, O_RDWR | O_CLOEXEC);
 | 
				
			||||||
 | 
					    if (fd < 0)
 | 
				
			||||||
 | 
					        return BadAlloc;
 | 
				
			||||||
 | 
					    *pfd = fd;
 | 
				
			||||||
 | 
					    return Success;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t
 | 
				
			||||||
 | 
					gbm_format_for_depth(CARD8 depth)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    switch (depth) {
 | 
				
			||||||
 | 
					    case 16:
 | 
				
			||||||
 | 
					        return GBM_FORMAT_RGB565;
 | 
				
			||||||
 | 
					    case 24:
 | 
				
			||||||
 | 
					        return GBM_FORMAT_XRGB8888;
 | 
				
			||||||
 | 
					    case 30:
 | 
				
			||||||
 | 
					        return GBM_FORMAT_ARGB2101010;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        ErrorF("unexpected depth: %d\n", depth);
 | 
				
			||||||
 | 
					        /* fallthrough */
 | 
				
			||||||
 | 
					    case 32:
 | 
				
			||||||
 | 
					        return GBM_FORMAT_ARGB8888;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void dri3_pixmap_set_private(PixmapPtr pixmap, gbm_pixmap *gp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    dixSetPrivate(&pixmap->devPrivates, &dri3_pixmap_private_key, gp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static gbm_pixmap *gbm_pixmap_get(PixmapPtr pixmap)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return dixLookupPrivate(&pixmap->devPrivates, &dri3_pixmap_private_key);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PixmapPtr
 | 
				
			||||||
 | 
					create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, CARD8 depth)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PixmapPtr pixmap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbm_pixmap *gp = calloc(1, sizeof(gbm_pixmap));
 | 
				
			||||||
 | 
					    if (!gp)
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pixmap = screen->CreatePixmap(screen, gbm_bo_get_width(bo), gbm_bo_get_height(bo),
 | 
				
			||||||
 | 
					                                  depth, CREATE_PIXMAP_USAGE_SCRATCH);
 | 
				
			||||||
 | 
					    if (!pixmap)
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gp->bo = bo;
 | 
				
			||||||
 | 
					    dri3_pixmap_set_private(pixmap, gp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return pixmap;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PixmapPtr
 | 
				
			||||||
 | 
					xvnc_pixmap_from_fds(ScreenPtr screen, CARD8 num_fds, const int *fds,
 | 
				
			||||||
 | 
					                       CARD16 width, CARD16 height,
 | 
				
			||||||
 | 
					                       const CARD32 *strides, const CARD32 *offsets,
 | 
				
			||||||
 | 
					                       CARD8 depth, CARD8 bpp, uint64_t modifier)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct gbm_bo *bo = NULL;
 | 
				
			||||||
 | 
					    PixmapPtr pixmap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (width == 0 || height == 0 || num_fds == 0 ||
 | 
				
			||||||
 | 
					        depth < 15 || bpp != BitsPerPixel(depth) ||
 | 
				
			||||||
 | 
					        strides[0] < width * bpp / 8)
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (num_fds == 1) {
 | 
				
			||||||
 | 
					        struct gbm_import_fd_data data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        data.fd = fds[0];
 | 
				
			||||||
 | 
					        data.width = width;
 | 
				
			||||||
 | 
					        data.height = height;
 | 
				
			||||||
 | 
					        data.stride = strides[0];
 | 
				
			||||||
 | 
					        data.format = gbm_format_for_depth(depth);
 | 
				
			||||||
 | 
					        bo = gbm_bo_import(priv.gbm, GBM_BO_IMPORT_FD, &data,
 | 
				
			||||||
 | 
					                           GBM_BO_USE_RENDERING);
 | 
				
			||||||
 | 
					        if (!bo)
 | 
				
			||||||
 | 
					            return NULL;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pixmap = create_pixmap_for_bo(screen, bo, depth);
 | 
				
			||||||
 | 
					    if (pixmap == NULL) {
 | 
				
			||||||
 | 
					        gbm_bo_destroy(bo);
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return pixmap;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					xvnc_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
 | 
				
			||||||
 | 
					                     uint32_t *strides, uint32_t *offsets,
 | 
				
			||||||
 | 
					                     uint64_t *modifier)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gbm_pixmap *gp = gbm_pixmap_get(pixmap);
 | 
				
			||||||
 | 
					    if (!gp)
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fds[0] = gbm_bo_get_fd(gp->bo);
 | 
				
			||||||
 | 
					    strides[0] = gbm_bo_get_stride(gp->bo);
 | 
				
			||||||
 | 
					    offsets[0] = 0;
 | 
				
			||||||
 | 
					    *modifier = DRM_FORMAT_MOD_INVALID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static Bool
 | 
				
			||||||
 | 
					xvnc_get_formats(ScreenPtr screen,
 | 
				
			||||||
 | 
					                 CARD32 *num_formats, CARD32 **formats)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ErrorF("xvnc_get_formats\n");
 | 
				
			||||||
 | 
					    return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static Bool
 | 
				
			||||||
 | 
					xvnc_get_modifiers(ScreenPtr screen, uint32_t format,
 | 
				
			||||||
 | 
					                   uint32_t *num_modifiers, uint64_t **modifiers)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ErrorF("xvnc_get_modifiers\n");
 | 
				
			||||||
 | 
					    return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static Bool
 | 
				
			||||||
 | 
					xvnc_get_drawable_modifiers(DrawablePtr draw, uint32_t format,
 | 
				
			||||||
 | 
					                            uint32_t *num_modifiers, uint64_t **modifiers)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ErrorF("xvnc_get_drawable_modifiers\n");
 | 
				
			||||||
 | 
					    return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const dri3_screen_info_rec xvnc_dri3_info = {
 | 
				
			||||||
 | 
					    .version = 2,
 | 
				
			||||||
 | 
					    .open = NULL,
 | 
				
			||||||
 | 
					    .pixmap_from_fds = xvnc_pixmap_from_fds,
 | 
				
			||||||
 | 
					    .fds_from_pixmap = xvnc_fds_from_pixmap,
 | 
				
			||||||
 | 
					    .open_client = xvnc_dri3_open_client,
 | 
				
			||||||
 | 
					    .get_formats = xvnc_get_formats,
 | 
				
			||||||
 | 
					    .get_modifiers = xvnc_get_modifiers,
 | 
				
			||||||
 | 
					    .get_drawable_modifiers = xvnc_get_drawable_modifiers,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void xvnc_sync_dri3_pixmap(PixmapPtr pixmap)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // There doesn't seem to be a good hook or sync point, so we do it manually
 | 
				
			||||||
 | 
					    // here, right before Present copies from the pixmap
 | 
				
			||||||
 | 
					    DrawablePtr pDraw;
 | 
				
			||||||
 | 
					    GCPtr gc;
 | 
				
			||||||
 | 
					    void *ptr;
 | 
				
			||||||
 | 
					    uint32_t stride, w, h;
 | 
				
			||||||
 | 
					    void *opaque = NULL;
 | 
				
			||||||
 | 
					    gbm_pixmap *gp = gbm_pixmap_get(pixmap);
 | 
				
			||||||
 | 
					    if (!gp) {
 | 
				
			||||||
 | 
					        ErrorF("Present tried to copy from a non-dri3 pixmap\n");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    w = gbm_bo_get_width(gp->bo);
 | 
				
			||||||
 | 
					    h = gbm_bo_get_height(gp->bo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ptr = gbm_bo_map(gp->bo, 0, 0, w, h,
 | 
				
			||||||
 | 
					                     GBM_BO_TRANSFER_READ, &stride, &opaque);
 | 
				
			||||||
 | 
					    if (!ptr) {
 | 
				
			||||||
 | 
					        ErrorF("gbm map failed, errno %d\n", errno);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pDraw = &pixmap->drawable;
 | 
				
			||||||
 | 
					    if ((gc = GetScratchGC(pDraw->depth, pDraw->pScreen))) {
 | 
				
			||||||
 | 
					        ValidateGC(pDraw, gc);
 | 
				
			||||||
 | 
					        //gc->ops->PutImage(pDraw, gc, pDraw->depth, 0, 0, w, h, 0, ZPixmap, data);
 | 
				
			||||||
 | 
					        fbPutZImage(pDraw, fbGetCompositeClip(gc), gc->alu, fbGetGCPrivate(gc)->pm,
 | 
				
			||||||
 | 
					                    0, 0, w, h, ptr, stride / sizeof(FbStip));
 | 
				
			||||||
 | 
					        FreeScratchGC(gc);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gbm_bo_unmap(gp->bo, opaque);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void xvnc_init_dri3(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    memset(&priv, 0, sizeof(priv));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gettimeofday(&start, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!dixRegisterPrivateKey(&dri3_pixmap_private_key, PRIVATE_PIXMAP, 0))
 | 
				
			||||||
 | 
					        FatalError("dix\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!driNode)
 | 
				
			||||||
 | 
					        driNode = "/dev/dri/renderD128";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    priv.fd = open(driNode, O_RDWR | O_CLOEXEC);
 | 
				
			||||||
 | 
					    if (!priv.fd)
 | 
				
			||||||
 | 
					        FatalError("Failed to open %s\n", driNode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    priv.gbm = gbm_create_device(priv.fd);
 | 
				
			||||||
 | 
					    if (!priv.gbm)
 | 
				
			||||||
 | 
					        FatalError("Failed to create gbm\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!dri3_screen_init(screenInfo.screens[0], &xvnc_dri3_info))
 | 
				
			||||||
 | 
					        FatalError("Couldn't init dri3\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // DRI3
 | 
				
			||||||
					Loading…
					
					
				
		Reference in New Issue