diff --git a/xorg/server/module/rdp.h b/xorg/server/module/rdp.h index a26d4deb..ba1bcfd0 100644 --- a/xorg/server/module/rdp.h +++ b/xorg/server/module/rdp.h @@ -30,6 +30,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdpPri.h" +/* PIXMAN_a8r8g8b8 */ +#define XRDP_a8r8g8b8 \ +((32 << 24) | (2 << 16) | (8 << 12) | (8 << 8) | (8 << 4) | 8) + #define PixelDPI 100 #define PixelToMM(_size) (((_size) * 254 + (PixelDPI) * 5) / ((PixelDPI) * 10)) diff --git a/xorg/server/module/rdpCapture.c b/xorg/server/module/rdpCapture.c index 62b9fde8..8819713a 100644 --- a/xorg/server/module/rdpCapture.c +++ b/xorg/server/module/rdpCapture.c @@ -38,65 +38,117 @@ #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) -/** - * Copy an array of rectangles from one memory area to another - *****************************************************************************/ - -Bool rdpCapture(RegionPtr in_reg, RegionPtr out_reg, - void *src, int src_width, int src_height, int src_stride, int src_format, - void *dst, int dst_width, int dst_height, int dst_stride, int dst_format, - int mode) +/******************************************************************************/ +static Bool +rdpCapture0(RegionPtr in_reg, RegionPtr out_reg, + void *src, int src_width, int src_height, + int src_stride, int src_format, + void *dst, int dst_width, int dst_height, + int dst_stride, int dst_format, int max_rects) { - BoxRec rect; - char *src_rect; - char *dst_rect; - int num_regions; - int bpp; - int width; - int height; - int offset; - int bytes; - int i; - int j; - - /* - * note: mode = 0: default, one is to one copy - * xxx_format = 0: default, 4 bytes per pixel - */ - - /* for now we only handle defaults */ - - /* number of rectangles to copy */ - num_regions = REGION_NUM_RECTS(in_reg); - - /* get bytes per pixel */ - bpp = src_stride / src_width; - - for (i = 0; i < num_regions; i++) + BoxPtr prects; + BoxRec rect; + RegionRec reg; + char *src_rect; + char *dst_rect; + int num_regions; + int bytespp; + int width; + int height; + int src_offset; + int dst_offset; + int bytes; + int i; + int j; + Bool rv; + + LLOGLN(10, ("rdpCapture0:")); + + rv = TRUE; + + rect.x1 = 0; + rect.y1 = 0; + rect.x2 = min(dst_width, src_width); + rect.y2 = min(dst_height, src_height); + rdpRegionInit(®, &rect, 0); + rdpRegionIntersect(®, in_reg, ®); + + num_regions = REGION_NUM_RECTS(®); + + if (num_regions > max_rects) { - /* get rect to copy */ - rect = REGION_RECTS(in_reg)[i]; - - /* get rect dimensions */ - width = rect.x2 - rect.x1; - height = rect.y2 - rect.y1; - - /* point to start of each rect in respective memory */ - offset = rect.y1 * src_stride + rect.x1 * bpp; - src_rect = src + offset; - dst_rect = dst + offset; + num_regions = 1; + prects = rdpRegionExtents(®); + rdpRegionUninit(out_reg); + rdpRegionInit(out_reg, prects, 0); + } + else + { + prects = REGION_RECTS(®); + rdpRegionCopy(out_reg, ®); + } - /* bytes per line */ - bytes = width * bpp; + if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_a8r8g8b8)) + { + bytespp = 4; - /* copy one line at a time */ - for (j = 0; j < height; j++) + for (i = 0; i < num_regions; i++) { - memcpy(dst_rect, src_rect, bytes); - src_rect += src_stride; - dst_rect += src_stride; + /* get rect to copy */ + rect = prects[i]; + + /* get rect dimensions */ + width = rect.x2 - rect.x1; + height = rect.y2 - rect.y1; + + /* point to start of each rect in respective memory */ + src_offset = rect.y1 * src_stride + rect.x1 * bytespp; + dst_offset = rect.y1 * dst_stride + rect.x1 * bytespp; + src_rect = src + src_offset; + dst_rect = dst + dst_offset; + + /* bytes per line */ + bytes = width * bytespp; + + /* copy one line at a time */ + for (j = 0; j < height; j++) + { + memcpy(dst_rect, src_rect, bytes); + src_rect += src_stride; + dst_rect += dst_stride; + } } } + else + { + LLOGLN(0, ("rdpCapture0: unimp color conversion")); + } + rdpRegionUninit(®); + return rv; +} - return rdpRegionCopy(out_reg, in_reg); +/** + * Copy an array of rectangles from one memory area to another + *****************************************************************************/ +Bool +rdpCapture(RegionPtr in_reg, RegionPtr out_reg, + void *src, int src_width, int src_height, + int src_stride, int src_format, + void *dst, int dst_width, int dst_height, + int dst_stride, int dst_format, int mode) +{ + LLOGLN(10, ("rdpCapture:")); + switch (mode) + { + case 0: + return rdpCapture0(in_reg, out_reg, + src, src_width, src_height, + src_stride, src_format, + dst, dst_width, dst_height, + dst_stride, dst_format, 15); + default: + LLOGLN(0, ("rdpCapture: unimp mode")); + break; + } + return TRUE; } diff --git a/xorg/server/module/rdpCapture.h b/xorg/server/module/rdpCapture.h index 87bf692b..f92508c4 100644 --- a/xorg/server/module/rdpCapture.h +++ b/xorg/server/module/rdpCapture.h @@ -18,7 +18,10 @@ * Routines to copy regions from framebuffer to shared memory */ -Bool rdpCapture(RegionPtr in_reg, RegionPtr out_reg, - void *src, int src_width, int src_height, int src_stride, int src_format, - void *dst, int dst_width, int dst_height, int dst_stride, int dst_format, - int mode) +Bool +rdpCapture(RegionPtr in_reg, RegionPtr out_reg, + void *src, int src_width, int src_height, + int src_stride, int src_format, + void *dst, int dst_width, int dst_height, + int dst_stride, int dst_format, + int mode); diff --git a/xorg/server/module/rdpClientCon.c b/xorg/server/module/rdpClientCon.c index c02e9f1e..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) \ @@ -116,6 +117,8 @@ 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); @@ -262,6 +265,8 @@ rdpClientConDisconnect(rdpPtr dev, rdpClientCon *clientCon) dev->clientConTail = plcli; } } + LLOGLN(0, ("rdpClientConDisconnect: clientCon removed from " + "dev list")); break; } plcli = pcli; @@ -797,6 +802,24 @@ rdpClientConProcessMsgClientRegion(rdpPtr dev, rdpClientCon *clientCon) return 0; } +/******************************************************************************/ +static int +rdpClientConProcessMsgClientRegionEx(rdpPtr dev, rdpClientCon *clientCon) +{ + struct stream *s; + int flags; + + LLOGLN(10, ("rdpClientConProcessMsgClientRegionEx:")); + s = clientCon->in_s; + + 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; +} + /******************************************************************************/ static int rdpClientConProcessMsg(rdpPtr dev, rdpClientCon *clientCon) @@ -819,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; } @@ -1848,40 +1874,104 @@ rdpClientConCheckDirtyScreen(rdpPtr dev, rdpClientCon *clientCon) return 0; } +/******************************************************************************/ +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; - int num_rects; - int index; - BoxRec box; + RegionRec reg; + struct image_data id; LLOGLN(10, ("rdpDeferredUpdateCallback:")); clientCon = (rdpClientCon *) arg; if (clientCon->rect_id != clientCon->rect_id_ack) { - LLOGLN(10, ("rdpDeferredUpdateCallback: reschedual")); + LLOGLN(0, ("rdpDeferredUpdateCallback: reschedual")); clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0, 40, rdpDeferredUpdateCallback, clientCon); return 0; } - - clientCon->updateSchedualed = FALSE; - rdpClientConBeginUpdate(clientCon->dev, clientCon); - num_rects = REGION_NUM_RECTS(clientCon->dirtyRegion); - for (index = 0; index < num_rects; index++) + else { - box = REGION_RECTS(clientCon->dirtyRegion)[index]; - LLOGLN(10, (" x1 %d y1 %d x2 %d y2 %d cx %d cy %d", box.x1, box.y1, - box.x2, box.y2, box.x2 - box.x1, box.y2 - box.y1)); - rdpClientConSendArea(clientCon->dev, clientCon, NULL, box.x1, box.y1, - box.x2 - box.x1, box.y2 - box.y1); + LLOGLN(10, ("rdpDeferredUpdateCallback: sending")); } - rdpClientConEndUpdate(clientCon->dev, clientCon); + 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; } @@ -1890,6 +1980,8 @@ int rdpClientConAddDirtyScreenReg(rdpPtr dev, rdpClientCon *clientCon, RegionPtr reg) { + LLOGLN(10, ("rdpClientConAddDirtyScreenReg:")); + rdpRegionUnion(clientCon->dirtyRegion, clientCon->dirtyRegion, reg); if (clientCon->updateSchedualed == FALSE) { @@ -1969,7 +2061,6 @@ rdpClientConSendArea(rdpPtr dev, rdpClientCon *clientCon, { struct image_data lid; BoxRec box; - RegionRec reg; int ly; int size; char *src; @@ -2069,9 +2160,7 @@ rdpClientConSendArea(rdpPtr dev, rdpClientCon *clientCon, out_uint16_le(s, id->height); out_uint16_le(s, x); out_uint16_le(s, y); - rdpRegionInit(®, &box, 0); - rdpRegionUnion(clientCon->shmRegion, clientCon->shmRegion, ®); - rdpRegionUninit(®); + rdpRegionUnionRect(clientCon->shmRegion, &box); return; } } diff --git a/xorg/server/module/rdpTrapezoids.c b/xorg/server/module/rdpTrapezoids.c index 05b34ec4..212780ce 100644 --- a/xorg/server/module/rdpTrapezoids.c +++ b/xorg/server/module/rdpTrapezoids.c @@ -30,7 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include -#include "mipict.h" +#include #include #include "rdp.h"