xfreerdp: optimize bitmap updates

This commit is contained in:
Marc-André Moreau 2014-09-11 22:29:09 -04:00
parent a3cdcc1641
commit 45d2bab95d
8 changed files with 214 additions and 75 deletions

View File

@ -882,7 +882,7 @@ BOOL xf_post_connect(freerdp *instance)
ZeroMemory(&gcv, sizeof(gcv));
if(xfc->modifierMap)
if (xfc->modifierMap)
XFreeModifiermap(xfc->modifierMap);
xfc->modifierMap = XGetModifierMapping(xfc->display);
@ -900,7 +900,7 @@ BOOL xf_post_connect(freerdp *instance)
(char*) xfc->primary_buffer, xfc->width, xfc->height, xfc->scanline_pad, 0);
xfc->bmp_codec_none = (BYTE *) malloc(64 * 64 * 4);
if (xfc->settings->SoftwareGdi)
if (settings->SoftwareGdi)
{
instance->update->BeginPaint = xf_sw_begin_paint;
instance->update->EndPaint = xf_sw_end_paint;
@ -915,13 +915,14 @@ BOOL xf_post_connect(freerdp *instance)
pointer_cache_register_callbacks(instance->update);
if (!xfc->settings->SoftwareGdi)
if (!settings->SoftwareGdi)
{
glyph_cache_register_callbacks(instance->update);
brush_cache_register_callbacks(instance->update);
bitmap_cache_register_callbacks(instance->update);
offscreen_cache_register_callbacks(instance->update);
palette_cache_register_callbacks(instance->update);
instance->update->BitmapUpdate = xf_gdi_bitmap_update;
}
instance->context->rail = rail_new(instance->settings);
@ -1477,22 +1478,29 @@ void xf_TerminateEventHandler(rdpContext *context, TerminateEventArgs *e)
static void xf_ScalingFactorChangeEventHandler(rdpContext *context, ScalingFactorChangeEventArgs *e)
{
xfContext *xfc = (xfContext *) context;
xfContext* xfc = (xfContext*) context;
xfc->settings->ScalingFactor += e->ScalingFactor;
if(xfc->settings->ScalingFactor > 1.2)
if (xfc->settings->ScalingFactor > 1.2)
xfc->settings->ScalingFactor = 1.2;
if(xfc->settings->ScalingFactor < 0.8)
if (xfc->settings->ScalingFactor < 0.8)
xfc->settings->ScalingFactor = 0.8;
xfc->currentWidth = xfc->originalWidth * xfc->settings->ScalingFactor;
xfc->currentHeight = xfc->originalHeight * xfc->settings->ScalingFactor;
xf_transform_window(xfc);
{
ResizeWindowEventArgs ev;
EventArgsInit(&ev, "xfreerdp");
ev.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
ev.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
PubSub_OnResizeWindow(((rdpContext *) xfc)->pubSub, xfc, &ev);
PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &ev);
}
xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
}
@ -1513,9 +1521,10 @@ static void xfreerdp_client_global_uninit()
static int xfreerdp_client_start(rdpContext *context)
{
xfContext *xfc = (xfContext *) context;
rdpSettings *settings = context->settings;
if(!settings->ServerHostname)
xfContext* xfc = (xfContext *) context;
rdpSettings* settings = context->settings;
if (!settings->ServerHostname)
{
DEBUG_WARN( "error: server hostname was not specified with /v:<server>[:port]\n");
return -1;
@ -1525,11 +1534,11 @@ static int xfreerdp_client_start(rdpContext *context)
return 0;
}
static int xfreerdp_client_stop(rdpContext *context)
static int xfreerdp_client_stop(rdpContext* context)
{
xfContext *xfc = (xfContext *) context;
assert(NULL != context);
if(context->settings->AsyncInput)
xfContext* xfc = (xfContext*) context;
if (context->settings->AsyncInput)
{
wMessageQueue *queue;
queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE);
@ -1540,19 +1549,23 @@ static int xfreerdp_client_stop(rdpContext *context)
{
xfc->disconnect = TRUE;
}
if(xfc->thread)
if (xfc->thread)
{
CloseHandle(xfc->thread);
xfc->thread = NULL;
}
return 0;
}
static int xfreerdp_client_new(freerdp *instance, rdpContext *context)
static int xfreerdp_client_new(freerdp* instance, rdpContext* context)
{
xfContext *xfc;
rdpSettings *settings;
xfc = (xfContext *) instance->context;
xfContext* xfc;
rdpSettings* settings;
xfc = (xfContext*) instance->context;
instance->PreConnect = xf_pre_connect;
instance->PostConnect = xf_post_connect;
instance->PostDisconnect = xf_post_disconnect;
@ -1560,27 +1573,36 @@ static int xfreerdp_client_new(freerdp *instance, rdpContext *context)
instance->VerifyCertificate = xf_verify_certificate;
instance->LogonErrorInfo = xf_logon_error_info;
context->channels = freerdp_channels_new();
settings = instance->settings;
xfc->settings = instance->context->settings;
PubSub_SubscribeTerminate(context->pubSub, (pTerminateEventHandler) xf_TerminateEventHandler);
PubSub_SubscribeScalingFactorChange(context->pubSub, (pScalingFactorChangeEventHandler) xf_ScalingFactorChangeEventHandler);
return 0;
}
static void xfreerdp_client_free(freerdp *instance, rdpContext *context)
static void xfreerdp_client_free(freerdp* instance, rdpContext* context)
{
xfContext *xfc = (xfContext *) context;
if(context)
xfContext* xfc = (xfContext*) context;
if (context)
{
xf_window_free(xfc);
if(xfc->bmp_codec_none)
if (xfc->bmp_codec_none)
free(xfc->bmp_codec_none);
if(xfc->display)
if (xfc->bitmap_buffer)
_aligned_free(xfc->bitmap_buffer);
if (xfc->display)
XCloseDisplay(xfc->display);
}
}
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS *pEntryPoints)
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
{
pEntryPoints->Version = 1;
pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);

