From e5882f514802efbaa5e7aa280f17effcbca3c4d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benoi=CC=82t=20LeBlanc?= Date: Fri, 30 May 2014 14:27:51 -0400 Subject: [PATCH 01/50] Added function header for freerdp_update_gateway_usage_method --- include/freerdp/settings.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index d73ccf22b..cb9e25cb7 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -1382,6 +1382,7 @@ FREERDP_API void freerdp_performance_flags_make(rdpSettings* settings); FREERDP_API void freerdp_performance_flags_split(rdpSettings* settings); FREERDP_API void freerdp_set_gateway_usage_method(rdpSettings* settings, UINT32 GatewayUsageMethod); +FREERDP_API void freerdp_update_gateway_usage_method(rdpSettings* settings, UINT32 GatewayEnabled, UINT32 GatewayBypassLocal); FREERDP_API BOOL freerdp_get_param_bool(rdpSettings* settings, int id); FREERDP_API int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param); From 267e95590bbb24e4319e950c3c60f0f4a0a02f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 2 Jun 2014 22:39:40 -0400 Subject: [PATCH 02/50] libfreerdp-client: fix /gfx option --- client/common/cmdline.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 34d300d9c..dc9ba2674 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1577,6 +1577,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, CommandLineSwitchCase(arg, "gfx") { settings->SupportGraphicsPipeline = TRUE; + settings->FastPathOutput = TRUE; + settings->ColorDepth = 32; + settings->LargePointerFlag = TRUE; + settings->FrameMarkerCommandEnabled = TRUE; } CommandLineSwitchCase(arg, "rfx") { From eb657773284dd210c79b01fda70723ee2c2f2c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 2 Jun 2014 22:40:01 -0400 Subject: [PATCH 03/50] channels/disp: cleanup --- channels/disp/client/disp_main.c | 47 +++++++++++++------------------- channels/disp/client/disp_main.h | 2 -- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c index 343c9e3db..881395bbd 100644 --- a/channels/disp/client/disp_main.c +++ b/channels/disp/client/disp_main.c @@ -83,11 +83,7 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback disp = (DISP_PLUGIN*) callback->plugin; -#ifdef DISP_PREVIEW - MonitorLayoutSize = 32; -#else MonitorLayoutSize = 40; -#endif length = 8 + 8 + (NumMonitors * MonitorLayoutSize); @@ -101,11 +97,7 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback if (NumMonitors > disp->MaxNumMonitors) NumMonitors = disp->MaxNumMonitors; -#ifdef DISP_PREVIEW - Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */ -#else Stream_Write_UINT32(s, MonitorLayoutSize); /* MonitorLayoutSize (4 bytes) */ -#endif Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */ @@ -147,10 +139,8 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback fprintf(stderr, "\t: Orientation: %d\n", Monitors[index].Orientation); #endif -#ifndef DISP_PREVIEW Stream_Write_UINT32(s, Monitors[index].DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */ -#endif } Stream_SealLength(s); @@ -308,33 +298,34 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) disp = (DISP_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "disp"); - if (disp == NULL) + if (!disp) { - disp = (DISP_PLUGIN*) malloc(sizeof(DISP_PLUGIN)); + disp = (DISP_PLUGIN*) calloc(1, sizeof(DISP_PLUGIN)); - if (disp) - { - ZeroMemory(disp, sizeof(DISP_PLUGIN)); + if (!disp) + return -1; - disp->iface.Initialize = disp_plugin_initialize; - disp->iface.Connected = NULL; - disp->iface.Disconnected = NULL; - disp->iface.Terminated = disp_plugin_terminated; + disp->iface.Initialize = disp_plugin_initialize; + disp->iface.Connected = NULL; + disp->iface.Disconnected = NULL; + disp->iface.Terminated = disp_plugin_terminated; - context = (DispClientContext*) malloc(sizeof(DispClientContext)); + context = (DispClientContext*) calloc(1, sizeof(DispClientContext)); - context->handle = (void*) disp; + if (!context) + return -1; - context->SendMonitorLayout = disp_send_monitor_layout; + context->handle = (void*) disp; - disp->iface.pInterface = (void*) context; + context->SendMonitorLayout = disp_send_monitor_layout; - disp->MaxNumMonitors = 16; - disp->MaxMonitorWidth = 8192; - disp->MaxMonitorHeight = 8192; + disp->iface.pInterface = (void*) context; - error = pEntryPoints->RegisterPlugin(pEntryPoints, "disp", (IWTSPlugin*) disp); - } + disp->MaxNumMonitors = 16; + disp->MaxMonitorWidth = 8192; + disp->MaxMonitorHeight = 8192; + + error = pEntryPoints->RegisterPlugin(pEntryPoints, "disp", (IWTSPlugin*) disp); } return error; diff --git a/channels/disp/client/disp_main.h b/channels/disp/client/disp_main.h index db1ce10c5..1851618a0 100644 --- a/channels/disp/client/disp_main.h +++ b/channels/disp/client/disp_main.h @@ -34,7 +34,5 @@ #define DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT 0x00000002 #define DISPLAY_CONTROL_PDU_TYPE_CAPS 0x00000003 -#define DISP_PREVIEW 1 - #endif /* FREERDP_CHANNEL_DISP_CLIENT_MAIN_H */ From e74fb24ad1f7d545ed1d0ebd174262f18329d29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 3 Jun 2014 00:05:43 -0400 Subject: [PATCH 04/50] channels/rdpgfx: start working on capability sets --- channels/rdpgfx/client/rdpgfx_main.c | 100 ++++++++++++++++++++++++--- include/freerdp/channels/rdpgfx.h | 4 +- 2 files changed, 92 insertions(+), 12 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 8c6d52b84..c6e2fc87a 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -70,6 +70,78 @@ struct _RDPGFX_PLUGIN }; typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; +int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) +{ + int status; + wStream* s; + UINT16 index; + RDPGFX_PLUGIN* gfx; + RDPGFX_HEADER header; + RDPGFX_CAPSET* capsSet; + RDPGFX_CAPSET* capsSets[2]; + RDPGFX_CAPS_ADVERTISE_PDU pdu; + RDPGFX_CAPSET_VERSION8 capset8; + RDPGFX_CAPSET_VERSION81 capset81; + + gfx = (RDPGFX_PLUGIN*) callback->plugin; + + header.cmdId = RDPGFX_CMDID_CAPSADVERTISE; + header.flags = 0; + + capset8.version = RDPGFX_CAPVERSION_8; + capset8.capsDataLength = 4; + capset8.flags = 0; + //capset8.flags |= RDPGFX_CAPS_FLAG_THINCLIENT; + //capset8.flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + + capset81.version = RDPGFX_CAPVERSION_81; + //capset81.version = 0x00080103; + capset81.capsDataLength = 4; + capset81.flags = 0; + //capset81.flags |= RDPGFX_CAPS_FLAG_THINCLIENT; + //capset81.flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + //capset81.flags |= RDPGFX_CAPS_FLAG_H264ENABLED; + + pdu.capsSetCount = 0; + pdu.capsSets = (RDPGFX_CAPSET**) capsSets; + + capsSets[pdu.capsSetCount++] = (RDPGFX_CAPSET*) &capset81; + capsSets[pdu.capsSetCount++] = (RDPGFX_CAPSET*) &capset8; + + header.pduLength = 8 + 2 + (pdu.capsSetCount * 12); + + fprintf(stderr, "RdpGfxSendCapsAdvertisePdu: %d\n", header.pduLength); + + s = Stream_New(NULL, header.pduLength); + + /* RDPGFX_HEADER */ + + Stream_Write_UINT16(s, header.cmdId); /* cmdId (2 bytes) */ + Stream_Write_UINT16(s, header.flags); /* flags (2 bytes) */ + Stream_Write_UINT32(s, header.pduLength); /* pduLength (4 bytes) */ + + /* RDPGFX_CAPS_ADVERTISE_PDU */ + + Stream_Write_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */ + + for (index = 0; index < pdu.capsSetCount; index++) + { + capsSet = pdu.capsSets[index]; + + Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */ + Stream_Write_UINT32(s, capsSet->capsDataLength); /* capsDataLength (4 bytes) */ + Stream_Write_UINT32(s, capsSet->capsData); /* capsData (4 bytes) */ + } + + Stream_SealLength(s); + + status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); + + Stream_Free(s, TRUE); + + return status; +} + int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { return 0; @@ -96,6 +168,8 @@ static int rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback) { RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; + fprintf(stderr, "RdpGfxOnClose\n"); + free(callback); return 0; @@ -108,8 +182,7 @@ static int rdpgfx_on_new_channel_connection(IWTSListenerCallback* pListenerCallb RDPGFX_CHANNEL_CALLBACK* callback; RDPGFX_LISTENER_CALLBACK* listener_callback = (RDPGFX_LISTENER_CALLBACK*) pListenerCallback; - callback = (RDPGFX_CHANNEL_CALLBACK*) malloc(sizeof(RDPGFX_CHANNEL_CALLBACK)); - ZeroMemory(callback, sizeof(RDPGFX_CHANNEL_CALLBACK)); + callback = (RDPGFX_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPGFX_CHANNEL_CALLBACK)); callback->iface.OnDataReceived = rdpgfx_on_data_received; callback->iface.OnClose = rdpgfx_on_close; @@ -122,6 +195,8 @@ static int rdpgfx_on_new_channel_connection(IWTSListenerCallback* pListenerCallb fprintf(stderr, "RdpGfxOnNewChannelConnection\n"); + rdpgfx_send_caps_advertise_pdu(callback); + return 0; } @@ -130,8 +205,10 @@ static int rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag int status; RDPGFX_PLUGIN* rdpgfx = (RDPGFX_PLUGIN*) pPlugin; - rdpgfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) malloc(sizeof(RDPGFX_LISTENER_CALLBACK)); - ZeroMemory(rdpgfx->listener_callback, sizeof(RDPGFX_LISTENER_CALLBACK)); + rdpgfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) calloc(1, sizeof(RDPGFX_LISTENER_CALLBACK)); + + if (!rdpgfx->listener_callback) + return -1; rdpgfx->listener_callback->iface.OnNewChannelConnection = rdpgfx_on_new_channel_connection; rdpgfx->listener_callback->plugin = pPlugin; @@ -142,7 +219,7 @@ static int rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag rdpgfx->listener->pInterface = rdpgfx->iface.pInterface; - fprintf(stderr, "RdpGfxInitialize\n"); + fprintf(stderr, "RdpGfxInitialize: %d\n", status); return status; } @@ -183,23 +260,26 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) if (!rdpgfx) { - rdpgfx = (RDPGFX_PLUGIN*) malloc(sizeof(RDPGFX_PLUGIN)); - ZeroMemory(rdpgfx, sizeof(RDPGFX_PLUGIN)); + rdpgfx = (RDPGFX_PLUGIN*) calloc(1, sizeof(RDPGFX_PLUGIN)); + + if (!rdpgfx) + return -1; rdpgfx->iface.Initialize = rdpgfx_plugin_initialize; rdpgfx->iface.Connected = NULL; rdpgfx->iface.Disconnected = NULL; rdpgfx->iface.Terminated = rdpgfx_plugin_terminated; - context = (RdpgfxClientContext*) malloc(sizeof(RdpgfxClientContext)); + context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext)); + + if (!context) + return -1; context->handle = (void*) rdpgfx; context->GetVersion = rdpgfx_get_version; rdpgfx->iface.pInterface = (void*) context; - fprintf(stderr, "RdpGfxDVCPluginEntry\n"); - error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpgfx", (IWTSPlugin*) rdpgfx); } diff --git a/include/freerdp/channels/rdpgfx.h b/include/freerdp/channels/rdpgfx.h index ef38bf0a3..d429f1e27 100644 --- a/include/freerdp/channels/rdpgfx.h +++ b/include/freerdp/channels/rdpgfx.h @@ -100,7 +100,7 @@ struct _RDPGFX_CAPSET { UINT32 version; UINT32 capsDataLength; - /* capsData (variable) */ + UINT32 capsData; }; typedef struct _RDPGFX_CAPSET RDPGFX_CAPSET; @@ -292,7 +292,7 @@ typedef struct _RDPGFX_CACHE_IMPORT_REPLY_PDU RDPGFX_CACHE_IMPORT_REPLY_PDU; struct _RDPGFX_CAPS_ADVERTISE_PDU { UINT16 capsSetCount; - /* capsSets */ + RDPGFX_CAPSET** capsSets; }; typedef struct _RDPGFX_CAPS_ADVERTISE_PDU RDPGFX_CAPS_ADVERTISE_PDU; From 8ea161de6182a74590fbd4a294a0bf40adfe9d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 3 Jun 2014 09:49:00 -0400 Subject: [PATCH 05/50] channels/drdynvc: add OnOpen callback --- channels/drdynvc/client/drdynvc_main.c | 10 ++++++++-- channels/drdynvc/client/dvcman.c | 22 ++++++++++++++++++++++ channels/drdynvc/client/dvcman.h | 1 + channels/rdpgfx/client/rdpgfx_main.c | 18 ++++++++++++++---- include/freerdp/dvc.h | 2 ++ 5 files changed, 47 insertions(+), 6 deletions(-) diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index d10f9a751..b1a6ed588 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -217,19 +217,20 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb int status; UINT32 ChannelId; wStream* data_out; + int channel_status; ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = Stream_GetPosition(s); DEBUG_DVC("ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s)); - status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s)); + channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s)); data_out = Stream_New(NULL, pos + 4); Stream_Write_UINT8(data_out, 0x10 | cbChId); Stream_SetPosition(s, 1); Stream_Copy(data_out, s, pos - 1); - if (status == 0) + if (channel_status == 0) { DEBUG_DVC("channel created"); Stream_Write_UINT32(data_out, 0); @@ -248,6 +249,11 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb return 1; } + if (channel_status == 0) + { + dvcman_open_channel(drdynvc->channel_mgr, ChannelId); + } + return 0; } diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c index da170160d..6f7e5b6ed 100644 --- a/channels/drdynvc/client/dvcman.c +++ b/channels/drdynvc/client/dvcman.c @@ -385,6 +385,28 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel return 1; } +int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId) +{ + DVCMAN_CHANNEL* channel; + IWTSVirtualChannelCallback* pCallback; + + channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); + + if (!channel) + { + DEBUG_WARN("ChannelId %d not found!", ChannelId); + return 1; + } + + if (channel->status == 0) + { + pCallback = channel->channel_callback; + pCallback->OnOpen(pCallback); + } + + return 0; +} + int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId) { DVCMAN_CHANNEL* channel; diff --git a/channels/drdynvc/client/dvcman.h b/channels/drdynvc/client/dvcman.h index ca886f3af..9d96d1460 100644 --- a/channels/drdynvc/client/dvcman.h +++ b/channels/drdynvc/client/dvcman.h @@ -87,6 +87,7 @@ int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args); void dvcman_free(IWTSVirtualChannelManager* pChannelMgr); int dvcman_init(IWTSVirtualChannelManager* pChannelMgr); int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName); +int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId); int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId); int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length); int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, BYTE* data, UINT32 data_size); diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index c6e2fc87a..218cecd41 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -91,14 +91,14 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) capset8.version = RDPGFX_CAPVERSION_8; capset8.capsDataLength = 4; capset8.flags = 0; - //capset8.flags |= RDPGFX_CAPS_FLAG_THINCLIENT; + capset8.flags |= RDPGFX_CAPS_FLAG_THINCLIENT; //capset8.flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; capset81.version = RDPGFX_CAPVERSION_81; //capset81.version = 0x00080103; capset81.capsDataLength = 4; capset81.flags = 0; - //capset81.flags |= RDPGFX_CAPS_FLAG_THINCLIENT; + capset81.flags |= RDPGFX_CAPS_FLAG_THINCLIENT; //capset81.flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; //capset81.flags |= RDPGFX_CAPS_FLAG_H264ENABLED; @@ -164,6 +164,17 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, return status; } +static int rdpgfx_on_open(IWTSVirtualChannelCallback* pChannelCallback) +{ + RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; + + fprintf(stderr, "RdpGfxOnOpen\n"); + + rdpgfx_send_caps_advertise_pdu(callback); + + return 0; +} + static int rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback) { RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; @@ -185,6 +196,7 @@ static int rdpgfx_on_new_channel_connection(IWTSListenerCallback* pListenerCallb callback = (RDPGFX_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPGFX_CHANNEL_CALLBACK)); callback->iface.OnDataReceived = rdpgfx_on_data_received; + callback->iface.OnOpen = rdpgfx_on_open; callback->iface.OnClose = rdpgfx_on_close; callback->plugin = listener_callback->plugin; callback->channel_mgr = listener_callback->channel_mgr; @@ -195,8 +207,6 @@ static int rdpgfx_on_new_channel_connection(IWTSListenerCallback* pListenerCallb fprintf(stderr, "RdpGfxOnNewChannelConnection\n"); - rdpgfx_send_caps_advertise_pdu(callback); - return 0; } diff --git a/include/freerdp/dvc.h b/include/freerdp/dvc.h index a2350bfe8..f89745ca4 100644 --- a/include/freerdp/dvc.h +++ b/include/freerdp/dvc.h @@ -140,6 +140,8 @@ struct _IWTSVirtualChannelCallback int (*OnDataReceived) (IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer); + /* Notifies the user that the channel has been opened. */ + int (*OnOpen) (IWTSVirtualChannelCallback* pChannelCallback); /* Notifies the user that the channel has been closed. */ int (*OnClose) (IWTSVirtualChannelCallback* pChannelCallback); }; From 3d7524cac91b4b33d07a5664923af8987ecdfdd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 3 Jun 2014 13:00:03 -0400 Subject: [PATCH 06/50] channels/drdynvc: add state machine, add workaround for missing capabilities pdu --- channels/drdynvc/client/drdynvc_main.c | 57 +++++++++++++++++++------- channels/drdynvc/client/drdynvc_main.h | 12 ++++++ 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index b1a6ed588..0b83753b0 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -153,12 +153,32 @@ int drdynvc_push_event(drdynvcPlugin* drdynvc, wMessage* event) return 0; } +static int drdynvc_send_capability_response(drdynvcPlugin* drdynvc) +{ + int status; + wStream* data_out; + + data_out = Stream_New(NULL, 4); + Stream_Write_UINT16(data_out, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */ + Stream_Write_UINT16(data_out, drdynvc->version); + + status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); + + if (status != CHANNEL_RC_OK) + { + DEBUG_WARN("VirtualChannelWrite failed %d", status); + return 1; + } + + return status; +} + static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { - wStream* data_out; - int error; + int status; DEBUG_DVC("Sp=%d cbChId=%d", Sp, cbChId); + Stream_Seek(s, 1); /* pad */ Stream_Read_UINT16(s, drdynvc->version); @@ -173,18 +193,11 @@ static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, in Stream_Read_UINT16(s, drdynvc->PriorityCharge3); } - data_out = Stream_New(NULL, 4); - Stream_Write_UINT16(data_out, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */ - Stream_Write_UINT16(data_out, drdynvc->version); - error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); + status = drdynvc_send_capability_response(drdynvc); - if (error != CHANNEL_RC_OK) - { - DEBUG_WARN("VirtualChannelWrite failed %d", error); - return 1; - } + drdynvc->channel_error = status; - drdynvc->channel_error = error; + drdynvc->state = DRDYNVC_STATE_READY; return 0; } @@ -219,6 +232,19 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb wStream* data_out; int channel_status; + if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES) + { + /** + * For some reason the server does not always send the + * capabilities pdu as it should. When this happens, + * send a capabilities response. + */ + + drdynvc->version = 3; + drdynvc_send_capability_response(drdynvc); + drdynvc->state = DRDYNVC_STATE_READY; + } + ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = Stream_GetPosition(s); DEBUG_DVC("ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s)); @@ -381,6 +407,8 @@ static void drdynvc_process_connect(rdpSvcPlugin* plugin) } dvcman_init(drdynvc->channel_mgr); + + drdynvc->state = DRDYNVC_STATE_CAPABILITIES; } static void drdynvc_process_event(rdpSvcPlugin* plugin, wMessage* event) @@ -419,8 +447,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) DrdynvcClientContext* context; CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; - _p = (drdynvcPlugin*) malloc(sizeof(drdynvcPlugin)); - ZeroMemory(_p, sizeof(drdynvcPlugin)); + _p = (drdynvcPlugin*) calloc(1, sizeof(drdynvcPlugin)); _p->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED | @@ -429,6 +456,8 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) strcpy(_p->plugin.channel_def.name, "drdynvc"); + _p->state = DRDYNVC_STATE_INITIAL; + _p->plugin.connect_callback = drdynvc_process_connect; _p->plugin.receive_callback = drdynvc_process_receive; _p->plugin.event_callback = drdynvc_process_event; diff --git a/channels/drdynvc/client/drdynvc_main.h b/channels/drdynvc/client/drdynvc_main.h index 369084a19..4eda9d8f5 100644 --- a/channels/drdynvc/client/drdynvc_main.h +++ b/channels/drdynvc/client/drdynvc_main.h @@ -26,6 +26,17 @@ #include #include +enum _DRDYNVC_STATE +{ + DRDYNVC_STATE_INITIAL, + DRDYNVC_STATE_CAPABILITIES, + DRDYNVC_STATE_READY, + DRDYNVC_STATE_OPENING_CHANNEL, + DRDYNVC_STATE_SEND_RECEIVE, + DRDYNVC_STATE_FINAL +}; +typedef enum _DRDYNVC_STATE DRDYNVC_STATE; + #define CREATE_REQUEST_PDU 0x01 #define DATA_FIRST_PDU 0x02 #define DATA_PDU 0x03 @@ -38,6 +49,7 @@ struct drdynvc_plugin { rdpSvcPlugin plugin; + DRDYNVC_STATE state; DrdynvcClientContext* context; int version; From abd833c27e98be6175a10addcf5410091770a5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 3 Jun 2014 13:38:10 -0400 Subject: [PATCH 07/50] libfreerdp-codec: stub new ZGFX (RDP8) bulk compressor/decompressor --- channels/rdpgfx/client/rdpgfx_main.c | 20 +++++- include/freerdp/codec/zgfx.h | 57 ++++++++++++++++ libfreerdp/codec/CMakeLists.txt | 1 + libfreerdp/codec/test/CMakeLists.txt | 1 + libfreerdp/codec/test/TestFreeRDPCodecZGfx.c | 10 +++ libfreerdp/codec/zgfx.c | 72 ++++++++++++++++++++ 6 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 include/freerdp/codec/zgfx.h create mode 100644 libfreerdp/codec/test/TestFreeRDPCodecZGfx.c create mode 100644 libfreerdp/codec/zgfx.c diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 218cecd41..ec77ba68f 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -144,6 +145,23 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { + RDPGFX_HEADER header; + + /* RDPGFX_HEADER */ + + /* data needs to be decompressed first */ + + //winpr_HexDump(Stream_Buffer(s), 32); + + return 0; + + Stream_Read_UINT16(s, header.cmdId); /* cmdId (2 bytes) */ + Stream_Read_UINT16(s, header.flags); /* flags (2 bytes) */ + Stream_Read_UINT32(s, header.pduLength); /* pduLength (4 bytes) */ + + printf("cmdId: 0x%04X flags: 0x%04X pduLength: %d\n", + header.cmdId, header.flags, header.pduLength); + return 0; } @@ -153,7 +171,7 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, int status = 0; RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; - fprintf(stderr, "RdpGfxOnDataReceived\n"); + fprintf(stderr, "RdpGfxOnDataReceived: cbSize: %d\n", cbSize); s = Stream_New(pBuffer, cbSize); diff --git a/include/freerdp/codec/zgfx.h b/include/freerdp/codec/zgfx.h new file mode 100644 index 000000000..b0bc9a8a6 --- /dev/null +++ b/include/freerdp/codec/zgfx.h @@ -0,0 +1,57 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * ZGFX (RDP8) Bulk Data Compression + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CODEC_ZGFX_H +#define FREERDP_CODEC_ZGFX_H + +#include +#include + +#include + +#pragma pack(push,1) + + + +#pragma pack(pop) + +struct _ZGFX_CONTEXT +{ + BOOL Compressor; +}; +typedef struct _ZGFX_CONTEXT ZGFX_CONTEXT; + +#ifdef __cplusplus +extern "C" { +#endif + +FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags); +FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags); + +FREERDP_API void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush); + +FREERDP_API ZGFX_CONTEXT* zgfx_context_new(BOOL Compressor); +FREERDP_API void zgfx_context_free(ZGFX_CONTEXT* zgfx); + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_CODEC_ZGFX_H */ + diff --git a/libfreerdp/codec/CMakeLists.txt b/libfreerdp/codec/CMakeLists.txt index f0ba7f746..abe48739b 100644 --- a/libfreerdp/codec/CMakeLists.txt +++ b/libfreerdp/codec/CMakeLists.txt @@ -50,6 +50,7 @@ set(${MODULE_PREFIX}_SRCS ncrush.c xcrush.c mppc.c + zgfx.c jpeg.c) set(${MODULE_PREFIX}_SSE2_SRCS diff --git a/libfreerdp/codec/test/CMakeLists.txt b/libfreerdp/codec/test/CMakeLists.txt index b63feac4c..fa268c270 100644 --- a/libfreerdp/codec/test/CMakeLists.txt +++ b/libfreerdp/codec/test/CMakeLists.txt @@ -9,6 +9,7 @@ set(${MODULE_PREFIX}_TESTS TestFreeRDPCodecMppc.c TestFreeRDPCodecNCrush.c TestFreeRDPCodecXCrush.c + TestFreeRDPCodecZGfx.c TestFreeRDPCodecPlanar.c TestFreeRDPCodecRemoteFX.c) diff --git a/libfreerdp/codec/test/TestFreeRDPCodecZGfx.c b/libfreerdp/codec/test/TestFreeRDPCodecZGfx.c new file mode 100644 index 000000000..7284424e5 --- /dev/null +++ b/libfreerdp/codec/test/TestFreeRDPCodecZGfx.c @@ -0,0 +1,10 @@ +#include +#include + +#include + +int TestFreeRDPCodecZGfx(int argc, char* argv[]) +{ + return 0; +} + diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c new file mode 100644 index 000000000..7d7ab67e0 --- /dev/null +++ b/libfreerdp/codec/zgfx.c @@ -0,0 +1,72 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * ZGFX (RDP8) Bulk Data Compression + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include + +int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) +{ + int status = 0; + + return status; +} + +int zgfx_compress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags) +{ + int status = 0; + + return 1; +} + +void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush) +{ + +} + +ZGFX_CONTEXT* zgfx_context_new(BOOL Compressor) +{ + ZGFX_CONTEXT* zgfx; + + zgfx = (ZGFX_CONTEXT*) calloc(1, sizeof(ZGFX_CONTEXT)); + + if (zgfx) + { + zgfx->Compressor = Compressor; + + zgfx_context_reset(zgfx, FALSE); + } + + return zgfx; +} + +void zgfx_context_free(ZGFX_CONTEXT* zgfx) +{ + if (zgfx) + { + free(zgfx); + } +} + From a50e4d16fc3beb675564dbf5728834ccb57f9e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 3 Jun 2014 14:29:55 -0400 Subject: [PATCH 08/50] libfreerdp-codec: integrate basic RDP8 decompression support --- channels/rdpgfx/client/CMakeLists.txt | 2 +- channels/rdpgfx/client/rdpgfx_main.c | 30 ++- include/freerdp/codec/zgfx.h | 28 +++ libfreerdp/codec/zgfx.c | 304 +++++++++++++++++++++++++- 4 files changed, 352 insertions(+), 12 deletions(-) diff --git a/channels/rdpgfx/client/CMakeLists.txt b/channels/rdpgfx/client/CMakeLists.txt index 2e76c8ced..f940d1707 100644 --- a/channels/rdpgfx/client/CMakeLists.txt +++ b/channels/rdpgfx/client/CMakeLists.txt @@ -32,7 +32,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE freerdp - MODULES freerdp-common freerdp-utils) + MODULES freerdp-common freerdp-codec freerdp-utils) set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index ec77ba68f..f1606bfe4 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -37,6 +37,7 @@ #include #include +#include #include "rdpgfx_common.h" @@ -68,6 +69,8 @@ struct _RDPGFX_PLUGIN IWTSListener* listener; RDPGFX_LISTENER_CALLBACK* listener_callback; + + ZGFX_CONTEXT* zgfx; }; typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; @@ -149,12 +152,6 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) /* RDPGFX_HEADER */ - /* data needs to be decompressed first */ - - //winpr_HexDump(Stream_Buffer(s), 32); - - return 0; - Stream_Read_UINT16(s, header.cmdId); /* cmdId (2 bytes) */ Stream_Read_UINT16(s, header.flags); /* flags (2 bytes) */ Stream_Read_UINT32(s, header.pduLength); /* pduLength (4 bytes) */ @@ -169,15 +166,28 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, { wStream* s; int status = 0; + UINT32 DstSize = 0; + BYTE* pDstData = NULL; + RDPGFX_PLUGIN* gfx = NULL; RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; + gfx = (RDPGFX_PLUGIN*) callback->plugin; + fprintf(stderr, "RdpGfxOnDataReceived: cbSize: %d\n", cbSize); - s = Stream_New(pBuffer, cbSize); + status = zgfx_decompress(gfx->zgfx, pBuffer, cbSize, &pDstData, &DstSize, 0); + + if (status < 0) + { + printf("zgfx_decompress failure! status: %d\n", status); + return 0; + } + + s = Stream_New(pDstData, DstSize); status = rdpgfx_recv_pdu(callback, s); - Stream_Free(s, FALSE); + Stream_Free(s, TRUE); return status; } @@ -259,6 +269,8 @@ static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin) if (rdpgfx->listener_callback) free(rdpgfx->listener_callback); + zgfx_context_free(rdpgfx->zgfx); + free(rdpgfx); return 0; @@ -308,6 +320,8 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) rdpgfx->iface.pInterface = (void*) context; + rdpgfx->zgfx = zgfx_context_new(FALSE); + error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpgfx", (IWTSPlugin*) rdpgfx); } diff --git a/include/freerdp/codec/zgfx.h b/include/freerdp/codec/zgfx.h index b0bc9a8a6..e7e080f38 100644 --- a/include/freerdp/codec/zgfx.h +++ b/include/freerdp/codec/zgfx.h @@ -25,15 +25,43 @@ #include +#define ZGFX_SEGMENTED_SINGLE 0xE0 +#define ZGFX_SEGMENTED_MULTIPART 0xE1 + #pragma pack(push,1) +typedef struct +{ + BYTE descriptor; + UINT16 segmentCount; + UINT32 uncompressedSize; + // RDP_DATA_SEGMENT first; +} RDP_SEGMENTED_DATA; +typedef struct +{ + UINT32 size; + // BYTE data[size]; +} RDP_DATA_SEGMENT; #pragma pack(pop) struct _ZGFX_CONTEXT { BOOL Compressor; + + BYTE* pbInputCurrent; + BYTE* pbInputEnd; + + UINT32 cBitsRemaining; + UINT32 BitsCurrent; + UINT32 cBitsCurrent; + + BYTE OutputBuffer[65536]; + UINT32 OutputCount; + + BYTE HistoryBuffer[2500000]; + UINT32 HistoryIndex; }; typedef struct _ZGFX_CONTEXT ZGFX_CONTEXT; diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c index 7d7ab67e0..e0e2de0ca 100644 --- a/libfreerdp/codec/zgfx.c +++ b/libfreerdp/codec/zgfx.c @@ -27,23 +27,321 @@ #include +struct _ZGFX_TOKEN +{ + int prefixLength; + int prefixCode; + int valueBits; + int tokenType; + UINT32 valueBase; +}; +typedef struct _ZGFX_TOKEN ZGFX_TOKEN; + +static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] = +{ + // len code vbits type vbase + { 1, 0, 8, 0, 0 }, // 0 + { 5, 17, 5, 1, 0 }, // 10001 + { 5, 18, 7, 1, 32 }, // 10010 + { 5, 19, 9, 1, 160 }, // 10011 + { 5, 20, 10, 1, 672 }, // 10100 + { 5, 21, 12, 1, 1696 }, // 10101 + { 5, 24, 0, 0, 0x00 }, // 11000 + { 5, 25, 0, 0, 0x01 }, // 11001 + { 6, 44, 14, 1, 5792 }, // 101100 + { 6, 45, 15, 1, 22176 }, // 101101 + { 6, 52, 0, 0, 0x02 }, // 110100 + { 6, 53, 0, 0, 0x03 }, // 110101 + { 6, 54, 0, 0, 0xFF }, // 110110 + { 7, 92, 18, 1, 54944 }, // 1011100 + { 7, 93, 20, 1, 317088 }, // 1011101 + { 7, 110, 0, 0, 0x04 }, // 1101110 + { 7, 111, 0, 0, 0x05 }, // 1101111 + { 7, 112, 0, 0, 0x06 }, // 1110000 + { 7, 113, 0, 0, 0x07 }, // 1110001 + { 7, 114, 0, 0, 0x08 }, // 1110010 + { 7, 115, 0, 0, 0x09 }, // 1110011 + { 7, 116, 0, 0, 0x0A }, // 1110100 + { 7, 117, 0, 0, 0x0B }, // 1110101 + { 7, 118, 0, 0, 0x3A }, // 1110110 + { 7, 119, 0, 0, 0x3B }, // 1110111 + { 7, 120, 0, 0, 0x3C }, // 1111000 + { 7, 121, 0, 0, 0x3D }, // 1111001 + { 7, 122, 0, 0, 0x3E }, // 1111010 + { 7, 123, 0, 0, 0x3F }, // 1111011 + { 7, 124, 0, 0, 0x40 }, // 1111100 + { 7, 125, 0, 0, 0x80 }, // 1111101 + { 8, 188, 20, 1, 1365664 }, // 10111100 + { 8, 189, 21, 1, 2414240 }, // 10111101 + { 8, 252, 0, 0, 0x0C }, // 11111100 + { 8, 253, 0, 0, 0x38 }, // 11111101 + { 8, 254, 0, 0, 0x39 }, // 11111110 + { 8, 255, 0, 0, 0x66 }, // 11111111 + { 9, 380, 22, 1, 4511392 }, // 101111100 + { 9, 381, 23, 1, 8705696 }, // 101111101 + { 9, 382, 24, 1, 17094304 }, // 101111110 + { 0 } +}; + +UINT32 zgfx_GetBits(ZGFX_CONTEXT* zgfx, UINT32 bitCount) +{ + UINT32 result; + + while (zgfx->cBitsCurrent < bitCount) + { + zgfx->BitsCurrent <<= 8; + + if (zgfx->pbInputCurrent < zgfx->pbInputEnd) + { + zgfx->BitsCurrent += *(zgfx->pbInputCurrent)++; + } + + zgfx->cBitsCurrent += 8; + } + + zgfx->cBitsRemaining -= bitCount; + zgfx->cBitsCurrent -= bitCount; + + result = zgfx->BitsCurrent >> zgfx->cBitsCurrent; + + zgfx->BitsCurrent &= ((1 << zgfx->cBitsCurrent) - 1); + + return result; +} + +int zgfx_OutputFromNotCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbRaw, int cbRaw) +{ + BYTE c; + int iRaw; + + zgfx->OutputCount = 0; + + for (iRaw = 0; iRaw < cbRaw; iRaw++) + { + c = pbRaw[iRaw]; + + zgfx->HistoryBuffer[zgfx->HistoryIndex++] = c; + + if (zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer)) + zgfx->HistoryIndex = 0; + + zgfx->OutputBuffer[zgfx->OutputCount++] = c; + } + + return 1; +} + +int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded) +{ + BYTE c; + int extra; + int opIndex; + int haveBits; + int inPrefix; + UINT32 count; + UINT32 distance; + UINT32 prevIndex; + + zgfx->OutputCount = 0; + + zgfx->pbInputCurrent = pbEncoded; + zgfx->pbInputEnd = pbEncoded + cbEncoded - 1; + + zgfx->cBitsRemaining = 8 * (cbEncoded - 1) - *zgfx->pbInputEnd; + zgfx->cBitsCurrent = 0; + zgfx->BitsCurrent = 0; + + while (zgfx->cBitsRemaining) + { + haveBits = 0; + inPrefix = 0; + + for (opIndex = 0; ZGFX_TOKEN_TABLE[opIndex].prefixLength != 0; opIndex++) + { + while (haveBits < ZGFX_TOKEN_TABLE[opIndex].prefixLength) + { + inPrefix = (inPrefix << 1) + zgfx_GetBits(zgfx, 1); + haveBits++; + } + + if (inPrefix == ZGFX_TOKEN_TABLE[opIndex].prefixCode) + { + if (ZGFX_TOKEN_TABLE[opIndex].tokenType == 0) + { + c = (BYTE)(ZGFX_TOKEN_TABLE[opIndex].valueBase + + zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits)); + + goto output_literal; + } + else + { + distance = ZGFX_TOKEN_TABLE[opIndex].valueBase + + zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); + + if (distance != 0) + { + if (zgfx_GetBits(zgfx, 1) == 0) + { + count = 3; + } + else + { + count = 4; + extra = 2; + + while (zgfx_GetBits(zgfx, 1) == 1) + { + count *= 2; + extra++; + } + + count += zgfx_GetBits(zgfx, extra); + } + + goto output_match; + } + else + { + count = zgfx_GetBits(zgfx, 15); + + zgfx->cBitsRemaining -= zgfx->cBitsCurrent; + zgfx->cBitsCurrent = 0; + zgfx->BitsCurrent = 0; + + goto output_unencoded; + } + } + } + } + break; + +output_literal: + + zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; + + if (++zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer)) + zgfx->HistoryIndex = 0; + + zgfx->OutputBuffer[zgfx->OutputCount++] = c; + continue; + +output_match: + + prevIndex = zgfx->HistoryIndex + sizeof(zgfx->HistoryBuffer) - distance; + prevIndex = prevIndex % sizeof(zgfx->HistoryBuffer); + + while (count--) + { + c = zgfx->HistoryBuffer[prevIndex]; + + if (++prevIndex == sizeof(zgfx->HistoryBuffer)) + prevIndex = 0; + + zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; + + if (++zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer)) + zgfx->HistoryIndex = 0; + + zgfx->OutputBuffer[zgfx->OutputCount] = c; + ++zgfx->OutputCount; + } + continue; + +output_unencoded: + while (count--) + { + c = *zgfx->pbInputCurrent++; + zgfx->cBitsRemaining -= 8; + + zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; + + if (++zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer)) + zgfx->HistoryIndex = 0; + + zgfx->OutputBuffer[zgfx->OutputCount] = c; + ++zgfx->OutputCount; + } + continue; + } + + return 1; +} + +int zgfx_OutputFromSegment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, int cbSegment) +{ + int status; + + if (pbSegment[0] & PACKET_COMPRESSED) + status = zgfx_OutputFromCompressed(zgfx, pbSegment + 1, cbSegment - 1); + else + status = zgfx_OutputFromNotCompressed(zgfx, pbSegment + 1, cbSegment - 1); + + return status; +} + +int zgfx_Decompress_Internal(ZGFX_CONTEXT* zgfx, BYTE* pbInput, int cbInput, BYTE** ppbOutput, int* pcbOutput) +{ + int status; + + RDP_SEGMENTED_DATA* pSegmentedData = (RDP_SEGMENTED_DATA*) pbInput; + + if (pSegmentedData->descriptor == ZGFX_SEGMENTED_SINGLE) + { + status = zgfx_OutputFromSegment(zgfx, pbInput + 1, cbInput - 1); + + *ppbOutput = (BYTE*) malloc(zgfx->OutputCount); + *pcbOutput = zgfx->OutputCount; + CopyMemory(*ppbOutput, zgfx->OutputBuffer, zgfx->OutputCount); + } + else if (pSegmentedData->descriptor == ZGFX_SEGMENTED_MULTIPART) + { + UINT16 segmentNumber; + UINT32 segmentOffset = sizeof(RDP_SEGMENTED_DATA); + BYTE* pConcatenated = (BYTE*) malloc(pSegmentedData->uncompressedSize); + + *ppbOutput = pConcatenated; + *pcbOutput = pSegmentedData->uncompressedSize; + + for (segmentNumber = 0; segmentNumber < pSegmentedData->segmentCount; segmentNumber++) + { + RDP_DATA_SEGMENT* pSegment = (RDP_DATA_SEGMENT*) (pbInput + segmentOffset); + + status = zgfx_OutputFromSegment(zgfx, pbInput + segmentOffset + sizeof(RDP_DATA_SEGMENT), pSegment->size); + + segmentOffset += sizeof(RDP_DATA_SEGMENT) + pSegment->size; + CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount); + pConcatenated += zgfx->OutputCount; + } + } + + return 1; +} + int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) { int status = 0; + int cbOutput = 0; + BYTE* pbOutput = NULL; + + status = zgfx_Decompress_Internal(zgfx, pSrcData, SrcSize, &pbOutput, &cbOutput); + + if (status >= 0) + { + *ppDstData = pbOutput; + *pDstSize = (UINT32) cbOutput; + } return status; } int zgfx_compress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags) { - int status = 0; - return 1; } void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush) { - + zgfx->HistoryIndex = 0; } ZGFX_CONTEXT* zgfx_context_new(BOOL Compressor) From c9172dfdb33c966309cd447aa63094dc8cd7f3e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 3 Jun 2014 15:32:03 -0400 Subject: [PATCH 09/50] channels/rdpgfx: start parsing pdus --- channels/rdpgfx/client/rdpgfx_main.c | 195 ++++++++++++++++++++++++++- include/freerdp/channels/rdpgfx.h | 8 +- 2 files changed, 195 insertions(+), 8 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index f1606bfe4..66a405410 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -74,6 +74,40 @@ struct _RDPGFX_PLUGIN }; typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; +const char* RDPGFX_CMDID_STRINGS[] = +{ + "RDPGFX_CMDID_UNUSED_0000", + "RDPGFX_CMDID_WIRETOSURFACE_1", + "RDPGFX_CMDID_WIRETOSURFACE_2", + "RDPGFX_CMDID_DELETEENCODINGCONTEXT", + "RDPGFX_CMDID_SOLIDFILL", + "RDPGFX_CMDID_SURFACETOSURFACE", + "RDPGFX_CMDID_SURFACETOCACHE", + "RDPGFX_CMDID_CACHETOSURFACE", + "RDPGFX_CMDID_EVICTCACHEENTRY", + "RDPGFX_CMDID_CREATESURFACE", + "RDPGFX_CMDID_DELETESURFACE", + "RDPGFX_CMDID_STARTFRAME", + "RDPGFX_CMDID_ENDFRAME", + "RDPGFX_CMDID_FRAMEACKNOWLEDGE", + "RDPGFX_CMDID_RESETGRAPHICS", + "RDPGFX_CMDID_MAPSURFACETOOUTPUT", + "RDPGFX_CMDID_CACHEIMPORTOFFER", + "RDPGFX_CMDID_CACHEIMPORTREPLY", + "RDPGFX_CMDID_CAPSADVERTISE", + "RDPGFX_CMDID_CAPSCONFIRM", + "RDPGFX_CMDID_UNUSED_0014", + "RDPGFX_CMDID_MAPSURFACETOWINDOW" +}; + +const char* rdpgfx_get_cmdid_string(UINT16 cmdId) +{ + if (cmdId <= RDPGFX_CMDID_MAPSURFACETOWINDOW) + return RDPGFX_CMDID_STRINGS[cmdId]; + else + return "RDPGFX_CMDID_UNKNOWN"; +} + int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) { int status; @@ -146,8 +180,96 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) return status; } +int rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_CAPSET capsSet; + RDPGFX_CAPS_CONFIRM_PDU pdu; + + pdu.capsSet = &capsSet; + + Stream_Read_UINT32(s, capsSet.version); /* version (4 bytes) */ + Stream_Read_UINT32(s, capsSet.capsDataLength); /* capsDataLength (4 bytes) */ + Stream_Read_UINT32(s, capsSet.capsData); /* capsData (4 bytes) */ + + fprintf(stderr, "RdpGfxRecvCapsConfirmPdu: version: 0x%04X capsDataLength: %d capsData: 0x%04X\n", + capsSet.version, capsSet.capsDataLength, capsSet.capsData); + + return 1; +} + +int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + UINT32 index; + MONITOR_DEF* monitor; + RDPGFX_RESET_GRAPHICS_PDU pdu; + + Stream_Read_UINT32(s, pdu.width); /* width (4 bytes) */ + Stream_Read_UINT32(s, pdu.height); /* height (4 bytes) */ + Stream_Read_UINT32(s, pdu.monitorCount); /* monitorCount (4 bytes) */ + + pdu.monitorDefArray = (MONITOR_DEF*) calloc(pdu.monitorCount, sizeof(MONITOR_DEF)); + + if (!pdu.monitorDefArray) + return -1; + + for (index = 0; index < pdu.monitorCount; index++) + { + monitor = &(pdu.monitorDefArray[index]); + Stream_Read_UINT32(s, monitor->left); /* left (4 bytes) */ + Stream_Read_UINT32(s, monitor->top); /* top (4 bytes) */ + Stream_Read_UINT32(s, monitor->right); /* right (4 bytes) */ + Stream_Read_UINT32(s, monitor->bottom); /* bottom (4 bytes) */ + Stream_Read_UINT32(s, monitor->flags); /* flags (4 bytes) */ + } + + fprintf(stderr, "RdpGfxRecvResetGraphicsPdu: width: %d height: %d count: %d\n", + pdu.width, pdu.height, pdu.monitorCount); + + return 1; +} + +int rdpgfx_recv_create_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_CREATE_SURFACE_PDU pdu; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT16(s, pdu.width); /* width (2 bytes) */ + Stream_Read_UINT16(s, pdu.height); /* height (2 bytes) */ + Stream_Read_UINT8(s, pdu.pixelFormat); /* RDPGFX_PIXELFORMAT (1 byte) */ + + fprintf(stderr, "RdpGfxRecvCreateSurfacePdu: surfaceId: %d width: %d height: %d pixelFormat: %d\n", + pdu.surfaceId, pdu.width, pdu.height, pdu.pixelFormat); + + return 1; +} + +int rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_START_FRAME_PDU pdu; + + Stream_Read_UINT32(s, pdu.timestamp); /* timestamp (4 bytes) */ + Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ + + fprintf(stderr, "RdpGfxRecvStartFramePdu: frameId: %d timestamp: 0x%04X\n", + pdu.frameId, pdu.timestamp); + + return 1; +} + +int rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_END_FRAME_PDU pdu; + + Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ + + fprintf(stderr, "RdpGfxRecvEndFramePdu: frameId: %d\n", pdu.frameId); + + return 1; +} + int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { + int status; RDPGFX_HEADER header; /* RDPGFX_HEADER */ @@ -156,8 +278,75 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) Stream_Read_UINT16(s, header.flags); /* flags (2 bytes) */ Stream_Read_UINT32(s, header.pduLength); /* pduLength (4 bytes) */ - printf("cmdId: 0x%04X flags: 0x%04X pduLength: %d\n", - header.cmdId, header.flags, header.pduLength); +#if 0 + printf("cmdId: %s (0x%04X) flags: 0x%04X pduLength: %d\n", + rdpgfx_get_cmdid_string(header.cmdId), header.cmdId, header.flags, header.pduLength); +#endif + + switch (header.cmdId) + { + case RDPGFX_CMDID_WIRETOSURFACE_1: + break; + + case RDPGFX_CMDID_WIRETOSURFACE_2: + break; + + case RDPGFX_CMDID_DELETEENCODINGCONTEXT: + break; + + case RDPGFX_CMDID_SOLIDFILL: + break; + + case RDPGFX_CMDID_SURFACETOSURFACE: + break; + + case RDPGFX_CMDID_SURFACETOCACHE: + break; + + case RDPGFX_CMDID_CACHETOSURFACE: + break; + + case RDPGFX_CMDID_EVICTCACHEENTRY: + break; + + case RDPGFX_CMDID_CREATESURFACE: + break; + + case RDPGFX_CMDID_DELETESURFACE: + break; + + case RDPGFX_CMDID_STARTFRAME: + status = rdpgfx_recv_start_frame_pdu(callback, s); + break; + + case RDPGFX_CMDID_ENDFRAME: + status = rdpgfx_recv_end_frame_pdu(callback, s); + break; + + case RDPGFX_CMDID_RESETGRAPHICS: + status = rdpgfx_recv_reset_graphics_pdu(callback, s); + break; + + case RDPGFX_CMDID_MAPSURFACETOOUTPUT: + break; + + case RDPGFX_CMDID_CACHEIMPORTOFFER: + break; + + case RDPGFX_CMDID_CACHEIMPORTREPLY: + break; + + case RDPGFX_CMDID_CAPSCONFIRM: + status = rdpgfx_recv_caps_confirm_pdu(callback, s); + break; + + case RDPGFX_CMDID_MAPSURFACETOWINDOW: + break; + + default: + fprintf(stderr, "Unknown GFX cmdId: 0x%04X\n", header.cmdId); + break; + } return 0; } @@ -173,8 +362,6 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, gfx = (RDPGFX_PLUGIN*) callback->plugin; - fprintf(stderr, "RdpGfxOnDataReceived: cbSize: %d\n", cbSize); - status = zgfx_decompress(gfx->zgfx, pBuffer, cbSize, &pDstData, &DstSize, 0); if (status < 0) diff --git a/include/freerdp/channels/rdpgfx.h b/include/freerdp/channels/rdpgfx.h index d429f1e27..05d18ed37 100644 --- a/include/freerdp/channels/rdpgfx.h +++ b/include/freerdp/channels/rdpgfx.h @@ -60,6 +60,7 @@ typedef struct _RDPGFX_COLOR32 RDPGFX_COLOR32; typedef BYTE RDPGFX_PIXELFORMAT; +#define RDPGFX_CMDID_UNUSED_0000 0x0000 #define RDPGFX_CMDID_WIRETOSURFACE_1 0x0001 #define RDPGFX_CMDID_WIRETOSURFACE_2 0x0002 #define RDPGFX_CMDID_DELETEENCODINGCONTEXT 0x0003 @@ -79,6 +80,7 @@ typedef BYTE RDPGFX_PIXELFORMAT; #define RDPGFX_CMDID_CACHEIMPORTREPLY 0x0011 #define RDPGFX_CMDID_CAPSADVERTISE 0x0012 #define RDPGFX_CMDID_CAPSCONFIRM 0x0013 +#define RDPGFX_CMDID_UNUSED_0014 0x0014 #define RDPGFX_CMDID_MAPSURFACETOWINDOW 0x0015 struct _RDPGFX_HEADER @@ -254,8 +256,7 @@ struct _RDPGFX_RESET_GRAPHICS_PDU UINT32 width; UINT32 height; UINT32 monitorCount; - /* monitorDefArray */ - /* pad */ + MONITOR_DEF* monitorDefArray; }; typedef struct _RDPGFX_RESET_GRAPHICS_PDU RDPGFX_RESET_GRAPHICS_PDU; @@ -298,8 +299,7 @@ typedef struct _RDPGFX_CAPS_ADVERTISE_PDU RDPGFX_CAPS_ADVERTISE_PDU; struct _RDPGFX_CAPS_CONFIRM_PDU { - RDPGFX_CAPSET* capSet; - /* capSet */ + RDPGFX_CAPSET* capsSet; }; typedef struct _RDPGFX_CAPS_CONFIRM_PDU RDPGFX_CAPS_CONFIRM_PDU; From 280d1c859fe5131834ff250e2da5aee9c09fbd10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 3 Jun 2014 19:48:47 -0400 Subject: [PATCH 10/50] channels/rdpgfx: parse all core egfx pdus --- channels/rdpgfx/client/rdpgfx_main.c | 469 ++++++++++++++++++++++++--- include/freerdp/channels/rdpgfx.h | 13 +- 2 files changed, 434 insertions(+), 48 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 66a405410..a6ba91486 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -70,7 +70,13 @@ struct _RDPGFX_PLUGIN IWTSListener* listener; RDPGFX_LISTENER_CALLBACK* listener_callback; + BOOL ThinClient; + BOOL SmallCache; + BOOL H264; + ZGFX_CONTEXT* zgfx; + UINT32 UnacknowledgedFrames; + UINT32 TotalDecodedFrames; }; typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; @@ -108,6 +114,80 @@ const char* rdpgfx_get_cmdid_string(UINT16 cmdId) return "RDPGFX_CMDID_UNKNOWN"; } +int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header) +{ + Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ + Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */ + Stream_Read_UINT32(s, header->pduLength); /* pduLength (4 bytes) */ + + return 1; +} + +int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header) +{ + Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ + Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */ + Stream_Write_UINT32(s, header->pduLength); /* pduLength (4 bytes) */ + + return 1; +} + +int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16) +{ + Stream_Read_UINT16(s, pt16->x); /* x (2 bytes) */ + Stream_Read_UINT16(s, pt16->y); /* y (2 bytes) */ + + return 1; +} + +int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16) +{ + Stream_Write_UINT16(s, point16->x); /* x (2 bytes) */ + Stream_Write_UINT16(s, point16->y); /* y (2 bytes) */ + + return 1; +} + +int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16) +{ + Stream_Read_UINT16(s, rect16->left); /* left (2 bytes) */ + Stream_Read_UINT16(s, rect16->top); /* top (2 bytes) */ + Stream_Read_UINT16(s, rect16->right); /* right (2 bytes) */ + Stream_Read_UINT16(s, rect16->bottom); /* bottom (2 bytes) */ + + return 1; +} + +int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16) +{ + Stream_Write_UINT16(s, rect16->left); /* left (2 bytes) */ + Stream_Write_UINT16(s, rect16->top); /* top (2 bytes) */ + Stream_Write_UINT16(s, rect16->right); /* right (2 bytes) */ + Stream_Write_UINT16(s, rect16->bottom); /* bottom (2 bytes) */ + + return 1; +} + +int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32) +{ + Stream_Read_UINT8(s, color32->B); /* B (1 byte) */ + Stream_Read_UINT8(s, color32->G); /* G (1 byte) */ + Stream_Read_UINT8(s, color32->R); /* R (1 byte) */ + Stream_Read_UINT8(s, color32->XA); /* XA (1 byte) */ + + return 1; +} + +int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32) +{ + Stream_Write_UINT8(s, color32->B); /* B (1 byte) */ + Stream_Write_UINT8(s, color32->G); /* G (1 byte) */ + Stream_Write_UINT8(s, color32->R); /* R (1 byte) */ + Stream_Write_UINT8(s, color32->XA); /* XA (1 byte) */ + + return 1; +} + int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) { int status; @@ -116,47 +196,53 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) RDPGFX_PLUGIN* gfx; RDPGFX_HEADER header; RDPGFX_CAPSET* capsSet; - RDPGFX_CAPSET* capsSets[2]; + RDPGFX_CAPSET capsSets[2]; RDPGFX_CAPS_ADVERTISE_PDU pdu; - RDPGFX_CAPSET_VERSION8 capset8; - RDPGFX_CAPSET_VERSION81 capset81; gfx = (RDPGFX_PLUGIN*) callback->plugin; - header.cmdId = RDPGFX_CMDID_CAPSADVERTISE; + gfx->ThinClient = FALSE; + gfx->SmallCache = TRUE; + gfx->H264 = TRUE; + header.flags = 0; + header.cmdId = RDPGFX_CMDID_CAPSADVERTISE; - capset8.version = RDPGFX_CAPVERSION_8; - capset8.capsDataLength = 4; - capset8.flags = 0; - capset8.flags |= RDPGFX_CAPS_FLAG_THINCLIENT; - //capset8.flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + pdu.capsSetCount = 2; + pdu.capsSets = (RDPGFX_CAPSET*) capsSets; - capset81.version = RDPGFX_CAPVERSION_81; - //capset81.version = 0x00080103; - capset81.capsDataLength = 4; - capset81.flags = 0; - capset81.flags |= RDPGFX_CAPS_FLAG_THINCLIENT; - //capset81.flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; - //capset81.flags |= RDPGFX_CAPS_FLAG_H264ENABLED; + capsSet = &capsSets[0]; - pdu.capsSetCount = 0; - pdu.capsSets = (RDPGFX_CAPSET**) capsSets; + capsSet->version = RDPGFX_CAPVERSION_8; + capsSet->flags = 0; - capsSets[pdu.capsSetCount++] = (RDPGFX_CAPSET*) &capset81; - capsSets[pdu.capsSetCount++] = (RDPGFX_CAPSET*) &capset8; + if (gfx->ThinClient) + capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; - header.pduLength = 8 + 2 + (pdu.capsSetCount * 12); + if (gfx->SmallCache) + capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + + capsSet = &capsSets[1]; + + capsSet->version = RDPGFX_CAPVERSION_81; + capsSet->flags = 0; + + if (gfx->ThinClient) + capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; + + if (gfx->SmallCache) + capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + + if (gfx->H264) + capsSet->flags |= RDPGFX_CAPS_FLAG_H264ENABLED; + + header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE); fprintf(stderr, "RdpGfxSendCapsAdvertisePdu: %d\n", header.pduLength); s = Stream_New(NULL, header.pduLength); - /* RDPGFX_HEADER */ - - Stream_Write_UINT16(s, header.cmdId); /* cmdId (2 bytes) */ - Stream_Write_UINT16(s, header.flags); /* flags (2 bytes) */ - Stream_Write_UINT32(s, header.pduLength); /* pduLength (4 bytes) */ + rdpgfx_write_header(s, &header); /* RDPGFX_CAPS_ADVERTISE_PDU */ @@ -164,11 +250,10 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) for (index = 0; index < pdu.capsSetCount; index++) { - capsSet = pdu.capsSets[index]; - + capsSet = &(pdu.capsSets[index]); Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */ - Stream_Write_UINT32(s, capsSet->capsDataLength); /* capsDataLength (4 bytes) */ - Stream_Write_UINT32(s, capsSet->capsData); /* capsData (4 bytes) */ + Stream_Write_UINT32(s, 4); /* capsDataLength (4 bytes) */ + Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */ } Stream_SealLength(s); @@ -183,20 +268,53 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) int rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_CAPSET capsSet; + UINT32 capsDataLength; RDPGFX_CAPS_CONFIRM_PDU pdu; pdu.capsSet = &capsSet; Stream_Read_UINT32(s, capsSet.version); /* version (4 bytes) */ - Stream_Read_UINT32(s, capsSet.capsDataLength); /* capsDataLength (4 bytes) */ - Stream_Read_UINT32(s, capsSet.capsData); /* capsData (4 bytes) */ + Stream_Read_UINT32(s, capsDataLength); /* capsDataLength (4 bytes) */ + Stream_Read_UINT32(s, capsSet.flags); /* capsData (4 bytes) */ - fprintf(stderr, "RdpGfxRecvCapsConfirmPdu: version: 0x%04X capsDataLength: %d capsData: 0x%04X\n", - capsSet.version, capsSet.capsDataLength, capsSet.capsData); + fprintf(stderr, "RdpGfxRecvCapsConfirmPdu: version: 0x%04X flags: 0x%04X\n", + capsSet.version, capsSet.flags); return 1; } +int rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, RDPGFX_FRAME_ACKNOWLEDGE_PDU* pdu) +{ + int status; + wStream* s; + RDPGFX_PLUGIN* gfx; + RDPGFX_HEADER header; + + gfx = (RDPGFX_PLUGIN*) callback->plugin; + + header.flags = 0; + header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE; + header.pduLength = RDPGFX_HEADER_SIZE + 12; + + fprintf(stderr, "RdpGfxSendFrameAcknowledgePdu: %d\n", pdu->frameId); + + s = Stream_New(NULL, header.pduLength); + + rdpgfx_write_header(s, &header); + + /* RDPGFX_FRAME_ACKNOWLEDGE_PDU */ + + Stream_Write_UINT32(s, pdu->queueDepth); /* queueDepth (4 bytes) */ + Stream_Write_UINT32(s, pdu->frameId); /* frameId (4 bytes) */ + Stream_Write_UINT32(s, pdu->totalFramesDecoded); /* totalFramesDecoded (4 bytes) */ + + status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); + + Stream_Free(s, TRUE); + + return status; +} + int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { UINT32 index; @@ -222,12 +340,48 @@ int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s Stream_Read_UINT32(s, monitor->flags); /* flags (4 bytes) */ } + /* pad (total size is 340 bytes) */ + fprintf(stderr, "RdpGfxRecvResetGraphicsPdu: width: %d height: %d count: %d\n", pdu.width, pdu.height, pdu.monitorCount); return 1; } +int rdpgfx_recv_evict_cache_entry_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_EVICT_CACHE_ENTRY_PDU pdu; + + Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ + + fprintf(stderr, "RdpGfxRecvEvictCacheEntryPdu: cacheSlot: %d\n", pdu.cacheSlot); + + return 1; +} + +int rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + UINT16 index; + RDPGFX_CACHE_IMPORT_REPLY_PDU pdu; + + Stream_Read_UINT16(s, pdu.importedEntriesCount); /* cacheSlot (2 bytes) */ + + pdu.cacheSlots = (UINT16*) calloc(pdu.importedEntriesCount, sizeof(UINT16)); + + if (!pdu.cacheSlots) + return -1; + + for (index = 0; index < pdu.importedEntriesCount; index++) + { + Stream_Read_UINT16(s, pdu.cacheSlots[index]); /* cacheSlot (2 bytes) */ + } + + fprintf(stderr, "RdpGfxRecvCacheImportReplyPdu: importedEntriesCount: %d\n", + pdu.importedEntriesCount); + + return 1; +} + int rdpgfx_recv_create_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_CREATE_SURFACE_PDU pdu; @@ -243,9 +397,21 @@ int rdpgfx_recv_create_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s return 1; } +int rdpgfx_recv_delete_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_DELETE_SURFACE_PDU pdu; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + + fprintf(stderr, "RdpGfxRecvDeleteSurfacePdu: surfaceId: %d\n", pdu.surfaceId); + + return 1; +} + int rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_START_FRAME_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; Stream_Read_UINT32(s, pdu.timestamp); /* timestamp (4 bytes) */ Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ @@ -253,17 +419,228 @@ int rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) fprintf(stderr, "RdpGfxRecvStartFramePdu: frameId: %d timestamp: 0x%04X\n", pdu.frameId, pdu.timestamp); + gfx->UnacknowledgedFrames++; + return 1; } int rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_END_FRAME_PDU pdu; + RDPGFX_FRAME_ACKNOWLEDGE_PDU ack; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ fprintf(stderr, "RdpGfxRecvEndFramePdu: frameId: %d\n", pdu.frameId); + gfx->UnacknowledgedFrames--; + gfx->TotalDecodedFrames++; + + ack.frameId = pdu.frameId; + ack.totalFramesDecoded = gfx->TotalDecodedFrames; + + ack.queueDepth = SUSPEND_FRAME_ACKNOWLEDGEMENT; + //ack.queueDepth = QUEUE_DEPTH_UNAVAILABLE; + //ack.queueDepth = gfx->UnacknowledgedFrames; + + rdpgfx_send_frame_acknowledge_pdu(callback, &ack); + + return 1; +} + +int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_WIRE_TO_SURFACE_PDU_1 pdu; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT16(s, pdu.codecId); /* codecId (2 bytes) */ + Stream_Read_UINT8(s, pdu.pixelFormat); /* pixelFormat (1 byte) */ + + Stream_Read_UINT16(s, pdu.destRect.left); /* left (2 bytes) */ + Stream_Read_UINT16(s, pdu.destRect.top); /* top (2 bytes) */ + Stream_Read_UINT16(s, pdu.destRect.right); /* right (2 bytes) */ + Stream_Read_UINT16(s, pdu.destRect.bottom); /* bottom (2 bytes) */ + + Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ + + pdu.bitmapData = Stream_Pointer(s); + + fprintf(stderr, "RdpGfxRecvWireToSurface1Pdu: surfaceId: %d codecId: 0x%04X pixelFormat: 0x%04X " + "destRect: left: %d top: %d right: %d bottom: %d bitmapDataLength: %d\n", + pdu.surfaceId, pdu.codecId, pdu.pixelFormat, + pdu.destRect.left, pdu.destRect.top, pdu.destRect.right, pdu.destRect.bottom, + pdu.bitmapDataLength); + + return 1; +} + +int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_WIRE_TO_SURFACE_PDU_2 pdu; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT16(s, pdu.codecId); /* codecId (2 bytes) */ + Stream_Read_UINT32(s, pdu.codecContextId); /* codecContextId (4 bytes) */ + Stream_Read_UINT8(s, pdu.pixelFormat); /* pixelFormat (1 byte) */ + Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ + + pdu.bitmapData = Stream_Pointer(s); + + fprintf(stderr, "RdpGfxRecvWireToSurface2Pdu: surfaceId: %d codecId: 0x%04X " + "codecContextId: %d pixelFormat: 0x%04X bitmapDataLength: %d\n", + pdu.surfaceId, pdu.codecId, pdu.codecContextId, pdu.pixelFormat, pdu.bitmapDataLength); + + return 1; +} + +int rdpgfx_recv_delete_encoding_context_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_DELETE_ENCODING_CONTEXT_PDU pdu; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT32(s, pdu.codecContextId); /* codecContextId (4 bytes) */ + + fprintf(stderr, "RdpGfxRecvDeleteEncodingContextPdu: surfaceId: %d codecContextId: %d\n", + pdu.surfaceId, pdu.codecContextId); + + return 1; +} + +int rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + UINT16 index; + RDPGFX_RECT16* fillRect; + RDPGFX_SOLID_FILL_PDU pdu; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + + rdpgfx_read_color32(s, &(pdu.fillPixel)); /* fillPixel (4 bytes) */ + + Stream_Read_UINT16(s, pdu.fillRectCount); /* fillRectCount (2 bytes) */ + + pdu.fillRects = (RDPGFX_RECT16*) calloc(pdu.fillRectCount, sizeof(RDPGFX_RECT16)); + + if (!pdu.fillRects) + return -1; + + for (index = 0; index < pdu.fillRectCount; index++) + { + fillRect = &(pdu.fillRects[index]); + rdpgfx_read_rect16(s, fillRect); + } + + fprintf(stderr, "RdpGfxRecvSolidFillPdu: surfaceId: %d fillRectCount: %d\n", + pdu.surfaceId, pdu.fillRectCount); + + return 1; +} + +int rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + UINT16 index; + RDPGFX_POINT16* destPt; + RDPGFX_SURFACE_TO_SURFACE_PDU pdu; + + Stream_Read_UINT16(s, pdu.surfaceIdSrc); /* surfaceIdSrc (2 bytes) */ + Stream_Read_UINT16(s, pdu.surfaceIdDest); /* surfaceIdDest (2 bytes) */ + + rdpgfx_read_rect16(s, &(pdu.rectSrc)); /* rectSrc (8 bytes ) */ + + Stream_Read_UINT16(s, pdu.destPtsCount); /* destPtsCount (2 bytes) */ + + pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16)); + + if (!pdu.destPts) + return -1; + + for (index = 0; index < pdu.destPtsCount; index++) + { + destPt = &(pdu.destPts[index]); + rdpgfx_read_point16(s, destPt); + } + + fprintf(stderr, "RdpGfxRecvSurfaceToSurfacePdu: surfaceIdSrc: %d surfaceIdDest: %d " + "left: %d top: %d right: %d bottom: %d destPtsCount: %d\n", + pdu.surfaceIdSrc, pdu.surfaceIdDest, + pdu.rectSrc.left, pdu.rectSrc.top, pdu.rectSrc.right, pdu.rectSrc.bottom, + pdu.destPtsCount); + + return 1; +} + +int rdpgfx_recv_surface_to_cache_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_SURFACE_TO_CACHE_PDU pdu; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT64(s, pdu.cacheKey); /* cacheKey (8 bytes) */ + Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ + rdpgfx_read_rect16(s, &(pdu.rectSrc)); /* rectSrc (8 bytes ) */ + + fprintf(stderr, "RdpGfxRecvSurfaceToCachePdu: surfaceId: %d cacheKey: 0x%08X cacheSlot: %d " + "left: %d top: %d right: %d bottom: %d\n", + pdu.surfaceId, pdu.cacheKey, pdu.cacheSlot, + pdu.rectSrc.left, pdu.rectSrc.top, + pdu.rectSrc.right, pdu.rectSrc.bottom); + + return 1; +} + +int rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + UINT16 index; + RDPGFX_POINT16* destPt; + RDPGFX_CACHE_TO_SURFACE_PDU pdu; + + Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT16(s, pdu.destPtsCount); /* destPtsCount (2 bytes) */ + + pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16)); + + if (!pdu.destPts) + return -1; + + for (index = 0; index < pdu.destPtsCount; index++) + { + destPt = &(pdu.destPts[index]); + rdpgfx_read_point16(s, destPt); + } + + fprintf(stderr, "RdpGfxRecvCacheToSurfacePdu: cacheSlot: %d surfaceId: %d destPtsCount: %d\n", + pdu.cacheSlot, pdu.surfaceId, pdu.destPtsCount); + + return 1; +} + +int rdpgfx_recv_map_surface_to_output_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU pdu; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT16(s, pdu.reserved); /* reserved (2 bytes) */ + Stream_Read_UINT32(s, pdu.outputOriginX); /* outputOriginX (4 bytes) */ + Stream_Read_UINT32(s, pdu.outputOriginY); /* outputOriginY (4 bytes) */ + + fprintf(stderr, "RdpGfxRecvMapSurfaceToOutputPdu: surfaceId: %d outputOriginX: %d outputOriginY: %d\n", + pdu.surfaceId, pdu.outputOriginX, pdu.outputOriginY); + + return 1; +} + +int rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_MAP_SURFACE_TO_WINDOW_PDU pdu; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT64(s, pdu.windowId); /* windowId (8 bytes) */ + Stream_Read_UINT32(s, pdu.mappedWidth); /* mappedWidth (4 bytes) */ + Stream_Read_UINT32(s, pdu.mappedHeight); /* mappedHeight (4 bytes) */ + + fprintf(stderr, "RdpGfxRecvMapSurfaceToWindowPdu: surfaceId: %d windowId: 0x%04X mappedWidth: %d mappedHeight: %d\n", + pdu.surfaceId, pdu.windowId, pdu.mappedWidth, pdu.mappedHeight); + return 1; } @@ -272,13 +649,9 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) int status; RDPGFX_HEADER header; - /* RDPGFX_HEADER */ + rdpgfx_read_header(s, &header); - Stream_Read_UINT16(s, header.cmdId); /* cmdId (2 bytes) */ - Stream_Read_UINT16(s, header.flags); /* flags (2 bytes) */ - Stream_Read_UINT32(s, header.pduLength); /* pduLength (4 bytes) */ - -#if 0 +#if 1 printf("cmdId: %s (0x%04X) flags: 0x%04X pduLength: %d\n", rdpgfx_get_cmdid_string(header.cmdId), header.cmdId, header.flags, header.pduLength); #endif @@ -286,33 +659,43 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) switch (header.cmdId) { case RDPGFX_CMDID_WIRETOSURFACE_1: + status = rdpgfx_recv_wire_to_surface_1_pdu(callback, s); break; case RDPGFX_CMDID_WIRETOSURFACE_2: + status = rdpgfx_recv_wire_to_surface_2_pdu(callback, s); break; case RDPGFX_CMDID_DELETEENCODINGCONTEXT: + status = rdpgfx_recv_delete_encoding_context_pdu(callback, s); break; case RDPGFX_CMDID_SOLIDFILL: + status = rdpgfx_recv_solid_fill_pdu(callback, s); break; case RDPGFX_CMDID_SURFACETOSURFACE: + status = rdpgfx_recv_surface_to_surface_pdu(callback, s); break; case RDPGFX_CMDID_SURFACETOCACHE: + status = rdpgfx_recv_surface_to_cache_pdu(callback, s); break; case RDPGFX_CMDID_CACHETOSURFACE: + status = rdpgfx_recv_cache_to_surface_pdu(callback, s); break; case RDPGFX_CMDID_EVICTCACHEENTRY: + status = rdpgfx_recv_evict_cache_entry_pdu(callback, s); break; case RDPGFX_CMDID_CREATESURFACE: + status = rdpgfx_recv_create_surface_pdu(callback, s); break; case RDPGFX_CMDID_DELETESURFACE: + status = rdpgfx_recv_delete_surface_pdu(callback, s); break; case RDPGFX_CMDID_STARTFRAME: @@ -328,12 +711,11 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) break; case RDPGFX_CMDID_MAPSURFACETOOUTPUT: - break; - - case RDPGFX_CMDID_CACHEIMPORTOFFER: + status = rdpgfx_recv_map_surface_to_output_pdu(callback, s); break; case RDPGFX_CMDID_CACHEIMPORTREPLY: + status = rdpgfx_recv_cache_import_reply_pdu(callback, s); break; case RDPGFX_CMDID_CAPSCONFIRM: @@ -341,6 +723,7 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) break; case RDPGFX_CMDID_MAPSURFACETOWINDOW: + status = rdpgfx_recv_map_surface_to_window_pdu(callback, s); break; default: diff --git a/include/freerdp/channels/rdpgfx.h b/include/freerdp/channels/rdpgfx.h index 05d18ed37..25c650712 100644 --- a/include/freerdp/channels/rdpgfx.h +++ b/include/freerdp/channels/rdpgfx.h @@ -83,6 +83,8 @@ typedef BYTE RDPGFX_PIXELFORMAT; #define RDPGFX_CMDID_UNUSED_0014 0x0014 #define RDPGFX_CMDID_MAPSURFACETOWINDOW 0x0015 +#define RDPGFX_HEADER_SIZE 8 + struct _RDPGFX_HEADER { UINT16 cmdId; @@ -98,11 +100,12 @@ typedef struct _RDPGFX_HEADER RDPGFX_HEADER; #define RDPGFX_CAPVERSION_8 0x00080004 #define RDPGFX_CAPVERSION_81 0x00080105 +#define RDPGFX_CAPSET_SIZE 12 + struct _RDPGFX_CAPSET { UINT32 version; - UINT32 capsDataLength; - UINT32 capsData; + UINT32 flags; }; typedef struct _RDPGFX_CAPSET RDPGFX_CAPSET; @@ -169,14 +172,14 @@ struct _RDPGFX_DELETE_ENCODING_CONTEXT_PDU }; typedef struct _RDPGFX_DELETE_ENCODING_CONTEXT_PDU RDPGFX_DELETE_ENCODING_CONTEXT_PDU; -struct _RDPGFX_SOLIDFILL_PDU +struct _RDPGFX_SOLID_FILL_PDU { UINT16 surfaceId; RDPGFX_COLOR32 fillPixel; UINT16 fillRectCount; RDPGFX_RECT16* fillRects; }; -typedef struct _RDPGFX_SOLIDFILL_PDU RDPGFX_SOLIDFILL_PDU; +typedef struct _RDPGFX_SOLID_FILL_PDU RDPGFX_SOLID_FILL_PDU; struct _RDPGFX_SURFACE_TO_SURFACE_PDU { @@ -293,7 +296,7 @@ typedef struct _RDPGFX_CACHE_IMPORT_REPLY_PDU RDPGFX_CACHE_IMPORT_REPLY_PDU; struct _RDPGFX_CAPS_ADVERTISE_PDU { UINT16 capsSetCount; - RDPGFX_CAPSET** capsSets; + RDPGFX_CAPSET* capsSets; }; typedef struct _RDPGFX_CAPS_ADVERTISE_PDU RDPGFX_CAPS_ADVERTISE_PDU; From d6e955e6f1eb68fd2cc08227d3da974d1a67c930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 3 Jun 2014 20:51:28 -0400 Subject: [PATCH 11/50] channels/rdpgfx: stub bitmap decompression --- channels/rdpgfx/client/CMakeLists.txt | 2 + channels/rdpgfx/client/rdpgfx_codec.c | 111 ++++++++++ channels/rdpgfx/client/rdpgfx_codec.h | 32 +++ channels/rdpgfx/client/rdpgfx_common.c | 118 ++++++++--- channels/rdpgfx/client/rdpgfx_common.h | 19 +- channels/rdpgfx/client/rdpgfx_main.c | 191 ++++-------------- channels/rdpgfx/client/rdpgfx_main.h | 43 +++- include/freerdp/channels/rdpgfx.h | 14 ++ include/freerdp/codec/clear.h | 49 +++++ libfreerdp/codec/CMakeLists.txt | 1 + libfreerdp/codec/clear.c | 68 +++++++ libfreerdp/codec/test/CMakeLists.txt | 1 + libfreerdp/codec/test/TestFreeRDPCodecClear.c | 10 + 13 files changed, 464 insertions(+), 195 deletions(-) create mode 100644 channels/rdpgfx/client/rdpgfx_codec.c create mode 100644 channels/rdpgfx/client/rdpgfx_codec.h create mode 100644 include/freerdp/codec/clear.h create mode 100644 libfreerdp/codec/clear.c create mode 100644 libfreerdp/codec/test/TestFreeRDPCodecClear.c diff --git a/channels/rdpgfx/client/CMakeLists.txt b/channels/rdpgfx/client/CMakeLists.txt index f940d1707..dc47804ce 100644 --- a/channels/rdpgfx/client/CMakeLists.txt +++ b/channels/rdpgfx/client/CMakeLists.txt @@ -20,6 +20,8 @@ define_channel_client("rdpgfx") set(${MODULE_PREFIX}_SRCS rdpgfx_main.c rdpgfx_main.h + rdpgfx_codec.c + rdpgfx_codec.h rdpgfx_common.c rdpgfx_common.h) diff --git a/channels/rdpgfx/client/rdpgfx_codec.c b/channels/rdpgfx/client/rdpgfx_codec.c new file mode 100644 index 000000000..a749478a8 --- /dev/null +++ b/channels/rdpgfx/client/rdpgfx_codec.c @@ -0,0 +1,111 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Graphics Pipeline Extension + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "rdpgfx_codec.h" + +int rdpgfx_decode_uncompressed(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_remotefx(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + fprintf(stderr, "RdpGfxDecodeRemoteFx\n"); + + return 1; +} + +int rdpgfx_decode_clear(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_planar(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_h264(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_alpha(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_progressive(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_progressive_v2(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + int status; + + switch (cmd->codecId) + { + case RDPGFX_CODECID_UNCOMPRESSED: + status = rdpgfx_decode_uncompressed(gfx, cmd); + break; + + case RDPGFX_CODECID_CAVIDEO: + status = rdpgfx_decode_remotefx(gfx, cmd); + break; + + case RDPGFX_CODECID_CLEARCODEC: + status = rdpgfx_decode_clear(gfx, cmd); + break; + + case RDPGFX_CODECID_PLANAR: + status = rdpgfx_decode_planar(gfx, cmd); + break; + + case RDPGFX_CODECID_H264: + status = rdpgfx_decode_h264(gfx, cmd); + break; + + case RDPGFX_CODECID_ALPHA: + status = rdpgfx_decode_alpha(gfx, cmd); + break; + + case RDPGFX_CODECID_CAPROGRESSIVE: + status = rdpgfx_decode_progressive(gfx, cmd); + break; + + case RDPGFX_CODECID_CAPROGRESSIVE_V2: + status = rdpgfx_decode_progressive_v2(gfx, cmd); + break; + } + + return 1; +} diff --git a/channels/rdpgfx/client/rdpgfx_codec.h b/channels/rdpgfx/client/rdpgfx_codec.h new file mode 100644 index 000000000..51ff0d63f --- /dev/null +++ b/channels/rdpgfx/client/rdpgfx_codec.h @@ -0,0 +1,32 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Graphics Pipeline Extension + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_RDPGFX_CLIENT_CODEC_H +#define FREERDP_CHANNEL_RDPGFX_CLIENT_CODEC_H + +#include +#include + +#include + +#include "rdpgfx_main.h" + +int rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd); + +#endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_CODEC_H */ diff --git a/channels/rdpgfx/client/rdpgfx_common.c b/channels/rdpgfx/client/rdpgfx_common.c index c2ea76d7d..f37864e32 100644 --- a/channels/rdpgfx/client/rdpgfx_common.c +++ b/channels/rdpgfx/client/rdpgfx_common.c @@ -26,12 +26,89 @@ #include "rdpgfx_common.h" -int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* point16) +const char* RDPGFX_CMDID_STRINGS[] = { - Stream_Read_UINT16(s, point16->x); /* x (2 bytes) */ - Stream_Read_UINT16(s, point16->y); /* y (2 bytes) */ + "RDPGFX_CMDID_UNUSED_0000", + "RDPGFX_CMDID_WIRETOSURFACE_1", + "RDPGFX_CMDID_WIRETOSURFACE_2", + "RDPGFX_CMDID_DELETEENCODINGCONTEXT", + "RDPGFX_CMDID_SOLIDFILL", + "RDPGFX_CMDID_SURFACETOSURFACE", + "RDPGFX_CMDID_SURFACETOCACHE", + "RDPGFX_CMDID_CACHETOSURFACE", + "RDPGFX_CMDID_EVICTCACHEENTRY", + "RDPGFX_CMDID_CREATESURFACE", + "RDPGFX_CMDID_DELETESURFACE", + "RDPGFX_CMDID_STARTFRAME", + "RDPGFX_CMDID_ENDFRAME", + "RDPGFX_CMDID_FRAMEACKNOWLEDGE", + "RDPGFX_CMDID_RESETGRAPHICS", + "RDPGFX_CMDID_MAPSURFACETOOUTPUT", + "RDPGFX_CMDID_CACHEIMPORTOFFER", + "RDPGFX_CMDID_CACHEIMPORTREPLY", + "RDPGFX_CMDID_CAPSADVERTISE", + "RDPGFX_CMDID_CAPSCONFIRM", + "RDPGFX_CMDID_UNUSED_0014", + "RDPGFX_CMDID_MAPSURFACETOWINDOW" +}; - return 0; +const char* rdpgfx_get_cmd_id_string(UINT16 cmdId) +{ + if (cmdId <= RDPGFX_CMDID_MAPSURFACETOWINDOW) + return RDPGFX_CMDID_STRINGS[cmdId]; + else + return "RDPGFX_CMDID_UNKNOWN"; +} + +const char* rdpgfx_get_codec_id_string(UINT16 codecId) +{ + switch (codecId) + { + case RDPGFX_CODECID_UNCOMPRESSED: + return "RDPGFX_CODECID_UNCOMPRESSED"; + case RDPGFX_CODECID_CAVIDEO: + return "RDPGFX_CODECID_CAVIDEO"; + case RDPGFX_CODECID_CLEARCODEC: + return "RDPGFX_CODECID_CLEARCODEC"; + case RDPGFX_CODECID_PLANAR: + return "RDPGFX_CODECID_PLANAR"; + case RDPGFX_CODECID_H264: + return "RDPGFX_CODECID_H264"; + case RDPGFX_CODECID_ALPHA: + return "RDPGFX_CODECID_ALPHA"; + case RDPGFX_CODECID_CAPROGRESSIVE: + return "RDPGFX_CODECID_CAPROGRESSIVE"; + case RDPGFX_CODECID_CAPROGRESSIVE_V2: + return "RDPGFX_CODECID_CAPROGRESSIVE_V2"; + } + + return "RDPGFX_CODECID_UNKNOWN"; +} + +int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header) +{ + Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ + Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */ + Stream_Read_UINT32(s, header->pduLength); /* pduLength (4 bytes) */ + + return 1; +} + +int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header) +{ + Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ + Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */ + Stream_Write_UINT32(s, header->pduLength); /* pduLength (4 bytes) */ + + return 1; +} + +int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16) +{ + Stream_Read_UINT16(s, pt16->x); /* x (2 bytes) */ + Stream_Read_UINT16(s, pt16->y); /* y (2 bytes) */ + + return 1; } int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16) @@ -39,7 +116,7 @@ int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16) Stream_Write_UINT16(s, point16->x); /* x (2 bytes) */ Stream_Write_UINT16(s, point16->y); /* y (2 bytes) */ - return 0; + return 1; } int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16) @@ -49,7 +126,7 @@ int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16) Stream_Read_UINT16(s, rect16->right); /* right (2 bytes) */ Stream_Read_UINT16(s, rect16->bottom); /* bottom (2 bytes) */ - return 0; + return 1; } int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16) @@ -59,7 +136,12 @@ int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16) Stream_Write_UINT16(s, rect16->right); /* right (2 bytes) */ Stream_Write_UINT16(s, rect16->bottom); /* bottom (2 bytes) */ - return 0; + return 1; +} + +void rdpgfx_copy_rect16(RDPGFX_RECT16* dst, RDPGFX_RECT16* src) +{ + CopyMemory(dst, src, sizeof(RDPGFX_RECT16)); } int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32) @@ -69,7 +151,7 @@ int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32) Stream_Read_UINT8(s, color32->R); /* R (1 byte) */ Stream_Read_UINT8(s, color32->XA); /* XA (1 byte) */ - return 0; + return 1; } int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32) @@ -79,23 +161,5 @@ int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32) Stream_Write_UINT8(s, color32->R); /* R (1 byte) */ Stream_Write_UINT8(s, color32->XA); /* XA (1 byte) */ - return 0; -} - -int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header) -{ - Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ - Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */ - Stream_Read_UINT16(s, header->pduLength); /* pduLength (4 bytes) */ - - return 0; -} - -int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header) -{ - Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ - Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */ - Stream_Write_UINT16(s, header->pduLength); /* pduLength (4 bytes) */ - - return 0; + return 1; } diff --git a/channels/rdpgfx/client/rdpgfx_common.h b/channels/rdpgfx/client/rdpgfx_common.h index df80c2af6..fcb39d9bc 100644 --- a/channels/rdpgfx/client/rdpgfx_common.h +++ b/channels/rdpgfx/client/rdpgfx_common.h @@ -25,14 +25,21 @@ #include -int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* point16); -int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16); -int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16); -int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16); -int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32); -int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32); +const char* rdpgfx_get_cmd_id_string(UINT16 cmdId); +const char* rdpgfx_get_codec_id_string(UINT16 codecId); + int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header); int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header); +int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16); +int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16); + +int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16); +int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16); +void rdpgfx_copy_rect16(RDPGFX_RECT16* dst, RDPGFX_RECT16* src); + +int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32); +int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32); + #endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_COMMON_H */ diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index a6ba91486..7ac460577 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -2,7 +2,7 @@ * FreeRDP: A Remote Desktop Protocol Implementation * Graphics Pipeline Extension * - * Copyright 2013 Marc-Andre Moreau + * Copyright 2013-2014 Marc-Andre Moreau * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,157 +37,12 @@ #include #include -#include #include "rdpgfx_common.h" +#include "rdpgfx_codec.h" #include "rdpgfx_main.h" -struct _RDPGFX_CHANNEL_CALLBACK -{ - IWTSVirtualChannelCallback iface; - - IWTSPlugin* plugin; - IWTSVirtualChannelManager* channel_mgr; - IWTSVirtualChannel* channel; -}; -typedef struct _RDPGFX_CHANNEL_CALLBACK RDPGFX_CHANNEL_CALLBACK; - -struct _RDPGFX_LISTENER_CALLBACK -{ - IWTSListenerCallback iface; - - IWTSPlugin* plugin; - IWTSVirtualChannelManager* channel_mgr; - RDPGFX_CHANNEL_CALLBACK* channel_callback; -}; -typedef struct _RDPGFX_LISTENER_CALLBACK RDPGFX_LISTENER_CALLBACK; - -struct _RDPGFX_PLUGIN -{ - IWTSPlugin iface; - - IWTSListener* listener; - RDPGFX_LISTENER_CALLBACK* listener_callback; - - BOOL ThinClient; - BOOL SmallCache; - BOOL H264; - - ZGFX_CONTEXT* zgfx; - UINT32 UnacknowledgedFrames; - UINT32 TotalDecodedFrames; -}; -typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; - -const char* RDPGFX_CMDID_STRINGS[] = -{ - "RDPGFX_CMDID_UNUSED_0000", - "RDPGFX_CMDID_WIRETOSURFACE_1", - "RDPGFX_CMDID_WIRETOSURFACE_2", - "RDPGFX_CMDID_DELETEENCODINGCONTEXT", - "RDPGFX_CMDID_SOLIDFILL", - "RDPGFX_CMDID_SURFACETOSURFACE", - "RDPGFX_CMDID_SURFACETOCACHE", - "RDPGFX_CMDID_CACHETOSURFACE", - "RDPGFX_CMDID_EVICTCACHEENTRY", - "RDPGFX_CMDID_CREATESURFACE", - "RDPGFX_CMDID_DELETESURFACE", - "RDPGFX_CMDID_STARTFRAME", - "RDPGFX_CMDID_ENDFRAME", - "RDPGFX_CMDID_FRAMEACKNOWLEDGE", - "RDPGFX_CMDID_RESETGRAPHICS", - "RDPGFX_CMDID_MAPSURFACETOOUTPUT", - "RDPGFX_CMDID_CACHEIMPORTOFFER", - "RDPGFX_CMDID_CACHEIMPORTREPLY", - "RDPGFX_CMDID_CAPSADVERTISE", - "RDPGFX_CMDID_CAPSCONFIRM", - "RDPGFX_CMDID_UNUSED_0014", - "RDPGFX_CMDID_MAPSURFACETOWINDOW" -}; - -const char* rdpgfx_get_cmdid_string(UINT16 cmdId) -{ - if (cmdId <= RDPGFX_CMDID_MAPSURFACETOWINDOW) - return RDPGFX_CMDID_STRINGS[cmdId]; - else - return "RDPGFX_CMDID_UNKNOWN"; -} - -int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header) -{ - Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ - Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */ - Stream_Read_UINT32(s, header->pduLength); /* pduLength (4 bytes) */ - - return 1; -} - -int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header) -{ - Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ - Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */ - Stream_Write_UINT32(s, header->pduLength); /* pduLength (4 bytes) */ - - return 1; -} - -int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16) -{ - Stream_Read_UINT16(s, pt16->x); /* x (2 bytes) */ - Stream_Read_UINT16(s, pt16->y); /* y (2 bytes) */ - - return 1; -} - -int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16) -{ - Stream_Write_UINT16(s, point16->x); /* x (2 bytes) */ - Stream_Write_UINT16(s, point16->y); /* y (2 bytes) */ - - return 1; -} - -int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16) -{ - Stream_Read_UINT16(s, rect16->left); /* left (2 bytes) */ - Stream_Read_UINT16(s, rect16->top); /* top (2 bytes) */ - Stream_Read_UINT16(s, rect16->right); /* right (2 bytes) */ - Stream_Read_UINT16(s, rect16->bottom); /* bottom (2 bytes) */ - - return 1; -} - -int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16) -{ - Stream_Write_UINT16(s, rect16->left); /* left (2 bytes) */ - Stream_Write_UINT16(s, rect16->top); /* top (2 bytes) */ - Stream_Write_UINT16(s, rect16->right); /* right (2 bytes) */ - Stream_Write_UINT16(s, rect16->bottom); /* bottom (2 bytes) */ - - return 1; -} - -int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32) -{ - Stream_Read_UINT8(s, color32->B); /* B (1 byte) */ - Stream_Read_UINT8(s, color32->G); /* G (1 byte) */ - Stream_Read_UINT8(s, color32->R); /* R (1 byte) */ - Stream_Read_UINT8(s, color32->XA); /* XA (1 byte) */ - - return 1; -} - -int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32) -{ - Stream_Write_UINT8(s, color32->B); /* B (1 byte) */ - Stream_Write_UINT8(s, color32->G); /* G (1 byte) */ - Stream_Write_UINT8(s, color32->R); /* R (1 byte) */ - Stream_Write_UINT8(s, color32->XA); /* XA (1 byte) */ - - return 1; -} - int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) { int status; @@ -201,9 +56,9 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) gfx = (RDPGFX_PLUGIN*) callback->plugin; - gfx->ThinClient = FALSE; - gfx->SmallCache = TRUE; - gfx->H264 = TRUE; + gfx->ThinClient = TRUE; + gfx->SmallCache = FALSE; + gfx->H264 = FALSE; header.flags = 0; header.cmdId = RDPGFX_CMDID_CAPSADVERTISE; @@ -451,38 +306,50 @@ int rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { + RDPGFX_SURFACE_COMMAND cmd; RDPGFX_WIRE_TO_SURFACE_PDU_1 pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.codecId); /* codecId (2 bytes) */ Stream_Read_UINT8(s, pdu.pixelFormat); /* pixelFormat (1 byte) */ - Stream_Read_UINT16(s, pdu.destRect.left); /* left (2 bytes) */ - Stream_Read_UINT16(s, pdu.destRect.top); /* top (2 bytes) */ - Stream_Read_UINT16(s, pdu.destRect.right); /* right (2 bytes) */ - Stream_Read_UINT16(s, pdu.destRect.bottom); /* bottom (2 bytes) */ + rdpgfx_read_rect16(s, &(pdu.destRect)); /* destRect (8 bytes) */ Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ pdu.bitmapData = Stream_Pointer(s); - fprintf(stderr, "RdpGfxRecvWireToSurface1Pdu: surfaceId: %d codecId: 0x%04X pixelFormat: 0x%04X " + fprintf(stderr, "RdpGfxRecvWireToSurface1Pdu: surfaceId: %d codecId: %s (0x%04X) pixelFormat: 0x%04X " "destRect: left: %d top: %d right: %d bottom: %d bitmapDataLength: %d\n", - pdu.surfaceId, pdu.codecId, pdu.pixelFormat, + pdu.surfaceId, rdpgfx_get_codec_id_string(pdu.codecId), pdu.codecId, pdu.pixelFormat, pdu.destRect.left, pdu.destRect.top, pdu.destRect.right, pdu.destRect.bottom, pdu.bitmapDataLength); + cmd.surfaceId = pdu.surfaceId; + cmd.codecId = pdu.codecId; + cmd.codecContextId = 0; + cmd.pixelFormat = pdu.pixelFormat; + rdpgfx_copy_rect16(&(cmd.destRect), &(pdu.destRect)); + cmd.bitmapDataLength = pdu.bitmapDataLength; + cmd.bitmapData = pdu.bitmapData; + + rdpgfx_decode(gfx, &cmd); + return 1; } int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { + RDPGFX_SURFACE_COMMAND cmd; RDPGFX_WIRE_TO_SURFACE_PDU_2 pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.codecId); /* codecId (2 bytes) */ Stream_Read_UINT32(s, pdu.codecContextId); /* codecContextId (4 bytes) */ Stream_Read_UINT8(s, pdu.pixelFormat); /* pixelFormat (1 byte) */ + Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ pdu.bitmapData = Stream_Pointer(s); @@ -491,6 +358,16 @@ int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream "codecContextId: %d pixelFormat: 0x%04X bitmapDataLength: %d\n", pdu.surfaceId, pdu.codecId, pdu.codecContextId, pdu.pixelFormat, pdu.bitmapDataLength); + cmd.surfaceId = pdu.surfaceId; + cmd.codecId = pdu.codecId; + cmd.codecContextId = pdu.codecContextId; + cmd.pixelFormat = pdu.pixelFormat; + ZeroMemory(&(cmd.destRect), sizeof(RDPGFX_RECT16)); + cmd.bitmapDataLength = pdu.bitmapDataLength; + cmd.bitmapData = pdu.bitmapData; + + rdpgfx_decode(gfx, &cmd); + return 1; } @@ -653,7 +530,7 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) #if 1 printf("cmdId: %s (0x%04X) flags: 0x%04X pduLength: %d\n", - rdpgfx_get_cmdid_string(header.cmdId), header.cmdId, header.flags, header.pduLength); + rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags, header.pduLength); #endif switch (header.cmdId) diff --git a/channels/rdpgfx/client/rdpgfx_main.h b/channels/rdpgfx/client/rdpgfx_main.h index 74cfcbef3..1055a3371 100644 --- a/channels/rdpgfx/client/rdpgfx_main.h +++ b/channels/rdpgfx/client/rdpgfx_main.h @@ -2,7 +2,7 @@ * FreeRDP: A Remote Desktop Protocol Implementation * Graphics Pipeline Extension * - * Copyright 2013 Marc-Andre Moreau + * Copyright 2013-2014 Marc-Andre Moreau * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,17 +20,50 @@ #ifndef FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H #define FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include #include #include #include +#include +struct _RDPGFX_CHANNEL_CALLBACK +{ + IWTSVirtualChannelCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; + IWTSVirtualChannel* channel; +}; +typedef struct _RDPGFX_CHANNEL_CALLBACK RDPGFX_CHANNEL_CALLBACK; + +struct _RDPGFX_LISTENER_CALLBACK +{ + IWTSListenerCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; + RDPGFX_CHANNEL_CALLBACK* channel_callback; +}; +typedef struct _RDPGFX_LISTENER_CALLBACK RDPGFX_LISTENER_CALLBACK; + +struct _RDPGFX_PLUGIN +{ + IWTSPlugin iface; + + IWTSListener* listener; + RDPGFX_LISTENER_CALLBACK* listener_callback; + + BOOL ThinClient; + BOOL SmallCache; + BOOL H264; + + ZGFX_CONTEXT* zgfx; + UINT32 UnacknowledgedFrames; + UINT32 TotalDecodedFrames; +}; +typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; #endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H */ diff --git a/include/freerdp/channels/rdpgfx.h b/include/freerdp/channels/rdpgfx.h index 25c650712..63c374153 100644 --- a/include/freerdp/channels/rdpgfx.h +++ b/include/freerdp/channels/rdpgfx.h @@ -165,6 +165,20 @@ struct _RDPGFX_WIRE_TO_SURFACE_PDU_2 }; typedef struct _RDPGFX_WIRE_TO_SURFACE_PDU_2 RDPGFX_WIRE_TO_SURFACE_PDU_2; +/* RDPGFX_SURFACE_COMMAND encapsulates both RDPGFX_WIRE_TO_SURFACE_PDU 1/2 */ + +struct _RDPGFX_SURFACE_COMMAND +{ + UINT16 surfaceId; + UINT16 codecId; + UINT32 codecContextId; + RDPGFX_PIXELFORMAT pixelFormat; + RDPGFX_RECT16 destRect; + UINT32 bitmapDataLength; + BYTE* bitmapData; +}; +typedef struct _RDPGFX_SURFACE_COMMAND RDPGFX_SURFACE_COMMAND; + struct _RDPGFX_DELETE_ENCODING_CONTEXT_PDU { UINT16 surfaceId; diff --git a/include/freerdp/codec/clear.h b/include/freerdp/codec/clear.h new file mode 100644 index 000000000..dc5e81a83 --- /dev/null +++ b/include/freerdp/codec/clear.h @@ -0,0 +1,49 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * ClearCodec Bitmap Compression + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CODEC_CLEAR_H +#define FREERDP_CODEC_CLEAR_H + +#include +#include + +struct _CLEAR_CONTEXT +{ + BOOL Compressor; +}; +typedef struct _CLEAR_CONTEXT CLEAR_CONTEXT; + +#ifdef __cplusplus +extern "C" { +#endif + +FREERDP_API int clear_compress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize); +FREERDP_API int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize); + +FREERDP_API void clear_context_reset(CLEAR_CONTEXT* clear); + +FREERDP_API CLEAR_CONTEXT* clear_context_new(BOOL Compressor); +FREERDP_API void clear_context_free(CLEAR_CONTEXT* clear); + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_CODEC_CLEAR_H */ + diff --git a/libfreerdp/codec/CMakeLists.txt b/libfreerdp/codec/CMakeLists.txt index abe48739b..ad0180e25 100644 --- a/libfreerdp/codec/CMakeLists.txt +++ b/libfreerdp/codec/CMakeLists.txt @@ -51,6 +51,7 @@ set(${MODULE_PREFIX}_SRCS xcrush.c mppc.c zgfx.c + clear.c jpeg.c) set(${MODULE_PREFIX}_SSE2_SRCS diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c new file mode 100644 index 000000000..564e5d364 --- /dev/null +++ b/libfreerdp/codec/clear.c @@ -0,0 +1,68 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * ClearCodec Bitmap Compression + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include + +int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize) +{ + return 1; +} + +int clear_compress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize) +{ + return 1; +} + +void clear_context_reset(CLEAR_CONTEXT* clear) +{ + +} + +CLEAR_CONTEXT* clear_context_new(BOOL Compressor) +{ + CLEAR_CONTEXT* clear; + + clear = (CLEAR_CONTEXT*) calloc(1, sizeof(CLEAR_CONTEXT)); + + if (clear) + { + clear->Compressor = Compressor; + + clear_context_reset(clear); + } + + return clear; +} + +void clear_context_free(CLEAR_CONTEXT* clear) +{ + if (clear) + { + free(clear); + } +} + diff --git a/libfreerdp/codec/test/CMakeLists.txt b/libfreerdp/codec/test/CMakeLists.txt index fa268c270..ba158560c 100644 --- a/libfreerdp/codec/test/CMakeLists.txt +++ b/libfreerdp/codec/test/CMakeLists.txt @@ -11,6 +11,7 @@ set(${MODULE_PREFIX}_TESTS TestFreeRDPCodecXCrush.c TestFreeRDPCodecZGfx.c TestFreeRDPCodecPlanar.c + TestFreeRDPCodecClear.c TestFreeRDPCodecRemoteFX.c) create_test_sourcelist(${MODULE_PREFIX}_SRCS diff --git a/libfreerdp/codec/test/TestFreeRDPCodecClear.c b/libfreerdp/codec/test/TestFreeRDPCodecClear.c new file mode 100644 index 000000000..6db7e6e12 --- /dev/null +++ b/libfreerdp/codec/test/TestFreeRDPCodecClear.c @@ -0,0 +1,10 @@ +#include +#include + +#include + +int TestFreeRDPCodecClear(int argc, char* argv[]) +{ + return 0; +} + From 193e7f6bd22fde8d5d2b3ff5118d5830af494960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 4 Jun 2014 15:18:02 -0400 Subject: [PATCH 12/50] channels/rdpgfx: define interface of callbacks --- channels/rdpgfx/client/rdpgfx_main.c | 121 +++++++++++++++++++++++++-- include/freerdp/client/rdpgfx.h | 34 +++++++- 2 files changed, 146 insertions(+), 9 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 7ac460577..54222d710 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -175,6 +175,8 @@ int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s UINT32 index; MONITOR_DEF* monitor; RDPGFX_RESET_GRAPHICS_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT32(s, pdu.width); /* width (4 bytes) */ Stream_Read_UINT32(s, pdu.height); /* height (4 bytes) */ @@ -200,17 +202,29 @@ int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s fprintf(stderr, "RdpGfxRecvResetGraphicsPdu: width: %d height: %d count: %d\n", pdu.width, pdu.height, pdu.monitorCount); + if (context && context->ResetGraphics) + { + context->ResetGraphics(context, &pdu); + } + return 1; } int rdpgfx_recv_evict_cache_entry_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_EVICT_CACHE_ENTRY_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ fprintf(stderr, "RdpGfxRecvEvictCacheEntryPdu: cacheSlot: %d\n", pdu.cacheSlot); + if (context && context->EvictCacheEntry) + { + context->EvictCacheEntry(context, &pdu); + } + return 1; } @@ -218,6 +232,8 @@ int rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea { UINT16 index; RDPGFX_CACHE_IMPORT_REPLY_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.importedEntriesCount); /* cacheSlot (2 bytes) */ @@ -234,12 +250,19 @@ int rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea fprintf(stderr, "RdpGfxRecvCacheImportReplyPdu: importedEntriesCount: %d\n", pdu.importedEntriesCount); + if (context && context->CacheImportReply) + { + context->CacheImportReply(context, &pdu); + } + return 1; } int rdpgfx_recv_create_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_CREATE_SURFACE_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.width); /* width (2 bytes) */ @@ -249,17 +272,29 @@ int rdpgfx_recv_create_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s fprintf(stderr, "RdpGfxRecvCreateSurfacePdu: surfaceId: %d width: %d height: %d pixelFormat: %d\n", pdu.surfaceId, pdu.width, pdu.height, pdu.pixelFormat); + if (context && context->CreateSurface) + { + context->CreateSurface(context, &pdu); + } + return 1; } int rdpgfx_recv_delete_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_DELETE_SURFACE_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ fprintf(stderr, "RdpGfxRecvDeleteSurfacePdu: surfaceId: %d\n", pdu.surfaceId); + if (context && context->DeleteSurface) + { + context->DeleteSurface(context, &pdu); + } + return 1; } @@ -267,6 +302,7 @@ int rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_START_FRAME_PDU pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT32(s, pdu.timestamp); /* timestamp (4 bytes) */ Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ @@ -274,6 +310,11 @@ int rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) fprintf(stderr, "RdpGfxRecvStartFramePdu: frameId: %d timestamp: 0x%04X\n", pdu.frameId, pdu.timestamp); + if (context && context->StartFrame) + { + context->StartFrame(context, &pdu); + } + gfx->UnacknowledgedFrames++; return 1; @@ -284,11 +325,17 @@ int rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) RDPGFX_END_FRAME_PDU pdu; RDPGFX_FRAME_ACKNOWLEDGE_PDU ack; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ fprintf(stderr, "RdpGfxRecvEndFramePdu: frameId: %d\n", pdu.frameId); + if (context && context->EndFrame) + { + context->EndFrame(context, &pdu); + } + gfx->UnacknowledgedFrames--; gfx->TotalDecodedFrames++; @@ -309,6 +356,7 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream RDPGFX_SURFACE_COMMAND cmd; RDPGFX_WIRE_TO_SURFACE_PDU_1 pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.codecId); /* codecId (2 bytes) */ @@ -322,7 +370,7 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream fprintf(stderr, "RdpGfxRecvWireToSurface1Pdu: surfaceId: %d codecId: %s (0x%04X) pixelFormat: 0x%04X " "destRect: left: %d top: %d right: %d bottom: %d bitmapDataLength: %d\n", - pdu.surfaceId, rdpgfx_get_codec_id_string(pdu.codecId), pdu.codecId, pdu.pixelFormat, + (int) pdu.surfaceId, rdpgfx_get_codec_id_string(pdu.codecId), pdu.codecId, pdu.pixelFormat, pdu.destRect.left, pdu.destRect.top, pdu.destRect.right, pdu.destRect.bottom, pdu.bitmapDataLength); @@ -334,6 +382,11 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream cmd.bitmapDataLength = pdu.bitmapDataLength; cmd.bitmapData = pdu.bitmapData; + if (context && context->SurfaceCommand) + { + context->SurfaceCommand(context, &cmd); + } + rdpgfx_decode(gfx, &cmd); return 1; @@ -344,6 +397,7 @@ int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream RDPGFX_SURFACE_COMMAND cmd; RDPGFX_WIRE_TO_SURFACE_PDU_2 pdu; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.codecId); /* codecId (2 bytes) */ @@ -356,7 +410,7 @@ int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream fprintf(stderr, "RdpGfxRecvWireToSurface2Pdu: surfaceId: %d codecId: 0x%04X " "codecContextId: %d pixelFormat: 0x%04X bitmapDataLength: %d\n", - pdu.surfaceId, pdu.codecId, pdu.codecContextId, pdu.pixelFormat, pdu.bitmapDataLength); + (int) pdu.surfaceId, pdu.codecId, pdu.codecContextId, pdu.pixelFormat, pdu.bitmapDataLength); cmd.surfaceId = pdu.surfaceId; cmd.codecId = pdu.codecId; @@ -366,6 +420,11 @@ int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream cmd.bitmapDataLength = pdu.bitmapDataLength; cmd.bitmapData = pdu.bitmapData; + if (context && context->SurfaceCommand) + { + context->SurfaceCommand(context, &cmd); + } + rdpgfx_decode(gfx, &cmd); return 1; @@ -374,6 +433,8 @@ int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream int rdpgfx_recv_delete_encoding_context_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_DELETE_ENCODING_CONTEXT_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT32(s, pdu.codecContextId); /* codecContextId (4 bytes) */ @@ -381,6 +442,11 @@ int rdpgfx_recv_delete_encoding_context_pdu(RDPGFX_CHANNEL_CALLBACK* callback, w fprintf(stderr, "RdpGfxRecvDeleteEncodingContextPdu: surfaceId: %d codecContextId: %d\n", pdu.surfaceId, pdu.codecContextId); + if (context && context->DeleteEncodingContext) + { + context->DeleteEncodingContext(context, &pdu); + } + return 1; } @@ -389,6 +455,8 @@ int rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) UINT16 index; RDPGFX_RECT16* fillRect; RDPGFX_SOLID_FILL_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ @@ -410,6 +478,11 @@ int rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) fprintf(stderr, "RdpGfxRecvSolidFillPdu: surfaceId: %d fillRectCount: %d\n", pdu.surfaceId, pdu.fillRectCount); + if (context && context->SolidFill) + { + context->SolidFill(context, &pdu); + } + return 1; } @@ -418,6 +491,8 @@ int rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea UINT16 index; RDPGFX_POINT16* destPt; RDPGFX_SURFACE_TO_SURFACE_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.surfaceIdSrc); /* surfaceIdSrc (2 bytes) */ Stream_Read_UINT16(s, pdu.surfaceIdDest); /* surfaceIdDest (2 bytes) */ @@ -443,12 +518,19 @@ int rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea pdu.rectSrc.left, pdu.rectSrc.top, pdu.rectSrc.right, pdu.rectSrc.bottom, pdu.destPtsCount); + if (context && context->SurfaceToSurface) + { + context->SurfaceToSurface(context, &pdu); + } + return 1; } int rdpgfx_recv_surface_to_cache_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_SURFACE_TO_CACHE_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT64(s, pdu.cacheKey); /* cacheKey (8 bytes) */ @@ -457,10 +539,15 @@ int rdpgfx_recv_surface_to_cache_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* fprintf(stderr, "RdpGfxRecvSurfaceToCachePdu: surfaceId: %d cacheKey: 0x%08X cacheSlot: %d " "left: %d top: %d right: %d bottom: %d\n", - pdu.surfaceId, pdu.cacheKey, pdu.cacheSlot, + pdu.surfaceId, (int) pdu.cacheKey, pdu.cacheSlot, pdu.rectSrc.left, pdu.rectSrc.top, pdu.rectSrc.right, pdu.rectSrc.bottom); + if (context && context->SurfaceToCache) + { + context->SurfaceToCache(context, &pdu); + } + return 1; } @@ -469,6 +556,8 @@ int rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* UINT16 index; RDPGFX_POINT16* destPt; RDPGFX_CACHE_TO_SURFACE_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ @@ -486,7 +575,12 @@ int rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* } fprintf(stderr, "RdpGfxRecvCacheToSurfacePdu: cacheSlot: %d surfaceId: %d destPtsCount: %d\n", - pdu.cacheSlot, pdu.surfaceId, pdu.destPtsCount); + pdu.cacheSlot, (int) pdu.surfaceId, pdu.destPtsCount); + + if (context && context->CacheToSurface) + { + context->CacheToSurface(context, &pdu); + } return 1; } @@ -494,6 +588,8 @@ int rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* int rdpgfx_recv_map_surface_to_output_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT16(s, pdu.reserved); /* reserved (2 bytes) */ @@ -501,7 +597,12 @@ int rdpgfx_recv_map_surface_to_output_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wSt Stream_Read_UINT32(s, pdu.outputOriginY); /* outputOriginY (4 bytes) */ fprintf(stderr, "RdpGfxRecvMapSurfaceToOutputPdu: surfaceId: %d outputOriginX: %d outputOriginY: %d\n", - pdu.surfaceId, pdu.outputOriginX, pdu.outputOriginY); + (int) pdu.surfaceId, pdu.outputOriginX, pdu.outputOriginY); + + if (context && context->MapSurfaceToOutput) + { + context->MapSurfaceToOutput(context, &pdu); + } return 1; } @@ -509,6 +610,8 @@ int rdpgfx_recv_map_surface_to_output_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wSt int rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_MAP_SURFACE_TO_WINDOW_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT64(s, pdu.windowId); /* windowId (8 bytes) */ @@ -516,7 +619,12 @@ int rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wSt Stream_Read_UINT32(s, pdu.mappedHeight); /* mappedHeight (4 bytes) */ fprintf(stderr, "RdpGfxRecvMapSurfaceToWindowPdu: surfaceId: %d windowId: 0x%04X mappedWidth: %d mappedHeight: %d\n", - pdu.surfaceId, pdu.windowId, pdu.mappedWidth, pdu.mappedHeight); + pdu.surfaceId, (int) pdu.windowId, pdu.mappedWidth, pdu.mappedHeight); + + if (context && context->MapSurfaceToWindow) + { + context->MapSurfaceToWindow(context, &pdu); + } return 1; } @@ -763,7 +871,6 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) return -1; context->handle = (void*) rdpgfx; - context->GetVersion = rdpgfx_get_version; rdpgfx->iface.pInterface = (void*) context; diff --git a/include/freerdp/client/rdpgfx.h b/include/freerdp/client/rdpgfx.h index b9e7c70e8..b2c0dda70 100644 --- a/include/freerdp/client/rdpgfx.h +++ b/include/freerdp/client/rdpgfx.h @@ -28,14 +28,44 @@ typedef struct _rdpgfx_client_context RdpgfxClientContext; -typedef UINT32 (*pcRdpgfxGetVersion)(RdpgfxClientContext* context); +typedef int (*pcRdpgfxResetGraphics)(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics); +typedef int (*pcRdpgfxStartFrame)(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame); +typedef int (*pcRdpgfxEndFrame)(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame); +typedef int (*pcRdpgfxSurfaceCommand)(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd); +typedef int (*pcRdpgfxDeleteEncodingContext)(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext); +typedef int (*pcRdpgfxCreateSurface)(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface); +typedef int (*pcRdpgfxDeleteSurface)(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface); +typedef int (*pcRdpgfxSolidFill)(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill); +typedef int (*pcRdpgfxSurfaceToSurface)(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface); +typedef int (*pcRdpgfxSurfaceToCache)(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache); +typedef int (*pcRdpgfxCacheToSurface)(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface); +typedef int (*pcRdpgfxCacheImportOffer)(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_OFFER_PDU* cacheImportOffer); +typedef int (*pcRdpgfxCacheImportReply)(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply); +typedef int (*pcRdpgfxEvictCacheEntry)(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry); +typedef int (*pcRdpgfxMapSurfaceToOutput)(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput); +typedef int (*pcRdpgfxMapSurfaceToWindow)(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow); struct _rdpgfx_client_context { void* handle; void* custom; - pcRdpgfxGetVersion GetVersion; + pcRdpgfxResetGraphics ResetGraphics; + pcRdpgfxStartFrame StartFrame; + pcRdpgfxEndFrame EndFrame; + pcRdpgfxSurfaceCommand SurfaceCommand; + pcRdpgfxDeleteEncodingContext DeleteEncodingContext; + pcRdpgfxCreateSurface CreateSurface; + pcRdpgfxDeleteSurface DeleteSurface; + pcRdpgfxSolidFill SolidFill; + pcRdpgfxSurfaceToSurface SurfaceToSurface; + pcRdpgfxSurfaceToCache SurfaceToCache; + pcRdpgfxCacheToSurface CacheToSurface; + pcRdpgfxCacheImportOffer CacheImportOffer; + pcRdpgfxCacheImportReply CacheImportReply; + pcRdpgfxEvictCacheEntry EvictCacheEntry; + pcRdpgfxMapSurfaceToOutput MapSurfaceToOutput; + pcRdpgfxMapSurfaceToWindow MapSurfaceToWindow; }; #endif /* FREERDP_CHANNEL_CLIENT_RDPGFX_H */ From 83edc684223ec6af77086a7b95f06ab3ceeb4030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 4 Jun 2014 18:03:25 -0400 Subject: [PATCH 13/50] xfreerdp: start integrating graphics pipeline --- client/X11/CMakeLists.txt | 2 + client/X11/xf_channels.c | 6 + client/X11/xf_channels.h | 1 + client/X11/xf_client.c | 22 ++- client/X11/xf_gdi.c | 13 +- client/X11/xf_gfx.c | 281 ++++++++++++++++++++++++++++++++++++++ client/X11/xf_gfx.h | 28 ++++ client/X11/xf_graphics.c | 6 +- client/X11/xfreerdp.h | 12 +- 9 files changed, 346 insertions(+), 25 deletions(-) create mode 100644 client/X11/xf_gfx.c create mode 100644 client/X11/xf_gfx.h diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt index 6cbe43a42..6c004e678 100644 --- a/client/X11/CMakeLists.txt +++ b/client/X11/CMakeLists.txt @@ -26,6 +26,8 @@ include_directories(${OPENSSL_INCLUDE_DIR}) set(${MODULE_PREFIX}_SRCS xf_gdi.c xf_gdi.h + xf_gfx.c + xf_gfx.h xf_rail.c xf_rail.h xf_tsmf.c diff --git a/client/X11/xf_channels.c b/client/X11/xf_channels.c index 24325046e..b00130c24 100644 --- a/client/X11/xf_channels.c +++ b/client/X11/xf_channels.c @@ -26,6 +26,8 @@ #include "xf_client.h" #include "xfreerdp.h" +#include "xf_gfx.h" + void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e) { xfContext* xfc = (xfContext*) context; @@ -34,6 +36,10 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven { xfc->rdpei = (RdpeiClientContext*) e->pInterface; } + else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) + { + xf_register_graphics_pipeline(xfc, (RdpgfxClientContext*) e->pInterface); + } } void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e) diff --git a/client/X11/xf_channels.h b/client/X11/xf_channels.h index bb52d5e52..dd5969d62 100644 --- a/client/X11/xf_channels.h +++ b/client/X11/xf_channels.h @@ -23,6 +23,7 @@ #include #include #include +#include int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface); int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface); diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index e8d09031a..7fddd874b 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -902,8 +902,6 @@ BOOL xf_post_connect(freerdp* instance) rdpChannels* channels; rdpSettings* settings; ResizeWindowEventArgs e; - RFX_CONTEXT* rfx_context = NULL; - NSC_CONTEXT* nsc_context = NULL; xfContext* xfc = (xfContext*) instance->context; cache = instance->context->cache; @@ -931,7 +929,7 @@ BOOL xf_post_connect(freerdp* instance) gdi = instance->context->gdi; xfc->primary_buffer = gdi->primary_buffer; - rfx_context = gdi->rfx_context; + xfc->rfx = gdi->rfx_context; } else { @@ -942,14 +940,12 @@ BOOL xf_post_connect(freerdp* instance) if (instance->settings->RemoteFxCodec) { - rfx_context = (void*) rfx_context_new(FALSE); - xfc->rfx_context = rfx_context; + xfc->rfx = rfx_context_new(FALSE); } if (instance->settings->NSCodec) { - nsc_context = (void*) nsc_context_new(); - xfc->nsc_context = nsc_context; + xfc->nsc = nsc_context_new(); } } @@ -1212,16 +1208,16 @@ void xf_window_free(xfContext* xfc) context->rail = NULL; } - if (xfc->rfx_context) + if (xfc->rfx) { - rfx_context_free(xfc->rfx_context); - xfc->rfx_context = NULL; + rfx_context_free(xfc->rfx); + xfc->rfx = NULL; } - if (xfc->nsc_context) + if (xfc->nsc) { - nsc_context_free(xfc->nsc_context); - xfc->nsc_context = NULL; + nsc_context_free(xfc->nsc); + xfc->nsc = NULL; } if (xfc->clrconv) diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index be63db5c2..1ab20af06 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -990,14 +990,12 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits XImage* image; RFX_MESSAGE* message; xfContext* xfc = (xfContext*) context; - RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) xfc->rfx_context; - NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) xfc->nsc_context; xf_lock_x11(xfc, FALSE); if (surface_bits_command->codecID == RDP_CODEC_ID_REMOTEFX) { - message = rfx_process_message(rfx_context, + message = rfx_process_message(xfc->rfx, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); XSetFunction(xfc->display, xfc->gc, GXcopy); @@ -1034,11 +1032,11 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits } XSetClipMask(xfc->display, xfc->gc, None); - rfx_message_free(rfx_context, message); + rfx_message_free(xfc->rfx, message); } else if (surface_bits_command->codecID == RDP_CODEC_ID_NSCODEC) { - nsc_process_message(nsc_context, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height, + nsc_process_message(xfc->nsc, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); XSetFunction(xfc->display, xfc->gc, GXcopy); @@ -1047,7 +1045,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits xfc->bmp_codec_nsc = (BYTE*) realloc(xfc->bmp_codec_nsc, surface_bits_command->width * surface_bits_command->height * 4); - freerdp_image_flip(nsc_context->BitmapData, xfc->bmp_codec_nsc, + freerdp_image_flip(xfc->nsc->BitmapData, xfc->bmp_codec_nsc, surface_bits_command->width, surface_bits_command->height, 32); image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, @@ -1060,13 +1058,14 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits free(xfc->bmp_codec_nsc); xfc->bmp_codec_nsc = NULL; - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, surface_bits_command->destLeft, surface_bits_command->destTop); } + xf_gdi_surface_update_frame(xfc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height); diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c new file mode 100644 index 000000000..2a94b74d2 --- /dev/null +++ b/client/X11/xf_gfx.c @@ -0,0 +1,281 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * X11 Graphics Pipeline + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf_gfx.h" + +int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics) +{ + xfContext* xfc = (xfContext*) context->custom; + + if (xfc->rfx) + { + rfx_context_free(xfc->rfx); + xfc->rfx = NULL; + } + + xfc->rfx = rfx_context_new(FALSE); + + xfc->rfx->width = resetGraphics->width; + xfc->rfx->height = resetGraphics->height; + rfx_context_set_pixel_format(xfc->rfx, RDP_PIXEL_FORMAT_B8G8R8A8); + + if (xfc->nsc) + { + nsc_context_free(xfc->nsc); + xfc->nsc = NULL; + } + + xfc->nsc = nsc_context_new(); + + xfc->nsc->width = resetGraphics->width; + xfc->nsc->height = resetGraphics->height; + nsc_context_set_pixel_format(xfc->nsc, RDP_PIXEL_FORMAT_B8G8R8A8); + + return 1; +} + +int xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame) +{ + return 1; +} + +int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame) +{ + return 1; +} + +int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + BYTE* data; + UINT32 width; + UINT32 height; + XImage* image; + RDPGFX_RECT16* destRect; + + destRect = &(cmd->destRect); + + width = destRect->right - destRect->left + 1; + height = destRect->bottom - destRect->top + 1; + + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + + /* Validate that the data received is large enough */ + if ((width * height * 4) <= cmd->bitmapDataLength) + { + data = (BYTE*) malloc(width * height * 4); + + freerdp_image_flip(cmd->bitmapData, data, width, height, 32); + + image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, (char*) data, width, height, 32, 0); + + XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, + destRect->left, destRect->top, width, height); + + XFree(image); + + free(data); + + if (!xfc->remote_app) + { + XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, + destRect->left, destRect->top, width, height, destRect->left, destRect->top); + } + + //xf_gdi_surface_update_frame(xfc, destRect->left, destRect->top, width, height); + + XSetClipMask(xfc->display, xfc->gc, None); + } + + return 1; +} + +int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + int i, tx, ty; + XImage* image; + RFX_MESSAGE* message; + RDPGFX_RECT16* destRect; + + destRect = &(cmd->destRect); + + message = rfx_process_message(xfc->rfx, cmd->bitmapData, cmd->bitmapDataLength); + + if (!message) + return -1; + + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + + XSetClipRectangles(xfc->display, xfc->gc, + destRect->left, destRect->top, + (XRectangle*) message->rects, message->numRects, YXBanded); + + /* 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); + + tx = message->tiles[i]->x + destRect->left; + ty = message->tiles[i]->y + destRect->top; + + XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, tx, ty, 64, 64); + XFree(image); + } + + /* Copy the updated region from backstore to the window. */ + for (i = 0; i < message->numRects; i++) + { + tx = message->rects[i].x + destRect->left; + ty = message->rects[i].y + destRect->top; + + 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); + } + } + + XSetClipMask(xfc->display, xfc->gc, None); + rfx_message_free(xfc->rfx, message); + + return 1; +} + +int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + int status = 1; + xfContext* xfc = (xfContext*) context->custom; + + printf("xf_SurfaceCommand: context: %p xfc: %p cmd: %p\n", context, xfc, cmd); + + switch (cmd->codecId) + { + case RDPGFX_CODECID_UNCOMPRESSED: + status = xf_SurfaceCommand_Uncompressed(xfc, context, cmd); + break; + + case RDPGFX_CODECID_CAVIDEO: + status = xf_SurfaceCommand_RemoteFX(xfc, context, cmd); + break; + + case RDPGFX_CODECID_CLEARCODEC: + break; + + case RDPGFX_CODECID_PLANAR: + break; + + case RDPGFX_CODECID_H264: + break; + + case RDPGFX_CODECID_ALPHA: + break; + + case RDPGFX_CODECID_CAPROGRESSIVE: + break; + + case RDPGFX_CODECID_CAPROGRESSIVE_V2: + break; + } + + return 1; +} + +int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext) +{ + return 1; +} + +int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface) +{ + return 1; +} + +int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface) +{ + return 1; +} + +int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill) +{ + return 1; +} + +int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) +{ + return 1; +} + +int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache) +{ + return 1; +} + +int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface) +{ + return 1; +} + +int xf_CacheImportReply(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply) +{ + return 1; +} + +int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry) +{ + return 1; +} + +int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput) +{ + return 1; +} + +int xf_MapSurfaceToWindow(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow) +{ + return 1; +} + +void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx) +{ + printf("RegisterGraphicsPipeline\n"); + + xfc->gfx = gfx; + gfx->custom = (void*) xfc; + + gfx->ResetGraphics = xf_ResetGraphics; + gfx->StartFrame = xf_StartFrame; + gfx->EndFrame = xf_EndFrame; + gfx->SurfaceCommand = xf_SurfaceCommand; + gfx->DeleteEncodingContext = xf_DeleteEncodingContext; + gfx->CreateSurface = xf_CreateSurface; + gfx->DeleteSurface = xf_DeleteSurface; + gfx->SolidFill = xf_SolidFill; + gfx->SurfaceToSurface = xf_SurfaceToSurface; + gfx->SurfaceToCache = xf_SurfaceToCache; + gfx->CacheToSurface = xf_CacheToSurface; + gfx->CacheImportReply = xf_CacheImportReply; + gfx->EvictCacheEntry = xf_EvictCacheEntry; + gfx->MapSurfaceToOutput = xf_MapSurfaceToOutput; + gfx->MapSurfaceToWindow = xf_MapSurfaceToWindow; +} diff --git a/client/X11/xf_gfx.h b/client/X11/xf_gfx.h new file mode 100644 index 000000000..01a61b9db --- /dev/null +++ b/client/X11/xf_gfx.h @@ -0,0 +1,28 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * X11 Graphics Pipeline + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __XF_GRAPHICS_PIPELINE_H +#define __XF_GRAPHICS_PIPELINE_H + +#include "xf_client.h" +#include "xfreerdp.h" + +void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx); + +#endif /* __XF_GRAPHICS_PIPELINE_H */ diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index 2c281d33d..fa24d967c 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -145,8 +145,8 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, break; case RDP_CODEC_ID_REMOTEFX: - rfx_context_set_pixel_format(xfc->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8); - msg = rfx_process_message(xfc->rfx_context, data, length); + rfx_context_set_pixel_format(xfc->rfx, RDP_PIXEL_FORMAT_B8G8R8A8); + msg = rfx_process_message(xfc->rfx, data, length); if (msg == NULL) { @@ -166,7 +166,7 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, src++; } } - rfx_message_free(xfc->rfx_context, msg); + rfx_message_free(xfc->rfx, msg); } break; diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index aa01ae905..4150d0727 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -28,6 +28,13 @@ typedef struct xf_context xfContext; #include "xf_monitor.h" #include "xf_channels.h" +#include +#include +#include +#include +#include +#include + struct xf_WorkArea { UINT32 x; @@ -137,8 +144,8 @@ struct xf_context VIRTUAL_SCREEN vscreen; BYTE* bmp_codec_none; BYTE* bmp_codec_nsc; - void* rfx_context; - void* nsc_context; + RFX_CONTEXT* rfx; + NSC_CONTEXT* nsc; void* xv_context; void* clipboard_context; @@ -168,6 +175,7 @@ struct xf_context /* Channels */ RdpeiClientContext* rdpei; + RdpgfxClientContext* gfx; }; void xf_create_window(xfContext* xfc); From f194a7b156a4608e6293dc4dd7196704648eb489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 4 Jun 2014 21:35:31 -0400 Subject: [PATCH 14/50] channels/rdpgfx: fix parsing of pdus in an array --- channels/rdpgfx/client/rdpgfx_common.c | 5 -- channels/rdpgfx/client/rdpgfx_common.h | 1 - channels/rdpgfx/client/rdpgfx_main.c | 64 ++++++++++++++++------- client/X11/xf_gfx.c | 72 ++++++++++---------------- include/freerdp/channels/rdpgfx.h | 21 ++++---- 5 files changed, 84 insertions(+), 79 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_common.c b/channels/rdpgfx/client/rdpgfx_common.c index f37864e32..fde1f9325 100644 --- a/channels/rdpgfx/client/rdpgfx_common.c +++ b/channels/rdpgfx/client/rdpgfx_common.c @@ -139,11 +139,6 @@ int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16) return 1; } -void rdpgfx_copy_rect16(RDPGFX_RECT16* dst, RDPGFX_RECT16* src) -{ - CopyMemory(dst, src, sizeof(RDPGFX_RECT16)); -} - int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32) { Stream_Read_UINT8(s, color32->B); /* B (1 byte) */ diff --git a/channels/rdpgfx/client/rdpgfx_common.h b/channels/rdpgfx/client/rdpgfx_common.h index fcb39d9bc..d2b1ea1d4 100644 --- a/channels/rdpgfx/client/rdpgfx_common.h +++ b/channels/rdpgfx/client/rdpgfx_common.h @@ -36,7 +36,6 @@ int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16); int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16); int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16); -void rdpgfx_copy_rect16(RDPGFX_RECT16* dst, RDPGFX_RECT16* src); int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32); int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32); diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 54222d710..7197e5f4c 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -63,7 +63,7 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) header.flags = 0; header.cmdId = RDPGFX_CMDID_CAPSADVERTISE; - pdu.capsSetCount = 2; + pdu.capsSetCount = 1; pdu.capsSets = (RDPGFX_CAPSET*) capsSets; capsSet = &capsSets[0]; @@ -172,6 +172,7 @@ int rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, RDPGFX_ int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { + int pad; UINT32 index; MONITOR_DEF* monitor; RDPGFX_RESET_GRAPHICS_PDU pdu; @@ -197,7 +198,8 @@ int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s Stream_Read_UINT32(s, monitor->flags); /* flags (4 bytes) */ } - /* pad (total size is 340 bytes) */ + pad = 340 - (RDPGFX_HEADER_SIZE + 12 + (pdu.monitorCount * 20)); + Stream_Seek(s, pad); /* pad (total size is 340 bytes) */ fprintf(stderr, "RdpGfxRecvResetGraphicsPdu: width: %d height: %d count: %d\n", pdu.width, pdu.height, pdu.monitorCount); @@ -367,6 +369,7 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ pdu.bitmapData = Stream_Pointer(s); + Stream_Seek(s, pdu.bitmapDataLength); fprintf(stderr, "RdpGfxRecvWireToSurface1Pdu: surfaceId: %d codecId: %s (0x%04X) pixelFormat: 0x%04X " "destRect: left: %d top: %d right: %d bottom: %d bitmapDataLength: %d\n", @@ -376,19 +379,22 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream cmd.surfaceId = pdu.surfaceId; cmd.codecId = pdu.codecId; - cmd.codecContextId = 0; - cmd.pixelFormat = pdu.pixelFormat; - rdpgfx_copy_rect16(&(cmd.destRect), &(pdu.destRect)); - cmd.bitmapDataLength = pdu.bitmapDataLength; - cmd.bitmapData = pdu.bitmapData; + cmd.contextId = 0; + cmd.format = pdu.pixelFormat; + cmd.left = pdu.destRect.left; + cmd.top = pdu.destRect.top; + cmd.right = pdu.destRect.right; + cmd.bottom = pdu.destRect.bottom; + cmd.width = cmd.right - cmd.left + 1; + cmd.height = cmd.bottom - cmd.top + 1; + cmd.length = pdu.bitmapDataLength; + cmd.data = pdu.bitmapData; if (context && context->SurfaceCommand) { context->SurfaceCommand(context, &cmd); } - rdpgfx_decode(gfx, &cmd); - return 1; } @@ -407,6 +413,7 @@ int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ pdu.bitmapData = Stream_Pointer(s); + Stream_Seek(s, pdu.bitmapDataLength); fprintf(stderr, "RdpGfxRecvWireToSurface2Pdu: surfaceId: %d codecId: 0x%04X " "codecContextId: %d pixelFormat: 0x%04X bitmapDataLength: %d\n", @@ -414,19 +421,22 @@ int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream cmd.surfaceId = pdu.surfaceId; cmd.codecId = pdu.codecId; - cmd.codecContextId = pdu.codecContextId; - cmd.pixelFormat = pdu.pixelFormat; - ZeroMemory(&(cmd.destRect), sizeof(RDPGFX_RECT16)); - cmd.bitmapDataLength = pdu.bitmapDataLength; - cmd.bitmapData = pdu.bitmapData; + cmd.contextId = pdu.codecContextId; + cmd.format = pdu.pixelFormat; + cmd.left = 0; + cmd.top = 0; + cmd.right = 0; + cmd.bottom = 0; + cmd.width = 0; + cmd.height = 0; + cmd.length = pdu.bitmapDataLength; + cmd.data = pdu.bitmapData; if (context && context->SurfaceCommand) { context->SurfaceCommand(context, &cmd); } - rdpgfx_decode(gfx, &cmd); - return 1; } @@ -632,8 +642,11 @@ int rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wSt int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { int status; + int beg, end; RDPGFX_HEADER header; + beg = Stream_GetPosition(s); + rdpgfx_read_header(s, &header); #if 1 @@ -716,7 +729,19 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) break; } - return 0; + end = Stream_GetPosition(s); + + if (end != (beg + header.pduLength)) + { + fprintf(stderr, "Unexpected pdu end: Actual: %d, Expected: %d\n", + end, (beg + header.pduLength)); + + exit(0); + + Stream_SetPosition(s, (beg + header.pduLength)); + } + + return status; } static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer) @@ -740,7 +765,10 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, s = Stream_New(pDstData, DstSize); - status = rdpgfx_recv_pdu(callback, s); + while (Stream_GetPosition(s) < Stream_Length(s)) + { + status = rdpgfx_recv_pdu(callback, s); + } Stream_Free(s, TRUE); diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 2a94b74d2..a014425b1 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -67,46 +67,32 @@ int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame) int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { BYTE* data; - UINT32 width; - UINT32 height; XImage* image; - RDPGFX_RECT16* destRect; - - destRect = &(cmd->destRect); - - width = destRect->right - destRect->left + 1; - height = destRect->bottom - destRect->top + 1; XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); - /* Validate that the data received is large enough */ - if ((width * height * 4) <= cmd->bitmapDataLength) + data = (BYTE*) malloc(cmd->width * cmd->height * 4); + + freerdp_image_flip(cmd->data, data, cmd->width, cmd->height, 32); + + image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, (char*) data, cmd->width, cmd->height, 32, 0); + + XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, + cmd->left, cmd->top, cmd->width, cmd->height); + + XFree(image); + + free(data); + + if (!xfc->remote_app) { - data = (BYTE*) malloc(width * height * 4); - - freerdp_image_flip(cmd->bitmapData, data, width, height, 32); - - image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, (char*) data, width, height, 32, 0); - - XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, - destRect->left, destRect->top, width, height); - - XFree(image); - - free(data); - - if (!xfc->remote_app) - { - XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, - destRect->left, destRect->top, width, height, destRect->left, destRect->top); - } - - //xf_gdi_surface_update_frame(xfc, destRect->left, destRect->top, width, height); - - XSetClipMask(xfc->display, xfc->gc, None); + XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, + cmd->left, cmd->top, cmd->width, cmd->height, cmd->left, cmd->top); } + XSetClipMask(xfc->display, xfc->gc, None); + return 1; } @@ -115,11 +101,8 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP int i, tx, ty; XImage* image; RFX_MESSAGE* message; - RDPGFX_RECT16* destRect; - destRect = &(cmd->destRect); - - message = rfx_process_message(xfc->rfx, cmd->bitmapData, cmd->bitmapDataLength); + message = rfx_process_message(xfc->rfx, cmd->data, cmd->length); if (!message) return -1; @@ -127,18 +110,16 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); - XSetClipRectangles(xfc->display, xfc->gc, - destRect->left, destRect->top, + XSetClipRectangles(xfc->display, xfc->gc, cmd->left, cmd->top, (XRectangle*) message->rects, message->numRects, YXBanded); - /* 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); - tx = message->tiles[i]->x + destRect->left; - ty = message->tiles[i]->y + destRect->top; + tx = message->tiles[i]->x + cmd->left; + ty = message->tiles[i]->y + cmd->top; XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, tx, ty, 64, 64); XFree(image); @@ -147,12 +128,13 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP /* Copy the updated region from backstore to the window. */ for (i = 0; i < message->numRects; i++) { - tx = message->rects[i].x + destRect->left; - ty = message->rects[i].y + destRect->top; + tx = message->rects[i].x + cmd->left; + ty = message->rects[i].y + cmd->top; 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); } } @@ -167,8 +149,6 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) int status = 1; xfContext* xfc = (xfContext*) context->custom; - printf("xf_SurfaceCommand: context: %p xfc: %p cmd: %p\n", context, xfc, cmd); - switch (cmd->codecId) { case RDPGFX_CODECID_UNCOMPRESSED: diff --git a/include/freerdp/channels/rdpgfx.h b/include/freerdp/channels/rdpgfx.h index 63c374153..e4070194b 100644 --- a/include/freerdp/channels/rdpgfx.h +++ b/include/freerdp/channels/rdpgfx.h @@ -165,17 +165,20 @@ struct _RDPGFX_WIRE_TO_SURFACE_PDU_2 }; typedef struct _RDPGFX_WIRE_TO_SURFACE_PDU_2 RDPGFX_WIRE_TO_SURFACE_PDU_2; -/* RDPGFX_SURFACE_COMMAND encapsulates both RDPGFX_WIRE_TO_SURFACE_PDU 1/2 */ - struct _RDPGFX_SURFACE_COMMAND { - UINT16 surfaceId; - UINT16 codecId; - UINT32 codecContextId; - RDPGFX_PIXELFORMAT pixelFormat; - RDPGFX_RECT16 destRect; - UINT32 bitmapDataLength; - BYTE* bitmapData; + UINT32 surfaceId; + UINT32 codecId; + UINT32 contextId; + UINT32 format; + UINT32 left; + UINT32 top; + UINT32 right; + UINT32 bottom; + UINT32 width; + UINT32 height; + UINT32 length; + BYTE* data; }; typedef struct _RDPGFX_SURFACE_COMMAND RDPGFX_SURFACE_COMMAND; From 12e6c845eb67986d895e752b336d1339b27a9fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 4 Jun 2014 22:06:29 -0400 Subject: [PATCH 15/50] channels/rdpgfx: cleanup debug output --- channels/rdpgfx/client/rdpgfx_main.c | 143 +++++++++++++-------------- channels/rdpgfx/client/rdpgfx_main.h | 4 + client/X11/xf_gfx.c | 2 - 3 files changed, 72 insertions(+), 77 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 7197e5f4c..1c6cd1614 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -93,7 +93,7 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE); - fprintf(stderr, "RdpGfxSendCapsAdvertisePdu: %d\n", header.pduLength); + WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu"); s = Stream_New(NULL, header.pduLength); @@ -125,6 +125,7 @@ int rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) RDPGFX_CAPSET capsSet; UINT32 capsDataLength; RDPGFX_CAPS_CONFIRM_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; pdu.capsSet = &capsSet; @@ -132,7 +133,7 @@ int rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) Stream_Read_UINT32(s, capsDataLength); /* capsDataLength (4 bytes) */ Stream_Read_UINT32(s, capsSet.flags); /* capsData (4 bytes) */ - fprintf(stderr, "RdpGfxRecvCapsConfirmPdu: version: 0x%04X flags: 0x%04X\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvCapsConfirmPdu: version: 0x%04X flags: 0x%04X", capsSet.version, capsSet.flags); return 1; @@ -142,16 +143,14 @@ int rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, RDPGFX_ { int status; wStream* s; - RDPGFX_PLUGIN* gfx; RDPGFX_HEADER header; - - gfx = (RDPGFX_PLUGIN*) callback->plugin; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; header.flags = 0; header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE; header.pduLength = RDPGFX_HEADER_SIZE + 12; - fprintf(stderr, "RdpGfxSendFrameAcknowledgePdu: %d\n", pdu->frameId); + WLog_Print(gfx->log, WLOG_DEBUG, "SendFrameAcknowledgePdu: %d", pdu->frameId); s = Stream_New(NULL, header.pduLength); @@ -201,7 +200,7 @@ int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s pad = 340 - (RDPGFX_HEADER_SIZE + 12 + (pdu.monitorCount * 20)); Stream_Seek(s, pad); /* pad (total size is 340 bytes) */ - fprintf(stderr, "RdpGfxRecvResetGraphicsPdu: width: %d height: %d count: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvResetGraphicsPdu: width: %d height: %d count: %d", pdu.width, pdu.height, pdu.monitorCount); if (context && context->ResetGraphics) @@ -220,7 +219,7 @@ int rdpgfx_recv_evict_cache_entry_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ - fprintf(stderr, "RdpGfxRecvEvictCacheEntryPdu: cacheSlot: %d\n", pdu.cacheSlot); + WLog_Print(gfx->log, WLOG_DEBUG, "RecvEvictCacheEntryPdu: cacheSlot: %d", pdu.cacheSlot); if (context && context->EvictCacheEntry) { @@ -249,7 +248,7 @@ int rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea Stream_Read_UINT16(s, pdu.cacheSlots[index]); /* cacheSlot (2 bytes) */ } - fprintf(stderr, "RdpGfxRecvCacheImportReplyPdu: importedEntriesCount: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvCacheImportReplyPdu: importedEntriesCount: %d", pdu.importedEntriesCount); if (context && context->CacheImportReply) @@ -271,7 +270,7 @@ int rdpgfx_recv_create_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s Stream_Read_UINT16(s, pdu.height); /* height (2 bytes) */ Stream_Read_UINT8(s, pdu.pixelFormat); /* RDPGFX_PIXELFORMAT (1 byte) */ - fprintf(stderr, "RdpGfxRecvCreateSurfacePdu: surfaceId: %d width: %d height: %d pixelFormat: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvCreateSurfacePdu: surfaceId: %d width: %d height: %d pixelFormat: 0x%02X", pdu.surfaceId, pdu.width, pdu.height, pdu.pixelFormat); if (context && context->CreateSurface) @@ -290,7 +289,7 @@ int rdpgfx_recv_delete_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ - fprintf(stderr, "RdpGfxRecvDeleteSurfacePdu: surfaceId: %d\n", pdu.surfaceId); + WLog_Print(gfx->log, WLOG_DEBUG, "RecvDeleteSurfacePdu: surfaceId: %d", pdu.surfaceId); if (context && context->DeleteSurface) { @@ -309,7 +308,7 @@ int rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) Stream_Read_UINT32(s, pdu.timestamp); /* timestamp (4 bytes) */ Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ - fprintf(stderr, "RdpGfxRecvStartFramePdu: frameId: %d timestamp: 0x%04X\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvStartFramePdu: frameId: %d timestamp: 0x%04X\n", pdu.frameId, pdu.timestamp); if (context && context->StartFrame) @@ -331,7 +330,7 @@ int rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ - fprintf(stderr, "RdpGfxRecvEndFramePdu: frameId: %d\n", pdu.frameId); + WLog_Print(gfx->log, WLOG_DEBUG, "RecvEndFramePdu: frameId: %d\n", pdu.frameId); if (context && context->EndFrame) { @@ -371,8 +370,8 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream pdu.bitmapData = Stream_Pointer(s); Stream_Seek(s, pdu.bitmapDataLength); - fprintf(stderr, "RdpGfxRecvWireToSurface1Pdu: surfaceId: %d codecId: %s (0x%04X) pixelFormat: 0x%04X " - "destRect: left: %d top: %d right: %d bottom: %d bitmapDataLength: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvWireToSurface1Pdu: surfaceId: %d codecId: %s (0x%04X) pixelFormat: 0x%04X " + "destRect: left: %d top: %d right: %d bottom: %d bitmapDataLength: %d", (int) pdu.surfaceId, rdpgfx_get_codec_id_string(pdu.codecId), pdu.codecId, pdu.pixelFormat, pdu.destRect.left, pdu.destRect.top, pdu.destRect.right, pdu.destRect.bottom, pdu.bitmapDataLength); @@ -415,8 +414,8 @@ int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream pdu.bitmapData = Stream_Pointer(s); Stream_Seek(s, pdu.bitmapDataLength); - fprintf(stderr, "RdpGfxRecvWireToSurface2Pdu: surfaceId: %d codecId: 0x%04X " - "codecContextId: %d pixelFormat: 0x%04X bitmapDataLength: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvWireToSurface2Pdu: surfaceId: %d codecId: 0x%04X " + "codecContextId: %d pixelFormat: 0x%04X bitmapDataLength: %d", (int) pdu.surfaceId, pdu.codecId, pdu.codecContextId, pdu.pixelFormat, pdu.bitmapDataLength); cmd.surfaceId = pdu.surfaceId; @@ -449,7 +448,7 @@ int rdpgfx_recv_delete_encoding_context_pdu(RDPGFX_CHANNEL_CALLBACK* callback, w Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT32(s, pdu.codecContextId); /* codecContextId (4 bytes) */ - fprintf(stderr, "RdpGfxRecvDeleteEncodingContextPdu: surfaceId: %d codecContextId: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvDeleteEncodingContextPdu: surfaceId: %d codecContextId: %d", pdu.surfaceId, pdu.codecContextId); if (context && context->DeleteEncodingContext) @@ -485,7 +484,7 @@ int rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) rdpgfx_read_rect16(s, fillRect); } - fprintf(stderr, "RdpGfxRecvSolidFillPdu: surfaceId: %d fillRectCount: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvSolidFillPdu: surfaceId: %d fillRectCount: %d", pdu.surfaceId, pdu.fillRectCount); if (context && context->SolidFill) @@ -522,8 +521,8 @@ int rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea rdpgfx_read_point16(s, destPt); } - fprintf(stderr, "RdpGfxRecvSurfaceToSurfacePdu: surfaceIdSrc: %d surfaceIdDest: %d " - "left: %d top: %d right: %d bottom: %d destPtsCount: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvSurfaceToSurfacePdu: surfaceIdSrc: %d surfaceIdDest: %d " + "left: %d top: %d right: %d bottom: %d destPtsCount: %d", pdu.surfaceIdSrc, pdu.surfaceIdDest, pdu.rectSrc.left, pdu.rectSrc.top, pdu.rectSrc.right, pdu.rectSrc.bottom, pdu.destPtsCount); @@ -547,8 +546,8 @@ int rdpgfx_recv_surface_to_cache_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ rdpgfx_read_rect16(s, &(pdu.rectSrc)); /* rectSrc (8 bytes ) */ - fprintf(stderr, "RdpGfxRecvSurfaceToCachePdu: surfaceId: %d cacheKey: 0x%08X cacheSlot: %d " - "left: %d top: %d right: %d bottom: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvSurfaceToCachePdu: surfaceId: %d cacheKey: 0x%08X cacheSlot: %d " + "left: %d top: %d right: %d bottom: %d", pdu.surfaceId, (int) pdu.cacheKey, pdu.cacheSlot, pdu.rectSrc.left, pdu.rectSrc.top, pdu.rectSrc.right, pdu.rectSrc.bottom); @@ -584,7 +583,7 @@ int rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* rdpgfx_read_point16(s, destPt); } - fprintf(stderr, "RdpGfxRecvCacheToSurfacePdu: cacheSlot: %d surfaceId: %d destPtsCount: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RdpGfxRecvCacheToSurfacePdu: cacheSlot: %d surfaceId: %d destPtsCount: %d", pdu.cacheSlot, (int) pdu.surfaceId, pdu.destPtsCount); if (context && context->CacheToSurface) @@ -606,7 +605,7 @@ int rdpgfx_recv_map_surface_to_output_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wSt Stream_Read_UINT32(s, pdu.outputOriginX); /* outputOriginX (4 bytes) */ Stream_Read_UINT32(s, pdu.outputOriginY); /* outputOriginY (4 bytes) */ - fprintf(stderr, "RdpGfxRecvMapSurfaceToOutputPdu: surfaceId: %d outputOriginX: %d outputOriginY: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvMapSurfaceToOutputPdu: surfaceId: %d outputOriginX: %d outputOriginY: %d", (int) pdu.surfaceId, pdu.outputOriginX, pdu.outputOriginY); if (context && context->MapSurfaceToOutput) @@ -628,7 +627,7 @@ int rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wSt Stream_Read_UINT32(s, pdu.mappedWidth); /* mappedWidth (4 bytes) */ Stream_Read_UINT32(s, pdu.mappedHeight); /* mappedHeight (4 bytes) */ - fprintf(stderr, "RdpGfxRecvMapSurfaceToWindowPdu: surfaceId: %d windowId: 0x%04X mappedWidth: %d mappedHeight: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "RecvMapSurfaceToWindowPdu: surfaceId: %d windowId: 0x%04X mappedWidth: %d mappedHeight: %d", pdu.surfaceId, (int) pdu.windowId, pdu.mappedWidth, pdu.mappedHeight); if (context && context->MapSurfaceToWindow) @@ -644,13 +643,14 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) int status; int beg, end; RDPGFX_HEADER header; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; beg = Stream_GetPosition(s); rdpgfx_read_header(s, &header); #if 1 - printf("cmdId: %s (0x%04X) flags: 0x%04X pduLength: %d\n", + WLog_Print(gfx->log, WLOG_DEBUG, "cmdId: %s (0x%04X) flags: 0x%04X pduLength: %d", rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags, header.pduLength); #endif @@ -733,11 +733,9 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) if (end != (beg + header.pduLength)) { - fprintf(stderr, "Unexpected pdu end: Actual: %d, Expected: %d\n", + fprintf(stderr, "Unexpected gfx pdu end: Actual: %d, Expected: %d\n", end, (beg + header.pduLength)); - exit(0); - Stream_SetPosition(s, (beg + header.pduLength)); } @@ -750,10 +748,8 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, int status = 0; UINT32 DstSize = 0; BYTE* pDstData = NULL; - RDPGFX_PLUGIN* gfx = NULL; RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; - - gfx = (RDPGFX_PLUGIN*) callback->plugin; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; status = zgfx_decompress(gfx->zgfx, pBuffer, cbSize, &pDstData, &DstSize, 0); @@ -778,8 +774,9 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, static int rdpgfx_on_open(IWTSVirtualChannelCallback* pChannelCallback) { RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; - fprintf(stderr, "RdpGfxOnOpen\n"); + WLog_Print(gfx->log, WLOG_DEBUG, "OnOpen"); rdpgfx_send_caps_advertise_pdu(callback); @@ -789,8 +786,9 @@ static int rdpgfx_on_open(IWTSVirtualChannelCallback* pChannelCallback) static int rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback) { RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; - fprintf(stderr, "RdpGfxOnClose\n"); + WLog_Print(gfx->log, WLOG_DEBUG, "OnClose"); free(callback); @@ -806,6 +804,9 @@ static int rdpgfx_on_new_channel_connection(IWTSListenerCallback* pListenerCallb callback = (RDPGFX_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPGFX_CHANNEL_CALLBACK)); + if (!callback) + return -1; + callback->iface.OnDataReceived = rdpgfx_on_data_received; callback->iface.OnOpen = rdpgfx_on_open; callback->iface.OnClose = rdpgfx_on_close; @@ -816,56 +817,46 @@ static int rdpgfx_on_new_channel_connection(IWTSListenerCallback* pListenerCallb *ppCallback = (IWTSVirtualChannelCallback*) callback; - fprintf(stderr, "RdpGfxOnNewChannelConnection\n"); - return 0; } static int rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { int status; - RDPGFX_PLUGIN* rdpgfx = (RDPGFX_PLUGIN*) pPlugin; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) pPlugin; - rdpgfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) calloc(1, sizeof(RDPGFX_LISTENER_CALLBACK)); + gfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) calloc(1, sizeof(RDPGFX_LISTENER_CALLBACK)); - if (!rdpgfx->listener_callback) + if (!gfx->listener_callback) return -1; - rdpgfx->listener_callback->iface.OnNewChannelConnection = rdpgfx_on_new_channel_connection; - rdpgfx->listener_callback->plugin = pPlugin; - rdpgfx->listener_callback->channel_mgr = pChannelMgr; + gfx->listener_callback->iface.OnNewChannelConnection = rdpgfx_on_new_channel_connection; + gfx->listener_callback->plugin = pPlugin; + gfx->listener_callback->channel_mgr = pChannelMgr; status = pChannelMgr->CreateListener(pChannelMgr, RDPGFX_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*) rdpgfx->listener_callback, &(rdpgfx->listener)); + (IWTSListenerCallback*) gfx->listener_callback, &(gfx->listener)); - rdpgfx->listener->pInterface = rdpgfx->iface.pInterface; + gfx->listener->pInterface = gfx->iface.pInterface; - fprintf(stderr, "RdpGfxInitialize: %d\n", status); + WLog_Print(gfx->log, WLOG_DEBUG, "Initialize"); return status; } static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin) { - RDPGFX_PLUGIN* rdpgfx = (RDPGFX_PLUGIN*) pPlugin; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) pPlugin; - if (rdpgfx->listener_callback) - free(rdpgfx->listener_callback); + WLog_Print(gfx->log, WLOG_DEBUG, "Terminated"); - zgfx_context_free(rdpgfx->zgfx); + if (gfx->listener_callback) + free(gfx->listener_callback); - free(rdpgfx); + zgfx_context_free(gfx->zgfx); - return 0; -} + free(gfx); -/** - * Channel Client Interface - */ - -UINT32 rdpgfx_get_version(RdpgfxClientContext* context) -{ - //RDPGFX_PLUGIN* rdpgfx = (RDPGFX_PLUGIN*) context->handle; return 0; } @@ -875,37 +866,39 @@ UINT32 rdpgfx_get_version(RdpgfxClientContext* context) int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - int error = 0; - RDPGFX_PLUGIN* rdpgfx; + int status = 0; + RDPGFX_PLUGIN* gfx; RdpgfxClientContext* context; - rdpgfx = (RDPGFX_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "rdpgfx"); + gfx = (RDPGFX_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "rdpgfx"); - if (!rdpgfx) + if (!gfx) { - rdpgfx = (RDPGFX_PLUGIN*) calloc(1, sizeof(RDPGFX_PLUGIN)); + gfx = (RDPGFX_PLUGIN*) calloc(1, sizeof(RDPGFX_PLUGIN)); - if (!rdpgfx) + if (!gfx) return -1; - rdpgfx->iface.Initialize = rdpgfx_plugin_initialize; - rdpgfx->iface.Connected = NULL; - rdpgfx->iface.Disconnected = NULL; - rdpgfx->iface.Terminated = rdpgfx_plugin_terminated; + gfx->log = WLog_Get("com.freerdp.gfx.client"); + + gfx->iface.Initialize = rdpgfx_plugin_initialize; + gfx->iface.Connected = NULL; + gfx->iface.Disconnected = NULL; + gfx->iface.Terminated = rdpgfx_plugin_terminated; context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext)); if (!context) return -1; - context->handle = (void*) rdpgfx; + context->handle = (void*) gfx; - rdpgfx->iface.pInterface = (void*) context; + gfx->iface.pInterface = (void*) context; - rdpgfx->zgfx = zgfx_context_new(FALSE); + gfx->zgfx = zgfx_context_new(FALSE); - error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpgfx", (IWTSPlugin*) rdpgfx); + status = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpgfx", (IWTSPlugin*) gfx); } - return error; + return status; } diff --git a/channels/rdpgfx/client/rdpgfx_main.h b/channels/rdpgfx/client/rdpgfx_main.h index 1055a3371..ace81bef3 100644 --- a/channels/rdpgfx/client/rdpgfx_main.h +++ b/channels/rdpgfx/client/rdpgfx_main.h @@ -24,6 +24,8 @@ #include #include +#include + #include #include @@ -55,6 +57,8 @@ struct _RDPGFX_PLUGIN IWTSListener* listener; RDPGFX_LISTENER_CALLBACK* listener_callback; + wLog* log; + BOOL ThinClient; BOOL SmallCache; BOOL H264; diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index a014425b1..d7d94e1f3 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -238,8 +238,6 @@ int xf_MapSurfaceToWindow(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WI void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx) { - printf("RegisterGraphicsPipeline\n"); - xfc->gfx = gfx; gfx->custom = (void*) xfc; From 38ac1fd7b0dd37cdb70f99c9a8de1b176bb17b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 4 Jun 2014 22:49:03 -0400 Subject: [PATCH 16/50] xfreerdp: improve graphics pipeline support --- client/X11/xf_gfx.c | 107 ++++++++++++++++++++++++++++++++++++------ client/X11/xfreerdp.h | 2 + 2 files changed, 95 insertions(+), 14 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index d7d94e1f3..0c2e24d1f 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -51,6 +51,8 @@ int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* re xfc->nsc->height = resetGraphics->height; nsc_context_set_pixel_format(xfc->nsc, RDP_PIXEL_FORMAT_B8G8R8A8); + region16_init(&(xfc->invalidRegion)); + return 1; } @@ -61,6 +63,23 @@ int xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFra int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame) { + UINT16 width, height; + const RECTANGLE_16* extents; + xfContext* xfc = (xfContext*) context->custom; + + if (!region16_is_empty(&(xfc->invalidRegion))) + { + extents = region16_extents(&(xfc->invalidRegion)); + + width = extents->right - extents->left; + height = extents->bottom - extents->top; + + XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, + extents->left, extents->top, width, height, extents->left, extents->top); + + region16_clear(&(xfc->invalidRegion)); + } + return 1; } @@ -68,6 +87,7 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, { BYTE* data; XImage* image; + RECTANGLE_16 invalidRect; XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); @@ -78,18 +98,18 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, (char*) data, cmd->width, cmd->height, 32, 0); - XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, - cmd->left, cmd->top, cmd->width, cmd->height); + XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, cmd->left, cmd->top, cmd->width, cmd->height); XFree(image); free(data); - if (!xfc->remote_app) - { - XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, - cmd->left, cmd->top, cmd->width, cmd->height, cmd->left, cmd->top); - } + invalidRect.left = cmd->left; + invalidRect.top = cmd->top; + invalidRect.right = cmd->right; + invalidRect.bottom = cmd->bottom; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); XSetClipMask(xfc->display, xfc->gc, None); @@ -101,6 +121,7 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP int i, tx, ty; XImage* image; RFX_MESSAGE* message; + RECTANGLE_16 invalidRect; message = rfx_process_message(xfc->rfx, cmd->data, cmd->length); @@ -125,22 +146,33 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP XFree(image); } - /* Copy the updated region from backstore to the window. */ for (i = 0; i < message->numRects; i++) { tx = message->rects[i].x + cmd->left; ty = message->rects[i].y + cmd->top; - 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); - } + invalidRect.left = tx; + invalidRect.top = ty; + invalidRect.right = tx + message->rects[i].width - 1; + invalidRect.bottom = ty + message->rects[i].height - 1; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); } - XSetClipMask(xfc->display, xfc->gc, None); rfx_message_free(xfc->rfx, message); + XSetClipMask(xfc->display, xfc->gc, None); + + return 1; +} + +int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ return 1; } @@ -160,9 +192,11 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) break; case RDPGFX_CODECID_CLEARCODEC: + status = xf_SurfaceCommand_ClearCodec(xfc, context, cmd); break; case RDPGFX_CODECID_PLANAR: + status = xf_SurfaceCommand_Planar(xfc, context, cmd); break; case RDPGFX_CODECID_H264: @@ -198,6 +232,51 @@ int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* de int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill) { + UINT16 index; + UINT32 color; + BYTE a, r, g, b; + XRectangle* xrects; + RDPGFX_RECT16* rect; + RECTANGLE_16 invalidRect; + xfContext* xfc = (xfContext*) context->custom; + + b = solidFill->fillPixel.B; + g = solidFill->fillPixel.G; + r = solidFill->fillPixel.R; + a = solidFill->fillPixel.XA; + + color = ARGB32(a, r, g, b); + + xrects = (XRectangle*) malloc(solidFill->fillRectCount * sizeof(XRectangle)); + + if (!xrects) + return -1; + + for (index = 0; index < solidFill->fillRectCount; index++) + { + rect = &(solidFill->fillRects[index]); + + xrects->x = rect->left; + xrects->y = rect->top; + xrects->width = rect->right - rect->left + 1; + xrects->height = rect->bottom - rect->top + 1; + + invalidRect.left = rect->left; + invalidRect.top = rect->top; + invalidRect.right = rect->right; + invalidRect.bottom = rect->bottom; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + } + + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + XSetForeground(xfc->display, xfc->gc, color); + + XFillRectangles(xfc->display, xfc->drawing, xfc->gc, xrects, solidFill->fillRectCount); + + free(xrects); + return 1; } diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 4150d0727..8f1bb2c8d 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -34,6 +34,7 @@ typedef struct xf_context xfContext; #include #include #include +#include struct xf_WorkArea { @@ -110,6 +111,7 @@ struct xf_context HGDI_DC hdc; BYTE* primary_buffer; + REGION16 invalidRegion; BOOL frame_begin; UINT16 frame_x1; From 68221cca73465c8297421ec351820eb9442a64d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 5 Jun 2014 12:36:01 -0400 Subject: [PATCH 17/50] xfreerdp: improve gfx frame handling --- channels/rdpgfx/client/rdpgfx_main.c | 5 +- client/X11/xf_event.c | 6 +- client/X11/xf_gfx.c | 164 +++++++++++++++++++++------ client/X11/xfreerdp.h | 1 + 4 files changed, 132 insertions(+), 44 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 1c6cd1614..1722087e5 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -343,9 +343,8 @@ int rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) ack.frameId = pdu.frameId; ack.totalFramesDecoded = gfx->TotalDecodedFrames; - ack.queueDepth = SUSPEND_FRAME_ACKNOWLEDGEMENT; - //ack.queueDepth = QUEUE_DEPTH_UNAVAILABLE; - //ack.queueDepth = gfx->UnacknowledgedFrames; + //ack.queueDepth = SUSPEND_FRAME_ACKNOWLEDGEMENT; + ack.queueDepth = QUEUE_DEPTH_UNAVAILABLE; rdpgfx_send_frame_acknowledge_pdu(callback, &ack); diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index d6f0c8dd7..169a31126 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -189,7 +189,7 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) y = event->xexpose.y; w = event->xexpose.width; h = event->xexpose.height; - + if (!app) { if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) @@ -199,9 +199,7 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) } else { - XCopyArea(xfc->display, xfc->primary, - xfc->window->handle, xfc->gc, x, y, w, - h, x, y); + XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y); } } else diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 0c2e24d1f..694eae6ea 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -27,6 +27,9 @@ int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* re { xfContext* xfc = (xfContext*) context->custom; + printf("xf_ResetGraphics: width: %d height: %d\n", + resetGraphics->width, resetGraphics->height); + if (xfc->rfx) { rfx_context_free(xfc->rfx); @@ -56,16 +59,18 @@ int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* re return 1; } -int xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame) -{ - return 1; -} - -int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame) +int xf_SurfaceUpdate(xfContext* xfc) { UINT16 width, height; + RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; - xfContext* xfc = (xfContext*) context->custom; + + surfaceRect.left = 0; + surfaceRect.top = 0; + surfaceRect.right = xfc->width - 1; + surfaceRect.bottom = xfc->height - 1; + + region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect); if (!region16_is_empty(&(xfc->invalidRegion))) { @@ -74,11 +79,48 @@ int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame) width = extents->right - extents->left; height = extents->bottom - extents->top; + if (width > xfc->width) + width = xfc->width; + + if (height > xfc->height) + height = xfc->height; + + printf("xf_SurfaceUpdate: x: %d y: %d width: %d height: %d\n", + extents->left, extents->top, width, height); + XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, extents->left, extents->top, width, height, extents->left, extents->top); - - region16_clear(&(xfc->invalidRegion)); } + else + { + printf("xf_SurfaceUpdate: null region\n"); + } + + region16_clear(&(xfc->invalidRegion)); + + return 1; +} + +int xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame) +{ + xfContext* xfc = (xfContext*) context->custom; + + printf("xf_StartFrame: %d\n", startFrame->frameId); + + xfc->inGfxFrame = TRUE; + + return 1; +} + +int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame) +{ + xfContext* xfc = (xfContext*) context->custom; + + printf("xf_EndFrame: %d\n", endFrame->frameId); + + xf_SurfaceUpdate(xfc); + + xfc->inGfxFrame = FALSE; return 1; } @@ -89,6 +131,8 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, XImage* image; RECTANGLE_16 invalidRect; + printf("xf_SurfaceCommand_Uncompressed\n"); + XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); @@ -113,66 +157,103 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, XSetClipMask(xfc->display, xfc->gc, None); + if (!xfc->inGfxFrame) + xf_SurfaceUpdate(xfc); + return 1; } int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { - int i, tx, ty; + UINT16 index; XImage* image; + RFX_RECT* rect; + RFX_TILE* tile; + XRectangle* xrects; RFX_MESSAGE* message; RECTANGLE_16 invalidRect; + RECTANGLE_16 surfaceRect; + + printf("xf_SurfaceCommand_RemoteFX\n"); + + surfaceRect.left = 0; + surfaceRect.top = 0; + surfaceRect.right = xfc->width - 1; + surfaceRect.bottom = xfc->height - 1; message = rfx_process_message(xfc->rfx, cmd->data, cmd->length); if (!message) return -1; - XSetFunction(xfc->display, xfc->gc, GXcopy); - XSetFillStyle(xfc->display, xfc->gc, FillSolid); + xrects = (XRectangle*) malloc(message->numRects * sizeof(XRectangle)); - XSetClipRectangles(xfc->display, xfc->gc, cmd->left, cmd->top, - (XRectangle*) message->rects, message->numRects, YXBanded); + if (!xrects) + return -1; - for (i = 0; i < message->numTiles; i++) + for (index = 0; index < message->numRects; index++) { - image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, - (char*) message->tiles[i]->data, 64, 64, 32, 0); + rect = &(message->rects[index]); - tx = message->tiles[i]->x + cmd->left; - ty = message->tiles[i]->y + cmd->top; + xrects[index].x = cmd->left + rect->x; + xrects[index].y = cmd->top + rect->y; + xrects[index].width = rect->width; + xrects[index].height = rect->height; - XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, tx, ty, 64, 64); - XFree(image); - } - - for (i = 0; i < message->numRects; i++) - { - tx = message->rects[i].x + cmd->left; - ty = message->rects[i].y + cmd->top; - - invalidRect.left = tx; - invalidRect.top = ty; - invalidRect.right = tx + message->rects[i].width - 1; - invalidRect.bottom = ty + message->rects[i].height - 1; + invalidRect.left = cmd->left + rect->x; + invalidRect.top = cmd->top + rect->y; + invalidRect.right = invalidRect.left + rect->width - 1; + invalidRect.bottom = invalidRect.top + rect->height - 1; region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); } - rfx_message_free(xfc->rfx, message); + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + + XSetClipRectangles(xfc->display, xfc->gc, cmd->left, cmd->top, xrects, message->numRects, YXBanded); + + for (index = 0; index < message->numTiles; index++) + { + tile = message->tiles[index]; + + image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, + (char*) tile->data, 64, 64, 32, 0); + + XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, + cmd->left + tile->x, cmd->top + tile->y, 64, 64); + + XFree(image); + } XSetClipMask(xfc->display, xfc->gc, None); + rfx_message_free(xfc->rfx, message); + free(xrects); + + if (!xfc->inGfxFrame) + xf_SurfaceUpdate(xfc); + return 1; } int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { + printf("xf_SurfaceCommand_ClearCodec\n"); + + if (!xfc->inGfxFrame) + xf_SurfaceUpdate(xfc); + return 1; } int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { + printf("xf_SurfaceCommand_Planar\n"); + + if (!xfc->inGfxFrame) + xf_SurfaceUpdate(xfc); + return 1; } @@ -200,15 +281,19 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) break; case RDPGFX_CODECID_H264: + printf("xf_SurfaceCommand_H264\n"); break; case RDPGFX_CODECID_ALPHA: + printf("xf_SurfaceCommand_Alpha\n"); break; case RDPGFX_CODECID_CAPROGRESSIVE: + printf("xf_SurfaceCommand_Progressive\n"); break; case RDPGFX_CODECID_CAPROGRESSIVE_V2: + printf("xf_SurfaceCommand_ProgressiveV2\n"); break; } @@ -240,6 +325,8 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill) RECTANGLE_16 invalidRect; xfContext* xfc = (xfContext*) context->custom; + printf("xf_SolidFill\n"); + b = solidFill->fillPixel.B; g = solidFill->fillPixel.G; r = solidFill->fillPixel.R; @@ -256,10 +343,10 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill) { rect = &(solidFill->fillRects[index]); - xrects->x = rect->left; - xrects->y = rect->top; - xrects->width = rect->right - rect->left + 1; - xrects->height = rect->bottom - rect->top + 1; + xrects[index].x = rect->left; + xrects[index].y = rect->top; + xrects[index].width = rect->right - rect->left + 1; + xrects[index].height = rect->bottom - rect->top + 1; invalidRect.left = rect->left; invalidRect.top = rect->top; @@ -277,6 +364,9 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill) free(xrects); + if (!xfc->inGfxFrame) + xf_SurfaceUpdate(xfc); + return 1; } diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 8f1bb2c8d..6f4394014 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -112,6 +112,7 @@ struct xf_context HGDI_DC hdc; BYTE* primary_buffer; REGION16 invalidRegion; + BOOL inGfxFrame; BOOL frame_begin; UINT16 frame_x1; From 6ad00125b48267ac8c5954f0cf5e8dbc13747f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 5 Jun 2014 13:13:47 -0400 Subject: [PATCH 18/50] xfreerdp: avoid using XCopyArea --- client/X11/xf_gfx.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 694eae6ea..63a8f8f26 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -87,9 +87,6 @@ int xf_SurfaceUpdate(xfContext* xfc) printf("xf_SurfaceUpdate: x: %d y: %d width: %d height: %d\n", extents->left, extents->top, width, height); - - XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, - extents->left, extents->top, width, height, extents->left, extents->top); } else { @@ -98,6 +95,8 @@ int xf_SurfaceUpdate(xfContext* xfc) region16_clear(&(xfc->invalidRegion)); + XSync(xfc->display, True); + return 1; } @@ -142,7 +141,7 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, (char*) data, cmd->width, cmd->height, 32, 0); - XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, cmd->left, cmd->top, cmd->width, cmd->height); + XPutImage(xfc->display, xfc->drawing, xfc->gc, image, 0, 0, cmd->left, cmd->top, cmd->width, cmd->height); XFree(image); @@ -220,7 +219,7 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, (char*) tile->data, 64, 64, 32, 0); - XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0, + XPutImage(xfc->display, xfc->drawable, xfc->gc, image, 0, 0, cmd->left + tile->x, cmd->top + tile->y, 64, 64); XFree(image); From 161e7b0026b9c45236441007ab33194779d10119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 5 Jun 2014 14:52:27 -0400 Subject: [PATCH 19/50] libfreerdp-codec: simplify zgfx segment processing --- client/X11/xf_gfx.c | 5 ++ include/freerdp/codec/zgfx.h | 19 +---- libfreerdp/codec/zgfx.c | 160 ++++++++++++++++++++--------------- 3 files changed, 96 insertions(+), 88 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 63a8f8f26..b068c5d54 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -306,11 +306,16 @@ int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODIN int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface) { + printf("xf_CreateSurface: surfaceId: %d width: %d height: %d format: 0x%02X\n", + createSurface->surfaceId, createSurface->width, createSurface->height, createSurface->pixelFormat); + return 1; } int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface) { + printf("xf_DeleteSurface: surfaceId: %d\n", deleteSurface->surfaceId); + return 1; } diff --git a/include/freerdp/codec/zgfx.h b/include/freerdp/codec/zgfx.h index e7e080f38..eb6ef7bed 100644 --- a/include/freerdp/codec/zgfx.h +++ b/include/freerdp/codec/zgfx.h @@ -28,24 +28,6 @@ #define ZGFX_SEGMENTED_SINGLE 0xE0 #define ZGFX_SEGMENTED_MULTIPART 0xE1 -#pragma pack(push,1) - -typedef struct -{ - BYTE descriptor; - UINT16 segmentCount; - UINT32 uncompressedSize; - // RDP_DATA_SEGMENT first; -} RDP_SEGMENTED_DATA; - -typedef struct -{ - UINT32 size; - // BYTE data[size]; -} RDP_DATA_SEGMENT; - -#pragma pack(pop) - struct _ZGFX_CONTEXT { BOOL Compressor; @@ -62,6 +44,7 @@ struct _ZGFX_CONTEXT BYTE HistoryBuffer[2500000]; UINT32 HistoryIndex; + UINT32 HistoryBufferSize; }; typedef struct _ZGFX_CONTEXT ZGFX_CONTEXT; diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c index e0e2de0ca..e60eb1e81 100644 --- a/libfreerdp/codec/zgfx.c +++ b/libfreerdp/codec/zgfx.c @@ -92,9 +92,7 @@ UINT32 zgfx_GetBits(ZGFX_CONTEXT* zgfx, UINT32 bitCount) zgfx->BitsCurrent <<= 8; if (zgfx->pbInputCurrent < zgfx->pbInputEnd) - { zgfx->BitsCurrent += *(zgfx->pbInputCurrent)++; - } zgfx->cBitsCurrent += 8; } @@ -122,7 +120,7 @@ int zgfx_OutputFromNotCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbRaw, int cbRaw) zgfx->HistoryBuffer[zgfx->HistoryIndex++] = c; - if (zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer)) + if (zgfx->HistoryIndex == zgfx->HistoryBufferSize) zgfx->HistoryIndex = 0; zgfx->OutputBuffer[zgfx->OutputCount++] = c; @@ -138,6 +136,7 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded int opIndex; int haveBits; int inPrefix; + UINT32 bits; UINT32 count; UINT32 distance; UINT32 prevIndex; @@ -160,7 +159,8 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded { while (haveBits < ZGFX_TOKEN_TABLE[opIndex].prefixLength) { - inPrefix = (inPrefix << 1) + zgfx_GetBits(zgfx, 1); + bits = zgfx_GetBits(zgfx, 1); + inPrefix = (inPrefix << 1) + bits; haveBits++; } @@ -168,19 +168,21 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded { if (ZGFX_TOKEN_TABLE[opIndex].tokenType == 0) { - c = (BYTE)(ZGFX_TOKEN_TABLE[opIndex].valueBase + - zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits)); + bits = zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); + c = (BYTE) (ZGFX_TOKEN_TABLE[opIndex].valueBase + bits); goto output_literal; } else { - distance = ZGFX_TOKEN_TABLE[opIndex].valueBase + - zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); + bits = zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); + distance = ZGFX_TOKEN_TABLE[opIndex].valueBase + bits; if (distance != 0) { - if (zgfx_GetBits(zgfx, 1) == 0) + bits = zgfx_GetBits(zgfx, 1); + + if (bits == 0) { count = 3; } @@ -189,20 +191,26 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded count = 4; extra = 2; - while (zgfx_GetBits(zgfx, 1) == 1) + bits = zgfx_GetBits(zgfx, 1); + + while (bits == 1) { count *= 2; extra++; + + bits = zgfx_GetBits(zgfx, 1); } - count += zgfx_GetBits(zgfx, extra); + bits = zgfx_GetBits(zgfx, extra); + count += bits; } goto output_match; } else { - count = zgfx_GetBits(zgfx, 15); + bits = zgfx_GetBits(zgfx, 15); + count = bits; zgfx->cBitsRemaining -= zgfx->cBitsCurrent; zgfx->cBitsCurrent = 0; @@ -216,30 +224,28 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded break; output_literal: - zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; - if (++zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer)) + if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) zgfx->HistoryIndex = 0; zgfx->OutputBuffer[zgfx->OutputCount++] = c; continue; output_match: - - prevIndex = zgfx->HistoryIndex + sizeof(zgfx->HistoryBuffer) - distance; - prevIndex = prevIndex % sizeof(zgfx->HistoryBuffer); + prevIndex = zgfx->HistoryIndex + zgfx->HistoryBufferSize - distance; + prevIndex = prevIndex % zgfx->HistoryBufferSize; while (count--) { c = zgfx->HistoryBuffer[prevIndex]; - if (++prevIndex == sizeof(zgfx->HistoryBuffer)) + if (++prevIndex == zgfx->HistoryBufferSize) prevIndex = 0; zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; - if (++zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer)) + if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) zgfx->HistoryIndex = 0; zgfx->OutputBuffer[zgfx->OutputCount] = c; @@ -255,7 +261,7 @@ output_unencoded: zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; - if (++zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer)) + if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) zgfx->HistoryIndex = 0; zgfx->OutputBuffer[zgfx->OutputCount] = c; @@ -267,71 +273,83 @@ output_unencoded: return 1; } -int zgfx_OutputFromSegment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, int cbSegment) +int zgfx_OutputFromSegment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegment) { int status; + BYTE header; - if (pbSegment[0] & PACKET_COMPRESSED) - status = zgfx_OutputFromCompressed(zgfx, pbSegment + 1, cbSegment - 1); + if (cbSegment < 1) + return -1; + + header = pbSegment[0]; + + if (header & PACKET_COMPRESSED) + { + status = zgfx_OutputFromCompressed(zgfx, &pbSegment[1], cbSegment - 1); + } else - status = zgfx_OutputFromNotCompressed(zgfx, pbSegment + 1, cbSegment - 1); + { + status = zgfx_OutputFromNotCompressed(zgfx, &pbSegment[1], cbSegment - 1); + } return status; } -int zgfx_Decompress_Internal(ZGFX_CONTEXT* zgfx, BYTE* pbInput, int cbInput, BYTE** ppbOutput, int* pcbOutput) -{ - int status; - - RDP_SEGMENTED_DATA* pSegmentedData = (RDP_SEGMENTED_DATA*) pbInput; - - if (pSegmentedData->descriptor == ZGFX_SEGMENTED_SINGLE) - { - status = zgfx_OutputFromSegment(zgfx, pbInput + 1, cbInput - 1); - - *ppbOutput = (BYTE*) malloc(zgfx->OutputCount); - *pcbOutput = zgfx->OutputCount; - CopyMemory(*ppbOutput, zgfx->OutputBuffer, zgfx->OutputCount); - } - else if (pSegmentedData->descriptor == ZGFX_SEGMENTED_MULTIPART) - { - UINT16 segmentNumber; - UINT32 segmentOffset = sizeof(RDP_SEGMENTED_DATA); - BYTE* pConcatenated = (BYTE*) malloc(pSegmentedData->uncompressedSize); - - *ppbOutput = pConcatenated; - *pcbOutput = pSegmentedData->uncompressedSize; - - for (segmentNumber = 0; segmentNumber < pSegmentedData->segmentCount; segmentNumber++) - { - RDP_DATA_SEGMENT* pSegment = (RDP_DATA_SEGMENT*) (pbInput + segmentOffset); - - status = zgfx_OutputFromSegment(zgfx, pbInput + segmentOffset + sizeof(RDP_DATA_SEGMENT), pSegment->size); - - segmentOffset += sizeof(RDP_DATA_SEGMENT) + pSegment->size; - CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount); - pConcatenated += zgfx->OutputCount; - } - } - - return 1; -} - int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) { - int status = 0; - int cbOutput = 0; - BYTE* pbOutput = NULL; + int status; + BYTE descriptor; - status = zgfx_Decompress_Internal(zgfx, pSrcData, SrcSize, &pbOutput, &cbOutput); + if (SrcSize < 1) + return -1; - if (status >= 0) + descriptor = pSrcData[0]; /* descriptor (1 byte) */ + + if (descriptor == ZGFX_SEGMENTED_SINGLE) { - *ppDstData = pbOutput; - *pDstSize = (UINT32) cbOutput; + status = zgfx_OutputFromSegment(zgfx, &pSrcData[1], SrcSize - 1); + + *ppDstData = (BYTE*) malloc(zgfx->OutputCount); + *pDstSize = zgfx->OutputCount; + + CopyMemory(*ppDstData, zgfx->OutputBuffer, zgfx->OutputCount); + } + else if (descriptor == ZGFX_SEGMENTED_MULTIPART) + { + UINT32 segmentSize; + UINT16 segmentNumber; + UINT16 segmentCount; + UINT32 segmentOffset; + UINT32 uncompressedSize; + BYTE* pConcatenated; + + segmentOffset = 7; + segmentCount = *((UINT16*) &pSrcData[1]); /* segmentCount (2 bytes) */ + uncompressedSize = *((UINT32*) &pSrcData[3]); /* uncompressedSize (4 bytes) */ + + pConcatenated = (BYTE*) malloc(uncompressedSize); + + *ppDstData = pConcatenated; + *pDstSize = uncompressedSize; + + for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++) + { + segmentSize = *((UINT32*) &pSrcData[segmentOffset]); /* segmentSize (4 bytes) */ + segmentOffset += 4; + + status = zgfx_OutputFromSegment(zgfx, &pSrcData[segmentOffset], segmentSize); + segmentOffset += segmentSize; + + CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount); + pConcatenated += zgfx->OutputCount; + } + } + else + { + return -1; } - return status; + return 1; } int zgfx_compress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags) @@ -354,6 +372,8 @@ ZGFX_CONTEXT* zgfx_context_new(BOOL Compressor) { zgfx->Compressor = Compressor; + zgfx->HistoryBufferSize = sizeof(zgfx->HistoryBuffer); + zgfx_context_reset(zgfx, FALSE); } From 4e86211f3411b965d01b0cf733e02aab4056f61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 5 Jun 2014 15:24:36 -0400 Subject: [PATCH 20/50] libfreerdp-codec: refactor zgfx --- libfreerdp/codec/zgfx.c | 172 +++++++++++++++++----------------------- 1 file changed, 72 insertions(+), 100 deletions(-) diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c index e60eb1e81..178dc970f 100644 --- a/libfreerdp/codec/zgfx.c +++ b/libfreerdp/codec/zgfx.c @@ -107,46 +107,51 @@ UINT32 zgfx_GetBits(ZGFX_CONTEXT* zgfx, UINT32 bitCount) return result; } -int zgfx_OutputFromNotCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbRaw, int cbRaw) -{ - BYTE c; - int iRaw; - - zgfx->OutputCount = 0; - - for (iRaw = 0; iRaw < cbRaw; iRaw++) - { - c = pbRaw[iRaw]; - - zgfx->HistoryBuffer[zgfx->HistoryIndex++] = c; - - if (zgfx->HistoryIndex == zgfx->HistoryBufferSize) - zgfx->HistoryIndex = 0; - - zgfx->OutputBuffer[zgfx->OutputCount++] = c; - } - - return 1; -} - -int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded) +int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegment) { BYTE c; + BYTE flags; int extra; int opIndex; int haveBits; int inPrefix; + UINT32 raw; UINT32 bits; UINT32 count; UINT32 distance; UINT32 prevIndex; + if (cbSegment < 1) + return -1; + + flags = pbSegment[0]; /* header (1 byte) */ + + pbSegment++; + cbSegment--; + zgfx->OutputCount = 0; - zgfx->pbInputCurrent = pbEncoded; - zgfx->pbInputEnd = pbEncoded + cbEncoded - 1; + if (!(flags & PACKET_COMPRESSED)) + { + for (raw = 0; raw < cbSegment; raw++) + { + c = pbSegment[raw]; - zgfx->cBitsRemaining = 8 * (cbEncoded - 1) - *zgfx->pbInputEnd; + zgfx->HistoryBuffer[zgfx->HistoryIndex++] = c; + + if (zgfx->HistoryIndex == zgfx->HistoryBufferSize) + zgfx->HistoryIndex = 0; + + zgfx->OutputBuffer[zgfx->OutputCount++] = c; + } + + return 1; + } + + zgfx->pbInputCurrent = pbSegment; + zgfx->pbInputEnd = &pbSegment[cbSegment - 1]; + + zgfx->cBitsRemaining = 8 * (cbSegment - 1) - *zgfx->pbInputEnd; zgfx->cBitsCurrent = 0; zgfx->BitsCurrent = 0; @@ -171,7 +176,12 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded bits = zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); c = (BYTE) (ZGFX_TOKEN_TABLE[opIndex].valueBase + bits); - goto output_literal; + zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; + + if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) + zgfx->HistoryIndex = 0; + + zgfx->OutputBuffer[zgfx->OutputCount++] = c; } else { @@ -205,7 +215,24 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded count += bits; } - goto output_match; + prevIndex = zgfx->HistoryIndex + zgfx->HistoryBufferSize - distance; + prevIndex = prevIndex % zgfx->HistoryBufferSize; + + while (count--) + { + c = zgfx->HistoryBuffer[prevIndex]; + + if (++prevIndex == zgfx->HistoryBufferSize) + prevIndex = 0; + + zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; + + if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) + zgfx->HistoryIndex = 0; + + zgfx->OutputBuffer[zgfx->OutputCount] = c; + ++zgfx->OutputCount; + } } else { @@ -216,85 +243,30 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded zgfx->cBitsCurrent = 0; zgfx->BitsCurrent = 0; - goto output_unencoded; + while (count--) + { + c = *zgfx->pbInputCurrent++; + zgfx->cBitsRemaining -= 8; + + zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; + + if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) + zgfx->HistoryIndex = 0; + + zgfx->OutputBuffer[zgfx->OutputCount] = c; + ++zgfx->OutputCount; + } } } + + break; } } - break; - -output_literal: - zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; - - if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) - zgfx->HistoryIndex = 0; - - zgfx->OutputBuffer[zgfx->OutputCount++] = c; - continue; - -output_match: - prevIndex = zgfx->HistoryIndex + zgfx->HistoryBufferSize - distance; - prevIndex = prevIndex % zgfx->HistoryBufferSize; - - while (count--) - { - c = zgfx->HistoryBuffer[prevIndex]; - - if (++prevIndex == zgfx->HistoryBufferSize) - prevIndex = 0; - - zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; - - if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) - zgfx->HistoryIndex = 0; - - zgfx->OutputBuffer[zgfx->OutputCount] = c; - ++zgfx->OutputCount; - } - continue; - -output_unencoded: - while (count--) - { - c = *zgfx->pbInputCurrent++; - zgfx->cBitsRemaining -= 8; - - zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; - - if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) - zgfx->HistoryIndex = 0; - - zgfx->OutputBuffer[zgfx->OutputCount] = c; - ++zgfx->OutputCount; - } - continue; } return 1; } -int zgfx_OutputFromSegment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegment) -{ - int status; - BYTE header; - - if (cbSegment < 1) - return -1; - - header = pbSegment[0]; - - if (header & PACKET_COMPRESSED) - { - status = zgfx_OutputFromCompressed(zgfx, &pbSegment[1], cbSegment - 1); - } - else - { - status = zgfx_OutputFromNotCompressed(zgfx, &pbSegment[1], cbSegment - 1); - } - - return status; -} - int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) { int status; @@ -307,7 +279,7 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** p if (descriptor == ZGFX_SEGMENTED_SINGLE) { - status = zgfx_OutputFromSegment(zgfx, &pSrcData[1], SrcSize - 1); + status = zgfx_decompress_segment(zgfx, &pSrcData[1], SrcSize - 1); *ppDstData = (BYTE*) malloc(zgfx->OutputCount); *pDstSize = zgfx->OutputCount; @@ -337,7 +309,7 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** p segmentSize = *((UINT32*) &pSrcData[segmentOffset]); /* segmentSize (4 bytes) */ segmentOffset += 4; - status = zgfx_OutputFromSegment(zgfx, &pSrcData[segmentOffset], segmentSize); + status = zgfx_decompress_segment(zgfx, &pSrcData[segmentOffset], segmentSize); segmentOffset += segmentSize; CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount); From b4ba2c7a3848d844330d5b7b8811403ba60c0c25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 5 Jun 2014 15:41:42 -0400 Subject: [PATCH 21/50] libfreerdp-codec: optimize zgfx bitstream --- include/freerdp/codec/zgfx.h | 1 + libfreerdp/codec/zgfx.c | 66 +++++++++++++++--------------------- 2 files changed, 28 insertions(+), 39 deletions(-) diff --git a/include/freerdp/codec/zgfx.h b/include/freerdp/codec/zgfx.h index eb6ef7bed..6fd35825a 100644 --- a/include/freerdp/codec/zgfx.h +++ b/include/freerdp/codec/zgfx.h @@ -35,6 +35,7 @@ struct _ZGFX_CONTEXT BYTE* pbInputCurrent; BYTE* pbInputEnd; + UINT32 bits; UINT32 cBitsRemaining; UINT32 BitsCurrent; UINT32 cBitsCurrent; diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c index 178dc970f..61f43bbf7 100644 --- a/libfreerdp/codec/zgfx.c +++ b/libfreerdp/codec/zgfx.c @@ -83,29 +83,17 @@ static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] = { 0 } }; -UINT32 zgfx_GetBits(ZGFX_CONTEXT* zgfx, UINT32 bitCount) -{ - UINT32 result; - - while (zgfx->cBitsCurrent < bitCount) - { - zgfx->BitsCurrent <<= 8; - - if (zgfx->pbInputCurrent < zgfx->pbInputEnd) - zgfx->BitsCurrent += *(zgfx->pbInputCurrent)++; - - zgfx->cBitsCurrent += 8; - } - - zgfx->cBitsRemaining -= bitCount; - zgfx->cBitsCurrent -= bitCount; - - result = zgfx->BitsCurrent >> zgfx->cBitsCurrent; - - zgfx->BitsCurrent &= ((1 << zgfx->cBitsCurrent) - 1); - - return result; -} +#define zgfx_GetBits(_zgfx, _nbits) \ + while (_zgfx->cBitsCurrent < _nbits) { \ + _zgfx->BitsCurrent <<= 8; \ + if (_zgfx->pbInputCurrent < _zgfx->pbInputEnd) \ + _zgfx->BitsCurrent += *(_zgfx->pbInputCurrent)++; \ + _zgfx->cBitsCurrent += 8; \ + } \ + _zgfx->cBitsRemaining -= _nbits; \ + _zgfx->cBitsCurrent -= _nbits; \ + _zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \ + _zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1); int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegment) { @@ -116,7 +104,6 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen int haveBits; int inPrefix; UINT32 raw; - UINT32 bits; UINT32 count; UINT32 distance; UINT32 prevIndex; @@ -151,6 +138,7 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen zgfx->pbInputCurrent = pbSegment; zgfx->pbInputEnd = &pbSegment[cbSegment - 1]; + /* NumberOfBitsToDecode = ((NumberOfBytesToDecode - 1) * 8) - ValueOfLastByte */ zgfx->cBitsRemaining = 8 * (cbSegment - 1) - *zgfx->pbInputEnd; zgfx->cBitsCurrent = 0; zgfx->BitsCurrent = 0; @@ -164,8 +152,8 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen { while (haveBits < ZGFX_TOKEN_TABLE[opIndex].prefixLength) { - bits = zgfx_GetBits(zgfx, 1); - inPrefix = (inPrefix << 1) + bits; + zgfx_GetBits(zgfx, 1); + inPrefix = (inPrefix << 1) + zgfx->bits; haveBits++; } @@ -173,8 +161,8 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen { if (ZGFX_TOKEN_TABLE[opIndex].tokenType == 0) { - bits = zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); - c = (BYTE) (ZGFX_TOKEN_TABLE[opIndex].valueBase + bits); + zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); + c = (BYTE) (ZGFX_TOKEN_TABLE[opIndex].valueBase + zgfx->bits); zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; @@ -185,14 +173,14 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen } else { - bits = zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); - distance = ZGFX_TOKEN_TABLE[opIndex].valueBase + bits; + zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); + distance = ZGFX_TOKEN_TABLE[opIndex].valueBase + zgfx->bits; if (distance != 0) { - bits = zgfx_GetBits(zgfx, 1); + zgfx_GetBits(zgfx, 1); - if (bits == 0) + if (zgfx->bits == 0) { count = 3; } @@ -201,18 +189,18 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen count = 4; extra = 2; - bits = zgfx_GetBits(zgfx, 1); + zgfx_GetBits(zgfx, 1); - while (bits == 1) + while (zgfx->bits == 1) { count *= 2; extra++; - bits = zgfx_GetBits(zgfx, 1); + zgfx_GetBits(zgfx, 1); } - bits = zgfx_GetBits(zgfx, extra); - count += bits; + zgfx_GetBits(zgfx, extra); + count += zgfx->bits; } prevIndex = zgfx->HistoryIndex + zgfx->HistoryBufferSize - distance; @@ -236,8 +224,8 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen } else { - bits = zgfx_GetBits(zgfx, 15); - count = bits; + zgfx_GetBits(zgfx, 15); + count = zgfx->bits; zgfx->cBitsRemaining -= zgfx->cBitsCurrent; zgfx->cBitsCurrent = 0; From 77c3de47d7011e2a150bd1e67b244430b9f107fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 5 Jun 2014 18:09:37 -0400 Subject: [PATCH 22/50] libfreerdp-codec: optimize zgfx history buffer wrap around --- libfreerdp/codec/zgfx.c | 153 +++++++++++++++++++++++++++++----------- 1 file changed, 110 insertions(+), 43 deletions(-) diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c index 61f43bbf7..5129296b7 100644 --- a/libfreerdp/codec/zgfx.c +++ b/libfreerdp/codec/zgfx.c @@ -27,6 +27,16 @@ #include +/** + * RDP8 Compressor Limits: + * + * Maximum number of uncompressed bytes in a single segment: 65535 + * Maximum match distance / minimum history size: 2500000 bytes. + * Maximum number of segments: 65535 + * Maximum expansion of a segment (when compressed size exceeds uncompressed): 1000 bytes + * Minimum match length: 3 bytes + */ + struct _ZGFX_TOKEN { int prefixLength; @@ -95,6 +105,89 @@ static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] = _zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \ _zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1); +void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, BYTE* src, UINT32 count) +{ + UINT32 front; + UINT32 residue; + + if (count <= 0) + return; + + if (count > zgfx->HistoryBufferSize) + { + residue = count - zgfx->HistoryBufferSize; + count = zgfx->HistoryBufferSize; + src += residue; + + zgfx->HistoryIndex = (zgfx->HistoryIndex + residue) % zgfx->HistoryBufferSize; + } + + if (zgfx->HistoryIndex + count <= zgfx->HistoryBufferSize) + { + CopyMemory(&(zgfx->HistoryBuffer[zgfx->HistoryIndex]), src, count); + + if ((zgfx->HistoryIndex += count) == zgfx->HistoryBufferSize) + zgfx->HistoryIndex = 0; + } + else + { + front = zgfx->HistoryBufferSize - zgfx->HistoryIndex; + CopyMemory(&(zgfx->HistoryBuffer[zgfx->HistoryIndex]), src, front); + CopyMemory(zgfx->HistoryBuffer, &src[front], count - front); + zgfx->HistoryIndex = count - front; + } +} + +void zgfx_history_buffer_ring_read(ZGFX_CONTEXT* zgfx, int offset, BYTE* dst, UINT32 count) +{ + UINT32 front; + UINT32 index; + UINT32 bytes; + UINT32 valid; + UINT32 bytesLeft; + BYTE* dptr = dst; + BYTE* origDst = dst; + + if (count <= 0) + return; + + bytesLeft = count; + + index = (zgfx->HistoryIndex + zgfx->HistoryBufferSize - offset) % zgfx->HistoryBufferSize; + + bytes = MIN(bytesLeft, offset); + + if ((index + bytes) <= zgfx->HistoryBufferSize) + { + CopyMemory(dptr, &(zgfx->HistoryBuffer[index]), bytes); + } + else + { + front = zgfx->HistoryBufferSize - index; + CopyMemory(dptr, &(zgfx->HistoryBuffer[index]), front); + CopyMemory(&dptr[front], zgfx->HistoryBuffer, bytes - front); + } + + if ((bytesLeft -= bytes) == 0) + return; + + dptr += bytes; + valid = bytes; + + do + { + bytes = valid; + + if (bytes > bytesLeft) + bytes = bytesLeft; + + CopyMemory(dptr, origDst, bytes); + dptr += bytes; + valid <<= 1; + } + while ((bytesLeft -= bytes) > 0); +} + int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegment) { BYTE c; @@ -103,10 +196,8 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen int opIndex; int haveBits; int inPrefix; - UINT32 raw; UINT32 count; UINT32 distance; - UINT32 prevIndex; if (cbSegment < 1) return -1; @@ -120,17 +211,9 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen if (!(flags & PACKET_COMPRESSED)) { - for (raw = 0; raw < cbSegment; raw++) - { - c = pbSegment[raw]; - - zgfx->HistoryBuffer[zgfx->HistoryIndex++] = c; - - if (zgfx->HistoryIndex == zgfx->HistoryBufferSize) - zgfx->HistoryIndex = 0; - - zgfx->OutputBuffer[zgfx->OutputCount++] = c; - } + zgfx_history_buffer_ring_write(zgfx, pbSegment, cbSegment); + CopyMemory(zgfx->OutputBuffer, pbSegment, cbSegment); + zgfx->OutputCount = cbSegment; return 1; } @@ -161,6 +244,8 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen { if (ZGFX_TOKEN_TABLE[opIndex].tokenType == 0) { + /* Literal */ + zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); c = (BYTE) (ZGFX_TOKEN_TABLE[opIndex].valueBase + zgfx->bits); @@ -178,6 +263,8 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen if (distance != 0) { + /* Match */ + zgfx_GetBits(zgfx, 1); if (zgfx->bits == 0) @@ -203,27 +290,14 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen count += zgfx->bits; } - prevIndex = zgfx->HistoryIndex + zgfx->HistoryBufferSize - distance; - prevIndex = prevIndex % zgfx->HistoryBufferSize; - - while (count--) - { - c = zgfx->HistoryBuffer[prevIndex]; - - if (++prevIndex == zgfx->HistoryBufferSize) - prevIndex = 0; - - zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; - - if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) - zgfx->HistoryIndex = 0; - - zgfx->OutputBuffer[zgfx->OutputCount] = c; - ++zgfx->OutputCount; - } + zgfx_history_buffer_ring_read(zgfx, distance, &(zgfx->OutputBuffer[zgfx->OutputCount]), count); + zgfx_history_buffer_ring_write(zgfx, &(zgfx->OutputBuffer[zgfx->OutputCount]), count); + zgfx->OutputCount += count; } else { + /* Unencoded */ + zgfx_GetBits(zgfx, 15); count = zgfx->bits; @@ -231,19 +305,12 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen zgfx->cBitsCurrent = 0; zgfx->BitsCurrent = 0; - while (count--) - { - c = *zgfx->pbInputCurrent++; - zgfx->cBitsRemaining -= 8; + CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent, count); + zgfx_history_buffer_ring_write(zgfx, zgfx->pbInputCurrent, count); - zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; - - if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) - zgfx->HistoryIndex = 0; - - zgfx->OutputBuffer[zgfx->OutputCount] = c; - ++zgfx->OutputCount; - } + zgfx->pbInputCurrent += count; + zgfx->cBitsRemaining -= (8 * count); + zgfx->OutputCount += count; } } From fb4fd9f5bb78ab6e798fd37ec53ec1c517536e01 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 11 Jun 2014 14:38:20 +0200 Subject: [PATCH 23/50] Added stream pool shrinking if large parts are unused. --- winpr/libwinpr/utils/collections/StreamPool.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/winpr/libwinpr/utils/collections/StreamPool.c b/winpr/libwinpr/utils/collections/StreamPool.c index 5dd0d852b..c95875fbe 100644 --- a/winpr/libwinpr/utils/collections/StreamPool.c +++ b/winpr/libwinpr/utils/collections/StreamPool.c @@ -182,6 +182,11 @@ void StreamPool_Return(wStreamPool* pool, wStream* s) pool->aCapacity *= 2; pool->aArray = (wStream**) realloc(pool->aArray, sizeof(wStream*) * pool->aCapacity); } + else if ((pool->aSize + 1) * 3 < pool->aCapacity) + { + pool->aCapacity /= 2; + pool->aArray = (wStream**) realloc(pool->aArray, sizeof(wStream*) * pool->aCapacity); + } pool->aArray[(pool->aSize)++] = s; StreamPool_RemoveUsed(pool, s); From 60b0d075e29d4bf48c89be6881ba1825fdf7aad8 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 11 Jun 2014 14:40:38 +0200 Subject: [PATCH 24/50] svc_plugin now uses reference counted StreamPool. Added termination function to clean up allocated resources. --- include/freerdp/utils/svc_plugin.h | 3 +++ libfreerdp/utils/svc_plugin.c | 13 +++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/freerdp/utils/svc_plugin.h b/include/freerdp/utils/svc_plugin.h index e4fff81be..6100c2cd7 100644 --- a/include/freerdp/utils/svc_plugin.h +++ b/include/freerdp/utils/svc_plugin.h @@ -55,6 +55,7 @@ struct rdp_svc_plugin void* InitHandle; DWORD OpenHandle; wMessagePipe* MsgPipe; + wStreamPool *pool; }; #ifdef __cplusplus @@ -62,6 +63,8 @@ extern "C" { #endif FREERDP_API void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints); +FREERDP_API void svc_plugin_terminate(rdpSvcPlugin* plugin); + FREERDP_API int svc_plugin_send(rdpSvcPlugin* plugin, wStream* data_out); FREERDP_API int svc_plugin_send_event(rdpSvcPlugin* plugin, wMessage* event); diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index 052e8957d..cb6018218 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -103,9 +103,9 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3 if (dataFlags & CHANNEL_FLAG_FIRST) { if (plugin->data_in != NULL) - Stream_Free(plugin->data_in, TRUE); + Stream_Release(plugin->data_in); - plugin->data_in = Stream_New(NULL, totalLength); + plugin->data_in = StreamPool_Take(plugin->pool, totalLength); } s = plugin->data_in; @@ -122,6 +122,7 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3 plugin->data_in = NULL; Stream_SealLength(s); Stream_SetPosition(s, 0); + Stream_AddRef(s); MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) s, NULL); } @@ -192,6 +193,7 @@ static void* svc_plugin_thread_func(void* arg) { data = (wStream*) message.wParam; IFCALL(plugin->receive_callback, plugin, data); + Stream_Release(data); } else if (message.id == 1) { @@ -296,10 +298,17 @@ void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints) plugin->channel_entry_points.pInterface = *(plugin->channel_entry_points.ppInterface); plugin->channel_entry_points.ppInterface = &(plugin->channel_entry_points.pInterface); plugin->started = CreateEvent(NULL,TRUE,FALSE,NULL); + plugin->pool = StreamPool_New(FALSE, 10); svc_plugin_add_init_handle_data(plugin->InitHandle, plugin); } +void svc_plugin_terminate(rdpSvcPlugin* plugin) +{ + StreamPool_Free(plugin->pool); + CloseHandle(plugin->started); +} + int svc_plugin_send(rdpSvcPlugin* plugin, wStream* data_out) { UINT32 status = 0; From 49f360521c8faccd5c4005a104cee0270ac66d01 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 11 Jun 2014 14:41:31 +0200 Subject: [PATCH 25/50] OnDataReceived function now uses a reference counted stream as argument. --- include/freerdp/dvc.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/freerdp/dvc.h b/include/freerdp/dvc.h index a2350bfe8..2a9596b7e 100644 --- a/include/freerdp/dvc.h +++ b/include/freerdp/dvc.h @@ -138,8 +138,7 @@ struct _IWTSVirtualChannelCallback { /* Notifies the user about data that is being received. */ int (*OnDataReceived) (IWTSVirtualChannelCallback* pChannelCallback, - UINT32 cbSize, - BYTE* pBuffer); + wStream *data); /* Notifies the user that the channel has been closed. */ int (*OnClose) (IWTSVirtualChannelCallback* pChannelCallback); }; From 15ce8c05521f2972f37a3eb7b86edb4d2d126da5 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 11 Jun 2014 14:42:32 +0200 Subject: [PATCH 26/50] Updated plugins to use new svc_plugin and OnDataReceived API. --- channels/audin/client/audin_main.c | 17 ++++++----------- channels/cliprdr/client/cliprdr_main.c | 3 +-- channels/disp/client/disp_main.c | 9 ++------- channels/drdynvc/client/drdynvc_main.c | 12 ++++-------- channels/drdynvc/client/dvcman.c | 25 +++++++++++++------------ channels/drdynvc/client/dvcman.h | 3 ++- channels/echo/client/echo_main.c | 4 +++- channels/rail/client/rail_main.c | 5 ++--- channels/rdpei/client/rdpei_main.c | 9 ++------- channels/rdpgfx/client/rdpgfx_main.c | 9 ++------- channels/sample/client/sample_main.c | 7 ++----- channels/tsmf/client/tsmf_main.c | 7 +++---- libfreerdp/core/freerdp.c | 2 -- 13 files changed, 42 insertions(+), 70 deletions(-) diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index 18632b759..38e7625bd 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -312,34 +312,31 @@ static int audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallb return 0; } -static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer) +static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { int error; - wStream* s; BYTE MessageId; - s = Stream_New(pBuffer, cbSize); - - Stream_Read_UINT8(s, MessageId); + Stream_Read_UINT8(data, MessageId); DEBUG_DVC("MessageId=0x%x", MessageId); switch (MessageId) { case MSG_SNDIN_VERSION: - error = audin_process_version(pChannelCallback, s); + error = audin_process_version(pChannelCallback, data); break; case MSG_SNDIN_FORMATS: - error = audin_process_formats(pChannelCallback, s); + error = audin_process_formats(pChannelCallback, data); break; case MSG_SNDIN_OPEN: - error = audin_process_open(pChannelCallback, s); + error = audin_process_open(pChannelCallback, data); break; case MSG_SNDIN_FORMATCHANGE: - error = audin_process_format_change(pChannelCallback, s); + error = audin_process_format_change(pChannelCallback, data); break; default: @@ -348,8 +345,6 @@ static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, break; } - Stream_Free(s, FALSE); - return error; } diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 07b03c19c..928d74750 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -382,8 +382,6 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s) DEBUG_WARN("unknown msgType %d", msgType); break; } - - Stream_Free(s, TRUE); } static void cliprdr_process_filecontents_request_event(cliprdrPlugin* plugin, RDP_CB_FILECONTENTS_REQUEST_EVENT * event) @@ -506,6 +504,7 @@ static void cliprdr_process_event(rdpSvcPlugin* plugin, wMessage* event) static void cliprdr_process_terminate(rdpSvcPlugin* plugin) { + svc_plugin_terminate(plugin); free(plugin); } diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c index 343c9e3db..2a6d7fca1 100644 --- a/channels/disp/client/disp_main.c +++ b/channels/disp/client/disp_main.c @@ -201,17 +201,12 @@ int disp_recv_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s) return 0; } -static int disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer) +static int disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { - wStream* s; int status = 0; DISP_CHANNEL_CALLBACK* callback = (DISP_CHANNEL_CALLBACK*) pChannelCallback; - s = Stream_New(pBuffer, cbSize); - - status = disp_recv_pdu(callback, s); - - Stream_Free(s, FALSE); + status = disp_recv_pdu(callback, data); return status; } diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index d10f9a751..42e923c54 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -266,8 +266,7 @@ static int drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, int cbChId if (status) return status; - return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, - Stream_Pointer(s), Stream_GetRemainingLength(s)); + return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s); } static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) @@ -277,8 +276,7 @@ static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStr ChannelId = drdynvc_read_variable_uint(s, cbChId); DEBUG_DVC("ChannelId=%d", ChannelId); - return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, - Stream_Pointer(s), Stream_GetRemainingLength(s)); + return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s); } static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) @@ -350,8 +348,6 @@ static void drdynvc_process_receive(rdpSvcPlugin* plugin, wStream* s) DEBUG_WARN("unknown drdynvc cmd 0x%x", Cmd); break; } - - Stream_Free(s, TRUE); } static void drdynvc_process_connect(rdpSvcPlugin* plugin) @@ -391,6 +387,7 @@ static void drdynvc_process_terminate(rdpSvcPlugin* plugin) if (drdynvc->channel_mgr) dvcman_free(drdynvc->channel_mgr); + svc_plugin_terminate(plugin); free(drdynvc); } @@ -413,8 +410,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) DrdynvcClientContext* context; CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; - _p = (drdynvcPlugin*) malloc(sizeof(drdynvcPlugin)); - ZeroMemory(_p, sizeof(drdynvcPlugin)); + _p = (drdynvcPlugin*) calloc(1, sizeof(drdynvcPlugin)); _p->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED | diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c index da170160d..75a3fdd18 100644 --- a/channels/drdynvc/client/dvcman.c +++ b/channels/drdynvc/client/dvcman.c @@ -195,8 +195,7 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) { DVCMAN* dvcman; - dvcman = (DVCMAN*) malloc(sizeof(DVCMAN)); - ZeroMemory(dvcman, sizeof(DVCMAN)); + dvcman = (DVCMAN*) calloc(1, sizeof(DVCMAN)); dvcman->iface.CreateListener = dvcman_create_listener; dvcman->iface.PushEvent = dvcman_push_event; @@ -278,6 +277,7 @@ void dvcman_free(IWTSVirtualChannelManager* pChannelMgr) pPlugin->Terminated(pPlugin); } + StreamPool_Free(dvcman->pool); free(dvcman); } @@ -402,7 +402,7 @@ int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelI if (channel->dvc_data) { - Stream_Free(channel->dvc_data, TRUE); + Stream_Release(channel->dvc_data); channel->dvc_data = NULL; } @@ -435,17 +435,19 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UI } if (channel->dvc_data) - Stream_Free(channel->dvc_data, TRUE); + Stream_Release(channel->dvc_data); - channel->dvc_data = Stream_New(NULL, length); + channel->dvc_data = StreamPool_Take(channel->dvcman->pool, length); + Stream_AddRef(channel->dvc_data); return 0; } -int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, BYTE* data, UINT32 data_size) +int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream *data) { int error = 0; DVCMAN_CHANNEL* channel; + UINT32 data_size = Stream_GetRemainingLength(data); channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); @@ -461,24 +463,23 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 C if (Stream_GetPosition(channel->dvc_data) + data_size > (UINT32) Stream_Capacity(channel->dvc_data)) { DEBUG_WARN("data exceeding declared length!"); - Stream_Free(channel->dvc_data, TRUE); + Stream_Release(channel->dvc_data); channel->dvc_data = NULL; return 1; } - Stream_Write(channel->dvc_data, data, data_size); + Stream_Write(channel->dvc_data, Stream_Pointer(data), data_size); if (((size_t) Stream_GetPosition(channel->dvc_data)) >= Stream_Capacity(channel->dvc_data)) { - error = channel->channel_callback->OnDataReceived(channel->channel_callback, - Stream_Capacity(channel->dvc_data), Stream_Buffer(channel->dvc_data)); - Stream_Free(channel->dvc_data, TRUE); + error = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data); + Stream_Release(channel->dvc_data); channel->dvc_data = NULL; } } else { - error = channel->channel_callback->OnDataReceived(channel->channel_callback, data_size, data); + error = channel->channel_callback->OnDataReceived(channel->channel_callback, data); } return error; diff --git a/channels/drdynvc/client/dvcman.h b/channels/drdynvc/client/dvcman.h index ca886f3af..8c233598f 100644 --- a/channels/drdynvc/client/dvcman.h +++ b/channels/drdynvc/client/dvcman.h @@ -43,6 +43,7 @@ struct _DVCMAN int num_listeners; wArrayList* channels; + wStreamPool* pool; }; typedef struct _DVCMAN DVCMAN; @@ -89,7 +90,7 @@ int dvcman_init(IWTSVirtualChannelManager* pChannelMgr); int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName); int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId); int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length); -int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, BYTE* data, UINT32 data_size); +int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream *data); void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName); diff --git a/channels/echo/client/echo_main.c b/channels/echo/client/echo_main.c index 595844918..ef381e21a 100644 --- a/channels/echo/client/echo_main.c +++ b/channels/echo/client/echo_main.c @@ -61,10 +61,12 @@ struct _ECHO_PLUGIN ECHO_LISTENER_CALLBACK* listener_callback; }; -static int echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer) +static int echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { int error; ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*) pChannelCallback; + BYTE *pBuffer = Stream_Pointer(data); + UINT32 cbSize = Stream_GetRemainingLength(data); #ifdef WITH_DEBUG_DVC int i = 0; diff --git a/channels/rail/client/rail_main.c b/channels/rail/client/rail_main.c index 99934bbfd..45a4f59a6 100644 --- a/channels/rail/client/rail_main.c +++ b/channels/rail/client/rail_main.c @@ -95,13 +95,13 @@ static void rail_process_terminate(rdpSvcPlugin* plugin) railPlugin* rail = (railPlugin*) plugin; WLog_Print(rail->log, WLOG_DEBUG, "Terminate"); + svc_plugin_terminate(plugin); } static void rail_process_receive(rdpSvcPlugin* plugin, wStream* s) { railPlugin* rail = (railPlugin*) plugin; rail_order_recv(rail, s); - Stream_Free(s, TRUE); } static void rail_process_addin_args(rdpRailOrder* railOrder, rdpSettings* settings) @@ -507,8 +507,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) RailClientContext* context; CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; - rail = (railPlugin*) malloc(sizeof(railPlugin)); - ZeroMemory(rail, sizeof(railPlugin)); + rail = (railPlugin*) calloc(1, sizeof(railPlugin)); rail->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED | diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index 9eff40876..cd837669f 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -434,17 +434,12 @@ int rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) return 0; } -static int rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer) +static int rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { - wStream* s; int status = 0; RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback; - s = Stream_New(pBuffer, cbSize); - - status = rdpei_recv_pdu(callback, s); - - Stream_Free(s, FALSE); + status = rdpei_recv_pdu(callback, data); return status; } diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 8c6d52b84..253f4e215 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -75,19 +75,14 @@ int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) return 0; } -static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer) +static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { - wStream* s; int status = 0; RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; fprintf(stderr, "RdpGfxOnDataReceived\n"); - s = Stream_New(pBuffer, cbSize); - - status = rdpgfx_recv_pdu(callback, s); - - Stream_Free(s, FALSE); + status = rdpgfx_recv_pdu(callback, data); return status; } diff --git a/channels/sample/client/sample_main.c b/channels/sample/client/sample_main.c index 3326b7168..c9e0b6780 100644 --- a/channels/sample/client/sample_main.c +++ b/channels/sample/client/sample_main.c @@ -78,8 +78,6 @@ static void sample_process_receive(rdpSvcPlugin* plugin, wStream* data_in) svc_plugin_send(plugin, data_out); } - - Stream_Free(data_in, TRUE); } static void sample_process_connect(rdpSvcPlugin* plugin) @@ -113,7 +111,7 @@ static void sample_process_terminate(rdpSvcPlugin* plugin) return; /* put your cleanup here */ - + svc_plugin_terminate(plugin); free(plugin); } @@ -123,8 +121,7 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { samplePlugin* _p; - _p = (samplePlugin*) malloc(sizeof(samplePlugin)); - ZeroMemory(_p, sizeof(samplePlugin)); + _p = (samplePlugin*) calloc(1, sizeof(samplePlugin)); _p->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED | diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c index e449e5935..2ce48f8c3 100644 --- a/channels/tsmf/client/tsmf_main.c +++ b/channels/tsmf/client/tsmf_main.c @@ -117,8 +117,7 @@ BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, wMessage* eve } static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, - UINT32 cbSize, - BYTE* pBuffer) + wStream *data) { int length; wStream* input; @@ -129,6 +128,7 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 FunctionId; UINT32 InterfaceId; TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback; + UINT32 cbSize = Stream_GetRemainingLength(data); /* 2.2.1 Shared Message Header (SHARED_MSG_HEADER) */ if (cbSize < 12) @@ -137,7 +137,7 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, return 1; } - input = Stream_New((BYTE*) pBuffer, cbSize); + input = data; output = Stream_New(NULL, 256); Stream_Seek(output, 8); @@ -286,7 +286,6 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, break; } - Stream_Free(input, FALSE); input = NULL; ifman.input = NULL; diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index 9a780eca5..f40bd6a28 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -169,8 +169,6 @@ BOOL freerdp_connect(freerdp* instance) update_recv_surfcmds(update, Stream_Length(s) , s); update->EndPaint(update->context); Stream_Release(s); - - StreamPool_Return(rdp->transport->ReceivePool, s); } pcap_close(update->pcap_rfx); From e952db52a7af3a3a66161c847719e73957b92b13 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 11 Jun 2014 15:00:37 +0200 Subject: [PATCH 27/50] Added missing stream pool creation. --- channels/drdynvc/client/dvcman.c | 1 + 1 file changed, 1 insertion(+) diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c index 75a3fdd18..8de05775a 100644 --- a/channels/drdynvc/client/dvcman.c +++ b/channels/drdynvc/client/dvcman.c @@ -203,6 +203,7 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) dvcman->iface.GetChannelId = dvcman_get_channel_id; dvcman->drdynvc = plugin; dvcman->channels = ArrayList_New(TRUE); + dvcman->pool = StreamPool_New(FALSE, 10); return (IWTSVirtualChannelManager*) dvcman; } From cc71d7e66a302e7bc122d78241d86dc51dd12c32 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 11 Jun 2014 15:13:58 +0200 Subject: [PATCH 28/50] Using synchronized stream pool now. --- channels/drdynvc/client/dvcman.c | 2 +- libfreerdp/utils/svc_plugin.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c index 8de05775a..6cbbb4208 100644 --- a/channels/drdynvc/client/dvcman.c +++ b/channels/drdynvc/client/dvcman.c @@ -203,7 +203,7 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) dvcman->iface.GetChannelId = dvcman_get_channel_id; dvcman->drdynvc = plugin; dvcman->channels = ArrayList_New(TRUE); - dvcman->pool = StreamPool_New(FALSE, 10); + dvcman->pool = StreamPool_New(TRUE, 10); return (IWTSVirtualChannelManager*) dvcman; } diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index cb6018218..cb1df331d 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -298,7 +298,7 @@ void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints) plugin->channel_entry_points.pInterface = *(plugin->channel_entry_points.ppInterface); plugin->channel_entry_points.ppInterface = &(plugin->channel_entry_points.pInterface); plugin->started = CreateEvent(NULL,TRUE,FALSE,NULL); - plugin->pool = StreamPool_New(FALSE, 10); + plugin->pool = StreamPool_New(TRUE, 10); svc_plugin_add_init_handle_data(plugin->InitHandle, plugin); } From 0901938590df83de5a98ff7909bd3e2fcacf7f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 11 Jun 2014 14:31:46 -0400 Subject: [PATCH 29/50] channels/drdynvc: fix fragmented packets --- channels/drdynvc/client/drdynvc_main.c | 3 ++- channels/drdynvc/client/dvcman.c | 10 ++++++---- channels/rdpgfx/client/rdpgfx_main.c | 4 +--- libfreerdp/utils/svc_plugin.c | 4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 5232cbb05..5219efdf1 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -421,7 +421,8 @@ static void drdynvc_process_terminate(rdpSvcPlugin* plugin) if (drdynvc->channel_mgr) dvcman_free(drdynvc->channel_mgr); - svc_plugin_terminate(plugin); + svc_plugin_terminate(plugin); + free(drdynvc); } diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c index 2f63ad5d8..5e736e8e9 100644 --- a/channels/drdynvc/client/dvcman.c +++ b/channels/drdynvc/client/dvcman.c @@ -466,11 +466,11 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UI return 0; } -int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream *data) +int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data) { int error = 0; DVCMAN_CHANNEL* channel; - UINT32 data_size = Stream_GetRemainingLength(data); + UINT32 dataSize = Stream_GetRemainingLength(data); channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); @@ -483,7 +483,7 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 C if (channel->dvc_data) { /* Fragmented data */ - if (Stream_GetPosition(channel->dvc_data) + data_size > (UINT32) Stream_Capacity(channel->dvc_data)) + if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(channel->dvc_data)) { DEBUG_WARN("data exceeding declared length!"); Stream_Release(channel->dvc_data); @@ -491,10 +491,12 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 C return 1; } - Stream_Write(channel->dvc_data, Stream_Pointer(data), data_size); + Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize); if (((size_t) Stream_GetPosition(channel->dvc_data)) >= Stream_Capacity(channel->dvc_data)) { + Stream_SealLength(channel->dvc_data); + Stream_SetPosition(channel->dvc_data, 0); error = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 00bdf21a3..2b50e9ce8 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -750,9 +750,7 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; - status = zgfx_decompress(gfx->zgfx, Stream_Buffer(data), Stream_Length(data), &pDstData, &DstSize, 0); - - Stream_Release(data); + status = zgfx_decompress(gfx->zgfx, Stream_Pointer(data), Stream_GetRemainingLength(data), &pDstData, &DstSize, 0); if (status < 0) { diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index cb1df331d..578c91562 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -102,10 +102,11 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3 if (dataFlags & CHANNEL_FLAG_FIRST) { - if (plugin->data_in != NULL) + if (plugin->data_in) Stream_Release(plugin->data_in); plugin->data_in = StreamPool_Take(plugin->pool, totalLength); + Stream_AddRef(plugin->data_in); } s = plugin->data_in; @@ -122,7 +123,6 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3 plugin->data_in = NULL; Stream_SealLength(s); Stream_SetPosition(s, 0); - Stream_AddRef(s); MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) s, NULL); } From 53639dea0b22d7005696a490999c9f933be387fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 11 Jun 2014 15:09:28 -0400 Subject: [PATCH 30/50] channels: reduce dependency on svc_plugin.h --- channels/cliprdr/client/cliprdr_format.c | 1 - channels/cliprdr/client/cliprdr_main.c | 1 - channels/cliprdr/client/cliprdr_main.h | 1 + channels/drdynvc/client/drdynvc_main.c | 1 - channels/parallel/client/parallel_main.c | 31 +- channels/printer/client/printer_cups.c | 29 +- channels/printer/client/printer_main.c | 26 +- channels/printer/client/printer_win.c | 83 ++-- channels/rail/client/rail_main.c | 1 - channels/rdpsnd/client/ios/rdpsnd_ios.c | 399 ++++++++++---------- channels/rdpsnd/client/mac/rdpsnd_mac.c | 27 +- channels/rdpsnd/client/pulse/rdpsnd_pulse.c | 31 +- channels/rdpsnd/client/winmm/rdpsnd_winmm.c | 7 +- channels/sample/CMakeLists.txt | 23 -- channels/sample/ChannelOptions.cmake | 16 - channels/sample/client/CMakeLists.txt | 35 -- channels/sample/client/readme.txt | 11 - channels/sample/client/sample_main.c | 140 ------- channels/sample/client/sample_main.h | 26 -- channels/sample/client/server_chan_test.cpp | 60 --- channels/serial/client/serial_main.c | 18 +- channels/serial/client/serial_tty.c | 71 +--- client/Windows/cli/wfreerdp.c | 1 - client/Windows/wf_interface.c | 2 - include/freerdp/utils/svc_plugin.h | 2 +- 25 files changed, 281 insertions(+), 762 deletions(-) delete mode 100644 channels/sample/CMakeLists.txt delete mode 100644 channels/sample/ChannelOptions.cmake delete mode 100644 channels/sample/client/CMakeLists.txt delete mode 100644 channels/sample/client/readme.txt delete mode 100644 channels/sample/client/sample_main.c delete mode 100644 channels/sample/client/sample_main.h delete mode 100644 channels/sample/client/server_chan_test.cpp diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index a9910cfb4..4389f5f58 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -31,7 +31,6 @@ #include #include -#include #include #include "cliprdr_main.h" diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 928d74750..7a7907021 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -31,7 +31,6 @@ #include #include -#include #include #include "cliprdr_main.h" diff --git a/channels/cliprdr/client/cliprdr_main.h b/channels/cliprdr/client/cliprdr_main.h index b3eabcb9d..9aec3348a 100644 --- a/channels/cliprdr/client/cliprdr_main.h +++ b/channels/cliprdr/client/cliprdr_main.h @@ -24,6 +24,7 @@ #include #include +#include struct cliprdr_plugin { diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 5219efdf1..30a64e3d5 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -29,7 +29,6 @@ #include #include -#include #include "dvcman.h" #include "drdynvc_types.h" diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c index ff6da340a..a6b5d8985 100644 --- a/channels/parallel/client/parallel_main.c +++ b/channels/parallel/client/parallel_main.c @@ -47,13 +47,12 @@ #include #include #include +#include #include #include #include #include -#include -#include #include struct _PARALLEL_DEVICE @@ -93,16 +92,14 @@ static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp) { irp->IoStatus = STATUS_ACCESS_DENIED; parallel->id = 0; - - DEBUG_WARN("failed to create %s: %s", parallel->path, strerror(errno)); } else { /* all read and write operations should be non-blocking */ if (fcntl(parallel->file, F_SETFL, O_NONBLOCK) == -1) - DEBUG_WARN("%s fcntl %s", path, strerror(errno)); + { - DEBUG_SVC("%s(%d) created", parallel->path, parallel->file); + } } Stream_Write_UINT32(irp->output, parallel->id); @@ -116,9 +113,13 @@ static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp) static void parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp) { if (close(parallel->file) < 0) - DEBUG_SVC("failed to close %s(%d)", parallel->path, parallel->id); + { + + } else - DEBUG_SVC("%s(%d) closed", parallel->path, parallel->id); + { + + } Stream_Zero(irp->output, 5); /* Padding(5) */ @@ -145,12 +146,10 @@ static void parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp) free(buffer); buffer = NULL; Length = 0; - - DEBUG_WARN("read %s(%d) failed", parallel->path, parallel->id); } else { - DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, parallel->id); + } Stream_Write_UINT32(irp->output, Length); @@ -177,8 +176,6 @@ static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) Stream_Read_UINT64(irp->input, Offset); Stream_Seek(irp->input, 20); /* Padding */ - DEBUG_SVC("Length %u Offset %llu", Length, Offset); - len = Length; while (len > 0) @@ -189,8 +186,6 @@ static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; - - DEBUG_WARN("write %s(%d) failed.", parallel->path, parallel->id); break; } @@ -206,15 +201,12 @@ static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) static void parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP* irp) { - DEBUG_SVC("in"); Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */ irp->Complete(irp); } static void parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) { - DEBUG_SVC("MajorFunction %u", irp->MajorFunction); - switch (irp->MajorFunction) { case IRP_MJ_CREATE: @@ -238,7 +230,6 @@ static void parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) break; default: - DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; @@ -281,8 +272,6 @@ static void parallel_free(DEVICE* device) { PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; - DEBUG_SVC("freeing device"); - MessageQueue_PostQuit(parallel->queue, 0); WaitForSingleObject(parallel->thread, INFINITE); CloseHandle(parallel->thread); diff --git a/channels/printer/client/printer_cups.c b/channels/printer/client/printer_cups.c index aa9b0ee2b..0d6fcbeb9 100644 --- a/channels/printer/client/printer_cups.c +++ b/channels/printer/client/printer_cups.c @@ -31,7 +31,6 @@ #include -#include #include #include "printer_main.h" @@ -87,15 +86,12 @@ static void printer_cups_write_printjob(rdpPrintJob* printjob, BYTE* data, int s fp = fopen((const char*) cups_printjob->printjob_object, "a+b"); - if (fp == NULL) - { - DEBUG_WARN("failed to open file %s", (char*) cups_printjob->printjob_object); + if (!fp) return; - } if (fwrite(data, 1, size, fp) < size) { - DEBUG_WARN("failed to write file %s", (char*) cups_printjob->printjob_object); + } fclose(fp); @@ -121,7 +117,7 @@ static void printer_cups_close_printjob(rdpPrintJob* printjob) if (cupsPrintFile(printjob->printer->name, (const char*) cups_printjob->printjob_object, buf, 0, NULL) == 0) { - DEBUG_WARN("cupsPrintFile: %s", cupsLastErrorString()); + } unlink(cups_printjob->printjob_object); @@ -167,20 +163,19 @@ static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id) cups_printjob->printjob_object = httpConnectEncrypt(cupsServer(), ippPort(), HTTP_ENCRYPT_IF_REQUESTED); - if (cups_printjob->printjob_object == NULL) + if (!cups_printjob->printjob_object) { - DEBUG_WARN("httpConnectEncrypt: %s", cupsLastErrorString()); free(cups_printjob); return NULL; } printer_cups_get_printjob_name(buf, sizeof(buf)); + cups_printjob->printjob_id = cupsCreateJob((http_t*) cups_printjob->printjob_object, printer->name, buf, 0, NULL); - if (cups_printjob->printjob_id == 0) + if (!cups_printjob->printjob_id) { - DEBUG_WARN("cupsCreateJob: %s", cupsLastErrorString()); httpClose((http_t*) cups_printjob->printjob_object); free(cups_printjob); return NULL; @@ -281,19 +276,15 @@ rdpPrinterDriver* printer_cups_get_driver(void) { if (cups_driver == NULL) { - cups_driver = (rdpCupsPrinterDriver*) malloc(sizeof(rdpCupsPrinterDriver)); - ZeroMemory(cups_driver, sizeof(rdpCupsPrinterDriver)); + cups_driver = (rdpCupsPrinterDriver*) calloc(1, sizeof(rdpCupsPrinterDriver)); + + if (!cups_driver) + return NULL; cups_driver->driver.EnumPrinters = printer_cups_enum_printers; cups_driver->driver.GetPrinter = printer_cups_get_printer; cups_driver->id_sequence = 1; - -#ifdef _CUPS_API_1_4 - DEBUG_SVC("using CUPS API 1.4"); -#else - DEBUG_SVC("using CUPS API 1.2"); -#endif } return (rdpPrinterDriver*) cups_driver; diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index b3b17fb04..40ba570ce 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -28,11 +28,10 @@ #include #include #include +#include #include -#include #include -#include #ifdef WITH_CUPS #include "printer_cups.h" @@ -69,15 +68,11 @@ static void printer_process_irp_create(PRINTER_DEVICE* printer_dev, IRP* irp) if (printjob) { Stream_Write_UINT32(irp->output, printjob->id); /* FileId */ - - DEBUG_SVC("printjob id: %d", printjob->id); } else { Stream_Write_UINT32(irp->output, 0); /* FileId */ irp->IoStatus = STATUS_PRINT_QUEUE_FULL; - - DEBUG_WARN("error creating print job."); } irp->Complete(irp); @@ -87,20 +82,16 @@ static void printer_process_irp_close(PRINTER_DEVICE* printer_dev, IRP* irp) { rdpPrintJob* printjob = NULL; - if (printer_dev->printer != NULL) + if (printer_dev->printer) printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId); if (!printjob) { irp->IoStatus = STATUS_UNSUCCESSFUL; - - DEBUG_WARN("printjob id %d not found.", irp->FileId); } else { printjob->Close(printjob); - - DEBUG_SVC("printjob id %d closed.", irp->FileId); } Stream_Zero(irp->output, 4); /* Padding(4) */ @@ -125,14 +116,10 @@ static void printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; - - DEBUG_WARN("printjob id %d not found.", irp->FileId); } else { printjob->Write(printjob, Stream_Pointer(irp->input), Length); - - DEBUG_SVC("printjob id %d written %d bytes.", irp->FileId, Length); } Stream_Write_UINT32(irp->output, Length); @@ -168,7 +155,6 @@ static void printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp) break; default: - DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; @@ -267,8 +253,6 @@ void printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri CachedFieldsLen = 0; CachedPrinterConfigData = NULL; - DEBUG_SVC("Printer %s registered", printer->name); - Flags = 0; if (printer->is_default) @@ -332,9 +316,8 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) driver = printer_win_get_driver(); #endif - if (driver == NULL) + if (!driver) { - DEBUG_WARN("no driver"); return 1; } @@ -347,10 +330,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) printer = driver->GetPrinter(driver, name); if (!printer) - { - DEBUG_WARN("printer %s not found.", name); return 1; - } if (driver_name && driver_name[0]) printer->driver = driver_name; diff --git a/channels/printer/client/printer_win.c b/channels/printer/client/printer_win.c index 733b24ff0..fcbbbc1fd 100644 --- a/channels/printer/client/printer_win.c +++ b/channels/printer/client/printer_win.c @@ -30,8 +30,6 @@ #include #include -#include - #include "printer_main.h" #include "printer_win.h" @@ -69,45 +67,44 @@ static void printer_win_get_printjob_name(char* buf, int size) time_t tt; struct tm* t; - DEBUG_WINPR(""); - tt = time(NULL); t = localtime(&tt); snprintf(buf, size - 1, "FreeRDP Print Job %d%02d%02d%02d%02d%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); - - DEBUG_WINPR("buf: %s", buf); - } static void printer_win_write_printjob(rdpPrintJob* printjob, BYTE* data, int size) { - rdpWinPrintJob* win_printjob = (rdpWinPrintJob*)printjob; + rdpWinPrintJob* win_printjob = (rdpWinPrintJob*) printjob; LPVOID pBuf = data; DWORD cbBuf = size; DWORD pcWritten; - if( ! WritePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter, pBuf, cbBuf, &pcWritten ) ) - DEBUG_WINPR("WritePrinter failed"); -; - + if(!WritePrinter(((rdpWinPrinter*)printjob->printer)->hPrinter, pBuf, cbBuf, &pcWritten)) + { + + } } static void printer_win_close_printjob(rdpPrintJob* printjob) { - rdpWinPrintJob* win_printjob = (rdpWinPrintJob*)printjob; + rdpWinPrintJob* win_printjob = (rdpWinPrintJob*) printjob; - DEBUG_WINPR(""); + if (!EndPagePrinter(((rdpWinPrinter*) printjob->printer)->hPrinter)) + { - if ( ! EndPagePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter ) ) - DEBUG_WINPR("EndPagePrinter failed");; - if ( ! ClosePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter ) ) - DEBUG_WINPR("ClosePrinter failed");; + } - ((rdpWinPrinter*)printjob->printer)->printjob = NULL; - free(win_printjob) ; + if (!ClosePrinter(((rdpWinPrinter*) printjob->printer)->hPrinter)) + { + + } + + ((rdpWinPrinter*) printjob->printer)->printjob = NULL; + + free(win_printjob); } static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id) @@ -115,13 +112,10 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id) rdpWinPrinter* win_printer = (rdpWinPrinter*)printer; rdpWinPrintJob* win_printjob; - DEBUG_WINPR(""); - if (win_printer->printjob != NULL) return NULL; - win_printjob = (rdpWinPrintJob*) malloc(sizeof(rdpWinPrintJob)); - ZeroMemory(win_printjob, sizeof(rdpWinPrintJob)); + win_printjob = (rdpWinPrintJob*) calloc(1, sizeof(rdpWinPrintJob)); win_printjob->printjob.id = id; win_printjob->printjob.printer = printer; @@ -132,10 +126,14 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id) win_printjob->handle = StartDocPrinter(win_printer->hPrinter, 1, (LPBYTE) &(win_printjob->di)); if (!win_printjob->handle) - DEBUG_WINPR("StartDocPrinter failed"); + { + + } if (!StartPagePrinter(win_printer->hPrinter)) - DEBUG_WINPR("ClosePrinter failed"); + { + + } win_printjob->printjob.Write = printer_win_write_printjob; win_printjob->printjob.Close = printer_win_close_printjob; @@ -149,9 +147,7 @@ static rdpPrintJob* printer_win_find_printjob(rdpPrinter* printer, UINT32 id) { rdpWinPrinter* win_printer = (rdpWinPrinter*) printer; - DEBUG_WINPR(""); - - if (win_printer->printjob == NULL) + if (!win_printer->printjob) return NULL; if (win_printer->printjob->printjob.id != id) @@ -164,8 +160,6 @@ static void printer_win_free_printer(rdpPrinter* printer) { rdpWinPrinter* win_printer = (rdpWinPrinter*) printer; - DEBUG_WINPR(""); - if (win_printer->printjob) win_printer->printjob->printjob.Close((rdpPrintJob*) win_printer->printjob); @@ -180,10 +174,8 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons DWORD needed; PRINTER_INFO_2 *prninfo=NULL; size_t charsConverted; - DEBUG_WINPR(""); - win_printer = (rdpWinPrinter*) malloc(sizeof(rdpWinPrinter)); - ZeroMemory(win_printer, sizeof(rdpWinPrinter)); + win_printer = (rdpWinPrinter*) calloc(1, sizeof(rdpWinPrinter)); win_printer->printer.id = win_driver->id_sequence++; win_printer->printer.name = _strdup(name); @@ -195,7 +187,6 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons swprintf(wname, 256, L"%hs", name); OpenPrinter(wname, &(win_printer->hPrinter), NULL); - DEBUG_WINPR("handle: 0x%08X", win_printer->hPrinter); GetPrinter(win_printer->hPrinter, 2, (LPBYTE) prninfo, 0, &needed); prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed); @@ -216,8 +207,6 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver) size_t charsConverted; PRINTER_INFO_2* prninfo = NULL; DWORD needed, returned; - - DEBUG_WINPR(""); /* find required size for the buffer */ EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &returned); @@ -227,19 +216,16 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver) prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed); /* call again */ - if ( !EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE) prninfo, needed, &needed, &returned) ) + if (!EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE) prninfo, needed, &needed, &returned)) { - DEBUG_WINPR("EnumPrinters failed"); - } ; /* ERROR... */ - DEBUG_WINPR("printers found: %d", returned); + } - printers = (rdpPrinter**) malloc(sizeof(rdpPrinter*) * (returned + 1)); - ZeroMemory(printers, sizeof(rdpPrinter*) * (returned + 1)); + printers = (rdpPrinter**) calloc((returned + 1), sizeof(rdpPrinter*)); num_printers = 0; - for (i = 0; i < (int)returned; i++) + for (i = 0; i < (int) returned; i++) { wcstombs_s(&charsConverted, pname, 1000, prninfo[i].pPrinterName, _TRUNCATE); printers[num_printers++] = printer_win_new_printer((rdpWinPrinterDriver*)driver, @@ -254,8 +240,6 @@ static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver, const char* { rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver; rdpPrinter *myPrinter = NULL; - - DEBUG_WINPR("printer %s", name); myPrinter = printer_win_new_printer(win_driver, name, L"", win_driver->id_sequence == 1 ? TRUE : FALSE); @@ -266,12 +250,9 @@ static rdpWinPrinterDriver* win_driver = NULL; rdpPrinterDriver* printer_win_get_driver(void) { - DEBUG_WINPR(""); - - if (win_driver == NULL) + if (!win_driver) { - win_driver = (rdpWinPrinterDriver*) malloc(sizeof(rdpWinPrinterDriver)); - ZeroMemory(win_driver, sizeof(rdpWinPrinterDriver)); + win_driver = (rdpWinPrinterDriver*) calloc(1, sizeof(rdpWinPrinterDriver)); win_driver->driver.EnumPrinters = printer_win_enum_printers; win_driver->driver.GetPrinter = printer_win_get_printer; diff --git a/channels/rail/client/rail_main.c b/channels/rail/client/rail_main.c index 45a4f59a6..17d585716 100644 --- a/channels/rail/client/rail_main.c +++ b/channels/rail/client/rail_main.c @@ -31,7 +31,6 @@ #include #include -#include #include #include diff --git a/channels/rdpsnd/client/ios/rdpsnd_ios.c b/channels/rdpsnd/client/ios/rdpsnd_ios.c index 60da43cc1..1adcc3eee 100644 --- a/channels/rdpsnd/client/ios/rdpsnd_ios.c +++ b/channels/rdpsnd/client/ios/rdpsnd_ios.c @@ -20,12 +20,11 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif - + #include #include #include -#include #import @@ -37,66 +36,66 @@ typedef struct rdpsnd_ios_plugin { - rdpsndDevicePlugin device; - AudioComponentInstance audio_unit; - TPCircularBuffer buffer; - BOOL is_opened; - BOOL is_playing; + rdpsndDevicePlugin device; + AudioComponentInstance audio_unit; + TPCircularBuffer buffer; + BOOL is_opened; + BOOL is_playing; } rdpsndIOSPlugin; #define THIS(__ptr) ((rdpsndIOSPlugin*)__ptr) static OSStatus rdpsnd_ios_render_cb( - void *inRefCon, - AudioUnitRenderActionFlags __unused *ioActionFlags, - const AudioTimeStamp __unused *inTimeStamp, - UInt32 inBusNumber, - UInt32 __unused inNumberFrames, - AudioBufferList *ioData + void *inRefCon, + AudioUnitRenderActionFlags __unused *ioActionFlags, + const AudioTimeStamp __unused *inTimeStamp, + UInt32 inBusNumber, + UInt32 __unused inNumberFrames, + AudioBufferList *ioData ) { - unsigned int i; - - if (inBusNumber != 0) - { - return noErr; - } - - rdpsndIOSPlugin *p = THIS(inRefCon); - - for (i = 0; i < ioData->mNumberBuffers; i++) - { - AudioBuffer* target_buffer = &ioData->mBuffers[i]; - - int32_t available_bytes = 0; - const void *buffer = TPCircularBufferTail(&p->buffer, &available_bytes); - if (buffer != NULL && available_bytes > 0) - { - const int bytes_to_copy = MIN((int32_t)target_buffer->mDataByteSize, available_bytes); - - memcpy(target_buffer->mData, buffer, bytes_to_copy); - target_buffer->mDataByteSize = bytes_to_copy; - - TPCircularBufferConsume(&p->buffer, bytes_to_copy); - } - else - { - target_buffer->mDataByteSize = 0; - AudioOutputUnitStop(p->audio_unit); - p->is_playing = 0; - } - } - - return noErr; + unsigned int i; + + if (inBusNumber != 0) + { + return noErr; + } + + rdpsndIOSPlugin *p = THIS(inRefCon); + + for (i = 0; i < ioData->mNumberBuffers; i++) + { + AudioBuffer* target_buffer = &ioData->mBuffers[i]; + + int32_t available_bytes = 0; + const void *buffer = TPCircularBufferTail(&p->buffer, &available_bytes); + if (buffer != NULL && available_bytes > 0) + { + const int bytes_to_copy = MIN((int32_t)target_buffer->mDataByteSize, available_bytes); + + memcpy(target_buffer->mData, buffer, bytes_to_copy); + target_buffer->mDataByteSize = bytes_to_copy; + + TPCircularBufferConsume(&p->buffer, bytes_to_copy); + } + else + { + target_buffer->mDataByteSize = 0; + AudioOutputUnitStop(p->audio_unit); + p->is_playing = 0; + } + } + + return noErr; } static BOOL rdpsnd_ios_format_supported(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* format) { - if (format->wFormatTag == WAVE_FORMAT_PCM) - { - return 1; - } - return 0; + if (format->wFormatTag == WAVE_FORMAT_PCM) + { + return 1; + } + return 0; } static void rdpsnd_ios_set_format(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* __unused format, int __unused latency) @@ -109,170 +108,170 @@ static void rdpsnd_ios_set_volume(rdpsndDevicePlugin* __unused device, UINT32 __ static void rdpsnd_ios_start(rdpsndDevicePlugin* device) { - rdpsndIOSPlugin *p = THIS(device); + rdpsndIOSPlugin *p = THIS(device); - /* If this device is not playing... */ - if (!p->is_playing) - { - /* Start the device. */ - int32_t available_bytes = 0; - TPCircularBufferTail(&p->buffer, &available_bytes); - if (available_bytes > 0) - { - p->is_playing = 1; - AudioOutputUnitStart(p->audio_unit); - } - } + /* If this device is not playing... */ + if (!p->is_playing) + { + /* Start the device. */ + int32_t available_bytes = 0; + TPCircularBufferTail(&p->buffer, &available_bytes); + if (available_bytes > 0) + { + p->is_playing = 1; + AudioOutputUnitStart(p->audio_unit); + } + } } static void rdpsnd_ios_stop(rdpsndDevicePlugin* __unused device) { - rdpsndIOSPlugin *p = THIS(device); + rdpsndIOSPlugin *p = THIS(device); - /* If the device is playing... */ - if (p->is_playing) - { - /* Stop the device. */ - AudioOutputUnitStop(p->audio_unit); - p->is_playing = 0; + /* If the device is playing... */ + if (p->is_playing) + { + /* Stop the device. */ + AudioOutputUnitStop(p->audio_unit); + p->is_playing = 0; - /* Free all buffers. */ - TPCircularBufferClear(&p->buffer); - } + /* Free all buffers. */ + TPCircularBufferClear(&p->buffer); + } } static void rdpsnd_ios_play(rdpsndDevicePlugin* device, BYTE* data, int size) { - rdpsndIOSPlugin *p = THIS(device); - - const BOOL ok = TPCircularBufferProduceBytes(&p->buffer, data, size); - if (!ok) - { - return; - } - - rdpsnd_ios_start(device); + rdpsndIOSPlugin *p = THIS(device); + + const BOOL ok = TPCircularBufferProduceBytes(&p->buffer, data, size); + if (!ok) + { + return; + } + + rdpsnd_ios_start(device); } static void rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int __unused latency) { - rdpsndIOSPlugin *p = THIS(device); - - if (p->is_opened) - { - return; - } + rdpsndIOSPlugin *p = THIS(device); - /* Find the output audio unit. */ - AudioComponentDescription desc; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_RemoteIO; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - AudioComponent audioComponent = AudioComponentFindNext(NULL, &desc); - if (audioComponent == NULL) return; + if (p->is_opened) + { + return; + } - /* Open the audio unit. */ - OSStatus status = AudioComponentInstanceNew(audioComponent, &p->audio_unit); - if (status != 0) return; + /* Find the output audio unit. */ + AudioComponentDescription desc; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_RemoteIO; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; - /* Set the format for the AudioUnit. */ - AudioStreamBasicDescription audioFormat = {0}; - audioFormat.mSampleRate = format->nSamplesPerSec; - audioFormat.mFormatID = kAudioFormatLinearPCM; - audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; - audioFormat.mFramesPerPacket = 1; /* imminent property of the Linear PCM */ - audioFormat.mChannelsPerFrame = format->nChannels; - audioFormat.mBitsPerChannel = format->wBitsPerSample; - audioFormat.mBytesPerFrame = (format->wBitsPerSample * format->nChannels) / 8; - audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket; - - status = AudioUnitSetProperty( - p->audio_unit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, - 0, - &audioFormat, - sizeof(audioFormat)); - if (status != 0) - { - AudioComponentInstanceDispose(p->audio_unit); - p->audio_unit = NULL; - return; - } - - /* Set up the AudioUnit callback. */ - AURenderCallbackStruct callbackStruct = {0}; - callbackStruct.inputProc = rdpsnd_ios_render_cb; - callbackStruct.inputProcRefCon = p; - status = AudioUnitSetProperty( - p->audio_unit, - kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Input, - 0, - &callbackStruct, - sizeof(callbackStruct)); - if (status != 0) - { - AudioComponentInstanceDispose(p->audio_unit); - p->audio_unit = NULL; - return; - } + AudioComponent audioComponent = AudioComponentFindNext(NULL, &desc); + if (audioComponent == NULL) return; - /* Initialize the AudioUnit. */ - status = AudioUnitInitialize(p->audio_unit); - if (status != 0) - { - AudioComponentInstanceDispose(p->audio_unit); - p->audio_unit = NULL; - return; - } - - /* Allocate the circular buffer. */ - const BOOL ok = TPCircularBufferInit(&p->buffer, CIRCULAR_BUFFER_SIZE); - if (!ok) - { - AudioUnitUninitialize(p->audio_unit); - AudioComponentInstanceDispose(p->audio_unit); - p->audio_unit = NULL; - return; - } + /* Open the audio unit. */ + OSStatus status = AudioComponentInstanceNew(audioComponent, &p->audio_unit); + if (status != 0) return; - p->is_opened = 1; + /* Set the format for the AudioUnit. */ + AudioStreamBasicDescription audioFormat = {0}; + audioFormat.mSampleRate = format->nSamplesPerSec; + audioFormat.mFormatID = kAudioFormatLinearPCM; + audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; + audioFormat.mFramesPerPacket = 1; /* imminent property of the Linear PCM */ + audioFormat.mChannelsPerFrame = format->nChannels; + audioFormat.mBitsPerChannel = format->wBitsPerSample; + audioFormat.mBytesPerFrame = (format->wBitsPerSample * format->nChannels) / 8; + audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket; + + status = AudioUnitSetProperty( + p->audio_unit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &audioFormat, + sizeof(audioFormat)); + if (status != 0) + { + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + /* Set up the AudioUnit callback. */ + AURenderCallbackStruct callbackStruct = {0}; + callbackStruct.inputProc = rdpsnd_ios_render_cb; + callbackStruct.inputProcRefCon = p; + status = AudioUnitSetProperty( + p->audio_unit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &callbackStruct, + sizeof(callbackStruct)); + if (status != 0) + { + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + /* Initialize the AudioUnit. */ + status = AudioUnitInitialize(p->audio_unit); + if (status != 0) + { + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + /* Allocate the circular buffer. */ + const BOOL ok = TPCircularBufferInit(&p->buffer, CIRCULAR_BUFFER_SIZE); + if (!ok) + { + AudioUnitUninitialize(p->audio_unit); + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + p->is_opened = 1; } static void rdpsnd_ios_close(rdpsndDevicePlugin* device) { - rdpsndIOSPlugin *p = THIS(device); + rdpsndIOSPlugin *p = THIS(device); - /* Make sure the device is stopped. */ - rdpsnd_ios_stop(device); + /* Make sure the device is stopped. */ + rdpsnd_ios_stop(device); - /* If the device is open... */ - if (p->is_opened) - { - /* Close the device. */ - AudioUnitUninitialize(p->audio_unit); - AudioComponentInstanceDispose(p->audio_unit); - p->audio_unit = NULL; - p->is_opened = 0; - - /* Destroy the circular buffer. */ - TPCircularBufferCleanup(&p->buffer); - } + /* If the device is open... */ + if (p->is_opened) + { + /* Close the device. */ + AudioUnitUninitialize(p->audio_unit); + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + p->is_opened = 0; + + /* Destroy the circular buffer. */ + TPCircularBufferCleanup(&p->buffer); + } } static void rdpsnd_ios_free(rdpsndDevicePlugin* device) { - rdpsndIOSPlugin *p = THIS(device); + rdpsndIOSPlugin *p = THIS(device); - /* Ensure the device is closed. */ - rdpsnd_ios_close(device); + /* Ensure the device is closed. */ + rdpsnd_ios_close(device); - /* Free memory associated with the device. */ - free(p); + /* Free memory associated with the device. */ + free(p); } #ifdef STATIC_CHANNELS @@ -281,19 +280,21 @@ static void rdpsnd_ios_free(rdpsndDevicePlugin* device) int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { - rdpsndIOSPlugin *p = (rdpsndIOSPlugin*)malloc(sizeof(rdpsndIOSPlugin)); - memset(p, 0, sizeof(rdpsndIOSPlugin)); - - p->device.Open = rdpsnd_ios_open; - p->device.FormatSupported = rdpsnd_ios_format_supported; - p->device.SetFormat = rdpsnd_ios_set_format; - p->device.SetVolume = rdpsnd_ios_set_volume; - p->device.Play = rdpsnd_ios_play; - p->device.Start = rdpsnd_ios_start; - p->device.Close = rdpsnd_ios_close; - p->device.Free = rdpsnd_ios_free; - - pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p); - - return 0; -} \ No newline at end of file + rdpsndIOSPlugin* p = (rdpsndIOSPlugin*) calloc(1, sizeof(rdpsndIOSPlugin)); + + if (!p) + return -1; + + p->device.Open = rdpsnd_ios_open; + p->device.FormatSupported = rdpsnd_ios_format_supported; + p->device.SetFormat = rdpsnd_ios_set_format; + p->device.SetVolume = rdpsnd_ios_set_volume; + p->device.Play = rdpsnd_ios_play; + p->device.Start = rdpsnd_ios_start; + p->device.Close = rdpsnd_ios_close; + p->device.Free = rdpsnd_ios_free; + + pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p); + + return 0; +} diff --git a/channels/rdpsnd/client/mac/rdpsnd_mac.c b/channels/rdpsnd/client/mac/rdpsnd_mac.c index 1fe05242c..96ffacd89 100644 --- a/channels/rdpsnd/client/mac/rdpsnd_mac.c +++ b/channels/rdpsnd/client/mac/rdpsnd_mac.c @@ -29,7 +29,6 @@ #include #include -#include #include #include @@ -282,23 +281,21 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE { rdpsndMacPlugin* mac; - mac = (rdpsndMacPlugin*) malloc(sizeof(rdpsndMacPlugin)); + mac = (rdpsndMacPlugin*) calloc(1, sizeof(rdpsndMacPlugin)); - if (mac) - { - ZeroMemory(mac, sizeof(rdpsndMacPlugin)); + if (!mac) + return -1; - mac->device.Open = rdpsnd_mac_open; - mac->device.FormatSupported = rdpsnd_mac_format_supported; - mac->device.SetFormat = rdpsnd_mac_set_format; - mac->device.SetVolume = rdpsnd_mac_set_volume; - mac->device.Play = rdpsnd_mac_play; - mac->device.Start = rdpsnd_mac_start; - mac->device.Close = rdpsnd_mac_close; - mac->device.Free = rdpsnd_mac_free; + mac->device.Open = rdpsnd_mac_open; + mac->device.FormatSupported = rdpsnd_mac_format_supported; + mac->device.SetFormat = rdpsnd_mac_set_format; + mac->device.SetVolume = rdpsnd_mac_set_volume; + mac->device.Play = rdpsnd_mac_play; + mac->device.Start = rdpsnd_mac_start; + mac->device.Close = rdpsnd_mac_close; + mac->device.Free = rdpsnd_mac_free; - pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) mac); - } + pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) mac); return 0; } diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c index e20cce9be..912563fe9 100644 --- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c @@ -37,7 +37,6 @@ #include #include -#include #include "rdpsnd_main.h" @@ -74,18 +73,15 @@ static void rdpsnd_pulse_context_state_callback(pa_context* context, void* userd switch (state) { case PA_CONTEXT_READY: - DEBUG_SVC("PA_CONTEXT_READY"); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; case PA_CONTEXT_FAILED: case PA_CONTEXT_TERMINATED: - DEBUG_SVC("PA_CONTEXT_FAILED/PA_CONTEXT_TERMINATED %d", (int)state); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; default: - DEBUG_SVC("state %d", (int)state); break; } } @@ -100,7 +96,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device) if (pa_context_connect(pulse->context, NULL, 0, NULL)) { - DEBUG_WARN("pa_context_connect failed (%d)", pa_context_errno(pulse->context)); return FALSE; } @@ -109,7 +104,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device) if (pa_threaded_mainloop_start(pulse->mainloop) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); - DEBUG_WARN("pa_threaded_mainloop_start failed (%d)", pa_context_errno(pulse->context)); return FALSE; } @@ -122,7 +116,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device) if (!PA_CONTEXT_IS_GOOD(state)) { - DEBUG_WARN("bad context state (%d)", pa_context_errno(pulse->context)); break; } @@ -133,7 +126,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device) if (state == PA_CONTEXT_READY) { - DEBUG_SVC("connected"); return TRUE; } else @@ -173,18 +165,15 @@ static void rdpsnd_pulse_stream_state_callback(pa_stream* stream, void* userdata switch (state) { case PA_STREAM_READY: - DEBUG_SVC("PA_STREAM_READY"); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; case PA_STREAM_FAILED: case PA_STREAM_TERMINATED: - DEBUG_SVC("state %d", (int)state); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; default: - DEBUG_SVC("state %d", (int)state); break; } } @@ -270,7 +259,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, if (!pulse->context || pulse->stream) { - DEBUG_WARN("pulse stream has been created."); return; } @@ -280,7 +268,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, if (pa_sample_spec_valid(&pulse->sample_spec) == 0) { pa_sample_spec_snprint(ss, sizeof(ss), &pulse->sample_spec); - DEBUG_WARN("Invalid sample spec %s", ss); return; } @@ -291,7 +278,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, if (!pulse->stream) { pa_threaded_mainloop_unlock(pulse->mainloop); - DEBUG_WARN("pa_stream_new failed (%d)", pa_context_errno(pulse->context)); return; } @@ -315,8 +301,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, pulse->device_name, pulse->latency > 0 ? &buffer_attr : NULL, flags, NULL, NULL) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); - DEBUG_WARN("pa_stream_connect_playback failed (%d)", - pa_context_errno(pulse->context)); return; } @@ -329,8 +313,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, if (!PA_STREAM_IS_GOOD(state)) { - DEBUG_WARN("bad stream state (%d)", - pa_context_errno(pulse->context)); break; } @@ -349,8 +331,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, pulse->gsm_context = gsm_create(); #endif - - DEBUG_SVC("connected"); } else { @@ -584,8 +564,6 @@ static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, BYTE* data, int size) if (status < 0) { - DEBUG_WARN("pa_stream_write failed (%d)", - pa_context_errno(pulse->context)); break; } @@ -653,8 +631,10 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE ADDIN_ARGV* args; rdpsndPulsePlugin* pulse; - pulse = (rdpsndPulsePlugin*) malloc(sizeof(rdpsndPulsePlugin)); - ZeroMemory(pulse, sizeof(rdpsndPulsePlugin)); + pulse = (rdpsndPulsePlugin*) calloc(1, sizeof(rdpsndPulsePlugin)); + + if (!pulse) + return -1; pulse->device.Open = rdpsnd_pulse_open; pulse->device.FormatSupported = rdpsnd_pulse_format_supported; @@ -678,7 +658,6 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE if (!pulse->mainloop) { - DEBUG_WARN("pa_threaded_mainloop_new failed"); rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse); return 1; } @@ -687,7 +666,6 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE if (!pulse->context) { - DEBUG_WARN("pa_context_new failed"); rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse); return 1; } @@ -696,7 +674,6 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE if (!rdpsnd_pulse_connect((rdpsndDevicePlugin*)pulse)) { - DEBUG_WARN("rdpsnd_pulse_connect failed"); rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse); return 1; } diff --git a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c index 7c1e47cd0..961b95e83 100644 --- a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c +++ b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c @@ -34,7 +34,6 @@ #include #include -#include #include "rdpsnd_main.h" @@ -333,8 +332,10 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE ADDIN_ARGV* args; rdpsndWinmmPlugin* winmm; - winmm = (rdpsndWinmmPlugin*) malloc(sizeof(rdpsndWinmmPlugin)); - ZeroMemory(winmm, sizeof(rdpsndWinmmPlugin)); + winmm = (rdpsndWinmmPlugin*) calloc(1, sizeof(rdpsndWinmmPlugin)); + + if (!winmm) + return -1; winmm->device.DisableConfirmThread = TRUE; diff --git a/channels/sample/CMakeLists.txt b/channels/sample/CMakeLists.txt deleted file mode 100644 index 183b8a65f..000000000 --- a/channels/sample/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -# FreeRDP: A Remote Desktop Protocol Implementation -# FreeRDP cmake build script -# -# Copyright 2012 Marc-Andre Moreau -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -define_channel("sample") - -if(WITH_CLIENT_CHANNELS) - add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME}) -endif() - diff --git a/channels/sample/ChannelOptions.cmake b/channels/sample/ChannelOptions.cmake deleted file mode 100644 index ae977457d..000000000 --- a/channels/sample/ChannelOptions.cmake +++ /dev/null @@ -1,16 +0,0 @@ -set(OPTION_DEFAULT OFF) - -if(WITH_SAMPLE) - set(OPTION_CLIENT_DEFAULT ON) -else() - set(OPTION_CLIENT_DEFAULT OFF) -endif() -set(OPTION_SERVER_DEFAULT OFF) - -define_channel_options(NAME "sample" TYPE "static" - DESCRIPTION "Sample Virtual Channel Extension" - SPECIFICATIONS "" - DEFAULT ${OPTION_DEFAULT}) - -define_channel_client_options(${OPTION_CLIENT_DEFAULT}) -define_channel_server_options(${OPTION_SERVER_DEFAULT}) diff --git a/channels/sample/client/CMakeLists.txt b/channels/sample/client/CMakeLists.txt deleted file mode 100644 index 867406d63..000000000 --- a/channels/sample/client/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -# FreeRDP: A Remote Desktop Protocol Implementation -# FreeRDP cmake build script -# -# Copyright 2012 Marc-Andre Moreau -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -define_channel_client("sample") - -set(${MODULE_PREFIX}_SRCS - sample_main.c - sample_main.h) - -add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry") - -set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") - -set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS - MONOLITHIC ${MONOLITHIC_BUILD} - MODULE freerdp - MODULES freerdp-utils) - -install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets) - -set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client") diff --git a/channels/sample/client/readme.txt b/channels/sample/client/readme.txt deleted file mode 100644 index 34c1b340c..000000000 --- a/channels/sample/client/readme.txt +++ /dev/null @@ -1,11 +0,0 @@ - -This is a skeleton virtual channel plugin for freerdp -To create your own virtual channel plugin, copy this directory -then change all references of "skel" to your plugin name -remember, plugin name are 7 chars or less, no spaces or funny chars - -server_chan_test.cpp is an example of how to open a channel to the client -this code needs to be compiled and run on the server in an rdp session -when connect with a client that has the "skel" plugin loaded - -Jay diff --git a/channels/sample/client/sample_main.c b/channels/sample/client/sample_main.c deleted file mode 100644 index c9e0b6780..000000000 --- a/channels/sample/client/sample_main.c +++ /dev/null @@ -1,140 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Sample Virtual Channel - * - * Copyright 2009-2012 Jay Sorg - * Copyright 2010-2012 Vic Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifndef _WIN32 -#include -#endif - -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "sample_main.h" - -struct sample_plugin -{ - rdpSvcPlugin plugin; - - /* put your private data here */ -}; - -static void sample_process_receive(rdpSvcPlugin* plugin, wStream* data_in) -{ - int bytes; - wStream* data_out; - samplePlugin* sample = (samplePlugin*) plugin; - - fprintf(stderr, "sample_process_receive:\n"); - - if (!sample) - { - fprintf(stderr, "sample_process_receive: sample is nil\n"); - return; - } - - /* process data in (from server) here */ - /* here we just send the same data back */ - - bytes = Stream_Capacity(data_in); - fprintf(stderr, "sample_process_receive: got bytes %d\n", bytes); - - if (bytes > 0) - { - data_out = Stream_New(NULL, bytes); - Stream_Copy(data_out, data_in, bytes); - /* svc_plugin_send takes ownership of data_out, that is why - we do not free it */ - - bytes = Stream_GetPosition(data_in); - fprintf(stderr, "sample_process_receive: sending bytes %d\n", bytes); - - svc_plugin_send(plugin, data_out); - } -} - -static void sample_process_connect(rdpSvcPlugin* plugin) -{ - samplePlugin* sample = (samplePlugin*) plugin; - DEBUG_SVC("connecting"); - - fprintf(stderr, "sample_process_connect:\n"); - - if (!sample) - return; -} - -static void sample_process_event(rdpSvcPlugin* plugin, wMessage* event) -{ - fprintf(stderr, "sample_process_event:\n"); - - /* events coming from main freerdp window to plugin */ - /* send them back with svc_plugin_send_event */ - - freerdp_event_free(event); -} - -static void sample_process_terminate(rdpSvcPlugin* plugin) -{ - samplePlugin* sample = (samplePlugin*) plugin; - - fprintf(stderr, "sample_process_terminate:\n"); - - if (!sample) - return; - - /* put your cleanup here */ - svc_plugin_terminate(plugin); - free(plugin); -} - -#define VirtualChannelEntry sample_VirtualChannelEntry - -int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) -{ - samplePlugin* _p; - - _p = (samplePlugin*) calloc(1, sizeof(samplePlugin)); - - _p->plugin.channel_def.options = - CHANNEL_OPTION_INITIALIZED | - CHANNEL_OPTION_ENCRYPT_RDP; - - strcpy(_p->plugin.channel_def.name, "sample"); - - _p->plugin.connect_callback = sample_process_connect; - _p->plugin.receive_callback = sample_process_receive; - _p->plugin.event_callback = sample_process_event; - _p->plugin.terminate_callback = sample_process_terminate; - - svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints); - - return 1; -} diff --git a/channels/sample/client/sample_main.h b/channels/sample/client/sample_main.h deleted file mode 100644 index 865919135..000000000 --- a/channels/sample/client/sample_main.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Sample Virtual Channel - * - * Copyright 2012 Jay Sorg - * Copyright 2010-2012 Vic Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __SAMPLE_MAIN_H -#define __SAMPLE_MAIN_H - -typedef struct sample_plugin samplePlugin; - -#endif /* __SAMPLE_MAIN_H */ diff --git a/channels/sample/client/server_chan_test.cpp b/channels/sample/client/server_chan_test.cpp deleted file mode 100644 index 577d7b1d1..000000000 --- a/channels/sample/client/server_chan_test.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// xrdp_chan_test.cpp : Basic test for virtual channel use. - -// These headers are required for the windows terminal service calls. -#include "windows.h" -#include "wtsapi32.h" -#include - -#define DSIZE 1024 - -int main() -{ - // Initialize the data for send/receive - char* data; - char* data1; - data = (char*)malloc(DSIZE); - data1 = (char*)malloc(DSIZE); - memset(data, 0xca, DSIZE); - memset(data1, 0, DSIZE); - - // Open the skel channel in current session - void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "skel", 0); - - unsigned long written = 0; - // Write the data to the channel - bool ret = WTSVirtualChannelWrite(channel, data, DSIZE, &written); - if (!ret) - { - long err = GetLastError(); - fprintf(stderr, "error 0x%8.8x\n", err); - return 1; - } - - ret = WTSVirtualChannelRead(channel, 100, data1, DSIZE, &written); - if (!ret) - { - long err = GetLastError(); - fprintf(stderr, "error 0x%8.8x\n", err); - return 1; - } - if (written != DSIZE) - { - fprintf(stderr, "error read %d\n", written); - return 1; - } - - ret = WTSVirtualChannelClose(channel); - if (memcmp(data, data1, DSIZE) == 0) - { - } - else - { - fprintf(stderr, "error data no match\n"); - return 1; - } - - fprintf(stderr, "Success!\n"); - - Sleep(2000); - return 0; -} diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index 2143f6c76..de78217bd 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -53,7 +53,6 @@ #include #include -#include typedef struct _SERIAL_DEVICE SERIAL_DEVICE; @@ -100,13 +99,10 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) { irp->IoStatus = STATUS_UNSUCCESSFUL; FileId = 0; - - DEBUG_WARN("failed to create %s", path); } else { serial->tty = tty; - DEBUG_SVC("%s(%d) created.", serial->path, FileId); } Stream_Write_UINT32(irp->output, FileId); /* FileId (4 bytes) */ @@ -126,12 +122,9 @@ static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp) if (!tty) { irp->IoStatus = STATUS_UNSUCCESSFUL; - DEBUG_WARN("tty not valid."); } else { - DEBUG_SVC("%s(%d) closed.", serial->path, tty->id); - serial_tty_free(tty); serial->tty = NULL; } @@ -156,8 +149,6 @@ static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; - - DEBUG_WARN("tty not valid."); } else { @@ -169,12 +160,10 @@ static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) free(buffer); buffer = NULL; Length = 0; - - DEBUG_WARN("read %s(%d) failed.", serial->path, tty->id); } else { - DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, tty->id); + } } @@ -207,8 +196,6 @@ static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp) irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; - DEBUG_WARN("tty not valid."); - Stream_Write_UINT32(irp->output, Length); /* Length (4 bytes) */ Stream_Write_UINT8(irp->output, 0); /* Padding (1 byte) */ irp->Complete(irp); @@ -252,8 +239,6 @@ static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp) { irp->IoStatus = STATUS_UNSUCCESSFUL; OutputBufferLength = 0; - - DEBUG_WARN("tty not valid."); } else { @@ -291,7 +276,6 @@ static void serial_process_irp(SERIAL_DEVICE* serial, IRP* irp) break; default: - DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; diff --git a/channels/serial/client/serial_tty.c b/channels/serial/client/serial_tty.c index 44faca061..9e65a71ef 100644 --- a/channels/serial/client/serial_tty.c +++ b/channels/serial/client/serial_tty.c @@ -30,7 +30,6 @@ #include #include -#include #include #ifndef _WIN32 @@ -119,19 +118,16 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, case IOCTL_SERIAL_SET_BAUD_RATE: Stream_Read_UINT32(input, tty->baud_rate); tty_set_termios(tty); - DEBUG_SVC("SERIAL_SET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_GET_BAUD_RATE: OutputBufferLength = 4; Stream_Write_UINT32(output, tty->baud_rate); - DEBUG_SVC("SERIAL_GET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_SET_QUEUE_SIZE: Stream_Read_UINT32(input, tty->queue_in_size); Stream_Read_UINT32(input, tty->queue_out_size); - DEBUG_SVC("SERIAL_SET_QUEUE_SIZE in %d out %d", tty->queue_in_size, tty->queue_out_size); break; case IOCTL_SERIAL_SET_LINE_CONTROL: @@ -139,12 +135,9 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, Stream_Read_UINT8(input, tty->parity); Stream_Read_UINT8(input, tty->word_length); tty_set_termios(tty); - DEBUG_SVC("SERIAL_SET_LINE_CONTROL stop %d parity %d word %d", - tty->stop_bits, tty->parity, tty->word_length); break; case IOCTL_SERIAL_GET_LINE_CONTROL: - DEBUG_SVC("SERIAL_GET_LINE_CONTROL"); OutputBufferLength = 3; Stream_Write_UINT8(output, tty->stop_bits); Stream_Write_UINT8(output, tty->parity); @@ -152,25 +145,21 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_IMMEDIATE_CHAR: - DEBUG_SVC("SERIAL_IMMEDIATE_CHAR"); Stream_Read_UINT8(input, immediate); tty_write_data(tty, &immediate, 1); break; case IOCTL_SERIAL_CONFIG_SIZE: - DEBUG_SVC("SERIAL_CONFIG_SIZE"); OutputBufferLength = 4; Stream_Write_UINT32(output, 0); break; case IOCTL_SERIAL_GET_CHARS: - DEBUG_SVC("SERIAL_GET_CHARS"); OutputBufferLength = 6; Stream_Write(output, tty->chars, 6); break; case IOCTL_SERIAL_SET_CHARS: - DEBUG_SVC("SERIAL_SET_CHARS"); Stream_Read(input, tty->chars, 6); tty_set_termios(tty); break; @@ -182,8 +171,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, Stream_Write_UINT32(output, tty->xonoff); Stream_Write_UINT32(output, tty->onlimit); Stream_Write_UINT32(output, tty->offlimit); - DEBUG_SVC("IOCTL_SERIAL_GET_HANDFLOW %X %X %X %X", - tty->control, tty->xonoff, tty->onlimit, tty->offlimit); break; case IOCTL_SERIAL_SET_HANDFLOW: @@ -191,8 +178,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, Stream_Read_UINT32(input, tty->xonoff); Stream_Read_UINT32(input, tty->onlimit); Stream_Read_UINT32(input, tty->offlimit); - DEBUG_SVC("IOCTL_SERIAL_SET_HANDFLOW %X %X %X %X", - tty->control, tty->xonoff, tty->onlimit, tty->offlimit); tty_set_termios(tty); break; @@ -211,17 +196,9 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, tty->read_total_timeout_multiplier = 0; } - DEBUG_SVC("SERIAL_SET_TIMEOUTS read timeout %d %d %d", - tty->read_interval_timeout, - tty->read_total_timeout_multiplier, - tty->read_total_timeout_constant); break; case IOCTL_SERIAL_GET_TIMEOUTS: - DEBUG_SVC("SERIAL_GET_TIMEOUTS read timeout %d %d %d", - tty->read_interval_timeout, - tty->read_total_timeout_multiplier, - tty->read_total_timeout_constant); OutputBufferLength = 20; Stream_Write_UINT32(output, tty->read_interval_timeout); Stream_Write_UINT32(output, tty->read_total_timeout_multiplier); @@ -231,18 +208,15 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_GET_WAIT_MASK: - DEBUG_SVC("SERIAL_GET_WAIT_MASK %X", tty->wait_mask); OutputBufferLength = 4; Stream_Write_UINT32(output, tty->wait_mask); break; case IOCTL_SERIAL_SET_WAIT_MASK: Stream_Read_UINT32(input, tty->wait_mask); - DEBUG_SVC("SERIAL_SET_WAIT_MASK %X", tty->wait_mask); break; case IOCTL_SERIAL_SET_DTR: - DEBUG_SVC("SERIAL_SET_DTR"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); @@ -250,7 +224,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_CLR_DTR: - DEBUG_SVC("SERIAL_CLR_DTR"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); @@ -258,7 +231,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_SET_RTS: - DEBUG_SVC("SERIAL_SET_RTS"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); @@ -266,7 +238,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_CLR_RTS: - DEBUG_SVC("SERIAL_CLR_RTS"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); @@ -290,7 +261,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, if (result & TIOCM_RTS) modemstate |= SERIAL_MS_RTS; #endif - DEBUG_SVC("SERIAL_GET_MODEMSTATUS %X", modemstate); OutputBufferLength = 4; Stream_Write_UINT32(output, modemstate); break; @@ -305,23 +275,18 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, ioctl(tty->fd, TIOCINQ, &result); #endif Stream_Write_UINT32(output, result); /* Amount in in queue */ - if (result) - DEBUG_SVC("SERIAL_GET_COMMSTATUS in queue %d", result); result = 0; #ifdef TIOCOUTQ ioctl(tty->fd, TIOCOUTQ, &result); #endif Stream_Write_UINT32(output, result); /* Amount in out queue */ - DEBUG_SVC("SERIAL_GET_COMMSTATUS out queue %d", result); - Stream_Write_UINT8(output, 0); /* EofReceived */ Stream_Write_UINT8(output, 0); /* WaitForImmediate */ break; case IOCTL_SERIAL_PURGE: Stream_Read_UINT32(input, purge_mask); - DEBUG_SVC("SERIAL_PURGE purge_mask %X", purge_mask); /* See http://msdn.microsoft.com/en-us/library/ms901431.aspx PURGE_TXCLEAR Clears the output buffer, if the driver has one. @@ -330,25 +295,16 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, It clearly states to clear the *driver* buffer, not the port buffer */ -#ifdef DEBUG_SVC - if (purge_mask & SERIAL_PURGE_TXCLEAR) - DEBUG_SVC("Ignoring SERIAL_PURGE_TXCLEAR"); - if (purge_mask & SERIAL_PURGE_RXCLEAR) - DEBUG_SVC("Ignoring SERIAL_PURGE_RXCLEAR"); -#endif - if (purge_mask & SERIAL_PURGE_TXABORT) *abortIo |= SERIAL_ABORT_IO_WRITE; if (purge_mask & SERIAL_PURGE_RXABORT) *abortIo |= SERIAL_ABORT_IO_READ; break; case IOCTL_SERIAL_WAIT_ON_MASK: - DEBUG_SVC("SERIAL_WAIT_ON_MASK %X", tty->wait_mask); tty->event_pending = 1; OutputBufferLength = 4; if (serial_tty_get_event(tty, &result)) { - DEBUG_SVC("WAIT end event = %X", result); Stream_Write_UINT32(output, result); break; } @@ -356,29 +312,23 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_SET_BREAK_ON: - DEBUG_SVC("SERIAL_SET_BREAK_ON"); tcsendbreak(tty->fd, 0); break; case IOCTL_SERIAL_RESET_DEVICE: - DEBUG_SVC("SERIAL_RESET_DEVICE"); break; case IOCTL_SERIAL_SET_BREAK_OFF: - DEBUG_SVC("SERIAL_SET_BREAK_OFF"); break; case IOCTL_SERIAL_SET_XOFF: - DEBUG_SVC("SERIAL_SET_XOFF"); break; case IOCTL_SERIAL_SET_XON: - DEBUG_SVC("SERIAL_SET_XON"); tcflow(tty->fd, TCION); break; default: - DEBUG_SVC("NOT FOUND IoControlCode SERIAL IOCTL 0x%08X", IoControlCode); return STATUS_INVALID_PARAMETER; } @@ -457,11 +407,7 @@ BOOL serial_tty_read(SERIAL_TTY* tty, BYTE* buffer, UINT32* Length) status = read(tty->fd, buffer, *Length); if (status < 0) - { - DEBUG_WARN("failed with %zd, errno=[%d] %s\n", - status, errno, strerror(errno)); return FALSE; - } tty->event_txempty = status; *Length = status; @@ -535,13 +481,12 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id) if (tty->fd < 0) { perror("open"); - DEBUG_WARN("failed to open device %s", path); serial_tty_free(tty); return NULL; } else { - DEBUG_SVC("tty fd %d successfully opened", tty->fd); + } tty->ptermios = (struct termios*) calloc(1, sizeof(struct termios)); @@ -563,7 +508,6 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id) if (!tty_get_termios(tty)) { - DEBUG_WARN("%s access denied", path); fflush(stdout); serial_tty_free(tty); return NULL; @@ -589,7 +533,6 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id) /* all read and writes should be non-blocking */ if (fcntl(tty->fd, F_SETFL, O_NONBLOCK) == -1) { - DEBUG_WARN("%s fcntl", path); perror("fcntl"); serial_tty_free(tty) ; return NULL; @@ -620,15 +563,12 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result) if (bytes > 0) { - DEBUG_SVC("bytes %d", bytes); - if (bytes > tty->event_rlsd) { tty->event_rlsd = bytes; if (tty->wait_mask & SERIAL_EV_RLSD) { - DEBUG_SVC("SERIAL_EV_RLSD"); *result |= SERIAL_EV_RLSD; status = TRUE; } @@ -636,14 +576,12 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result) if ((bytes > 1) && (tty->wait_mask & SERIAL_EV_RXFLAG)) { - DEBUG_SVC("SERIAL_EV_RXFLAG bytes %d", bytes); *result |= SERIAL_EV_RXFLAG; status = TRUE; } if ((tty->wait_mask & SERIAL_EV_RXCHAR)) { - DEBUG_SVC("SERIAL_EV_RXCHAR bytes %d", bytes); *result |= SERIAL_EV_RXCHAR; status = TRUE; } @@ -658,7 +596,6 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result) ioctl(tty->fd, TIOCOUTQ, &bytes); if ((bytes == 0) && (tty->event_txempty > 0) && (tty->wait_mask & SERIAL_EV_TXEMPTY)) { - DEBUG_SVC("SERIAL_EV_TXEMPTY"); *result |= SERIAL_EV_TXEMPTY; status = TRUE; } @@ -669,9 +606,9 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result) if ((bytes & TIOCM_DSR) != tty->event_dsr) { tty->event_dsr = bytes & TIOCM_DSR; + if (tty->wait_mask & SERIAL_EV_DSR) { - DEBUG_SVC("SERIAL_EV_DSR %s", (bytes & TIOCM_DSR) ? "ON" : "OFF"); *result |= SERIAL_EV_DSR; status = TRUE; } @@ -680,9 +617,9 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result) if ((bytes & TIOCM_CTS) != tty->event_cts) { tty->event_cts = bytes & TIOCM_CTS; + if (tty->wait_mask & SERIAL_EV_CTS) { - DEBUG_SVC("SERIAL_EV_CTS %s", (bytes & TIOCM_CTS) ? "ON" : "OFF"); *result |= SERIAL_EV_CTS; status = TRUE; } @@ -700,8 +637,6 @@ static BOOL tty_get_termios(SERIAL_TTY* tty) struct termios* ptermios; ptermios = tty->ptermios; - DEBUG_SVC("tcgetattr? %d", tcgetattr(tty->fd, ptermios) >= 0); - if (tcgetattr(tty->fd, ptermios) < 0) return FALSE; diff --git a/client/Windows/cli/wfreerdp.c b/client/Windows/cli/wfreerdp.c index f19cc7ecc..c5f5fa0a8 100644 --- a/client/Windows/cli/wfreerdp.c +++ b/client/Windows/cli/wfreerdp.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c index 7efbac346..cb942d6cd 100644 --- a/client/Windows/wf_interface.c +++ b/client/Windows/wf_interface.c @@ -43,9 +43,7 @@ #include #include #include -#include -//#include #include #include #include diff --git a/include/freerdp/utils/svc_plugin.h b/include/freerdp/utils/svc_plugin.h index 6100c2cd7..82d55225a 100644 --- a/include/freerdp/utils/svc_plugin.h +++ b/include/freerdp/utils/svc_plugin.h @@ -55,7 +55,7 @@ struct rdp_svc_plugin void* InitHandle; DWORD OpenHandle; wMessagePipe* MsgPipe; - wStreamPool *pool; + wStreamPool *pool; }; #ifdef __cplusplus From 2a82684521dc8b23ae92e284e866227e5194a7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 11 Jun 2014 16:27:31 -0400 Subject: [PATCH 31/50] channels: cleanup unused freerdp channels global functions --- .../FreeRDPCore/jni/android_jni_utils.c | 2 -- client/DirectFB/dfreerdp.c | 4 --- client/Mac/MRDPView.m | 2 -- client/Mac/mf_client.m | 3 +-- client/Sample/freerdp.c | 4 --- client/Windows/wf_interface.c | 2 -- client/X11/xf_client.c | 3 +-- client/iOS/FreeRDP/ios_freerdp.m | 3 +-- cunit/test_cliprdr.c | 2 -- cunit/test_drdynvc.c | 2 -- cunit/test_rail.c | 2 -- include/freerdp/channels/channels.h | 2 -- libfreerdp/core/client.c | 25 +++---------------- libfreerdp/utils/svc_plugin.c | 6 ++--- 14 files changed, 10 insertions(+), 52 deletions(-) diff --git a/client/Android/FreeRDPCore/jni/android_jni_utils.c b/client/Android/FreeRDPCore/jni/android_jni_utils.c index 4e6357b3a..f83f74938 100644 --- a/client/Android/FreeRDPCore/jni/android_jni_utils.c +++ b/client/Android/FreeRDPCore/jni/android_jni_utils.c @@ -203,8 +203,6 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) result = init_callback_environment(vm); setlocale(LC_ALL, ""); - - freerdp_channels_global_init(); return result; } diff --git a/client/DirectFB/dfreerdp.c b/client/DirectFB/dfreerdp.c index cc621480b..df68a1d6c 100644 --- a/client/DirectFB/dfreerdp.c +++ b/client/DirectFB/dfreerdp.c @@ -441,8 +441,6 @@ int main(int argc, char* argv[]) setlocale(LC_ALL, ""); - freerdp_channels_global_init(); - g_sem = CreateSemaphore(NULL, 0, 1, NULL); instance = freerdp_new(); @@ -484,7 +482,5 @@ int main(int argc, char* argv[]) WaitForSingleObject(g_sem, INFINITE); } - freerdp_channels_global_uninit(); - return 0; } diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index fda9a8dcc..5de0da47f 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -760,8 +760,6 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type) return; gdi_free(context->instance); - - freerdp_channels_global_uninit(); if (pixel_data) free(pixel_data); diff --git a/client/Mac/mf_client.m b/client/Mac/mf_client.m index b9b16171f..9b22e94c8 100755 --- a/client/Mac/mf_client.m +++ b/client/Mac/mf_client.m @@ -33,12 +33,11 @@ void mfreerdp_client_global_init() { freerdp_handle_signals(); - freerdp_channels_global_init(); } void mfreerdp_client_global_uninit() { - freerdp_channels_global_uninit(); + } int mfreerdp_client_start(rdpContext* context) diff --git a/client/Sample/freerdp.c b/client/Sample/freerdp.c index 065cada69..4495bf9a9 100644 --- a/client/Sample/freerdp.c +++ b/client/Sample/freerdp.c @@ -305,8 +305,6 @@ int main(int argc, char* argv[]) rdpChannels* channels; struct thread_data* data; - freerdp_channels_global_init(); - g_sem = CreateSemaphore(NULL, 0, 1, NULL); instance = freerdp_new(); @@ -341,7 +339,5 @@ int main(int argc, char* argv[]) WaitForSingleObject(g_sem, INFINITE); } - freerdp_channels_global_uninit(); - return 0; } diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c index cb942d6cd..ec7c70db2 100644 --- a/client/Windows/wf_interface.c +++ b/client/Windows/wf_interface.c @@ -1169,8 +1169,6 @@ void wfreerdp_client_global_init(void) wf_create_console(); #endif - freerdp_channels_global_init(); - freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); } diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 7fddd874b..5cf4c6350 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -1787,12 +1787,11 @@ static void xfreerdp_client_global_init() { setlocale(LC_ALL, ""); freerdp_handle_signals(); - freerdp_channels_global_init(); } static void xfreerdp_client_global_uninit() { - freerdp_channels_global_uninit(); + } static int xfreerdp_client_start(rdpContext* context) diff --git a/client/iOS/FreeRDP/ios_freerdp.m b/client/iOS/FreeRDP/ios_freerdp.m index a6eac2ce8..fa8c75383 100644 --- a/client/iOS/FreeRDP/ios_freerdp.m +++ b/client/iOS/FreeRDP/ios_freerdp.m @@ -303,12 +303,11 @@ void ios_freerdp_free(freerdp* instance) void ios_init_freerdp() { signal(SIGPIPE, SIG_IGN); - freerdp_channels_global_init(); freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); } void ios_uninit_freerdp() { - freerdp_channels_global_uninit(); + } diff --git a/cunit/test_cliprdr.c b/cunit/test_cliprdr.c index 6b329a8fd..85fb580ef 100644 --- a/cunit/test_cliprdr.c +++ b/cunit/test_cliprdr.c @@ -31,13 +31,11 @@ int init_cliprdr_suite(void) { - freerdp_channels_global_init(); return 0; } int clean_cliprdr_suite(void) { - freerdp_channels_global_uninit(); return 0; } diff --git a/cunit/test_drdynvc.c b/cunit/test_drdynvc.c index fcbadcf22..64b5a59a2 100644 --- a/cunit/test_drdynvc.c +++ b/cunit/test_drdynvc.c @@ -31,13 +31,11 @@ int init_drdynvc_suite(void) { - freerdp_channels_global_init(); return 0; } int clean_drdynvc_suite(void) { - freerdp_channels_global_uninit(); return 0; } diff --git a/cunit/test_rail.c b/cunit/test_rail.c index 601024d5c..461701c51 100644 --- a/cunit/test_rail.c +++ b/cunit/test_rail.c @@ -46,13 +46,11 @@ int init_rail_suite(void) { - freerdp_channels_global_init(); return 0; } int clean_rail_suite(void) { - freerdp_channels_global_uninit(); return 0; } diff --git a/include/freerdp/channels/channels.h b/include/freerdp/channels/channels.h index c136411dd..60b481d17 100644 --- a/include/freerdp/channels/channels.h +++ b/include/freerdp/channels/channels.h @@ -32,8 +32,6 @@ extern "C" { #endif -FREERDP_API int freerdp_channels_global_init(void); -FREERDP_API int freerdp_channels_global_uninit(void); FREERDP_API rdpChannels* freerdp_channels_new(void); FREERDP_API void freerdp_channels_free(rdpChannels* channels); FREERDP_API int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, diff --git a/libfreerdp/core/client.c b/libfreerdp/core/client.c index cc13e28f8..5f4aec1e6 100644 --- a/libfreerdp/core/client.c +++ b/libfreerdp/core/client.c @@ -72,27 +72,14 @@ rdpMcsChannel* freerdp_channels_find_channel_by_name(rdpRdp* rdp, const char* na return NULL; } -/** - * this is called shortly after the application starts and - * before any other function in the file - * called only from main thread - */ -int freerdp_channels_global_init(void) -{ - return 0; -} - -int freerdp_channels_global_uninit(void) -{ - return 0; -} - rdpChannels* freerdp_channels_new(void) { rdpChannels* channels; - channels = (rdpChannels*) malloc(sizeof(rdpChannels)); - ZeroMemory(channels, sizeof(rdpChannels)); + channels = (rdpChannels*) calloc(1, sizeof(rdpChannels)); + + if (!channels) + return NULL; channels->MsgPipe = MessagePipe_New(); @@ -280,10 +267,6 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* eve switch (GetMessageClass(event->id)) { - case DebugChannel_Class: - name = "rdpdbg"; - break; - case CliprdrChannel_Class: name = "cliprdr"; break; diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index 578c91562..b5787438a 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -298,15 +298,15 @@ void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints) plugin->channel_entry_points.pInterface = *(plugin->channel_entry_points.ppInterface); plugin->channel_entry_points.ppInterface = &(plugin->channel_entry_points.pInterface); plugin->started = CreateEvent(NULL,TRUE,FALSE,NULL); - plugin->pool = StreamPool_New(TRUE, 10); + plugin->pool = StreamPool_New(TRUE, 10); svc_plugin_add_init_handle_data(plugin->InitHandle, plugin); } void svc_plugin_terminate(rdpSvcPlugin* plugin) { - StreamPool_Free(plugin->pool); - CloseHandle(plugin->started); + StreamPool_Free(plugin->pool); + CloseHandle(plugin->started); } int svc_plugin_send(rdpSvcPlugin* plugin, wStream* data_out) From fbea223ecf789306585c0b1adfbd966c921990e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 11 Jun 2014 17:48:04 -0400 Subject: [PATCH 32/50] channels/gfx: add surface table helper, surface creation/deletion --- channels/rdpgfx/client/rdpgfx_main.c | 38 ++++++++++++++++++++++++++++ channels/rdpgfx/client/rdpgfx_main.h | 3 +++ client/X11/xf_gfx.c | 36 ++++++++++++++++++++++++++ client/X11/xf_gfx.h | 11 ++++++++ include/freerdp/client/rdpgfx.h | 6 +++++ 5 files changed, 94 insertions(+) diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 2b50e9ce8..b6d9f3b2f 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -854,11 +854,41 @@ static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin) zgfx_context_free(gfx->zgfx); + HashTable_Free(gfx->SurfaceTable); + free(gfx); return 0; } +int rdpgfx_set_surface_data(RdpgfxClientContext* context, UINT16 surfaceId, void* pData) +{ + ULONG_PTR key; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; + + key = ((ULONG_PTR) surfaceId) + 1; + + if (pData) + HashTable_Add(gfx->SurfaceTable, (void*) key, pData); + else + HashTable_Remove(gfx->SurfaceTable, (void*) key); + + return 1; +} + +void* rdpgfx_get_surface_data(RdpgfxClientContext* context, UINT16 surfaceId) +{ + ULONG_PTR key; + void* pData = NULL; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; + + key = ((ULONG_PTR) surfaceId) + 1; + + pData = HashTable_GetItemValue(gfx->SurfaceTable, (void*) key); + + return pData; +} + #ifdef STATIC_CHANNELS #define DVCPluginEntry rdpgfx_DVCPluginEntry #endif @@ -885,6 +915,11 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) gfx->iface.Disconnected = NULL; gfx->iface.Terminated = rdpgfx_plugin_terminated; + gfx->SurfaceTable = HashTable_New(TRUE); + + if (!gfx->SurfaceTable) + return -1; + context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext)); if (!context) @@ -892,6 +927,9 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) context->handle = (void*) gfx; + context->SetSurfaceData = rdpgfx_set_surface_data; + context->GetSurfaceData = rdpgfx_get_surface_data; + gfx->iface.pInterface = (void*) context; gfx->zgfx = zgfx_context_new(FALSE); diff --git a/channels/rdpgfx/client/rdpgfx_main.h b/channels/rdpgfx/client/rdpgfx_main.h index ace81bef3..da0e64822 100644 --- a/channels/rdpgfx/client/rdpgfx_main.h +++ b/channels/rdpgfx/client/rdpgfx_main.h @@ -25,6 +25,7 @@ #include #include +#include #include @@ -66,6 +67,8 @@ struct _RDPGFX_PLUGIN ZGFX_CONTEXT* zgfx; UINT32 UnacknowledgedFrames; UINT32 TotalDecodedFrames; + + wHashTable* SurfaceTable; }; typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index b068c5d54..8cea5027e 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -306,16 +306,52 @@ int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODIN int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface) { + xfGfxSurface* surface; + xfContext* xfc = (xfContext*) context->custom; + printf("xf_CreateSurface: surfaceId: %d width: %d height: %d format: 0x%02X\n", createSurface->surfaceId, createSurface->width, createSurface->height, createSurface->pixelFormat); + surface = (xfGfxSurface*) calloc(1, sizeof(xfGfxSurface)); + + if (!surface) + return -1; + + surface->surfaceId = createSurface->surfaceId; + surface->width = (UINT32) createSurface->width; + surface->height = (UINT32) createSurface->height; + surface->alpha = (createSurface->pixelFormat == PIXEL_FORMAT_ARGB_8888) ? TRUE : FALSE; + + surface->data = (BYTE*) calloc(1, surface->width * surface->height * 4); + + if (!surface->data) + return -1; + + surface->image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, + (char*) surface->data, surface->width, surface->height, 32, 0); + + context->SetSurfaceData(context, surface->surfaceId, (void*) surface); + return 1; } int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface) { + xfGfxSurface* surface = NULL; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, deleteSurface->surfaceId); + printf("xf_DeleteSurface: surfaceId: %d\n", deleteSurface->surfaceId); + if (surface) + { + XFree(surface->image); + free(surface->data); + free(surface); + } + + context->SetSurfaceData(context, deleteSurface->surfaceId, NULL); + return 1; } diff --git a/client/X11/xf_gfx.h b/client/X11/xf_gfx.h index 01a61b9db..efc7c46dd 100644 --- a/client/X11/xf_gfx.h +++ b/client/X11/xf_gfx.h @@ -23,6 +23,17 @@ #include "xf_client.h" #include "xfreerdp.h" +struct xf_gfx_surface +{ + UINT16 surfaceId; + UINT32 width; + UINT32 height; + BOOL alpha; + BYTE* data; + XImage* image; +}; +typedef struct xf_gfx_surface xfGfxSurface; + void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx); #endif /* __XF_GRAPHICS_PIPELINE_H */ diff --git a/include/freerdp/client/rdpgfx.h b/include/freerdp/client/rdpgfx.h index b2c0dda70..64c1155a1 100644 --- a/include/freerdp/client/rdpgfx.h +++ b/include/freerdp/client/rdpgfx.h @@ -45,6 +45,9 @@ typedef int (*pcRdpgfxEvictCacheEntry)(RdpgfxClientContext* context, RDPGFX_EVIC typedef int (*pcRdpgfxMapSurfaceToOutput)(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput); typedef int (*pcRdpgfxMapSurfaceToWindow)(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow); +typedef int (*pcRdpgfxSetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId, void* pData); +typedef void* (*pcRdpgfxGetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId); + struct _rdpgfx_client_context { void* handle; @@ -66,6 +69,9 @@ struct _rdpgfx_client_context pcRdpgfxEvictCacheEntry EvictCacheEntry; pcRdpgfxMapSurfaceToOutput MapSurfaceToOutput; pcRdpgfxMapSurfaceToWindow MapSurfaceToWindow; + + pcRdpgfxSetSurfaceData SetSurfaceData; + pcRdpgfxGetSurfaceData GetSurfaceData; }; #endif /* FREERDP_CHANNEL_CLIENT_RDPGFX_H */ From ae02b5b512e92b6b1200ab85648ec5d91007ac5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 12 Jun 2014 16:13:12 -0400 Subject: [PATCH 33/50] xfreerdp: start handling egfx surface-to-surface --- client/X11/xf_event.c | 7 ++ client/X11/xf_gfx.c | 202 +++++++++++++++++++++++----------- client/X11/xf_gfx.h | 3 + client/X11/xfreerdp.h | 2 + include/freerdp/codec/color.h | 130 +++++++++++++--------- libfreerdp/codec/color.c | 11 +- 6 files changed, 239 insertions(+), 116 deletions(-) diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index 169a31126..a4692fe3a 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -30,6 +30,7 @@ #include "xf_window.h" #include "xf_cliprdr.h" #include "xf_input.h" +#include "xf_gfx.h" #include "xf_event.h" #include "xf_input.h" @@ -190,6 +191,12 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) w = event->xexpose.width; h = event->xexpose.height; + if (xfc->gfx) + { + xf_OutputExpose(xfc, x, y, w, h); + return TRUE; + } + if (!app) { if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 8cea5027e..0d20244b3 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -56,15 +56,26 @@ int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* re region16_init(&(xfc->invalidRegion)); + xfc->graphicsReset = TRUE; + return 1; } -int xf_SurfaceUpdate(xfContext* xfc) +int xf_OutputUpdate(xfContext* xfc) { UINT16 width, height; + xfGfxSurface* surface; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; + if (!xfc->graphicsReset) + return 1; + + surface = (xfGfxSurface*) xfc->gfx->GetSurfaceData(xfc->gfx, xfc->outputSurfaceId); + + if (!surface) + return -1; + surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = xfc->width - 1; @@ -72,6 +83,10 @@ int xf_SurfaceUpdate(xfContext* xfc) region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect); + XSetClipMask(xfc->display, xfc->gc, None); + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + if (!region16_is_empty(&(xfc->invalidRegion))) { extents = region16_extents(&(xfc->invalidRegion)); @@ -85,27 +100,39 @@ int xf_SurfaceUpdate(xfContext* xfc) if (height > xfc->height) height = xfc->height; - printf("xf_SurfaceUpdate: x: %d y: %d width: %d height: %d\n", + XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, + extents->left, extents->top, extents->left, extents->top, width, height); } - else - { - printf("xf_SurfaceUpdate: null region\n"); - } region16_clear(&(xfc->invalidRegion)); + XSetClipMask(xfc->display, xfc->gc, None); XSync(xfc->display, True); return 1; } +int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height) +{ + RECTANGLE_16 invalidRect; + + invalidRect.left = x; + invalidRect.top = y; + invalidRect.right = x + width - 1; + invalidRect.bottom = y + height - 1; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + + xf_OutputUpdate(xfc); + + return 1; +} + int xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame) { xfContext* xfc = (xfContext*) context->custom; - printf("xf_StartFrame: %d\n", startFrame->frameId); - xfc->inGfxFrame = TRUE; return 1; @@ -115,9 +142,7 @@ int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame) { xfContext* xfc = (xfContext*) context->custom; - printf("xf_EndFrame: %d\n", endFrame->frameId); - - xf_SurfaceUpdate(xfc); + xf_OutputUpdate(xfc); xfc->inGfxFrame = FALSE; @@ -126,26 +151,20 @@ int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame) int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { - BYTE* data; - XImage* image; + xfGfxSurface* surface; RECTANGLE_16 invalidRect; printf("xf_SurfaceCommand_Uncompressed\n"); - XSetFunction(xfc->display, xfc->gc, GXcopy); - XSetFillStyle(xfc->display, xfc->gc, FillSolid); + surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); - data = (BYTE*) malloc(cmd->width * cmd->height * 4); + if (!surface) + return -1; - freerdp_image_flip(cmd->data, data, cmd->width, cmd->height, 32); + /* TODO: bitmap flipping in freerdp_image_copy */ - image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, (char*) data, cmd->width, cmd->height, 32, 0); - - XPutImage(xfc->display, xfc->drawing, xfc->gc, image, 0, 0, cmd->left, cmd->top, cmd->width, cmd->height); - - XFree(image); - - free(data); + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, + cmd->width, cmd->height, cmd->data, PIXEL_FORMAT_XRGB32_VF, cmd->width * 4, 0, 0); invalidRect.left = cmd->left; invalidRect.top = cmd->top; @@ -154,10 +173,8 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); - XSetClipMask(xfc->display, xfc->gc, None); - if (!xfc->inGfxFrame) - xf_SurfaceUpdate(xfc); + xf_OutputUpdate(xfc); return 1; } @@ -165,15 +182,19 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { UINT16 index; - XImage* image; RFX_RECT* rect; RFX_TILE* tile; - XRectangle* xrects; + int nXDst, nYDst; + int nWidth, nHeight; RFX_MESSAGE* message; + xfGfxSurface* surface; RECTANGLE_16 invalidRect; RECTANGLE_16 surfaceRect; - printf("xf_SurfaceCommand_RemoteFX\n"); + surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + + if (!surface) + return -1; surfaceRect.left = 0; surfaceRect.top = 0; @@ -185,20 +206,10 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP if (!message) return -1; - xrects = (XRectangle*) malloc(message->numRects * sizeof(XRectangle)); - - if (!xrects) - return -1; - for (index = 0; index < message->numRects; index++) { rect = &(message->rects[index]); - xrects[index].x = cmd->left + rect->x; - xrects[index].y = cmd->top + rect->y; - xrects[index].width = rect->width; - xrects[index].height = rect->height; - invalidRect.left = cmd->left + rect->x; invalidRect.top = cmd->top + rect->y; invalidRect.right = invalidRect.left + rect->width - 1; @@ -207,51 +218,47 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); } - XSetFunction(xfc->display, xfc->gc, GXcopy); - XSetFillStyle(xfc->display, xfc->gc, FillSolid); - - XSetClipRectangles(xfc->display, xfc->gc, cmd->left, cmd->top, xrects, message->numRects, YXBanded); - for (index = 0; index < message->numTiles; index++) { tile = message->tiles[index]; - image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, - (char*) tile->data, 64, 64, 32, 0); + nWidth = nHeight = 64; + nXDst = cmd->left + tile->x; + nYDst = cmd->top + tile->y; - XPutImage(xfc->display, xfc->drawable, xfc->gc, image, 0, 0, - cmd->left + tile->x, cmd->top + tile->y, 64, 64); + if ((nXDst + nWidth) > surface->width) + nWidth = surface->width - nXDst; - XFree(image); + if (nYDst + nHeight > surface->height) + nHeight = surface->height - nYDst; + + /* TODO: properly handle RemoteFX tile clipping */ + + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + nXDst, nYDst, nWidth, nHeight, + tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0); } - XSetClipMask(xfc->display, xfc->gc, None); - rfx_message_free(xfc->rfx, message); - free(xrects); if (!xfc->inGfxFrame) - xf_SurfaceUpdate(xfc); + xf_OutputUpdate(xfc); return 1; } int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { - printf("xf_SurfaceCommand_ClearCodec\n"); - if (!xfc->inGfxFrame) - xf_SurfaceUpdate(xfc); + xf_OutputUpdate(xfc); return 1; } int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { - printf("xf_SurfaceCommand_Planar\n"); - if (!xfc->inGfxFrame) - xf_SurfaceUpdate(xfc); + xf_OutputUpdate(xfc); return 1; } @@ -272,10 +279,12 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) break; case RDPGFX_CODECID_CLEARCODEC: + printf("xf_SurfaceCommand_ClearCodec\n"); status = xf_SurfaceCommand_ClearCodec(xfc, context, cmd); break; case RDPGFX_CODECID_PLANAR: + printf("xf_SurfaceCommand_Planar\n"); status = xf_SurfaceCommand_Planar(xfc, context, cmd); break; @@ -301,6 +310,8 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext) { + printf("xf_DeleteEncodingContext\n"); + return 1; } @@ -322,7 +333,8 @@ int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* cr surface->height = (UINT32) createSurface->height; surface->alpha = (createSurface->pixelFormat == PIXEL_FORMAT_ARGB_8888) ? TRUE : FALSE; - surface->data = (BYTE*) calloc(1, surface->width * surface->height * 4); + surface->scanline = surface->width * 4; + surface->data = (BYTE*) calloc(1, surface->scanline * surface->height); if (!surface->data) return -1; @@ -405,23 +417,78 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill) free(xrects); if (!xfc->inGfxFrame) - xf_SurfaceUpdate(xfc); + xf_OutputUpdate(xfc); return 1; } int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) { + UINT16 index; + int nWidth, nHeight; + RDPGFX_RECT16* rectSrc; + RDPGFX_POINT16* destPt; + RECTANGLE_16 invalidRect; + xfGfxSurface* surfaceSrc; + xfGfxSurface* surfaceDst; + xfContext* xfc = (xfContext*) context->custom; + + rectSrc = &(surfaceToSurface->rectSrc); + destPt = &surfaceToSurface->destPts[0]; + + printf("xf_SurfaceToSurface: srcId: %d dstId: %d rect: x: %d y: %d w: %d h: %d ptsCount: %d x: %d y: %d\n", + (int) surfaceToSurface->surfaceIdSrc, (int) surfaceToSurface->surfaceIdDest, + rectSrc->left, rectSrc->top, rectSrc->right - rectSrc->left, + rectSrc->bottom - rectSrc->top, (int) surfaceToSurface->destPtsCount, + destPt->x, destPt->y); + + surfaceSrc = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc); + + if (surfaceToSurface->surfaceIdSrc != surfaceToSurface->surfaceIdDest) + surfaceDst = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest); + else + surfaceDst = surfaceSrc; + + if (!surfaceSrc || !surfaceDst) + return -1; + + nWidth = rectSrc->right - rectSrc->left + 1; + nHeight = rectSrc->bottom - rectSrc->top + 1; + + for (index = 0; index < surfaceToSurface->destPtsCount; index++) + { + destPt = &surfaceToSurface->destPts[index]; + + /* TODO: copy overlap handling in freerdp_image_copy */ + + freerdp_image_copy(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline, destPt->x, destPt->y, + nWidth, nHeight, surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceSrc->scanline, 0, 0); + + invalidRect.left = destPt->x; + invalidRect.top = destPt->y; + invalidRect.right = destPt->x + nWidth - 1; + invalidRect.bottom = destPt->y + nHeight - 1; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + } + + if (!xfc->inGfxFrame) + xf_OutputUpdate(xfc); + return 1; } int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache) { + printf("xf_SurfaceToCache\n"); + return 1; } int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface) { + printf("xf_CacheToSurface\n"); + return 1; } @@ -432,11 +499,20 @@ int xf_CacheImportReply(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY_ int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry) { + printf("xf_EvictCacheEntry\n"); + return 1; } int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput) { + xfContext* xfc = (xfContext*) context->custom; + + printf("xf_MapSurfaceToOutput: surfaceId: %d outputOriginX: %d outputOriginY: %d\n", + surfaceToOutput->surfaceId, surfaceToOutput->outputOriginX, surfaceToOutput->outputOriginY); + + xfc->outputSurfaceId = surfaceToOutput->surfaceId; + return 1; } @@ -465,4 +541,6 @@ void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx) gfx->EvictCacheEntry = xf_EvictCacheEntry; gfx->MapSurfaceToOutput = xf_MapSurfaceToOutput; gfx->MapSurfaceToWindow = xf_MapSurfaceToWindow; + + region16_init(&(xfc->invalidRegion)); } diff --git a/client/X11/xf_gfx.h b/client/X11/xf_gfx.h index efc7c46dd..623df31b0 100644 --- a/client/X11/xf_gfx.h +++ b/client/X11/xf_gfx.h @@ -31,9 +31,12 @@ struct xf_gfx_surface BOOL alpha; BYTE* data; XImage* image; + int scanline; }; typedef struct xf_gfx_surface xfGfxSurface; +int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height); + void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx); #endif /* __XF_GRAPHICS_PIPELINE_H */ diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 6f4394014..347d7c62f 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -113,6 +113,8 @@ struct xf_context BYTE* primary_buffer; REGION16 invalidRegion; BOOL inGfxFrame; + BOOL graphicsReset; + UINT16 outputSurfaceId; BOOL frame_begin; UINT16 frame_x1; diff --git a/include/freerdp/codec/color.h b/include/freerdp/codec/color.h index fc14f1518..489aab960 100644 --- a/include/freerdp/codec/color.h +++ b/include/freerdp/codec/color.h @@ -33,8 +33,8 @@ #define FREERDP_PIXEL_FLIP_VERTICAL 1 #define FREERDP_PIXEL_FLIP_HORIZONTAL 2 -#define FREERDP_PIXEL_FORMAT(_bpp, _type, _a, _r, _g, _b) \ - ((_bpp << 24) | (_type << 16) | (_a << 12) | (_r << 8) | (_g << 4) | (_b)) +#define FREERDP_PIXEL_FORMAT(_flip, _bpp, _type, _a, _r, _g, _b) \ + ((_flip << 30) | (_bpp << 24) | (_type << 16) | (_a << 12) | (_r << 8) | (_g << 4) | (_b)) #define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 30) & 0x02) #define FREERDP_PIXEL_FORMAT_BPP(_format) (((_format) >> 24) & 0x3F) @@ -54,84 +54,110 @@ /* 32bpp formats */ -#define PIXEL_FORMAT_A8R8G8B8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 8, 8, 8, 8) -#define PIXEL_FORMAT_ARGB32 PIXEL_FORMAT_A8R8G8B8 +#define PIXEL_FORMAT_A8R8G8B8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 8, 8, 8, 8) +#define PIXEL_FORMAT_A8R8G8B8 PIXEL_FORMAT_A8R8G8B8_F(0) +#define PIXEL_FORMAT_ARGB32 PIXEL_FORMAT_A8R8G8B8 +#define PIXEL_FORMAT_A8R8G8B8_VF PIXEL_FORMAT_A8R8G8B8_F(1) +#define PIXEL_FORMAT_ARGB32_VF PIXEL_FORMAT_A8R8G8B8_VF -#define PIXEL_FORMAT_X8R8G8B8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8) -#define PIXEL_FORMAT_XRGB32 PIXEL_FORMAT_X8R8G8B8 -#define PIXEL_FORMAT_RGB32 PIXEL_FORMAT_XRGB32 +#define PIXEL_FORMAT_X8R8G8B8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8) +#define PIXEL_FORMAT_X8R8G8B8 PIXEL_FORMAT_X8R8G8B8_F(0) +#define PIXEL_FORMAT_XRGB32 PIXEL_FORMAT_X8R8G8B8 +#define PIXEL_FORMAT_RGB32 PIXEL_FORMAT_XRGB32 +#define PIXEL_FORMAT_X8R8G8B8_VF PIXEL_FORMAT_X8R8G8B8_F(1) +#define PIXEL_FORMAT_XRGB32_VF PIXEL_FORMAT_X8R8G8B8_VF +#define PIXEL_FORMAT_RGB32_VF PIXEL_FORMAT_XRGB32_VF -#define PIXEL_FORMAT_A8B8G8R8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 8, 8, 8, 8) -#define PIXEL_FORMAT_ABGR32 PIXEL_FORMAT_A8B8G8R8 +#define PIXEL_FORMAT_A8B8G8R8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 8, 8, 8, 8) +#define PIXEL_FORMAT_A8B8G8R8 PIXEL_FORMAT_A8B8G8R8_F(0) +#define PIXEL_FORMAT_ABGR32 PIXEL_FORMAT_A8B8G8R8 +#define PIXEL_FORMAT_A8B8G8R8_VF PIXEL_FORMAT_A8B8G8R8_F(1) +#define PIXEL_FORMAT_ABGR32_VF PIXEL_FORMAT_A8B8G8R8_VF -#define PIXEL_FORMAT_X8B8G8R8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8) -#define PIXEL_FORMAT_XBGR32 PIXEL_FORMAT_X8B8G8R8 -#define PIXEL_FORMAT_BGR32 PIXEL_FORMAT_XBGR32 +#define PIXEL_FORMAT_X8B8G8R8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8) +#define PIXEL_FORMAT_X8B8G8R8 PIXEL_FORMAT_X8B8G8R8_F(0) +#define PIXEL_FORMAT_XBGR32 PIXEL_FORMAT_X8B8G8R8 +#define PIXEL_FORMAT_BGR32 PIXEL_FORMAT_XBGR32 +#define PIXEL_FORMAT_X8B8G8R8_VF PIXEL_FORMAT_X8B8G8R8_F(1) +#define PIXEL_FORMAT_XBGR32_VF PIXEL_FORMAT_X8B8G8R8_VF +#define PIXEL_FORMAT_BGR32_VF PIXEL_FORMAT_XBGR32_VF -#define PIXEL_FORMAT_B8G8R8A8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 8, 8, 8, 8) -#define PIXEL_FORMAT_BGRA32 PIXEL_FORMAT_B8G8R8A8 +#define PIXEL_FORMAT_B8G8R8A8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 8, 8, 8, 8) +#define PIXEL_FORMAT_B8G8R8A8 PIXEL_FORMAT_B8G8R8A8_F(0) +#define PIXEL_FORMAT_BGRA32 PIXEL_FORMAT_B8G8R8A8 +#define PIXEL_FORMAT_B8G8R8A8_VF PIXEL_FORMAT_B8G8R8A8_F(1) +#define PIXEL_FORMAT_BGRA32_VF PIXEL_FORMAT_B8G8R8A8_VF -#define PIXEL_FORMAT_B8G8R8X8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 0, 8, 8, 8) -#define PIXEL_FORMAT_BGRX32 PIXEL_FORMAT_B8G8R8X8 +#define PIXEL_FORMAT_B8G8R8X8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 0, 8, 8, 8) +#define PIXEL_FORMAT_B8G8R8X8 PIXEL_FORMAT_B8G8R8X8_F(0) +#define PIXEL_FORMAT_BGRX32 PIXEL_FORMAT_B8G8R8X8 +#define PIXEL_FORMAT_B8G8R8X8_VF PIXEL_FORMAT_B8G8R8X8_F(1) +#define PIXEL_FORMAT_BGRX32_VF PIXEL_FORMAT_B8G8R8X8_VF -#define PIXEL_FORMAT_R8G8B8A8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 8, 8, 8, 8) -#define PIXEL_FORMAT_RGBA32 PIXEL_FORMAT_R8G8B8A8 +#define PIXEL_FORMAT_R8G8B8A8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 8, 8, 8, 8) +#define PIXEL_FORMAT_R8G8B8A8 PIXEL_FORMAT_R8G8B8A8_F(0) +#define PIXEL_FORMAT_RGBA32 PIXEL_FORMAT_R8G8B8A8 +#define PIXEL_FORMAT_R8G8B8A8_VF PIXEL_FORMAT_R8G8B8A8_F(1) +#define PIXEL_FORMAT_RGBA32_VF PIXEL_FORMAT_R8G8B8A8_VF -#define PIXEL_FORMAT_R8G8B8X8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 0, 8, 8, 8) -#define PIXEL_FORMAT_RGBX32 PIXEL_FORMAT_R8G8B8X8 +#define PIXEL_FORMAT_R8G8B8X8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 0, 8, 8, 8) +#define PIXEL_FORMAT_R8G8B8X8 PIXEL_FORMAT_R8G8B8X8_F(0) +#define PIXEL_FORMAT_RGBX32 PIXEL_FORMAT_R8G8B8X8 +#define PIXEL_FORMAT_R8G8B8X8_VF PIXEL_FORMAT_R8G8B8X8_F(1) +#define PIXEL_FORMAT_RGBX32_VF PIXEL_FORMAT_R8G8B8X8_VF /* 24bpp formats */ -#define PIXEL_FORMAT_R8G8B8 FREERDP_PIXEL_FORMAT(24, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8) -#define PIXEL_FORMAT_RGB24 PIXEL_FORMAT_R8G8B8 +#define PIXEL_FORMAT_R8G8B8 FREERDP_PIXEL_FORMAT(0, 24, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8) +#define PIXEL_FORMAT_RGB24 PIXEL_FORMAT_R8G8B8 -#define PIXEL_FORMAT_B8G8R8 FREERDP_PIXEL_FORMAT(24, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8) -#define PIXEL_FORMAT_BGR24 PIXEL_FORMAT_B8G8R8 +#define PIXEL_FORMAT_B8G8R8 FREERDP_PIXEL_FORMAT(0, 24, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8) +#define PIXEL_FORMAT_BGR24 PIXEL_FORMAT_B8G8R8 /* 16bpp formats */ -#define PIXEL_FORMAT_R5G6B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 6, 5) -#define PIXEL_FORMAT_RGB565 PIXEL_FORMAT_R5G6B5 -#define PIXEL_FORMAT_RGB16 PIXEL_FORMAT_R5G6B5 +#define PIXEL_FORMAT_R5G6B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 6, 5) +#define PIXEL_FORMAT_RGB565 PIXEL_FORMAT_R5G6B5 +#define PIXEL_FORMAT_RGB16 PIXEL_FORMAT_R5G6B5 -#define PIXEL_FORMAT_B5G6R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 6, 5) -#define PIXEL_FORMAT_BGR565 PIXEL_FORMAT_B5G6R5 -#define PIXEL_FORMAT_BGR16 PIXEL_FORMAT_B5G6R5 +#define PIXEL_FORMAT_B5G6R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 6, 5) +#define PIXEL_FORMAT_BGR565 PIXEL_FORMAT_B5G6R5 +#define PIXEL_FORMAT_BGR16 PIXEL_FORMAT_B5G6R5 -#define PIXEL_FORMAT_A1R5G5B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 1, 5, 5, 5) -#define PIXEL_FORMAT_ARGB555 PIXEL_FORMAT_A1R5G5B5 -#define PIXEL_FORMAT_ARGB15 PIXEL_FORMAT_A1R5G5B5 +#define PIXEL_FORMAT_A1R5G5B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 1, 5, 5, 5) +#define PIXEL_FORMAT_ARGB555 PIXEL_FORMAT_A1R5G5B5 +#define PIXEL_FORMAT_ARGB15 PIXEL_FORMAT_A1R5G5B5 -#define PIXEL_FORMAT_X1R5G5B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 5, 5) -#define PIXEL_FORMAT_XRGB555 PIXEL_FORMAT_X1R5G5B5 -#define PIXEL_FORMAT_RGB555 PIXEL_FORMAT_X1R5G5B5 -#define PIXEL_FORMAT_RGB15 PIXEL_FORMAT_X1R5G5B5 +#define PIXEL_FORMAT_X1R5G5B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 5, 5) +#define PIXEL_FORMAT_XRGB555 PIXEL_FORMAT_X1R5G5B5 +#define PIXEL_FORMAT_RGB555 PIXEL_FORMAT_X1R5G5B5 +#define PIXEL_FORMAT_RGB15 PIXEL_FORMAT_X1R5G5B5 -#define PIXEL_FORMAT_A1B5G5R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 1, 5, 5, 5) -#define PIXEL_FORMAT_ABGR555 PIXEL_FORMAT_A1B5G5R5 -#define PIXEL_FORMAT_ABGR15 PIXEL_FORMAT_A1B5G5R5 +#define PIXEL_FORMAT_A1B5G5R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 1, 5, 5, 5) +#define PIXEL_FORMAT_ABGR555 PIXEL_FORMAT_A1B5G5R5 +#define PIXEL_FORMAT_ABGR15 PIXEL_FORMAT_A1B5G5R5 -#define PIXEL_FORMAT_X1B5G5R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 5, 5) -#define PIXEL_FORMAT_XBGR555 PIXEL_FORMAT_X1B5G5R5 -#define PIXEL_FORMAT_BGR555 PIXEL_FORMAT_X1B5G5R5 -#define PIXEL_FORMAT_BGR15 PIXEL_FORMAT_X1B5G5R5 +#define PIXEL_FORMAT_X1B5G5R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 5, 5) +#define PIXEL_FORMAT_XBGR555 PIXEL_FORMAT_X1B5G5R5 +#define PIXEL_FORMAT_BGR555 PIXEL_FORMAT_X1B5G5R5 +#define PIXEL_FORMAT_BGR15 PIXEL_FORMAT_X1B5G5R5 /* 8bpp formats */ -#define PIXEL_FORMAT_A8 FREERDP_PIXEL_FORMAT(8, FREERDP_PIXEL_FORMAT_TYPE_A, 8, 0, 0, 0) -#define PIXEL_FORMAT_8BPP PIXEL_FORMAT_A8 -#define PIXEL_FORMAT_256 PIXEL_FORMAT_A8 +#define PIXEL_FORMAT_A8 FREERDP_PIXEL_FORMAT(0, 8, FREERDP_PIXEL_FORMAT_TYPE_A, 8, 0, 0, 0) +#define PIXEL_FORMAT_8BPP PIXEL_FORMAT_A8 +#define PIXEL_FORMAT_256 PIXEL_FORMAT_A8 /* 4 bpp formats */ -#define PIXEL_FORMAT_A4 FREERDP_PIXEL_FORMAT(4, FREERDP_PIXEL_FORMAT_TYPE_A, 4, 0, 0, 0) -#define PIXEL_FORMAT_4BPP PIXEL_FORMAT_A4 +#define PIXEL_FORMAT_A4 FREERDP_PIXEL_FORMAT(0, 4, FREERDP_PIXEL_FORMAT_TYPE_A, 4, 0, 0, 0) +#define PIXEL_FORMAT_4BPP PIXEL_FORMAT_A4 /* 1bpp formats */ -#define PIXEL_FORMAT_A1 FREERDP_PIXEL_FORMAT(1, FREERDP_PIXEL_FORMAT_TYPE_A, 1, 0, 0, 0) -#define PIXEL_FORMAT_1BPP PIXEL_FORMAT_A1 -#define PIXEL_FORMAT_MONO PIXEL_FORMAT_A1 +#define PIXEL_FORMAT_A1 FREERDP_PIXEL_FORMAT(0, 1, FREERDP_PIXEL_FORMAT_TYPE_A, 1, 0, 0, 0) +#define PIXEL_FORMAT_1BPP PIXEL_FORMAT_A1 +#define PIXEL_FORMAT_MONO PIXEL_FORMAT_A1 #ifdef __cplusplus extern "C" { diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 69a871c84..2f2c88b02 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -1181,6 +1181,7 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs int srcBytesPerPixel; int dstBitsPerPixel; int dstBytesPerPixel; + BOOL overlap = FALSE; srcBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwSrcFormat); srcBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwSrcFormat) / 8); @@ -1188,6 +1189,12 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwDstFormat); dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwDstFormat) / 8); + if (pDstData == pSrcData) + { + overlap = (((nXDst + nWidth) > nXSrc) && (nXDst < (nXSrc + nWidth)) && + ((nYDst + nHeight) > nYSrc) && (nYDst < (nYSrc + nHeight))) ? TRUE : FALSE; + } + if (srcBytesPerPixel == 4) { if (nSrcStep < 0) @@ -1195,7 +1202,7 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs if (srcBitsPerPixel == 24) { - if (dstBytesPerPixel == 4) + if (dstBytesPerPixel == 4) /* srcBytesPerPixel == dstBytesPerPixel */ { if (dstBitsPerPixel == 32) { @@ -1223,7 +1230,7 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))]; } } - else if (dstBitsPerPixel == 24) + else if (dstBitsPerPixel == 24) /* srcBitsPerPixel == dstBitsPerPixel */ { UINT32* pSrcPixel; UINT32* pDstPixel; From 50883e6c83fff6f66d708e59cd2f0974af829712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 12 Jun 2014 18:23:51 -0400 Subject: [PATCH 34/50] xfreerdp: fix egfx RemoteFX bitmap updates --- client/X11/xf_gfx.c | 71 ++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 0d20244b3..37fa9880d 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -154,8 +154,6 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, xfGfxSurface* surface; RECTANGLE_16 invalidRect; - printf("xf_SurfaceCommand_Uncompressed\n"); - surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); if (!surface) @@ -171,6 +169,8 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, invalidRect.right = cmd->right; invalidRect.bottom = cmd->bottom; + printf("xf_SurfaceCommand_Uncompressed: x: %d y: %d w: %d h: %d\n", cmd->left, cmd->top, cmd->width, cmd->height); + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); if (!xfc->inGfxFrame) @@ -181,62 +181,73 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { - UINT16 index; + int j; + UINT16 i; RFX_RECT* rect; RFX_TILE* tile; int nXDst, nYDst; int nWidth, nHeight; + int nbUpdateRects; RFX_MESSAGE* message; xfGfxSurface* surface; - RECTANGLE_16 invalidRect; - RECTANGLE_16 surfaceRect; + REGION16 updateRegion; + RECTANGLE_16 updateRect; + RECTANGLE_16* updateRects; + REGION16 clippingRects; + RECTANGLE_16 clippingRect; surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); if (!surface) return -1; - surfaceRect.left = 0; - surfaceRect.top = 0; - surfaceRect.right = xfc->width - 1; - surfaceRect.bottom = xfc->height - 1; - message = rfx_process_message(xfc->rfx, cmd->data, cmd->length); if (!message) return -1; - for (index = 0; index < message->numRects; index++) + region16_init(&clippingRects); + + for (i = 0; i < message->numRects; i++) { - rect = &(message->rects[index]); + rect = &(message->rects[i]); - invalidRect.left = cmd->left + rect->x; - invalidRect.top = cmd->top + rect->y; - invalidRect.right = invalidRect.left + rect->width - 1; - invalidRect.bottom = invalidRect.top + rect->height - 1; + clippingRect.left = cmd->left + rect->x; + clippingRect.top = cmd->top + rect->y; + clippingRect.right = clippingRect.left + rect->width - 1; + clippingRect.bottom = clippingRect.top + rect->height - 1; - region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + region16_union_rect(&clippingRects, &clippingRects, &clippingRect); } - for (index = 0; index < message->numTiles; index++) + for (i = 0; i < message->numTiles; i++) { - tile = message->tiles[index]; + tile = message->tiles[i]; - nWidth = nHeight = 64; - nXDst = cmd->left + tile->x; - nYDst = cmd->top + tile->y; + updateRect.left = cmd->left + tile->x; + updateRect.top = cmd->top + tile->y; + updateRect.right = updateRect.left + 64 - 1; + updateRect.bottom = updateRect.top + 64 - 1; - if ((nXDst + nWidth) > surface->width) - nWidth = surface->width - nXDst; + region16_init(&updateRegion); + region16_intersect_rect(&updateRegion, &clippingRects, &updateRect); + updateRects = (RECTANGLE_16*) region16_rects(&updateRegion, &nbUpdateRects); - if (nYDst + nHeight > surface->height) - nHeight = surface->height - nYDst; + for (j = 0; j < nbUpdateRects; j++) + { + nXDst = updateRects[j].left; + nYDst = updateRects[j].top; + nWidth = updateRects[j].right - updateRects[j].left + 1; + nHeight = updateRects[j].bottom - updateRects[j].top + 1; - /* TODO: properly handle RemoteFX tile clipping */ + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + nXDst, nYDst, nWidth, nHeight, + tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0); - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, - nXDst, nYDst, nWidth, nHeight, - tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0); + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &updateRects[j]); + } + + region16_uninit(&updateRegion); } rfx_message_free(xfc->rfx, message); From 27b1e76dbb06c4cbe77b199ee8e02f9b20a6e9ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 12 Jun 2014 21:02:25 -0400 Subject: [PATCH 35/50] xfreerdp: fix egfx SurfaceToSurface overlapping copies --- channels/rdpgfx/client/rdpgfx_main.c | 7 ++-- client/X11/xf_gfx.c | 22 ++++++------- libfreerdp/codec/color.c | 49 +++++++++++++++------------- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index b6d9f3b2f..66074976b 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -366,6 +366,9 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ + if (pdu.bitmapDataLength > Stream_GetRemainingLength(s)) + return -1; + pdu.bitmapData = Stream_Pointer(s); Stream_Seek(s, pdu.bitmapDataLength); @@ -383,8 +386,8 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream cmd.top = pdu.destRect.top; cmd.right = pdu.destRect.right; cmd.bottom = pdu.destRect.bottom; - cmd.width = cmd.right - cmd.left + 1; - cmd.height = cmd.bottom - cmd.top + 1; + cmd.width = cmd.right - cmd.left; + cmd.height = cmd.bottom - cmd.top; cmd.length = pdu.bitmapDataLength; cmd.data = pdu.bitmapData; diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 37fa9880d..3e27dd604 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -91,8 +91,8 @@ int xf_OutputUpdate(xfContext* xfc) { extents = region16_extents(&(xfc->invalidRegion)); - width = extents->right - extents->left; - height = extents->bottom - extents->top; + width = extents->right - extents->left + 1; + height = extents->bottom - extents->top + 1; if (width > xfc->width) width = xfc->width; @@ -159,17 +159,16 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, if (!surface) return -1; - /* TODO: bitmap flipping in freerdp_image_copy */ - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, - cmd->width, cmd->height, cmd->data, PIXEL_FORMAT_XRGB32_VF, cmd->width * 4, 0, 0); + cmd->width, cmd->height, cmd->data, PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0); invalidRect.left = cmd->left; invalidRect.top = cmd->top; invalidRect.right = cmd->right; invalidRect.bottom = cmd->bottom; - printf("xf_SurfaceCommand_Uncompressed: x: %d y: %d w: %d h: %d\n", cmd->left, cmd->top, cmd->width, cmd->height); + printf("xf_SurfaceCommand_Uncompressed: x: %d y: %d w: %d h: %d r: %d b: %d\n", + cmd->left, cmd->top, cmd->width, cmd->height, cmd->right, cmd->bottom); region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); @@ -470,15 +469,14 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_ { destPt = &surfaceToSurface->destPts[index]; - /* TODO: copy overlap handling in freerdp_image_copy */ - - freerdp_image_copy(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline, destPt->x, destPt->y, - nWidth, nHeight, surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceSrc->scanline, 0, 0); + freerdp_image_copy(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline, + destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, PIXEL_FORMAT_XRGB32, + surfaceSrc->scanline, rectSrc->left, rectSrc->top); invalidRect.left = destPt->x; invalidRect.top = destPt->y; - invalidRect.right = destPt->x + nWidth - 1; - invalidRect.bottom = destPt->y + nHeight - 1; + invalidRect.right = destPt->x + rectSrc->right; + invalidRect.bottom = destPt->y + rectSrc->bottom; region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); } diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 2f2c88b02..f2fc9116d 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -1175,8 +1175,9 @@ void freerdp_clrconv_free(HCLRCONV clrconv) int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc) { - int i, j; + int y, x; BYTE a, r, g, b; + int beg, end, inc; int srcBitsPerPixel; int srcBytesPerPixel; int dstBitsPerPixel; @@ -1215,9 +1216,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; - for (i = 0; i < nHeight; i++) + for (y = 0; y < nHeight; y++) { - for (j = 0; j < nWidth; j++) + for (x = 0; x < nWidth; x++) { GetARGB32(a, r, g, b, *pSrcPixel); *pDstPixel = ARGB32(a, r, g, b); @@ -1238,22 +1239,24 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs if (nDstStep < 0) nDstStep = dstBytesPerPixel * nWidth; - pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; - pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; - - for (i = 0; i < nHeight; i++) + if (overlap && (nYSrc < nYDst)) { - for (j = 0; j < nWidth; j++) - { - GetRGB32(r, g, b, *pSrcPixel); - *pDstPixel = RGB32(r, g, b); + beg = nHeight - 1; + inc = -1; /* downward copy */ + end = -1; + } + else + { + beg = 0; + inc = 1; /* upward copy */ + end = nHeight; + } - pSrcPixel++; - pDstPixel++; - } - - pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))]; - pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))]; + for (y = beg; y != end; y += inc) + { + pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * srcBytesPerPixel)]; + pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * dstBytesPerPixel)]; + MoveMemory(pDstPixel, pSrcPixel, nWidth * 4); } } } @@ -1268,9 +1271,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; pDstPixel = (BYTE*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; - for (i = 0; i < nHeight; i++) + for (y = 0; y < nHeight; y++) { - for (j = 0; j < nWidth; j++) + for (x = 0; x < nWidth; x++) { GetRGB32(r, g, b, *pSrcPixel); @@ -1298,9 +1301,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; - for (i = 0; i < nHeight; i++) + for (y = 0; y < nHeight; y++) { - for (j = 0; j < nWidth; j++) + for (x = 0; x < nWidth; x++) { GetRGB32(r, g, b, *pSrcPixel); RGB_888_565(r, g, b); @@ -1325,9 +1328,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; - for (i = 0; i < nHeight; i++) + for (y = 0; y < nHeight; y++) { - for (j = 0; j < nWidth; j++) + for (x = 0; x < nWidth; x++) { GetRGB32(r, g, b, *pSrcPixel); RGB_888_555(r, g, b); From eeb7cd2cb2191ba082e4a68a5f3de823da99a7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 13 Jun 2014 08:36:09 -0400 Subject: [PATCH 36/50] xfreerdp: initial egfx bitmap caching --- channels/rdpgfx/client/rdpgfx_main.c | 32 ++++++++ channels/rdpgfx/client/rdpgfx_main.h | 3 + client/X11/xf_gfx.c | 112 +++++++++++++++++++-------- client/X11/xf_gfx.h | 12 +++ include/freerdp/client/rdpgfx.h | 4 + include/freerdp/codec/color.h | 2 + libfreerdp/codec/color.c | 55 ++++++++++++- 7 files changed, 187 insertions(+), 33 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 66074976b..0bb29bb8c 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -60,6 +60,8 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) gfx->SmallCache = FALSE; gfx->H264 = FALSE; + gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600; + header.flags = 0; header.cmdId = RDPGFX_CMDID_CAPSADVERTISE; @@ -892,6 +894,31 @@ void* rdpgfx_get_surface_data(RdpgfxClientContext* context, UINT16 surfaceId) return pData; } +int rdpgfx_set_cache_slot_data(RdpgfxClientContext* context, UINT16 cacheSlot, void* pData) +{ + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; + + if (cacheSlot >= gfx->MaxCacheSlot) + return -1; + + gfx->CacheSlots[cacheSlot] = pData; + + return 1; +} + +void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cacheSlot) +{ + void* pData = NULL; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; + + if (cacheSlot >= gfx->MaxCacheSlot) + return NULL; + + pData = gfx->CacheSlots[cacheSlot]; + + return pData; +} + #ifdef STATIC_CHANNELS #define DVCPluginEntry rdpgfx_DVCPluginEntry #endif @@ -923,6 +950,9 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) if (!gfx->SurfaceTable) return -1; + gfx->ThinClient = TRUE; + gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600; + context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext)); if (!context) @@ -932,6 +962,8 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) context->SetSurfaceData = rdpgfx_set_surface_data; context->GetSurfaceData = rdpgfx_get_surface_data; + context->SetCacheSlotData = rdpgfx_set_cache_slot_data; + context->GetCacheSlotData = rdpgfx_get_cache_slot_data; gfx->iface.pInterface = (void*) context; diff --git a/channels/rdpgfx/client/rdpgfx_main.h b/channels/rdpgfx/client/rdpgfx_main.h index da0e64822..e1dc362ea 100644 --- a/channels/rdpgfx/client/rdpgfx_main.h +++ b/channels/rdpgfx/client/rdpgfx_main.h @@ -69,6 +69,9 @@ struct _RDPGFX_PLUGIN UINT32 TotalDecodedFrames; wHashTable* SurfaceTable; + + UINT16 MaxCacheSlot; + void* CacheSlots[25600]; }; typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 3e27dd604..55dffb2c1 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -167,9 +167,6 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, invalidRect.right = cmd->right; invalidRect.bottom = cmd->bottom; - printf("xf_SurfaceCommand_Uncompressed: x: %d y: %d w: %d h: %d r: %d b: %d\n", - cmd->left, cmd->top, cmd->width, cmd->height, cmd->right, cmd->bottom); - region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); if (!xfc->inGfxFrame) @@ -382,13 +379,19 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill) UINT16 index; UINT32 color; BYTE a, r, g, b; - XRectangle* xrects; + int nWidth, nHeight; RDPGFX_RECT16* rect; + xfGfxSurface* surface; RECTANGLE_16 invalidRect; xfContext* xfc = (xfContext*) context->custom; + surface = (xfGfxSurface*) context->GetSurfaceData(context, solidFill->surfaceId); + printf("xf_SolidFill\n"); + if (!surface) + return -1; + b = solidFill->fillPixel.B; g = solidFill->fillPixel.G; r = solidFill->fillPixel.R; @@ -396,36 +399,24 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill) color = ARGB32(a, r, g, b); - xrects = (XRectangle*) malloc(solidFill->fillRectCount * sizeof(XRectangle)); - - if (!xrects) - return -1; - for (index = 0; index < solidFill->fillRectCount; index++) { rect = &(solidFill->fillRects[index]); - xrects[index].x = rect->left; - xrects[index].y = rect->top; - xrects[index].width = rect->right - rect->left + 1; - xrects[index].height = rect->bottom - rect->top + 1; + nWidth = rect->right - rect->left; + nHeight = rect->bottom - rect->top; invalidRect.left = rect->left; invalidRect.top = rect->top; invalidRect.right = rect->right; invalidRect.bottom = rect->bottom; + freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + rect->left, rect->top, nWidth, nHeight, color); + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); } - XSetFunction(xfc->display, xfc->gc, GXcopy); - XSetFillStyle(xfc->display, xfc->gc, FillSolid); - XSetForeground(xfc->display, xfc->gc, color); - - XFillRectangles(xfc->display, xfc->drawing, xfc->gc, xrects, solidFill->fillRectCount); - - free(xrects); - if (!xfc->inGfxFrame) xf_OutputUpdate(xfc); @@ -446,12 +437,6 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_ rectSrc = &(surfaceToSurface->rectSrc); destPt = &surfaceToSurface->destPts[0]; - printf("xf_SurfaceToSurface: srcId: %d dstId: %d rect: x: %d y: %d w: %d h: %d ptsCount: %d x: %d y: %d\n", - (int) surfaceToSurface->surfaceIdSrc, (int) surfaceToSurface->surfaceIdDest, - rectSrc->left, rectSrc->top, rectSrc->right - rectSrc->left, - rectSrc->bottom - rectSrc->top, (int) surfaceToSurface->destPtsCount, - destPt->x, destPt->y); - surfaceSrc = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc); if (surfaceToSurface->surfaceIdSrc != surfaceToSurface->surfaceIdDest) @@ -489,14 +474,80 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_ int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache) { - printf("xf_SurfaceToCache\n"); + RDPGFX_RECT16* rect; + xfGfxSurface* surface; + xfGfxCacheEntry* cacheEntry; + + rect = &(surfaceToCache->rectSrc); + + surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId); + + printf("xf_SurfaceToCache: cacheKey: 0x%016X cacheSlot: %ld\n", + surfaceToCache->cacheKey, surfaceToCache->cacheSlot); + + if (!surface) + return -1; + + cacheEntry = (xfGfxCacheEntry*) calloc(1, sizeof(xfGfxCacheEntry)); + + if (!cacheEntry) + return -1; + + cacheEntry->width = (UINT32) (rect->right - rect->left); + cacheEntry->height = (UINT32) (rect->bottom - rect->top); + cacheEntry->alpha = surface->alpha; + + cacheEntry->scanline = cacheEntry->width * 4; + cacheEntry->data = (BYTE*) calloc(1, surface->scanline * surface->height); + + if (!cacheEntry->data) + return -1; + + freerdp_image_copy(cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, + 0, 0, cacheEntry->width, cacheEntry->height, surface->data, + PIXEL_FORMAT_XRGB32, surface->scanline, rect->left, rect->top); + + context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry); return 1; } int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface) { - printf("xf_CacheToSurface\n"); + UINT16 index; + RDPGFX_POINT16* destPt; + xfGfxSurface* surface; + xfGfxCacheEntry* cacheEntry; + RECTANGLE_16 invalidRect; + xfContext* xfc = (xfContext*) context->custom; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId); + cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot); + + printf("xf_CacheToSurface: cacheEntry: %d\n", + cacheToSurface->cacheSlot); + + if (!surface || !cacheEntry) + return -1; + + for (index = 0; index < cacheToSurface->destPtsCount; index++) + { + destPt = &cacheToSurface->destPts[index]; + + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + destPt->x, destPt->y, cacheEntry->width, cacheEntry->height, + cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, 0, 0); + + invalidRect.left = destPt->x; + invalidRect.top = destPt->y; + invalidRect.right = destPt->x + cacheEntry->width - 1; + invalidRect.bottom = destPt->y + cacheEntry->height - 1; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + } + + if (!xfc->inGfxFrame) + xf_OutputUpdate(xfc); return 1; } @@ -517,9 +568,6 @@ int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OU { xfContext* xfc = (xfContext*) context->custom; - printf("xf_MapSurfaceToOutput: surfaceId: %d outputOriginX: %d outputOriginY: %d\n", - surfaceToOutput->surfaceId, surfaceToOutput->outputOriginX, surfaceToOutput->outputOriginY); - xfc->outputSurfaceId = surfaceToOutput->surfaceId; return 1; diff --git a/client/X11/xf_gfx.h b/client/X11/xf_gfx.h index 623df31b0..6451d258c 100644 --- a/client/X11/xf_gfx.h +++ b/client/X11/xf_gfx.h @@ -35,6 +35,18 @@ struct xf_gfx_surface }; typedef struct xf_gfx_surface xfGfxSurface; +struct xf_gfx_cache_entry +{ + UINT64 cacheKey; + UINT32 width; + UINT32 height; + BOOL alpha; + BYTE* data; + XImage* image; + int scanline; +}; +typedef struct xf_gfx_cache_entry xfGfxCacheEntry; + int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height); void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx); diff --git a/include/freerdp/client/rdpgfx.h b/include/freerdp/client/rdpgfx.h index 64c1155a1..f44cfbbeb 100644 --- a/include/freerdp/client/rdpgfx.h +++ b/include/freerdp/client/rdpgfx.h @@ -47,6 +47,8 @@ typedef int (*pcRdpgfxMapSurfaceToWindow)(RdpgfxClientContext* context, RDPGFX_M typedef int (*pcRdpgfxSetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId, void* pData); typedef void* (*pcRdpgfxGetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId); +typedef int (*pcRdpgfxSetCacheSlotData)(RdpgfxClientContext* context, UINT16 cacheSlot, void* pData); +typedef void* (*pcRdpgfxGetCacheSlotData)(RdpgfxClientContext* context, UINT16 cacheSlot); struct _rdpgfx_client_context { @@ -72,6 +74,8 @@ struct _rdpgfx_client_context pcRdpgfxSetSurfaceData SetSurfaceData; pcRdpgfxGetSurfaceData GetSurfaceData; + pcRdpgfxSetCacheSlotData SetCacheSlotData; + pcRdpgfxGetCacheSlotData GetCacheSlotData; }; #endif /* FREERDP_CHANNEL_CLIENT_RDPGFX_H */ diff --git a/include/freerdp/codec/color.h b/include/freerdp/codec/color.h index 489aab960..0d72ed07c 100644 --- a/include/freerdp/codec/color.h +++ b/include/freerdp/codec/color.h @@ -398,6 +398,8 @@ FREERDP_API void freerdp_clrconv_free(HCLRCONV clrconv); FREERDP_API int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc); +FREERDP_API int freerdp_image_fill(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, + int nWidth, int nHeight, UINT32 color); #ifdef __cplusplus } diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index f2fc9116d..bd5b1c238 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -1175,7 +1175,7 @@ void freerdp_clrconv_free(HCLRCONV clrconv) int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc) { - int y, x; + int x, y; BYTE a, r, g, b; int beg, end, inc; int srcBitsPerPixel; @@ -1350,3 +1350,56 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs return 0; } + +void* freerdp_image_memset32(UINT32* ptr, UINT32 fill, size_t length) +{ + while (length--) + { + *ptr++ = fill; + } + + return (void*) ptr; +} + +int freerdp_image_fill(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, + int nWidth, int nHeight, UINT32 color) +{ + int y; + int dstBitsPerPixel; + int dstBytesPerPixel; + + dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwDstFormat); + dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwDstFormat) / 8); + + if (dstBytesPerPixel == 4) + { + UINT32* pDstPixel; + + if (nDstStep < 0) + nDstStep = dstBytesPerPixel * nWidth; + + for (y = 0; y < nHeight; y++) + { + pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * dstBytesPerPixel)]; + freerdp_image_memset32(pDstPixel, color, nWidth); + } + } + else if (dstBytesPerPixel == 3) + { + + } + else if (dstBytesPerPixel == 2) + { + if (dstBitsPerPixel == 16) + { + + } + else if (dstBitsPerPixel == 15) + { + + } + } + + return 0; +} + From 0e27f5abe40f9f5da4c9939da7acc1c1841b42ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 13 Jun 2014 12:17:16 -0400 Subject: [PATCH 37/50] libfreerdp-codec: start working on clearcodec decompressor --- include/freerdp/codec/clear.h | 4 + libfreerdp/codec/clear.c | 231 ++++++++++++++++++ libfreerdp/codec/test/TestFreeRDPCodecClear.c | 134 ++++++++++ 3 files changed, 369 insertions(+) diff --git a/include/freerdp/codec/clear.h b/include/freerdp/codec/clear.h index dc5e81a83..c7fc22433 100644 --- a/include/freerdp/codec/clear.h +++ b/include/freerdp/codec/clear.h @@ -23,6 +23,10 @@ #include #include +#define CLEARCODEC_FLAG_GLYPH_INDEX 0x01 +#define CLEARCODEC_FLAG_GLYPH_HIT 0x02 +#define CLEARCODEC_FLAG_CACHE_RESET 0x03 + struct _CLEAR_CONTEXT { BOOL Compressor; diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c index 564e5d364..d0bc0924f 100644 --- a/libfreerdp/codec/clear.c +++ b/libfreerdp/codec/clear.c @@ -29,6 +29,237 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize) { + BYTE glyphFlags; + BYTE seqNumber; + UINT16 glyphIndex; + UINT32 offset = 0; + UINT32 residualByteCount; + UINT32 bandsByteCount; + UINT32 subcodecByteCount; + + if (SrcSize < 2) + return -1; + + glyphFlags = pSrcData[0]; + seqNumber = pSrcData[1]; + offset += 2; + + printf("glyphFlags: 0x%02X seqNumber: %d\n", glyphFlags, seqNumber); + + if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX) + { + if (SrcSize < 4) + return -1; + + glyphIndex = *((UINT16*) &pSrcData[2]); + offset += 2; + + if (glyphFlags & CLEARCODEC_FLAG_GLYPH_HIT) + { + /** + * Copy pixels from the Decompressor Glyph Storage position + * specified by the glyphIndex field to the output bitmap + */ + + return 1; /* Finish */ + } + } + + /* Read composition payload header parameters */ + + if ((SrcSize - offset) < 12) + return -1; + + residualByteCount = *((UINT32*) &pSrcData[offset]); + bandsByteCount = *((UINT32*) &pSrcData[offset + 4]); + subcodecByteCount = *((UINT32*) &pSrcData[offset + 8]); + offset += 12; + + printf("residualByteCount: %d bandsByteCount: %d subcodecByteCount: %d\n", + residualByteCount, bandsByteCount, subcodecByteCount); + + if (residualByteCount > 0) + { + BYTE blueValue; + BYTE greenValue; + BYTE redValue; + UINT32 suboffset; + BYTE* residualData; + BYTE runLengthFactor1 = 0; + UINT16 runLengthFactor2 = 0; + UINT32 runLengthFactor3 = 0; + UINT32 runLengthFactor = 0; + + if ((SrcSize - offset) < residualByteCount) + return -1; + + suboffset = 0; + residualData = &pSrcData[offset]; + + while (suboffset < residualByteCount) + { + if ((residualByteCount - suboffset) < 4) + return -1; + + blueValue = residualData[suboffset]; + greenValue = residualData[suboffset + 1]; + redValue = residualData[suboffset + 2]; + suboffset += 3; + + runLengthFactor1 = residualData[suboffset]; + runLengthFactor = runLengthFactor1; + suboffset += 1; + + if (runLengthFactor1 >= 0xFF) + { + if ((residualByteCount - suboffset) < 2) + return -1; + + runLengthFactor2 = *((UINT16*) &residualData[suboffset]); + runLengthFactor = runLengthFactor2; + suboffset += 2; + + if (runLengthFactor2 >= 0xFFFF) + { + if ((residualByteCount - suboffset) < 4) + return -1; + + runLengthFactor3 = *((UINT32*) &residualData[suboffset]); + runLengthFactor = runLengthFactor3; + suboffset += 4; + } + } + } + + /* Decompress residual layer and write to output bitmap */ + offset += residualByteCount; + } + + if (bandsByteCount > 0) + { + BYTE* bandsData; + UINT32 suboffset; + + if ((SrcSize - offset) < bandsByteCount) + return -1; + + suboffset = 0; + bandsData = &pSrcData[offset]; + + while (suboffset < bandsByteCount) + { + UINT16 xStart; + UINT16 xEnd; + UINT16 yStart; + UINT16 yEnd; + BYTE blueBkg; + BYTE greenBkg; + BYTE redBkg; + BYTE* vBars; + UINT16 vBarHeader; + + if ((bandsByteCount - suboffset) < 11) + return -1; + + xStart = *((UINT16*) &bandsData[suboffset]); + xEnd = *((UINT16*) &bandsData[suboffset + 2]); + yStart = *((UINT16*) &bandsData[suboffset + 4]); + yEnd = *((UINT16*) &bandsData[suboffset + 6]); + blueBkg = bandsData[suboffset + 8]; + greenBkg = bandsData[suboffset + 9]; + redBkg = bandsData[suboffset + 10]; + suboffset += 11; + + vBars = &bandsData[suboffset]; + + vBarHeader = *((UINT16*) &vBars[0]); + + if ((vBarHeader & 0xC000) == 0x8000) /* VBAR_CACHE_HIT */ + { + printf("VBAR_CACHE_HIT\n"); + suboffset += 2; + } + else if ((vBarHeader & 0xC000) == 0xC000) /* SHORT_VBAR_CACHE_HIT */ + { + printf("SHORT_VBAR_CACHE_HIT\n"); + suboffset += 3; + } + else if ((vBarHeader & 0xC000) == 0) /* SHORT_VBAR_CACHE_MISS */ + { + printf("SHORT_VBAR_CACHE_MISS\n"); + suboffset += 2; + } + else + { + return -1; /* invalid vBarHeader */ + } + + /* shortVBarPixels: variable */ + } + + /* Decompress bands layer and write to output bitmap */ + offset += bandsByteCount; + } + + if (subcodecByteCount > 0) + { + UINT16 xStart; + UINT16 yStart; + UINT16 width; + UINT16 height; + BYTE* bitmapData; + UINT32 bitmapDataByteCount; + BYTE subcodecId; + BYTE* subcodecs; + UINT32 suboffset; + + if ((SrcSize - offset) < subcodecByteCount) + return -1; + + suboffset = 0; + subcodecs = &pSrcData[offset]; + + while (suboffset < subcodecByteCount) + { + if ((subcodecByteCount - suboffset) < 13) + return -1; + + xStart = *((UINT16*) &subcodecs[suboffset]); + yStart = *((UINT16*) &subcodecs[suboffset + 2]); + width = *((UINT16*) &subcodecs[suboffset + 4]); + height = *((UINT16*) &subcodecs[suboffset + 6]); + bitmapDataByteCount = *((UINT32*) &subcodecs[suboffset + 8]); + subcodecId = subcodecs[suboffset + 12]; + suboffset += 13; + + printf("bitmapDataByteCount: %d subcodecByteCount: %d suboffset: %d\n", + bitmapDataByteCount, subcodecByteCount, suboffset); + + if ((subcodecByteCount - suboffset) < bitmapDataByteCount) + return -1; + + bitmapData = &subcodecs[suboffset]; + + suboffset += bitmapDataByteCount; + } + + /* Decompress subcodec layer and write to output bitmap */ + offset += subcodecByteCount; + } + + if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX) + { + /** + * Copy decompressed bitmap to the Decompressor Glyph + * Storage position specified by the glyphIndex field + */ + } + + if (offset != SrcSize) + { + printf("clear_decompress: incomplete processing of bytes: Actual: %d, Expected: %d\n", offset, SrcSize); + } + return 1; } diff --git a/libfreerdp/codec/test/TestFreeRDPCodecClear.c b/libfreerdp/codec/test/TestFreeRDPCodecClear.c index 6db7e6e12..c83993b0f 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecClear.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecClear.c @@ -3,8 +3,142 @@ #include +static BYTE TEST_CLEAR_EXAMPLE_1[] = "\x03\xc3\x11\x00"; + +static BYTE TEST_CLEAR_EXAMPLE_2[] = + "\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x82\x00\x00\x00\x00\x00" + "\x00\x00\x4e\x00\x11\x00\x75\x00\x00\x00\x02\x0e\xff\xff\xff\x00" + "\x00\x00\xdb\xff\xff\x00\x3a\x90\xff\xb6\x66\x66\xb6\xff\xb6\x66" + "\x00\x90\xdb\xff\x00\x00\x3a\xdb\x90\x3a\x3a\x90\xdb\x66\x00\x00" + "\xff\xff\xb6\x64\x64\x64\x11\x04\x11\x4c\x11\x4c\x11\x4c\x11\x4c" + "\x11\x4c\x00\x47\x13\x00\x01\x01\x04\x00\x01\x00\x00\x47\x16\x00" + "\x11\x02\x00\x47\x29\x00\x11\x01\x00\x49\x0a\x00\x01\x00\x04\x00" + "\x01\x00\x00\x4a\x0a\x00\x09\x00\x01\x00\x00\x47\x05\x00\x01\x01" + "\x1c\x00\x01\x00\x11\x4c\x11\x4c\x11\x4c\x00\x47\x0d\x4d\x00\x4d"; + +static BYTE TEST_CLEAR_EXAMPLE_3[] = + "\x00\xdf\x0e\x00\x00\x00\x8b\x00\x00\x00\x00\x00\x00\x00\xfe\xfe" + "\xfe\xff\x80\x05\xff\xff\xff\x40\xfe\xfe\xfe\x40\x00\x00\x3f\x00" + "\x03\x00\x0b\x00\xfe\xfe\xfe\xc5\xd0\xc6\xd0\xc7\xd0\x68\xd4\x69" + "\xd4\x6a\xd4\x6b\xd4\x6c\xd4\x6d\xd4\x1a\xd4\x1a\xd4\xa6\xd0\x6e" + "\xd4\x6f\xd4\x70\xd4\x71\xd4\x72\xd4\x73\xd4\x74\xd4\x21\xd4\x22" + "\xd4\x23\xd4\x24\xd4\x25\xd4\xd9\xd0\xda\xd0\xdb\xd0\xc5\xd0\xc5" + "\xd0\xdc\xd0\xc2\xd0\x21\xd4\x22\xd4\x23\xd4\x24\xd4\x25\xd4\xc9" + "\xd0\xca\xd0\x5a\xd4\x2b\xd1\x28\xd1\x2c\xd1\x75\xd4\x27\xd4\x28" + "\xd4\x29\xd4\x2a\xd4\x1a\xd4\x1a\xd4\x1a\xd4\xb7\xd0\xb8\xd0\xb9" + "\xd0\xba\xd0\xbb\xd0\xbc\xd0\xbd\xd0\xbe\xd0\xbf\xd0\xc0\xd0\xc1" + "\xd0\xc2\xd0\xc3\xd0\xc4\xd0"; + +static BYTE TEST_CLEAR_EXAMPLE_4[] = + "\x01\x0b\x78\x00\x00\x00\x00\x00\x46\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x06\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x0f\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xb6\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xb6\x66\xff\xff\xff\xff\xff\xff\xff\xb6\x66\xdb\x90\x3a\xff\xff" + "\xb6\xff\xff\xff\xff\xff\xff\xff\xff\xff\x46\x91\x47\x91\x48\x91" + "\x49\x91\x4a\x91\x1b\x91"; + +int test_ClearDecompressExample1() +{ + int status; + BYTE* pSrcData; + UINT32 SrcSize; + UINT32 DstSize; + BYTE* pDstData = NULL; + CLEAR_CONTEXT* clear; + + clear = clear_context_new(FALSE); + + SrcSize = sizeof(TEST_CLEAR_EXAMPLE_1) - 1; + pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_1; + + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + + printf("clear_decompress example 1 status: %d\n", status); + + clear_context_free(clear); + + return 1; +} + +int test_ClearDecompressExample2() +{ + int status; + BYTE* pSrcData; + UINT32 SrcSize; + UINT32 DstSize; + BYTE* pDstData = NULL; + CLEAR_CONTEXT* clear; + + clear = clear_context_new(FALSE); + + SrcSize = sizeof(TEST_CLEAR_EXAMPLE_2) - 1; + pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_2; + + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + + printf("clear_decompress example 2 status: %d\n", status); + + clear_context_free(clear); + + return 1; +} + +int test_ClearDecompressExample3() +{ + int status; + BYTE* pSrcData; + UINT32 SrcSize; + UINT32 DstSize; + BYTE* pDstData = NULL; + CLEAR_CONTEXT* clear; + + clear = clear_context_new(FALSE); + + SrcSize = sizeof(TEST_CLEAR_EXAMPLE_3) - 1; + pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_3; + + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + + printf("clear_decompress example 3 status: %d\n", status); + + clear_context_free(clear); + + return 1; +} + +int test_ClearDecompressExample4() +{ + int status; + BYTE* pSrcData; + UINT32 SrcSize; + UINT32 DstSize; + BYTE* pDstData = NULL; + CLEAR_CONTEXT* clear; + + clear = clear_context_new(FALSE); + + SrcSize = sizeof(TEST_CLEAR_EXAMPLE_4) - 1; + pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_4; + + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + + printf("clear_decompress example 4 status: %d\n", status); + + clear_context_free(clear); + + return 1; +} + int TestFreeRDPCodecClear(int argc, char* argv[]) { + //test_ClearDecompressExample1(); + + //test_ClearDecompressExample2(); + + test_ClearDecompressExample3(); + + //test_ClearDecompressExample4(); + return 0; } From 61eb7f2f8e7dbda8ecc02a795b013b7eef1ed0b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 13 Jun 2014 17:30:13 -0400 Subject: [PATCH 38/50] libfreerdp-codec: fix ClearCodec decoding --- client/X11/xf_client.c | 49 +++++--- client/X11/xf_gfx.c | 38 +++++- client/X11/xfreerdp.h | 3 +- include/freerdp/codec/clear.h | 4 + libfreerdp/codec/clear.c | 109 ++++++++++++------ libfreerdp/codec/test/TestFreeRDPCodecClear.c | 4 +- 6 files changed, 151 insertions(+), 56 deletions(-) diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 4d9c26151..8011e6a82 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -985,45 +985,54 @@ void xf_process_channel_event(rdpChannels *channels, freerdp *instance) void xf_window_free(xfContext *xfc) { - rdpContext *context = (rdpContext *) xfc; + rdpContext* context = (rdpContext*) xfc; + xf_keyboard_free(xfc); - if(xfc->gc) + + if (xfc->gc) { XFreeGC(xfc->display, xfc->gc); xfc->gc = 0; } - if(xfc->gc_mono) + + if (xfc->gc_mono) { XFreeGC(xfc->display, xfc->gc_mono); xfc->gc_mono = 0; } - if(xfc->window) + + if (xfc->window) { xf_DestroyWindow(xfc, xfc->window); xfc->window = NULL; } - if(xfc->primary) + + if (xfc->primary) { XFreePixmap(xfc->display, xfc->primary); xfc->primary = 0; } - if(xfc->bitmap_mono) + + if (xfc->bitmap_mono) { XFreePixmap(xfc->display, xfc->bitmap_mono); xfc->bitmap_mono = 0; } - if(xfc->image) + + if (xfc->image) { xfc->image->data = NULL; XDestroyImage(xfc->image); xfc->image = NULL; } - if(context->cache) + + if (context->cache) { cache_free(context->cache); context->cache = NULL; } - if(context->rail) + + if (context->rail) { rail_free(context->rail); context->rail = NULL; @@ -1040,26 +1049,38 @@ void xf_window_free(xfContext *xfc) nsc_context_free(xfc->nsc); xfc->nsc = NULL; } - if(xfc->clrconv) + + if (xfc->clear) + { + clear_context_free(xfc->clear); + xfc->clear = NULL; + } + + if (xfc->clrconv) { freerdp_clrconv_free(xfc->clrconv); xfc->clrconv = NULL; } - if(xfc->hdc) + + if (xfc->hdc) + { gdi_DeleteDC(xfc->hdc); - if(xfc->xv_context) + } + + if (xfc->xv_context) { xf_tsmf_uninit(xfc); xfc->xv_context = NULL; } - if(xfc->clipboard_context) + + if (xfc->clipboard_context) { xf_cliprdr_uninit(xfc); xfc->clipboard_context = NULL; } } -void *xf_update_thread(void *arg) +void* xf_update_thread(void *arg) { int status; wMessage message; diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 55dffb2c1..94d01257c 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -54,6 +54,8 @@ int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* re xfc->nsc->height = resetGraphics->height; nsc_context_set_pixel_format(xfc->nsc, RDP_PIXEL_FORMAT_B8G8R8A8); + xfc->clear = clear_context_new(FALSE); + region16_init(&(xfc->invalidRegion)); xfc->graphicsReset = TRUE; @@ -256,6 +258,33 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { + int status; + UINT32 DstSize = 0; + BYTE* pDstData = NULL; + xfGfxSurface* surface; + RECTANGLE_16 invalidRect; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + + if (!surface) + return -1; + + status = clear_decompress(xfc->clear, cmd->data, cmd->length, &pDstData, &DstSize); + + printf("xf_SurfaceCommand_ClearCodec: status: %d\n", status); + + /* fill with pink for now to distinguish from the rest */ + + freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + cmd->left, cmd->top, cmd->width, cmd->height, 0xFF69B4); + + invalidRect.left = cmd->left; + invalidRect.top = cmd->top; + invalidRect.right = cmd->right; + invalidRect.bottom = cmd->bottom; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + if (!xfc->inGfxFrame) xf_OutputUpdate(xfc); @@ -286,7 +315,6 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) break; case RDPGFX_CODECID_CLEARCODEC: - printf("xf_SurfaceCommand_ClearCodec\n"); status = xf_SurfaceCommand_ClearCodec(xfc, context, cmd); break; @@ -482,8 +510,8 @@ int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId); - printf("xf_SurfaceToCache: cacheKey: 0x%016X cacheSlot: %ld\n", - surfaceToCache->cacheKey, surfaceToCache->cacheSlot); + //printf("xf_SurfaceToCache: cacheKey: 0x%016X cacheSlot: %ld\n", + // surfaceToCache->cacheKey, surfaceToCache->cacheSlot); if (!surface) return -1; @@ -524,8 +552,8 @@ int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* surface = (xfGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId); cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot); - printf("xf_CacheToSurface: cacheEntry: %d\n", - cacheToSurface->cacheSlot); + //printf("xf_CacheToSurface: cacheEntry: %d\n", + // cacheToSurface->cacheSlot); if (!surface || !cacheEntry) return -1; diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 347d7c62f..a1e6ebf16 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -31,7 +31,7 @@ typedef struct xf_context xfContext; #include #include #include -#include +#include #include #include #include @@ -151,6 +151,7 @@ struct xf_context BYTE* bmp_codec_nsc; RFX_CONTEXT* rfx; NSC_CONTEXT* nsc; + CLEAR_CONTEXT* clear; void* xv_context; void* clipboard_context; diff --git a/include/freerdp/codec/clear.h b/include/freerdp/codec/clear.h index c7fc22433..bb1550a25 100644 --- a/include/freerdp/codec/clear.h +++ b/include/freerdp/codec/clear.h @@ -30,6 +30,10 @@ struct _CLEAR_CONTEXT { BOOL Compressor; + UINT32 VBarStorageCursor; + void* VBarStorage[32768]; + UINT32 ShortVBarStorageCursor; + void* ShortVBarStorage[16384]; }; typedef struct _CLEAR_CONTEXT CLEAR_CONTEXT; diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c index d0bc0924f..c57f8c641 100644 --- a/libfreerdp/codec/clear.c +++ b/libfreerdp/codec/clear.c @@ -29,6 +29,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize) { + int index; BYTE glyphFlags; BYTE seqNumber; UINT16 glyphIndex; @@ -38,7 +39,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* UINT32 subcodecByteCount; if (SrcSize < 2) - return -1; + return -1001; glyphFlags = pSrcData[0]; seqNumber = pSrcData[1]; @@ -49,7 +50,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX) { if (SrcSize < 4) - return -1; + return -1002; glyphIndex = *((UINT16*) &pSrcData[2]); offset += 2; @@ -68,7 +69,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* /* Read composition payload header parameters */ if ((SrcSize - offset) < 12) - return -1; + return -1003; residualByteCount = *((UINT32*) &pSrcData[offset]); bandsByteCount = *((UINT32*) &pSrcData[offset + 4]); @@ -91,7 +92,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* UINT32 runLengthFactor = 0; if ((SrcSize - offset) < residualByteCount) - return -1; + return -1004; suboffset = 0; residualData = &pSrcData[offset]; @@ -99,7 +100,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* while (suboffset < residualByteCount) { if ((residualByteCount - suboffset) < 4) - return -1; + return -1005; blueValue = residualData[suboffset]; greenValue = residualData[suboffset + 1]; @@ -113,7 +114,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* if (runLengthFactor1 >= 0xFF) { if ((residualByteCount - suboffset) < 2) - return -1; + return -1006; runLengthFactor2 = *((UINT16*) &residualData[suboffset]); runLengthFactor = runLengthFactor2; @@ -122,7 +123,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* if (runLengthFactor2 >= 0xFFFF) { if ((residualByteCount - suboffset) < 4) - return -1; + return -1007; runLengthFactor3 = *((UINT32*) &residualData[suboffset]); runLengthFactor = runLengthFactor3; @@ -141,7 +142,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* UINT32 suboffset; if ((SrcSize - offset) < bandsByteCount) - return -1; + return -1008; suboffset = 0; bandsData = &pSrcData[offset]; @@ -157,9 +158,14 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* BYTE redBkg; BYTE* vBars; UINT16 vBarHeader; + UINT16 vBarIndex; + UINT16 vBarYOn; + UINT16 vBarYOff; + int vBarCount; + int vBarPixelCount; if ((bandsByteCount - suboffset) < 11) - return -1; + return -1009; xStart = *((UINT16*) &bandsData[suboffset]); xEnd = *((UINT16*) &bandsData[suboffset + 2]); @@ -170,31 +176,66 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* redBkg = bandsData[suboffset + 10]; suboffset += 11; - vBars = &bandsData[suboffset]; + vBarCount = (xEnd - xStart) + 1; - vBarHeader = *((UINT16*) &vBars[0]); + printf("CLEARCODEC_BAND: xStart: %d xEnd: %d yStart: %d yEnd: %d vBarCount: %d blueBkg: 0x%02X greenBkg: 0x%02X redBkg: 0x%02X\n", + xStart, xEnd, yStart, yEnd, vBarCount, blueBkg, greenBkg, redBkg); - if ((vBarHeader & 0xC000) == 0x8000) /* VBAR_CACHE_HIT */ + for (index = 0; index < vBarCount; index++) { - printf("VBAR_CACHE_HIT\n"); + vBars = &bandsData[suboffset]; + + if ((bandsByteCount - suboffset) < 2) + return -1010; + + vBarHeader = *((UINT16*) &vBars[0]); suboffset += 2; - } - else if ((vBarHeader & 0xC000) == 0xC000) /* SHORT_VBAR_CACHE_HIT */ - { - printf("SHORT_VBAR_CACHE_HIT\n"); - suboffset += 3; - } - else if ((vBarHeader & 0xC000) == 0) /* SHORT_VBAR_CACHE_MISS */ - { - printf("SHORT_VBAR_CACHE_MISS\n"); - suboffset += 2; - } - else - { - return -1; /* invalid vBarHeader */ - } - /* shortVBarPixels: variable */ + if ((vBarHeader & 0xC000) == 0x8000) /* VBAR_CACHE_HIT */ + { + vBarIndex = (vBarHeader & 0x7FFF); + + printf("VBAR_CACHE_HIT: vBarIndex: %d\n", + vBarIndex); + } + else if ((vBarHeader & 0xC000) == 0xC000) /* SHORT_VBAR_CACHE_HIT */ + { + vBarIndex = (vBarHeader & 0x3FFF); + + if ((bandsByteCount - suboffset) < 1) + return -1011; + + vBarYOn = vBars[2]; + suboffset += 1; + + printf("SHORT_VBAR_CACHE_HIT: vBarIndex: %d vBarYOn: %d\n", + vBarIndex, vBarYOn); + } + else if ((vBarHeader & 0xC000) == 0x0000) /* SHORT_VBAR_CACHE_MISS */ + { + vBarYOn = (vBarHeader & 0xFF); + vBarYOff = ((vBarHeader >> 8) & 0x3F); + + if (vBarYOff < vBarYOn) + return -1012; + + /* shortVBarPixels: variable */ + + vBarPixelCount = (3 * (vBarYOff - vBarYOn)); + + printf("SHORT_VBAR_CACHE_MISS: vBarYOn: %d vBarYOff: %d bytes: %d\n", + vBarYOn, vBarYOff, vBarPixelCount); + + if ((bandsByteCount - suboffset) < vBarPixelCount) + return -1013; + + suboffset += vBarPixelCount; + } + else + { + return -1014; /* invalid vBarHeader */ + } + } } /* Decompress bands layer and write to output bitmap */ @@ -214,7 +255,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* UINT32 suboffset; if ((SrcSize - offset) < subcodecByteCount) - return -1; + return -1015; suboffset = 0; subcodecs = &pSrcData[offset]; @@ -222,7 +263,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* while (suboffset < subcodecByteCount) { if ((subcodecByteCount - suboffset) < 13) - return -1; + return -1016; xStart = *((UINT16*) &subcodecs[suboffset]); yStart = *((UINT16*) &subcodecs[suboffset + 2]); @@ -232,11 +273,11 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE* subcodecId = subcodecs[suboffset + 12]; suboffset += 13; - printf("bitmapDataByteCount: %d subcodecByteCount: %d suboffset: %d\n", - bitmapDataByteCount, subcodecByteCount, suboffset); + printf("bitmapDataByteCount: %d subcodecByteCount: %d suboffset: %d subCodecId: %d\n", + bitmapDataByteCount, subcodecByteCount, suboffset, subcodecId); if ((subcodecByteCount - suboffset) < bitmapDataByteCount) - return -1; + return -1017; bitmapData = &subcodecs[suboffset]; diff --git a/libfreerdp/codec/test/TestFreeRDPCodecClear.c b/libfreerdp/codec/test/TestFreeRDPCodecClear.c index c83993b0f..fcec61acf 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecClear.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecClear.c @@ -135,9 +135,9 @@ int TestFreeRDPCodecClear(int argc, char* argv[]) //test_ClearDecompressExample2(); - test_ClearDecompressExample3(); + //test_ClearDecompressExample3(); - //test_ClearDecompressExample4(); + test_ClearDecompressExample4(); return 0; } From 903c5dada15f60c52964e471fc138eace48a60c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benoi=CC=82t=20LeBlanc?= Date: Mon, 16 Jun 2014 15:01:09 -0400 Subject: [PATCH 39/50] fix smart sizing parsing --- client/common/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/common/file.c b/client/common/file.c index 3d018b845..c4937343a 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -63,7 +63,7 @@ BOOL freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, int va file->ScreenModeId = value; else if (_stricmp(name, "span monitors") == 0) file->SpanMonitors = value; - else if (_stricmp(name, "smartsizing") == 0) + else if (_stricmp(name, "smart sizing") == 0) file->SmartSizing = value; else if (_stricmp(name, "enablesuperpan") == 0) file->EnableSuperSpan = value; From b782486e8949f44378298335197ba87dfa155b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 17 Jun 2014 13:34:23 -0400 Subject: [PATCH 40/50] channels/drdynvc: cleanup --- channels/drdynvc/client/drdynvc_main.c | 94 ++++++++++++++------------ channels/drdynvc/client/dvcman.c | 17 +++-- channels/drdynvc/client/dvcman.h | 3 +- 3 files changed, 64 insertions(+), 50 deletions(-) diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 6b4066202..2daa99782 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -34,39 +34,39 @@ #include "drdynvc_types.h" #include "drdynvc_main.h" -static int drdynvc_write_variable_uint(wStream* stream, UINT32 val) +static int drdynvc_write_variable_uint(wStream* s, UINT32 val) { int cb; if (val <= 0xFF) { cb = 0; - Stream_Write_UINT8(stream, val); + Stream_Write_UINT8(s, val); } else if (val <= 0xFFFF) { cb = 1; - Stream_Write_UINT16(stream, val); + Stream_Write_UINT16(s, val); } else { cb = 2; - Stream_Write_UINT32(stream, val); + Stream_Write_UINT32(s, val); } return cb; } -int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UINT32 data_size) +int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UINT32 dataSize) { wStream* data_out; UINT32 pos = 0; UINT32 cbChId; UINT32 cbLen; - UINT32 chunk_len; - int error; + UINT32 chunkLength; + int status; - DEBUG_DVC("ChannelId=%d size=%d", ChannelId, data_size); + DEBUG_DVC("ChannelId=%d size=%d", ChannelId, dataSize); if (drdynvc->channel_error != CHANNEL_RC_OK) return 1; @@ -75,38 +75,38 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN Stream_SetPosition(data_out, 1); cbChId = drdynvc_write_variable_uint(data_out, ChannelId); - if (data_size == 0) + if (dataSize == 0) { pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x40 | cbChId); Stream_SetPosition(data_out, pos); - error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); + status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); } - else if (data_size <= CHANNEL_CHUNK_LENGTH - pos) + else if (dataSize <= CHANNEL_CHUNK_LENGTH - pos) { pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x30 | cbChId); Stream_SetPosition(data_out, pos); - Stream_Write(data_out, data, data_size); - error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); + Stream_Write(data_out, data, dataSize); + status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); } else { /* Fragment the data */ - cbLen = drdynvc_write_variable_uint(data_out, data_size); + cbLen = drdynvc_write_variable_uint(data_out, dataSize); pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x20 | cbChId | (cbLen << 2)); Stream_SetPosition(data_out, pos); - chunk_len = CHANNEL_CHUNK_LENGTH - pos; - Stream_Write(data_out, data, chunk_len); - data += chunk_len; - data_size -= chunk_len; - error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); + chunkLength = CHANNEL_CHUNK_LENGTH - pos; + Stream_Write(data_out, data, chunkLength); + data += chunkLength; + dataSize -= chunkLength; + status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); - while (error == CHANNEL_RC_OK && data_size > 0) + while (status == CHANNEL_RC_OK && dataSize > 0) { data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); Stream_SetPosition(data_out, 1); @@ -117,20 +117,20 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN Stream_Write_UINT8(data_out, 0x30 | cbChId); Stream_SetPosition(data_out, pos); - chunk_len = data_size; - if (chunk_len > CHANNEL_CHUNK_LENGTH - pos) - chunk_len = CHANNEL_CHUNK_LENGTH - pos; - Stream_Write(data_out, data, chunk_len); - data += chunk_len; - data_size -= chunk_len; - error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); + chunkLength = dataSize; + if (chunkLength > CHANNEL_CHUNK_LENGTH - pos) + chunkLength = CHANNEL_CHUNK_LENGTH - pos; + Stream_Write(data_out, data, chunkLength); + data += chunkLength; + dataSize -= chunkLength; + status = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); } } - if (error != CHANNEL_RC_OK) + if (status != CHANNEL_RC_OK) { - drdynvc->channel_error = error; - DEBUG_WARN("VirtualChannelWrite failed %d", error); + drdynvc->channel_error = status; + DEBUG_WARN("VirtualChannelWrite failed %d", status); return 1; } @@ -139,13 +139,13 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN int drdynvc_push_event(drdynvcPlugin* drdynvc, wMessage* event) { - int error; + int status; - error = svc_plugin_send_event((rdpSvcPlugin*) drdynvc, event); + status = svc_plugin_send_event((rdpSvcPlugin*) drdynvc, event); - if (error != CHANNEL_RC_OK) + if (status != CHANNEL_RC_OK) { - DEBUG_WARN("pVirtualChannelEventPush failed %d", error); + DEBUG_WARN("pVirtualChannelEventPush failed %d", status); return 1; } @@ -155,13 +155,13 @@ int drdynvc_push_event(drdynvcPlugin* drdynvc, wMessage* event) static int drdynvc_send_capability_response(drdynvcPlugin* drdynvc) { int status; - wStream* data_out; + wStream* s; - data_out = Stream_New(NULL, 4); - Stream_Write_UINT16(data_out, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */ - Stream_Write_UINT16(data_out, drdynvc->version); + s = Stream_New(NULL, 4); + Stream_Write_UINT16(s, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */ + Stream_Write_UINT16(s, drdynvc->version); - status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); + status = svc_plugin_send((rdpSvcPlugin*) drdynvc, s); if (status != CHANNEL_RC_OK) { @@ -201,22 +201,22 @@ static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, in return 0; } -static UINT32 drdynvc_read_variable_uint(wStream* stream, int cbLen) +static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen) { UINT32 val; switch (cbLen) { case 0: - Stream_Read_UINT8(stream, val); + Stream_Read_UINT8(s, val); break; case 1: - Stream_Read_UINT16(stream, val); + Stream_Read_UINT16(s, val); break; default: - Stream_Read_UINT32(stream, val); + Stream_Read_UINT32(s, val); break; } @@ -446,6 +446,9 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) _p = (drdynvcPlugin*) calloc(1, sizeof(drdynvcPlugin)); + if (!_p) + return FALSE; + _p->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | @@ -465,7 +468,10 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) && (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { - context = (DrdynvcClientContext*) malloc(sizeof(DrdynvcClientContext)); + context = (DrdynvcClientContext*) calloc(1, sizeof(DrdynvcClientContext)); + + if (!context) + return -1; context->handle = (void*) _p; _p->context = context; diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c index 274d00cbb..a831bf6eb 100644 --- a/channels/drdynvc/client/dvcman.c +++ b/channels/drdynvc/client/dvcman.c @@ -237,6 +237,8 @@ static void dvcman_channel_free(DVCMAN_CHANNEL* channel) if (channel->channel_callback) channel->channel_callback->OnClose(channel->channel_callback); + DeleteCriticalSection(&(channel->lock)); + free(channel); } @@ -304,9 +306,11 @@ static int dvcman_write_channel(IWTSVirtualChannel* pChannel, UINT32 cbSize, BYT int status; DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel; - WaitForSingleObject(channel->dvc_chan_mutex, INFINITE); + EnterCriticalSection(&(channel->lock)); + status = drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize); - ReleaseMutex(channel->dvc_chan_mutex); + + LeaveCriticalSection(&(channel->lock)); return status; } @@ -335,8 +339,10 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel IWTSVirtualChannelCallback* pCallback; DVCMAN* dvcman = (DVCMAN*) pChannelMgr; - channel = (DVCMAN_CHANNEL*) malloc(sizeof(DVCMAN_CHANNEL)); - ZeroMemory(channel, sizeof(DVCMAN_CHANNEL)); + channel = (DVCMAN_CHANNEL*) calloc(1, sizeof(DVCMAN_CHANNEL)); + + if (!channel) + return -1; channel->dvcman = dvcman; channel->channel_id = ChannelId; @@ -350,7 +356,8 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel { channel->iface.Write = dvcman_write_channel; channel->iface.Close = dvcman_close_channel_iface; - channel->dvc_chan_mutex = CreateMutex(NULL, FALSE, NULL); + + InitializeCriticalSection(&(channel->lock)); bAccept = 1; pCallback = NULL; diff --git a/channels/drdynvc/client/dvcman.h b/channels/drdynvc/client/dvcman.h index 0cf33960f..3b627eae4 100644 --- a/channels/drdynvc/client/dvcman.h +++ b/channels/drdynvc/client/dvcman.h @@ -23,6 +23,7 @@ #include #include +#include #include #include "drdynvc_main.h" @@ -79,7 +80,7 @@ struct _DVCMAN_CHANNEL IWTSVirtualChannelCallback* channel_callback; wStream* dvc_data; - HANDLE dvc_chan_mutex; + CRITICAL_SECTION lock; }; typedef struct _DVCMAN_CHANNEL DVCMAN_CHANNEL; From d69316198f2a4bfb8cb696b3fce08d310fcd97c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 17 Jun 2014 16:15:30 -0400 Subject: [PATCH 41/50] xfreerdp: add egfx support for planar codec --- client/X11/xf_gfx.c | 32 +++++++++++++++++++++++++++++++- include/freerdp/codec/bitmap.h | 2 ++ include/freerdp/codec/color.h | 2 +- libfreerdp/codec/color.c | 28 ++++++++++++++++++++++++---- libfreerdp/codec/planar.h | 2 -- 5 files changed, 58 insertions(+), 8 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 94d01257c..044499b0d 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -293,6 +293,37 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { + int status; + UINT32 DstSize = 0; + BYTE* DstData = NULL; + xfGfxSurface* surface; + RECTANGLE_16 invalidRect; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + + if (!surface) + return -1; + + DstSize = cmd->width * cmd->height * 4; + DstData = (BYTE*) malloc(DstSize); + + if (!DstData) + return -1; + + status = freerdp_bitmap_planar_decompress(cmd->data, DstData, cmd->width, cmd->height, cmd->length); + + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, + cmd->width, cmd->height, DstData, PIXEL_FORMAT_XRGB32_VF, cmd->width * 4, 0, 0); + + free(DstData); + + invalidRect.left = cmd->left; + invalidRect.top = cmd->top; + invalidRect.right = cmd->right; + invalidRect.bottom = cmd->bottom; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + if (!xfc->inGfxFrame) xf_OutputUpdate(xfc); @@ -319,7 +350,6 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) break; case RDPGFX_CODECID_PLANAR: - printf("xf_SurfaceCommand_Planar\n"); status = xf_SurfaceCommand_Planar(xfc, context, cmd); break; diff --git a/include/freerdp/codec/bitmap.h b/include/freerdp/codec/bitmap.h index 6e09f2d8c..babfe6246 100644 --- a/include/freerdp/codec/bitmap.h +++ b/include/freerdp/codec/bitmap.h @@ -40,6 +40,8 @@ FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height, typedef struct _BITMAP_PLANAR_CONTEXT BITMAP_PLANAR_CONTEXT; +FREERDP_API int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size); + FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* dstData, int* dstSize); diff --git a/include/freerdp/codec/color.h b/include/freerdp/codec/color.h index 0d72ed07c..4fdaf8aa9 100644 --- a/include/freerdp/codec/color.h +++ b/include/freerdp/codec/color.h @@ -36,7 +36,7 @@ #define FREERDP_PIXEL_FORMAT(_flip, _bpp, _type, _a, _r, _g, _b) \ ((_flip << 30) | (_bpp << 24) | (_type << 16) | (_a << 12) | (_r << 8) | (_g << 4) | (_b)) -#define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 30) & 0x02) +#define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 30) & 0x03) #define FREERDP_PIXEL_FORMAT_BPP(_format) (((_format) >> 24) & 0x3F) #define FREERDP_PIXEL_FORMAT_TYPE(_format) (((_format) >> 16) & 0xFF) #define FREERDP_PIXEL_FORMAT_A(_format) (((_format) >> 12) & 0x0F) diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index bd5b1c238..540d31331 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -1176,6 +1176,8 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc) { int x, y; + int srcFlip; + int dstFlip; BYTE a, r, g, b; int beg, end, inc; int srcBitsPerPixel; @@ -1183,12 +1185,18 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs int dstBitsPerPixel; int dstBytesPerPixel; BOOL overlap = FALSE; + BOOL vFlip = FALSE; srcBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwSrcFormat); srcBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwSrcFormat) / 8); + srcFlip = FREERDP_PIXEL_FORMAT_FLIP(dwSrcFormat); dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwDstFormat); dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwDstFormat) / 8); + dstFlip = FREERDP_PIXEL_FORMAT_FLIP(dwDstFormat); + + if (srcFlip != dstFlip) + vFlip = TRUE; if (pDstData == pSrcData) { @@ -1252,11 +1260,23 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs end = nHeight; } - for (y = beg; y != end; y += inc) + if (!vFlip) { - pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * srcBytesPerPixel)]; - pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * dstBytesPerPixel)]; - MoveMemory(pDstPixel, pSrcPixel, nWidth * 4); + for (y = beg; y != end; y += inc) + { + pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * srcBytesPerPixel)]; + pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * dstBytesPerPixel)]; + MoveMemory(pDstPixel, pSrcPixel, nWidth * 4); + } + } + else + { + for (y = beg; y != end; y += inc) + { + pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * srcBytesPerPixel)]; + pDstPixel = (UINT32*) &pDstData[((nYDst + (nHeight - y - 1)) * nDstStep) + (nXDst * dstBytesPerPixel)]; + MoveMemory(pDstPixel, pSrcPixel, nWidth * 4); + } } } } diff --git a/libfreerdp/codec/planar.h b/libfreerdp/codec/planar.h index bbb9f6068..a8e34c87a 100644 --- a/libfreerdp/codec/planar.h +++ b/libfreerdp/codec/planar.h @@ -87,8 +87,6 @@ struct _BITMAP_PLANAR_CONTEXT BYTE* rlePlanesBuffer; }; -FREERDP_API int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size); - FREERDP_API int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4]); FREERDP_API BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* plane, int width, int height, BYTE* outPlane, int* dstSize); FREERDP_API BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane); From 425763d30a96cc3a2f518cc40aaa76f8b6951092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 17 Jun 2014 16:44:24 -0400 Subject: [PATCH 42/50] libfreerdp-codec: start offering more flexible planar codec decompression --- client/X11/xf_gfx.c | 10 +-- include/freerdp/codec/bitmap.h | 3 + libfreerdp/codec/planar.c | 112 +++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 8 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 044499b0d..98b4bb437 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -294,7 +294,6 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { int status; - UINT32 DstSize = 0; BYTE* DstData = NULL; xfGfxSurface* surface; RECTANGLE_16 invalidRect; @@ -304,13 +303,8 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF if (!surface) return -1; - DstSize = cmd->width * cmd->height * 4; - DstData = (BYTE*) malloc(DstSize); - - if (!DstData) - return -1; - - status = freerdp_bitmap_planar_decompress(cmd->data, DstData, cmd->width, cmd->height, cmd->length); + status = planar_decompress(NULL, cmd->data, cmd->length, &DstData, + PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0, cmd->width, cmd->height); freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, DstData, PIXEL_FORMAT_XRGB32_VF, cmd->width * 4, 0, 0); diff --git a/include/freerdp/codec/bitmap.h b/include/freerdp/codec/bitmap.h index babfe6246..0f0a6c6da 100644 --- a/include/freerdp/codec/bitmap.h +++ b/include/freerdp/codec/bitmap.h @@ -48,4 +48,7 @@ FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, FREERDP_API BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight); FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context); +FREERDP_API int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize, + BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight); + #endif /* FREERDP_CODEC_BITMAP_H */ diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index a320da5a3..4021651e7 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -273,6 +273,118 @@ int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, in return (size == (srcp - srcData)) ? 0 : -1; } +int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize, + BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) +{ + int status; + BYTE* srcp; + BYTE FormatHeader; + BYTE* pDstData = NULL; + UINT32 UncompressedSize; + + if ((nWidth * nHeight) <= 0) + return -1; + + srcp = pSrcData; + UncompressedSize = nWidth * nHeight * 4; + + pDstData = *ppDstData; + + if (!pDstData) + { + pDstData = (BYTE*) malloc(UncompressedSize); + + if (!pDstData) + return -1; + + *ppDstData = pDstData; + } + + FormatHeader = *srcp; + srcp++; + + /* AlphaPlane */ + + if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA)) + { + if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) + { + status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, + pDstData + 3, UncompressedSize - (srcp - pSrcData)); + + if (status < 0) + return -1; + + srcp += status; + } + else + { + status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, + pDstData + 3, UncompressedSize - (srcp - pSrcData)); + + srcp += status; + } + } + + if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) + { + /* LumaOrRedPlane */ + + status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, + pDstData + 2, UncompressedSize - (srcp - pSrcData)); + + if (status < 0) + return -1; + + srcp += status; + + /* OrangeChromaOrGreenPlane */ + + status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, + pDstData + 1, UncompressedSize - (srcp - pSrcData)); + + if (status < 0) + return -1; + + srcp += status; + + /* GreenChromeOrBluePlane */ + + status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, + pDstData + 0, UncompressedSize - (srcp - pSrcData)); + + if (status < 0) + return -1; + + srcp += status; + } + else + { + /* LumaOrRedPlane */ + + status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, + pDstData + 2, UncompressedSize - (srcp - pSrcData)); + srcp += status; + + /* OrangeChromaOrGreenPlane */ + + status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, + pDstData + 1, UncompressedSize - (srcp - pSrcData)); + srcp += status; + + /* GreenChromeOrBluePlane */ + + status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, + pDstData + 0, UncompressedSize - (srcp - pSrcData)); + srcp += status; + srcp++; + } + + status = (UncompressedSize == (srcp - pSrcData)) ? 1 : -1; + + return status; +} + int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4]) { int bpp; From ea3822c357a8d58c1b7efd9db4d438c799fea647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 18 Jun 2014 17:46:22 -0400 Subject: [PATCH 43/50] libfreerdp-codec: cleanup planar decoder --- include/freerdp/codec/bitmap.h | 2 - libfreerdp/codec/bitmap_decode.c | 11 +- libfreerdp/codec/planar.c | 179 ++++++++----------------------- 3 files changed, 51 insertions(+), 141 deletions(-) diff --git a/include/freerdp/codec/bitmap.h b/include/freerdp/codec/bitmap.h index 0f0a6c6da..d25c28b84 100644 --- a/include/freerdp/codec/bitmap.h +++ b/include/freerdp/codec/bitmap.h @@ -40,8 +40,6 @@ FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height, typedef struct _BITMAP_PLANAR_CONTEXT BITMAP_PLANAR_CONTEXT; -FREERDP_API int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size); - FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* dstData, int* dstSize); diff --git a/libfreerdp/codec/bitmap_decode.c b/libfreerdp/codec/bitmap_decode.c index 2330872c9..74ae94a74 100644 --- a/libfreerdp/codec/bitmap_decode.c +++ b/libfreerdp/codec/bitmap_decode.c @@ -260,7 +260,9 @@ static UINT32 ExtractRunLength(UINT32 code, BYTE* pbOrderHdr, UINT32* advance) */ BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp) { - BYTE* TmpBfr; + int status; + BYTE* TmpBfr; + BYTE* pDstData; if (srcBpp == 16 && dstBpp == 16) { @@ -271,7 +273,12 @@ BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int } else if (srcBpp == 32 && dstBpp == 32) { - if (freerdp_bitmap_planar_decompress(srcData, dstData, width, height, size) < 0) + pDstData = dstData; + + status = planar_decompress(NULL, srcData, size, &pDstData, + PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height); + + if (status < 0) return FALSE; } else if (srcBpp == 15 && dstBpp == 15) diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index 4021651e7..a527b4bee 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -28,7 +28,7 @@ #include "planar.h" -static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int srcSize) +static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, int nWidth, int nHeight, int nChannel) { int k; int x, y; @@ -44,38 +44,33 @@ static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, BYTE* previousScanline; k = 0; + pDstData = &pDstData[nChannel]; - srcp = inPlane; - dstp = outPlane; - scanline = width * 4; + srcp = pSrcData; + dstp = pDstData; + scanline = nWidth * 4; previousScanline = NULL; - y = 0; - - while (y < height) + for (y = 0; y < nHeight; y++) { pixel = 0; - dstp = (outPlane + height * scanline) - ((y + 1) * scanline); + dstp = &pDstData[(nHeight - y - 1) * scanline]; currentScanline = dstp; - x = 0; - - while (x < width) + for (x = 0; x < nWidth; ) { controlByte = *srcp; srcp++; - if ((srcp - inPlane) > srcSize) + if ((srcp - pSrcData) > SrcSize) { - printf("freerdp_bitmap_planar_decompress_plane_rle: error reading input buffer\n"); + printf("planar_decompress_plane_rle: error reading input buffer\n"); return -1; } nRunLength = PLANAR_CONTROL_BYTE_RUN_LENGTH(controlByte); cRawBytes = PLANAR_CONTROL_BYTE_RAW_BYTES(controlByte); - //printf("CONTROL(%d, %d)\n", cRawBytes, nRunLength); - if (nRunLength == 1) { nRunLength = cRawBytes + 16; @@ -87,23 +82,9 @@ static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, cRawBytes = 0; } -#if 0 - printf("y: %d cRawBytes: %d nRunLength: %d\n", y, cRawBytes, nRunLength); - - printf("RAW["); - - for (k = 0; k < cRawBytes; k++) + if (((dstp + (cRawBytes + nRunLength)) - currentScanline) > nWidth * 4) { - printf("0x%02X%s", srcp[k], - ((k + 1) == cRawBytes) ? "" : ", "); - } - - printf("] RUN[%d]\n", nRunLength); -#endif - - if (((dstp + (cRawBytes + nRunLength)) - currentScanline) > width * 4) - { - printf("freerdp_bitmap_planar_decompress_plane_rle: too many pixels in scanline\n"); + printf("planar_decompress_plane_rle: too many pixels in scanline\n"); return -1; } @@ -170,107 +151,28 @@ static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, } previousScanline = currentScanline; - y++; } - return (int) (srcp - inPlane); + return (int) (srcp - pSrcData); } -static int freerdp_bitmap_planar_decompress_plane_raw(BYTE* srcData, int width, int height, BYTE* dstData, int size) +static int planar_decompress_plane_raw(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, int nWidth, int nHeight, int nChannel) { int x, y; + BYTE* srcp = pSrcData; - for (y = 0; y < height; y++) + pDstData = &pDstData[nChannel]; + + for (y = 0; y < nHeight; y++) { - for (x = 0; x < width; x++) + for (x = 0; x < nWidth; x++) { - dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)]; + pDstData[(((nHeight - y - 1) * nWidth) + x) * 4] = *srcp; + srcp++; } } - return (width * height); -} - -int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size) -{ - BYTE* srcp; - int dstSize; - BYTE FormatHeader; - - srcp = srcData; - - FormatHeader = *srcp; - srcp++; - - /* AlphaPlane */ - - if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA)) - { - if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) - { - dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 3, size - (srcp - srcData)); - - if (dstSize < 0) - return -1; - - srcp += dstSize; - } - else - { - dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 3, size - (srcp - srcData)); - srcp += dstSize; - } - } - - if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) - { - /* LumaOrRedPlane */ - - dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 2, size - (srcp - srcData)); - - if (dstSize < 0) - return -1; - - srcp += dstSize; - - /* OrangeChromaOrGreenPlane */ - - dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 1, size - (srcp - srcData)); - - if (dstSize < 0) - return -1; - - srcp += dstSize; - - /* GreenChromeOrBluePlane */ - - dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 0, size - (srcp - srcData)); - - if (dstSize < 0) - return -1; - - srcp += dstSize; - } - else - { - /* LumaOrRedPlane */ - - dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 2, size - (srcp - srcData)); - srcp += dstSize; - - /* OrangeChromaOrGreenPlane */ - - dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 1, size - (srcp - srcData)); - srcp += dstSize; - - /* GreenChromeOrBluePlane */ - - dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 0, size - (srcp - srcData)); - srcp += dstSize; - srcp++; - } - - return (size == (srcp - srcData)) ? 0 : -1; + return (nWidth * nHeight); } int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize, @@ -309,8 +211,8 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS { if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) { - status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, - pDstData + 3, UncompressedSize - (srcp - pSrcData)); + status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), + pDstData, nWidth, nHeight, 3); if (status < 0) return -1; @@ -319,8 +221,8 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS } else { - status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, - pDstData + 3, UncompressedSize - (srcp - pSrcData)); + status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), + pDstData, nWidth, nHeight, 3); srcp += status; } @@ -330,8 +232,8 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS { /* LumaOrRedPlane */ - status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, - pDstData + 2, UncompressedSize - (srcp - pSrcData)); + status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), + pDstData, nWidth, nHeight, 2); if (status < 0) return -1; @@ -340,8 +242,8 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* OrangeChromaOrGreenPlane */ - status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, - pDstData + 1, UncompressedSize - (srcp - pSrcData)); + status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), + pDstData, nWidth, nHeight, 1); if (status < 0) return -1; @@ -350,8 +252,8 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* GreenChromeOrBluePlane */ - status = freerdp_bitmap_planar_decompress_plane_rle(srcp, nWidth, nHeight, - pDstData + 0, UncompressedSize - (srcp - pSrcData)); + status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), + pDstData, nWidth, nHeight, 0); if (status < 0) return -1; @@ -362,25 +264,28 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS { /* LumaOrRedPlane */ - status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, - pDstData + 2, UncompressedSize - (srcp - pSrcData)); + status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), + pDstData, nWidth, nHeight, 2); + srcp += status; /* OrangeChromaOrGreenPlane */ - status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, - pDstData + 1, UncompressedSize - (srcp - pSrcData)); + status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), + pDstData, nWidth, nHeight, 1); + srcp += status; /* GreenChromeOrBluePlane */ - status = freerdp_bitmap_planar_decompress_plane_raw(srcp, nWidth, nHeight, - pDstData + 0, UncompressedSize - (srcp - pSrcData)); + status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), + pDstData, nWidth, nHeight, 0); + srcp += status; srcp++; } - status = (UncompressedSize == (srcp - pSrcData)) ? 1 : -1; + status = (SrcSize == (srcp - pSrcData)) ? 1 : -1; return status; } From f6d029d5acf66d76f681e30405fb19d570df5e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 19 Jun 2014 12:11:06 -0400 Subject: [PATCH 44/50] libfreerdp-codec: improve planar handling of scanlines --- libfreerdp/codec/planar.c | 56 +++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index a527b4bee..9b57f33cb 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -28,14 +28,13 @@ #include "planar.h" -static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, int nWidth, int nHeight, int nChannel) +static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, + int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel) { - int k; int x, y; BYTE* srcp; BYTE* dstp; UINT32 pixel; - int scanline; int cRawBytes; int nRunLength; int deltaValue; @@ -43,18 +42,14 @@ static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs BYTE* currentScanline; BYTE* previousScanline; - k = 0; - pDstData = &pDstData[nChannel]; - srcp = pSrcData; dstp = pDstData; - scanline = nWidth * 4; previousScanline = NULL; for (y = 0; y < nHeight; y++) { pixel = 0; - dstp = &pDstData[(nHeight - y - 1) * scanline]; + dstp = &pDstData[((nHeight - y - 1) * nDstStep) + nChannel]; currentScanline = dstp; for (x = 0; x < nWidth; ) @@ -64,7 +59,7 @@ static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs if ((srcp - pSrcData) > SrcSize) { - printf("planar_decompress_plane_rle: error reading input buffer\n"); + fprintf(stderr, "planar_decompress_plane_rle: error reading input buffer\n"); return -1; } @@ -84,7 +79,7 @@ static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs if (((dstp + (cRawBytes + nRunLength)) - currentScanline) > nWidth * 4) { - printf("planar_decompress_plane_rle: too many pixels in scanline\n"); + fprintf(stderr, "planar_decompress_plane_rle: too many pixels in scanline\n"); return -1; } @@ -156,23 +151,26 @@ static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs return (int) (srcp - pSrcData); } -static int planar_decompress_plane_raw(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, int nWidth, int nHeight, int nChannel) +static int planar_decompress_plane_raw(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, + int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel) { int x, y; + BYTE* dstp = NULL; BYTE* srcp = pSrcData; - pDstData = &pDstData[nChannel]; - for (y = 0; y < nHeight; y++) { + dstp = &pDstData[((nHeight - y - 1) * nDstStep) + nChannel]; + for (x = 0; x < nWidth; x++) { - pDstData[(((nHeight - y - 1) * nWidth) + x) * 4] = *srcp; + *dstp = *srcp; + dstp += 4; srcp++; } } - return (nWidth * nHeight); + return (int) (srcp - pSrcData); } int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize, @@ -212,7 +210,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) { status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), - pDstData, nWidth, nHeight, 3); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3); if (status < 0) return -1; @@ -222,7 +220,10 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS else { status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), - pDstData, nWidth, nHeight, 3); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3); + + if (status < 0) + return -1; srcp += status; } @@ -233,7 +234,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* LumaOrRedPlane */ status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), - pDstData, nWidth, nHeight, 2); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2); if (status < 0) return -1; @@ -243,7 +244,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* OrangeChromaOrGreenPlane */ status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), - pDstData, nWidth, nHeight, 1); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1); if (status < 0) return -1; @@ -253,7 +254,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* GreenChromeOrBluePlane */ status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), - pDstData, nWidth, nHeight, 0); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0); if (status < 0) return -1; @@ -265,21 +266,30 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* LumaOrRedPlane */ status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), - pDstData, nWidth, nHeight, 2); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2); + + if (status < 0) + return -1; srcp += status; /* OrangeChromaOrGreenPlane */ status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), - pDstData, nWidth, nHeight, 1); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1); + + if (status < 0) + return -1; srcp += status; /* GreenChromeOrBluePlane */ status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), - pDstData, nWidth, nHeight, 0); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0); + + if (status < 0) + return -1; srcp += status; srcp++; From 57b0e4d01008474b5beaa9fb058bc6e0f823f0c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 19 Jun 2014 13:08:07 -0400 Subject: [PATCH 45/50] libfreerdp-codec: handle flipping in planar decompression --- client/X11/xf_gfx.c | 2 +- libfreerdp/codec/bitmap_decode.c | 2 +- libfreerdp/codec/planar.c | 60 ++++++++++++++++++++++++-------- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 98b4bb437..c4336a6fd 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -307,7 +307,7 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0, cmd->width, cmd->height); freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, - cmd->width, cmd->height, DstData, PIXEL_FORMAT_XRGB32_VF, cmd->width * 4, 0, 0); + cmd->width, cmd->height, DstData, PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0); free(DstData); diff --git a/libfreerdp/codec/bitmap_decode.c b/libfreerdp/codec/bitmap_decode.c index 74ae94a74..c5232d988 100644 --- a/libfreerdp/codec/bitmap_decode.c +++ b/libfreerdp/codec/bitmap_decode.c @@ -276,7 +276,7 @@ BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int pDstData = dstData; status = planar_decompress(NULL, srcData, size, &pDstData, - PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height); + PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height); if (status < 0) return FALSE; diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index 9b57f33cb..15ac70f9f 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -29,7 +29,7 @@ #include "planar.h" static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, - int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel) + int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel, BOOL vFlip) { int x, y; BYTE* srcp; @@ -38,6 +38,7 @@ static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs int cRawBytes; int nRunLength; int deltaValue; + int beg, end, inc; BYTE controlByte; BYTE* currentScanline; BYTE* previousScanline; @@ -46,10 +47,24 @@ static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs dstp = pDstData; previousScanline = NULL; - for (y = 0; y < nHeight; y++) + if (vFlip) { + beg = nHeight - 1; + end = -1; + inc = -1; + } + else + { + beg = 0; + end = nHeight; + inc = 1; + } + + for (y = beg; y != end; y += inc) + { + dstp = &pDstData[(y * nDstStep) + nChannel]; + pixel = 0; - dstp = &pDstData[((nHeight - y - 1) * nDstStep) + nChannel]; currentScanline = dstp; for (x = 0; x < nWidth; ) @@ -152,15 +167,29 @@ static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs } static int planar_decompress_plane_raw(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, - int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel) + int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel, BOOL vFlip) { int x, y; + int beg, end, inc; BYTE* dstp = NULL; BYTE* srcp = pSrcData; - for (y = 0; y < nHeight; y++) + if (vFlip) { - dstp = &pDstData[((nHeight - y - 1) * nDstStep) + nChannel]; + beg = nHeight - 1; + end = -1; + inc = -1; + } + else + { + beg = 0; + end = nHeight; + inc = 1; + } + + for (y = beg; y != end; y += inc) + { + dstp = &pDstData[(y * nDstStep) + nChannel]; for (x = 0; x < nWidth; x++) { @@ -178,6 +207,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS { int status; BYTE* srcp; + BOOL vFlip; BYTE FormatHeader; BYTE* pDstData = NULL; UINT32 UncompressedSize; @@ -185,6 +215,8 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS if ((nWidth * nHeight) <= 0) return -1; + vFlip = FREERDP_PIXEL_FORMAT_FLIP(DstFormat) ? TRUE : FALSE; + srcp = pSrcData; UncompressedSize = nWidth * nHeight * 4; @@ -210,7 +242,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) { status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), - pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3, vFlip); if (status < 0) return -1; @@ -220,7 +252,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS else { status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), - pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3, vFlip); if (status < 0) return -1; @@ -234,7 +266,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* LumaOrRedPlane */ status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), - pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip); if (status < 0) return -1; @@ -244,7 +276,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* OrangeChromaOrGreenPlane */ status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), - pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip); if (status < 0) return -1; @@ -254,7 +286,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* GreenChromeOrBluePlane */ status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), - pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip); if (status < 0) return -1; @@ -266,7 +298,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* LumaOrRedPlane */ status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), - pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip); if (status < 0) return -1; @@ -276,7 +308,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* OrangeChromaOrGreenPlane */ status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), - pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip); if (status < 0) return -1; @@ -286,7 +318,7 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS /* GreenChromeOrBluePlane */ status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), - pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0); + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip); if (status < 0) return -1; From 160a3c4b61fe1d552cb8052b14e2f04056b293b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 19 Jun 2014 13:55:34 -0400 Subject: [PATCH 46/50] libfreerdp-codec: avoid intermediate copy with planar egfx --- client/X11/xf_gfx.c | 9 +++------ libfreerdp/codec/planar.c | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index c4336a6fd..e22884bd6 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -303,13 +303,10 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF if (!surface) return -1; + DstData = surface->data; + status = planar_decompress(NULL, cmd->data, cmd->length, &DstData, - PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0, cmd->width, cmd->height); - - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, - cmd->width, cmd->height, DstData, PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0); - - free(DstData); + PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height); invalidRect.left = cmd->left; invalidRect.top = cmd->top; diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index 15ac70f9f..824376ffb 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -62,7 +62,7 @@ static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs for (y = beg; y != end; y += inc) { - dstp = &pDstData[(y * nDstStep) + nChannel]; + dstp = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4) + nChannel]; pixel = 0; currentScanline = dstp; @@ -189,7 +189,7 @@ static int planar_decompress_plane_raw(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs for (y = beg; y != end; y += inc) { - dstp = &pDstData[(y * nDstStep) + nChannel]; + dstp = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4) + nChannel]; for (x = 0; x < nWidth; x++) { From ce6ff3529755a8fbcc309644d3e6869891792e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 19 Jun 2014 17:08:50 -0400 Subject: [PATCH 47/50] xfreerdp: fix egfx off-by-one errors --- channels/drdynvc/client/drdynvc_main.c | 6 +++ client/X11/xf_gfx.c | 42 +++++++++++++------- client/X11/xf_gfx.h | 1 - winpr/libwinpr/utils/collections/HashTable.c | 4 +- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 2daa99782..05146f044 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -417,8 +417,14 @@ static void drdynvc_process_terminate(rdpSvcPlugin* plugin) DEBUG_DVC("terminating"); + if (!drdynvc) + return; + if (drdynvc->channel_mgr) + { dvcman_free(drdynvc->channel_mgr); + drdynvc->channel_mgr = NULL; + } svc_plugin_terminate(plugin); diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index e22884bd6..35288c515 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -80,8 +80,8 @@ int xf_OutputUpdate(xfContext* xfc) surfaceRect.left = 0; surfaceRect.top = 0; - surfaceRect.right = xfc->width - 1; - surfaceRect.bottom = xfc->height - 1; + surfaceRect.right = xfc->width; + surfaceRect.bottom = xfc->height; region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect); @@ -93,8 +93,8 @@ int xf_OutputUpdate(xfContext* xfc) { extents = region16_extents(&(xfc->invalidRegion)); - width = extents->right - extents->left + 1; - height = extents->bottom - extents->top + 1; + width = extents->right - extents->left; + height = extents->bottom - extents->top; if (width > xfc->width) width = xfc->width; @@ -121,8 +121,8 @@ int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height) invalidRect.left = x; invalidRect.top = y; - invalidRect.right = x + width - 1; - invalidRect.bottom = y + height - 1; + invalidRect.right = x + width; + invalidRect.bottom = y + height; region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); @@ -212,8 +212,8 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP clippingRect.left = cmd->left + rect->x; clippingRect.top = cmd->top + rect->y; - clippingRect.right = clippingRect.left + rect->width - 1; - clippingRect.bottom = clippingRect.top + rect->height - 1; + clippingRect.right = clippingRect.left + rect->width; + clippingRect.bottom = clippingRect.top + rect->height; region16_union_rect(&clippingRects, &clippingRects, &clippingRect); } @@ -224,8 +224,8 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP updateRect.left = cmd->left + tile->x; updateRect.top = cmd->top + tile->y; - updateRect.right = updateRect.left + 64 - 1; - updateRect.bottom = updateRect.top + 64 - 1; + updateRect.right = updateRect.left + 64; + updateRect.bottom = updateRect.top + 64; region16_init(&updateRegion); region16_intersect_rect(&updateRegion, &clippingRects, &updateRect); @@ -235,8 +235,8 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP { nXDst = updateRects[j].left; nYDst = updateRects[j].top; - nWidth = updateRects[j].right - updateRects[j].left + 1; - nHeight = updateRects[j].bottom - updateRects[j].top + 1; + nWidth = updateRects[j].right - updateRects[j].left; + nHeight = updateRects[j].bottom - updateRects[j].top; freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, nXDst, nYDst, nWidth, nHeight, @@ -389,14 +389,14 @@ int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* cr surface->height = (UINT32) createSurface->height; surface->alpha = (createSurface->pixelFormat == PIXEL_FORMAT_ARGB_8888) ? TRUE : FALSE; - surface->scanline = surface->width * 4; + surface->scanline = (surface->width + (surface->width % 4)) * 4; surface->data = (BYTE*) calloc(1, surface->scanline * surface->height); if (!surface->data) return -1; surface->image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, - (char*) surface->data, surface->width, surface->height, 32, 0); + (char*) surface->data, surface->width, surface->height, 32, surface->scanline); context->SetSurfaceData(context, surface->surfaceId, (void*) surface); @@ -546,7 +546,7 @@ int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* cacheEntry->height = (UINT32) (rect->bottom - rect->top); cacheEntry->alpha = surface->alpha; - cacheEntry->scanline = cacheEntry->width * 4; + cacheEntry->scanline = (cacheEntry->width + (cacheEntry->width % 4)) * 4; cacheEntry->data = (BYTE*) calloc(1, surface->scanline * surface->height); if (!cacheEntry->data) @@ -608,8 +608,20 @@ int xf_CacheImportReply(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY_ int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry) { + xfGfxCacheEntry* cacheEntry; + printf("xf_EvictCacheEntry\n"); + cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, evictCacheEntry->cacheSlot); + + if (cacheEntry) + { + free(cacheEntry->data); + free(cacheEntry); + } + + context->SetCacheSlotData(context, evictCacheEntry->cacheSlot, NULL); + return 1; } diff --git a/client/X11/xf_gfx.h b/client/X11/xf_gfx.h index 6451d258c..3a95d33e0 100644 --- a/client/X11/xf_gfx.h +++ b/client/X11/xf_gfx.h @@ -42,7 +42,6 @@ struct xf_gfx_cache_entry UINT32 height; BOOL alpha; BYTE* data; - XImage* image; int scanline; }; typedef struct xf_gfx_cache_entry xfGfxCacheEntry; diff --git a/winpr/libwinpr/utils/collections/HashTable.c b/winpr/libwinpr/utils/collections/HashTable.c index 15ae5175e..fd75143c9 100644 --- a/winpr/libwinpr/utils/collections/HashTable.c +++ b/winpr/libwinpr/utils/collections/HashTable.c @@ -479,7 +479,7 @@ wHashTable* HashTable_New(BOOL synchronized) if (table) { table->synchronized = synchronized; - InitializeCriticalSectionAndSpinCount(&table->lock, 4000); + InitializeCriticalSectionAndSpinCount(&(table->lock), 4000); table->numOfBuckets = 64; table->numOfElements = 0; @@ -537,6 +537,8 @@ void HashTable_Free(wHashTable* table) } } + DeleteCriticalSection(&(table->lock)); + free(table->bucketArray); free(table); } From cd65a0d6b8a515509839015936f2e11c23e30400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 20 Jun 2014 12:35:21 -0400 Subject: [PATCH 48/50] libfreerdp-codec: cleanup and fix insufficient rectangle array size in region16_union_rect --- libfreerdp/codec/region.c | 125 +++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 43 deletions(-) diff --git a/libfreerdp/codec/region.c b/libfreerdp/codec/region.c index aee2e3036..b8a24e136 100644 --- a/libfreerdp/codec/region.c +++ b/libfreerdp/codec/region.c @@ -107,13 +107,14 @@ const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRects) static INLINE RECTANGLE_16 *region16_rects_noconst(REGION16 *region) { - REGION16_DATA *data; + REGION16_DATA* data; data = region->data; - if (!data) - return 0; - return (RECTANGLE_16 *)(data + 1); + if (!data) + return NULL; + + return (RECTANGLE_16*)(&data[1]); } const RECTANGLE_16 *region16_extents(const REGION16 *region) @@ -158,20 +159,24 @@ void region16_clear(REGION16 *region) if (region->data->size) free(region->data); + region->data = &empty_region; ZeroMemory(®ion->extents, sizeof(region->extents)); } -static INLINE REGION16_DATA *allocateRegion(long nbItems) +static INLINE REGION16_DATA* allocateRegion(long nbItems) { - long allocSize = sizeof(REGION16_DATA) + nbItems * sizeof(RECTANGLE_16); - REGION16_DATA *ret = (REGION16_DATA *)malloc(allocSize); + long allocSize = sizeof(REGION16_DATA) + (nbItems * sizeof(RECTANGLE_16)); + + REGION16_DATA* ret = (REGION16_DATA*) malloc(allocSize); + if (!ret) return ret; ret->size = allocSize; ret->nbRects = nbItems; + return ret; } @@ -186,6 +191,7 @@ BOOL region16_copy(REGION16 *dst, const REGION16 *src) return TRUE; dst->extents = src->extents; + if (dst->data->size) free(dst->data); @@ -196,11 +202,13 @@ BOOL region16_copy(REGION16 *dst, const REGION16 *src) else { dst->data = allocateRegion(src->data->nbRects); + if (!dst->data) return FALSE; - memcpy(dst->data, src->data, src->data->size); + CopyMemory(dst->data, src->data, src->data->size); } + return TRUE; } @@ -310,29 +318,34 @@ void region16_copy_band_with_union(RECTANGLE_16 *dst, src++; dst++; *dstCounter += 1; } - if(srcPtr) + if (srcPtr) *srcPtr = src; + *dstPtr = dst; } -static RECTANGLE_16 *next_band(RECTANGLE_16 *band1, RECTANGLE_16 *endPtr, int *nbItems) +static RECTANGLE_16* next_band(RECTANGLE_16* band1, RECTANGLE_16* endPtr, int* nbItems) { UINT16 refY = band1->top; *nbItems = 0; - while((band1 < endPtr) && (band1->top == refY)) { + + while((band1 < endPtr) && (band1->top == refY)) + { band1++; *nbItems += 1; } + return band1; } -static BOOL band_match(const RECTANGLE_16 *band1, const RECTANGLE_16 *band2, RECTANGLE_16 *endPtr) +static BOOL band_match(const RECTANGLE_16* band1, const RECTANGLE_16* band2, RECTANGLE_16* endPtr) { int refBand2 = band2->top; - const RECTANGLE_16 *band2Start = band2; + const RECTANGLE_16* band2Start = band2; - while ((band1 < band2Start) && (band2 < endPtr) && (band2->top == refBand2)) { + while ((band1 < band2Start) && (band2 < endPtr) && (band2->top == refBand2)) + { if ((band1->left != band2->left) || (band1->right != band2->right)) return FALSE; @@ -391,14 +404,17 @@ BOOL region16_simplify_bands(REGION16 *region) int bandItems, toMove; finalNbRects = nbRects = region16_n_rects(region); + if (nbRects < 2) return TRUE; band1 = region16_rects_noconst(region); endPtr = band1 + nbRects; - do { + do + { band2 = next_band(band1, endPtr, &bandItems); + if (band2 == endPtr) break; @@ -416,38 +432,45 @@ BOOL region16_simplify_bands(REGION16 *region) * may be merged too */ endBand = band2 + bandItems; toMove = (endPtr - endBand) * sizeof(RECTANGLE_16); + if (toMove) - memmove(band2, endBand, toMove); + MoveMemory(band2, endBand, toMove); + finalNbRects -= bandItems; endPtr -= bandItems; - } else { + } + else + { band1 = band2; } - } while(TRUE); + } + while(TRUE); if (finalNbRects != nbRects) { - int allocSize = sizeof(REGION16_DATA) + finalNbRects * sizeof(RECTANGLE_16); + int allocSize = sizeof(REGION16_DATA) + (finalNbRects * sizeof(RECTANGLE_16)); region->data = realloc(region->data, allocSize); + if (!region->data) { region->data = &empty_region; return FALSE; } + region->data->nbRects = finalNbRects; region->data->size = allocSize; } + return TRUE; } - BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 *rect) { - const RECTANGLE_16 *srcExtents; - RECTANGLE_16 *dstExtents; + const RECTANGLE_16* srcExtents; + RECTANGLE_16* dstExtents; const RECTANGLE_16 *currentBand, *endSrcRect, *nextBand; - REGION16_DATA *newItems; - RECTANGLE_16 *dstRect; + REGION16_DATA* newItems = NULL; + RECTANGLE_16* dstRect = NULL; int usedRects, srcNbRects; UINT16 topInterBand; @@ -463,19 +486,26 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 /* source is empty, so the union is rect */ dst->extents = *rect; dst->data = allocateRegion(1); + if (!dst->data) return FALSE; dstRect = region16_rects_noconst(dst); - *dstRect = *rect; + + dstRect->top = rect->top; + dstRect->left = rect->left; + dstRect->right = rect->right; + dstRect->bottom = rect->bottom; + return TRUE; } - newItems = allocateRegion((1 + region16_n_rects(src)) * 2); + newItems = allocateRegion((1 + region16_n_rects(src)) * 4); + if (!newItems) return FALSE; - dstRect = (RECTANGLE_16 *)(newItems + 1); + dstRect = (RECTANGLE_16*) (&newItems[1]); usedRects = 0; /* adds the piece of rect that is on the top of src */ @@ -497,8 +527,7 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 while (currentBand < endSrcRect) { if ((currentBand->bottom <= rect->top) || (rect->bottom <= currentBand->top) || - rectangle_contained_in_band(currentBand, endSrcRect, rect) - ) + rectangle_contained_in_band(currentBand, endSrcRect, rect)) { /* no overlap between rect and the band, rect is totally below or totally above * the current band, or rect is already covered by an item of the band. @@ -560,9 +589,10 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 mergeTop = rect->top; } - /* do the merge zone (all cases ) */ + /* do the merge zone (all cases) */ if (rect->bottom < currentBand->bottom) mergeBottom = rect->bottom; + region16_copy_band_with_union(dstRect, currentBand, endSrcRect, mergeTop, mergeBottom, @@ -629,19 +659,20 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 dstExtents->bottom = MAX(rect->bottom, srcExtents->bottom); dstExtents->right = MAX(rect->right, srcExtents->right); - newItems->size = sizeof(REGION16_DATA) + usedRects * sizeof(RECTANGLE_16); + newItems->size = sizeof(REGION16_DATA) + (usedRects * sizeof(RECTANGLE_16)); dst->data = realloc(newItems, newItems->size); + if (!dst->data) { free(newItems); return FALSE; } + dst->data->nbRects = usedRects; return region16_simplify_bands(dst); } - BOOL region16_intersects_rect(const REGION16 *src, const RECTANGLE_16 *arg2) { const RECTANGLE_16 *rect, *endPtr, *srcExtents; @@ -651,10 +682,12 @@ BOOL region16_intersects_rect(const REGION16 *src, const RECTANGLE_16 *arg2) assert(src->data); rect = region16_rects(src, &nbRects); + if (!nbRects) return FALSE; srcExtents = region16_extents(src); + if (nbRects == 1) return rectangles_intersects(srcExtents, arg2); @@ -684,6 +717,7 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE assert(src->data); srcPtr = region16_rects(src, &nbRects); + if (!nbRects) { region16_clear(dst); @@ -691,27 +725,32 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE } srcExtents = region16_extents(src); + if (nbRects == 1) { BOOL intersects = rectangles_intersection(srcExtents, rect, &common); region16_clear(dst); + if (intersects) return region16_union_rect(dst, dst, &common); + return TRUE; } newItems = allocateRegion(nbRects); + if (!newItems) return FALSE; - dstPtr = (RECTANGLE_16 *)(newItems + 1); + + dstPtr = (RECTANGLE_16*) (&newItems[1]); usedRects = 0; ZeroMemory(&newExtents, sizeof(newExtents)); /* accumulate intersecting rectangles, the final region16_simplify_bands() will * do all the bad job to recreate correct rectangles */ - for(endPtr = srcPtr + nbRects; (srcPtr < endPtr) && (rect->bottom > srcPtr->top); srcPtr++) + for (endPtr = srcPtr + nbRects; (srcPtr < endPtr) && (rect->bottom > srcPtr->top); srcPtr++) { if (rectangles_intersection(srcPtr, rect, &common)) { @@ -727,13 +766,15 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE } newItems->nbRects = usedRects; - newItems->size = sizeof(REGION16_DATA) + usedRects * sizeof(RECTANGLE_16); + newItems->size = sizeof(REGION16_DATA) + (usedRects * sizeof(RECTANGLE_16)); if (dst->data->size) free(dst->data); dst->data = realloc(newItems, newItems->size); - if (!dst->data) { + + if (!dst->data) + { free(newItems); return FALSE; } @@ -742,15 +783,13 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE return region16_simplify_bands(dst); } -void region16_uninit(REGION16 *region) { +void region16_uninit(REGION16 *region) +{ assert(region); assert(region->data); - if(region->data->size) + if (region->data->size) free(region->data); - region->data = 0; + + region->data = NULL; } - - - - From 78d3c82798572ab939c34f89e47c478d97f6564e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 20 Jun 2014 13:52:13 -0400 Subject: [PATCH 49/50] xfreerdp: fix multiple egfx-related memory leaks --- channels/drdynvc/client/dvcman.c | 8 +-- channels/rdpgfx/client/rdpgfx_main.c | 41 +++++++++++++++ client/X11/xf_channels.c | 11 +++- client/X11/xf_gfx.c | 12 ++++- client/X11/xf_gfx.h | 3 +- client/X11/xf_window.c | 22 +++++--- libfreerdp/common/settings.c | 11 ++-- libfreerdp/utils/svc_plugin.c | 27 +++++++--- winpr/include/winpr/collections.h | 7 +++ winpr/libwinpr/utils/collections/HashTable.c | 51 +++++++++++++++++++ .../utils/collections/ListDictionary.c | 3 +- 11 files changed, 170 insertions(+), 26 deletions(-) diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c index a831bf6eb..bd3718a60 100644 --- a/channels/drdynvc/client/dvcman.c +++ b/channels/drdynvc/client/dvcman.c @@ -475,7 +475,7 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UI int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data) { - int error = 0; + int status = 0; DVCMAN_CHANNEL* channel; UINT32 dataSize = Stream_GetRemainingLength(data); @@ -504,16 +504,16 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 C { Stream_SealLength(channel->dvc_data); Stream_SetPosition(channel->dvc_data, 0); - error = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data); + status = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; } } else { - error = channel->channel_callback->OnDataReceived(channel->channel_callback, data); + status = channel->channel_callback->OnDataReceived(channel->channel_callback, data); } - return error; + return status; } diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 0bb29bb8c..032b51b81 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -210,6 +210,8 @@ int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s context->ResetGraphics(context, &pdu); } + free(pdu.monitorDefArray); + return 1; } @@ -595,6 +597,8 @@ int rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* context->CacheToSurface(context, &pdu); } + free(pdu.destPts); + return 1; } @@ -850,7 +854,11 @@ static int rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin) { + int count; + int index; + ULONG_PTR* pKeys = NULL; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) pPlugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; WLog_Print(gfx->log, WLOG_DEBUG, "Terminated"); @@ -859,8 +867,41 @@ static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin) zgfx_context_free(gfx->zgfx); + count = HashTable_GetKeys(gfx->SurfaceTable, &pKeys); + + for (index = 0; index < count; index++) + { + RDPGFX_DELETE_SURFACE_PDU pdu; + + pdu.surfaceId = ((UINT16) pKeys[index]) - 1; + + if (context && context->DeleteSurface) + { + context->DeleteSurface(context, &pdu); + } + } + + free(pKeys); + HashTable_Free(gfx->SurfaceTable); + for (index = 0; index < gfx->MaxCacheSlot; index++) + { + if (gfx->CacheSlots[index]) + { + RDPGFX_EVICT_CACHE_ENTRY_PDU pdu; + + pdu.cacheSlot = (UINT16) index; + + if (context && context->EvictCacheEntry) + { + context->EvictCacheEntry(context, &pdu); + } + + gfx->CacheSlots[index] = NULL; + } + } + free(gfx); return 0; diff --git a/client/X11/xf_channels.c b/client/X11/xf_channels.c index b00130c24..9bb36152e 100644 --- a/client/X11/xf_channels.c +++ b/client/X11/xf_channels.c @@ -38,11 +38,20 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven } else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) { - xf_register_graphics_pipeline(xfc, (RdpgfxClientContext*) e->pInterface); + xf_graphics_pipeline_init(xfc, (RdpgfxClientContext*) e->pInterface); } } void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e) { + xfContext* xfc = (xfContext*) context; + if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) + { + xfc->rdpei = NULL; + } + else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) + { + xf_graphics_pipeline_uninit(xfc, (RdpgfxClientContext*) e->pInterface); + } } diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 35288c515..fec5036b8 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -610,7 +610,7 @@ int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PD { xfGfxCacheEntry* cacheEntry; - printf("xf_EvictCacheEntry\n"); + //printf("xf_EvictCacheEntry\n"); cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, evictCacheEntry->cacheSlot); @@ -639,7 +639,7 @@ int xf_MapSurfaceToWindow(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WI return 1; } -void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx) +void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx) { xfc->gfx = gfx; gfx->custom = (void*) xfc; @@ -662,3 +662,11 @@ void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx) region16_init(&(xfc->invalidRegion)); } + +void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx) +{ + region16_uninit(&(xfc->invalidRegion)); + + gfx->custom = NULL; + xfc->gfx = NULL; +} diff --git a/client/X11/xf_gfx.h b/client/X11/xf_gfx.h index 3a95d33e0..ba937ee92 100644 --- a/client/X11/xf_gfx.h +++ b/client/X11/xf_gfx.h @@ -48,6 +48,7 @@ typedef struct xf_gfx_cache_entry xfGfxCacheEntry; int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height); -void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx); +void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx); +void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx); #endif /* __XF_GRAPHICS_PIPELINE_H */ diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index ba42368da..682c0cfca 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -822,25 +822,33 @@ BOOL xf_IsWindowBorder(xfContext *xfc, xfWindow *xfw, int x, int y) void xf_DestroyWindow(xfContext *xfc, xfWindow *window) { - if(window == NULL) + if (!window) return; - if(xfc->window == window) + + if (xfc->window == window) xfc->window = NULL; - if(window->gc) + + if (window->gc) XFreeGC(xfc->display, window->gc); - if(window->handle) + + if (window->handle) { XUnmapWindow(xfc->display, window->handle); XDestroyWindow(xfc->display, window->handle); } - free(window); - if(window->xfwin) + + if (window->xfwin) munmap(0, sizeof(*window->xfwin)); - if(window->shmid >= 0) + + if (window->shmid >= 0) close(window->shmid); + shm_unlink(get_shm_id()); + window->xfwin = -1; window->shmid = -1; + + free(window); } rdpWindow *xf_rdpWindowFromWindow(xfContext *xfc, Window wnd) diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index 8f1455b81..e04230f37 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -517,11 +517,16 @@ out_free: void freerdp_dynamic_channel_collection_free(rdpSettings* settings) { - UINT32 index; + int j; + UINT32 i; - for (index = 0; index < settings->DynamicChannelCount; index++) + for (i = 0; i < settings->DynamicChannelCount; i++) { - free(settings->DynamicChannelArray[index]); + for (j = 0; j < settings->DynamicChannelArray[i]->argc; j++) + free(settings->DynamicChannelArray[i]->argv[j]); + + free(settings->DynamicChannelArray[i]->argv); + free(settings->DynamicChannelArray[i]); } free(settings->DynamicChannelArray); diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index b5787438a..7a529d256 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -179,6 +179,7 @@ static void* svc_plugin_thread_func(void* arg) IFCALL(plugin->connect_callback, plugin); SetEvent(plugin->started); + while (1) { if (!MessageQueue_Wait(plugin->MsgPipe->In)) @@ -238,7 +239,12 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin) MessagePipe_Free(plugin->MsgPipe); CloseHandle(plugin->thread); - CloseHandle(plugin->started); + + if (plugin->started) + { + CloseHandle(plugin->started); + plugin->started = NULL; + } plugin->channel_entry_points.pVirtualChannelClose(plugin->OpenHandle); @@ -248,10 +254,10 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin) plugin->data_in = NULL; } - IFCALL(plugin->terminate_callback, plugin); - svc_plugin_remove_open_handle_data(plugin->OpenHandle); svc_plugin_remove_init_handle_data(plugin->InitHandle); + + IFCALL(plugin->terminate_callback, plugin); } static VOID VCAPITYPE svc_plugin_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) @@ -297,7 +303,7 @@ void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints) plugin->channel_entry_points.pInterface = *(plugin->channel_entry_points.ppInterface); plugin->channel_entry_points.ppInterface = &(plugin->channel_entry_points.pInterface); - plugin->started = CreateEvent(NULL,TRUE,FALSE,NULL); + plugin->started = CreateEvent(NULL, TRUE, FALSE, NULL); plugin->pool = StreamPool_New(TRUE, 10); svc_plugin_add_init_handle_data(plugin->InitHandle, plugin); @@ -305,8 +311,17 @@ void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints) void svc_plugin_terminate(rdpSvcPlugin* plugin) { - StreamPool_Free(plugin->pool); - CloseHandle(plugin->started); + if (plugin->pool) + { + StreamPool_Free(plugin->pool); + plugin->pool = NULL; + } + + if (plugin->started) + { + CloseHandle(plugin->started); + plugin->started = NULL; + } } int svc_plugin_send(rdpSvcPlugin* plugin, wStream* data_out) diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index b1b945b9a..f56a556d8 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -326,6 +326,8 @@ WINPR_API void CountdownEvent_Free(wCountdownEvent* countdown); /* Hash Table */ +typedef void (*KEY_VALUE_FREE_FN)(void* context, void* key, void* value); + struct _wHashTable { BOOL synchronized; @@ -342,6 +344,9 @@ struct _wHashTable unsigned long (*hashFunction)(void* key); void (*keyDeallocator)(void* key); void (*valueDeallocator)(void* value); + + void* context; + KEY_VALUE_FREE_FN pfnKeyValueFree; }; typedef struct _wHashTable wHashTable; @@ -354,6 +359,8 @@ WINPR_API BOOL HashTable_ContainsKey(wHashTable* table, void* key); WINPR_API BOOL HashTable_ContainsValue(wHashTable* table, void* value); WINPR_API void* HashTable_GetItemValue(wHashTable* table, void* key); WINPR_API BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value); +WINPR_API void HashTable_SetFreeFunction(wHashTable* table, void* context, KEY_VALUE_FREE_FN pfnKeyValueFree); +WINPR_API int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys); WINPR_API wHashTable* HashTable_New(BOOL synchronized); WINPR_API void HashTable_Free(wHashTable* table); diff --git a/winpr/libwinpr/utils/collections/HashTable.c b/winpr/libwinpr/utils/collections/HashTable.c index fd75143c9..fcbe4aa3d 100644 --- a/winpr/libwinpr/utils/collections/HashTable.c +++ b/winpr/libwinpr/utils/collections/HashTable.c @@ -368,6 +368,9 @@ void HashTable_Clear(wHashTable* table) { nextPair = pair->next; + if (table->pfnKeyValueFree) + table->pfnKeyValueFree(table->context, pair->key, pair->value); + if (table->keyDeallocator) table->keyDeallocator((void*) pair->key); @@ -389,6 +392,48 @@ void HashTable_Clear(wHashTable* table) LeaveCriticalSection(&table->lock); } +/** + * Gets the list of keys as an array + */ + +int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys) +{ + int iKey; + int count; + int index; + ULONG_PTR* pKeys; + wKeyValuePair* pair; + wKeyValuePair* nextPair; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + iKey = 0; + count = table->numOfElements; + pKeys = (ULONG_PTR*) calloc(count, sizeof(ULONG_PTR)); + + for (index = 0; index < table->numOfBuckets; index++) + { + pair = table->bucketArray[index]; + + while (pair) + { + nextPair = pair->next; + + pKeys[iKey++] = (ULONG_PTR) pair->key; + + pair = nextPair; + } + } + + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + *ppKeys = pKeys; + + return count; +} + /** * Determines whether the HashTable contains a specific key. */ @@ -465,6 +510,12 @@ BOOL HashTable_ContainsValue(wHashTable* table, void* value) return status; } +void HashTable_SetFreeFunction(wHashTable* table, void* context, KEY_VALUE_FREE_FN pfnKeyValueFree) +{ + table->context = context; + table->pfnKeyValueFree = pfnKeyValueFree; +} + /** * Construction, Destruction */ diff --git a/winpr/libwinpr/utils/collections/ListDictionary.c b/winpr/libwinpr/utils/collections/ListDictionary.c index ca65d8a08..918bee44c 100644 --- a/winpr/libwinpr/utils/collections/ListDictionary.c +++ b/winpr/libwinpr/utils/collections/ListDictionary.c @@ -144,8 +144,7 @@ int ListDictionary_GetKeys(wListDictionary* listDictionary, ULONG_PTR** ppKeys) } } - pKeys = (ULONG_PTR*) malloc(sizeof(ULONG_PTR) * count); - ZeroMemory(pKeys, sizeof(ULONG_PTR) * count); + pKeys = (ULONG_PTR*) calloc(count, sizeof(ULONG_PTR)); index = 0; From 95a0d96b5821e0c1e92526078eed967f12293258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 23 Jun 2014 12:08:34 -0400 Subject: [PATCH 50/50] xfreerdp: fix build warnings --- client/X11/generate_argument_docbook.c | 6 +-- client/X11/xf_window.c | 57 +++++++++++++++++--------- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/client/X11/generate_argument_docbook.c b/client/X11/generate_argument_docbook.c index aaab2239c..4b49f34da 100644 --- a/client/X11/generate_argument_docbook.c +++ b/client/X11/generate_argument_docbook.c @@ -154,9 +154,9 @@ int main(int argc, char *argv[]) fprintf(fp, "\t\t\t\t\t%s\n", format); fprintf(fp, "\t\t\t\t\n"); fprintf(fp, "\t\t\t\n"); - free(name); - free(format); - free(text); + free((void*) name); + free((void*) format); + free((void*) text); } fprintf(fp, "\t\t\n"); fprintf(fp, "\t\n"); diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index 682c0cfca..7df1f8768 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -299,15 +299,16 @@ static const char *get_shm_id() return shm_id; } -xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int height, BOOL decorations) +xfWindow* xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int height, BOOL decorations) { - xfWindow *window; + xfWindow* window; XEvent xevent; - rdpSettings *settings; - window = (xfWindow *) malloc(sizeof(xfWindow)); - ZeroMemory(window, sizeof(xfWindow)); + rdpSettings* settings; + window = (xfWindow*) calloc(1, sizeof(xfWindow)); + settings = xfc->instance->settings; - if(window) + + if (window) { int input_mask; XClassHint *class_hints; @@ -322,48 +323,65 @@ xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int heig xfc->workArea.x, xfc->workArea.y, xfc->workArea.width, xfc->workArea.height, 0, xfc->depth, InputOutput, xfc->visual, CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap | CWBorderPixel | CWWinGravity | CWBitGravity, &xfc->attribs); + window->shmid = shm_open(get_shm_id(), O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE); - if(window->shmid < 0) + + if (window->shmid < 0) { DEBUG_X11("xf_CreateDesktopWindow: failed to get access to shared memory - shmget()\n"); } else { + void* mem; + ftruncate(window->shmid, sizeof(window->handle)); - window->xfwin = mmap(0, sizeof(window->handle), PROT_READ | PROT_WRITE, MAP_SHARED, window->shmid, 0); - if(window->xfwin == (int *) -1) + + mem = mmap(0, sizeof(window->handle), PROT_READ | PROT_WRITE, MAP_SHARED, window->shmid, 0); + + if (mem == ((int*) -1)) { DEBUG_X11("xf_CreateDesktopWindow: failed to assign pointer to the memory address - shmat()\n"); } else { + window->xfwin = mem; *window->xfwin = window->handle; } } + class_hints = XAllocClassHint(); - if(class_hints) + + if (class_hints) { class_hints->res_name = "xfreerdp"; - if(xfc->instance->settings->WmClass) + + if (xfc->instance->settings->WmClass) class_hints->res_class = xfc->instance->settings->WmClass; else class_hints->res_class = "xfreerdp"; + XSetClassHint(xfc->display, window->handle, class_hints); XFree(class_hints); } + xf_ResizeDesktopWindow(xfc, window, width, height); xf_SetWindowDecorations(xfc, window, decorations); xf_SetWindowPID(xfc, window, 0); + input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | VisibilityChangeMask | FocusChangeMask | StructureNotifyMask | PointerMotionMask | ExposureMask | PropertyChangeMask; - if(xfc->grab_keyboard) + + if (xfc->grab_keyboard) input_mask |= EnterWindowMask | LeaveWindowMask; + XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, (BYTE *) xf_icon_prop, ARRAYSIZE(xf_icon_prop)); - if(xfc->settings->ParentWindowId) + + if (xfc->settings->ParentWindowId) XReparentWindow(xfc->display, window->handle, (Window) xfc->settings->ParentWindowId, 0, 0); + XSelectInput(xfc->display, window->handle, input_mask); XClearWindow(xfc->display, window->handle); XMapWindow(xfc->display, window->handle); @@ -382,15 +400,14 @@ xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int heig * monitor instead of the upper-left monitor for remote app mode(which uses all monitors). * This extra call after the window is mapped will position the login window correctly */ - if(xfc->instance->settings->RemoteApplicationMode) + if (xfc->instance->settings->RemoteApplicationMode) { XMoveWindow(xfc->display, window->handle, 0, 0); } - else - if(settings->DesktopPosX || settings->DesktopPosY) - { - XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY); - } + else if(settings->DesktopPosX || settings->DesktopPosY) + { + XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY); + } } xf_SetWindowText(xfc, window, name); return window; @@ -845,7 +862,7 @@ void xf_DestroyWindow(xfContext *xfc, xfWindow *window) shm_unlink(get_shm_id()); - window->xfwin = -1; + window->xfwin = (Window*) -1; window->shmid = -1; free(window);