summaryrefslogtreecommitdiffstats
path: root/xorg
diff options
context:
space:
mode:
Diffstat (limited to 'xorg')
-rw-r--r--xorg/server/module/rdpCapture.c440
-rw-r--r--xorg/server/module/rdpCapture.h3
-rw-r--r--xorg/server/module/rdpClientCon.c17
3 files changed, 362 insertions, 98 deletions
diff --git a/xorg/server/module/rdpCapture.c b/xorg/server/module/rdpCapture.c
index e9fef483..d5ee04fb 100644
--- a/xorg/server/module/rdpCapture.c
+++ b/xorg/server/module/rdpCapture.c
@@ -39,9 +39,216 @@
#define LLOGLN(_level, _args) \
do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)
+#define RDP_MAX_TILES 1024
+
+/******************************************************************************/
+static int
+rdpLimitRects(RegionPtr reg, int max_rects, BoxPtr *rects)
+{
+ int nrects;
+
+ nrects = REGION_NUM_RECTS(reg);
+ if (nrects > max_rects)
+ {
+ nrects = 1;
+ *rects = rdpRegionExtents(reg);
+ }
+ else
+ {
+ *rects = REGION_RECTS(reg);
+ }
+ return nrects;
+}
+
+/******************************************************************************/
+/* copy rects with no error checking */
+static int
+rdpCopyBox_a8r8g8b8_to_a8r8g8b8(void *src, int src_stride, int srcx, int srcy,
+ void *dst, int dst_stride, int dstx, int dsty,
+ BoxPtr rects, int num_rects)
+{
+ char *s8;
+ char *d8;
+ int index;
+ int jndex;
+ int bytes;
+ int height;
+ BoxPtr box;
+
+ for (index = 0; index < num_rects; index++)
+ {
+ box = rects + index;
+ s8 = ((char *) src) + (box->y1 - srcy) * src_stride;
+ s8 += (box->x1 - srcx) * 4;
+ d8 = ((char *) dst) + (box->y1 - dsty) * dst_stride;
+ d8 += (box->x1 - dstx) * 4;
+ bytes = box->x2 - box->x1;
+ bytes *= 4;
+ height = box->y2 - box->y1;
+ for (jndex = 0; jndex < height; jndex++)
+ {
+ memcpy(d8, s8, bytes);
+ d8 += dst_stride;
+ s8 += src_stride;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+static int
+rdpFillBox_yuvalp(int ax, int ay,
+ void *dst, int dst_stride)
+{
+ dst = ((char *) dst) + (ay << 8) * (dst_stride >> 8) + (ax << 8);
+ memset(dst, 0, 64 * 64 * 4);
+ return 0;
+}
+
+/******************************************************************************/
+/* copy rects with no error checking
+ * convert ARGB32 to 64x64 linear planar YUVA */
+/* http://msdn.microsoft.com/en-us/library/ff635643.aspx
+ * 0.299 -0.168935 0.499813
+ * 0.587 -0.331665 -0.418531
+ * 0.114 0.50059 -0.081282
+ y = r * 0.299000 + g * 0.587000 + b * 0.114000;
+ u = r * -0.168935 + g * -0.331665 + b * 0.500590;
+ v = r * 0.499813 + g * -0.418531 + b * -0.081282; */
+/* 19595 38470 7471
+ -11071 -21736 32807
+ 32756 -27429 -5327 */
+static int
+rdpCopyBox_a8r8g8b8_to_yuvalp(int ax, int ay,
+ void *src, int src_stride,
+ void *dst, int dst_stride,
+ BoxPtr rects, int num_rects)
+{
+ char *s8;
+ char *d8;
+ char *yptr;
+ char *uptr;
+ char *vptr;
+ char *aptr;
+ int *s32;
+ int index;
+ int jndex;
+ int kndex;
+ int width;
+ int height;
+ int pixel;
+ int a;
+ int r;
+ int g;
+ int b;
+ int y;
+ int u;
+ int v;
+ BoxPtr box;
+
+ dst = ((char *) dst) + (ay << 8) * (dst_stride >> 8) + (ax << 8);
+ for (index = 0; index < num_rects; index++)
+ {
+ box = rects + index;
+ s8 = ((char *) src) + box->y1 * src_stride;
+ s8 += box->x1 * 4;
+ d8 = ((char *) dst) + (box->y1 - ay) * 64;
+ d8 += box->x1 - ax;
+ width = box->x2 - box->x1;
+ height = box->y2 - box->y1;
+ for (jndex = 0; jndex < height; jndex++)
+ {
+ s32 = (int *) s8;
+ yptr = d8;
+ uptr = yptr + 64 * 64;
+ vptr = uptr + 64 * 64;
+ aptr = vptr + 64 * 64;
+ kndex = 0;
+ while (kndex < width)
+ {
+ pixel = *(s32++);
+ a = (pixel >> 24) & 0xff;
+ r = (pixel >> 16) & 0xff;
+ g = (pixel >> 8) & 0xff;
+ b = (pixel >> 0) & 0xff;
+ y = (r * 19595 + g * 38470 + b * 7471) >> 16;
+ u = (r * -11071 + g * -21736 + b * 32807) >> 16;
+ v = (r * 32756 + g * -27429 + b * -5327) >> 16;
+ y = y - 128;
+ y = max(y, -128);
+ u = max(u, -128);
+ v = max(v, -128);
+ y = min(y, 127);
+ u = min(u, 127);
+ v = min(v, 127);
+ *(yptr++) = y;
+ *(uptr++) = u;
+ *(vptr++) = v;
+ *(aptr++) = a;
+ kndex++;
+ }
+ d8 += 64;
+ s8 += src_stride;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/* copy rects with no error checking */
+static int
+rdpCopyBox_a8r8g8b8_to_a8b8g8r8(void *src, int src_stride,
+ void *dst, int dst_stride,
+ BoxPtr rects, int num_rects)
+{
+ char *s8;
+ char *d8;
+ int index;
+ int jndex;
+ int kndex;
+ int bytes;
+ int width;
+ int height;
+ int red;
+ int green;
+ int blue;
+ BoxPtr box;
+ unsigned int *s32;
+ unsigned int *d32;
+
+ for (index = 0; index < num_rects; index++)
+ {
+ box = rects + index;
+ s8 = ((char *) src) + box->y1 * src_stride;
+ s8 += box->x1 * 4;
+ d8 = ((char *) dst) + box->y1 * dst_stride;
+ d8 += box->x1 * 4;
+ bytes = box->x2 - box->x1;
+ bytes *= 4;
+ width = box->x2 - box->x1;
+ height = box->y2 - box->y1;
+ for (jndex = 0; jndex < height; jndex++)
+ {
+ s32 = (unsigned int *) s8;
+ d32 = (unsigned int *) d8;
+ for (kndex = 0; kndex < width; kndex++)
+ {
+ SPLITCOLOR32(red, green, blue, *s32);
+ *d32 = COLOR24(red, green, blue);
+ s32++;
+ d32++;
+ }
+ d8 += dst_stride;
+ s8 += src_stride;
+ }
+ }
+ return 0;
+}
+
/******************************************************************************/
static Bool
-rdpCapture0(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
+rdpCapture0(rdpClientCon *clientCon,
+ RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
void *src, int src_width, int src_height,
int src_stride, int src_format,
void *dst, int dst_width, int dst_height,
@@ -52,15 +259,13 @@ rdpCapture0(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
RegionRec reg;
char *src_rect;
char *dst_rect;
- int num_regions;
- int bytespp;
+ int num_rects;
int src_bytespp;
int dst_bytespp;
int width;
int height;
int src_offset;
int dst_offset;
- int bytes;
int i;
int j;
int k;
@@ -69,7 +274,6 @@ rdpCapture0(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
int blue;
Bool rv;
unsigned int *s32;
- unsigned int *d32;
unsigned short *d16;
unsigned char *d8;
@@ -84,27 +288,18 @@ rdpCapture0(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
rdpRegionInit(&reg, &rect, 0);
rdpRegionIntersect(&reg, in_reg, &reg);
- num_regions = REGION_NUM_RECTS(&reg);
-
- if (num_regions > max_rects)
- {
- num_regions = 1;
- psrc_rects = rdpRegionExtents(&reg);
- }
- else
- {
- psrc_rects = REGION_RECTS(&reg);
- }
-
- if (num_regions < 1)
+ psrc_rects = 0;
+ num_rects = rdpLimitRects(&reg, max_rects, &psrc_rects);
+ if (num_rects < 1)
{
+ rdpRegionUninit(&reg);
return FALSE;
}
- *num_out_rects = num_regions;
+ *num_out_rects = num_rects;
- *out_rects = (BoxPtr) g_malloc(sizeof(BoxRec) * num_regions, 0);
- for (i = 0; i < num_regions; i++)
+ *out_rects = (BoxPtr) g_malloc(sizeof(BoxRec) * num_rects, 0);
+ for (i = 0; i < num_rects; i++)
{
rect = psrc_rects[i];
(*out_rects)[i] = rect;
@@ -112,78 +307,22 @@ rdpCapture0(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_a8r8g8b8))
{
- bytespp = 4;
-
- for (i = 0; i < num_regions; i++)
- {
- /* get rect to copy */
- rect = (*out_rects)[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;
- }
- }
+ rdpCopyBox_a8r8g8b8_to_a8r8g8b8(src, src_stride, 0, 0,
+ dst, dst_stride, 0, 0,
+ psrc_rects, num_rects);
}
else if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_a8b8g8r8))
{
- src_bytespp = 4;
- dst_bytespp = 4;
-
- for (i = 0; i < num_regions; i++)
- {
- /* get rect to copy */
- rect = (*out_rects)[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 * src_bytespp;
- dst_offset = rect.y1 * dst_stride + rect.x1 * dst_bytespp;
- src_rect = src + src_offset;
- dst_rect = dst + dst_offset;
-
- /* copy one line at a time */
- for (j = 0; j < height; j++)
- {
- s32 = (unsigned int *) src_rect;
- d32 = (unsigned int *) dst_rect;
- for (k = 0; k < width; k++)
- {
- SPLITCOLOR32(red, green, blue, *s32);
- *d32 = COLOR24(red, green, blue);
- s32++;
- d32++;
- }
- src_rect += src_stride;
- dst_rect += dst_stride;
- }
- }
+ rdpCopyBox_a8r8g8b8_to_a8b8g8r8(src, src_stride,
+ dst, dst_stride,
+ psrc_rects, num_rects);
}
else if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_r5g6b5))
{
src_bytespp = 4;
dst_bytespp = 2;
- for (i = 0; i < num_regions; i++)
+ for (i = 0; i < num_rects; i++)
{
/* get rect to copy */
rect = (*out_rects)[i];
@@ -220,7 +359,7 @@ rdpCapture0(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
src_bytespp = 4;
dst_bytespp = 2;
- for (i = 0; i < num_regions; i++)
+ for (i = 0; i < num_rects; i++)
{
/* get rect to copy */
rect = (*out_rects)[i];
@@ -257,7 +396,7 @@ rdpCapture0(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
src_bytespp = 4;
dst_bytespp = 1;
- for (i = 0; i < num_regions; i++)
+ for (i = 0; i < num_rects; i++)
{
/* get rect to copy */
rect = (*out_rects)[i];
@@ -300,7 +439,8 @@ rdpCapture0(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
/******************************************************************************/
/* make out_rects always multiple of 16 width and height */
static Bool
-rdpCapture1(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
+rdpCapture1(rdpClientCon *clientCon,
+ RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
void *src, int src_width, int src_height,
int src_stride, int src_format,
void *dst, int dst_width, int dst_height,
@@ -475,11 +615,125 @@ rdpCapture1(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
return rv;
}
+/******************************************************************************/
+static Bool
+rdpCapture2(rdpClientCon *clientCon,
+ RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
+ 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)
+{
+ int x;
+ int y;
+ int out_rect_index;
+ int num_rects;
+ int rcode;
+ BoxRec rect;
+ BoxRec extents_rect;
+ BoxPtr rects;
+ RegionRec tile_reg;
+ RegionRec lin_reg;
+ RegionRec temp_reg;
+ RegionPtr pin_reg;
+
+ LLOGLN(10, ("rdpCapture2:"));
+
+ *out_rects = (BoxPtr) g_malloc(sizeof(BoxRec) * RDP_MAX_TILES, 0);
+ if (*out_rects == NULL)
+ {
+ return FALSE;
+ }
+ out_rect_index = 0;
+
+ /* clip for smaller of 2 */
+ rect.x1 = 0;
+ rect.y1 = 0;
+ rect.x2 = min(dst_width, src_width);
+ rect.y2 = min(dst_height, src_height);
+ rdpRegionInit(&temp_reg, &rect, 0);
+ rdpRegionIntersect(&temp_reg, in_reg, &temp_reg);
+
+ /* limit the numer of rects */
+ num_rects = REGION_NUM_RECTS(&temp_reg);
+ if (num_rects > max_rects)
+ {
+ LLOGLN(10, ("rdpCapture2: too many rects"));
+ rdpRegionInit(&lin_reg, rdpRegionExtents(&temp_reg), 0);
+ pin_reg = &lin_reg;
+ }
+ else
+ {
+ LLOGLN(10, ("rdpCapture2: not too many rects"));
+ rdpRegionInit(&lin_reg, NullBox, 0);
+ pin_reg = &temp_reg;
+ }
+
+ extents_rect = *rdpRegionExtents(pin_reg);
+ y = extents_rect.y1 & ~63;
+ while (y < extents_rect.y2)
+ {
+ x = extents_rect.x1 & ~63;
+ while (x < extents_rect.x2)
+ {
+ rect.x1 = x;
+ rect.y1 = y;
+ rect.x2 = rect.x1 + 64;
+ rect.y2 = rect.y1 + 64;
+ rcode = rdpRegionContainsRect(pin_reg, &rect);
+ LLOGLN(10, ("rdpCapture2: rcode %d", rcode));
+
+ if (rcode != rgnOUT)
+ {
+ if (rcode == rgnPART)
+ {
+ LLOGLN(10, ("rdpCapture2: rgnPART"));
+ rdpFillBox_yuvalp(x, y, dst, dst_stride);
+ rdpRegionInit(&tile_reg, &rect, 0);
+ rdpRegionIntersect(&tile_reg, pin_reg, &tile_reg);
+ rects = REGION_RECTS(&tile_reg);
+ num_rects = REGION_NUM_RECTS(&tile_reg);
+ rdpCopyBox_a8r8g8b8_to_yuvalp(x, y,
+ src, src_stride,
+ dst, dst_stride,
+ rects, num_rects);
+ rdpRegionUninit(&tile_reg);
+ }
+ else /* rgnIN */
+ {
+ LLOGLN(10, ("rdpCapture2: rgnIN"));
+ rdpCopyBox_a8r8g8b8_to_yuvalp(x, y,
+ src, src_stride,
+ dst, dst_stride,
+ &rect, 1);
+ }
+ (*out_rects)[out_rect_index] = rect;
+ out_rect_index++;
+ if (out_rect_index >= RDP_MAX_TILES)
+ {
+ g_free(*out_rects);
+ *out_rects = NULL;
+ rdpRegionUninit(&temp_reg);
+ rdpRegionUninit(&lin_reg);
+ return FALSE;
+ }
+ }
+ x += 64;
+ }
+ y += 64;
+ }
+ *num_out_rects = out_rect_index;
+ rdpRegionUninit(&temp_reg);
+ rdpRegionUninit(&lin_reg);
+ return TRUE;
+}
+
/**
* Copy an array of rectangles from one memory area to another
*****************************************************************************/
Bool
-rdpCapture(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
+rdpCapture(rdpClientCon *clientCon,
+ RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
void *src, int src_width, int src_height,
int src_stride, int src_format,
void *dst, int dst_width, int dst_height,
@@ -489,13 +743,19 @@ rdpCapture(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
switch (mode)
{
case 0:
- return rdpCapture0(in_reg, out_rects, num_out_rects,
+ return rdpCapture0(clientCon, in_reg, out_rects, num_out_rects,
src, src_width, src_height,
src_stride, src_format,
dst, dst_width, dst_height,
dst_stride, dst_format, 15);
case 1:
- return rdpCapture1(in_reg, out_rects, num_out_rects,
+ return rdpCapture1(clientCon, in_reg, out_rects, num_out_rects,
+ src, src_width, src_height,
+ src_stride, src_format,
+ dst, dst_width, dst_height,
+ dst_stride, dst_format, 15);
+ case 2:
+ return rdpCapture2(clientCon, in_reg, out_rects, num_out_rects,
src, src_width, src_height,
src_stride, src_format,
dst, dst_width, dst_height,
diff --git a/xorg/server/module/rdpCapture.h b/xorg/server/module/rdpCapture.h
index 5810e3b6..4dff1eea 100644
--- a/xorg/server/module/rdpCapture.h
+++ b/xorg/server/module/rdpCapture.h
@@ -19,7 +19,8 @@
*/
Bool
-rdpCapture(RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
+rdpCapture(rdpClientCon *clientCon,
+ RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects,
void *src, int src_width, int src_height,
int src_stride, int src_format,
void *dst, int dst_width, int dst_height,
diff --git a/xorg/server/module/rdpClientCon.c b/xorg/server/module/rdpClientCon.c
index 24870557..00ea4645 100644
--- a/xorg/server/module/rdpClientCon.c
+++ b/xorg/server/module/rdpClientCon.c
@@ -691,11 +691,9 @@ rdpClientConProcessMsgClientInfo(rdpPtr dev, rdpClientCon *clientCon)
i1 = clientCon->client_info.offscreen_cache_entries;
LLOGLN(0, (" offscreen entries %d", i1));
- if ((clientCon->client_info.mcs_connection_type == 6) && /* LAN */
- (clientCon->client_info.jpeg_codec_id == 2))
+ if (clientCon->client_info.capture_format != 0)
{
- /* jpeg capture needs swap */
- clientCon->rdp_format = XRDP_a8b8g8r8;
+ clientCon->rdp_format = clientCon->client_info.capture_format;
}
if (clientCon->client_info.offscreen_support_level > 0)
@@ -1964,7 +1962,9 @@ rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
LLOGLN(10, ("rdpDeferredUpdateCallback:"));
clientCon = (rdpClientCon *) arg;
- if (clientCon->rect_id > clientCon->rect_id_ack)
+ if ((clientCon->rect_id > clientCon->rect_id_ack) ||
+ /* do not allow captures until we have the client_info */
+ clientCon->client_info.size == 0)
{
LLOGLN(0, ("rdpDeferredUpdateCallback: reschedual rect_id %d "
"rect_id_ack %d",
@@ -1986,13 +1986,16 @@ rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
clientCon->updateSchedualed = FALSE;
rects = 0;
num_rects = 0;
- if (rdpCapture(clientCon->dirtyRegion, &rects, &num_rects,
+ LLOGLN(10, ("rdpDeferredUpdateCallback: capture_code %d",
+ clientCon->client_info.capture_code));
+ if (rdpCapture(clientCon, clientCon->dirtyRegion, &rects, &num_rects,
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,
- clientCon->rdp_format, 0))
+ clientCon->rdp_format, clientCon->client_info.capture_code))
{
+ LLOGLN(10, ("rdpDeferredUpdateCallback: num_rects %d", num_rects));
rdpClientConSendPaintRectShmEx(clientCon->dev, clientCon, &id,
clientCon->dirtyRegion,
rects, num_rects);