From a6d0d1a0104af2b790f78421521c4a43f34671f5 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Fri, 24 May 2024 15:26:45 -0700 Subject: [PATCH] add support for nvenc and accel_assist --- configure.ac | 5 + module/Makefile.am | 7 + module/rdp.h | 3 +- module/rdpCapture.c | 218 ++++--- module/rdpClientCon.c | 243 +++++++- module/rdpClientCon.h | 5 + module/rdpLRandR.c | 1255 ++++++++++++++++++++++++++++++++++++++ module/rdpLRandR.h | 9 + module/rdpMain.c | 445 +++++++++++++- module/rdpMain.h | 2 + module/rdpPutImage.c | 60 ++ module/rdpRandR.c | 9 +- xrdpdev/Makefile.am | 2 +- xrdpdev/xorg_nvidia.conf | 47 ++ xrdpdev/xrdpdev.c | 10 +- xrdpkeyb/rdpKeyboard.c | 2 + xrdpmouse/rdpMouse.c | 22 +- 17 files changed, 2246 insertions(+), 98 deletions(-) create mode 100644 module/rdpLRandR.c create mode 100644 module/rdpLRandR.h create mode 100644 xrdpdev/xorg_nvidia.conf diff --git a/configure.ac b/configure.ac index 0d05a66b..5d2f8f02 100644 --- a/configure.ac +++ b/configure.ac @@ -120,6 +120,11 @@ AC_ARG_ENABLE(glamor, AS_HELP_STRING([--enable-glamor], [], [enable_glamor=no]) AM_CONDITIONAL(WITH_GLAMOR, [test x$enable_glamor = xyes]) +AC_ARG_ENABLE(lrandr, AS_HELP_STRING([--enable-lrandr], + [Use local randr (default: no)]), + [], [enable_lrandr=no]) +AM_CONDITIONAL(WITH_LRANDR, [test x$enable_lrandr = xyes]) + AM_CONDITIONAL(WITH_SIMD_AMD64, [test x$simd_arch = xx86_64]) AM_CONDITIONAL(WITH_SIMD_X86, [test x$simd_arch = xi386]) diff --git a/module/Makefile.am b/module/Makefile.am index c7cd2a14..9cc7ab21 100644 --- a/module/Makefile.am +++ b/module/Makefile.am @@ -27,7 +27,14 @@ EGLLIB += -L$(XORG_SERVER_MODULES) -lglamoregl -lepoxy LIB_SEARCH_PATH += -R$(XORG_SERVER_MODULES) endif +if WITH_LRANDR +EXTRA_FLAGS += -DXORGXRDP_LRANDR +EXTRA_SOURCES += rdpLRandR.c +EXTRA_HEADERS += rdpLRandR.h +endif + AM_CFLAGS = \ + -DXRDP_LIBEXEC_PATH=\"${libexecdir}/xrdp\" \ $(XORG_SERVER_CFLAGS) \ $(XRDP_CFLAGS) \ -DPACKAGE_VERSION_MAJOR=@package_version_major@ \ diff --git a/module/rdp.h b/module/rdp.h index d4f5c47c..70c8eec8 100644 --- a/module/rdp.h +++ b/module/rdp.h @@ -316,6 +316,7 @@ struct _rdpRec int monitorCount; /* glamor */ Bool glamor; + Bool nvidia; PixmapPtr screenSwPixmap; void *xvPutImage; /* dri */ @@ -326,7 +327,7 @@ struct _rdpRec }; typedef struct _rdpRec rdpRec; typedef struct _rdpRec * rdpPtr; -#define XRDPPTR(_p) ((rdpPtr)((_p)->driverPrivate)) +#define XRDPPTR(_p) ((rdpPtr)((_p)->reservedPtr[0])) struct _rdpGCRec { diff --git a/module/rdpCapture.c b/module/rdpCapture.c index 7591af47..83abb38f 100644 --- a/module/rdpCapture.c +++ b/module/rdpCapture.c @@ -725,6 +725,64 @@ rdpCopyBox_a8r8g8b8_to_nv12_709fr(rdpClientCon *clientCon, return 0; } +/******************************************************************************/ +static Bool +rdpCopyBoxList(rdpClientCon *clientCon, PixmapPtr dstPixmap, + BoxPtr out_rects, int num_out_rects, + int srcx, int srcy, + int dstx, int dsty) +{ + PixmapPtr hwPixmap; + BoxPtr pbox; + ScreenPtr pScreen; + GCPtr copyGC; + ChangeGCVal tmpval[1]; + int count; + int index; + int left; + int top; + int width; + int height; + char pix1[16]; + rdpPtr dev; + + LLOGLN(10, ("rdpCopyBoxList:")); + + dev = clientCon->dev; + pScreen = dev->pScreen; + hwPixmap = pScreen->GetScreenPixmap(pScreen); + copyGC = GetScratchGC(dev->depth, pScreen); + if (copyGC == NULL) + { + return FALSE; + } + tmpval[0].val = GXcopy; + ChangeGC(NullClient, copyGC, GCFunction, tmpval); + ValidateGC(&(hwPixmap->drawable), copyGC); + count = num_out_rects; + pbox = out_rects; + for (index = 0; index < count; index++) + { + left = pbox[index].x1; + top = pbox[index].y1; + width = pbox[index].x2 - pbox[index].x1; + height = pbox[index].y2 - pbox[index].y1; + if ((width > 0) && (height > 0)) + { + copyGC->ops->CopyArea(&(hwPixmap->drawable), + &(dstPixmap->drawable), copyGC, + left - srcx, top - srcy, + width, height, + left - dstx, top - dsty); + } + } + FreeScratchGC(copyGC); + pScreen->GetImage(&(dstPixmap->drawable), 0, 0, 1, 1, ZPixmap, + 0xffffffff, pix1); + + return TRUE; +} + /******************************************************************************/ static Bool isShmStatusActive(enum shared_memory_status status) { @@ -800,6 +858,17 @@ rdpCaptureSimple(rdpClientCon *clientCon, RegionPtr in_reg, BoxPtr *out_rects, (*out_rects)[i] = rect; } + if (clientCon->dev->glamor || clientCon->dev->nvidia) + { + /* copy vmem to smem */ + if (!rdpCopyBoxList(clientCon, clientCon->dev->screenSwPixmap, + *out_rects, *num_out_rects, + 0, 0, 0, 0)) + { + return FALSE; + } + } + src = id->pixels; dst = id->shmem_pixels; dst_format = clientCon->rdp_format; @@ -947,6 +1016,17 @@ rdpCaptureSufA16(rdpClientCon *clientCon, RegionPtr in_reg, BoxPtr *out_rects, index++; } + if (clientCon->dev->glamor || clientCon->dev->nvidia) + { + /* copy vmem to smem */ + if (!rdpCopyBoxList(clientCon, clientCon->dev->screenSwPixmap, + *out_rects, *num_out_rects, + 0, 0, 0, 0)) + { + return FALSE; + } + } + src = id->pixels; dst = id->shmem_pixels; dst_format = clientCon->rdp_format; @@ -1031,6 +1111,17 @@ rdpCaptureGfxPro(rdpClientCon *clientCon, RegionPtr in_reg, BoxPtr *out_rects, return FALSE; } + if (clientCon->dev->glamor || clientCon->dev->nvidia) + { + /* copy vmem to smem */ + if (!rdpCopyBoxList(clientCon, clientCon->dev->screenSwPixmap, + REGION_RECTS(in_reg), REGION_NUM_RECTS(in_reg), + 0, 0, 0, 0)) + { + return FALSE; + } + } + *out_rects = g_new(BoxRec, RDP_MAX_TILES); if (*out_rects == NULL) { @@ -1164,6 +1255,7 @@ rdpCaptureSufA2(rdpClientCon *clientCon, RegionPtr in_reg, BoxPtr *out_rects, int src_stride; int dst_stride; int dst_format; + int monitor_index; LLOGLN(10, ("rdpCaptureSufA2:")); @@ -1184,6 +1276,26 @@ rdpCaptureSufA2(rdpClientCon *clientCon, RegionPtr in_reg, BoxPtr *out_rects, return FALSE; } + monitor_index = (id->flags >> 28) & 0xF; + if (clientCon->accelAssistPixmaps[monitor_index] != NULL) + { + /* copy vmem to vmem */ + rv = rdpCopyBoxList(clientCon, + clientCon->accelAssistPixmaps[monitor_index], + *out_rects, *num_out_rects, + 0, 0, id->left, id->top); + id->flags |= 1; + return rv; + /* accel assist will do the rest */ + } + else if (clientCon->dev->glamor || clientCon->dev->nvidia) + { + /* copy vmem to smem */ + rv = rdpCopyBoxList(clientCon, clientCon->dev->screenSwPixmap, + *out_rects, *num_out_rects, + 0, 0, id->left, id->top); + } + *num_out_rects = num_rects; *out_rects = g_new(BoxRec, num_rects * 4); @@ -1252,6 +1364,7 @@ rdpCaptureGfxA2(rdpClientCon *clientCon, RegionPtr in_reg, BoxPtr *out_rects, int src_stride; int dst_stride; int dst_format; + int monitor_index; LLOGLN(10, ("rdpCaptureGfxA2:")); @@ -1262,8 +1375,6 @@ rdpCaptureGfxA2(rdpClientCon *clientCon, RegionPtr in_reg, BoxPtr *out_rects, return FALSE; } - rv = TRUE; - rdpRegionTranslate(in_reg, -id->left, -id->top); num_rects = REGION_NUM_RECTS(in_reg); @@ -1300,6 +1411,34 @@ rdpCaptureGfxA2(rdpClientCon *clientCon, RegionPtr in_reg, BoxPtr *out_rects, (*out_rects)[index] = rect; index++; } + rv = TRUE; + monitor_index = (id->flags >> 28) & 0xF; + if (clientCon->accelAssistPixmaps[monitor_index] != NULL) + { + LLOGLN(10, ("rdpCaptureGfxA2: a monitor_index %d left %d top %d", + monitor_index, id->left, id->top)); + /* copy vmem to vmem */ + rv = rdpCopyBoxList(clientCon, + clientCon->accelAssistPixmaps[monitor_index], + *out_rects, num_rects, + -id->left, -id->top, 0, 0); + id->flags |= 1; + return rv; + /* accel assist will do the rest */ + } + else if (clientCon->dev->glamor || clientCon->dev->nvidia) + { + LLOGLN(10, ("rdpCaptureGfxA2: b monitor_index %d left %d top %d", + monitor_index, id->left, id->top)); + /* copy vmem to smem */ + if (!rdpCopyBoxList(clientCon, + clientCon->dev->screenSwPixmap, + *out_rects, num_rects, + -id->left, -id->top, -id->left, -id->top)) + { + return FALSE; + } + } src = id->pixels; dst = id->shmem_pixels; @@ -1307,14 +1446,13 @@ rdpCaptureGfxA2(rdpClientCon *clientCon, RegionPtr in_reg, BoxPtr *out_rects, src_stride = id->lineBytes; dst_stride = id->width; - src = src + src_stride * id->top + id->left * 4; - if (dst_format == XRDP_nv12_709fr) { dst_uv = dst; dst_uv += id->width * id->height; rdpCopyBox_a8r8g8b8_to_nv12_709fr(clientCon, - src, src_stride, 0, 0, + src, src_stride, + -id->left, -id->top, dst, dst_stride, dst_uv, dst_stride, 0, 0, @@ -1328,65 +1466,6 @@ rdpCaptureGfxA2(rdpClientCon *clientCon, RegionPtr in_reg, BoxPtr *out_rects, return rv; } -#if defined(XORGXRDP_GLAMOR) -/******************************************************************************/ -static int -copy_vmem(rdpPtr dev, RegionPtr in_reg) -{ - PixmapPtr hwPixmap; - PixmapPtr swPixmap; - BoxPtr pbox; - ScreenPtr pScreen; - GCPtr copyGC; - ChangeGCVal tmpval[1]; - int count; - int index; - int left; - int top; - int width; - int height; - - /* copy the dirty area from the screen hw pixmap to a sw pixmap - this should do a dma */ - pScreen = dev->pScreen; - hwPixmap = pScreen->GetScreenPixmap(pScreen); - swPixmap = dev->screenSwPixmap; - copyGC = GetScratchGC(dev->depth, pScreen); - if (copyGC != NULL) - { - tmpval[0].val = GXcopy; - ChangeGC(NullClient, copyGC, GCFunction, tmpval); - ValidateGC(&(hwPixmap->drawable), copyGC); - count = REGION_NUM_RECTS(in_reg); - pbox = REGION_RECTS(in_reg); - for (index = 0; index < count; index++) - { - left = pbox[index].x1; - top = pbox[index].y1; - width = pbox[index].x2 - pbox[index].x1; - height = pbox[index].y2 - pbox[index].y1; - if ((width > 0) && (height > 0)) - { - LLOGLN(10, ("copy_vmem: hwPixmap tex 0x%8.8x " - "swPixmap tex 0x%8.8x", - glamor_get_pixmap_texture(hwPixmap), - glamor_get_pixmap_texture(swPixmap))); - copyGC->ops->CopyArea(&(hwPixmap->drawable), - &(swPixmap->drawable), - copyGC, left, top, - width, height, left, top); - } - } - FreeScratchGC(copyGC); - } - else - { - return 1; - } - return 0; -} -#endif - /** * Copy an array of rectangles from one memory area to another *****************************************************************************/ @@ -1398,17 +1477,6 @@ rdpCapture(rdpClientCon *clientCon, RegionPtr in_reg, BoxPtr *out_rects, LLOGLN(10, ("rdpCapture:")); mode = clientCon->client_info.capture_code; - if (clientCon->dev->glamor) - { -#if defined(XORGXRDP_GLAMOR) - if ((mode == 2) || (mode == 4)) - { - return rdpEglCaptureRfx(clientCon, in_reg, out_rects, - num_out_rects, id); - } - copy_vmem(clientCon->dev, in_reg); -#endif - } switch (mode) { case CC_SIMPLE: diff --git a/module/rdpClientCon.c b/module/rdpClientCon.c index 72556ca5..baebe8b0 100644 --- a/module/rdpClientCon.c +++ b/module/rdpClientCon.c @@ -30,10 +30,12 @@ Client connection to xrdp #include #include #include +#include #include #include #include -#include +#include +#include /* this should be before all X11 .h files */ #include @@ -50,7 +52,13 @@ Client connection to xrdp #include "rdpInput.h" #include "rdpReg.h" #include "rdpCapture.h" + +#if defined(XORGXRDP_LRANDR) +#include "rdpRandR.h" +#include "rdpLRandR.h" +#else #include "rdpRandR.h" +#endif #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -113,6 +121,8 @@ static void rdpClientConProcessClientInfoMonitors(rdpPtr dev, rdpClientCon *clientCon); static int rdpSendMemoryAllocationComplete(rdpPtr dev, rdpClientCon *clientCon); +static int +rdpSendAccelAssistMonitors(rdpPtr dev, rdpClientCon *clientCon); #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 5, 0, 0) @@ -264,14 +274,14 @@ rdpClientConGotConnection(ScreenPtr pScreen, rdpPtr dev) /* set idle timer to disconnect */ if (dev->idle_disconnect_timeout_s > 0) { - LLOGLN(0, ("rdpClientConGetConnection: " + LLOGLN(0, ("rdpClientConGotConnection: " "engaging idle timer, timeout [%d] sec", dev->idle_disconnect_timeout_s)); dev->idleDisconnectTimer = TimerSet(dev->idleDisconnectTimer, 0, dev->idle_disconnect_timeout_s * 1000, rdpDeferredIdleDisconnectCallback, dev); } else { - LLOGLN(0, ("rdpClientConGetConnection: " + LLOGLN(0, ("rdpClientConGotConnection: " "idle_disconnect_timeout set to non-positive value, idle timer turned off")); } @@ -362,6 +372,63 @@ rdpDeferredIdleDisconnectCallback(OsTimerPtr timer, CARD32 now, pointer arg) rdpDeferredIdleDisconnectCallback, dev); return 0; } + +/*****************************************************************************/ +static int +rdpShutdownAccelAssist(rdpPtr dev, rdpClientCon *clientCon) { + ScreenPtr pScreen; + PixmapPtr pPixmap; + int index; + int exit_code = 0; + + LLOGLN(0, ("rdpShutdownAccelAssist:")); + if (clientCon->accel_assist_pid <= 0) + { + return 0; + } + if (waitpid(clientCon->accel_assist_pid, &exit_code, WNOHANG) == 0) + { + /* still running */ + kill(clientCon->accel_assist_pid, SIGTERM); + waitpid(clientCon->accel_assist_pid, &exit_code, 0); + } + pScreen = clientCon->dev->pScreen; + for (index = 0; index < 16; index++) + { + pPixmap = clientCon->accelAssistPixmaps[index]; + if (pPixmap != NULL) + { + pScreen->DestroyPixmap(pPixmap); + } + } + clientCon->accel_assist_pid = -1; + clientCon->use_accel_assist = 0; + return exit_code; +} + +/******************************************************************************/ +static Bool +rdpClientConUseAccelAssist(rdpPtr dev, rdpClientCon *clientCon) +{ + const char *xrdp_use_accel_assist = getenv("XRDP_USE_ACCEL_ASSIST"); + + if (xrdp_use_accel_assist == NULL) + { + return FALSE; + } + if (strcmp(xrdp_use_accel_assist, "0") == 0) + { + return FALSE; + } + if (strcmp(xrdp_use_accel_assist, "1") == 0) + { + return ((dev->nvidia || dev->glamor) && + ((clientCon->client_info.capture_code == CC_SUF_A2) || + (clientCon->client_info.capture_code == CC_GFX_A2))); + } + return 0; +} + /*****************************************************************************/ static int rdpClientConDisconnect(rdpPtr dev, rdpClientCon *clientCon) @@ -425,6 +492,10 @@ rdpClientConDisconnect(rdpPtr dev, rdpClientCon *clientCon) clientCon->shmemfd, clientCon->shmem_bytes); } + if (clientCon->use_accel_assist) + { + rdpShutdownAccelAssist(dev, clientCon); + } free(clientCon); return 0; } @@ -739,8 +810,10 @@ rdpClientConAllocateSharedMemory(rdpClientCon *clientCon, int bytes) /******************************************************************************/ static enum shared_memory_status -convertSharedMemoryStatusToActive(enum shared_memory_status status) { - switch (status) { +convertSharedMemoryStatusToActive(enum shared_memory_status status) +{ + switch (status) + { case SHM_ACTIVE_PENDING: return SHM_ACTIVE; case SHM_RFX_ACTIVE_PENDING: @@ -774,6 +847,8 @@ rdpClientConResizeAllMemoryAreas(rdpPtr dev, rdpClientCon *clientCon) enum shared_memory_status shmemstatus; + LLOGLN(0, ("rdpClientConResizeAllMemoryAreas:")); + // Updare the rdp size from the client size clientCon->rdp_width = width; clientCon->rdp_height = height; @@ -782,7 +857,7 @@ rdpClientConResizeAllMemoryAreas(rdpPtr dev, rdpClientCon *clientCon) if ((clientCon->client_info.capture_code == CC_SUF_RFX) || /* RFX */ (clientCon->client_info.capture_code == CC_GFX_PRO)) { - LLOGLN(0, ("rdpClientConProcessMsgClientInfo: got RFX capture")); + LLOGLN(0, ("rdpClientConResizeAllMemoryAreas: got RFX capture")); /* RFX capture needs fixed-size rectangles */ clientCon->cap_width = RDPALIGN(width, XRDP_RFX_ALIGN); clientCon->cap_height = RDPALIGN(height, XRDP_RFX_ALIGN); @@ -799,7 +874,7 @@ rdpClientConResizeAllMemoryAreas(rdpPtr dev, rdpClientCon *clientCon) else if ((clientCon->client_info.capture_code == CC_SUF_A2) || /* H264 */ (clientCon->client_info.capture_code == CC_GFX_A2)) { - LLOGLN(0, ("rdpClientConProcessMsgClientInfo: got H264 capture")); + LLOGLN(0, ("rdpClientConResizeAllMemoryAreas: got H264 capture")); clientCon->cap_width = width; clientCon->cap_height = height; @@ -878,7 +953,7 @@ rdpClientConResizeAllMemoryAreas(rdpPtr dev, rdpClientCon *clientCon) dev->allow_screen_resize = 1; ok = RRScreenSizeSet(dev->pScreen, width, height, mmwidth, mmheight); dev->allow_screen_resize = 0; - LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: RRScreenSizeSet ok=[%d]", ok)); + LLOGLN(0, ("rdpClientConResizeAllMemoryAreas: RRScreenSizeSet ok=[%d]", ok)); } rdpCaptureResetState(clientCon); @@ -901,7 +976,6 @@ rdpClientConProcessMonitorUpdateMsg(rdpPtr dev, rdpClientCon *clientCon, LLOGLN(0, ("rdpClientConProcessMonitorUpdateMsg: (%dx%d) #%d", width, height, num_monitors)); - // Update the client_info we have clientCon->client_info.display_sizes.monitorCount = num_monitors; for (i = 0; i < num_monitors; ++i) @@ -919,6 +993,11 @@ rdpClientConProcessMonitorUpdateMsg(rdpPtr dev, rdpClientCon *clientCon, rdpClientConAddDirtyScreen(dev, clientCon, 0, 0, width, height); rdpSendMemoryAllocationComplete(dev, clientCon); + if (clientCon->use_accel_assist) + { + rdpSendAccelAssistMonitors(dev, clientCon); + } + return 0; } @@ -998,6 +1077,129 @@ rdpClientConProcessMsgClientInput(rdpPtr dev, rdpClientCon *clientCon) return 0; } +/******************************************************************************/ +static int +rdpStartAccelAssist(rdpPtr dev, rdpClientCon *clientCon) +{ + char text[64]; + int spair[2]; + int index; + + // Accel assist is already running, don't attempt to initialize it again. + if (clientCon->accel_assist_pid > 0) + { + return 0; + } + + socketpair(AF_UNIX, SOCK_STREAM, 0, spair); + + clientCon->accel_assist_pid = fork(); + if (clientCon->accel_assist_pid == -1) + { + /* error */ + close(spair[0]); + close(spair[1]); + } + else if (clientCon->accel_assist_pid == 0) + { + /* child */ + for (index = 0; index < 256; index++) + { + if ((index != clientCon->sck) && (index != spair[0])) + { + close(index); + } + } + open("/dev/null", O_RDWR); + open("/dev/null", O_RDWR); + open("/dev/null", O_RDWR); + snprintf(text, 63, ":%s", display); + text[63] = 0; + setenv("DISPLAY", text, 1); + snprintf(text, 63, "%d", spair[0]); + text[63] = 0; + setenv("XORGXRDP_XORG_FD", text, 1); + snprintf(text, 63, "%d", clientCon->sck); + text[63] = 0; + setenv("XORGXRDP_XRDP_FD", text, 1); + snprintf(text, 63, "%s/xrdp-accel-assist", XRDP_LIBEXEC_PATH); + text[63] = 0; + execlp(text, text, "-d", (void *) 0); + exit(0); + } + else + { + /* parent */ + LLOGLN(0, ("rdpStartAccelAssist: started accel assist pid %d", + clientCon->accel_assist_pid)); + rdpClientConRemoveEnabledDevice(clientCon->sck); + close(clientCon->sck); + close(spair[0]); + clientCon->sck = spair[1]; + g_sck_set_non_blocking(clientCon->sck); + rdpClientConAddEnabledDevice(dev->pScreen, clientCon->sck); + } + return 0; +} + +/******************************************************************************/ +static int +rdpSendAccelAssistMonitors(rdpPtr dev, rdpClientCon *clientCon) +{ + int index; + int len; + int rv; + int width; + int height; + const int layer_size = 8; + + LLOGLN(0, ("rdpSendAccelAssistMonitors: monitorCount %d", + dev->monitorCount)); + rdpClientConSendPending(dev, clientCon); + init_stream(clientCon->out_s, 0); + s_push_layer(clientCon->out_s, iso_hdr, layer_size); + out_uint16_le(clientCon->out_s, 1); /* clear monitors */ + out_uint16_le(clientCon->out_s, 4); /* size */ + clientCon->count++; + if (dev->monitorCount < 1) + { + width = dev->width; + height = dev->height; + out_uint16_le(clientCon->out_s, 2); + out_uint16_le(clientCon->out_s, 20); /* size */ + out_uint16_le(clientCon->out_s, width); + out_uint16_le(clientCon->out_s, height); + out_uint32_le(clientCon->out_s, 0xDEADBEEF); + out_uint32_le(clientCon->out_s, clientCon->conNumber); + out_uint32_le(clientCon->out_s, 0); + clientCon->count++; + } + else + { + for (index = 0; index < dev->monitorCount; index++) + { + width = dev->minfo[index].right - dev->minfo[index].left + 1; + height = dev->minfo[index].bottom - dev->minfo[index].top + 1; + out_uint16_le(clientCon->out_s, 2); + out_uint16_le(clientCon->out_s, 20); /* size */ + out_uint16_le(clientCon->out_s, width); + out_uint16_le(clientCon->out_s, height); + out_uint32_le(clientCon->out_s, 0xDEADBEEF); + out_uint32_le(clientCon->out_s, clientCon->conNumber); + out_uint32_le(clientCon->out_s, index); + clientCon->count++; + } + } + s_mark_end(clientCon->out_s); + len = (int) (clientCon->out_s->end - clientCon->out_s->data); + s_pop_layer(clientCon->out_s, iso_hdr); + out_uint16_le(clientCon->out_s, 100); + out_uint16_le(clientCon->out_s, clientCon->count); + out_uint32_le(clientCon->out_s, len - layer_size); + rv = rdpClientConSend(dev, clientCon, clientCon->out_s->data, len); + return rv; +} + int rdpClientConPreCheck(rdpPtr dev, rdpClientCon *clientCon, int in_size); @@ -1042,7 +1244,7 @@ rdpSendMemoryAllocationComplete(rdpPtr dev, rdpClientCon *clientCon) s_mark_end(clientCon->out_s); len = (int) (clientCon->out_s->end - clientCon->out_s->data); s_pop_layer(clientCon->out_s, iso_hdr); - out_uint16_le(clientCon->out_s, 100); /* Metadata message to xrdp (or if using helper, helper signal) */ + out_uint16_le(clientCon->out_s, 100); /* Metadata message to xrdp (or if using accel assist, signal) */ out_uint16_le(clientCon->out_s, clientCon->count); out_uint32_le(clientCon->out_s, len - layer_size); rv = rdpClientConSend(dev, clientCon, clientCon->out_s->data, len); @@ -1101,9 +1303,20 @@ rdpClientConProcessClientInfoMonitors(rdpPtr dev, rdpClientCon *clientCon) dev->doMultimon = 0; dev->monitorCount = 0; } - +#if defined(XORGXRDP_LRANDR) + if (dev->nvidia) + { + rdpLRRSetRdpOutputs(dev); + } + else + { + rdpRRSetRdpOutputs(dev); + RRTellChanged(dev->pScreen); + } +#else rdpRRSetRdpOutputs(dev); RRTellChanged(dev->pScreen); +#endif } /******************************************************************************/ @@ -1223,6 +1436,14 @@ rdpClientConProcessMsgClientInfo(rdpPtr dev, rdpClientCon *clientCon) rdpClientConAddDirtyScreen(dev, clientCon, 0, 0, clientCon->rdp_width, clientCon->rdp_height); + /* currently only nvenc and h264 is supported */ + if (rdpClientConUseAccelAssist(dev, clientCon)) + { + clientCon->use_accel_assist = 1; + rdpStartAccelAssist(dev, clientCon); + rdpSendAccelAssistMonitors(dev, clientCon); + } + return 0; } diff --git a/module/rdpClientCon.h b/module/rdpClientCon.h index 5ff1de21..63186993 100644 --- a/module/rdpClientCon.h +++ b/module/rdpClientCon.h @@ -115,6 +115,8 @@ struct _rdpClientCon int rect_id_ack; enum shared_memory_status shmemstatus; + PixmapPtr accelAssistPixmaps[16]; + OsTimerPtr updateTimer; CARD32 lastUpdateTime; /* millisecond timestamp */ int updateScheduled; /* boolean */ @@ -129,6 +131,9 @@ struct _rdpClientCon /* true = skip drawing */ int suppress_output; + int use_accel_assist; + int accel_assist_pid; + struct _rdpClientCon *next; struct _rdpClientCon *prev; }; diff --git a/module/rdpLRandR.c b/module/rdpLRandR.c new file mode 100644 index 00000000..d2e8d86c --- /dev/null +++ b/module/rdpLRandR.c @@ -0,0 +1,1255 @@ +#if defined(HAVE_CONFIG_H) +#include "config_ac.h" +#endif + +#include +#include +#include + +/* this should be before all X11 .h files */ +#include +#include + +/* all driver need this */ +#include +#include + +#include "rdp.h" +#include "rdpDraw.h" +#include "rdpMisc.h" +#include "rdpReg.h" +#include "rdpLRandR.h" + +#if defined(XORGXRDP_GLAMOR) +#include +#endif + +/******************************************************************************/ +#define LOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +/* + start end +crtc ids 1 16 +output ids 17 32 +mode ids 33 48 +*/ + +#define LRANDR_NAME "RANDR" +#define SERVER_LRANDR_MAJOR_VERSION 1 +#define SERVER_LRANDR_MINOR_VERSION 3 +#define LRRNumberEvents 2 +#define LRRNumberErrors 4 +#define LRRNumberRequests 32 /* 1.3 */ +#define LRRMaxCrtcs 16 +#define LRRMaxOutputs 16 +#define LRRMaxOutputNameLength 32 +#define LRRMaxModes 16 +#define LRRMaxModesNameLength 32 +#define LRRCrtcStart 1 +#define LRROutputStart 17 +#define LRRModeStart 33 + +#define OUTPUT2CRTC(_output) ((_output) - LRRMaxCrtcs) +#define OUTPUT2MODE(_output) ((_output) + LRRMaxOutputs) + +#define CRTC2OUTPUT(_crtc) ((_crtc) + LRRMaxCrtcs) +#define CRTC2MODE(_crtc) ((_crtc) + LRRMaxCrtcs + LRRMaxOutputs) + +struct _interestedClientRec +{ + ClientPtr pClient; + XID window; + CARD32 mask; + struct xorg_list entry; +}; +typedef struct _interestedClientRec interestedClientRec; + +struct _LRRCrtcRec +{ + RRCrtc id; /* XID */ + int x; + int y; + int width; + int height; +}; +typedef struct _LRRCrtcRec LRRCrtcRec; + +struct _LRROutputRec +{ + RROutput id; /* XID */ + char name[LRRMaxOutputNameLength]; +}; +typedef struct _LRROutputRec LRROutputRec; + +static int g_numCrtcs = 0; +static LRRCrtcRec g_crtcs[LRRMaxCrtcs]; + +static int g_numOutputs = 0; +static LRROutputRec g_outputs[LRRMaxOutputs]; +static RROutput g_primaryOutput = None; /* XID */ + +static int g_numModes = 0; +static xRRModeInfo g_modes[LRRMaxModes]; +static char g_modeNames[LRRMaxModes][LRRMaxModesNameLength]; + +static CARD32 g_updateTime; + +static int (*g_procLRandrVector[LRRNumberRequests]) (ClientPtr); + +static struct xorg_list g_interestedClients; + +static int LRRErrorBase; +static int LRREventBase; + +static int g_width; +static int g_height; +static int g_mmWidth; +static int g_mmHeight; + +/******************************************************************************/ +static int +remove_client(ClientPtr pClient) +{ + interestedClientRec *iterator; + interestedClientRec *next; + + xorg_list_for_each_entry_safe(iterator, next, &g_interestedClients, entry) + { + if (iterator->pClient == pClient) + { + LLOGLN(10, ("remove_client: client %p found " + "pClient, removing", pClient)); + xorg_list_del(&(iterator->entry)); + free(iterator); + } + } + return 0; +} + +/******************************************************************************/ +static int +LRRDeliverScreenEvent(interestedClientRec *ic, ScreenPtr pScreen) +{ + xRRScreenChangeNotifyEvent se; + WindowPtr pRoot; + WindowPtr pWin; + + LLOGLN(10, ("LRRDeliverScreenEvent: client %p", ic->pClient)); + if (dixLookupWindow(&pWin, ic->window, ic->pClient, + DixGetAttrAccess) != Success) + { + return 1; + } + memset(&se, 0, sizeof(se)); + pRoot = pScreen->root; + LLOGLN(10, ("LRRDeliverScreenEvent: root id 0x%8.8x win id 0x%8.8x " + "width %d height %d", + pRoot->drawable.id, ic->window, + pScreen->width, pScreen->height)); + se.type = RRScreenChangeNotify + LRREventBase; + se.rotation = RR_Rotate_0; + se.timestamp = g_updateTime; + se.configTimestamp = g_updateTime; + se.root = pRoot->drawable.id; + se.window = ic->window; + //se.sizeID = RR10CurrentSizeID(pScreen); + se.widthInPixels = pScreen->width; + se.heightInPixels = pScreen->height; + se.widthInMillimeters = pScreen->mmWidth; + se.heightInMillimeters = pScreen->mmHeight; + WriteEventsToClient(ic->pClient, 1, (xEvent *) &se); + return 0; +} + +/******************************************************************************/ +static int +LRRDeliverCrtcEvent(interestedClientRec *ic, LRRCrtcRec *pCrtc) +{ + xRRCrtcChangeNotifyEvent ce; + WindowPtr pWin; + + LLOGLN(10, ("LRRDeliverCrtcEvent: client %p", ic->pClient)); + if (dixLookupWindow(&pWin, ic->window, ic->pClient, + DixGetAttrAccess) != Success) + { + return 1; + } + LLOGLN(10, ("LRRDeliverCrtcEvent: x %d y %d width %d height %d", + pCrtc->x, pCrtc->y, pCrtc->width, pCrtc->height)); + memset(&ce, 0, sizeof(ce)); + ce.type = RRNotify + LRREventBase; + ce.subCode = RRNotify_CrtcChange; + ce.timestamp = g_updateTime; + ce.window = ic->window; + ce.crtc = pCrtc->id; + ce.mode = CRTC2MODE(ce.crtc); + ce.rotation = RR_Rotate_0; + ce.x = pCrtc->x; + ce.y = pCrtc->y; + ce.width = pCrtc->width; + ce.height = pCrtc->height; + WriteEventsToClient(ic->pClient, 1, (xEvent *) &ce); + return 0; +} + +/******************************************************************************/ +static int +LRRDeliverOutputEvent(interestedClientRec *ic, LRROutputRec *pOutput) +{ + xRROutputChangeNotifyEvent oe; + WindowPtr pWin; + + LLOGLN(10, ("LRRDeliverOutputEvent: client %p", ic->pClient)); + if (dixLookupWindow(&pWin, ic->window, ic->pClient, + DixGetAttrAccess) != Success) + { + return 1; + } + memset(&oe, 0, sizeof(oe)); + oe.type = RRNotify + LRREventBase; + oe.subCode = RRNotify_OutputChange; + oe.timestamp = g_updateTime; + oe.configTimestamp = g_updateTime; + oe.window = ic->window; + oe.output = pOutput->id; + oe.crtc = OUTPUT2CRTC(oe.output); + oe.mode = OUTPUT2MODE(oe.output); + oe.rotation = RR_Rotate_0; + oe.connection = RR_Connected; + WriteEventsToClient(ic->pClient, 1, (xEvent *) &oe); + return 0; +} + +/******************************************************************************/ +/* 0 */ +/* RRQueryVersion + client-major-version: CARD32 + client-minor-version: CARD32 + x + major-version: CARD32 + minor-version: CARD32 */ +static int +ProcLRRQueryVersion(ClientPtr client) +{ + xRRQueryVersionReply rep; + REQUEST(xRRQueryVersionReq); + + REQUEST_SIZE_MATCH(xRRQueryVersionReq); + LLOGLN(10, ("ProcLRRQueryVersion: client %p version %d %d", + client, stuff->majorVersion, stuff->minorVersion)); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + if (version_compare(stuff->majorVersion, stuff->minorVersion, + SERVER_LRANDR_MAJOR_VERSION, + SERVER_LRANDR_MINOR_VERSION) < 0) + { + rep.majorVersion = stuff->majorVersion; + rep.minorVersion = stuff->minorVersion; + } + else + { + rep.majorVersion = SERVER_LRANDR_MAJOR_VERSION; + rep.minorVersion = SERVER_LRANDR_MINOR_VERSION; + } + /* require 1.1 or greater randr client */ + if (version_compare(rep.majorVersion, rep.minorVersion, 1, 1) < 0) + { + LLOGLN(0, ("ProcLRRQueryVersion: bad version")); + return BadValue; + } + /* don't allow swapping */ + if (client->swapped) + { + LLOGLN(0, ("ProcLRRQueryVersion: no swap support")); + return BadValue; + } + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +/******************************************************************************/ +/* 4 */ +/* RRSelectInput + window: WINDOW + enable: SETofRRSELECTMASK */ +static int +ProcLRRSelectInput(ClientPtr client) +{ + int rc; + WindowPtr pWin; + interestedClientRec* ic; + REQUEST(xRRSelectInputReq); + + LLOGLN(10, ("ProcLRRSelectInput: client %p enable 0x%8.8x", client, + stuff->enable)); + REQUEST_SIZE_MATCH(xRRSelectInputReq); + + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + { + return rc; + } + + if (stuff->enable & (RRScreenChangeNotifyMask | + RRCrtcChangeNotifyMask | + RROutputChangeNotifyMask | + RROutputPropertyNotifyMask)) + { + ic = (interestedClientRec *) calloc(1, sizeof(interestedClientRec)); + if (ic == NULL) + { + return BadAlloc; + } + remove_client(client); + ic->pClient = client; + ic->mask = stuff->enable; + ic->window = stuff->window; + LLOGLN(10, ("ProcLRRSelectInput: client %p adding " + "pClient to list", client)); + xorg_list_add(&(ic->entry), &g_interestedClients); + } + else if (stuff->enable == 0) + { + /* delete the interest */ + remove_client(client); + } + else + { + LLOGLN(0, ("ProcLRRSelectInput: bad enable 0x%8.8x", stuff->enable)); + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + +/******************************************************************************/ +/* 5 */ +/* RRGetScreenInfo + window: WINDOW + x + rotations: SETofROTATION + root: WINDOW + timestamp: TIMESTAMP + config-timestamp: TIMESTAMP + size-id: SIZEID + rotation: ROTATION + rate: CARD16 + sizes: LISTofSCREENSIZE + refresh: LISTofREFRESH */ +static int +ProcLRRGetScreenInfo(ClientPtr client) +{ + int rc; + WindowPtr pWin; + xRRGetScreenInfoReply rep; + unsigned long extraLen; + CARD8 *extra; + xScreenSizes *size; + CARD16 *rates; + REQUEST(xRRGetScreenInfoReq); + + LLOGLN(10, ("ProcLRRGetScreenInfo: client %p", client)); + REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + { + return rc; + } + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.setOfRotations = RR_Rotate_0; + rep.sequenceNumber = client->sequence; + rep.root = pWin->drawable.pScreen->root->drawable.id; + rep.timestamp = g_updateTime; + rep.configTimestamp = g_updateTime; + rep.rotation = RR_Rotate_0; + rep.nSizes = 1; + rep.nrateEnts = 1 + 1; + rep.sizeID = 0; + rep.rate = 50; + extraLen = rep.nSizes * sizeof(xScreenSizes); + extraLen += rep.nrateEnts * sizeof(CARD16); + extra = (CARD8 *) calloc(extraLen, 1); + if (extra == NULL) + { + return BadAlloc; + } + size = (xScreenSizes *) extra; + rates = (CARD16 *) (size + rep.nSizes); + size->widthInPixels = g_width; + size->heightInPixels = g_height; + size->widthInMillimeters = g_mmWidth; + size->heightInMillimeters = g_mmHeight; + size++; + *rates = 1; /* number of rates */ + rates++; + *rates = 50; + rep.length = bytes_to_int32(extraLen); + WriteToClient(client, sizeof(rep), &rep); + if (extraLen != 0) + { + WriteToClient(client, extraLen, extra); + free(extra); + } + return Success; +} + +/******************************************************************************/ +/* 6 */ +/* RRGetScreenSizeRange + window: WINDOW + x + CARD16 minWidth, minHeight + CARD16 maxWidth, maxHeight */ +static int +ProcLRRGetScreenSizeRange(ClientPtr client) +{ + xRRGetScreenSizeRangeReply rep; + REQUEST(xRRGetScreenSizeRangeReq); + + (void) stuff; + + LLOGLN(10, ("ProcLRRGetScreenSizeRange: client %p", client)); + REQUEST_SIZE_MATCH(xRRGetScreenSizeRangeReq); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.minWidth = 64; + rep.minHeight = 64; + rep.maxWidth = 8192; + rep.maxHeight = 8192; + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +/******************************************************************************/ +/* 8 */ +/* RRGetScreenResources + window: WINDOW + x + timestamp: TIMESTAMP + config-timestamp: TIMESTAMP + crtcs: LISTofCRTC + outputs: LISTofOUTPUT + modes: LISTofMODEINFO */ +static int +ProcLRRGetScreenResources(ClientPtr client) +{ + int index; + CARD8 *extra; + unsigned long extraLen; + RRCrtc *crtcs; + RROutput *outputs; + xRRModeInfo *modeinfos; + CARD8 *names; + xRRGetScreenResourcesReply rep; + REQUEST(xRRGetScreenResourcesReq); + + (void) stuff; + + LLOGLN(10, ("ProcLRRGetScreenResources: client %p", client)); + REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.timestamp = g_updateTime; + rep.configTimestamp = g_updateTime; + rep.nCrtcs = g_numCrtcs; + rep.nOutputs = g_numOutputs; + rep.nModes = g_numModes; + for (index = 0; index < g_numModes; index++) + { + rep.nbytesNames += g_modes[index].nameLength; + } + LLOGLN(10, ("ProcLRRGetScreenResources: rep.nbytesNames %d", + rep.nbytesNames)); + rep.length = (g_numCrtcs + g_numOutputs + + g_numModes * bytes_to_int32(SIZEOF(xRRModeInfo)) + + bytes_to_int32(rep.nbytesNames)); + LLOGLN(10, ("ProcLRRGetScreenResources: rep.length %d", rep.length)); + extraLen = rep.length << 2; + if (extraLen != 0) + { + extra = (CARD8 *) calloc(1, extraLen); + if (extra == NULL) + { + return BadAlloc; + } + } + else + { + extra = NULL; + } + LLOGLN(10, ("ProcLRRGetScreenResources: extraLen %d", (int) extraLen)); + crtcs = (RRCrtc *) extra; + outputs = (RROutput *) (crtcs + g_numCrtcs); + modeinfos = (xRRModeInfo *) (outputs + g_numOutputs); + names = (CARD8 *) (modeinfos + g_numModes); + for (index = 0; index < g_numCrtcs; index++) + { + crtcs[index] = g_crtcs[index].id; + } + for (index = 0; index < g_numOutputs; index++) + { + outputs[index] = g_outputs[index].id; + } + for (index = 0; index < g_numModes; index++) + { + modeinfos[index] = g_modes[index]; + memcpy(names, g_modeNames[index], g_modes[index].nameLength); + names += g_modes[index].nameLength; + } + WriteToClient(client, sizeof(rep), &rep); + if (extraLen != 0) + { + WriteToClient(client, extraLen, extra); + free(extra); + } + return Success; +} + +#define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32) + +/******************************************************************************/ +/* 9 */ +/* RRGetOutputInfo + output: OUTPUT + config-timestamp: TIMESTAMP + x + status: RRCONFIGSTATUS + timestamp: TIMESTAMP + crtc: CRTC + name: STRING + connection: CONNECTION + subpixel-order: SUBPIXELORDER + widthInMillimeters, heightInMillimeters: CARD32 + crtcs: LISTofCRTC + clones: LISTofOUTPUT + modes: LISTofMODE + num-preferred: CARD16 */ +int +ProcLRRGetOutputInfo(ClientPtr client) +{ + int index; + CARD8 *extra; + unsigned long extraLen; + LRROutputRec *output; + RRCrtc *crtcs; + RRMode *modes; + char *name; + xRRGetOutputInfoReply rep; + REQUEST(xRRGetOutputInfoReq); + + LLOGLN(10, ("ProcLRRGetOutputInfo: client %p", client)); + REQUEST_SIZE_MATCH(xRRGetOutputInfoReq); + + if ((stuff->output < LRROutputStart) || + (stuff->output >= LRROutputStart + LRRMaxOutputs)) + { + return BadRequest; + } + output = g_outputs + (stuff->output - LRROutputStart); + + memset(&rep, 0, sizeof(rep)); + LLOGLN(10, ("ProcLRRGetOutputInfo: stuff->output %d", stuff->output)); + rep.type = X_Reply; + rep.status = RRSetConfigSuccess; + rep.sequenceNumber = client->sequence; + rep.length = bytes_to_int32(OutputInfoExtra); + rep.timestamp = g_updateTime; + rep.crtc = OUTPUT2CRTC(stuff->output); + rep.mmWidth = 0; + rep.mmHeight = 0; + rep.connection = RR_Connected; + rep.subpixelOrder = SubPixelUnknown; + rep.nCrtcs = 1; + rep.nModes = 1; + rep.nPreferred = 1; + rep.nClones = 0; + rep.nameLength = strlen(output->name); + extraLen = (rep.nCrtcs + rep.nModes + bytes_to_int32(rep.nameLength)) << 2; + if (extraLen != 0) + { + rep.length += bytes_to_int32(extraLen); + extra = calloc(1, extraLen); + if (extra == NULL) + { + return BadAlloc; + } + } + else + { + extra = NULL; + } + crtcs = (RRCrtc *) extra; + modes = (RRMode *) (crtcs + rep.nCrtcs); + name = (char *) (modes + rep.nModes); + for (index = 0; index < rep.nCrtcs; index++) + { + crtcs[index] = OUTPUT2CRTC(stuff->output); + } + for (index = 0; index < rep.nModes; index++) + { + modes[index] = OUTPUT2MODE(stuff->output); + } + memcpy(name, output->name, rep.nameLength); + WriteToClient(client, sizeof(rep), &rep); + if (extraLen != 0) + { + WriteToClient(client, extraLen, extra); + free(extra); + } + return Success; + +} + +/******************************************************************************/ +/* 10 */ +/* RRListOutputProperties + output:OUTPUT + x + atoms: LISTofATOM */ +static int +ProcLRRListOutputProperties(ClientPtr client) +{ + xRRListOutputPropertiesReply rep; + REQUEST(xRRListOutputPropertiesReq); + + (void) stuff; + + LLOGLN(10, ("ProcLRRListOutputProperties: client %p", client)); + REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +/******************************************************************************/ +/* 11 */ +/* RRQueryOutputProperty + output: OUTPUT + property: ATOM + x + pending: BOOL + range: BOOL + immutable: BOOL + valid-values: LISTofINT32 */ +static int +ProcLRRQueryOutputProperty(ClientPtr client) +{ + xRRQueryOutputPropertyReply rep; + + LLOGLN(10, ("ProcLRRQueryOutputProperty: client %p", client)); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +/******************************************************************************/ +/* 15 */ +/* RRGetOutputProperty + output: OUTPUT + property: ATOM + type: ATOM or AnyPropertyType + long-offset, long-length: CARD32 + delete: BOOL + pending: BOOL + x + type: ATOM or None + format: {0, 8, 16, 32} + bytes-after: CARD32 + value: LISTofINT8 or LISTofINT16 or LISTofINT32 */ +static int +ProcLRRGetOutputProperty(ClientPtr client) +{ + xRRGetOutputPropertyReply rep; + REQUEST(xRRGetOutputPropertyReq); + + (void) stuff; + + LLOGLN(10, ("ProcLRRGetOutputProperty: client %p", client)); + REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +/******************************************************************************/ +/* 20 */ +/* RRGetCrtcInfo + crtc: CRTC + config-timestamp: TIMESTAMP + x + status: RRCONFIGSTATUS + timestamp: TIMESTAMP + x, y: INT16 + width, height: CARD16 + mode: MODE + rotation: ROTATION + outputs: LISTofOUTPUT + rotations: SETofROTATION + possible-outputs: LISTofOUTPUT */ +int +ProcLRRGetCrtcInfo(ClientPtr client) +{ + RROutput output; + LRRCrtcRec *crtc; + xRRGetCrtcInfoReply rep; + REQUEST(xRRGetCrtcInfoReq); + + LLOGLN(10, ("ProcLRRGetCrtcInfo: client %p crtc %d", client, stuff->crtc)); + REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); + + if ((stuff->crtc < LRRCrtcStart) || + (stuff->crtc >= LRRCrtcStart + LRRMaxCrtcs)) + { + return BadRequest; + } + crtc = g_crtcs + (stuff->crtc - LRRCrtcStart); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.status = RRSetConfigSuccess; + rep.sequenceNumber = client->sequence; + rep.timestamp = g_updateTime; + rep.x = crtc->x; + rep.y = crtc->y; + rep.width = crtc->width; + rep.height = crtc->height; + rep.mode = CRTC2MODE(stuff->crtc); + rep.nOutput = 1; + rep.nPossibleOutput = 1; + rep.length = rep.nOutput + rep.nPossibleOutput; + rep.rotation = RR_Rotate_0; + rep.rotations = RR_Rotate_0; + output = CRTC2OUTPUT(stuff->crtc); + WriteToClient(client, sizeof(rep), &rep); + WriteToClient(client, sizeof(output), &output); + WriteToClient(client, sizeof(output), &output); + return 0; +} + +/******************************************************************************/ +/* 21 */ +/* RRSetCrtcConfig + crtc: CRTC + timestamp: TIMESTAMP + config-timestamp: TIMESTAMP + x, y: INT16 + mode: MODE + rotation: ROTATION + outputs: LISTofOUTPUT + x + status: RRCONFIGSTATUS + new-timestamp: TIMESTAMP */ +int +ProcLRRSetCrtcConfig(ClientPtr client) +{ + xRRSetCrtcConfigReply rep; + REQUEST(xRRSetCrtcConfigReq); + TimeStamp ts; + + (void) stuff; + + LLOGLN(10, ("ProcLRRSetCrtcConfig: client %p", client)); + REQUEST_SIZE_MATCH(xRRSetCrtcConfigReq); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.status = RRSetConfigSuccess; + rep.sequenceNumber = client->sequence; + ts = ClientTimeToServerTime(stuff->timestamp); + g_updateTime = ts.milliseconds; + rep.newTimestamp = g_updateTime; + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +/******************************************************************************/ +/* 22 */ +/* RRGetCrtcGammaSize + crtc: CRTC + x + size: CARD16 */ +int +ProcLRRGetCrtcGammaSize(ClientPtr client) +{ + xRRGetCrtcGammaSizeReply rep; + REQUEST(xRRGetCrtcGammaSizeReq); + + (void) stuff; + + LLOGLN(10, ("ProcLRRGetCrtcGammaSize: client %p", client)); + REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.size = 256; + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +/******************************************************************************/ +/* 23 */ +/* RRGetCrtcGamma + crtc: CRTC + x + red: LISTofCARD16 + green: LISTofCARD16 + blue: LISTofCARD16 */ +int +ProcLRRGetCrtcGamma(ClientPtr client) +{ + xRRGetCrtcGammaReply rep; + unsigned long len; + unsigned short *vals; + unsigned short val; + char *extra; + int index; + REQUEST(xRRGetCrtcGammaReq); + + (void) stuff; + + LLOGLN(10, ("ProcLRRGetCrtcGamma: client %p", client)); + REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); + len = 256 * 3 * 2; + extra = (char *) malloc(len); + if (extra == NULL) + { + return BadAlloc; + } + vals = (unsigned short *) extra; + /* red */ + for (index = 0; index < 256; index++) + { + val = (0xffff * index) / 255; + vals[0] = val; + vals += 1; + } + /* green */ + for (index = 0; index < 256; index++) + { + val = (0xffff * index) / 255; + vals[0] = val; + vals += 1; + } + /* blue */ + for (index = 0; index < 256; index++) + { + val = (0xffff * index) / 255; + vals[0] = val; + vals += 1; + } + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = bytes_to_int32(len); + rep.size = 256; + WriteToClient(client, sizeof(rep), &rep); + WriteToClient(client, len, extra); + return Success; +} + +/******************************************************************************/ +/* 25 */ +/* RRGetScreenResourcesCurrent + window: WINDOW + x + timestamp: TIMESTAMP + config-timestamp: TIMESTAMP + crtcs: LISTofCRTC + outputs: LISTofOUTPUT + modes: LISTofMODEINFO */ +int +ProcLRRGetScreenResourcesCurrent(ClientPtr client) +{ + LLOGLN(10, ("ProcLRRGetScreenResourcesCurrent: client %p", client)); + return ProcLRRGetScreenResources(client); +} + +#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) +#define ToFixed(f) ((int) ((f) * 65536)) + +/******************************************************************************/ +/* 27 */ +/* RRGetCrtcTransform + crtc: CRTC + x + pending-transform: TRANSFORM + pending-filter: STRING8 + pending-values: LISTofFIXED + current-transform: TRANSFORM + current-filter: STRING8 + current-values: LISTofFIXED */ +int +ProcLRRGetCrtcTransform(ClientPtr client) +{ + xRRGetCrtcTransformReply rep; + REQUEST(xRRGetCrtcTransformReq); + + (void) stuff; + + LLOGLN(10, ("ProcLRRGetCrtcTransform: client %p", client)); + REQUEST_SIZE_MATCH(xRRGetPanningReq); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.currentTransform.matrix11 = ToFixed(1); + rep.currentTransform.matrix22 = ToFixed(1); + rep.currentTransform.matrix33 = ToFixed(1); + rep.length = bytes_to_int32(CrtcTransformExtra); + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +/******************************************************************************/ +/* 28 */ +/* RRGetPanning + crtc: CRTC + x + status: RRCONFIGSTATUS + timestamp: TIMESTAMP + left, top, width, height: CARD16 + track_left, track_top, track_width, track_height: CARD16 + border_left, border_top, border_right, border_bottom: INT16 */ +int +ProcLRRGetPanning(ClientPtr client) +{ + xRRGetPanningReply rep; + REQUEST(xRRGetPanningReq); + + (void) stuff; + + LLOGLN(10, ("ProcLRRGetPanning: client %p", client)); + REQUEST_SIZE_MATCH(xRRGetPanningReq); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.status = RRSetConfigSuccess; + rep.sequenceNumber = client->sequence; + rep.length = 1, + rep.timestamp = g_updateTime; + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +/******************************************************************************/ +/* 31 */ +/* RRGetOutputPrimary + window: WINDOW + x + output: OUTPUT */ +int +ProcLRRGetOutputPrimary(ClientPtr client) +{ + xRRGetOutputPrimaryReply rep; + REQUEST(xRRGetOutputPrimaryReq); + + (void) stuff; + + LLOGLN(10, ("ProcLRRGetOutputPrimary: client %p", client)); + REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq); + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.output = g_primaryOutput; + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +/******************************************************************************/ +static int +ProcLRRDispatch(ClientPtr client) +{ + REQUEST(xReq); + + LLOGLN(10, ("ProcLRRDispatch: data %d", stuff->data)); + if (stuff->data >= LRRNumberRequests) + { + LLOGLN(0, ("ProcLRRDispatch: returning BadRequest, data %d", + stuff->data)); + return BadRequest; + } + if (g_procLRandrVector[stuff->data] == NULL) + { + LLOGLN(0, ("ProcLRRDispatch: returning Success, data %d", + stuff->data)); + return Success; + } + return g_procLRandrVector[stuff->data](client); +} + +/******************************************************************************/ +static int +SProcLRRDispatch(ClientPtr client) +{ + LLOGLN(0, ("SProcLRRDispatch:")); + return 0; +} + +/******************************************************************************/ +static void +LRRClientCallback(CallbackListPtr *list, void *closure, void *data) +{ + NewClientInfoRec *clientinfo; + ClientPtr pClient; + + LLOGLN(10, ("LRRClientCallback: list %p closure %p data %p", + list, closure, data)); + if (data != NULL) + { + clientinfo = (NewClientInfoRec *) data; + if (clientinfo->client != NULL) + { + pClient = clientinfo->client; + LLOGLN(10, ("LRRClientCallback: clientState %d clientGone %d", + pClient->clientState, pClient->clientGone)); + if (pClient->clientGone || + (pClient->clientState == ClientStateRetained) || + (pClient->clientState == ClientStateGone)) + { + LLOGLN(10, ("LRRClientCallback: client gone")); + remove_client(pClient); + } + } + } +} + +/******************************************************************************/ +int +rdpLRRInit(rdpPtr dev) +{ + ExtensionEntry *extEntry; + int index; + + LLOGLN(10, ("rdpLRRInit:")); + if (!AddCallback(&ClientStateCallback, LRRClientCallback, 0)) + { + LLOGLN(0, ("rdpLRRInit: AddCallback failed")); + return 1; + } + LLOGLN(0, ("rdpLRRInit: AddCallback ok")); + + extEntry = AddExtension(LRANDR_NAME, + LRRNumberEvents, LRRNumberErrors, + ProcLRRDispatch, SProcLRRDispatch, + NULL, StandardMinorOpcode); + if (extEntry == NULL) + { + LLOGLN(0, ("rdpLRRInit: AddExtension failed")); + return 1; + } + LLOGLN(0, ("rdpLRRInit: AddExtension ok")); + + LRRErrorBase = extEntry->errorBase; + LRREventBase = extEntry->eventBase; + + for (index = 0; index < LRRMaxCrtcs; index++) + { + g_crtcs[index].id = index + LRRCrtcStart; + } + + for (index = 0; index < LRRMaxOutputs; index++) + { + g_outputs[index].id = index + LRROutputStart; + snprintf(g_outputs[index].name, LRRMaxOutputNameLength, + "rdp%d", index); + } + + for (index = 0; index < LRRMaxModes; index++) + { + g_modes[index].id = index + LRRModeStart; + } + + xorg_list_init(&g_interestedClients); + + memset(g_procLRandrVector, 0, sizeof(g_procLRandrVector)); + g_procLRandrVector[0] = ProcLRRQueryVersion; + //g_procLRandrVector[2] = ProcLRRSetScreenConfig; TODO + g_procLRandrVector[4] = ProcLRRSelectInput; + g_procLRandrVector[5] = ProcLRRGetScreenInfo; + /* V1.2 additions */ + g_procLRandrVector[6] = ProcLRRGetScreenSizeRange; + //g_procLRandrVector[7] = ProcLRRSetScreenSize; ok + g_procLRandrVector[8] = ProcLRRGetScreenResources; + g_procLRandrVector[9] = ProcLRRGetOutputInfo; + g_procLRandrVector[10] = ProcLRRListOutputProperties; + g_procLRandrVector[11] = ProcLRRQueryOutputProperty; + //g_procLRandrVector[12] = ProcLRRConfigureOutputProperty; ok + //g_procLRandrVector[13] = ProcLRRChangeOutputProperty; ok + //g_procLRandrVector[14] = ProcLRRDeleteOutputProperty; ok + g_procLRandrVector[15] = ProcLRRGetOutputProperty; + //g_procLRandrVector[16] = ProcLRRCreateMode; ok + //g_procLRandrVector[17] = ProcLRRDestroyMode; ok + //g_procLRandrVector[18] = ProcLRRAddOutputMode; ok + //g_procLRandrVector[19] = ProcLRRDeleteOutputMode; ok + g_procLRandrVector[20] = ProcLRRGetCrtcInfo; + g_procLRandrVector[21] = ProcLRRSetCrtcConfig; + g_procLRandrVector[22] = ProcLRRGetCrtcGammaSize; + g_procLRandrVector[23] = ProcLRRGetCrtcGamma; + //g_procLRandrVector[24] = ProcLRRSetCrtcGamma; ok + /* V1.3 additions */ + g_procLRandrVector[25] = ProcLRRGetScreenResourcesCurrent; + //g_procLRandrVector[26] = ProcLRRSetCrtcTransform; ok + g_procLRandrVector[27] = ProcLRRGetCrtcTransform; + g_procLRandrVector[28] = ProcLRRGetPanning; + //g_procLRandrVector[29] = ProcLRRSetPanning; TODO + //g_procLRandrVector[30] = ProcLRRSetOutputPrimary; ok + g_procLRandrVector[31] = ProcLRRGetOutputPrimary; + rdpLRRSetRdpOutputs(dev); + return 0; +} + +/******************************************************************************/ +static void +LRRSendConfigNotify(ScreenPtr pScreen) +{ + WindowPtr pWin; + xEvent event; + + pWin = pScreen->root; + memset(&event, 0, sizeof(event)); + event.u.configureNotify.window = pWin->drawable.id; + event.u.configureNotify.width = pWin->drawable.width; + event.u.configureNotify.height = pWin->drawable.height; + event.u.configureNotify.borderWidth = wBorderWidth(pWin); + event.u.configureNotify.override = pWin->overrideRedirect; + event.u.u.type = ConfigureNotify; + DeliverEvents(pWin, &event, 1, NullWindow); +} + +/******************************************************************************/ +Bool +rdpLRRSetRdpOutputs(rdpPtr dev) +{ + interestedClientRec *iterator; + interestedClientRec *next; + char modeName[LRRMaxModesNameLength]; + int width; + int height; + int index; + int count; + int cont; + + LLOGLN(10, ("rdpLRRSetRdpOutputs: numCrtcs %d numOutputs %d " + "monitorCount %d", + g_numCrtcs, g_numOutputs, dev->monitorCount)); + LRRSendConfigNotify(dev->pScreen); + g_primaryOutput = None; + width = dev->width; + height = dev->height; + LLOGLN(10, ("rdpLRRSetRdpOutputs: width %d height %d", width, height)); + if (dev->monitorCount <= 0) + { + g_numCrtcs = 1; + g_crtcs[0].x = 0; + g_crtcs[0].y = 0; + g_crtcs[0].width = width; + g_crtcs[0].height = height; + g_numOutputs = 1; + g_numModes = 1; + g_modes[0].width = width; + g_modes[0].height = height; + g_modes[0].hTotal = width; + g_modes[0].vTotal = height; + g_modes[0].dotClock = 50 * width * height; + snprintf(modeName, LRRMaxModesNameLength, "%dx%d", width, height); + g_modes[0].nameLength = strlen(modeName); + memcpy(g_modeNames[0], modeName, g_modes[0].nameLength); + } + else + { + count = dev->monitorCount; + if (count > 16) + { + count = 16; + } + g_numCrtcs = count; + g_numOutputs = count; + g_numModes = count; + for (index = 0; index < count; index++) + { + g_crtcs[index].x = dev->minfo[index].left; + g_crtcs[index].y = dev->minfo[index].top; + width = dev->minfo[index].right - dev->minfo[index].left + 1; + height = dev->minfo[index].bottom - dev->minfo[index].top + 1; + g_crtcs[index].width = width; + g_crtcs[index].height = height; + g_modes[index].width = width; + g_modes[index].height = height; + g_modes[index].hTotal = width; + g_modes[index].vTotal = height; + g_modes[index].dotClock = 50 * width * height; + snprintf(modeName, LRRMaxModesNameLength, "%dx%d", width, height); + g_modes[index].nameLength = strlen(modeName); + memcpy(g_modeNames[index], modeName, g_modes[index].nameLength); + if (dev->minfo[index].is_primary) + { + g_primaryOutput = g_outputs[index].id; + } + } + } + g_updateTime = GetTimeInMillis(); + xorg_list_for_each_entry_safe(iterator, next, &g_interestedClients, entry) + { + cont = 0; + LLOGLN(10, ("rdpLRRSetRdpOutputs: client %p", + iterator->pClient)); + if (iterator->mask & RRScreenChangeNotifyMask) + { + if (LRRDeliverScreenEvent(iterator, dev->pScreen) != 0) + { + LLOGLN(0, ("rdpLRRSetRdpOutputs: error removing from " + "interested list")); + xorg_list_del(&(iterator->entry)); + free(iterator); + continue; + } + } + if (iterator->mask & RRCrtcChangeNotifyMask) + { + for (index = 0; index < g_numCrtcs; index++) + { + if (LRRDeliverCrtcEvent(iterator, g_crtcs + index) != 0) + { + LLOGLN(0, ("rdpLRRSetRdpOutputs: error removing from " + "interested list")); + xorg_list_del(&(iterator->entry)); + free(iterator); + cont = 1; + break; + } + } + if (cont) + { + continue; + } + } + if (iterator->mask & RROutputChangeNotifyMask) + { + for (index = 0; index < g_numOutputs; index++) + { + if (LRRDeliverOutputEvent(iterator, g_outputs + index) != 0) + { + LLOGLN(0, ("rdpLRRSetRdpOutputs: error removing from " + "interested list")); + xorg_list_del(&(iterator->entry)); + free(iterator); + cont = 1; + break; + } + } + if (cont) + { + continue; + } + } + } + return TRUE; +} diff --git a/module/rdpLRandR.h b/module/rdpLRandR.h new file mode 100644 index 00000000..d80c386a --- /dev/null +++ b/module/rdpLRandR.h @@ -0,0 +1,9 @@ +#ifndef _RDPLRANDR_H +#define _RDPLRANDR_H + +int +rdpLRRInit(rdpPtr dev); +Bool +rdpLRRSetRdpOutputs(rdpPtr dev); + +#endif diff --git a/module/rdpMain.c b/module/rdpMain.c index 59b7e029..ebf8bac6 100644 --- a/module/rdpMain.c +++ b/module/rdpMain.c @@ -1,5 +1,5 @@ /* -Copyright 2013-2017 Jay Sorg +Copyright 2013-2024 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -41,12 +41,43 @@ rdp module main #include #include #include +#include + +#include +#include + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(21, 1, 4, 0, 0) +#define XACE_DISABLE_DRI3_PRESENT +#endif + +#ifdef XACE_DISABLE_DRI3_PRESENT +#include +#include +#endif #include "rdp.h" #include "rdpInput.h" #include "rdpDraw.h" #include "rdpClientCon.h" #include "rdpMain.h" +#include "rdpPri.h" +#include "rdpPixmap.h" +#include "rdpGC.h" +#include "rdpMisc.h" +#include "rdpComposite.h" +#include "rdpGlyphs.h" +#include "rdpTrapezoids.h" +#include "rdpTriangles.h" +#include "rdpCompositeRects.h" +#include "rdpCursor.h" +#include "rdpSimd.h" +#include "rdpReg.h" +#ifdef XORGXRDP_LRANDR +#include "rdpRandR.h" +#include "rdpLRandR.h" +#else +#include "rdpRandR.h" +#endif /******************************************************************************/ #define LOG_LEVEL 1 @@ -55,6 +86,418 @@ rdp module main static Bool g_initialised = FALSE; +static Bool g_nvidia_wrap_done = FALSE; +static DriverRec g_saved_driver; + +static OsTimerPtr g_timer = NULL; +static xf86PreInitProc *g_orgPreInit; +static xf86ScreenInitProc *g_orgScreenInit; + +extern DriverPtr *xf86DriverList; +extern int xf86NumDrivers; + +/*****************************************************************************/ +static Bool +xorgxrdpPreInit(ScrnInfoPtr pScrn, int flags) +{ + Bool rv; + + LLOGLN(0, ("xorgxrdpPreInit:")); + rv = g_orgPreInit(pScrn, flags); + if (rv) + { + pScrn->reservedPtr[0] = xnfcalloc(sizeof(rdpRec), 1); +#if defined(RANDR) && defined(XORGXRDP_LRANDR) + noRRExtension = TRUE; /* do not use built in randr */ +#endif + } + return rv; +} + +/******************************************************************************/ +static miPointerSpriteFuncRec g_rdpSpritePointerFuncs = +{ + /* these are in rdpCursor.c */ + rdpSpriteRealizeCursor, + rdpSpriteUnrealizeCursor, + rdpSpriteSetCursor, + rdpSpriteMoveCursor, + rdpSpriteDeviceCursorInitialize, + rdpSpriteDeviceCursorCleanup +}; + +/******************************************************************************/ +static void +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 5, 0, 0) +rdpBlockHandler1(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) +#else +rdpBlockHandler1(void *blockData, void *pTimeout) +#endif +{ +} + +/******************************************************************************/ +static void +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 5, 0, 0) +rdpWakeupHandler1(pointer blockData, int result, pointer pReadmask) +#else +rdpWakeupHandler1(void *blockData, int result) +#endif +{ + rdpClientConCheck((ScreenPtr)blockData); +} + +/*****************************************************************************/ +static Bool +rdpCreateScreenResources(ScreenPtr pScreen) +{ + Bool ret; + rdpPtr dev; + + LLOGLN(0, ("rdpCreateScreenResources:")); + dev = rdpGetDevFromScreen(pScreen); + pScreen->CreateScreenResources = dev->CreateScreenResources; + ret = pScreen->CreateScreenResources(pScreen); + pScreen->CreateScreenResources = rdpCreateScreenResources; + if (!ret) + { + return FALSE; + } + dev->screenSwPixmap = pScreen->CreatePixmap(pScreen, + dev->width, dev->height, + dev->depth, + CREATE_PIXMAP_USAGE_SHARED); + dev->pfbMemory = dev->screenSwPixmap->devPrivate.ptr; + dev->paddedWidthInBytes = dev->screenSwPixmap->devKind; + dev->sizeInBytes = dev->paddedWidthInBytes * dev->height; + return TRUE; +} + +/******************************************************************************/ +static Bool +xorgxrdpRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height, + CARD32 mmWidth, CARD32 mmHeight) +{ + Bool rv; + rdpPtr dev; + rrScrPrivPtr pRRScrPriv; + + LLOGLN(0, ("xorgxrdpRRScreenSetSize: width %d height %d", width, height)); + dev = rdpGetDevFromScreen(pScreen); + + pRRScrPriv = rrGetScrPriv(pScreen); + pRRScrPriv->rrScreenSetSize = dev->rrScreenSetSize; + rv = pRRScrPriv->rrScreenSetSize(pScreen, width, height, mmWidth, mmHeight); + pRRScrPriv->rrScreenSetSize = xorgxrdpRRScreenSetSize; + + dev->width = width; + dev->height = height; + + pScreen->DestroyPixmap(dev->screenSwPixmap); + dev->screenSwPixmap = pScreen->CreatePixmap(pScreen, + dev->width, dev->height, + dev->depth, + CREATE_PIXMAP_USAGE_SHARED); + dev->pfbMemory = dev->screenSwPixmap->devPrivate.ptr; + dev->paddedWidthInBytes = dev->screenSwPixmap->devKind; + dev->sizeInBytes = dev->paddedWidthInBytes * dev->height; + + LLOGLN(0, ("xorgxrdpRRScreenSetSize: screenInfo x %d y %d " + "width %d height %d", screenInfo.x, screenInfo.y, + screenInfo.width, screenInfo.height)); + + return rv; +} + +/*****************************************************************************/ +static void +xorgxrdpDamageReport(DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + rdpPtr dev; + ScreenPtr pScreen; + + LLOGLN(10, ("xorgxrdpDamageReport:")); + pScreen = (ScreenPtr)closure; + dev = rdpGetDevFromScreen(pScreen); + rdpClientConAddAllReg(dev, pRegion, &(pScreen->root->drawable)); +} + +/*****************************************************************************/ +static void +xorgxrdpDamageDestroy(DamagePtr pDamage, void *closure) +{ + LLOGLN(0, ("xorgxrdpDamageDestroy:")); +} + +#ifdef XACE_DISABLE_DRI3_PRESENT +/*****************************************************************************/ +static void +xorgxrdpExtension(CallbackListPtr *pcbl, void *unused, void *calldata) +{ + XaceExtAccessRec *rec = calldata; + LLOGLN(10, ("xorgxrdpExtension:")); + LLOGLN(10, (" name %s", rec->ext->name)); + if (strcmp(rec->ext->name, "DRI3") == 0) + { + LLOGLN(10, (" disabling name %s", rec->ext->name)); + rec->status = BadValue; + } + if (strcmp(rec->ext->name, "Present") == 0) + { + LLOGLN(10, (" disabling name %s", rec->ext->name)); + rec->status = BadValue; + } +} +#endif + +/******************************************************************************/ +/* returns error */ +static CARD32 +xorgxrdpDeferredStartup(OsTimerPtr timer, CARD32 now, pointer arg) +{ + rdpPtr dev; + ScreenPtr pScreen; + + LLOGLN(0, ("xorgxrdpDeferredStartup:")); + pScreen = (ScreenPtr)arg; + if (pScreen->root != NULL) + { + dev = rdpGetDevFromScreen(pScreen); +#if defined(XORGXRDP_LRANDR) + rdpLRRInit(dev); +#endif + dev->damage = DamageCreate(xorgxrdpDamageReport, xorgxrdpDamageDestroy, + DamageReportRawRegion, TRUE, + pScreen, pScreen); + if (dev->damage != NULL) + { + DamageSetReportAfterOp(dev->damage, TRUE); + DamageRegister(&(pScreen->root->drawable), dev->damage); + LLOGLN(0, ("xorgxrdpSetupDamage: DamageRegister ok")); + TimerFree(g_timer); + g_timer = NULL; +#ifdef XACE_DISABLE_DRI3_PRESENT + if (getenv("XORGXRDP_NO_XACE_DISABLE_DRI3_PRESENT") == NULL) + { + XaceRegisterCallback(XACE_EXT_ACCESS, xorgxrdpExtension, NULL); + } +#endif + return 0; + } + } + g_timer = TimerSet(g_timer, 0, 1, xorgxrdpDeferredStartup, pScreen); + return 0; +} + +/*****************************************************************************/ +static Bool +xorgxrdpScreenInit(ScreenPtr pScreen, int argc, char** argv) +{ + Bool rv; + rdpPtr dev; + ScrnInfoPtr pScrn; + PictureScreenPtr ps; + miPointerScreenPtr PointPriv; + rrScrPrivPtr pRRScrPriv; + + LLOGLN(0, ("xorgxrdpScreenInit:")); + rv = g_orgScreenInit(pScreen, argc, argv); + if (rv) + { + pScrn = xf86Screens[pScreen->myNum]; + dev = XRDPPTR(pScrn); + dev->nvidia = TRUE; + dev->pScreen = pScreen; + dev->depth = pScrn->depth; + dev->width = pScrn->virtualX; + dev->height = pScrn->virtualY; + dev->paddedWidthInBytes = PixmapBytePad(dev->width, dev->depth); + dev->bitsPerPixel = rdpBitsPerPixel(dev->depth); + dev->sizeInBytes = dev->paddedWidthInBytes * dev->height; + + LLOGLN(0, ("xorgxrdpScreenInit: width %d height %d", dev->width, dev->height)); + + PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); + PointPriv->spriteFuncs = &g_rdpSpritePointerFuncs; + + dev->privateKeyRecGC = rdpAllocateGCPrivate(pScreen, sizeof(rdpGCRec)); + dev->privateKeyRecPixmap = rdpAllocatePixmapPrivate(pScreen, sizeof(rdpPixmapRec)); + + dev->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = rdpCloseScreen; + + dev->CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = rdpCopyWindow; + + dev->CreateGC = pScreen->CreateGC; + pScreen->CreateGC = rdpCreateGC; + + dev->CreatePixmap = pScreen->CreatePixmap; + pScreen->CreatePixmap = rdpCreatePixmap; + + dev->DestroyPixmap = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = rdpDestroyPixmap; + + dev->ModifyPixmapHeader = pScreen->ModifyPixmapHeader; + pScreen->ModifyPixmapHeader = rdpModifyPixmapHeader; + + ps = GetPictureScreenIfSet(pScreen); + if (ps != 0) + { + /* composite */ + dev->Composite = ps->Composite; + ps->Composite = rdpComposite; + /* glyphs */ + dev->Glyphs = ps->Glyphs; + ps->Glyphs = rdpGlyphs; + /* trapezoids */ + dev->Trapezoids = ps->Trapezoids; + ps->Trapezoids = rdpTrapezoids; + /* triangles */ + dev->Triangles = ps->Triangles; + ps->Triangles = rdpTriangles; + /* composite rects */ + dev->CompositeRects = ps->CompositeRects; + ps->CompositeRects = rdpCompositeRects; + } + + dev->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = rdpCreateScreenResources; + + RegisterBlockAndWakeupHandlers(rdpBlockHandler1, rdpWakeupHandler1, pScreen); + + if (rdpClientConInit(dev) != 0) + { + LLOGLN(0, ("xorgxrdpScreenInit: rdpClientConInit failed")); + } + + dev->Bpp_mask = 0x00FFFFFF; + dev->Bpp = 4; + dev->bitsPerPixel = 32; + + rdpSimdInit(pScreen, pScrn); + pRRScrPriv = rrGetScrPriv(pScreen); + if (pRRScrPriv != NULL) + { + dev->rrSetConfig = pRRScrPriv->rrSetConfig; + dev->rrGetInfo = pRRScrPriv->rrGetInfo; + dev->rrScreenSetSize = pRRScrPriv->rrScreenSetSize; + dev->rrCrtcSet = pRRScrPriv->rrCrtcSet; + dev->rrCrtcSetGamma = pRRScrPriv->rrCrtcSetGamma; + dev->rrCrtcGetGamma = pRRScrPriv->rrCrtcGetGamma; + dev->rrOutputSetProperty = pRRScrPriv->rrOutputSetProperty; + dev->rrOutputValidateMode = pRRScrPriv->rrOutputValidateMode; + dev->rrModeDestroy = pRRScrPriv->rrModeDestroy; + dev->rrOutputGetProperty = pRRScrPriv->rrOutputGetProperty; + dev->rrGetPanning = pRRScrPriv->rrGetPanning; + dev->rrSetPanning = pRRScrPriv->rrSetPanning; + pRRScrPriv->rrScreenSetSize = xorgxrdpRRScreenSetSize; + } + g_timer = TimerSet(g_timer, 0, 1, xorgxrdpDeferredStartup, pScreen); + } + return rv; +} + +/*****************************************************************************/ +static Bool +xorgxrdpWrapPreIntScreenInit(Bool ok) +{ + if (ok && (g_orgPreInit == NULL)) + { + if ((xf86Screens != NULL) && (xf86Screens[0] != NULL)) + { + if ((xf86Screens[0]->PreInit != NULL) && + (xf86Screens[0]->ScreenInit != NULL)) + { + g_orgPreInit = xf86Screens[0]->PreInit; + xf86Screens[0]->PreInit = xorgxrdpPreInit; + g_orgScreenInit = xf86Screens[0]->ScreenInit; + xf86Screens[0]->ScreenInit = xorgxrdpScreenInit; + } + else + { + LLOGLN(0, ("xorgxrdpWrapPreIntScreenInit: error")); + } + } + else + { + LLOGLN(0, ("xorgxrdpWrapPreIntScreenInit: error")); + } + } + return ok; +} + +/*****************************************************************************/ +static Bool +xorgxrdpPciProbe(struct _DriverRec * drv, int entity_num, + struct pci_device * dev, intptr_t match_data) +{ + Bool rv; + + LLOGLN(0, ("xorgxrdpPciProbe:")); + rv = g_saved_driver.PciProbe(drv, entity_num, dev, match_data); + return xorgxrdpWrapPreIntScreenInit(rv); +} + +/*****************************************************************************/ +static Bool +xorgxrdpPlatformProbe(struct _DriverRec * drv, int entity_num, int flags, + struct xf86_platform_device * dev, intptr_t match_data) +{ + Bool rv; + + LLOGLN(0, ("xorgxrdpPlatformProbe:")); + rv = g_saved_driver.platformProbe(drv, entity_num, flags, dev, match_data); + return xorgxrdpWrapPreIntScreenInit(rv); +} + +/*****************************************************************************/ +static Bool +xorgxrdpDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) +{ + xorgHWFlags *flags; + Bool rv; + + LLOGLN(0, ("xorgxrdpDriverFunc:")); + rv = g_saved_driver.driverFunc(pScrn, op, ptr); + if (op == GET_REQUIRED_HW_INTERFACES) + { + flags = (xorgHWFlags *) ptr; + *flags = HW_SKIP_CONSOLE; + rv = TRUE; + } + return rv; +} + +/*****************************************************************************/ +int +xorgxrdpCheckWrap(void) +{ + if (g_nvidia_wrap_done) + { + return 0; + } + if (xf86NumDrivers < 1) + { + return 0; + } + if ((xf86DriverList == NULL) || (xf86DriverList[0] == NULL) || + (xf86DriverList[0]->driverName == NULL)) + { + return 0; + } + if (strcmp(xf86DriverList[0]->driverName, "NVIDIA") == 0) + { + g_saved_driver = *(xf86DriverList[0]); + g_nvidia_wrap_done = TRUE; + LLOGLN(0, ("xorgxrdpCheckWrap: NVIDIA driver found")); + xf86DriverList[0]->PciProbe = xorgxrdpPciProbe; + xf86DriverList[0]->platformProbe = xorgxrdpPlatformProbe; + xf86DriverList[0]->driverFunc = xorgxrdpDriverFunc; + } + return 0; +} + /*****************************************************************************/ static pointer xorgxrdpSetup(pointer Module, pointer Options, diff --git a/module/rdpMain.h b/module/rdpMain.h index b3511980..2a92a25a 100644 --- a/module/rdpMain.h +++ b/module/rdpMain.h @@ -28,6 +28,8 @@ rdp module main #include #include +extern _X_EXPORT int +xorgxrdpCheckWrap(void); extern _X_EXPORT void xorgxrdpDownDown(ScreenPtr pScreen); diff --git a/module/rdpPutImage.c b/module/rdpPutImage.c index d099a417..01aa58f6 100644 --- a/module/rdpPutImage.c +++ b/module/rdpPutImage.c @@ -68,9 +68,69 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y, RegionRec reg; int cd; BoxRec box; + PixmapPtr pixmap; + int *pBits32; + rdpClientCon *clientCon; + ScreenPtr pScreen; LLOGLN(10, ("rdpPutImage:")); + pScreen = pGC->pScreen; dev = rdpGetDevFromScreen(pGC->pScreen); + if ((x == 0) && (y == 0) && (w == 4) && (h == 4) && (depth >= 24) && + (pDst->type == DRAWABLE_PIXMAP)) + { + pBits32 = (int *) pBits; + if (pBits32[0] == 0xDEADBEEF) + { + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + if (clientCon->conNumber == pBits32[1]) + { + /* free old */ + int monitor_index = pBits32[2] & 0xF; + pixmap = clientCon->accelAssistPixmaps[monitor_index]; + if (pixmap != NULL) + { + pScreen->DestroyPixmap(pixmap); + } + /* set new */ + pixmap = (PixmapPtr) pDst; + LLOGLN(0, ("rdpPutImage: setting conNumber %d, monitor num %d " + "to pixmap %p", pBits32[1], monitor_index, pixmap)); + clientCon->accelAssistPixmaps[monitor_index] = pixmap; + /* so it can not get freed early */ + pixmap->refcnt++; + /* invalidate */ + if (dev->monitorCount < 1) + { + LLOGLN(0, ("rdpPutImage: monitor_index %d " + "invalidating 0 0 %d %d", + monitor_index, dev->width, dev->height)); + rdpClientConAddDirtyScreen(dev, clientCon, 0, 0, + dev->width, dev->height); + } + else if (monitor_index < dev->monitorCount) + { + int left = dev->minfo[monitor_index].left; + int top = dev->minfo[monitor_index].top; + int width = dev->minfo[monitor_index].right - + dev->minfo[monitor_index].left + 1; + int height = dev->minfo[monitor_index].bottom - + dev->minfo[monitor_index].top + 1; + LLOGLN(0, ("rdpPutImage: monitor_index %d " + "invalidating %d %d %d %d", + monitor_index, left, top, width, height)); + rdpClientConAddDirtyScreen(dev, clientCon, + left, top , width, height); + } + break; + } + clientCon = clientCon->next; + } + return; + } + } dev->counts.rdpPutImageCallCount++; box.x1 = x + pDst->x; box.y1 = y + pDst->y; diff --git a/module/rdpRandR.c b/module/rdpRandR.c index 612f7169..5b98b040 100644 --- a/module/rdpRandR.c +++ b/module/rdpRandR.c @@ -146,12 +146,12 @@ rdpRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height, } dev->width = width; dev->height = height; - dev->paddedWidthInBytes = PixmapBytePad(dev->width, dev->depth); - dev->sizeInBytes = dev->paddedWidthInBytes * dev->height; pScreen->width = width; pScreen->height = height; pScreen->mmWidth = mmWidth; pScreen->mmHeight = mmHeight; + dev->paddedWidthInBytes = PixmapBytePad(dev->width, dev->depth); + dev->sizeInBytes = dev->paddedWidthInBytes * dev->height; screenPixmap = dev->screenSwPixmap; free(dev->pfbMemory_alloc); dev->pfbMemory_alloc = g_new0(uint8_t, dev->sizeInBytes + 16); @@ -206,6 +206,11 @@ rdpRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height, xf86EnableDisableFBAccess(xf86Screens[pScreen->myNum], FALSE); xf86EnableDisableFBAccess(xf86Screens[pScreen->myNum], TRUE); #endif + + LLOGLN(0, ("rdpRRScreenSetSize: screenInfo x %d y %d " + "width %d height %d", screenInfo.x, screenInfo.y, + screenInfo.width, screenInfo.height)); + return TRUE; } diff --git a/xrdpdev/Makefile.am b/xrdpdev/Makefile.am index c55b7c19..8efc456b 100644 --- a/xrdpdev/Makefile.am +++ b/xrdpdev/Makefile.am @@ -34,5 +34,5 @@ xrdpdev_drv_la_LIBADD = xrdpdevsysconfdir=$(sysconfdir)/X11/xrdp dist_xrdpdevsysconf_DATA = \ - xorg.conf + xorg.conf xorg_nvidia.conf diff --git a/xrdpdev/xorg_nvidia.conf b/xrdpdev/xorg_nvidia.conf new file mode 100644 index 00000000..00b6f574 --- /dev/null +++ b/xrdpdev/xorg_nvidia.conf @@ -0,0 +1,47 @@ +Section "ServerLayout" + Identifier "XRDP GPU Server" + Screen 0 "dGPU" + InputDevice "xrdpMouse" "CorePointer" + InputDevice "xrdpKeyboard" "CoreKeyboard" +EndSection + +Section "ServerFlags" + # This line prevents "ServerLayout" sections in xorg.conf.d files + # overriding the "XRDP GPU Server" layout (xrdp #1784) + Option "DefaultServerLayout" "XRDP GPU Server" + Option "DontVTSwitch" "on" + Option "AutoAddDevices" "off" +EndSection + +Section "Module" + Load "xorgxrdp" +EndSection + +Section "InputDevice" + Identifier "xrdpKeyboard" + Driver "xrdpkeyb" +EndSection + +Section "InputDevice" + Identifier "xrdpMouse" + Driver "xrdpmouse" +EndSection + +Section "Screen" + Identifier "dGPU" + Device "dGPU" + Option "DPI" "96 x 96" +# T4 needs an entry here, this is not the desktop size + SubSection "Display" + Virtual 1920 1080 + EndSubSection +EndSection + +Section "Device" + Identifier "dGPU" + Driver "nvidia" +# T4 may need to comment out next line + Option "UseDisplayDevice" "none" + Option "ConnectToAcpid" "false" + BusID "PCI:3:0:0" +EndSection diff --git a/xrdpdev/xrdpdev.c b/xrdpdev/xrdpdev.c index 5c7d9277..c0c6c7a1 100644 --- a/xrdpdev/xrdpdev.c +++ b/xrdpdev/xrdpdev.c @@ -123,12 +123,12 @@ static Bool rdpAllocRec(ScrnInfoPtr pScrn) { LLOGLN(10, ("rdpAllocRec:")); - if (pScrn->driverPrivate != 0) + if (pScrn->reservedPtr[0] != NULL) { return TRUE; } /* xnfcalloc exits if alloc failed */ - pScrn->driverPrivate = xnfcalloc(sizeof(rdpRec), 1); + pScrn->reservedPtr[0] = xnfcalloc(sizeof(rdpRec), 1); return TRUE; } @@ -137,12 +137,12 @@ static void rdpFreeRec(ScrnInfoPtr pScrn) { LLOGLN(10, ("rdpFreeRec:")); - if (pScrn->driverPrivate == 0) + if (pScrn->reservedPtr[0] == NULL) { return; } - free(pScrn->driverPrivate); - pScrn->driverPrivate = 0; + free(pScrn->reservedPtr[0]); + pScrn->reservedPtr[0] = NULL; } /*****************************************************************************/ diff --git a/xrdpkeyb/rdpKeyboard.c b/xrdpkeyb/rdpKeyboard.c index a15174fa..a3170a70 100644 --- a/xrdpkeyb/rdpKeyboard.c +++ b/xrdpkeyb/rdpKeyboard.c @@ -52,6 +52,7 @@ xrdp keyboard module #include "rdpInput.h" #include "rdpDraw.h" #include "rdpMisc.h" +#include "rdpMain.h" // Check the minimum xrdp client version. #if CLIENT_INFO_CURRENT_VERSION < 20240805 @@ -500,6 +501,7 @@ rdpkeybPlug(pointer module, pointer options, int *errmaj, int *errmin) { LLOGLN(0, ("rdpkeybPlug:")); xf86AddInputDriver(&rdpkeyb, module, 0); + xorgxrdpCheckWrap(); return module; } diff --git a/xrdpmouse/rdpMouse.c b/xrdpmouse/rdpMouse.c index 2221734c..507a9ca9 100644 --- a/xrdpmouse/rdpMouse.c +++ b/xrdpmouse/rdpMouse.c @@ -101,16 +101,34 @@ l_bound_by(int val, int low, int high) static void rdpEnqueueMotion(DeviceIntPtr device, int x, int y) { + int flags; + ValuatorMask *mask; + LLOGLN(10, ("rdpEnqueueMotion:")); - xf86PostMotionEvent(device, TRUE, 0, 2, x, y); + mask = valuator_mask_new(2); + if (mask != NULL) + { + flags = POINTER_ABSOLUTE | POINTER_SCREEN | POINTER_NORAW; + valuator_mask_set(mask, 0, x); + valuator_mask_set(mask, 1, y); + QueuePointerEvents(device, MotionNotify, 0, flags, mask); + valuator_mask_free(&mask); + } } /******************************************************************************/ static void rdpEnqueueButton(DeviceIntPtr device, int type, int buttons) { + ValuatorMask *mask; + LLOGLN(10, ("rdpEnqueueButton:")); - xf86PostButtonEvent(device, FALSE, buttons, type == ButtonPress, 0, 0); + mask = valuator_mask_new(0); + if (mask != NULL) + { + QueuePointerEvents(device, type, buttons, 0, mask); + valuator_mask_free(&mask); + } } /******************************************************************************/