21 #include <freerdp/config.h>
23 #include <winpr/crt.h>
24 #include <winpr/assert.h>
25 #include <winpr/file.h>
26 #include <winpr/path.h>
27 #include <winpr/synch.h>
28 #include <winpr/thread.h>
29 #include <winpr/sysinfo.h>
30 #include <winpr/interlocked.h>
32 #include <freerdp/log.h>
33 #include <freerdp/channels/drdynvc.h>
37 #define TAG CLIENT_TAG("shadow")
42 BOOL gfxSurfaceCreated;
52 #define BitmapUpdateProxy(update, context, bitmap) \
53 BitmapUpdateProxyEx((update), (context), (bitmap), __FILE__, __LINE__, __func__)
54 static BOOL BitmapUpdateProxyEx(rdpUpdate* update, rdpContext* context,
const BITMAP_UPDATE* bitmap,
55 const char* file,
size_t line,
const char* fkt)
58 WINPR_ASSERT(context);
61 for (UINT32 x = 0; x < bitmap->number; x++)
67 cur.skipCompression = bitmap->skipCompression;
68 const BOOL rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, &cur);
71 WLog_Print(WLog_Get(TAG), WLOG_ERROR, line, file, fkt,
72 "BitmapUpdate[%" PRIu32
"] failed", x);
80 static INLINE BOOL shadow_client_rdpgfx_new_surface(rdpShadowClient* client)
82 UINT error = CHANNEL_RC_OK;
85 RdpgfxServerContext* context = NULL;
86 rdpSettings* settings = NULL;
89 context = client->rdpgfx;
90 WINPR_ASSERT(context);
91 settings = ((rdpContext*)client)->settings;
92 WINPR_ASSERT(settings);
98 createSurface.pixelFormat = GFX_PIXEL_FORMAT_XRGB_8888;
99 createSurface.surfaceId = client->surfaceId;
100 surfaceToOutput.outputOriginX = 0;
101 surfaceToOutput.outputOriginY = 0;
102 surfaceToOutput.surfaceId = client->surfaceId;
103 surfaceToOutput.reserved = 0;
104 IFCALLRET(context->CreateSurface, error, context, &createSurface);
108 WLog_ERR(TAG,
"CreateSurface failed with error %" PRIu32
"", error);
112 IFCALLRET(context->MapSurfaceToOutput, error, context, &surfaceToOutput);
116 WLog_ERR(TAG,
"MapSurfaceToOutput failed with error %" PRIu32
"", error);
123 static INLINE BOOL shadow_client_rdpgfx_release_surface(rdpShadowClient* client)
125 UINT error = CHANNEL_RC_OK;
127 RdpgfxServerContext* context = NULL;
129 WINPR_ASSERT(client);
131 context = client->rdpgfx;
132 WINPR_ASSERT(context);
134 pdu.surfaceId = client->surfaceId++;
135 IFCALLRET(context->DeleteSurface, error, context, &pdu);
139 WLog_ERR(TAG,
"DeleteSurface failed with error %" PRIu32
"", error);
146 static INLINE BOOL shadow_client_rdpgfx_reset_graphic(rdpShadowClient* client)
148 UINT error = CHANNEL_RC_OK;
150 RdpgfxServerContext* context = NULL;
151 rdpSettings* settings = NULL;
153 WINPR_ASSERT(client);
154 WINPR_ASSERT(client->rdpgfx);
156 context = client->rdpgfx;
157 WINPR_ASSERT(context);
159 settings = client->context.settings;
160 WINPR_ASSERT(settings);
164 pdu.monitorCount = client->subsystem->numMonitors;
165 pdu.monitorDefArray = client->subsystem->monitors;
166 IFCALLRET(context->ResetGraphics, error, context, &pdu);
170 WLog_ERR(TAG,
"ResetGraphics failed with error %" PRIu32
"", error);
174 client->first_frame = TRUE;
178 static INLINE
void shadow_client_free_queued_message(
void* obj)
180 wMessage* message = (wMessage*)obj;
182 WINPR_ASSERT(message);
185 message->Free(message);
186 message->Free = NULL;
190 static void shadow_client_context_free(freerdp_peer* peer, rdpContext* context)
192 rdpShadowClient* client = (rdpShadowClient*)context;
193 rdpShadowServer* server = NULL;
199 server = client->server;
200 if (server && server->clients)
201 ArrayList_Remove(server->clients, (
void*)client);
203 shadow_encoder_free(client->encoder);
206 MessageQueue_Free(client->MsgQueue);
207 WTSCloseServer(client->vcm);
208 region16_uninit(&(client->invalidRegion));
209 DeleteCriticalSection(&(client->lock));
211 client->MsgQueue = NULL;
212 client->encoder = NULL;
216 static BOOL shadow_client_context_new(freerdp_peer* peer, rdpContext* context)
219 const char bind_address[] =
"bind-address,";
220 rdpShadowClient* client = (rdpShadowClient*)context;
221 rdpSettings* settings = NULL;
222 const rdpSettings* srvSettings = NULL;
223 rdpShadowServer* server = NULL;
224 const wObject cb = { NULL, NULL, NULL, shadow_client_free_queued_message, NULL };
226 WINPR_ASSERT(client);
228 WINPR_ASSERT(peer->context);
230 server = (rdpShadowServer*)peer->ContextExtra;
231 WINPR_ASSERT(server);
233 srvSettings = server->settings;
234 WINPR_ASSERT(srvSettings);
236 client->surfaceId = 1;
237 client->server = server;
238 client->subsystem = server->subsystem;
239 WINPR_ASSERT(client->subsystem);
241 settings = peer->context->settings;
242 WINPR_ASSERT(settings);
254 settings, FreeRDP_RemoteFxRlgrMode,
264 settings, FreeRDP_SupportGraphicsPipeline,
279 if (server->ipcSocket && (strncmp(bind_address, server->ipcSocket,
280 strnlen(bind_address,
sizeof(bind_address))) != 0))
288 client->inLobby = TRUE;
289 client->mayView = server->mayView;
290 client->mayInteract = server->mayInteract;
292 if (!InitializeCriticalSectionAndSpinCount(&(client->lock), 4000))
295 region16_init(&(client->invalidRegion));
296 client->vcm = WTSOpenServerA((LPSTR)peer->context);
298 if (!client->vcm || client->vcm == INVALID_HANDLE_VALUE)
301 if (!(client->MsgQueue = MessageQueue_New(&cb)))
304 if (!(client->encoder = shadow_encoder_new(client)))
307 if (!ArrayList_Append(server->clients, (
void*)client))
313 shadow_client_context_free(peer, context);
317 static INLINE
void shadow_client_mark_invalid(rdpShadowClient* client, UINT32 numRects,
321 rdpSettings* settings = NULL;
323 WINPR_ASSERT(client);
324 WINPR_ASSERT(rects || (numRects == 0));
326 settings = client->context.settings;
327 WINPR_ASSERT(settings);
329 EnterCriticalSection(&(client->lock));
334 for (UINT32 index = 0; index < numRects; index++)
336 region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
341 screenRegion.left = 0;
342 screenRegion.top = 0;
347 region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &screenRegion);
350 LeaveCriticalSection(&(client->lock));
359 static INLINE BOOL shadow_client_recalc_desktop_size(rdpShadowClient* client)
363 rdpShadowServer* server = NULL;
364 rdpSettings* settings = NULL;
367 WINPR_ASSERT(client);
368 server = client->server;
369 settings = client->context.settings;
371 WINPR_ASSERT(server);
372 WINPR_ASSERT(server->surface);
373 WINPR_ASSERT(settings);
375 WINPR_ASSERT(server->surface->width <= UINT16_MAX);
376 WINPR_ASSERT(server->surface->height <= UINT16_MAX);
377 viewport.right = (UINT16)server->surface->width;
378 viewport.bottom = (UINT16)server->surface->height;
380 if (server->shareSubRect)
382 rectangles_intersection(&viewport, &(server->subRect), &viewport);
385 width = viewport.right - viewport.left;
386 height = viewport.bottom - viewport.top;
388 WINPR_ASSERT(width >= 0);
389 WINPR_ASSERT(width <= UINT16_MAX);
390 WINPR_ASSERT(height >= 0);
391 WINPR_ASSERT(height <= UINT16_MAX);
399 static BOOL shadow_client_capabilities(freerdp_peer* peer)
401 rdpShadowSubsystem* subsystem = NULL;
402 rdpShadowClient* client = NULL;
407 client = (rdpShadowClient*)peer->context;
408 WINPR_ASSERT(client);
409 WINPR_ASSERT(client->server);
411 subsystem = client->server->subsystem;
412 WINPR_ASSERT(subsystem);
414 IFCALLRET(subsystem->ClientCapabilities, ret, subsystem, client);
417 WLog_WARN(TAG,
"subsystem->ClientCapabilities failed");
422 static void shadow_reset_desktop_resize(rdpShadowClient* client)
424 WINPR_ASSERT(client);
425 client->resizeRequested = FALSE;
428 static BOOL shadow_send_desktop_resize(rdpShadowClient* client)
431 rdpUpdate* update = NULL;
432 rdpSettings* settings = NULL;
433 const freerdp_peer* peer = NULL;
435 WINPR_ASSERT(client);
437 settings = client->context.settings;
438 peer = client->context.peer;
440 WINPR_ASSERT(client->server);
441 WINPR_ASSERT(client->server->surface);
443 const UINT32 resizeWidth = client->server->surface->width;
444 const UINT32 resizeHeight = client->server->surface->height;
446 if (client->resizeRequested)
448 if ((resizeWidth == client->resizeWidth) && (resizeHeight == client->resizeHeight))
453 "detected previous resize request for resolution %" PRIu32
"x%" PRIu32
454 ", still have %" PRIu32
"x%" PRIu32
", disconnecting peer",
455 resizeWidth, resizeHeight, w, h);
460 update = client->context.update;
461 WINPR_ASSERT(update);
462 WINPR_ASSERT(update->DesktopResize);
470 rc = update->DesktopResize(update->context);
471 WLog_INFO(TAG,
"Client %s resize requested (%" PRIu32
"x%" PRIu32
"@%" PRIu32
")",
472 peer->hostname, resizeWidth, resizeHeight,
474 client->resizeRequested = TRUE;
475 client->resizeWidth = resizeWidth;
476 client->resizeHeight = resizeHeight;
481 static BOOL shadow_client_post_connect(freerdp_peer* peer)
484 rdpSettings* settings = NULL;
485 rdpShadowClient* client = NULL;
486 rdpShadowServer* server = NULL;
487 rdpShadowSubsystem* subsystem = NULL;
491 client = (rdpShadowClient*)peer->context;
492 WINPR_ASSERT(client);
494 settings = peer->context->settings;
495 WINPR_ASSERT(settings);
497 server = client->server;
498 WINPR_ASSERT(server);
500 subsystem = server->subsystem;
501 WINPR_ASSERT(subsystem);
509 const UINT32 MultifragMaxRequestSize =
511 if (MultifragMaxRequestSize < 0x3F0000)
514 settings, FreeRDP_NSCodec,
520 WLog_INFO(TAG,
"Client from %s is activated (%" PRIu32
"x%" PRIu32
"@%" PRIu32
")",
525 if (shadow_client_channels_post_connect(client) != CHANNEL_RC_OK)
528 shadow_client_mark_invalid(client, 0, NULL);
535 if (Username && Password)
543 if (subsystem->Authenticate)
545 authStatus = subsystem->Authenticate(subsystem, client, Username, Domain, Password);
550 WLog_ERR(TAG,
"client authentication failure: %d", authStatus);
555 if (subsystem->ClientConnect)
557 return subsystem->ClientConnect(subsystem, client);
564 static INLINE
void shadow_client_convert_rects(rdpShadowClient* client,
RECTANGLE_16* dst,
567 WINPR_ASSERT(client);
568 WINPR_ASSERT(client->server);
570 WINPR_ASSERT(src || (numRects == 0));
572 if (client->server->shareSubRect)
574 UINT16 offsetX = client->server->subRect.left;
575 UINT16 offsetY = client->server->subRect.top;
577 for (UINT32 i = 0; i < numRects; i++)
582 d->left = s->left + offsetX;
583 d->right = s->right + offsetX;
584 d->top = s->top + offsetY;
585 d->bottom = s->bottom + offsetY;
597 static BOOL shadow_client_refresh_request(rdpShadowClient* client)
599 wMessage message = { 0 };
602 WINPR_ASSERT(client);
603 WINPR_ASSERT(client->subsystem);
605 MsgPipe = client->subsystem->MsgPipe;
606 WINPR_ASSERT(MsgPipe);
608 message.id = SHADOW_MSG_IN_REFRESH_REQUEST_ID;
609 message.wParam = NULL;
610 message.lParam = NULL;
611 message.context = (
void*)client;
613 return MessageQueue_Dispatch(MsgPipe->In, &message);
616 static BOOL shadow_client_refresh_rect(rdpContext* context, BYTE count,
const RECTANGLE_16* areas)
618 rdpShadowClient* client = (rdpShadowClient*)context;
634 shadow_client_convert_rects(client, rects, areas, count);
635 shadow_client_mark_invalid(client, count, rects);
640 shadow_client_mark_invalid(client, 0, NULL);
643 return shadow_client_refresh_request(client);
646 static BOOL shadow_client_suppress_output(rdpContext* context, BYTE allow,
const RECTANGLE_16* area)
648 rdpShadowClient* client = (rdpShadowClient*)context;
651 WINPR_ASSERT(client);
653 client->suppressOutput = allow ? FALSE : TRUE;
659 shadow_client_convert_rects(client, ®ion, area, 1);
660 shadow_client_mark_invalid(client, 1, ®ion);
664 shadow_client_mark_invalid(client, 0, NULL);
668 return shadow_client_refresh_request(client);
671 static BOOL shadow_client_activate(freerdp_peer* peer)
673 rdpSettings* settings = NULL;
674 rdpShadowClient* client = NULL;
678 client = (rdpShadowClient*)peer->context;
679 WINPR_ASSERT(client);
681 settings = peer->context->settings;
682 WINPR_ASSERT(settings);
685 if (shadow_client_recalc_desktop_size(client))
686 return shadow_send_desktop_resize(client);
688 shadow_reset_desktop_resize(client);
689 client->activated = TRUE;
690 client->inLobby = client->mayView ? FALSE : TRUE;
692 if (shadow_encoder_reset(client->encoder) < 0)
694 WLog_ERR(TAG,
"Failed to reset encoder");
699 return shadow_client_refresh_rect(&client->context, 0, NULL);
702 static BOOL shadow_client_logon(freerdp_peer* peer,
const SEC_WINNT_AUTH_IDENTITY* identity,
708 char* password = NULL;
709 rdpSettings* settings = NULL;
711 WINPR_UNUSED(automatic);
714 WINPR_ASSERT(identity);
716 WINPR_ASSERT(peer->context);
718 settings = peer->context->settings;
719 WINPR_ASSERT(settings);
721 if (identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
724 user = ConvertWCharNToUtf8Alloc(identity->User, identity->UserLength, NULL);
726 if (identity->Domain)
727 domain = ConvertWCharNToUtf8Alloc(identity->Domain, identity->DomainLength, NULL);
729 if (identity->Password)
730 password = ConvertWCharNToUtf8Alloc(identity->Password, identity->PasswordLength, NULL);
735 user = _strdup((
char*)identity->User);
737 if (identity->Domain)
738 domain = _strdup((
char*)identity->Domain);
740 if (identity->Password)
741 password = _strdup((
char*)identity->Password);
744 if ((identity->User && !user) || (identity->Domain && !domain) ||
745 (identity->Password && !password))
772 static INLINE
void shadow_client_common_frame_acknowledge(rdpShadowClient* client, UINT32 frameId)
782 WINPR_ASSERT(client);
783 WINPR_ASSERT(client->encoder);
784 client->encoder->lastAckframeId = frameId;
787 static BOOL shadow_client_surface_frame_acknowledge(rdpContext* context, UINT32 frameId)
789 rdpShadowClient* client = (rdpShadowClient*)context;
790 shadow_client_common_frame_acknowledge(client, frameId);
794 WINPR_ASSERT(client);
795 WINPR_ASSERT(client->encoder);
796 client->encoder->queueDepth = QUEUE_DEPTH_UNAVAILABLE;
801 shadow_client_rdpgfx_frame_acknowledge(RdpgfxServerContext* context,
804 rdpShadowClient* client = NULL;
806 WINPR_ASSERT(context);
807 WINPR_ASSERT(frameAcknowledge);
809 client = (rdpShadowClient*)context->custom;
810 shadow_client_common_frame_acknowledge(client, frameAcknowledge->frameId);
812 WINPR_ASSERT(client);
813 WINPR_ASSERT(client->encoder);
814 client->encoder->queueDepth = frameAcknowledge->queueDepth;
815 return CHANNEL_RC_OK;
818 static BOOL shadow_are_caps_filtered(
const rdpSettings* settings, UINT32 caps)
820 const UINT32 capList[] = { RDPGFX_CAPVERSION_8, RDPGFX_CAPVERSION_81,
821 RDPGFX_CAPVERSION_10, RDPGFX_CAPVERSION_101,
822 RDPGFX_CAPVERSION_102, RDPGFX_CAPVERSION_103,
823 RDPGFX_CAPVERSION_104, RDPGFX_CAPVERSION_105,
824 RDPGFX_CAPVERSION_106, RDPGFX_CAPVERSION_106_ERR,
825 RDPGFX_CAPVERSION_107 };
827 WINPR_ASSERT(settings);
830 for (UINT32 x = 0; x < ARRAYSIZE(capList); x++)
832 if (caps == capList[x])
833 return (filter & (1 << x)) != 0;
839 static UINT shadow_client_send_caps_confirm(RdpgfxServerContext* context, rdpShadowClient* client,
842 WINPR_ASSERT(context);
843 WINPR_ASSERT(client);
846 WINPR_ASSERT(context->CapsConfirm);
847 UINT rc = context->CapsConfirm(context, pdu);
848 client->areGfxCapsReady = (rc == CHANNEL_RC_OK);
852 static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context, rdpShadowClient* client,
854 UINT32 capsSetCount, UINT32 capsVersion, UINT* rc)
856 const rdpSettings* srvSettings = NULL;
857 rdpSettings* clientSettings = NULL;
859 WINPR_ASSERT(context);
860 WINPR_ASSERT(client);
861 WINPR_ASSERT(capsSets || (capsSetCount == 0));
864 WINPR_ASSERT(context->rdpcontext);
865 srvSettings = context->rdpcontext->settings;
866 WINPR_ASSERT(srvSettings);
868 clientSettings = client->context.settings;
869 WINPR_ASSERT(clientSettings);
871 if (shadow_are_caps_filtered(srvSettings, capsVersion))
874 for (UINT32 index = 0; index < capsSetCount; index++)
878 if (currentCaps->version == capsVersion)
883 BOOL avc444v2 = FALSE;
886 BOOL progressive = FALSE;
891 flags = pdu.capsSet->flags;
894 (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) ? TRUE : FALSE))
897 avc444v2 = avc444 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED);
926 if (!avc444v2 && !avc444 && !avc420)
927 pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
929 *rc = shadow_client_send_caps_confirm(context, client, &pdu);
942 static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context,
945 UINT rc = ERROR_INTERNAL_ERROR;
946 const rdpSettings* srvSettings = NULL;
947 rdpSettings* clientSettings = NULL;
952 WINPR_ASSERT(context);
953 WINPR_ASSERT(capsAdvertise);
955 rdpShadowClient* client = (rdpShadowClient*)context->custom;
956 WINPR_ASSERT(client);
957 WINPR_ASSERT(context->rdpcontext);
959 srvSettings = context->rdpcontext->settings;
960 WINPR_ASSERT(srvSettings);
962 clientSettings = client->context.settings;
963 WINPR_ASSERT(clientSettings);
967 (shadow_encoder_prepare(client->encoder, FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444) >= 0);
978 if (!shadow_client_refresh_rect(&client->context, 0, NULL))
981 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
982 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_107, &rc))
985 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
986 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_106, &rc))
989 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
990 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_106_ERR,
994 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
995 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_105, &rc))
998 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
999 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_104, &rc))
1002 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1003 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_103, &rc))
1006 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1007 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_102, &rc))
1010 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1011 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_101, &rc))
1014 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1015 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_10, &rc))
1018 if (!shadow_are_caps_filtered(srvSettings, RDPGFX_CAPVERSION_81))
1020 for (UINT32 index = 0; index < capsAdvertise->capsSetCount; index++)
1022 const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
1024 if (currentCaps->version == RDPGFX_CAPVERSION_81)
1028 pdu.capsSet = ∩︀
1030 flags = pdu.capsSet->flags;
1038 (flags & RDPGFX_CAPS_FLAG_THINCLIENT) ? TRUE
1042 (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) ? TRUE
1046 #ifndef WITH_GFX_H264
1049 pdu.capsSet->flags &= ~RDPGFX_CAPS_FLAG_AVC420_ENABLED;
1055 clientSettings, FreeRDP_GfxH264,
1056 (flags & RDPGFX_CAPS_FLAG_AVC420_ENABLED) ? TRUE : FALSE))
1066 return shadow_client_send_caps_confirm(context, client, &pdu);
1071 if (!shadow_are_caps_filtered(srvSettings, RDPGFX_CAPVERSION_8))
1073 for (UINT32 index = 0; index < capsAdvertise->capsSetCount; index++)
1075 const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
1077 if (currentCaps->version == RDPGFX_CAPVERSION_8)
1081 pdu.capsSet = ∩︀
1082 flags = pdu.capsSet->flags;
1092 (flags & RDPGFX_CAPS_FLAG_THINCLIENT) ? TRUE
1096 (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) ? TRUE
1100 return shadow_client_send_caps_confirm(context, client, &pdu);
1105 return CHANNEL_RC_UNSUPPORTED_VERSION;
1111 WINPR_ASSERT(havc420);
1112 return sizeof(UINT32)
1114 * havc420->meta.numRegionRects +
1123 static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client,
const BYTE* pSrcData,
1124 UINT32 nSrcStep, UINT32 SrcFormat, UINT16 nXSrc,
1125 UINT16 nYSrc, UINT16 nWidth, UINT16 nHeight)
1128 UINT error = CHANNEL_RC_OK;
1129 const rdpContext* context = (
const rdpContext*)client;
1130 const rdpSettings* settings = NULL;
1131 rdpShadowEncoder* encoder = NULL;
1135 SYSTEMTIME sTime = { 0 };
1137 if (!context || !pSrcData)
1140 settings = context->settings;
1141 encoder = client->encoder;
1143 if (!settings || !encoder)
1146 if (client->first_frame)
1148 rfx_context_reset(encoder->rfx, nWidth, nHeight);
1149 client->first_frame = FALSE;
1152 cmdstart.frameId = shadow_encoder_create_frame_id(encoder);
1153 GetSystemTime(&sTime);
1154 cmdstart.timestamp = (UINT32)(sTime.wHour << 22U | sTime.wMinute << 16U | sTime.wSecond << 10U |
1155 sTime.wMilliseconds);
1156 cmdend.frameId = cmdstart.frameId;
1157 cmd.surfaceId = client->surfaceId;
1158 cmd.format = PIXEL_FORMAT_BGRX32;
1161 cmd.right = cmd.left + nWidth;
1162 cmd.bottom = cmd.top + nHeight;
1164 cmd.height = nHeight;
1167 #ifdef WITH_GFX_H264
1171 if (GfxAVC444 || GfxAVC444v2)
1176 BYTE version = GfxAVC444v2 ? 2 : 1;
1178 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC444) < 0)
1180 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_AVC444");
1184 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1185 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1186 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1187 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1188 regionRect.left = (UINT16)cmd.left;
1189 regionRect.top = (UINT16)cmd.top;
1190 regionRect.right = (UINT16)cmd.right;
1191 regionRect.bottom = (UINT16)cmd.bottom;
1192 rc = avc444_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
1193 version, ®ionRect, &avc444.LC, &avc444.bitstream[0].data,
1194 &avc444.bitstream[0].length, &avc444.bitstream[1].data,
1195 &avc444.bitstream[1].length, &avc444.bitstream[0].meta,
1196 &avc444.bitstream[1].meta);
1199 WLog_ERR(TAG,
"avc420_compress failed for avc444");
1206 avc444.cbAvc420EncodedBitstream1 = rdpgfx_estimate_h264_avc420(&avc444.bitstream[0]);
1207 cmd.codecId = GfxAVC444v2 ? RDPGFX_CODECID_AVC444v2 : RDPGFX_CODECID_AVC444;
1208 cmd.extra = (
void*)&avc444;
1209 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1213 free_h264_metablock(&avc444.bitstream[0].meta);
1214 free_h264_metablock(&avc444.bitstream[1].meta);
1217 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1227 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC420) < 0)
1229 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_AVC420");
1233 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1234 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1235 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1236 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1237 regionRect.left = (UINT16)cmd.left;
1238 regionRect.top = (UINT16)cmd.top;
1239 regionRect.right = (UINT16)cmd.right;
1240 regionRect.bottom = (UINT16)cmd.bottom;
1241 rc = avc420_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
1242 ®ionRect, &avc420.data, &avc420.length, &avc420.meta);
1245 WLog_ERR(TAG,
"avc420_compress failed");
1252 cmd.codecId = RDPGFX_CODECID_AVC420;
1253 cmd.extra = (
void*)&avc420;
1255 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1258 free_h264_metablock(&avc420.meta);
1262 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1274 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX) < 0)
1276 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_REMOTEFX");
1280 s = Stream_New(NULL, 1024);
1283 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1284 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1285 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1286 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1287 rect.x = (UINT16)cmd.left;
1288 rect.y = (UINT16)cmd.top;
1289 rect.width = (UINT16)cmd.right - cmd.left;
1290 rect.height = (UINT16)cmd.bottom - cmd.top;
1292 rc = rfx_compose_message(encoder->rfx, s, &rect, 1, pSrcData, nWidth, nHeight, nSrcStep);
1296 WLog_ERR(TAG,
"rfx_compose_message failed");
1297 Stream_Free(s, TRUE);
1304 const size_t pos = Stream_GetPosition(s);
1305 WINPR_ASSERT(pos <= UINT32_MAX);
1307 cmd.codecId = RDPGFX_CODECID_CAVIDEO;
1308 cmd.data = Stream_Buffer(s);
1309 cmd.length = (UINT32)pos;
1311 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1315 Stream_Free(s, TRUE);
1318 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1328 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PROGRESSIVE) < 0)
1330 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_PROGRESSIVE");
1334 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1335 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1336 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1337 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1338 regionRect.left = (UINT16)cmd.left;
1339 regionRect.top = (UINT16)cmd.top;
1340 regionRect.right = (UINT16)cmd.right;
1341 regionRect.bottom = (UINT16)cmd.bottom;
1342 region16_init(®ion);
1343 region16_union_rect(®ion, ®ion, ®ionRect);
1344 rc = progressive_compress(encoder->progressive, pSrcData, nSrcStep * nHeight, cmd.format,
1345 nWidth, nHeight, nSrcStep, ®ion, &cmd.data, &cmd.length);
1346 region16_uninit(®ion);
1349 WLog_ERR(TAG,
"progressive_compress failed");
1356 cmd.codecId = RDPGFX_CODECID_CAPROGRESSIVE;
1358 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1364 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1371 const UINT32 w = cmd.right - cmd.left;
1372 const UINT32 h = cmd.bottom - cmd.top;
1374 &pSrcData[cmd.top * nSrcStep + cmd.left * FreeRDPGetBytesPerPixel(SrcFormat)];
1375 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR) < 0)
1377 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_PLANAR");
1381 rc = freerdp_bitmap_planar_context_reset(encoder->planar, w, h);
1383 freerdp_planar_topdown_image(encoder->planar, TRUE);
1385 cmd.data = freerdp_bitmap_compress_planar(encoder->planar, src, SrcFormat, w, h, nSrcStep,
1387 WINPR_ASSERT(cmd.data || (cmd.length == 0));
1389 cmd.codecId = RDPGFX_CODECID_PLANAR;
1391 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1396 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1403 const UINT32 w = cmd.right - cmd.left;
1404 const UINT32 h = cmd.bottom - cmd.top;
1405 const UINT32 length = w * 4 * h;
1406 BYTE* data = malloc(length);
1410 rc = freerdp_image_copy_no_overlap(data, PIXEL_FORMAT_BGRA32, 0, 0, 0, w, h, pSrcData,
1411 SrcFormat, nSrcStep, cmd.left, cmd.top, NULL, 0);
1415 cmd.length = length;
1416 cmd.codecId = RDPGFX_CODECID_UNCOMPRESSED;
1418 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1423 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1430 static BOOL stream_surface_bits_supported(
const rdpSettings* settings)
1432 const UINT32 supported =
1434 return ((supported & SURFCMDS_STREAM_SURFACE_BITS) != 0);
1437 static BOOL set_surface_bits_supported(
const rdpSettings* settings)
1439 const UINT32 supported =
1441 return ((supported & SURFCMDS_SET_SURFACE_BITS) != 0);
1444 static BOOL is_surface_command_supported(
const rdpSettings* settings)
1446 if (stream_surface_bits_supported(settings))
1450 if (supported && (rfxID != 0))
1453 if (set_surface_bits_supported(settings))
1457 if (supported && (nsID != 0))
1468 static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcData,
1469 UINT32 nSrcStep, UINT16 nXSrc, UINT16 nYSrc,
1470 UINT16 nWidth, UINT16 nHeight)
1476 size_t numMessages = 0;
1478 rdpUpdate* update = NULL;
1479 rdpContext* context = (rdpContext*)client;
1480 rdpSettings* settings = NULL;
1481 rdpShadowEncoder* encoder = NULL;
1484 if (!context || !pSrcData)
1487 update = context->update;
1488 settings = context->settings;
1489 encoder = client->encoder;
1491 if (!update || !settings || !encoder)
1494 if (encoder->frameAck)
1495 frameId = shadow_encoder_create_frame_id(encoder);
1500 if (stream_surface_bits_supported(settings) &&
1505 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX) < 0)
1507 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_REMOTEFX");
1514 rect.width = nWidth;
1515 rect.height = nHeight;
1517 const UINT32 MultifragMaxRequestSize =
1519 RFX_MESSAGE_LIST* messages =
1520 rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData,
1523 nSrcStep, &numMessages, MultifragMaxRequestSize);
1526 WLog_ERR(TAG,
"rfx_encode_messages failed");
1530 cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
1531 WINPR_ASSERT(rfxID <= UINT16_MAX);
1532 cmd.bmp.codecID = (UINT16)rfxID;
1543 cmd.skipCompression = TRUE;
1545 for (
size_t i = 0; i < numMessages; i++)
1547 Stream_SetPosition(s, 0);
1549 const RFX_MESSAGE* msg = rfx_message_list_get(messages, i);
1550 if (!rfx_write_message(encoder->rfx, s, msg))
1552 WLog_ERR(TAG,
"rfx_write_message failed");
1557 WINPR_ASSERT(Stream_GetPosition(s) <= UINT32_MAX);
1558 cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
1559 cmd.bmp.bitmapData = Stream_Buffer(s);
1560 first = (i == 0) ? TRUE : FALSE;
1561 last = ((i + 1) == numMessages) ? TRUE : FALSE;
1563 if (!encoder->frameAck)
1564 IFCALLRET(update->SurfaceBits, ret, update->context, &cmd);
1566 IFCALLRET(update->SurfaceFrameBits, ret, update->context, &cmd, first, last,
1571 WLog_ERR(TAG,
"Send surface bits(RemoteFxCodec) failed");
1576 rfx_message_list_free(messages);
1578 else if (set_surface_bits_supported(settings) &&
1581 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_NSCODEC) < 0)
1583 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_NSCODEC");
1588 Stream_SetPosition(s, 0);
1589 pSrcData = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
1590 nsc_compose_message(encoder->nsc, s, pSrcData, nWidth, nHeight, nSrcStep);
1591 cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
1593 WINPR_ASSERT(nsID <= UINT16_MAX);
1594 cmd.bmp.codecID = (UINT16)nsID;
1595 cmd.destLeft = nXSrc;
1596 cmd.destTop = nYSrc;
1597 cmd.destRight = cmd.destLeft + nWidth;
1598 cmd.destBottom = cmd.destTop + nHeight;
1599 cmd.bmp.width = nWidth;
1600 cmd.bmp.height = nHeight;
1601 WINPR_ASSERT(Stream_GetPosition(s) <= UINT32_MAX);
1602 cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
1603 cmd.bmp.bitmapData = Stream_Buffer(s);
1607 if (!encoder->frameAck)
1608 IFCALLRET(update->SurfaceBits, ret, update->context, &cmd);
1610 IFCALLRET(update->SurfaceFrameBits, ret, update->context, &cmd, first, last, frameId);
1614 WLog_ERR(TAG,
"Send surface bits(NSCodec) failed");
1626 static BOOL shadow_client_send_bitmap_update(rdpShadowClient* client, BYTE* pSrcData,
1627 UINT32 nSrcStep, UINT16 nXSrc, UINT16 nYSrc,
1628 UINT16 nWidth, UINT16 nHeight)
1632 BYTE* buffer = NULL;
1639 UINT32 SrcFormat = 0;
1641 rdpContext* context = (rdpContext*)client;
1642 UINT32 totalBitmapSize = 0;
1643 UINT32 updateSizeEstimate = 0;
1647 if (!context || !pSrcData)
1650 rdpUpdate* update = context->update;
1651 rdpSettings* settings = context->settings;
1652 rdpShadowEncoder* encoder = client->encoder;
1654 if (!update || !settings || !encoder)
1657 const UINT32 maxUpdateSize =
1661 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED) < 0)
1663 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_INTERLEAVED");
1669 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR) < 0)
1671 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_PLANAR");
1676 SrcFormat = PIXEL_FORMAT_BGRX32;
1678 if ((nXSrc % 4) != 0)
1680 nWidth += (nXSrc % 4);
1681 nXSrc -= (nXSrc % 4);
1684 if ((nYSrc % 4) != 0)
1686 nHeight += (nYSrc % 4);
1687 nYSrc -= (nYSrc % 4);
1690 rows = (nHeight / 64) + ((nHeight % 64) ? 1 : 0);
1691 cols = (nWidth / 64) + ((nWidth % 64) ? 1 : 0);
1693 totalBitmapSize = 0;
1694 bitmapUpdate.number = rows * cols;
1699 bitmapUpdate.rectangles = bitmapData;
1701 if ((nWidth % 4) != 0)
1703 nWidth += (4 - (nWidth % 4));
1706 if ((nHeight % 4) != 0)
1708 nHeight += (4 - (nHeight % 4));
1711 for (yIdx = 0; yIdx < rows; yIdx++)
1713 for (xIdx = 0; xIdx < cols; xIdx++)
1715 bitmap = &bitmapData[k];
1717 bitmap->height = 64;
1718 bitmap->destLeft = nXSrc + (xIdx * 64);
1719 bitmap->destTop = nYSrc + (yIdx * 64);
1721 if (((INT64)bitmap->destLeft + bitmap->width) > (nXSrc + nWidth))
1722 bitmap->width = (UINT32)(nXSrc + nWidth) - bitmap->destLeft;
1724 if (((INT64)bitmap->destTop + bitmap->height) > (nYSrc + nHeight))
1725 bitmap->height = (UINT32)(nYSrc + nHeight) - bitmap->destTop;
1727 bitmap->destRight = bitmap->destLeft + bitmap->width - 1;
1728 bitmap->destBottom = bitmap->destTop + bitmap->height - 1;
1729 bitmap->compressed = TRUE;
1731 if ((bitmap->width < 4) || (bitmap->height < 4))
1737 UINT32 bytesPerPixel = (bitsPerPixel + 7) / 8;
1738 DstSize = 64 * 64 * 4;
1739 buffer = encoder->grid[k];
1740 interleaved_compress(encoder->interleaved, buffer, &DstSize, bitmap->width,
1741 bitmap->height, pSrcData, SrcFormat, nSrcStep,
1742 bitmap->destLeft, bitmap->destTop, NULL, bitsPerPixel);
1743 bitmap->bitmapDataStream = buffer;
1744 bitmap->bitmapLength = DstSize;
1745 bitmap->bitsPerPixel = bitsPerPixel;
1746 bitmap->cbScanWidth = bitmap->width * bytesPerPixel;
1747 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * bytesPerPixel;
1752 buffer = encoder->grid[k];
1753 data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)];
1756 freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat, bitmap->width,
1757 bitmap->height, nSrcStep, buffer, &dstSize);
1758 bitmap->bitmapDataStream = buffer;
1759 bitmap->bitmapLength = dstSize;
1760 bitmap->bitsPerPixel = 32;
1761 bitmap->cbScanWidth = bitmap->width * 4;
1762 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * 4;
1765 bitmap->cbCompFirstRowSize = 0;
1766 bitmap->cbCompMainBodySize = bitmap->bitmapLength;
1767 totalBitmapSize += bitmap->bitmapLength;
1772 bitmapUpdate.number = k;
1773 updateSizeEstimate = totalBitmapSize + (k * bitmapUpdate.number) + 16;
1775 if (updateSizeEstimate > maxUpdateSize)
1779 UINT32 updateSize = 0;
1780 UINT32 newUpdateSize = 0;
1786 if (!fragBitmapData)
1788 WLog_ERR(TAG,
"Failed to allocate memory for fragBitmapData");
1793 bitmapUpdate.rectangles = fragBitmapData;
1799 newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16);
1801 if (newUpdateSize < maxUpdateSize)
1803 CopyMemory(&fragBitmapData[j++], &bitmapData[i++],
sizeof(
BITMAP_DATA));
1804 updateSize = newUpdateSize;
1807 if ((newUpdateSize >= maxUpdateSize) || (i + 1) >= k)
1809 bitmapUpdate.number = j;
1810 ret = BitmapUpdateProxy(update, context, &bitmapUpdate);
1820 free(fragBitmapData);
1824 ret = BitmapUpdateProxy(update, context, &bitmapUpdate);
1837 static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
1844 rdpContext* context = (rdpContext*)client;
1845 rdpSettings* settings = NULL;
1846 rdpShadowServer* server = NULL;
1847 rdpShadowSurface* surface = NULL;
1851 BYTE* pSrcData = NULL;
1852 UINT32 nSrcStep = 0;
1853 UINT32 SrcFormat = 0;
1854 UINT32 numRects = 0;
1857 if (!context || !pStatus)
1860 settings = context->settings;
1861 server = client->server;
1863 if (!settings || !server)
1866 surface = client->inLobby ? server->lobby : server->surface;
1871 EnterCriticalSection(&(client->lock));
1872 region16_init(&invalidRegion);
1873 region16_copy(&invalidRegion, &(client->invalidRegion));
1874 region16_clear(&(client->invalidRegion));
1875 LeaveCriticalSection(&(client->lock));
1877 EnterCriticalSection(&surface->lock);
1878 rects = region16_rects(&(surface->invalidRegion), &numRects);
1880 for (UINT32 index = 0; index < numRects; index++)
1881 region16_union_rect(&invalidRegion, &invalidRegion, &rects[index]);
1883 surfaceRect.left = 0;
1884 surfaceRect.top = 0;
1885 WINPR_ASSERT(surface->width <= UINT16_MAX);
1886 WINPR_ASSERT(surface->height <= UINT16_MAX);
1887 surfaceRect.right = (UINT16)surface->width;
1888 surfaceRect.bottom = (UINT16)surface->height;
1889 region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
1891 if (server->shareSubRect)
1893 region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
1896 if (region16_is_empty(&invalidRegion))
1902 extents = region16_extents(&invalidRegion);
1903 nXSrc = extents->left;
1904 nYSrc = extents->top;
1905 nWidth = extents->right - extents->left;
1906 nHeight = extents->bottom - extents->top;
1907 pSrcData = surface->data;
1908 nSrcStep = surface->scanline;
1909 SrcFormat = surface->format;
1912 if (server->shareSubRect)
1916 subX = server->subRect.left;
1917 subY = server->subRect.top;
1920 WINPR_ASSERT(nXSrc >= 0);
1921 WINPR_ASSERT(nXSrc <= UINT16_MAX);
1922 WINPR_ASSERT(nYSrc >= 0);
1923 WINPR_ASSERT(nYSrc <= UINT16_MAX);
1924 pSrcData = &pSrcData[((UINT16)subY * nSrcStep) + ((UINT16)subX * 4U)];
1933 if (pStatus->gfxOpened && client->areGfxCapsReady)
1940 if (!pStatus->gfxSurfaceCreated)
1943 if (!(ret = shadow_client_rdpgfx_reset_graphic(client)))
1946 if (!(ret = shadow_client_rdpgfx_new_surface(client)))
1949 pStatus->gfxSurfaceCreated = TRUE;
1952 WINPR_ASSERT(nWidth >= 0);
1953 WINPR_ASSERT(nWidth <= UINT16_MAX);
1954 WINPR_ASSERT(nHeight >= 0);
1955 WINPR_ASSERT(nHeight <= UINT16_MAX);
1956 ret = shadow_client_send_surface_gfx(client, pSrcData, nSrcStep, SrcFormat, 0, 0,
1957 (UINT16)nWidth, (UINT16)nHeight);
1964 else if (is_surface_command_supported(settings))
1966 WINPR_ASSERT(nXSrc >= 0);
1967 WINPR_ASSERT(nXSrc <= UINT16_MAX);
1968 WINPR_ASSERT(nYSrc >= 0);
1969 WINPR_ASSERT(nYSrc <= UINT16_MAX);
1970 WINPR_ASSERT(nWidth >= 0);
1971 WINPR_ASSERT(nWidth <= UINT16_MAX);
1972 WINPR_ASSERT(nHeight >= 0);
1973 WINPR_ASSERT(nHeight <= UINT16_MAX);
1974 ret = shadow_client_send_surface_bits(client, pSrcData, nSrcStep, (UINT16)nXSrc,
1975 (UINT16)nYSrc, (UINT16)nWidth, (UINT16)nHeight);
1979 WINPR_ASSERT(nXSrc >= 0);
1980 WINPR_ASSERT(nXSrc <= UINT16_MAX);
1981 WINPR_ASSERT(nYSrc >= 0);
1982 WINPR_ASSERT(nYSrc <= UINT16_MAX);
1983 WINPR_ASSERT(nWidth >= 0);
1984 WINPR_ASSERT(nWidth <= UINT16_MAX);
1985 WINPR_ASSERT(nHeight >= 0);
1986 WINPR_ASSERT(nHeight <= UINT16_MAX);
1987 ret = shadow_client_send_bitmap_update(client, pSrcData, nSrcStep, (UINT16)nXSrc,
1988 (UINT16)nYSrc, (UINT16)nWidth, (UINT16)nHeight);
1992 LeaveCriticalSection(&surface->lock);
1993 region16_uninit(&invalidRegion);
2004 static BOOL shadow_client_send_resize(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
2006 rdpContext* context = (rdpContext*)client;
2007 rdpSettings* settings = NULL;
2008 freerdp_peer* peer = NULL;
2010 if (!context || !pStatus)
2013 peer = context->peer;
2014 settings = context->settings;
2016 if (!peer || !settings)
2024 client->activated = FALSE;
2027 if (pStatus->gfxSurfaceCreated)
2029 if (!shadow_client_rdpgfx_release_surface(client))
2032 pStatus->gfxSurfaceCreated = FALSE;
2036 if (!shadow_send_desktop_resize(client))
2038 shadow_reset_desktop_resize(client);
2041 EnterCriticalSection(&(client->lock));
2042 region16_clear(&(client->invalidRegion));
2043 LeaveCriticalSection(&(client->lock));
2053 static BOOL shadow_client_surface_update(rdpShadowClient* client,
REGION16* region)
2055 UINT32 numRects = 0;
2057 rects = region16_rects(region, &numRects);
2058 shadow_client_mark_invalid(client, numRects, rects);
2068 static INLINE BOOL shadow_client_no_surface_update(rdpShadowClient* client,
2069 SHADOW_GFX_STATUS* pStatus)
2071 rdpShadowServer* server = NULL;
2072 rdpShadowSurface* surface = NULL;
2073 WINPR_UNUSED(pStatus);
2074 WINPR_ASSERT(client);
2075 server = client->server;
2076 WINPR_ASSERT(server);
2077 surface = client->inLobby ? server->lobby : server->surface;
2078 EnterCriticalSection(&surface->lock);
2079 const BOOL rc = shadow_client_surface_update(client, &(surface->invalidRegion));
2080 LeaveCriticalSection(&surface->lock);
2084 static int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message)
2086 rdpContext* context = (rdpContext*)client;
2087 rdpUpdate* update = NULL;
2089 WINPR_ASSERT(message);
2090 WINPR_ASSERT(context);
2091 update = context->update;
2092 WINPR_ASSERT(update);
2096 switch (message->id)
2098 case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
2103 pointerPosition.xPos = msg->xPos;
2104 pointerPosition.yPos = msg->yPos;
2106 WINPR_ASSERT(client->server);
2107 if (client->server->shareSubRect)
2109 pointerPosition.xPos -= client->server->subRect.left;
2110 pointerPosition.yPos -= client->server->subRect.top;
2113 if (client->activated)
2115 if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY))
2117 WINPR_ASSERT(update->pointer);
2118 IFCALL(update->pointer->PointerPosition, context, &pointerPosition);
2119 client->pointerX = msg->xPos;
2120 client->pointerY = msg->yPos;
2127 case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
2136 pointerNew.xorBpp = 24;
2137 pointerColor = &(pointerNew.colorPtrAttr);
2138 pointerColor->cacheIndex = 0;
2139 pointerColor->hotSpotX = msg->xHot;
2140 pointerColor->hotSpotY = msg->yHot;
2141 pointerColor->width = msg->width;
2142 pointerColor->height = msg->height;
2143 pointerColor->lengthAndMask = msg->lengthAndMask;
2144 pointerColor->lengthXorMask = msg->lengthXorMask;
2145 pointerColor->xorMaskData = msg->xorMaskData;
2146 pointerColor->andMaskData = msg->andMaskData;
2147 pointerCached.cacheIndex = pointerColor->cacheIndex;
2149 if (client->activated)
2151 IFCALL(update->pointer->PointerNew, context, &pointerNew);
2152 IFCALL(update->pointer->PointerCached, context, &pointerCached);
2158 case SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES_ID:
2165 if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
2167 client->rdpsnd->src_format = msg->audio_format;
2168 IFCALL(client->rdpsnd->SendSamples, client->rdpsnd, msg->buf, msg->nFrames,
2175 case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
2180 if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
2182 IFCALL(client->rdpsnd->SetVolume, client->rdpsnd, msg->left, msg->right);
2189 WLog_ERR(TAG,
"Unknown message id: %" PRIu32
"", message->id);
2193 shadow_client_free_queued_message(message);
2197 static DWORD WINAPI shadow_client_thread(LPVOID arg)
2199 rdpShadowClient* client = (rdpShadowClient*)arg;
2202 wMessage message = { 0 };
2203 wMessage pointerPositionMsg = { 0 };
2204 wMessage pointerAlphaMsg = { 0 };
2205 wMessage audioVolumeMsg = { 0 };
2206 HANDLE ChannelEvent = 0;
2207 void* UpdateSubscriber = NULL;
2208 HANDLE UpdateEvent = 0;
2209 freerdp_peer* peer = NULL;
2210 rdpContext* context = NULL;
2211 rdpSettings* settings = NULL;
2212 rdpShadowServer* server = NULL;
2213 rdpShadowSubsystem* subsystem = NULL;
2214 wMessageQueue* MsgQueue = NULL;
2216 SHADOW_GFX_STATUS gfxstatus = { 0 };
2217 rdpUpdate* update = NULL;
2219 WINPR_ASSERT(client);
2221 MsgQueue = client->MsgQueue;
2222 WINPR_ASSERT(MsgQueue);
2224 server = client->server;
2225 WINPR_ASSERT(server);
2226 subsystem = server->subsystem;
2227 context = (rdpContext*)client;
2228 peer = context->peer;
2230 WINPR_ASSERT(peer->context);
2232 settings = peer->context->settings;
2233 WINPR_ASSERT(settings);
2235 peer->Capabilities = shadow_client_capabilities;
2236 peer->PostConnect = shadow_client_post_connect;
2237 peer->Activate = shadow_client_activate;
2238 peer->Logon = shadow_client_logon;
2239 shadow_input_register_callbacks(peer->context->input);
2241 rc = peer->Initialize(peer);
2245 update = peer->context->update;
2246 WINPR_ASSERT(update);
2248 update->RefreshRect = shadow_client_refresh_rect;
2249 update->SuppressOutput = shadow_client_suppress_output;
2250 update->SurfaceFrameAcknowledge = shadow_client_surface_frame_acknowledge;
2252 if ((!client->vcm) || (!subsystem->updateEvent))
2255 UpdateSubscriber = shadow_multiclient_get_subscriber(subsystem->updateEvent);
2257 if (!UpdateSubscriber)
2260 UpdateEvent = shadow_multiclient_getevent(UpdateSubscriber);
2261 WINPR_ASSERT(UpdateEvent);
2263 ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm);
2264 WINPR_ASSERT(ChannelEvent);
2276 HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
2278 events[nCount++] = UpdateEvent;
2280 DWORD tmp = peer->GetEventHandles(peer, &events[nCount], 64 - nCount);
2284 WLog_ERR(TAG,
"Failed to get FreeRDP transport event handles");
2290 events[nCount++] = ChannelEvent;
2291 events[nCount++] = MessageQueue_Event(MsgQueue);
2293 #if defined(CHANNEL_RDPGFX_SERVER)
2294 HANDLE gfxevent = rdpgfx_server_get_event_handle(client->rdpgfx);
2297 events[nCount++] = gfxevent;
2300 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
2302 if (status == WAIT_FAILED)
2305 if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
2314 if (client->activated && !client->suppressOutput)
2319 if (shadow_client_recalc_desktop_size(client))
2322 if (!shadow_client_send_resize(client, &gfxstatus))
2324 WLog_ERR(TAG,
"Failed to send resize message");
2331 if (!shadow_client_send_surface_update(client, &gfxstatus))
2333 WLog_ERR(TAG,
"Failed to send surface update");
2341 if (!shadow_client_no_surface_update(client, &gfxstatus))
2343 WLog_ERR(TAG,
"Failed to handle surface update");
2352 (void)shadow_multiclient_consume(UpdateSubscriber);
2355 WINPR_ASSERT(peer->CheckFileDescriptor);
2356 if (!peer->CheckFileDescriptor(peer))
2358 WLog_ERR(TAG,
"Failed to check FreeRDP file descriptor");
2362 if (client->activated &&
2363 WTSVirtualChannelManagerIsChannelJoined(client->vcm, DRDYNVC_SVC_CHANNEL_NAME))
2365 switch (WTSVirtualChannelManagerGetDrdynvcState(client->vcm))
2368 case DRDYNVC_STATE_NONE:
2371 if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
2373 WLog_ERR(TAG,
"Failed to initialize drdynvc channel");
2379 case DRDYNVC_STATE_READY:
2380 #if defined(CHANNEL_AUDIN_SERVER)
2381 if (client->audin && !IFCALLRESULT(TRUE, client->audin->IsOpen, client->audin))
2383 if (!IFCALLRESULT(FALSE, client->audin->Open, client->audin))
2385 WLog_ERR(TAG,
"Failed to initialize audin channel");
2393 client->rdpgfx && !gfxstatus.gfxOpened)
2395 client->rdpgfx->FrameAcknowledge = shadow_client_rdpgfx_frame_acknowledge;
2396 client->rdpgfx->CapsAdvertise = shadow_client_rdpgfx_caps_advertise;
2398 if (!client->rdpgfx->Open(client->rdpgfx))
2400 WLog_WARN(TAG,
"Failed to open GraphicsPipeline");
2402 FreeRDP_SupportGraphicsPipeline, FALSE))
2407 gfxstatus.gfxOpened = TRUE;
2408 WLog_INFO(TAG,
"Gfx Pipeline Opened");
2419 if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
2421 if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
2423 WLog_ERR(TAG,
"WTSVirtualChannelManagerCheckFileDescriptor failure");
2428 #if defined(CHANNEL_RDPGFX_SERVER)
2431 if (WaitForSingleObject(gfxevent, 0) == WAIT_OBJECT_0)
2433 rdpgfx_server_handle_messages(client->rdpgfx);
2438 if (WaitForSingleObject(MessageQueue_Event(MsgQueue), 0) == WAIT_OBJECT_0)
2441 pointerPositionMsg.id = 0;
2442 pointerPositionMsg.Free = NULL;
2443 pointerAlphaMsg.id = 0;
2444 pointerAlphaMsg.Free = NULL;
2445 audioVolumeMsg.id = 0;
2446 audioVolumeMsg.Free = NULL;
2448 while (MessageQueue_Peek(MsgQueue, &message, TRUE))
2450 if (message.id == WMQ_QUIT)
2457 case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
2459 shadow_client_free_queued_message(&pointerPositionMsg);
2460 pointerPositionMsg = message;
2463 case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
2465 shadow_client_free_queued_message(&pointerAlphaMsg);
2466 pointerAlphaMsg = message;
2469 case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
2471 shadow_client_free_queued_message(&audioVolumeMsg);
2472 audioVolumeMsg = message;
2476 shadow_client_subsystem_process_message(client, &message);
2481 if (message.id == WMQ_QUIT)
2484 shadow_client_free_queued_message(&pointerPositionMsg);
2485 shadow_client_free_queued_message(&pointerAlphaMsg);
2486 shadow_client_free_queued_message(&audioVolumeMsg);
2492 if (pointerPositionMsg.id)
2494 shadow_client_subsystem_process_message(client, &pointerPositionMsg);
2497 if (pointerAlphaMsg.id)
2499 shadow_client_subsystem_process_message(client, &pointerAlphaMsg);
2502 if (audioVolumeMsg.id)
2504 shadow_client_subsystem_process_message(client, &audioVolumeMsg);
2513 #if defined(CHANNEL_AUDIN_SERVER)
2514 if (client->audin && !IFCALLRESULT(TRUE, client->audin->IsOpen, client->audin))
2516 if (!IFCALLRESULT(FALSE, client->audin->Close, client->audin))
2518 WLog_WARN(TAG,
"AUDIN shutdown failure!");
2523 if (gfxstatus.gfxOpened)
2525 if (gfxstatus.gfxSurfaceCreated)
2527 if (!shadow_client_rdpgfx_release_surface(client))
2528 WLog_WARN(TAG,
"GFX release surface failure!");
2531 WINPR_ASSERT(client->rdpgfx);
2532 WINPR_ASSERT(client->rdpgfx->Close);
2533 rc = client->rdpgfx->Close(client->rdpgfx);
2537 shadow_client_channels_free(client);
2539 if (UpdateSubscriber)
2541 shadow_multiclient_release_subscriber(UpdateSubscriber);
2542 UpdateSubscriber = NULL;
2545 if (peer->connected && subsystem->ClientDisconnect)
2547 subsystem->ClientDisconnect(subsystem, client);
2551 WINPR_ASSERT(peer->Disconnect);
2552 peer->Disconnect(peer);
2553 freerdp_peer_context_free(peer);
2554 freerdp_peer_free(peer);
2559 BOOL shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
2561 rdpShadowClient* client = NULL;
2562 rdpShadowServer* server = NULL;
2564 if (!listener || !peer)
2567 server = (rdpShadowServer*)listener->info;
2568 WINPR_ASSERT(server);
2570 peer->ContextExtra = (
void*)server;
2571 peer->ContextSize =
sizeof(rdpShadowClient);
2572 peer->ContextNew = shadow_client_context_new;
2573 peer->ContextFree = shadow_client_context_free;
2575 if (!freerdp_peer_context_new_ex(peer, server->settings))
2578 client = (rdpShadowClient*)peer->context;
2579 WINPR_ASSERT(client);
2581 if (!(client->thread = CreateThread(NULL, 0, shadow_client_thread, client, 0, NULL)))
2583 freerdp_peer_context_free(peer);
2589 (void)CloseHandle(client->thread);
2590 client->thread = NULL;
2596 static void shadow_msg_out_addref(wMessage* message)
2598 SHADOW_MSG_OUT* msg = NULL;
2600 WINPR_ASSERT(message);
2601 msg = (SHADOW_MSG_OUT*)message->wParam;
2604 InterlockedIncrement(&(msg->refCount));
2607 static void shadow_msg_out_release(wMessage* message)
2609 SHADOW_MSG_OUT* msg = NULL;
2611 WINPR_ASSERT(message);
2612 msg = (SHADOW_MSG_OUT*)message->wParam;
2615 if (InterlockedDecrement(&(msg->refCount)) <= 0)
2617 IFCALL(msg->Free, message->id, msg);
2621 static BOOL shadow_client_dispatch_msg(rdpShadowClient* client, wMessage* message)
2623 if (!client || !message)
2627 shadow_msg_out_addref(message);
2629 WINPR_ASSERT(client->MsgQueue);
2630 if (MessageQueue_Dispatch(client->MsgQueue, message))
2635 shadow_msg_out_release(message);
2640 BOOL shadow_client_post_msg(rdpShadowClient* client,
void* context, UINT32 type,
2641 SHADOW_MSG_OUT* msg,
void* lParam)
2643 wMessage message = { 0 };
2644 message.context = context;
2646 message.wParam = (
void*)msg;
2647 message.lParam = lParam;
2648 message.Free = shadow_msg_out_release;
2649 return shadow_client_dispatch_msg(client, &message);
2652 int shadow_client_boardcast_msg(rdpShadowServer* server,
void* context, UINT32 type,
2653 SHADOW_MSG_OUT* msg,
void* lParam)
2655 wMessage message = { 0 };
2656 rdpShadowClient* client = NULL;
2659 WINPR_ASSERT(server);
2662 message.context = context;
2664 message.wParam = (
void*)msg;
2665 message.lParam = lParam;
2666 message.Free = shadow_msg_out_release;
2669 shadow_msg_out_addref(&message);
2671 WINPR_ASSERT(server->clients);
2672 ArrayList_Lock(server->clients);
2674 for (
size_t index = 0; index < ArrayList_Count(server->clients); index++)
2676 client = (rdpShadowClient*)ArrayList_GetItem(server->clients, index);
2678 if (shadow_client_dispatch_msg(client, &message))
2684 ArrayList_Unlock(server->clients);
2686 shadow_msg_out_release(&message);
2690 int shadow_client_boardcast_quit(rdpShadowServer* server,
int nExitCode)
2692 wMessageQueue* queue = NULL;
2695 WINPR_ASSERT(server);
2696 WINPR_ASSERT(server->clients);
2698 ArrayList_Lock(server->clients);
2700 for (
size_t index = 0; index < ArrayList_Count(server->clients); index++)
2702 queue = ((rdpShadowClient*)ArrayList_GetItem(server->clients, index))->MsgQueue;
2704 if (MessageQueue_PostQuit(queue, nExitCode))
2710 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.