diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 82c1b5658..c981b02e4 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -946,9 +946,9 @@ BOOL xf_post_connect(freerdp *instance) XSetForeground(xfc->display, xfc->gc, BlackPixelOfScreen(xfc->screen)); XFillRectangle(xfc->display, xfc->primary, xfc->gc, 0, 0, xfc->width, xfc->height); XFlush(xfc->display); + xfc->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*) xfc->primary_buffer, xfc->width, xfc->height, xfc->scanline_pad, 0); - xfc->bmp_codec_none = (BYTE *) malloc(64 * 64 * 4); if (settings->SoftwareGdi) { @@ -1641,9 +1641,6 @@ static void xfreerdp_client_free(freerdp* instance, rdpContext* context) { xf_window_free(xfc); - if (xfc->bmp_codec_none) - free(xfc->bmp_codec_none); - if (xfc->bitmap_buffer) _aligned_free(xfc->bitmap_buffer); diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index 2bcc0dd79..3cb43f2d3 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -1139,6 +1139,8 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) { int i, tx, ty; XImage* image; + BYTE* pSrcData; + BYTE* pDstData; RFX_MESSAGE* message; xfContext* xfc = (xfContext*) context; @@ -1148,21 +1150,39 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) { freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_REMOTEFX); - message = rfx_process_message(xfc->codecs->rfx, - cmd->bitmapData, cmd->bitmapDataLength); + message = rfx_process_message(xfc->codecs->rfx, cmd->bitmapData, cmd->bitmapDataLength); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); - XSetClipRectangles(xfc->display, xfc->gc, - cmd->destLeft, cmd->destTop, + XSetClipRectangles(xfc->display, xfc->gc, cmd->destLeft, cmd->destTop, (XRectangle*) message->rects, message->numRects, YXBanded); + if (xfc->bitmap_size < (64 * 64 * 4)) + { + xfc->bitmap_size = 64 * 64 * 4; + xfc->bitmap_buffer = (BYTE*) _aligned_realloc(xfc->bitmap_buffer, xfc->bitmap_size, 16); + + if (!xfc->bitmap_buffer) + return; + } + /* Draw the tiles to primary surface, each is 64x64. */ for (i = 0; i < message->numTiles; i++) { - image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, - (char*) message->tiles[i]->data, 64, 64, 32, 0); + pSrcData = message->tiles[i]->data; + pDstData = pSrcData; + + if ((xfc->depth != 24) || (xfc->depth != 32)) + { + pDstData = xfc->bitmap_buffer; + + freerdp_image_copy(pDstData, xfc->format, -1, 0, 0, + 64, 64, pSrcData, PIXEL_FORMAT_XRGB32, -1, 0, 0); + } + + image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, + (char*) pDstData, 64, 64, xfc->scanline_pad, 0); tx = message->tiles[i]->x + cmd->destLeft; ty = message->tiles[i]->y + cmd->destTop; @@ -1176,9 +1196,11 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) { tx = message->rects[i].x + cmd->destLeft; ty = message->rects[i].y + cmd->destTop; + if (!xfc->remote_app) { - XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, tx, ty, message->rects[i].width, message->rects[i].height, tx, ty); + XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, + tx, ty, message->rects[i].width, message->rects[i].height, tx, ty); } xf_gdi_surface_update_frame(xfc, tx, ty, message->rects[i].width, message->rects[i].height); @@ -1191,39 +1213,42 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) { freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_NSCODEC); - nsc_process_message(xfc->codecs->nsc, cmd->bpp, cmd->width, cmd->height, - cmd->bitmapData, cmd->bitmapDataLength); + nsc_process_message(xfc->codecs->nsc, cmd->bpp, cmd->width, cmd->height, cmd->bitmapData, cmd->bitmapDataLength); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); - xfc->bmp_codec_nsc = (BYTE*) realloc(xfc->bmp_codec_nsc, - cmd->width * cmd->height * 4); + if (xfc->bitmap_size < (cmd->width * cmd->height * 4)) + { + xfc->bitmap_size = cmd->width * cmd->height * 4; + xfc->bitmap_buffer = (BYTE*) _aligned_realloc(xfc->bitmap_buffer, xfc->bitmap_size, 16); - freerdp_image_flip(xfc->codecs->nsc->BitmapData, xfc->bmp_codec_nsc, - cmd->width, cmd->height, 32); + if (!xfc->bitmap_buffer) + return; + } - image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, - (char*) xfc->bmp_codec_nsc, cmd->width, cmd->height, 32, 0); + pSrcData = xfc->codecs->nsc->BitmapData; + pDstData = xfc->bitmap_buffer; + + freerdp_image_copy(pDstData, xfc->format, -1, 0, 0, + cmd->width, cmd->height, pSrcData, PIXEL_FORMAT_XRGB32_VF, -1, 0, 0); + + image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, + (char*) pDstData, cmd->width, cmd->height, xfc->scanline_pad, 0); XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, - cmd->destLeft, cmd->destTop, - cmd->width, cmd->height); + cmd->destLeft, cmd->destTop, cmd->width, cmd->height); + XFree(image); - free(xfc->bmp_codec_nsc); - xfc->bmp_codec_nsc = NULL; if (!xfc->remote_app) { XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, - cmd->destLeft, cmd->destTop, - cmd->width, cmd->height, + cmd->destLeft, cmd->destTop, cmd->width, cmd->height, cmd->destLeft, cmd->destTop); } - xf_gdi_surface_update_frame(xfc, - cmd->destLeft, cmd->destTop, - cmd->width, cmd->height); + xf_gdi_surface_update_frame(xfc, cmd->destLeft, cmd->destTop, cmd->width, cmd->height); XSetClipMask(xfc->display, xfc->gc, None); } @@ -1232,43 +1257,39 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); - /* Validate that the data received is large enough */ - if ((cmd->width * cmd->height * cmd->bpp / 8) <= (cmd->bitmapDataLength)) + if (xfc->bitmap_size < (cmd->width * cmd->height * 4)) { - xfc->bmp_codec_none = (BYTE*) realloc(xfc->bmp_codec_none, - cmd->width * cmd->height * 4); + xfc->bitmap_size = cmd->width * cmd->height * 4; + xfc->bitmap_buffer = (BYTE*) _aligned_realloc(xfc->bitmap_buffer, xfc->bitmap_size, 16); - freerdp_image_flip(cmd->bitmapData, xfc->bmp_codec_none, - cmd->width, cmd->height, 32); + if (!xfc->bitmap_buffer) + return; + } - image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, - (char*) xfc->bmp_codec_none, cmd->width, cmd->height, 32, 0); + pSrcData = cmd->bitmapData; + pDstData = xfc->bitmap_buffer; - XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, - cmd->destLeft, cmd->destTop, - cmd->width, cmd->height); - XFree(image); - free(xfc->bmp_codec_none); - xfc->bmp_codec_none = NULL; + freerdp_image_copy(pDstData, xfc->format, -1, 0, 0, + cmd->width, cmd->height, pSrcData, PIXEL_FORMAT_XRGB32_VF, -1, 0, 0); - if (!xfc->remote_app) - { - XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, - cmd->destLeft, cmd->destTop, - cmd->width, cmd->height, - cmd->destLeft, cmd->destTop); - } - xf_gdi_surface_update_frame(xfc, + image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, + (char*) pDstData, cmd->width, cmd->height, xfc->scanline_pad, 0); + + XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, cmd->destLeft, cmd->destTop, cmd->width, cmd->height); + XFree(image); - XSetClipMask(xfc->display, xfc->gc, None); - } - else + if (!xfc->remote_app) { - DEBUG_WARN("Invalid bitmap size - data is %d bytes for %dx%d\n update", - cmd->bitmapDataLength, cmd->width, cmd->height); + XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, + cmd->destLeft, cmd->destTop, + cmd->width, cmd->height, cmd->destLeft, cmd->destTop); } + + xf_gdi_surface_update_frame(xfc, cmd->destLeft, cmd->destTop, cmd->width, cmd->height); + + XSetClipMask(xfc->display, xfc->gc, None); } else { diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 9e2408686..02d09e052 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -75,9 +75,17 @@ int xf_OutputUpdate(xfContext* xfc) if (height > xfc->height) height = xfc->height; + if (surface->stage) + { + freerdp_image_copy(surface->stage, xfc->format, surface->stageStep, 0, 0, + surface->width, surface->height, surface->data, surface->format, surface->scanline, 0, 0); + + //freerdp_image_copy(surface->stage, xfc->format, surface->stageStep, extents->left, extents->top, + // width, height, surface->data, surface->format, surface->scanline, extents->left, extents->top); + } + XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, - extents->left, extents->top, - extents->left, extents->top, width, height); + extents->left, extents->top, extents->left, extents->top, width, height); } region16_clear(&(xfc->invalidRegion)); @@ -90,9 +98,6 @@ int xf_OutputUpdate(xfContext* xfc) int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height) { -/** ********************************* - * to be improved? - * *********************************/ RECTANGLE_16 invalidRect; invalidRect.left = x; @@ -137,7 +142,7 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, if (!surface) return -1; - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, + freerdp_image_copy(surface->data, surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->data, PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0); invalidRect.left = cmd->left; @@ -216,7 +221,7 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP nWidth = updateRects[j].right - updateRects[j].left; nHeight = updateRects[j].bottom - updateRects[j].top; - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + freerdp_image_copy(surface->data, surface->format, surface->scanline, nXDst, nYDst, nWidth, nHeight, tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0); @@ -251,7 +256,7 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R DstData = surface->data; status = clear_decompress(xfc->codecs->clear, cmd->data, cmd->length, &DstData, - PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height); + surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height); if (status < 0) { @@ -266,7 +271,6 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); - if (!xfc->inGfxFrame) xf_OutputUpdate(xfc); @@ -290,7 +294,7 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF DstData = surface->data; status = planar_decompress(xfc->codecs->planar, cmd->data, cmd->length, &DstData, - PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, FALSE); + surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, FALSE); invalidRect.left = cmd->left; invalidRect.top = cmd->top; @@ -334,7 +338,7 @@ int xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_ DstData = surface->data; status = h264_decompress(xfc->codecs->h264, bs->data, bs->length, &DstData, - PIXEL_FORMAT_XRGB32, surface->scanline , surface->height, meta->regionRects, meta->numRegionRects); + surface->format, surface->scanline , surface->height, meta->regionRects, meta->numRegionRects); if (status < 0) { @@ -417,7 +421,7 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, DstData = surface->data; status = progressive_decompress(xfc->codecs->progressive, cmd->data, cmd->length, &DstData, - PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->surfaceId); + surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->surfaceId); if (status < 0) { @@ -529,6 +533,8 @@ int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODIN int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface) { + size_t size; + UINT32 bytesPerPixel; xfGfxSurface* surface; xfContext* xfc = (xfContext*) context->custom; @@ -541,16 +547,41 @@ int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* cr surface->width = (UINT32) createSurface->width; surface->height = (UINT32) createSurface->height; surface->alpha = (createSurface->pixelFormat == PIXEL_FORMAT_ARGB_8888) ? TRUE : FALSE; - surface->format = xfc->format; + surface->format = PIXEL_FORMAT_XRGB32; - surface->scanline = (surface->width + (surface->width % 4)) * 4; - surface->data = (BYTE*) calloc(1, surface->scanline * surface->height); + surface->scanline = surface->width * 4; + surface->scanline += (surface->scanline % (xfc->scanline_pad / 8)); + + size = surface->scanline * surface->height; + surface->data = (BYTE*) _aligned_malloc(size, 16); if (!surface->data) return -1; - surface->image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, - (char*) surface->data, surface->width, surface->height, 32, surface->scanline); + ZeroMemory(surface->data, size); + + if ((xfc->depth == 24) || (xfc->depth == 32)) + { + surface->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, + (char*) surface->data, surface->width, surface->height, xfc->scanline_pad, surface->scanline); + } + else + { + bytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(xfc->format) / 8); + surface->stageStep = surface->width * bytesPerPixel; + surface->stageStep += (surface->stageStep % (xfc->scanline_pad / 8)); + size = surface->stageStep * surface->height; + + surface->stage = (BYTE*) _aligned_malloc(size, 16); + + if (!surface->stage) + return -1; + + ZeroMemory(surface->stage, size); + + surface->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, + (char*) surface->stage, surface->width, surface->height, xfc->scanline_pad, surface->stageStep); + } context->SetSurfaceData(context, surface->surfaceId, (void*) surface); @@ -567,7 +598,8 @@ int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* de if (surface) { XFree(surface->image); - free(surface->data); + _aligned_free(surface->data); + _aligned_free(surface->stage); free(surface); } @@ -614,7 +646,7 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill) invalidRect.right = rect->right; invalidRect.bottom = rect->bottom; - freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + freerdp_image_fill(surface->data, surface->format, surface->scanline, rect->left, rect->top, nWidth, nHeight, color); region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); @@ -662,13 +694,13 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_ if (sameSurface) { - freerdp_image_move(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline, + freerdp_image_move(surfaceDst->data, surfaceDst->format, surfaceDst->scanline, destPt->x, destPt->y, nWidth, nHeight, rectSrc->left, rectSrc->top); } else { - freerdp_image_copy(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline, - destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, PIXEL_FORMAT_XRGB32, + freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline, + destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, surfaceSrc->format, surfaceSrc->scanline, rectSrc->left, rectSrc->top); } @@ -688,6 +720,7 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_ int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache) { + size_t size; RDPGFX_RECT16* rect; xfGfxSurface* surface; xfGfxCacheEntry* cacheEntry; @@ -708,17 +741,22 @@ int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* cacheEntry->width = (UINT32) (rect->right - rect->left); cacheEntry->height = (UINT32) (rect->bottom - rect->top); cacheEntry->alpha = surface->alpha; - cacheEntry->format = xfc->format; + cacheEntry->format = surface->format; - cacheEntry->scanline = (cacheEntry->width + (cacheEntry->width % 4)) * 4; - cacheEntry->data = (BYTE*) calloc(1, cacheEntry->scanline * cacheEntry->height); + cacheEntry->scanline = cacheEntry->width * 4; + cacheEntry->scanline += (cacheEntry->scanline % (xfc->scanline_pad / 8)); + + size = cacheEntry->scanline * cacheEntry->height; + cacheEntry->data = (BYTE*) _aligned_malloc(size, 16); if (!cacheEntry->data) return -1; - freerdp_image_copy(cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, + ZeroMemory(cacheEntry->data, size); + + freerdp_image_copy(cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0, cacheEntry->width, cacheEntry->height, surface->data, - PIXEL_FORMAT_XRGB32, surface->scanline, rect->left, rect->top); + surface->format, surface->scanline, rect->left, rect->top); context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry); @@ -744,9 +782,9 @@ int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* { destPt = &cacheToSurface->destPts[index]; - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + freerdp_image_copy(surface->data, surface->format, surface->scanline, destPt->x, destPt->y, cacheEntry->width, cacheEntry->height, - cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, 0, 0); + cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0); invalidRect.left = destPt->x; invalidRect.top = destPt->y; @@ -775,7 +813,7 @@ int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PD if (cacheEntry) { - free(cacheEntry->data); + _aligned_free(cacheEntry->data); free(cacheEntry); } diff --git a/client/X11/xf_gfx.h b/client/X11/xf_gfx.h index 9d0661f79..06039a8cf 100644 --- a/client/X11/xf_gfx.h +++ b/client/X11/xf_gfx.h @@ -32,8 +32,10 @@ struct xf_gfx_surface UINT32 height; BOOL alpha; BYTE* data; + BYTE* stage; XImage* image; int scanline; + int stageStep; UINT32 format; }; typedef struct xf_gfx_surface xfGfxSurface; diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index f538a2b9c..349ae3bc5 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -155,8 +155,6 @@ struct xf_context XSetWindowAttributes attribs; BOOL complex_regions; VIRTUAL_SCREEN vscreen; - BYTE* bmp_codec_none; - BYTE* bmp_codec_nsc; void* xv_context; void* clipboard_context; diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index c04816963..52b9d4086 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -603,6 +603,8 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS if (useTempBuffer) { + pDstData = *ppDstData; + status = freerdp_image_copy(pDstData, DstFormat, -1, 0, 0, nWidth, nHeight, planar->TempBuffer, PIXEL_FORMAT_XRGB32, -1, 0, 0); }