diff options
Diffstat (limited to 'xorg/server/module/rdpClientCon.c')
| -rw-r--r-- | xorg/server/module/rdpClientCon.c | 410 |
1 files changed, 365 insertions, 45 deletions
diff --git a/xorg/server/module/rdpClientCon.c b/xorg/server/module/rdpClientCon.c index 73b08500..3c9cdad5 100644 --- a/xorg/server/module/rdpClientCon.c +++ b/xorg/server/module/rdpClientCon.c @@ -42,6 +42,7 @@ Client connection to xrdp #include "rdpMisc.h" #include "rdpInput.h" #include "rdpReg.h" +#include "rdpCapture.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -115,6 +116,9 @@ rdpClientConGotConnection(ScreenPtr pScreen, rdpPtr dev) LLOGLN(0, ("rdpClientConGotConnection:")); clientCon = (rdpClientCon *) g_malloc(sizeof(rdpClientCon), 1); + clientCon->dev = dev; + dev->do_dirty_ons = 1; + make_stream(clientCon->in_s); init_stream(clientCon->in_s, 8192); make_stream(clientCon->out_s); @@ -154,6 +158,7 @@ rdpClientConGotConnection(ScreenPtr pScreen, rdpPtr dev) } clientCon->dirtyRegion = rdpRegionCreate(NullBox, 0); + clientCon->shmRegion = rdpRegionCreate(NullBox, 0); return 0; } @@ -260,12 +265,15 @@ rdpClientConDisconnect(rdpPtr dev, rdpClientCon *clientCon) dev->clientConTail = plcli; } } + LLOGLN(0, ("rdpClientConDisconnect: clientCon removed from " + "dev list")); break; } plcli = pcli; pcli = pcli->next; } rdpRegionDestroy(clientCon->dirtyRegion); + rdpRegionDestroy(clientCon->shmRegion); g_free(clientCon); return 0; } @@ -568,46 +576,36 @@ rdpClientConProcessScreenSizeMsg(rdpPtr dev, rdpClientCon *clientCon, clientCon->rdp_Bpp_mask = 0xffffff; } -// todo -#if 0 - if (g_use_shmem) + if (clientCon->shmemptr != 0) { - if (g_shmemptr != 0) - { - shmdt(g_shmemptr); - } - bytes = g_rdpScreen.rdp_width * g_rdpScreen.rdp_height * - g_rdpScreen.rdp_Bpp; - g_shmemid = shmget(IPC_PRIVATE, bytes, IPC_CREAT | 0777); - g_shmemptr = shmat(g_shmemid, 0, 0); - shmctl(g_shmemid, IPC_RMID, NULL); - LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: g_shmemid %d g_shmemptr %p", - g_shmemid, g_shmemptr)); - g_shmem_lineBytes = g_rdpScreen.rdp_Bpp * g_rdpScreen.rdp_width; - - if (g_shm_reg != 0) - { - RegionDestroy(g_shm_reg); - } - g_shm_reg = RegionCreate(NullBox, 0); + shmdt(clientCon->shmemptr); } -#endif + bytes = clientCon->rdp_width * clientCon->rdp_height * + clientCon->rdp_Bpp; + clientCon->shmemid = shmget(IPC_PRIVATE, bytes, IPC_CREAT | 0777); + clientCon->shmemptr = shmat(clientCon->shmemid, 0, 0); + shmctl(clientCon->shmemid, IPC_RMID, NULL); + LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: shmemid %d shmemptr %p", + clientCon->shmemid, clientCon->shmemptr)); + clientCon->shmem_lineBytes = clientCon->rdp_Bpp * clientCon->rdp_width; + + if (clientCon->shmRegion != 0) + { + rdpRegionDestroy(clientCon->shmRegion); + } + clientCon->shmRegion = rdpRegionCreate(NullBox, 0); mmwidth = PixelToMM(width); mmheight = PixelToMM(height); -// todo -#if 0 - pSize = RRRegisterSize(g_pScreen, width, height, mmwidth, mmheight); - RRSetCurrentConfig(g_pScreen, RR_Rotate_0, 0, pSize); + pSize = RRRegisterSize(dev->pScreen, width, height, mmwidth, mmheight); + RRSetCurrentConfig(dev->pScreen, RR_Rotate_0, 0, pSize); - if ((g_rdpScreen.width != width) || (g_rdpScreen.height != height)) + if ((dev->width != width) || (dev->height != height)) { - LLOGLN(0, (" calling RRScreenSizeSet")); - ok = RRScreenSizeSet(g_pScreen, width, height, mmwidth, mmheight); - LLOGLN(0, (" RRScreenSizeSet ok=[%d]", ok)); + ok = RRScreenSizeSet(dev->pScreen, width, height, mmwidth, mmheight); + LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: RRScreenSizeSet ok=[%d]", ok)); } -#endif return 0; } @@ -622,6 +620,10 @@ rdpClientConProcessMsgClientInput(rdpPtr dev, rdpClientCon *clientCon) int param2; int param3; int param4; + int x; + int y; + int cx; + int cy; s = clientCon->in_s; in_uint32_le(s, msg); @@ -643,10 +645,13 @@ rdpClientConProcessMsgClientInput(rdpPtr dev, rdpClientCon *clientCon) } else if (msg == 200) /* invalidate */ { - rdpClientConBeginUpdate(dev, clientCon); - rdpClientConSetFgcolor(dev, clientCon, 0x00ff0000); - rdpClientConFillRect(dev, clientCon, 0, 0, dev->width, dev->height); - rdpClientConEndUpdate(dev, clientCon); + x = (param1 >> 16) & 0xffff; + y = param1 & 0xffff; + cx = (param2 >> 16) & 0xffff; + cy = param2 & 0xffff; + LLOGLN(0, ("rdpClientConProcessMsgClientInput: invalidate x %d y %d " + "cx %d cy %d", x, y, cx, cy)); + rdpClientConAddDirtyScreen(dev, clientCon, x, y, cx, cy); } else if (msg == 300) /* resize desktop */ { @@ -761,10 +766,57 @@ static int rdpClientConProcessMsgClientRegion(rdpPtr dev, rdpClientCon *clientCon) { struct stream *s; + int flags; + int x; + int y; + int cx; + int cy; + RegionRec reg; + BoxRec box; + + LLOGLN(10, ("rdpClientConProcessMsgClientRegion:")); + s = clientCon->in_s; + + in_uint32_le(s, flags); + in_uint32_le(s, clientCon->rect_id_ack); + in_uint32_le(s, x); + in_uint32_le(s, y); + in_uint32_le(s, cx); + in_uint32_le(s, cy); + LLOGLN(10, ("rdpClientConProcessMsgClientRegion: %d %d %d %d flags 0x%8.8x", + x, y, cx, cy, flags)); + LLOGLN(10, ("rdpClientConProcessMsgClientRegion: rect_id %d rect_id_ack %d", + clientCon->rect_id, clientCon->rect_id_ack)); + + box.x1 = x; + box.y1 = y; + box.x2 = box.x1 + cx; + box.y2 = box.y1 + cy; + + rdpRegionInit(®, &box, 0); + LLOGLN(10, ("rdpClientConProcessMsgClientRegion: %d %d %d %d", + box.x1, box.y1, box.x2, box.y2)); + rdpRegionSubtract(clientCon->shmRegion, clientCon->shmRegion, ®); + rdpRegionUninit(®); + + return 0; +} - LLOGLN(0, ("rdpClientConProcessMsgClientRegion:")); +/******************************************************************************/ +static int +rdpClientConProcessMsgClientRegionEx(rdpPtr dev, rdpClientCon *clientCon) +{ + struct stream *s; + int flags; + + LLOGLN(10, ("rdpClientConProcessMsgClientRegionEx:")); s = clientCon->in_s; - g_hexdump(s->p, s->end - s->p); + + in_uint32_le(s, flags); + in_uint32_le(s, clientCon->rect_id_ack); + LLOGLN(10, ("rdpClientConProcessMsgClientRegionEx: flags 0x%8.8x", flags)); + LLOGLN(10, ("rdpClientConProcessMsgClientRegionEx: rect_id %d " + "rect_id_ack %d", clientCon->rect_id, clientCon->rect_id_ack)); return 0; } @@ -790,6 +842,9 @@ rdpClientConProcessMsg(rdpPtr dev, rdpClientCon *clientCon) case 105: /* client region */ rdpClientConProcessMsgClientRegion(dev, clientCon); break; + case 106: /* client region ex */ + rdpClientConProcessMsgClientRegionEx(dev, clientCon); + break; default: break; } @@ -1820,11 +1875,148 @@ rdpClientConCheckDirtyScreen(rdpPtr dev, rdpClientCon *clientCon) } /******************************************************************************/ +static int +rdpClientConSendPaintRectShmEx(rdpPtr dev, rdpClientCon *clientCon, + struct image_data *id, + RegionPtr dirtyReg, RegionPtr copyReg) +{ + int index; + int size; + int num_rects_d; + int num_rects_c; + struct stream *s; + BoxRec box; + + rdpClientConBeginUpdate(dev, clientCon); + + num_rects_d = REGION_NUM_RECTS(dirtyReg); + num_rects_c = REGION_NUM_RECTS(copyReg); + size = 2 + 2 + 2 + num_rects_d * 8 + 2 + num_rects_c * 8; + size += 4 + 4 + 4 + 4 + 2 + 2; + rdpClientConPreCheck(dev, clientCon, size); + + s = clientCon->out_s; + out_uint16_le(s, 61); + out_uint16_le(s, size); + clientCon->count++; + + out_uint16_le(s, num_rects_d); + for (index = 0; index < num_rects_d; index++) + { + box = REGION_RECTS(dirtyReg)[index]; + out_uint16_le(s, box.x1); + out_uint16_le(s, box.y1); + out_uint16_le(s, box.x2 - box.x1); + out_uint16_le(s, box.y2 - box.y1); + } + + out_uint16_le(s, num_rects_c); + for (index = 0; index < num_rects_c; index++) + { + box = REGION_RECTS(copyReg)[index]; + out_uint16_le(s, box.x1); + out_uint16_le(s, box.y1); + out_uint16_le(s, box.x2 - box.x1); + out_uint16_le(s, box.y2 - box.y1); + } + + out_uint32_le(s, 0); + clientCon->rect_id++; + out_uint32_le(s, clientCon->rect_id); + out_uint32_le(s, id->shmem_id); + out_uint32_le(s, id->shmem_offset); + out_uint16_le(s, clientCon->rdp_width); + out_uint16_le(s, clientCon->rdp_height); + + rdpClientConEndUpdate(dev, clientCon); + + return 0; +} + +/******************************************************************************/ +static CARD32 +rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) +{ + rdpClientCon *clientCon; + RegionRec reg; + struct image_data id; + + LLOGLN(10, ("rdpDeferredUpdateCallback:")); + clientCon = (rdpClientCon *) arg; + + if (clientCon->rect_id != clientCon->rect_id_ack) + { + LLOGLN(0, ("rdpDeferredUpdateCallback: reschedual")); + clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0, 40, + rdpDeferredUpdateCallback, clientCon); + return 0; + } + else + { + LLOGLN(10, ("rdpDeferredUpdateCallback: sending")); + } + rdpClientConGetScreenImageRect(clientCon->dev, clientCon, &id); + LLOGLN(10, ("rdpDeferredUpdateCallback: rdp_width %d rdp_height %d " + "rdp_Bpp %d screen width %d screen height %d", + clientCon->rdp_width, clientCon->rdp_height, clientCon->rdp_Bpp, + id.width, id.height)); + clientCon->updateSchedualed = FALSE; + rdpRegionInit(®, NullBox, 0); + rdpCapture(clientCon->dirtyRegion, ®, + id.pixels, id.width, id.height, + id.lineBytes, XRDP_a8r8g8b8, + id.shmem_pixels, clientCon->rdp_width, clientCon->rdp_height, + clientCon->rdp_width * clientCon->rdp_Bpp , XRDP_a8r8g8b8, 0); + rdpClientConSendPaintRectShmEx(clientCon->dev, clientCon, &id, + clientCon->dirtyRegion, ®); + rdpRegionDestroy(clientCon->dirtyRegion); + clientCon->dirtyRegion = rdpRegionCreate(NullBox, 0); + rdpRegionUninit(®); + return 0; +} + +/******************************************************************************/ int rdpClientConAddDirtyScreenReg(rdpPtr dev, rdpClientCon *clientCon, RegionPtr reg) { + LLOGLN(10, ("rdpClientConAddDirtyScreenReg:")); + rdpRegionUnion(clientCon->dirtyRegion, clientCon->dirtyRegion, reg); + if (clientCon->updateSchedualed == FALSE) + { + clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0, 40, + rdpDeferredUpdateCallback, clientCon); + clientCon->updateSchedualed = TRUE; + } + return 0; +} + +/******************************************************************************/ +int +rdpClientConAddDirtyScreenBox(rdpPtr dev, rdpClientCon *clientCon, + BoxPtr box) +{ + RegionPtr reg; + + reg = rdpRegionCreate(box, 0); + rdpClientConAddDirtyScreenReg(dev, clientCon, reg); + rdpRegionDestroy(reg); + return 0; +} + +/******************************************************************************/ +int +rdpClientConAddDirtyScreen(rdpPtr dev, rdpClientCon *clientCon, + int x, int y, int cx, int cy) +{ + BoxRec box; + + box.x1 = x; + box.y1 = y; + box.x2 = box.x1 + cx; + box.y2 = box.y1 + cy; + rdpClientConAddDirtyScreenBox(dev, clientCon, &box); return 0; } @@ -1839,10 +2031,10 @@ rdpClientConGetScreenImageRect(rdpPtr dev, rdpClientCon *clientCon, id->Bpp = clientCon->rdp_Bpp; id->lineBytes = dev->paddedWidthInBytes; id->pixels = dev->pfbMemory; - id->shmem_pixels = g_shmemptr; - id->shmem_id = g_shmemid; + id->shmem_pixels = clientCon->shmemptr; + id->shmem_id = clientCon->shmemid; id->shmem_offset = 0; - id->shmem_lineBytes = g_shmem_lineBytes; + id->shmem_lineBytes = clientCon->shmem_lineBytes; } /******************************************************************************/ @@ -1852,8 +2044,8 @@ rdpClientConGetPixmapImageRect(rdpPtr dev, rdpClientCon *clientCon, { id->width = pPixmap->drawable.width; id->height = pPixmap->drawable.height; - id->bpp = g_rdpScreen.rdp_bpp; - id->Bpp = g_rdpScreen.rdp_Bpp; + id->bpp = clientCon->rdp_bpp; + id->Bpp = clientCon->rdp_Bpp; id->lineBytes = pPixmap->devKind; id->pixels = (char *)(pPixmap->devPrivate.ptr); id->shmem_pixels = 0; @@ -1864,15 +2056,22 @@ rdpClientConGetPixmapImageRect(rdpPtr dev, rdpClientCon *clientCon, /******************************************************************************/ void -rdpClientConSendArea(struct image_data *id, int x, int y, int w, int h) +rdpClientConSendArea(rdpPtr dev, rdpClientCon *clientCon, + struct image_data *id, int x, int y, int w, int h) { struct image_data lid; + BoxRec box; + int ly; + int size; + char *src; + char *dst; + struct stream *s; LLOGLN(10, ("rdpClientConSendArea: id %p x %d y %d w %d h %d", id, x, y, w, h)); - if (id == 0) + if (id == NULL) { - rdpup_get_screen_image_rect(&lid); + rdpClientConGetScreenImageRect(dev, clientCon, &lid); id = &lid; } @@ -1886,4 +2085,125 @@ rdpClientConSendArea(struct image_data *id, int x, int y, int w, int h) return; } + if (x < 0) + { + w += x; + x = 0; + } + + if (y < 0) + { + h += y; + y = 0; + } + + if (w <= 0) + { + return; + } + + if (h <= 0) + { + return; + } + + if (x + w > id->width) + { + w = id->width - x; + } + + if (y + h > id->height) + { + h = id->height - y; + } + + if (clientCon->connected && clientCon->begin) + { + if (id->shmem_pixels != 0) + { + LLOGLN(10, ("rdpClientConSendArea: using shmem")); + box.x1 = x; + box.y1 = y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + src = id->pixels; + src += y * id->lineBytes; + src += x * dev->Bpp; + dst = id->shmem_pixels + id->shmem_offset; + dst += y * id->shmem_lineBytes; + dst += x * clientCon->rdp_Bpp; + ly = y; + while (ly < y + h) + { + rdpClientConConvertPixels(dev, clientCon, src, dst, w); + src += id->lineBytes; + dst += id->shmem_lineBytes; + ly += 1; + } + size = 36; + rdpClientConPreCheck(dev, clientCon, size); + s = clientCon->out_s; + out_uint16_le(s, 60); + out_uint16_le(s, size); + clientCon->count++; + LLOGLN(10, ("rdpClientConSendArea: 2 x %d y %d w %d h %d", x, y, w, h)); + out_uint16_le(s, x); + out_uint16_le(s, y); + out_uint16_le(s, w); + out_uint16_le(s, h); + out_uint32_le(s, 0); + clientCon->rect_id++; + out_uint32_le(s, clientCon->rect_id); + out_uint32_le(s, id->shmem_id); + out_uint32_le(s, id->shmem_offset); + out_uint16_le(s, id->width); + out_uint16_le(s, id->height); + out_uint16_le(s, x); + out_uint16_le(s, y); + rdpRegionUnionRect(clientCon->shmRegion, &box); + return; + } + } +} + +/******************************************************************************/ +int +rdpClientConAddAllReg(rdpPtr dev, RegionPtr reg, DrawablePtr pDrawable) +{ + rdpClientCon *clientCon; + Bool drw_is_vis; + + drw_is_vis = XRDP_DRAWABLE_IS_VISIBLE(dev, pDrawable); + if (!drw_is_vis) + { + return 0; + } + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + rdpClientConAddDirtyScreenReg(dev, clientCon, reg); + clientCon = clientCon->next; + } + return 0; +} + +/******************************************************************************/ +int +rdpClientConAddAllBox(rdpPtr dev, BoxPtr box, DrawablePtr pDrawable) +{ + rdpClientCon *clientCon; + Bool drw_is_vis; + + drw_is_vis = XRDP_DRAWABLE_IS_VISIBLE(dev, pDrawable); + if (!drw_is_vis) + { + return 0; + } + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + rdpClientConAddDirtyScreenBox(dev, clientCon, box); + clientCon = clientCon->next; + } + return 0; } |
