rdp: Improve raw surfaces

This patch does miscellanous improvements with raw surfaces:
* some frames markers are sent to identify a single frame made of
multiple surface updates
* we send the dirty sub-rectangles instead of the full bouncing box
* the size of the fragmentation buffer is now honored, so that our big
surface updates don't look like a DoS
* the subtile and image flipping are done in one step (not requiring a
temporary tile)
* we don't care about the size of the dirty region and always use the
preferred codec for surface update
dev
Hardening 12 years ago committed by Kristian Høgsberg
parent c39118be7e
commit fe36a13a8f
  1. 100
      src/compositor-rdp.c

@ -210,37 +210,74 @@ rdp_peer_refresh_nsc(pixman_region32_t *damage, pixman_image_t *image, freerdp_p
update->SurfaceBits(update->context, cmd);
}
static void
pixman_image_flipped_subrect(const pixman_box32_t *rect, pixman_image_t *img, BYTE *dest) {
int stride = pixman_image_get_stride(img);
int h;
int toCopy = (rect->x2 - rect->x1) * 4;
int height = (rect->y2 - rect->y1);
const BYTE *src = (const BYTE *)pixman_image_get_data(img);
src += ((rect->y2-1) * stride) + (rect->x1 * 4);
for (h = 0; h < height; h++, src -= stride, dest += toCopy)
memcpy(dest, src, toCopy);
}
static void
rdp_peer_refresh_raw(pixman_region32_t *region, pixman_image_t *image, freerdp_peer *peer)
{
pixman_image_t *tile;
rdpUpdate *update = peer->update;
SURFACE_BITS_COMMAND *cmd = &update->surface_bits_command;
pixman_box32_t *extends = pixman_region32_extents(region);
SURFACE_FRAME_MARKER *marker = &update->surface_frame_marker;
pixman_box32_t *rect, subrect;
int nrects, i;
int heightIncrement, remainingHeight, top;
rect = pixman_region32_rectangles(region, &nrects);
if (!nrects)
return;
marker->frameId++;
marker->frameAction = SURFACECMD_FRAMEACTION_BEGIN;
update->SurfaceFrameMarker(peer->context, marker);
cmd->bpp = 32;
cmd->codecID = 0;
cmd->width = (extends->x2 - extends->x1);
cmd->height = (extends->y2 - extends->y1);;
cmd->bitmapDataLength = cmd->width * cmd->height * 4;
tile = pixman_image_create_bits(PIXMAN_x8r8g8b8, cmd->width, cmd->height, 0, cmd->width * 4);
pixman_image_composite32(PIXMAN_OP_SRC, image, NULL, /* op, src, mask */
tile, extends->x1, extends->y1, /* dest, src_x, src_y */
0, 0, /* mask_x, mask_y */
0, 0, /* dest_x, dest_y */
cmd->width, cmd->height /* width, height */
);
freerdp_image_flip((BYTE *)pixman_image_get_data(tile),
(BYTE *)pixman_image_get_data(tile),
cmd->width, cmd->height, cmd->bpp
);
cmd->bitmapData = (BYTE *)pixman_image_get_data(tile);
cmd->destLeft = extends->x1;
cmd->destTop = extends->y1;
cmd->destRight = extends->x2;
cmd->destBottom = extends->y2;
update->SurfaceBits(peer->context, cmd);
pixman_image_unref(tile);
for (i = 0; i < nrects; i++, rect++) {
/*weston_log("rect(%d,%d, %d,%d)\n", rect->x1, rect->y1, rect->x2, rect->y2);*/
cmd->destLeft = rect->x1;
cmd->destRight = rect->x2;
cmd->width = rect->x2 - rect->x1;
heightIncrement = peer->settings->MultifragMaxRequestSize / (16 + cmd->width * 4);
remainingHeight = rect->y2 - rect->y1;
top = rect->y1;
subrect.x1 = rect->x1;
subrect.x2 = rect->x2;
while (remainingHeight) {
cmd->height = (remainingHeight > heightIncrement) ? heightIncrement : remainingHeight;
cmd->destTop = top;
cmd->destBottom = top + cmd->height;
cmd->bitmapDataLength = cmd->width * cmd->height * 4;
cmd->bitmapData = (BYTE *)realloc(cmd->bitmapData, cmd->bitmapDataLength);
subrect.y1 = top;
subrect.y2 = top + cmd->height;
pixman_image_flipped_subrect(&subrect, image, cmd->bitmapData);
/*weston_log("* sending (%d,%d, %d,%d)\n", subrect.x1, subrect.y1, subrect.x2, subrect.y2); */
update->SurfaceBits(peer->context, cmd);
remainingHeight -= cmd->height;
top += cmd->height;
}
}
marker->frameAction = SURFACECMD_FRAMEACTION_END;
update->SurfaceFrameMarker(peer->context, marker);
}
static void
@ -249,20 +286,13 @@ rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer)
RdpPeerContext *context = (RdpPeerContext *)peer->context;
struct rdp_output *output = context->rdpCompositor->output;
rdpSettings *settings = peer->settings;
pixman_box32_t *extents = pixman_region32_extents(region);
int regionSz = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
if(regionSz > 64 * 64) {
if(settings->RemoteFxCodec)
rdp_peer_refresh_rfx(region, output->shadow_surface, peer);
else if(settings->NSCodec)
rdp_peer_refresh_nsc(region, output->shadow_surface, peer);
else
rdp_peer_refresh_raw(region, output->shadow_surface, peer);
} else {
if (settings->RemoteFxCodec)
rdp_peer_refresh_rfx(region, output->shadow_surface, peer);
else if (settings->NSCodec)
rdp_peer_refresh_nsc(region, output->shadow_surface, peer);
else
rdp_peer_refresh_raw(region, output->shadow_surface, peer);
}
}
static void

Loading…
Cancel
Save