21 #include <freerdp/config.h>
23 #include <winpr/crt.h>
24 #include <winpr/assert.h>
25 #include <winpr/cast.h>
26 #include <winpr/file.h>
27 #include <winpr/path.h>
28 #include <winpr/synch.h>
29 #include <winpr/thread.h>
30 #include <winpr/sysinfo.h>
31 #include <winpr/interlocked.h>
33 #include <freerdp/log.h>
34 #include <freerdp/channels/drdynvc.h>
38 #define TAG CLIENT_TAG("shadow")
43 BOOL gfxSurfaceCreated;
53 #define BitmapUpdateProxy(update, context, bitmap) \
54 BitmapUpdateProxyEx((update), (context), (bitmap), __FILE__, __LINE__, __func__)
55 static BOOL BitmapUpdateProxyEx(rdpUpdate* update, rdpContext* context,
const BITMAP_UPDATE* bitmap,
56 const char* file,
size_t line,
const char* fkt)
59 WINPR_ASSERT(context);
62 for (UINT32 x = 0; x < bitmap->number; x++)
68 cur.skipCompression = bitmap->skipCompression;
69 const BOOL rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, &cur);
72 const DWORD log_level = WLOG_ERROR;
73 wLog* log = WLog_Get(TAG);
74 if (WLog_IsLevelActive(log, log_level))
76 WLog_PrintMessage(log, WLOG_MESSAGE_TEXT, log_level, line, file, fkt,
77 "BitmapUpdate[%" PRIu32
"] failed", x);
86 static INLINE BOOL shadow_client_rdpgfx_new_surface(rdpShadowClient* client)
88 UINT error = CHANNEL_RC_OK;
91 RdpgfxServerContext* context = NULL;
92 rdpSettings* settings = NULL;
95 context = client->rdpgfx;
96 WINPR_ASSERT(context);
97 settings = ((rdpContext*)client)->settings;
98 WINPR_ASSERT(settings);
104 createSurface.pixelFormat = GFX_PIXEL_FORMAT_XRGB_8888;
105 createSurface.surfaceId = client->surfaceId;
106 surfaceToOutput.outputOriginX = 0;
107 surfaceToOutput.outputOriginY = 0;
108 surfaceToOutput.surfaceId = client->surfaceId;
109 surfaceToOutput.reserved = 0;
110 IFCALLRET(context->CreateSurface, error, context, &createSurface);
114 WLog_ERR(TAG,
"CreateSurface failed with error %" PRIu32
"", error);
118 IFCALLRET(context->MapSurfaceToOutput, error, context, &surfaceToOutput);
122 WLog_ERR(TAG,
"MapSurfaceToOutput failed with error %" PRIu32
"", error);
129 static INLINE BOOL shadow_client_rdpgfx_release_surface(rdpShadowClient* client)
131 UINT error = CHANNEL_RC_OK;
133 RdpgfxServerContext* context = NULL;
135 WINPR_ASSERT(client);
137 context = client->rdpgfx;
138 WINPR_ASSERT(context);
140 pdu.surfaceId = client->surfaceId++;
141 IFCALLRET(context->DeleteSurface, error, context, &pdu);
145 WLog_ERR(TAG,
"DeleteSurface failed with error %" PRIu32
"", error);
152 static INLINE BOOL shadow_client_rdpgfx_reset_graphic(rdpShadowClient* client)
154 UINT error = CHANNEL_RC_OK;
156 RdpgfxServerContext* context = NULL;
157 rdpSettings* settings = NULL;
159 WINPR_ASSERT(client);
160 WINPR_ASSERT(client->rdpgfx);
162 context = client->rdpgfx;
163 WINPR_ASSERT(context);
165 settings = client->context.settings;
166 WINPR_ASSERT(settings);
170 pdu.monitorCount = client->subsystem->numMonitors;
171 pdu.monitorDefArray = client->subsystem->monitors;
172 IFCALLRET(context->ResetGraphics, error, context, &pdu);
176 WLog_ERR(TAG,
"ResetGraphics failed with error %" PRIu32
"", error);
180 client->first_frame = TRUE;
184 static INLINE
void shadow_client_free_queued_message(
void* obj)
186 wMessage* message = (wMessage*)obj;
188 WINPR_ASSERT(message);
191 message->Free(message);
192 message->Free = NULL;
196 static void shadow_client_context_free(freerdp_peer* peer, rdpContext* context)
198 rdpShadowClient* client = (rdpShadowClient*)context;
199 rdpShadowServer* server = NULL;
205 server = client->server;
206 if (server && server->clients)
207 ArrayList_Remove(server->clients, (
void*)client);
209 shadow_encoder_free(client->encoder);
212 MessageQueue_Free(client->MsgQueue);
213 WTSCloseServer(client->vcm);
214 region16_uninit(&(client->invalidRegion));
215 DeleteCriticalSection(&(client->lock));
217 client->MsgQueue = NULL;
218 client->encoder = NULL;
222 static BOOL shadow_client_context_new(freerdp_peer* peer, rdpContext* context)
225 const char bind_address[] =
"bind-address,";
226 rdpShadowClient* client = (rdpShadowClient*)context;
227 rdpSettings* settings = NULL;
228 const rdpSettings* srvSettings = NULL;
229 rdpShadowServer* server = NULL;
230 const wObject cb = { NULL, NULL, NULL, shadow_client_free_queued_message, NULL };
232 WINPR_ASSERT(client);
234 WINPR_ASSERT(peer->context);
236 server = (rdpShadowServer*)peer->ContextExtra;
237 WINPR_ASSERT(server);
239 srvSettings = server->settings;
240 WINPR_ASSERT(srvSettings);
242 client->surfaceId = 1;
243 client->server = server;
244 client->subsystem = server->subsystem;
245 WINPR_ASSERT(client->subsystem);
247 settings = peer->context->settings;
248 WINPR_ASSERT(settings);
260 settings, FreeRDP_RemoteFxRlgrMode,
270 settings, FreeRDP_SupportGraphicsPipeline,
285 if (server->ipcSocket && (strncmp(bind_address, server->ipcSocket,
286 strnlen(bind_address,
sizeof(bind_address))) != 0))
294 client->inLobby = TRUE;
295 client->mayView = server->mayView;
296 client->mayInteract = server->mayInteract;
298 if (!InitializeCriticalSectionAndSpinCount(&(client->lock), 4000))
301 region16_init(&(client->invalidRegion));
302 client->vcm = WTSOpenServerA((LPSTR)peer->context);
304 if (!client->vcm || client->vcm == INVALID_HANDLE_VALUE)
307 if (!(client->MsgQueue = MessageQueue_New(&cb)))
310 if (!(client->encoder = shadow_encoder_new(client)))
313 if (!ArrayList_Append(server->clients, (
void*)client))
319 shadow_client_context_free(peer, context);
323 static INLINE
void shadow_client_mark_invalid(rdpShadowClient* client, UINT32 numRects,
327 rdpSettings* settings = NULL;
329 WINPR_ASSERT(client);
330 WINPR_ASSERT(rects || (numRects == 0));
332 settings = client->context.settings;
333 WINPR_ASSERT(settings);
335 EnterCriticalSection(&(client->lock));
340 for (UINT32 index = 0; index < numRects; index++)
342 region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
347 screenRegion.left = 0;
348 screenRegion.top = 0;
353 region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &screenRegion);
356 LeaveCriticalSection(&(client->lock));
365 static INLINE BOOL shadow_client_recalc_desktop_size(rdpShadowClient* client)
369 rdpShadowServer* server = NULL;
370 rdpSettings* settings = NULL;
373 WINPR_ASSERT(client);
374 server = client->server;
375 settings = client->context.settings;
377 WINPR_ASSERT(server);
378 WINPR_ASSERT(server->surface);
379 WINPR_ASSERT(settings);
381 WINPR_ASSERT(server->surface->width <= UINT16_MAX);
382 WINPR_ASSERT(server->surface->height <= UINT16_MAX);
383 viewport.right = (UINT16)server->surface->width;
384 viewport.bottom = (UINT16)server->surface->height;
386 if (server->shareSubRect)
388 rectangles_intersection(&viewport, &(server->subRect), &viewport);
391 width = viewport.right - viewport.left;
392 height = viewport.bottom - viewport.top;
394 WINPR_ASSERT(width >= 0);
395 WINPR_ASSERT(width <= UINT16_MAX);
396 WINPR_ASSERT(height >= 0);
397 WINPR_ASSERT(height <= UINT16_MAX);
405 static BOOL shadow_client_capabilities(freerdp_peer* peer)
407 rdpShadowSubsystem* subsystem = NULL;
408 rdpShadowClient* client = NULL;
413 client = (rdpShadowClient*)peer->context;
414 WINPR_ASSERT(client);
415 WINPR_ASSERT(client->server);
417 subsystem = client->server->subsystem;
418 WINPR_ASSERT(subsystem);
420 IFCALLRET(subsystem->ClientCapabilities, ret, subsystem, client);
423 WLog_WARN(TAG,
"subsystem->ClientCapabilities failed");
428 static void shadow_reset_desktop_resize(rdpShadowClient* client)
430 WINPR_ASSERT(client);
431 client->resizeRequested = FALSE;
434 static BOOL shadow_send_desktop_resize(rdpShadowClient* client)
437 rdpUpdate* update = NULL;
438 rdpSettings* settings = NULL;
439 const freerdp_peer* peer = NULL;
441 WINPR_ASSERT(client);
443 settings = client->context.settings;
444 peer = client->context.peer;
446 WINPR_ASSERT(client->server);
447 WINPR_ASSERT(client->server->surface);
449 const UINT32 resizeWidth = client->server->surface->width;
450 const UINT32 resizeHeight = client->server->surface->height;
452 if (client->resizeRequested)
454 if ((resizeWidth == client->resizeWidth) && (resizeHeight == client->resizeHeight))
459 "detected previous resize request for resolution %" PRIu32
"x%" PRIu32
460 ", still have %" PRIu32
"x%" PRIu32
", disconnecting peer",
461 resizeWidth, resizeHeight, w, h);
466 update = client->context.update;
467 WINPR_ASSERT(update);
468 WINPR_ASSERT(update->DesktopResize);
476 rc = update->DesktopResize(update->context);
477 WLog_INFO(TAG,
"Client %s resize requested (%" PRIu32
"x%" PRIu32
"@%" PRIu32
")",
478 peer->hostname, resizeWidth, resizeHeight,
480 client->resizeRequested = TRUE;
481 client->resizeWidth = resizeWidth;
482 client->resizeHeight = resizeHeight;
487 static BOOL shadow_client_post_connect(freerdp_peer* peer)
490 rdpSettings* settings = NULL;
491 rdpShadowClient* client = NULL;
492 rdpShadowServer* server = NULL;
493 rdpShadowSubsystem* subsystem = NULL;
497 client = (rdpShadowClient*)peer->context;
498 WINPR_ASSERT(client);
500 settings = peer->context->settings;
501 WINPR_ASSERT(settings);
503 server = client->server;
504 WINPR_ASSERT(server);
506 subsystem = server->subsystem;
507 WINPR_ASSERT(subsystem);
515 const UINT32 MultifragMaxRequestSize =
517 if (MultifragMaxRequestSize < 0x3F0000)
520 settings, FreeRDP_NSCodec,
526 WLog_INFO(TAG,
"Client from %s is activated (%" PRIu32
"x%" PRIu32
"@%" PRIu32
")",
531 if (shadow_client_channels_post_connect(client) != CHANNEL_RC_OK)
534 shadow_client_mark_invalid(client, 0, NULL);
541 if (Username && Password)
549 if (subsystem->Authenticate)
551 authStatus = subsystem->Authenticate(subsystem, client, Username, Domain, Password);
556 WLog_ERR(TAG,
"client authentication failure: %d", authStatus);
561 if (subsystem->ClientConnect)
563 return subsystem->ClientConnect(subsystem, client);
570 static INLINE
void shadow_client_convert_rects(rdpShadowClient* client,
RECTANGLE_16* dst,
573 WINPR_ASSERT(client);
574 WINPR_ASSERT(client->server);
576 WINPR_ASSERT(src || (numRects == 0));
578 if (client->server->shareSubRect)
580 UINT16 offsetX = client->server->subRect.left;
581 UINT16 offsetY = client->server->subRect.top;
583 for (UINT32 i = 0; i < numRects; i++)
588 d->left = s->left + offsetX;
589 d->right = s->right + offsetX;
590 d->top = s->top + offsetY;
591 d->bottom = s->bottom + offsetY;
603 static BOOL shadow_client_refresh_request(rdpShadowClient* client)
605 wMessage message = { 0 };
608 WINPR_ASSERT(client);
609 WINPR_ASSERT(client->subsystem);
611 MsgPipe = client->subsystem->MsgPipe;
612 WINPR_ASSERT(MsgPipe);
614 message.id = SHADOW_MSG_IN_REFRESH_REQUEST_ID;
615 message.wParam = NULL;
616 message.lParam = NULL;
617 message.context = (
void*)client;
619 return MessageQueue_Dispatch(MsgPipe->In, &message);
622 static BOOL shadow_client_refresh_rect(rdpContext* context, BYTE count,
const RECTANGLE_16* areas)
624 rdpShadowClient* client = (rdpShadowClient*)context;
640 shadow_client_convert_rects(client, rects, areas, count);
641 shadow_client_mark_invalid(client, count, rects);
646 shadow_client_mark_invalid(client, 0, NULL);
649 return shadow_client_refresh_request(client);
652 static BOOL shadow_client_suppress_output(rdpContext* context, BYTE allow,
const RECTANGLE_16* area)
654 rdpShadowClient* client = (rdpShadowClient*)context;
657 WINPR_ASSERT(client);
659 client->suppressOutput = allow ? FALSE : TRUE;
665 shadow_client_convert_rects(client, ®ion, area, 1);
666 shadow_client_mark_invalid(client, 1, ®ion);
670 shadow_client_mark_invalid(client, 0, NULL);
674 return shadow_client_refresh_request(client);
677 static BOOL shadow_client_activate(freerdp_peer* peer)
679 rdpSettings* settings = NULL;
680 rdpShadowClient* client = NULL;
684 client = (rdpShadowClient*)peer->context;
685 WINPR_ASSERT(client);
687 settings = peer->context->settings;
688 WINPR_ASSERT(settings);
691 if (shadow_client_recalc_desktop_size(client))
692 return shadow_send_desktop_resize(client);
694 shadow_reset_desktop_resize(client);
695 client->activated = TRUE;
696 client->inLobby = client->mayView ? FALSE : TRUE;
698 if (shadow_encoder_reset(client->encoder) < 0)
700 WLog_ERR(TAG,
"Failed to reset encoder");
705 return shadow_client_refresh_rect(&client->context, 0, NULL);
708 static BOOL shadow_client_logon(freerdp_peer* peer,
const SEC_WINNT_AUTH_IDENTITY* identity,
714 char* password = NULL;
715 rdpSettings* settings = NULL;
717 WINPR_UNUSED(automatic);
720 WINPR_ASSERT(identity);
722 WINPR_ASSERT(peer->context);
724 settings = peer->context->settings;
725 WINPR_ASSERT(settings);
727 if (identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
730 user = ConvertWCharNToUtf8Alloc(identity->User, identity->UserLength, NULL);
732 if (identity->Domain)
733 domain = ConvertWCharNToUtf8Alloc(identity->Domain, identity->DomainLength, NULL);
735 if (identity->Password)
736 password = ConvertWCharNToUtf8Alloc(identity->Password, identity->PasswordLength, NULL);
741 user = _strdup((
char*)identity->User);
743 if (identity->Domain)
744 domain = _strdup((
char*)identity->Domain);
746 if (identity->Password)
747 password = _strdup((
char*)identity->Password);
750 if ((identity->User && !user) || (identity->Domain && !domain) ||
751 (identity->Password && !password))
778 static INLINE
void shadow_client_common_frame_acknowledge(rdpShadowClient* client, UINT32 frameId)
788 WINPR_ASSERT(client);
789 WINPR_ASSERT(client->encoder);
790 client->encoder->lastAckframeId = frameId;
793 static BOOL shadow_client_surface_frame_acknowledge(rdpContext* context, UINT32 frameId)
795 rdpShadowClient* client = (rdpShadowClient*)context;
796 shadow_client_common_frame_acknowledge(client, frameId);
800 WINPR_ASSERT(client);
801 WINPR_ASSERT(client->encoder);
802 client->encoder->queueDepth = QUEUE_DEPTH_UNAVAILABLE;
807 shadow_client_rdpgfx_frame_acknowledge(RdpgfxServerContext* context,
810 rdpShadowClient* client = NULL;
812 WINPR_ASSERT(context);
813 WINPR_ASSERT(frameAcknowledge);
815 client = (rdpShadowClient*)context->custom;
816 shadow_client_common_frame_acknowledge(client, frameAcknowledge->frameId);
818 WINPR_ASSERT(client);
819 WINPR_ASSERT(client->encoder);
820 client->encoder->queueDepth = frameAcknowledge->queueDepth;
821 return CHANNEL_RC_OK;
824 static BOOL shadow_are_caps_filtered(
const rdpSettings* settings, UINT32 caps)
826 const UINT32 capList[] = { RDPGFX_CAPVERSION_8, RDPGFX_CAPVERSION_81,
827 RDPGFX_CAPVERSION_10, RDPGFX_CAPVERSION_101,
828 RDPGFX_CAPVERSION_102, RDPGFX_CAPVERSION_103,
829 RDPGFX_CAPVERSION_104, RDPGFX_CAPVERSION_105,
830 RDPGFX_CAPVERSION_106, RDPGFX_CAPVERSION_106_ERR,
831 RDPGFX_CAPVERSION_107 };
833 WINPR_ASSERT(settings);
836 for (UINT32 x = 0; x < ARRAYSIZE(capList); x++)
838 if (caps == capList[x])
839 return (filter & (1 << x)) != 0;
845 static UINT shadow_client_send_caps_confirm(RdpgfxServerContext* context, rdpShadowClient* client,
848 WINPR_ASSERT(context);
849 WINPR_ASSERT(client);
852 WINPR_ASSERT(context->CapsConfirm);
853 UINT rc = context->CapsConfirm(context, pdu);
854 client->areGfxCapsReady = (rc == CHANNEL_RC_OK);
858 static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context, rdpShadowClient* client,
860 UINT32 capsSetCount, UINT32 capsVersion, UINT* rc)
862 const rdpSettings* srvSettings = NULL;
863 rdpSettings* clientSettings = NULL;
865 WINPR_ASSERT(context);
866 WINPR_ASSERT(client);
867 WINPR_ASSERT(capsSets || (capsSetCount == 0));
870 WINPR_ASSERT(context->rdpcontext);
871 srvSettings = context->rdpcontext->settings;
872 WINPR_ASSERT(srvSettings);
874 clientSettings = client->context.settings;
875 WINPR_ASSERT(clientSettings);
877 if (shadow_are_caps_filtered(srvSettings, capsVersion))
880 for (UINT32 index = 0; index < capsSetCount; index++)
884 if (currentCaps->version == capsVersion)
889 BOOL avc444v2 = FALSE;
892 BOOL progressive = FALSE;
897 flags = pdu.capsSet->flags;
900 (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) ? TRUE : FALSE))
903 avc444v2 = avc444 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED);
932 if (!avc444v2 && !avc444 && !avc420)
933 pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
935 *rc = shadow_client_send_caps_confirm(context, client, &pdu);
948 static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context,
951 UINT rc = ERROR_INTERNAL_ERROR;
952 const rdpSettings* srvSettings = NULL;
953 rdpSettings* clientSettings = NULL;
958 WINPR_ASSERT(context);
959 WINPR_ASSERT(capsAdvertise);
961 rdpShadowClient* client = (rdpShadowClient*)context->custom;
962 WINPR_ASSERT(client);
963 WINPR_ASSERT(context->rdpcontext);
965 srvSettings = context->rdpcontext->settings;
966 WINPR_ASSERT(srvSettings);
968 clientSettings = client->context.settings;
969 WINPR_ASSERT(clientSettings);
973 (shadow_encoder_prepare(client->encoder, FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444) >= 0);
984 if (!shadow_client_refresh_rect(&client->context, 0, NULL))
987 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
988 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_107, &rc))
991 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
992 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_106, &rc))
995 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
996 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_106_ERR,
1000 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1001 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_105, &rc))
1004 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1005 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_104, &rc))
1008 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1009 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_103, &rc))
1012 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1013 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_102, &rc))
1016 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1017 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_101, &rc))
1020 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1021 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_10, &rc))
1024 if (!shadow_are_caps_filtered(srvSettings, RDPGFX_CAPVERSION_81))
1026 for (UINT32 index = 0; index < capsAdvertise->capsSetCount; index++)
1028 const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
1030 if (currentCaps->version == RDPGFX_CAPVERSION_81)
1034 pdu.capsSet = ∩︀
1036 flags = pdu.capsSet->flags;
1044 (flags & RDPGFX_CAPS_FLAG_THINCLIENT) ? TRUE
1048 (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) ? TRUE
1052 #ifndef WITH_GFX_H264
1055 pdu.capsSet->flags &= ~RDPGFX_CAPS_FLAG_AVC420_ENABLED;
1061 clientSettings, FreeRDP_GfxH264,
1062 (flags & RDPGFX_CAPS_FLAG_AVC420_ENABLED) ? TRUE : FALSE))
1072 return shadow_client_send_caps_confirm(context, client, &pdu);
1077 if (!shadow_are_caps_filtered(srvSettings, RDPGFX_CAPVERSION_8))
1079 for (UINT32 index = 0; index < capsAdvertise->capsSetCount; index++)
1081 const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
1083 if (currentCaps->version == RDPGFX_CAPVERSION_8)
1087 pdu.capsSet = ∩︀
1088 flags = pdu.capsSet->flags;
1098 (flags & RDPGFX_CAPS_FLAG_THINCLIENT) ? TRUE
1102 (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) ? TRUE
1106 return shadow_client_send_caps_confirm(context, client, &pdu);
1111 return CHANNEL_RC_UNSUPPORTED_VERSION;
1117 WINPR_ASSERT(havc420);
1118 return sizeof(UINT32)
1120 * havc420->meta.numRegionRects +
1129 static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client,
const BYTE* pSrcData,
1130 UINT32 nSrcStep, UINT32 SrcFormat, UINT16 nXSrc,
1131 UINT16 nYSrc, UINT16 nWidth, UINT16 nHeight)
1134 UINT error = CHANNEL_RC_OK;
1135 const rdpContext* context = (
const rdpContext*)client;
1136 const rdpSettings* settings = NULL;
1137 rdpShadowEncoder* encoder = NULL;
1143 if (!context || !pSrcData)
1146 settings = context->settings;
1147 encoder = client->encoder;
1149 if (!settings || !encoder)
1152 if (client->first_frame)
1154 rfx_context_reset(encoder->rfx, nWidth, nHeight);
1155 client->first_frame = FALSE;
1158 cmdstart.frameId = shadow_encoder_create_frame_id(encoder);
1159 GetSystemTime(&sTime);
1160 cmdstart.timestamp = (UINT32)(sTime.wHour << 22U | sTime.wMinute << 16U | sTime.wSecond << 10U |
1161 sTime.wMilliseconds);
1162 cmdend.frameId = cmdstart.frameId;
1163 cmd.surfaceId = client->surfaceId;
1164 cmd.format = PIXEL_FORMAT_BGRX32;
1167 cmd.right = cmd.left + nWidth;
1168 cmd.bottom = cmd.top + nHeight;
1170 cmd.height = nHeight;
1173 #ifdef WITH_GFX_H264
1177 if (GfxAVC444 || GfxAVC444v2)
1182 BYTE version = GfxAVC444v2 ? 2 : 1;
1184 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC444) < 0)
1186 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_AVC444");
1190 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1191 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1192 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1193 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1194 regionRect.left = (UINT16)cmd.left;
1195 regionRect.top = (UINT16)cmd.top;
1196 regionRect.right = (UINT16)cmd.right;
1197 regionRect.bottom = (UINT16)cmd.bottom;
1198 rc = avc444_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
1199 version, ®ionRect, &avc444.LC, &avc444.bitstream[0].data,
1200 &avc444.bitstream[0].length, &avc444.bitstream[1].data,
1201 &avc444.bitstream[1].length, &avc444.bitstream[0].meta,
1202 &avc444.bitstream[1].meta);
1205 WLog_ERR(TAG,
"avc420_compress failed for avc444");
1212 avc444.cbAvc420EncodedBitstream1 = rdpgfx_estimate_h264_avc420(&avc444.bitstream[0]);
1213 cmd.codecId = GfxAVC444v2 ? RDPGFX_CODECID_AVC444v2 : RDPGFX_CODECID_AVC444;
1214 cmd.extra = (
void*)&avc444;
1215 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1219 free_h264_metablock(&avc444.bitstream[0].meta);
1220 free_h264_metablock(&avc444.bitstream[1].meta);
1223 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1233 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC420) < 0)
1235 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_AVC420");
1239 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1240 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1241 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1242 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1243 regionRect.left = (UINT16)cmd.left;
1244 regionRect.top = (UINT16)cmd.top;
1245 regionRect.right = (UINT16)cmd.right;
1246 regionRect.bottom = (UINT16)cmd.bottom;
1247 rc = avc420_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
1248 ®ionRect, &avc420.data, &avc420.length, &avc420.meta);
1251 WLog_ERR(TAG,
"avc420_compress failed");
1258 cmd.codecId = RDPGFX_CODECID_AVC420;
1259 cmd.extra = (
void*)&avc420;
1261 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1264 free_h264_metablock(&avc420.meta);
1268 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1280 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX) < 0)
1282 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_REMOTEFX");
1286 s = Stream_New(NULL, 1024);
1289 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1290 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1291 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1292 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1293 rect.x = (UINT16)cmd.left;
1294 rect.y = (UINT16)cmd.top;
1295 rect.width = WINPR_ASSERTING_INT_CAST(UINT16, cmd.right - cmd.left);
1296 rect.height = WINPR_ASSERTING_INT_CAST(UINT16, cmd.bottom - cmd.top);
1298 rc = rfx_compose_message(encoder->rfx, s, &rect, 1, pSrcData, nWidth, nHeight, nSrcStep);
1302 WLog_ERR(TAG,
"rfx_compose_message failed");
1303 Stream_Free(s, TRUE);
1310 const size_t pos = Stream_GetPosition(s);
1311 WINPR_ASSERT(pos <= UINT32_MAX);
1313 cmd.codecId = RDPGFX_CODECID_CAVIDEO;
1314 cmd.data = Stream_Buffer(s);
1315 cmd.length = (UINT32)pos;
1317 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1321 Stream_Free(s, TRUE);
1324 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1334 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PROGRESSIVE) < 0)
1336 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_PROGRESSIVE");
1340 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1341 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1342 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1343 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1344 regionRect.left = (UINT16)cmd.left;
1345 regionRect.top = (UINT16)cmd.top;
1346 regionRect.right = (UINT16)cmd.right;
1347 regionRect.bottom = (UINT16)cmd.bottom;
1348 region16_init(®ion);
1349 region16_union_rect(®ion, ®ion, ®ionRect);
1350 rc = progressive_compress(encoder->progressive, pSrcData, nSrcStep * nHeight, cmd.format,
1351 nWidth, nHeight, nSrcStep, ®ion, &cmd.data, &cmd.length);
1352 region16_uninit(®ion);
1355 WLog_ERR(TAG,
"progressive_compress failed");
1362 cmd.codecId = RDPGFX_CODECID_CAPROGRESSIVE;
1364 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1370 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1377 const UINT32 w = cmd.right - cmd.left;
1378 const UINT32 h = cmd.bottom - cmd.top;
1380 &pSrcData[cmd.top * nSrcStep + cmd.left * FreeRDPGetBytesPerPixel(SrcFormat)];
1381 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR) < 0)
1383 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_PLANAR");
1387 rc = freerdp_bitmap_planar_context_reset(encoder->planar, w, h);
1389 freerdp_planar_topdown_image(encoder->planar, TRUE);
1391 cmd.data = freerdp_bitmap_compress_planar(encoder->planar, src, SrcFormat, w, h, nSrcStep,
1393 WINPR_ASSERT(cmd.data || (cmd.length == 0));
1395 cmd.codecId = RDPGFX_CODECID_PLANAR;
1397 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1402 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1409 const UINT32 w = cmd.right - cmd.left;
1410 const UINT32 h = cmd.bottom - cmd.top;
1411 const UINT32 length = w * 4 * h;
1412 BYTE* data = malloc(length);
1416 rc = freerdp_image_copy_no_overlap(data, PIXEL_FORMAT_BGRA32, 0, 0, 0, w, h, pSrcData,
1417 SrcFormat, nSrcStep, cmd.left, cmd.top, NULL, 0);
1421 cmd.length = length;
1422 cmd.codecId = RDPGFX_CODECID_UNCOMPRESSED;
1424 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1429 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1436 static BOOL stream_surface_bits_supported(
const rdpSettings* settings)
1438 const UINT32 supported =
1440 return ((supported & SURFCMDS_STREAM_SURFACE_BITS) != 0);
1443 static BOOL set_surface_bits_supported(
const rdpSettings* settings)
1445 const UINT32 supported =
1447 return ((supported & SURFCMDS_SET_SURFACE_BITS) != 0);
1450 static BOOL is_surface_command_supported(
const rdpSettings* settings)
1452 if (stream_surface_bits_supported(settings))
1456 if (supported && (rfxID != 0))
1459 if (set_surface_bits_supported(settings))
1463 if (supported && (nsID != 0))
1474 static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcData,
1475 UINT32 nSrcStep, UINT16 nXSrc, UINT16 nYSrc,
1476 UINT16 nWidth, UINT16 nHeight)
1482 size_t numMessages = 0;
1484 rdpUpdate* update = NULL;
1485 rdpContext* context = (rdpContext*)client;
1486 rdpSettings* settings = NULL;
1487 rdpShadowEncoder* encoder = NULL;
1490 if (!context || !pSrcData)
1493 update = context->update;
1494 settings = context->settings;
1495 encoder = client->encoder;
1497 if (!update || !settings || !encoder)
1500 if (encoder->frameAck)
1501 frameId = shadow_encoder_create_frame_id(encoder);
1506 if (stream_surface_bits_supported(settings) &&
1511 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX) < 0)
1513 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_REMOTEFX");
1520 rect.width = nWidth;
1521 rect.height = nHeight;
1523 const UINT32 MultifragMaxRequestSize =
1525 RFX_MESSAGE_LIST* messages =
1526 rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData,
1529 nSrcStep, &numMessages, MultifragMaxRequestSize);
1532 WLog_ERR(TAG,
"rfx_encode_messages failed");
1536 cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
1537 WINPR_ASSERT(rfxID <= UINT16_MAX);
1538 cmd.bmp.codecID = (UINT16)rfxID;
1549 cmd.skipCompression = TRUE;
1551 for (
size_t i = 0; i < numMessages; i++)
1553 Stream_SetPosition(s, 0);
1555 const RFX_MESSAGE* msg = rfx_message_list_get(messages, i);
1556 if (!rfx_write_message(encoder->rfx, s, msg))
1558 WLog_ERR(TAG,
"rfx_write_message failed");
1563 WINPR_ASSERT(Stream_GetPosition(s) <= UINT32_MAX);
1564 cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
1565 cmd.bmp.bitmapData = Stream_Buffer(s);
1566 first = (i == 0) ? TRUE : FALSE;
1567 last = ((i + 1) == numMessages) ? TRUE : FALSE;
1569 if (!encoder->frameAck)
1570 IFCALLRET(update->SurfaceBits, ret, update->context, &cmd);
1572 IFCALLRET(update->SurfaceFrameBits, ret, update->context, &cmd, first, last,
1577 WLog_ERR(TAG,
"Send surface bits(RemoteFxCodec) failed");
1582 rfx_message_list_free(messages);
1584 else if (set_surface_bits_supported(settings) &&
1587 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_NSCODEC) < 0)
1589 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_NSCODEC");
1594 Stream_SetPosition(s, 0);
1595 pSrcData = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
1596 nsc_compose_message(encoder->nsc, s, pSrcData, nWidth, nHeight, nSrcStep);
1597 cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
1599 WINPR_ASSERT(nsID <= UINT16_MAX);
1600 cmd.bmp.codecID = (UINT16)nsID;
1601 cmd.destLeft = nXSrc;
1602 cmd.destTop = nYSrc;
1603 cmd.destRight = cmd.destLeft + nWidth;
1604 cmd.destBottom = cmd.destTop + nHeight;
1605 cmd.bmp.width = nWidth;
1606 cmd.bmp.height = nHeight;
1607 WINPR_ASSERT(Stream_GetPosition(s) <= UINT32_MAX);
1608 cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
1609 cmd.bmp.bitmapData = Stream_Buffer(s);
1613 if (!encoder->frameAck)
1614 IFCALLRET(update->SurfaceBits, ret, update->context, &cmd);
1616 IFCALLRET(update->SurfaceFrameBits, ret, update->context, &cmd, first, last, frameId);
1620 WLog_ERR(TAG,
"Send surface bits(NSCodec) failed");
1632 static BOOL shadow_client_send_bitmap_update(rdpShadowClient* client, BYTE* pSrcData,
1633 UINT32 nSrcStep, UINT16 nXSrc, UINT16 nYSrc,
1634 UINT16 nWidth, UINT16 nHeight)
1638 BYTE* buffer = NULL;
1645 UINT32 SrcFormat = 0;
1647 rdpContext* context = (rdpContext*)client;
1648 UINT32 totalBitmapSize = 0;
1649 UINT32 updateSizeEstimate = 0;
1653 if (!context || !pSrcData)
1656 rdpUpdate* update = context->update;
1657 rdpSettings* settings = context->settings;
1658 rdpShadowEncoder* encoder = client->encoder;
1660 if (!update || !settings || !encoder)
1663 const UINT32 maxUpdateSize =
1667 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED) < 0)
1669 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_INTERLEAVED");
1675 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR) < 0)
1677 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_PLANAR");
1682 SrcFormat = PIXEL_FORMAT_BGRX32;
1684 if ((nXSrc % 4) != 0)
1686 nWidth += (nXSrc % 4);
1687 nXSrc -= (nXSrc % 4);
1690 if ((nYSrc % 4) != 0)
1692 nHeight += (nYSrc % 4);
1693 nYSrc -= (nYSrc % 4);
1696 rows = (nHeight / 64) + ((nHeight % 64) ? 1 : 0);
1697 cols = (nWidth / 64) + ((nWidth % 64) ? 1 : 0);
1699 totalBitmapSize = 0;
1700 bitmapUpdate.number = rows * cols;
1705 bitmapUpdate.rectangles = bitmapData;
1707 if ((nWidth % 4) != 0)
1709 nWidth += (4 - (nWidth % 4));
1712 if ((nHeight % 4) != 0)
1714 nHeight += (4 - (nHeight % 4));
1717 for (yIdx = 0; yIdx < rows; yIdx++)
1719 for (xIdx = 0; xIdx < cols; xIdx++)
1721 bitmap = &bitmapData[k];
1723 bitmap->height = 64;
1724 bitmap->destLeft = nXSrc + (xIdx * 64);
1725 bitmap->destTop = nYSrc + (yIdx * 64);
1727 if (((INT64)bitmap->destLeft + bitmap->width) > (nXSrc + nWidth))
1728 bitmap->width = (UINT32)(nXSrc + nWidth) - bitmap->destLeft;
1730 if (((INT64)bitmap->destTop + bitmap->height) > (nYSrc + nHeight))
1731 bitmap->height = (UINT32)(nYSrc + nHeight) - bitmap->destTop;
1733 bitmap->destRight = bitmap->destLeft + bitmap->width - 1;
1734 bitmap->destBottom = bitmap->destTop + bitmap->height - 1;
1735 bitmap->compressed = TRUE;
1737 if ((bitmap->width < 4) || (bitmap->height < 4))
1743 UINT32 bytesPerPixel = (bitsPerPixel + 7) / 8;
1744 DstSize = 64 * 64 * 4;
1745 buffer = encoder->grid[k];
1746 interleaved_compress(encoder->interleaved, buffer, &DstSize, bitmap->width,
1747 bitmap->height, pSrcData, SrcFormat, nSrcStep,
1748 bitmap->destLeft, bitmap->destTop, NULL, bitsPerPixel);
1749 bitmap->bitmapDataStream = buffer;
1750 bitmap->bitmapLength = DstSize;
1751 bitmap->bitsPerPixel = bitsPerPixel;
1752 bitmap->cbScanWidth = bitmap->width * bytesPerPixel;
1753 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * bytesPerPixel;
1758 buffer = encoder->grid[k];
1759 data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)];
1762 freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat, bitmap->width,
1763 bitmap->height, nSrcStep, buffer, &dstSize);
1764 bitmap->bitmapDataStream = buffer;
1765 bitmap->bitmapLength = dstSize;
1766 bitmap->bitsPerPixel = 32;
1767 bitmap->cbScanWidth = bitmap->width * 4;
1768 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * 4;
1771 bitmap->cbCompFirstRowSize = 0;
1772 bitmap->cbCompMainBodySize = bitmap->bitmapLength;
1773 totalBitmapSize += bitmap->bitmapLength;
1778 bitmapUpdate.number = k;
1779 updateSizeEstimate = totalBitmapSize + (k * bitmapUpdate.number) + 16;
1781 if (updateSizeEstimate > maxUpdateSize)
1785 UINT32 updateSize = 0;
1786 UINT32 newUpdateSize = 0;
1792 if (!fragBitmapData)
1794 WLog_ERR(TAG,
"Failed to allocate memory for fragBitmapData");
1799 bitmapUpdate.rectangles = fragBitmapData;
1805 newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16);
1807 if (newUpdateSize < maxUpdateSize)
1809 CopyMemory(&fragBitmapData[j++], &bitmapData[i++],
sizeof(
BITMAP_DATA));
1810 updateSize = newUpdateSize;
1813 if ((newUpdateSize >= maxUpdateSize) || (i + 1) >= k)
1815 bitmapUpdate.number = j;
1816 ret = BitmapUpdateProxy(update, context, &bitmapUpdate);
1826 free(fragBitmapData);
1830 ret = BitmapUpdateProxy(update, context, &bitmapUpdate);
1843 static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
1850 rdpContext* context = (rdpContext*)client;
1851 rdpSettings* settings = NULL;
1852 rdpShadowServer* server = NULL;
1853 rdpShadowSurface* surface = NULL;
1857 BYTE* pSrcData = NULL;
1858 UINT32 nSrcStep = 0;
1859 UINT32 SrcFormat = 0;
1860 UINT32 numRects = 0;
1863 if (!context || !pStatus)
1866 settings = context->settings;
1867 server = client->server;
1869 if (!settings || !server)
1872 surface = client->inLobby ? server->lobby : server->surface;
1877 EnterCriticalSection(&(client->lock));
1878 region16_init(&invalidRegion);
1879 region16_copy(&invalidRegion, &(client->invalidRegion));
1880 region16_clear(&(client->invalidRegion));
1881 LeaveCriticalSection(&(client->lock));
1883 EnterCriticalSection(&surface->lock);
1884 rects = region16_rects(&(surface->invalidRegion), &numRects);
1886 for (UINT32 index = 0; index < numRects; index++)
1887 region16_union_rect(&invalidRegion, &invalidRegion, &rects[index]);
1889 surfaceRect.left = 0;
1890 surfaceRect.top = 0;
1891 WINPR_ASSERT(surface->width <= UINT16_MAX);
1892 WINPR_ASSERT(surface->height <= UINT16_MAX);
1893 surfaceRect.right = (UINT16)surface->width;
1894 surfaceRect.bottom = (UINT16)surface->height;
1895 region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
1897 if (server->shareSubRect)
1899 region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
1902 if (region16_is_empty(&invalidRegion))
1908 extents = region16_extents(&invalidRegion);
1909 nXSrc = extents->left;
1910 nYSrc = extents->top;
1911 nWidth = extents->right - extents->left;
1912 nHeight = extents->bottom - extents->top;
1913 pSrcData = surface->data;
1914 nSrcStep = surface->scanline;
1915 SrcFormat = surface->format;
1918 if (server->shareSubRect)
1922 subX = server->subRect.left;
1923 subY = server->subRect.top;
1926 WINPR_ASSERT(nXSrc >= 0);
1927 WINPR_ASSERT(nXSrc <= UINT16_MAX);
1928 WINPR_ASSERT(nYSrc >= 0);
1929 WINPR_ASSERT(nYSrc <= UINT16_MAX);
1930 pSrcData = &pSrcData[((UINT16)subY * nSrcStep) + ((UINT16)subX * 4U)];
1939 if (pStatus->gfxOpened && client->areGfxCapsReady)
1946 if (!pStatus->gfxSurfaceCreated)
1949 if (!(ret = shadow_client_rdpgfx_reset_graphic(client)))
1952 if (!(ret = shadow_client_rdpgfx_new_surface(client)))
1955 pStatus->gfxSurfaceCreated = TRUE;
1958 WINPR_ASSERT(nWidth >= 0);
1959 WINPR_ASSERT(nWidth <= UINT16_MAX);
1960 WINPR_ASSERT(nHeight >= 0);
1961 WINPR_ASSERT(nHeight <= UINT16_MAX);
1962 ret = shadow_client_send_surface_gfx(client, pSrcData, nSrcStep, SrcFormat, 0, 0,
1963 (UINT16)nWidth, (UINT16)nHeight);
1970 else if (is_surface_command_supported(settings))
1972 WINPR_ASSERT(nXSrc >= 0);
1973 WINPR_ASSERT(nXSrc <= UINT16_MAX);
1974 WINPR_ASSERT(nYSrc >= 0);
1975 WINPR_ASSERT(nYSrc <= UINT16_MAX);
1976 WINPR_ASSERT(nWidth >= 0);
1977 WINPR_ASSERT(nWidth <= UINT16_MAX);
1978 WINPR_ASSERT(nHeight >= 0);
1979 WINPR_ASSERT(nHeight <= UINT16_MAX);
1980 ret = shadow_client_send_surface_bits(client, pSrcData, nSrcStep, (UINT16)nXSrc,
1981 (UINT16)nYSrc, (UINT16)nWidth, (UINT16)nHeight);
1985 WINPR_ASSERT(nXSrc >= 0);
1986 WINPR_ASSERT(nXSrc <= UINT16_MAX);
1987 WINPR_ASSERT(nYSrc >= 0);
1988 WINPR_ASSERT(nYSrc <= UINT16_MAX);
1989 WINPR_ASSERT(nWidth >= 0);
1990 WINPR_ASSERT(nWidth <= UINT16_MAX);
1991 WINPR_ASSERT(nHeight >= 0);
1992 WINPR_ASSERT(nHeight <= UINT16_MAX);
1993 ret = shadow_client_send_bitmap_update(client, pSrcData, nSrcStep, (UINT16)nXSrc,
1994 (UINT16)nYSrc, (UINT16)nWidth, (UINT16)nHeight);
1998 LeaveCriticalSection(&surface->lock);
1999 region16_uninit(&invalidRegion);
2010 static BOOL shadow_client_send_resize(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
2012 rdpContext* context = (rdpContext*)client;
2013 rdpSettings* settings = NULL;
2014 freerdp_peer* peer = NULL;
2016 if (!context || !pStatus)
2019 peer = context->peer;
2020 settings = context->settings;
2022 if (!peer || !settings)
2030 client->activated = FALSE;
2033 if (pStatus->gfxSurfaceCreated)
2035 if (!shadow_client_rdpgfx_release_surface(client))
2038 pStatus->gfxSurfaceCreated = FALSE;
2042 if (!shadow_send_desktop_resize(client))
2044 shadow_reset_desktop_resize(client);
2047 EnterCriticalSection(&(client->lock));
2048 region16_clear(&(client->invalidRegion));
2049 LeaveCriticalSection(&(client->lock));
2059 static BOOL shadow_client_surface_update(rdpShadowClient* client,
REGION16* region)
2061 UINT32 numRects = 0;
2063 rects = region16_rects(region, &numRects);
2064 shadow_client_mark_invalid(client, numRects, rects);
2074 static INLINE BOOL shadow_client_no_surface_update(rdpShadowClient* client,
2075 SHADOW_GFX_STATUS* pStatus)
2077 rdpShadowServer* server = NULL;
2078 rdpShadowSurface* surface = NULL;
2079 WINPR_UNUSED(pStatus);
2080 WINPR_ASSERT(client);
2081 server = client->server;
2082 WINPR_ASSERT(server);
2083 surface = client->inLobby ? server->lobby : server->surface;
2084 EnterCriticalSection(&surface->lock);
2085 const BOOL rc = shadow_client_surface_update(client, &(surface->invalidRegion));
2086 LeaveCriticalSection(&surface->lock);
2090 static int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message)
2092 rdpContext* context = (rdpContext*)client;
2093 rdpUpdate* update = NULL;
2095 WINPR_ASSERT(message);
2096 WINPR_ASSERT(context);
2097 update = context->update;
2098 WINPR_ASSERT(update);
2102 switch (message->id)
2104 case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
2109 pointerPosition.xPos = msg->xPos;
2110 pointerPosition.yPos = msg->yPos;
2112 WINPR_ASSERT(client->server);
2113 if (client->server->shareSubRect)
2115 pointerPosition.xPos -= client->server->subRect.left;
2116 pointerPosition.yPos -= client->server->subRect.top;
2119 if (client->activated)
2121 if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY))
2123 WINPR_ASSERT(update->pointer);
2124 IFCALL(update->pointer->PointerPosition, context, &pointerPosition);
2125 client->pointerX = msg->xPos;
2126 client->pointerY = msg->yPos;
2133 case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
2142 pointerNew.xorBpp = 24;
2143 pointerColor = &(pointerNew.colorPtrAttr);
2144 pointerColor->cacheIndex = 0;
2145 pointerColor->hotSpotX = WINPR_ASSERTING_INT_CAST(UINT16, msg->xHot);
2146 pointerColor->hotSpotY = WINPR_ASSERTING_INT_CAST(UINT16, msg->yHot);
2147 pointerColor->width = WINPR_ASSERTING_INT_CAST(UINT16, msg->width);
2148 pointerColor->height = WINPR_ASSERTING_INT_CAST(UINT16, msg->height);
2149 pointerColor->lengthAndMask = WINPR_ASSERTING_INT_CAST(UINT16, msg->lengthAndMask);
2150 pointerColor->lengthXorMask = WINPR_ASSERTING_INT_CAST(UINT16, msg->lengthXorMask);
2151 pointerColor->xorMaskData = msg->xorMaskData;
2152 pointerColor->andMaskData = msg->andMaskData;
2153 pointerCached.cacheIndex = pointerColor->cacheIndex;
2155 if (client->activated)
2157 IFCALL(update->pointer->PointerNew, context, &pointerNew);
2158 IFCALL(update->pointer->PointerCached, context, &pointerCached);
2164 case SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES_ID:
2171 if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
2173 client->rdpsnd->src_format = msg->audio_format;
2174 IFCALL(client->rdpsnd->SendSamples, client->rdpsnd, msg->buf, msg->nFrames,
2181 case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
2186 if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
2188 IFCALL(client->rdpsnd->SetVolume, client->rdpsnd, msg->left, msg->right);
2195 WLog_ERR(TAG,
"Unknown message id: %" PRIu32
"", message->id);
2199 shadow_client_free_queued_message(message);
2203 static DWORD WINAPI shadow_client_thread(LPVOID arg)
2205 rdpShadowClient* client = (rdpShadowClient*)arg;
2208 wMessage message = { 0 };
2209 wMessage pointerPositionMsg = { 0 };
2210 wMessage pointerAlphaMsg = { 0 };
2211 wMessage audioVolumeMsg = { 0 };
2212 HANDLE ChannelEvent = 0;
2213 void* UpdateSubscriber = NULL;
2214 HANDLE UpdateEvent = 0;
2215 freerdp_peer* peer = NULL;
2216 rdpContext* context = NULL;
2217 rdpSettings* settings = NULL;
2218 rdpShadowServer* server = NULL;
2219 rdpShadowSubsystem* subsystem = NULL;
2220 wMessageQueue* MsgQueue = NULL;
2222 SHADOW_GFX_STATUS gfxstatus = { 0 };
2223 rdpUpdate* update = NULL;
2225 WINPR_ASSERT(client);
2227 MsgQueue = client->MsgQueue;
2228 WINPR_ASSERT(MsgQueue);
2230 server = client->server;
2231 WINPR_ASSERT(server);
2232 subsystem = server->subsystem;
2233 context = (rdpContext*)client;
2234 peer = context->peer;
2236 WINPR_ASSERT(peer->context);
2238 settings = peer->context->settings;
2239 WINPR_ASSERT(settings);
2241 peer->Capabilities = shadow_client_capabilities;
2242 peer->PostConnect = shadow_client_post_connect;
2243 peer->Activate = shadow_client_activate;
2244 peer->Logon = shadow_client_logon;
2245 shadow_input_register_callbacks(peer->context->input);
2247 rc = peer->Initialize(peer);
2251 update = peer->context->update;
2252 WINPR_ASSERT(update);
2254 update->RefreshRect = shadow_client_refresh_rect;
2255 update->SuppressOutput = shadow_client_suppress_output;
2256 update->SurfaceFrameAcknowledge = shadow_client_surface_frame_acknowledge;
2258 if ((!client->vcm) || (!subsystem->updateEvent))
2261 UpdateSubscriber = shadow_multiclient_get_subscriber(subsystem->updateEvent);
2263 if (!UpdateSubscriber)
2266 UpdateEvent = shadow_multiclient_getevent(UpdateSubscriber);
2267 WINPR_ASSERT(UpdateEvent);
2269 ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm);
2270 WINPR_ASSERT(ChannelEvent);
2282 HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
2284 events[nCount++] = UpdateEvent;
2286 DWORD tmp = peer->GetEventHandles(peer, &events[nCount], 64 - nCount);
2290 WLog_ERR(TAG,
"Failed to get FreeRDP transport event handles");
2296 events[nCount++] = ChannelEvent;
2297 events[nCount++] = MessageQueue_Event(MsgQueue);
2299 #if defined(CHANNEL_RDPGFX_SERVER)
2300 HANDLE gfxevent = rdpgfx_server_get_event_handle(client->rdpgfx);
2303 events[nCount++] = gfxevent;
2306 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
2308 if (status == WAIT_FAILED)
2311 if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
2320 if (client->activated && !client->suppressOutput)
2325 if (shadow_client_recalc_desktop_size(client))
2328 if (!shadow_client_send_resize(client, &gfxstatus))
2330 WLog_ERR(TAG,
"Failed to send resize message");
2337 if (!shadow_client_send_surface_update(client, &gfxstatus))
2339 WLog_ERR(TAG,
"Failed to send surface update");
2347 if (!shadow_client_no_surface_update(client, &gfxstatus))
2349 WLog_ERR(TAG,
"Failed to handle surface update");
2358 (void)shadow_multiclient_consume(UpdateSubscriber);
2361 WINPR_ASSERT(peer->CheckFileDescriptor);
2362 if (!peer->CheckFileDescriptor(peer))
2364 WLog_ERR(TAG,
"Failed to check FreeRDP file descriptor");
2368 if (client->activated &&
2369 WTSVirtualChannelManagerIsChannelJoined(client->vcm, DRDYNVC_SVC_CHANNEL_NAME))
2371 switch (WTSVirtualChannelManagerGetDrdynvcState(client->vcm))
2374 case DRDYNVC_STATE_NONE:
2377 if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
2379 WLog_ERR(TAG,
"Failed to initialize drdynvc channel");
2385 case DRDYNVC_STATE_READY:
2386 #if defined(CHANNEL_AUDIN_SERVER)
2387 if (client->audin && !IFCALLRESULT(TRUE, client->audin->IsOpen, client->audin))
2389 if (!IFCALLRESULT(FALSE, client->audin->Open, client->audin))
2391 WLog_ERR(TAG,
"Failed to initialize audin channel");
2399 client->rdpgfx && !gfxstatus.gfxOpened)
2401 client->rdpgfx->FrameAcknowledge = shadow_client_rdpgfx_frame_acknowledge;
2402 client->rdpgfx->CapsAdvertise = shadow_client_rdpgfx_caps_advertise;
2404 if (!client->rdpgfx->Open(client->rdpgfx))
2406 WLog_WARN(TAG,
"Failed to open GraphicsPipeline");
2408 FreeRDP_SupportGraphicsPipeline, FALSE))
2413 gfxstatus.gfxOpened = TRUE;
2414 WLog_INFO(TAG,
"Gfx Pipeline Opened");
2425 if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
2427 if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
2429 WLog_ERR(TAG,
"WTSVirtualChannelManagerCheckFileDescriptor failure");
2434 #if defined(CHANNEL_RDPGFX_SERVER)
2437 if (WaitForSingleObject(gfxevent, 0) == WAIT_OBJECT_0)
2439 rdpgfx_server_handle_messages(client->rdpgfx);
2444 if (WaitForSingleObject(MessageQueue_Event(MsgQueue), 0) == WAIT_OBJECT_0)
2447 pointerPositionMsg.id = 0;
2448 pointerPositionMsg.Free = NULL;
2449 pointerAlphaMsg.id = 0;
2450 pointerAlphaMsg.Free = NULL;
2451 audioVolumeMsg.id = 0;
2452 audioVolumeMsg.Free = NULL;
2454 while (MessageQueue_Peek(MsgQueue, &message, TRUE))
2456 if (message.id == WMQ_QUIT)
2463 case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
2465 shadow_client_free_queued_message(&pointerPositionMsg);
2466 pointerPositionMsg = message;
2469 case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
2471 shadow_client_free_queued_message(&pointerAlphaMsg);
2472 pointerAlphaMsg = message;
2475 case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
2477 shadow_client_free_queued_message(&audioVolumeMsg);
2478 audioVolumeMsg = message;
2482 shadow_client_subsystem_process_message(client, &message);
2487 if (message.id == WMQ_QUIT)
2490 shadow_client_free_queued_message(&pointerPositionMsg);
2491 shadow_client_free_queued_message(&pointerAlphaMsg);
2492 shadow_client_free_queued_message(&audioVolumeMsg);
2498 if (pointerPositionMsg.id)
2500 shadow_client_subsystem_process_message(client, &pointerPositionMsg);
2503 if (pointerAlphaMsg.id)
2505 shadow_client_subsystem_process_message(client, &pointerAlphaMsg);
2508 if (audioVolumeMsg.id)
2510 shadow_client_subsystem_process_message(client, &audioVolumeMsg);
2519 #if defined(CHANNEL_AUDIN_SERVER)
2520 if (client->audin && !IFCALLRESULT(TRUE, client->audin->IsOpen, client->audin))
2522 if (!IFCALLRESULT(FALSE, client->audin->Close, client->audin))
2524 WLog_WARN(TAG,
"AUDIN shutdown failure!");
2529 if (gfxstatus.gfxOpened)
2531 if (gfxstatus.gfxSurfaceCreated)
2533 if (!shadow_client_rdpgfx_release_surface(client))
2534 WLog_WARN(TAG,
"GFX release surface failure!");
2537 WINPR_ASSERT(client->rdpgfx);
2538 WINPR_ASSERT(client->rdpgfx->Close);
2539 rc = client->rdpgfx->Close(client->rdpgfx);
2543 shadow_client_channels_free(client);
2545 if (UpdateSubscriber)
2547 shadow_multiclient_release_subscriber(UpdateSubscriber);
2548 UpdateSubscriber = NULL;
2551 if (peer->connected && subsystem->ClientDisconnect)
2553 subsystem->ClientDisconnect(subsystem, client);
2557 WINPR_ASSERT(peer->Disconnect);
2558 peer->Disconnect(peer);
2559 freerdp_peer_context_free(peer);
2560 freerdp_peer_free(peer);
2565 BOOL shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
2567 rdpShadowClient* client = NULL;
2568 rdpShadowServer* server = NULL;
2570 if (!listener || !peer)
2573 server = (rdpShadowServer*)listener->info;
2574 WINPR_ASSERT(server);
2576 peer->ContextExtra = (
void*)server;
2577 peer->ContextSize =
sizeof(rdpShadowClient);
2578 peer->ContextNew = shadow_client_context_new;
2579 peer->ContextFree = shadow_client_context_free;
2581 if (!freerdp_peer_context_new_ex(peer, server->settings))
2584 client = (rdpShadowClient*)peer->context;
2585 WINPR_ASSERT(client);
2587 if (!(client->thread = CreateThread(NULL, 0, shadow_client_thread, client, 0, NULL)))
2589 freerdp_peer_context_free(peer);
2595 (void)CloseHandle(client->thread);
2596 client->thread = NULL;
2602 static void shadow_msg_out_addref(wMessage* message)
2604 SHADOW_MSG_OUT* msg = NULL;
2606 WINPR_ASSERT(message);
2607 msg = (SHADOW_MSG_OUT*)message->wParam;
2610 InterlockedIncrement(&(msg->refCount));
2613 static void shadow_msg_out_release(wMessage* message)
2615 SHADOW_MSG_OUT* msg = NULL;
2617 WINPR_ASSERT(message);
2618 msg = (SHADOW_MSG_OUT*)message->wParam;
2621 if (InterlockedDecrement(&(msg->refCount)) <= 0)
2623 IFCALL(msg->Free, message->id, msg);
2627 static BOOL shadow_client_dispatch_msg(rdpShadowClient* client, wMessage* message)
2629 if (!client || !message)
2633 shadow_msg_out_addref(message);
2635 WINPR_ASSERT(client->MsgQueue);
2636 if (MessageQueue_Dispatch(client->MsgQueue, message))
2641 shadow_msg_out_release(message);
2646 BOOL shadow_client_post_msg(rdpShadowClient* client,
void* context, UINT32 type,
2647 SHADOW_MSG_OUT* msg,
void* lParam)
2649 wMessage message = { 0 };
2650 message.context = context;
2652 message.wParam = (
void*)msg;
2653 message.lParam = lParam;
2654 message.Free = shadow_msg_out_release;
2655 return shadow_client_dispatch_msg(client, &message);
2658 int shadow_client_boardcast_msg(rdpShadowServer* server,
void* context, UINT32 type,
2659 SHADOW_MSG_OUT* msg,
void* lParam)
2661 wMessage message = { 0 };
2662 rdpShadowClient* client = NULL;
2665 WINPR_ASSERT(server);
2668 message.context = context;
2670 message.wParam = (
void*)msg;
2671 message.lParam = lParam;
2672 message.Free = shadow_msg_out_release;
2675 shadow_msg_out_addref(&message);
2677 WINPR_ASSERT(server->clients);
2678 ArrayList_Lock(server->clients);
2680 for (
size_t index = 0; index < ArrayList_Count(server->clients); index++)
2682 client = (rdpShadowClient*)ArrayList_GetItem(server->clients, index);
2684 if (shadow_client_dispatch_msg(client, &message))
2690 ArrayList_Unlock(server->clients);
2692 shadow_msg_out_release(&message);
2696 int shadow_client_boardcast_quit(rdpShadowServer* server,
int nExitCode)
2698 wMessageQueue* queue = NULL;
2701 WINPR_ASSERT(server);
2702 WINPR_ASSERT(server->clients);
2704 ArrayList_Lock(server->clients);
2706 for (
size_t index = 0; index < ArrayList_Count(server->clients); index++)
2708 queue = ((rdpShadowClient*)ArrayList_GetItem(server->clients, index))->MsgQueue;
2710 if (MessageQueue_PostQuit(queue, nExitCode))
2716 ArrayList_Unlock(server->clients);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param)
Sets a string settings value. The param is copied.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.
This struct contains function pointer to initialize/free objects.