View File

@ -285,6 +285,108 @@ Pixmap xf_mono_bitmap_new(xfContext* xfc, int width, int height, BYTE* data)
return bitmap;
}
void xf_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
{
int status;
int nXDst;
int nYDst;
int nXSrc;
int nYSrc;
int nWidth;
int nHeight;
UINT32 index;
XImage* image;
BYTE* pSrcData;
BYTE* pDstData;
UINT32 SrcSize;
BOOL compressed;
UINT32 SrcFormat;
UINT32 bitsPerPixel;
UINT32 bytesPerPixel;
BITMAP_DATA* bitmap;
rdpCodecs* codecs = context->codecs;
xfContext* xfc = (xfContext*) context;
for (index = 0; index < bitmapUpdate->number; index++)
{
bitmap = &(bitmapUpdate->rectangles[index]);
nXSrc = 0;
nYSrc = 0;
nXDst = bitmap->destLeft;
nYDst = bitmap->destTop;
nWidth = bitmap->width;
nHeight = bitmap->height;
pSrcData = bitmap->bitmapDataStream;
SrcSize = bitmap->bitmapLength;
compressed = bitmap->compressed;
bitsPerPixel = bitmap->bitsPerPixel;
bytesPerPixel = (bitsPerPixel + 7) / 8;
SrcFormat = gdi_get_pixel_format(bitsPerPixel, TRUE);
if (xfc->bitmap_size < (nWidth * nHeight * 4))
{
xfc->bitmap_size = nWidth * nHeight * 4;
xfc->bitmap_buffer = (BYTE*) _aligned_realloc(xfc->bitmap_buffer, xfc->bitmap_size, 16);
if (!xfc->bitmap_buffer)
return;
}
if (compressed)
{
pDstData = xfc->bitmap_buffer;
if (bitsPerPixel < 32)
{
freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_INTERLEAVED);
status = interleaved_decompress(codecs->interleaved, pSrcData, SrcSize, bitsPerPixel,
&pDstData, PIXEL_FORMAT_XRGB32, nWidth * 4, 0, 0, nWidth, nHeight);
}
else
{
freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR);
status = planar_decompress(codecs->planar, pSrcData, SrcSize, &pDstData,
PIXEL_FORMAT_XRGB32_VF, nWidth * 4, 0, 0, nWidth, nHeight);
}
if (status < 0)
{
DEBUG_WARN("xf_gdi_bitmap_update: bitmap decompression failure\n");
return;
}
pSrcData = xfc->bitmap_buffer;
}
xf_lock_x11(xfc, FALSE);
XSetFunction(xfc->display, xfc->gc, GXcopy);
image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
(char*) pSrcData, nWidth, nHeight, xfc->scanline_pad, 0);
nWidth = bitmap->destRight - bitmap->destLeft + 1; /* clip width */
nHeight = bitmap->destBottom - bitmap->destTop + 1; /* clip height */
XPutImage(xfc->display, xfc->primary, xfc->gc,
image, 0, 0, nXDst, nYDst, nWidth, nHeight);
XFree(image);
gdi_InvalidateRegion(xfc->hdc, nXDst, nYDst, nWidth, nHeight);
xf_unlock_x11(xfc, FALSE);
}
}
void xf_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette)
{
xfContext* xfc = (xfContext*) context;

View File

@ -26,5 +26,6 @@
#include "xfreerdp.h"
void xf_gdi_register_update_callbacks(rdpUpdate* update);
void xf_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate);
#endif /* __XF_GDI_H */

View File

@ -113,6 +113,8 @@ struct xf_context
BOOL cursorHidden;
HGDI_DC hdc;
UINT32 bitmap_size;
BYTE* bitmap_buffer;
BYTE* primary_buffer;
REGION16 invalidRegion;
BOOL inGfxFrame;

View File

@ -32,8 +32,8 @@ struct _BITMAP_INTERLEAVED_CONTEXT
{
BOOL Compressor;
UINT32 FlipSize;
BYTE* FlipBuffer;
UINT32 TempSize;
BYTE* TempBuffer;
};
FREERDP_API int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcData, UINT32 SrcSize, int bpp,

View File

@ -298,6 +298,7 @@ extern "C" {
#endif
FREERDP_API UINT32 gdi_rop3_code(BYTE code);
FREERDP_API UINT32 gdi_get_pixel_format(UINT32 bitsPerPixel, BOOL vFlip);
FREERDP_API BYTE* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, int x, int y);
FREERDP_API BYTE* gdi_get_brush_pointer(HGDI_DC hdcBrush, int x, int y);
FREERDP_API int gdi_is_mono_pixel_set(BYTE* data, int x, int y, int width);

View File

@ -238,9 +238,11 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, BYTE* pbOrderHdr, UINT32* adv
int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcData, UINT32 SrcSize, int bpp,
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
{
int status;
BOOL vFlip;
int scanline;
BYTE* pDstData;
UINT32 SrcFormat;
UINT32 BufferSize;
int dstBitsPerPixel;
int dstBytesPerPixel;
@ -258,72 +260,81 @@ int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcDa
scanline = nWidth * 3;
BufferSize = scanline * nHeight;
if (vFlip)
{
if (BufferSize > interleaved->FlipSize)
{
interleaved->FlipBuffer = _aligned_realloc(interleaved->FlipBuffer, BufferSize, 16);
interleaved->FlipSize = BufferSize;
}
SrcFormat = PIXEL_FORMAT_RGB24_VF;
if (!interleaved->FlipBuffer)
return -1;
RleDecompress24to24(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
}
else
if ((SrcFormat == DstFormat) && !nXDst && !nYDst && (scanline == nDstStep))
{
RleDecompress24to24(pSrcData, SrcSize, pDstData, scanline, nWidth, nHeight);
return 1;
}
if (BufferSize > interleaved->TempSize)
{
interleaved->TempBuffer = _aligned_realloc(interleaved->TempBuffer, BufferSize, 16);
interleaved->TempSize = BufferSize;
}
if (!interleaved->TempBuffer)
return -1;
RleDecompress24to24(pSrcData, SrcSize, interleaved->TempBuffer, scanline, nWidth, nHeight);
status = freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst,
nWidth, nHeight, interleaved->TempBuffer, SrcFormat, scanline, 0, 0);
}
else if ((bpp == 16) || (bpp == 15))
{
scanline = nWidth * 2;
BufferSize = scanline * nHeight;
if (vFlip)
{
if (BufferSize > interleaved->FlipSize)
{
interleaved->FlipBuffer = _aligned_realloc(interleaved->FlipBuffer, BufferSize, 16);
interleaved->FlipSize = BufferSize;
}
SrcFormat = (bpp == 16) ? PIXEL_FORMAT_RGB16_VF : PIXEL_FORMAT_RGB15_VF;
if (!interleaved->FlipBuffer)
return -1;
RleDecompress16to16(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
}
else
if ((SrcFormat == DstFormat) && !nXDst && !nYDst && (scanline == nDstStep))
{
RleDecompress16to16(pSrcData, SrcSize, pDstData, scanline, nWidth, nHeight);
return 1;
}
if (BufferSize > interleaved->TempSize)
{
interleaved->TempBuffer = _aligned_realloc(interleaved->TempBuffer, BufferSize, 16);
interleaved->TempSize = BufferSize;
}
if (!interleaved->TempBuffer)
return -1;
RleDecompress16to16(pSrcData, SrcSize, interleaved->TempBuffer, scanline, nWidth, nHeight);
status = freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst,
nWidth, nHeight, interleaved->TempBuffer, SrcFormat, scanline, 0, 0);
}
else if (bpp == 8)
{
scanline = nWidth;
BufferSize = scanline * nHeight;
if (vFlip)
{
if (BufferSize > interleaved->FlipSize)
{
interleaved->FlipBuffer = _aligned_realloc(interleaved->FlipBuffer, BufferSize, 16);
interleaved->FlipSize = BufferSize;
}
SrcFormat = PIXEL_FORMAT_RGB8_VF;
if (!interleaved->FlipBuffer)
return -1;
RleDecompress8to8(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
}
else
if ((SrcFormat == DstFormat) && !nXDst && !nYDst && (scanline == nDstStep))
{
RleDecompress8to8(pSrcData, SrcSize, pDstData, scanline, nWidth, nHeight);
return 1;
}
if (BufferSize > interleaved->TempSize)
{
interleaved->TempBuffer = _aligned_realloc(interleaved->TempBuffer, BufferSize, 16);
interleaved->TempSize = BufferSize;
}
if (!interleaved->TempBuffer)
return -1;
RleDecompress8to8(pSrcData, SrcSize, interleaved->TempBuffer, scanline, nWidth, nHeight);
status = freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst,
nWidth, nHeight, interleaved->TempBuffer, SrcFormat, scanline, 0, 0);
}
else
{
@ -341,8 +352,8 @@ BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor)
if (interleaved)
{
interleaved->FlipSize = 64 * 64 * 3;
interleaved->FlipBuffer = _aligned_malloc(interleaved->FlipSize, 16);
interleaved->TempSize = 64 * 64 * 3;
interleaved->TempBuffer = _aligned_malloc(interleaved->TempSize, 16);
}
return interleaved;
@ -353,7 +364,7 @@ void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* interleaved)
if (!interleaved)
return;
_aligned_free(interleaved->FlipBuffer);
_aligned_free(interleaved->TempBuffer);
free(interleaved);
}

View File

@ -529,9 +529,9 @@ void gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
SrcFormat = gdi_get_pixel_format(bitsPerPixel, TRUE);
if (gdi->bitmap_size < (nWidth * nHeight * bytesPerPixel))
if (gdi->bitmap_size < (nWidth * nHeight * 4))
{
gdi->bitmap_size = nWidth * nHeight * bytesPerPixel;
gdi->bitmap_size = nWidth * nHeight * 4;
gdi->bitmap_buffer = (BYTE*) _aligned_realloc(gdi->bitmap_buffer, gdi->bitmap_size, 16);
if (!gdi->bitmap_buffer)
@ -547,7 +547,7 @@ void gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_INTERLEAVED);
status = interleaved_decompress(codecs->interleaved, pSrcData, SrcSize, bitsPerPixel,
&pDstData, PIXEL_FORMAT_XRGB32, nWidth * 4, 0, 0, nWidth, nHeight);
&pDstData, SrcFormat, nWidth * bytesPerPixel, 0, 0, nWidth, nHeight);
}
else
{