21#include <freerdp/config.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(client, bitmap) \
54 BitmapUpdateProxyEx((client), (bitmap), __FILE__, __LINE__, __func__)
56static BOOL BitmapUpdateProxyEx(rdpShadowClient* client,
const BITMAP_UPDATE* bitmap,
57 const char* file,
size_t line,
const char* fkt)
62 rdpShadowServer* server = client->server;
65 rdpContext* context = (rdpContext*)client;
67 rdpUpdate* update = context->update;
70 if (server->SupportMultiRectBitmapUpdates)
72 const BOOL rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, bitmap);
75 const DWORD log_level = WLOG_ERROR;
76 wLog* log = WLog_Get(TAG);
77 if (WLog_IsLevelActive(log, log_level))
79 WLog_PrintTextMessage(log, log_level, line, file, fkt,
80 "BitmapUpdate[count %" PRIu32
"] failed", bitmap->number);
87 for (UINT32 x = 0; x < bitmap->number; x++)
93 cur.skipCompression = bitmap->skipCompression;
94 const BOOL rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, &cur);
97 const DWORD log_level = WLOG_ERROR;
98 wLog* log = WLog_Get(TAG);
99 if (WLog_IsLevelActive(log, log_level))
101 WLog_PrintTextMessage(log, log_level, line, file, fkt,
102 "BitmapUpdate[count 1, at %" PRIu32
"] failed", x);
113static inline BOOL shadow_client_rdpgfx_new_surface(rdpShadowClient* client)
115 UINT error = CHANNEL_RC_OK;
118 RdpgfxServerContext* context =
nullptr;
119 rdpSettings* settings =
nullptr;
121 WINPR_ASSERT(client);
122 context = client->rdpgfx;
123 WINPR_ASSERT(context);
124 settings = ((rdpContext*)client)->settings;
125 WINPR_ASSERT(settings);
131 createSurface.pixelFormat = GFX_PIXEL_FORMAT_XRGB_8888;
132 createSurface.surfaceId = client->surfaceId;
133 surfaceToOutput.outputOriginX = 0;
134 surfaceToOutput.outputOriginY = 0;
135 surfaceToOutput.surfaceId = client->surfaceId;
136 surfaceToOutput.reserved = 0;
137 IFCALLRET(context->CreateSurface, error, context, &createSurface);
141 WLog_ERR(TAG,
"CreateSurface failed with error %" PRIu32
"", error);
145 IFCALLRET(context->MapSurfaceToOutput, error, context, &surfaceToOutput);
149 WLog_ERR(TAG,
"MapSurfaceToOutput failed with error %" PRIu32
"", error);
157static inline BOOL shadow_client_rdpgfx_release_surface(rdpShadowClient* client)
159 UINT error = CHANNEL_RC_OK;
161 RdpgfxServerContext* context =
nullptr;
163 WINPR_ASSERT(client);
165 context = client->rdpgfx;
166 WINPR_ASSERT(context);
168 pdu.surfaceId = client->surfaceId++;
169 IFCALLRET(context->DeleteSurface, error, context, &pdu);
173 WLog_ERR(TAG,
"DeleteSurface failed with error %" PRIu32
"", error);
181static inline BOOL shadow_client_rdpgfx_reset_graphic(rdpShadowClient* client)
183 UINT error = CHANNEL_RC_OK;
185 RdpgfxServerContext* context =
nullptr;
186 rdpSettings* settings =
nullptr;
188 WINPR_ASSERT(client);
189 WINPR_ASSERT(client->rdpgfx);
191 context = client->rdpgfx;
192 WINPR_ASSERT(context);
194 settings = client->context.settings;
195 WINPR_ASSERT(settings);
199 pdu.monitorCount = client->subsystem->numMonitors;
200 pdu.monitorDefArray = client->subsystem->monitors;
201 IFCALLRET(context->ResetGraphics, error, context, &pdu);
205 WLog_ERR(TAG,
"ResetGraphics failed with error %" PRIu32
"", error);
209 client->first_frame = TRUE;
213static inline void shadow_client_free_queued_message(
void* obj)
215 wMessage* message = (wMessage*)obj;
217 WINPR_ASSERT(message);
220 message->Free(message);
221 message->Free =
nullptr;
225static void shadow_client_context_free(freerdp_peer* peer, rdpContext* context)
227 rdpShadowClient* client = (rdpShadowClient*)context;
228 rdpShadowServer* server =
nullptr;
234 server = client->server;
235 if (server && server->clients)
236 ArrayList_Remove(server->clients, (
void*)client);
238 shadow_encoder_free(client->encoder);
241 MessageQueue_Free(client->MsgQueue);
242 WTSCloseServer(client->vcm);
243 region16_uninit(&(client->invalidRegion));
244 DeleteCriticalSection(&(client->lock));
246 client->MsgQueue =
nullptr;
247 client->encoder =
nullptr;
248 client->vcm =
nullptr;
252static BOOL shadow_client_context_new(freerdp_peer* peer, rdpContext* context)
255 const char bind_address[] =
"bind-address,";
256 rdpShadowClient* client = (rdpShadowClient*)context;
257 rdpSettings* settings =
nullptr;
258 const rdpSettings* srvSettings =
nullptr;
259 rdpShadowServer* server =
nullptr;
260 const wObject cb = {
nullptr,
nullptr,
nullptr, shadow_client_free_queued_message,
nullptr };
262 WINPR_ASSERT(client);
264 WINPR_ASSERT(peer->context);
266 server = (rdpShadowServer*)peer->ContextExtra;
267 WINPR_ASSERT(server);
269 srvSettings = server->settings;
270 WINPR_ASSERT(srvSettings);
272 client->surfaceId = 1;
273 client->server = server;
274 client->subsystem = server->subsystem;
275 WINPR_ASSERT(client->subsystem);
277 settings = peer->context->settings;
278 WINPR_ASSERT(settings);
290 settings, FreeRDP_RemoteFxRlgrMode,
300 settings, FreeRDP_SupportGraphicsPipeline,
315 if (server->ipcSocket && (strncmp(bind_address, server->ipcSocket,
316 strnlen(bind_address,
sizeof(bind_address))) != 0))
324 client->inLobby = TRUE;
325 client->mayView = server->mayView;
326 client->mayInteract = server->mayInteract;
328 if (!InitializeCriticalSectionAndSpinCount(&(client->lock), 4000))
331 region16_init(&(client->invalidRegion));
332 client->vcm = WTSOpenServerA((LPSTR)peer->context);
334 if (!client->vcm || client->vcm == INVALID_HANDLE_VALUE)
337 if (!(client->MsgQueue = MessageQueue_New(&cb)))
340 if (!(client->encoder = shadow_encoder_new(client)))
343 if (!ArrayList_Append(server->clients, (
void*)client))
349 shadow_client_context_free(peer, context);
353static inline void shadow_client_mark_invalid(rdpShadowClient* client, UINT32 numRects,
356 WINPR_ASSERT(client);
357 WINPR_ASSERT(rects || (numRects == 0));
359 rdpSettings* settings = client->context.settings;
360 WINPR_ASSERT(settings);
362 EnterCriticalSection(&(client->lock));
367 for (UINT32 index = 0; index < numRects; index++)
369 if (!region16_union_rect(&(client->invalidRegion), &(client->invalidRegion),
381 if (!region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &screenRegion))
385 LeaveCriticalSection(&(client->lock));
395static inline BOOL shadow_client_recalc_desktop_size(rdpShadowClient* client)
399 rdpShadowServer* server =
nullptr;
400 rdpSettings* settings =
nullptr;
403 WINPR_ASSERT(client);
404 server = client->server;
405 settings = client->context.settings;
407 WINPR_ASSERT(server);
408 WINPR_ASSERT(server->surface);
409 WINPR_ASSERT(settings);
411 WINPR_ASSERT(server->surface->width <= UINT16_MAX);
412 WINPR_ASSERT(server->surface->height <= UINT16_MAX);
413 viewport.right = (UINT16)server->surface->width;
414 viewport.bottom = (UINT16)server->surface->height;
416 if (server->shareSubRect)
418 if (!rectangles_intersection(&viewport, &(server->subRect), &viewport))
422 width = viewport.right - viewport.left;
423 height = viewport.bottom - viewport.top;
425 WINPR_ASSERT(width >= 0);
426 WINPR_ASSERT(width <= UINT16_MAX);
427 WINPR_ASSERT(height >= 0);
428 WINPR_ASSERT(height <= UINT16_MAX);
434static BOOL shadow_client_capabilities(freerdp_peer* peer)
436 rdpShadowSubsystem* subsystem =
nullptr;
437 rdpShadowClient* client =
nullptr;
442 client = (rdpShadowClient*)peer->context;
443 WINPR_ASSERT(client);
444 WINPR_ASSERT(client->server);
446 subsystem = client->server->subsystem;
447 WINPR_ASSERT(subsystem);
449 IFCALLRET(subsystem->ClientCapabilities, ret, subsystem, client);
452 WLog_WARN(TAG,
"subsystem->ClientCapabilities failed");
457static void shadow_reset_desktop_resize(rdpShadowClient* client)
459 WINPR_ASSERT(client);
460 client->resizeRequested = FALSE;
464static BOOL shadow_send_desktop_resize(rdpShadowClient* client)
467 rdpUpdate* update =
nullptr;
468 rdpSettings* settings =
nullptr;
469 const freerdp_peer* peer =
nullptr;
471 WINPR_ASSERT(client);
473 settings = client->context.settings;
474 peer = client->context.peer;
476 WINPR_ASSERT(client->server);
477 WINPR_ASSERT(client->server->surface);
479 const UINT32 resizeWidth = client->server->surface->width;
480 const UINT32 resizeHeight = client->server->surface->height;
482 if (client->resizeRequested)
484 if ((resizeWidth == client->resizeWidth) && (resizeHeight == client->resizeHeight))
489 "detected previous resize request for resolution %" PRIu32
"x%" PRIu32
490 ", still have %" PRIu32
"x%" PRIu32
", disconnecting peer",
491 resizeWidth, resizeHeight, w, h);
496 update = client->context.update;
497 WINPR_ASSERT(update);
498 WINPR_ASSERT(update->DesktopResize);
506 rc = update->DesktopResize(update->context);
507 WLog_INFO(TAG,
"Client %s resize requested (%" PRIu32
"x%" PRIu32
"@%" PRIu32
")",
508 peer->hostname, resizeWidth, resizeHeight,
510 client->resizeRequested = TRUE;
511 client->resizeWidth = resizeWidth;
512 client->resizeHeight = resizeHeight;
518static BOOL shadow_client_post_connect(freerdp_peer* peer)
521 rdpSettings* settings =
nullptr;
522 rdpShadowClient* client =
nullptr;
523 rdpShadowServer* server =
nullptr;
524 rdpShadowSubsystem* subsystem =
nullptr;
528 client = (rdpShadowClient*)peer->context;
529 WINPR_ASSERT(client);
531 settings = peer->context->settings;
532 WINPR_ASSERT(settings);
534 server = client->server;
535 WINPR_ASSERT(server);
537 subsystem = server->subsystem;
538 WINPR_ASSERT(subsystem);
546 const UINT32 MultifragMaxRequestSize =
548 if (MultifragMaxRequestSize < 0x3F0000)
551 settings, FreeRDP_NSCodec,
557 WLog_INFO(TAG,
"Client from %s is activated (%" PRIu32
"x%" PRIu32
"@%" PRIu32
")",
562 if (shadow_client_channels_post_connect(client) != CHANNEL_RC_OK)
565 shadow_client_mark_invalid(client, 0,
nullptr);
572 if (Username && Password)
580 if (subsystem->Authenticate)
582 authStatus = subsystem->Authenticate(subsystem, client, Username, Domain, Password);
587 WLog_ERR(TAG,
"client authentication failure: %d", authStatus);
592 if (subsystem->ClientConnect)
594 return subsystem->ClientConnect(subsystem, client);
601static inline void shadow_client_convert_rects(rdpShadowClient* client,
RECTANGLE_16* dst,
604 WINPR_ASSERT(client);
605 WINPR_ASSERT(client->server);
607 WINPR_ASSERT(src || (numRects == 0));
609 if (client->server->shareSubRect)
611 UINT16 offsetX = client->server->subRect.left;
612 UINT16 offsetY = client->server->subRect.top;
614 for (UINT32 i = 0; i < numRects; i++)
619 d->left = s->left + offsetX;
620 d->right = s->right + offsetX;
621 d->top = s->top + offsetY;
622 d->bottom = s->bottom + offsetY;
635static BOOL shadow_client_refresh_request(rdpShadowClient* client)
637 wMessage message = WINPR_C_ARRAY_INIT;
640 WINPR_ASSERT(client);
641 WINPR_ASSERT(client->subsystem);
643 MsgPipe = client->subsystem->MsgPipe;
644 WINPR_ASSERT(MsgPipe);
646 message.id = SHADOW_MSG_IN_REFRESH_REQUEST_ID;
647 message.wParam =
nullptr;
648 message.lParam =
nullptr;
649 message.context = (
void*)client;
650 message.Free =
nullptr;
651 return MessageQueue_Dispatch(MsgPipe->In, &message);
655static BOOL shadow_client_refresh_rect(rdpContext* context, BYTE count,
const RECTANGLE_16* areas)
657 rdpShadowClient* client = (rdpShadowClient*)context;
673 shadow_client_convert_rects(client, rects, areas, count);
674 shadow_client_mark_invalid(client, count, rects);
679 shadow_client_mark_invalid(client, 0,
nullptr);
682 return shadow_client_refresh_request(client);
686static BOOL shadow_client_suppress_output(rdpContext* context, BYTE allow,
const RECTANGLE_16* area)
688 rdpShadowClient* client = (rdpShadowClient*)context;
691 WINPR_ASSERT(client);
693 client->suppressOutput = !(allow);
699 shadow_client_convert_rects(client, ®ion, area, 1);
700 shadow_client_mark_invalid(client, 1, ®ion);
704 shadow_client_mark_invalid(client, 0,
nullptr);
708 return shadow_client_refresh_request(client);
712static BOOL shadow_client_activate(freerdp_peer* peer)
716 rdpShadowClient* client = (rdpShadowClient*)peer->context;
717 WINPR_ASSERT(client);
720 if (shadow_client_recalc_desktop_size(client))
721 return shadow_send_desktop_resize(client);
723 shadow_reset_desktop_resize(client);
724 client->activated = TRUE;
725 client->inLobby = !(client->mayView);
727 if (shadow_encoder_reset(client->encoder) < 0)
729 WLog_ERR(TAG,
"Failed to reset encoder");
734 return shadow_client_refresh_rect(&client->context, 0,
nullptr);
738static BOOL shadow_client_logon(freerdp_peer* peer,
const SEC_WINNT_AUTH_IDENTITY* identity,
742 char* user =
nullptr;
743 char* domain =
nullptr;
744 char* password =
nullptr;
745 rdpSettings* settings =
nullptr;
747 WINPR_UNUSED(automatic);
750 WINPR_ASSERT(identity);
752 WINPR_ASSERT(peer->context);
754 settings = peer->context->settings;
755 WINPR_ASSERT(settings);
757 if (identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
760 user = ConvertWCharNToUtf8Alloc(identity->User, identity->UserLength,
nullptr);
762 if (identity->Domain)
763 domain = ConvertWCharNToUtf8Alloc(identity->Domain, identity->DomainLength,
nullptr);
765 if (identity->Password)
767 ConvertWCharNToUtf8Alloc(identity->Password, identity->PasswordLength,
nullptr);
772 user = _strdup((
char*)identity->User);
774 if (identity->Domain)
775 domain = _strdup((
char*)identity->Domain);
777 if (identity->Password)
778 password = _strdup((
char*)identity->Password);
781 if ((identity->User && !user) || (identity->Domain && !domain) ||
782 (identity->Password && !password))
809static inline void shadow_client_common_frame_acknowledge(rdpShadowClient* client, UINT32 frameId)
819 WINPR_ASSERT(client);
820 WINPR_ASSERT(client->encoder);
821 client->encoder->lastAckframeId = frameId;
825static BOOL shadow_client_surface_frame_acknowledge(rdpContext* context, UINT32 frameId)
827 rdpShadowClient* client = (rdpShadowClient*)context;
828 shadow_client_common_frame_acknowledge(client, frameId);
832 WINPR_ASSERT(client);
833 WINPR_ASSERT(client->encoder);
834 client->encoder->queueDepth = QUEUE_DEPTH_UNAVAILABLE;
840shadow_client_rdpgfx_frame_acknowledge(RdpgfxServerContext* context,
843 rdpShadowClient* client =
nullptr;
845 WINPR_ASSERT(context);
846 WINPR_ASSERT(frameAcknowledge);
848 client = (rdpShadowClient*)context->custom;
849 shadow_client_common_frame_acknowledge(client, frameAcknowledge->frameId);
851 WINPR_ASSERT(client);
852 WINPR_ASSERT(client->encoder);
853 client->encoder->queueDepth = frameAcknowledge->queueDepth;
854 return CHANNEL_RC_OK;
858static BOOL shadow_are_caps_filtered(
const rdpSettings* settings, UINT32 caps)
860 const UINT32 capList[] = { RDPGFX_CAPVERSION_8, RDPGFX_CAPVERSION_81,
861 RDPGFX_CAPVERSION_10, RDPGFX_CAPVERSION_101,
862 RDPGFX_CAPVERSION_102, RDPGFX_CAPVERSION_103,
863 RDPGFX_CAPVERSION_104, RDPGFX_CAPVERSION_105,
864 RDPGFX_CAPVERSION_106, RDPGFX_CAPVERSION_106_ERR,
865 RDPGFX_CAPVERSION_107 };
867 WINPR_ASSERT(settings);
870 for (UINT32 x = 0; x < ARRAYSIZE(capList); x++)
872 if (caps == capList[x])
873 return (filter & (1u << x)) != 0;
880static UINT shadow_client_send_caps_confirm(RdpgfxServerContext* context, rdpShadowClient* client,
883 WINPR_ASSERT(context);
884 WINPR_ASSERT(client);
887 WINPR_ASSERT(context->CapsConfirm);
888 UINT rc = context->CapsConfirm(context, pdu);
889 client->areGfxCapsReady = (rc == CHANNEL_RC_OK);
894static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context, rdpShadowClient* client,
896 UINT32 capsSetCount, UINT32 capsVersion, UINT* rc)
898 const rdpSettings* srvSettings =
nullptr;
899 rdpSettings* clientSettings =
nullptr;
901 WINPR_ASSERT(context);
902 WINPR_ASSERT(client);
903 WINPR_ASSERT(capsSets || (capsSetCount == 0));
906 WINPR_ASSERT(context->rdpcontext);
907 srvSettings = context->rdpcontext->settings;
908 WINPR_ASSERT(srvSettings);
910 clientSettings = client->context.settings;
911 WINPR_ASSERT(clientSettings);
913 if (shadow_are_caps_filtered(srvSettings, capsVersion))
916 for (UINT32 index = 0; index < capsSetCount; index++)
920 if (currentCaps->version == capsVersion)
925 BOOL avc444v2 = FALSE;
928 BOOL progressive = FALSE;
933 flags = pdu.capsSet->flags;
936 (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) != 0))
939 avc444v2 = avc444 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED);
968 if (!avc444v2 && !avc444 && !avc420)
969 pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
971 *rc = shadow_client_send_caps_confirm(context, client, &pdu);
985static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context,
988 UINT rc = ERROR_INTERNAL_ERROR;
989 const rdpSettings* srvSettings =
nullptr;
990 rdpSettings* clientSettings =
nullptr;
995 WINPR_ASSERT(context);
996 WINPR_ASSERT(capsAdvertise);
998 rdpShadowClient* client = (rdpShadowClient*)context->custom;
999 WINPR_ASSERT(client);
1000 WINPR_ASSERT(context->rdpcontext);
1002 srvSettings = context->rdpcontext->settings;
1003 WINPR_ASSERT(srvSettings);
1005 clientSettings = client->context.settings;
1006 WINPR_ASSERT(clientSettings);
1010 (shadow_encoder_prepare(client->encoder, FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444) >= 0);
1021 if (!shadow_client_refresh_rect(&client->context, 0,
nullptr))
1024 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1025 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_107, &rc))
1028 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1029 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_106, &rc))
1032 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1033 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_106_ERR,
1037 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1038 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_105, &rc))
1041 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1042 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_104, &rc))
1045 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1046 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_103, &rc))
1049 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1050 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_102, &rc))
1053 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1054 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_101, &rc))
1057 if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
1058 capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_10, &rc))
1061 if (!shadow_are_caps_filtered(srvSettings, RDPGFX_CAPVERSION_81))
1063 for (UINT32 index = 0; index < capsAdvertise->capsSetCount; index++)
1065 const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
1067 if (currentCaps->version == RDPGFX_CAPVERSION_81)
1071 pdu.capsSet = ∩︀
1073 flags = pdu.capsSet->flags;
1081 (flags & RDPGFX_CAPS_FLAG_THINCLIENT) != 0))
1084 (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) != 0))
1087#ifndef WITH_GFX_H264
1090 pdu.capsSet->flags &= ~RDPGFX_CAPS_FLAG_AVC420_ENABLED;
1096 (flags & RDPGFX_CAPS_FLAG_AVC420_ENABLED) != 0))
1106 return shadow_client_send_caps_confirm(context, client, &pdu);
1111 if (!shadow_are_caps_filtered(srvSettings, RDPGFX_CAPVERSION_8))
1113 for (UINT32 index = 0; index < capsAdvertise->capsSetCount; index++)
1115 const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
1117 if (currentCaps->version == RDPGFX_CAPVERSION_8)
1121 pdu.capsSet = ∩︀
1122 flags = pdu.capsSet->flags;
1132 (flags & RDPGFX_CAPS_FLAG_THINCLIENT) != 0))
1135 (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) != 0))
1138 return shadow_client_send_caps_confirm(context, client, &pdu);
1143 return CHANNEL_RC_UNSUPPORTED_VERSION;
1150 WINPR_ASSERT(havc420);
1151 return sizeof(UINT32)
1153 * havc420->meta.numRegionRects +
1163static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client,
const BYTE* pSrcData,
1164 UINT32 nSrcStep, UINT32 SrcFormat, UINT16 nXSrc,
1165 UINT16 nYSrc, UINT16 nWidth, UINT16 nHeight)
1168 UINT error = CHANNEL_RC_OK;
1169 const rdpContext* context = (
const rdpContext*)client;
1170 const rdpSettings* settings =
nullptr;
1171 rdpShadowEncoder* encoder =
nullptr;
1177 if (!context || !pSrcData)
1180 settings = context->settings;
1181 encoder = client->encoder;
1183 if (!settings || !encoder)
1186 if (client->first_frame)
1190 if (!rfx_context_reset(encoder->rfx, nWidth, nHeight))
1193 client->first_frame = FALSE;
1196 cmdstart.frameId = shadow_encoder_create_frame_id(encoder);
1197 GetSystemTime(&sTime);
1198 cmdstart.timestamp = (UINT32)(sTime.wHour << 22U | sTime.wMinute << 16U | sTime.wSecond << 10U |
1199 sTime.wMilliseconds);
1200 cmdend.frameId = cmdstart.frameId;
1201 cmd.surfaceId = client->surfaceId;
1202 cmd.format = PIXEL_FORMAT_BGRX32;
1205 cmd.right = cmd.left + nWidth;
1206 cmd.bottom = cmd.top + nHeight;
1208 cmd.height = nHeight;
1215 if (GfxAVC444 || GfxAVC444v2)
1220 BYTE version = GfxAVC444v2 ? 2 : 1;
1222 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC444) < 0)
1224 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_AVC444");
1228 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1229 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1230 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1231 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1232 regionRect.left = (UINT16)cmd.left;
1233 regionRect.top = (UINT16)cmd.top;
1234 regionRect.right = (UINT16)cmd.right;
1235 regionRect.bottom = (UINT16)cmd.bottom;
1236 rc = avc444_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
1237 version, ®ionRect, &avc444.LC, &avc444.bitstream[0].data,
1238 &avc444.bitstream[0].length, &avc444.bitstream[1].data,
1239 &avc444.bitstream[1].length, &avc444.bitstream[0].meta,
1240 &avc444.bitstream[1].meta);
1243 WLog_ERR(TAG,
"avc420_compress failed for avc444");
1250 avc444.cbAvc420EncodedBitstream1 = rdpgfx_estimate_h264_avc420(&avc444.bitstream[0]);
1251 cmd.codecId = GfxAVC444v2 ? RDPGFX_CODECID_AVC444v2 : RDPGFX_CODECID_AVC444;
1252 cmd.extra = (
void*)&avc444;
1253 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1257 free_h264_metablock(&avc444.bitstream[0].meta);
1258 free_h264_metablock(&avc444.bitstream[1].meta);
1261 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1271 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC420) < 0)
1273 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_AVC420");
1277 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1278 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1279 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1280 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1281 regionRect.left = (UINT16)cmd.left;
1282 regionRect.top = (UINT16)cmd.top;
1283 regionRect.right = (UINT16)cmd.right;
1284 regionRect.bottom = (UINT16)cmd.bottom;
1285 rc = avc420_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
1286 ®ionRect, &avc420.data, &avc420.length, &avc420.meta);
1289 WLog_ERR(TAG,
"avc420_compress failed");
1296 cmd.codecId = RDPGFX_CODECID_AVC420;
1297 cmd.extra = (
void*)&avc420;
1299 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1302 free_h264_metablock(&avc420.meta);
1306 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1318 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX) < 0)
1320 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_REMOTEFX");
1324 s = Stream_New(
nullptr, 1024);
1327 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1328 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1329 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1330 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1331 rect.x = (UINT16)cmd.left;
1332 rect.y = (UINT16)cmd.top;
1333 rect.width = WINPR_ASSERTING_INT_CAST(UINT16, cmd.right - cmd.left);
1334 rect.height = WINPR_ASSERTING_INT_CAST(UINT16, cmd.bottom - cmd.top);
1336 rc = rfx_compose_message(encoder->rfx, s, &rect, 1, pSrcData, nWidth, nHeight, nSrcStep);
1340 WLog_ERR(TAG,
"rfx_compose_message failed");
1341 Stream_Free(s, TRUE);
1348 const size_t pos = Stream_GetPosition(s);
1349 WINPR_ASSERT(pos <= UINT32_MAX);
1351 cmd.codecId = RDPGFX_CODECID_CAVIDEO;
1352 cmd.data = Stream_Buffer(s);
1353 cmd.length = (UINT32)pos;
1355 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1359 Stream_Free(s, TRUE);
1362 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1372 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PROGRESSIVE) < 0)
1374 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_PROGRESSIVE");
1378 WINPR_ASSERT(cmd.left <= UINT16_MAX);
1379 WINPR_ASSERT(cmd.top <= UINT16_MAX);
1380 WINPR_ASSERT(cmd.right <= UINT16_MAX);
1381 WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
1382 regionRect.left = (UINT16)cmd.left;
1383 regionRect.top = (UINT16)cmd.top;
1384 regionRect.right = (UINT16)cmd.right;
1385 regionRect.bottom = (UINT16)cmd.bottom;
1386 region16_init(®ion);
1387 if (!region16_union_rect(®ion, ®ion, ®ionRect))
1389 region16_uninit(®ion);
1392 rc = progressive_compress(encoder->progressive, pSrcData, nSrcStep * nHeight, cmd.format,
1393 nWidth, nHeight, nSrcStep, ®ion, &cmd.data, &cmd.length);
1394 region16_uninit(®ion);
1397 WLog_ERR(TAG,
"progressive_compress failed");
1404 cmd.codecId = RDPGFX_CODECID_CAPROGRESSIVE;
1406 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1412 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1418 const UINT32 w = cmd.right - cmd.left;
1419 const UINT32 h = cmd.bottom - cmd.top;
1421 &pSrcData[cmd.top * nSrcStep + cmd.left * FreeRDPGetBytesPerPixel(SrcFormat)];
1422 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR) < 0)
1424 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_PLANAR");
1428 const BOOL rc = freerdp_bitmap_planar_context_reset(encoder->planar, w, h);
1432 freerdp_planar_topdown_image(encoder->planar, TRUE);
1434 cmd.data = freerdp_bitmap_compress_planar(encoder->planar, src, SrcFormat, w, h, nSrcStep,
1435 nullptr, &cmd.length);
1436 WINPR_ASSERT(cmd.data || (cmd.length == 0));
1438 cmd.codecId = RDPGFX_CODECID_PLANAR;
1440 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1445 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1451 const UINT32 w = cmd.right - cmd.left;
1452 const UINT32 h = cmd.bottom - cmd.top;
1453 const UINT32 length = w * 4 * h;
1455 BYTE* data = malloc(length);
1459 BOOL rc = freerdp_image_copy_no_overlap(data, PIXEL_FORMAT_BGRA32, 0, 0, 0, w, h, pSrcData,
1460 SrcFormat, nSrcStep, cmd.left, cmd.top,
nullptr, 0);
1468 cmd.length = length;
1469 cmd.codecId = RDPGFX_CODECID_UNCOMPRESSED;
1471 IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
1476 WLog_ERR(TAG,
"SurfaceFrameCommand failed with error %" PRIu32
"", error);
1484static BOOL stream_surface_bits_supported(
const rdpSettings* settings)
1486 const UINT32 supported =
1488 return ((supported & SURFCMDS_STREAM_SURFACE_BITS) != 0);
1492static BOOL set_surface_bits_supported(
const rdpSettings* settings)
1494 const UINT32 supported =
1496 return ((supported & SURFCMDS_SET_SURFACE_BITS) != 0);
1500static BOOL is_surface_command_supported(
const rdpSettings* settings)
1502 if (stream_surface_bits_supported(settings))
1506 if (supported && (rfxID != 0))
1509 if (set_surface_bits_supported(settings))
1513 if (supported && (nsID != 0))
1525static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcData,
1526 UINT32 nSrcStep, UINT16 nXSrc, UINT16 nYSrc,
1527 UINT16 nWidth, UINT16 nHeight)
1533 size_t numMessages = 0;
1535 rdpUpdate* update =
nullptr;
1536 rdpContext* context = (rdpContext*)client;
1537 rdpSettings* settings =
nullptr;
1538 rdpShadowEncoder* encoder =
nullptr;
1541 if (!context || !pSrcData)
1544 update = context->update;
1545 settings = context->settings;
1546 encoder = client->encoder;
1548 if (!update || !settings || !encoder)
1551 if (encoder->frameAck)
1552 frameId = shadow_encoder_create_frame_id(encoder);
1557 if (stream_surface_bits_supported(settings) &&
1560 RFX_RECT rect = WINPR_C_ARRAY_INIT;
1562 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX) < 0)
1564 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_REMOTEFX");
1571 rect.width = nWidth;
1572 rect.height = nHeight;
1574 const UINT32 MultifragMaxRequestSize =
1576 RFX_MESSAGE_LIST* messages =
1577 rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData,
1580 nSrcStep, &numMessages, MultifragMaxRequestSize);
1583 WLog_ERR(TAG,
"rfx_encode_messages failed");
1587 cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
1588 WINPR_ASSERT(rfxID <= UINT16_MAX);
1589 cmd.bmp.codecID = (UINT16)rfxID;
1600 cmd.skipCompression = TRUE;
1602 for (
size_t i = 0; i < numMessages; i++)
1604 Stream_ResetPosition(s);
1606 const RFX_MESSAGE* msg = rfx_message_list_get(messages, i);
1607 if (!rfx_write_message(encoder->rfx, s, msg))
1609 WLog_ERR(TAG,
"rfx_write_message failed");
1614 cmd.bmp.bitmapDataLength = WINPR_ASSERTING_INT_CAST(UINT32, Stream_GetPosition(s));
1615 cmd.bmp.bitmapData = Stream_Buffer(s);
1617 last = ((i + 1) == numMessages);
1619 if (!encoder->frameAck)
1620 IFCALLRET(update->SurfaceBits, ret, update->context, &cmd);
1622 IFCALLRET(update->SurfaceFrameBits, ret, update->context, &cmd, first, last,
1627 WLog_ERR(TAG,
"Send surface bits(RemoteFxCodec) failed");
1632 rfx_message_list_free(messages);
1634 else if (set_surface_bits_supported(settings) &&
1637 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_NSCODEC) < 0)
1639 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_NSCODEC");
1644 Stream_ResetPosition(s);
1645 pSrcData = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
1646 if (!nsc_compose_message(encoder->nsc, s, pSrcData, nWidth, nHeight, nSrcStep))
1649 cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
1651 WINPR_ASSERT(nsID <= UINT16_MAX);
1652 cmd.bmp.codecID = (UINT16)nsID;
1653 cmd.destLeft = nXSrc;
1654 cmd.destTop = nYSrc;
1655 cmd.destRight = cmd.destLeft + nWidth;
1656 cmd.destBottom = cmd.destTop + nHeight;
1657 cmd.bmp.width = nWidth;
1658 cmd.bmp.height = nHeight;
1660 cmd.bmp.bitmapDataLength = WINPR_ASSERTING_INT_CAST(UINT32, Stream_GetPosition(s));
1661 cmd.bmp.bitmapData = Stream_Buffer(s);
1665 if (!encoder->frameAck)
1666 IFCALLRET(update->SurfaceBits, ret, update->context, &cmd);
1668 IFCALLRET(update->SurfaceFrameBits, ret, update->context, &cmd, first, last, frameId);
1672 WLog_ERR(TAG,
"Send surface bits(NSCodec) failed");
1685static BOOL shadow_client_send_bitmap_update(rdpShadowClient* client, BYTE* pSrcData,
1686 UINT32 nSrcStep, UINT16 nXSrc, UINT16 nYSrc,
1687 UINT16 nWidth, UINT16 nHeight)
1690 BYTE* data =
nullptr;
1691 BYTE* buffer =
nullptr;
1698 UINT32 SrcFormat = 0;
1700 rdpContext* context = (rdpContext*)client;
1701 UINT32 totalBitmapSize = 0;
1702 UINT32 updateSizeEstimate = 0;
1706 if (!context || !pSrcData)
1709 rdpUpdate* update = context->update;
1710 rdpSettings* settings = context->settings;
1711 rdpShadowEncoder* encoder = client->encoder;
1713 if (!update || !settings || !encoder)
1716 const UINT32 maxUpdateSize =
1720 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED) < 0)
1722 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_INTERLEAVED");
1728 if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR) < 0)
1730 WLog_ERR(TAG,
"Failed to prepare encoder FREERDP_CODEC_PLANAR");
1735 SrcFormat = PIXEL_FORMAT_BGRX32;
1737 if ((nXSrc % 4) != 0)
1739 nWidth += (nXSrc % 4);
1740 nXSrc -= (nXSrc % 4);
1743 if ((nYSrc % 4) != 0)
1745 nHeight += (nYSrc % 4);
1746 nYSrc -= (nYSrc % 4);
1749 rows = (nHeight / 64) + ((nHeight % 64) ? 1 : 0);
1750 cols = (nWidth / 64) + ((nWidth % 64) ? 1 : 0);
1752 totalBitmapSize = 0;
1753 bitmapUpdate.number = rows * cols;
1758 bitmapUpdate.rectangles = bitmapData;
1760 if ((nWidth % 4) != 0)
1762 nWidth += (4 - (nWidth % 4));
1765 if ((nHeight % 4) != 0)
1767 nHeight += (4 - (nHeight % 4));
1770 for (yIdx = 0; yIdx < rows; yIdx++)
1772 for (xIdx = 0; xIdx < cols; xIdx++)
1774 bitmap = &bitmapData[k];
1776 bitmap->height = 64;
1777 bitmap->destLeft = nXSrc + (xIdx * 64);
1778 bitmap->destTop = nYSrc + (yIdx * 64);
1780 if (((INT64)bitmap->destLeft + bitmap->width) > (nXSrc + nWidth))
1781 bitmap->width = (UINT32)(nXSrc + nWidth) - bitmap->destLeft;
1783 if (((INT64)bitmap->destTop + bitmap->height) > (nYSrc + nHeight))
1784 bitmap->height = (UINT32)(nYSrc + nHeight) - bitmap->destTop;
1786 bitmap->destRight = bitmap->destLeft + bitmap->width - 1;
1787 bitmap->destBottom = bitmap->destTop + bitmap->height - 1;
1788 bitmap->compressed = TRUE;
1790 if ((bitmap->width < 4) || (bitmap->height < 4))
1796 UINT32 bytesPerPixel = (bitsPerPixel + 7) / 8;
1797 DstSize = 64 * 64 * 4;
1798 buffer = encoder->grid[k];
1800 ret = interleaved_compress(
1801 encoder->interleaved, buffer, &DstSize, bitmap->width, bitmap->height, pSrcData,
1802 SrcFormat, nSrcStep, bitmap->destLeft, bitmap->destTop,
nullptr, bitsPerPixel);
1805 bitmap->bitmapDataStream = buffer;
1806 bitmap->bitmapLength = DstSize;
1807 bitmap->bitsPerPixel = bitsPerPixel;
1808 bitmap->cbScanWidth = bitmap->width * bytesPerPixel;
1809 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * bytesPerPixel;
1814 buffer = encoder->grid[k];
1815 data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)];
1818 freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat, bitmap->width,
1819 bitmap->height, nSrcStep, buffer, &dstSize);
1820 bitmap->bitmapDataStream = buffer;
1821 bitmap->bitmapLength = dstSize;
1822 bitmap->bitsPerPixel = 32;
1823 bitmap->cbScanWidth = bitmap->width * 4;
1824 bitmap->cbUncompressedSize = bitmap->width * bitmap->height * 4;
1827 bitmap->cbCompFirstRowSize = 0;
1828 bitmap->cbCompMainBodySize = bitmap->bitmapLength;
1829 totalBitmapSize += bitmap->bitmapLength;
1834 bitmapUpdate.number = k;
1835 updateSizeEstimate = totalBitmapSize + (k * bitmapUpdate.number) + 16;
1837 if (updateSizeEstimate > maxUpdateSize)
1841 UINT32 updateSize = 0;
1842 UINT32 newUpdateSize = 0;
1848 if (!fragBitmapData)
1850 WLog_ERR(TAG,
"Failed to allocate memory for fragBitmapData");
1855 bitmapUpdate.rectangles = fragBitmapData;
1861 newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16);
1863 if (newUpdateSize < maxUpdateSize)
1865 CopyMemory(&fragBitmapData[j++], &bitmapData[i++],
sizeof(
BITMAP_DATA));
1866 updateSize = newUpdateSize;
1869 if ((newUpdateSize >= maxUpdateSize) || (i + 1) >= k)
1871 bitmapUpdate.number = j;
1872 ret = BitmapUpdateProxy(client, &bitmapUpdate);
1882 free(fragBitmapData);
1886 ret = BitmapUpdateProxy(client, &bitmapUpdate);
1900static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
1907 rdpContext* context = (rdpContext*)client;
1908 rdpSettings* settings =
nullptr;
1909 rdpShadowServer* server =
nullptr;
1910 rdpShadowSurface* surface =
nullptr;
1914 BYTE* pSrcData =
nullptr;
1915 UINT32 nSrcStep = 0;
1916 UINT32 SrcFormat = 0;
1917 UINT32 numRects = 0;
1920 if (!context || !pStatus)
1923 settings = context->settings;
1924 server = client->server;
1926 if (!settings || !server)
1929 surface = client->inLobby ? server->lobby : server->surface;
1935 EnterCriticalSection(&(client->lock));
1936 region16_init(&invalidRegion);
1938 const BOOL res = region16_copy(&invalidRegion, &(client->invalidRegion));
1939 region16_clear(&(client->invalidRegion));
1940 LeaveCriticalSection(&(client->lock));
1945 EnterCriticalSection(&surface->lock);
1946 rects = region16_rects(&(surface->invalidRegion), &numRects);
1948 for (UINT32 index = 0; index < numRects; index++)
1950 if (!region16_union_rect(&invalidRegion, &invalidRegion, &rects[index]))
1954 surfaceRect.left = 0;
1955 surfaceRect.top = 0;
1956 WINPR_ASSERT(surface->width <= UINT16_MAX);
1957 WINPR_ASSERT(surface->height <= UINT16_MAX);
1958 surfaceRect.right = (UINT16)surface->width;
1959 surfaceRect.bottom = (UINT16)surface->height;
1960 if (!region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect))
1963 if (server->shareSubRect)
1965 if (!region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect)))
1969 if (region16_is_empty(&invalidRegion))
1975 extents = region16_extents(&invalidRegion);
1976 nXSrc = extents->left;
1977 nYSrc = extents->top;
1978 nWidth = extents->right - extents->left;
1979 nHeight = extents->bottom - extents->top;
1980 pSrcData = surface->data;
1981 nSrcStep = surface->scanline;
1982 SrcFormat = surface->format;
1985 if (server->shareSubRect)
1989 subX = server->subRect.left;
1990 subY = server->subRect.top;
1993 WINPR_ASSERT(nXSrc >= 0);
1994 WINPR_ASSERT(nXSrc <= UINT16_MAX);
1995 WINPR_ASSERT(nYSrc >= 0);
1996 WINPR_ASSERT(nYSrc <= UINT16_MAX);
1997 pSrcData = &pSrcData[((UINT16)subY * nSrcStep) + ((UINT16)subX * 4U)];
2006 if (pStatus->gfxOpened && client->areGfxCapsReady)
2013 if (!pStatus->gfxSurfaceCreated)
2016 if (!(ret = shadow_client_rdpgfx_reset_graphic(client)))
2019 if (!(ret = shadow_client_rdpgfx_new_surface(client)))
2022 pStatus->gfxSurfaceCreated = TRUE;
2025 WINPR_ASSERT(nWidth >= 0);
2026 WINPR_ASSERT(nWidth <= UINT16_MAX);
2027 WINPR_ASSERT(nHeight >= 0);
2028 WINPR_ASSERT(nHeight <= UINT16_MAX);
2029 ret = shadow_client_send_surface_gfx(client, pSrcData, nSrcStep, SrcFormat, 0, 0,
2030 (UINT16)nWidth, (UINT16)nHeight);
2037 else if (is_surface_command_supported(settings))
2039 WINPR_ASSERT(nXSrc >= 0);
2040 WINPR_ASSERT(nXSrc <= UINT16_MAX);
2041 WINPR_ASSERT(nYSrc >= 0);
2042 WINPR_ASSERT(nYSrc <= UINT16_MAX);
2043 WINPR_ASSERT(nWidth >= 0);
2044 WINPR_ASSERT(nWidth <= UINT16_MAX);
2045 WINPR_ASSERT(nHeight >= 0);
2046 WINPR_ASSERT(nHeight <= UINT16_MAX);
2047 ret = shadow_client_send_surface_bits(client, pSrcData, nSrcStep, (UINT16)nXSrc,
2048 (UINT16)nYSrc, (UINT16)nWidth, (UINT16)nHeight);
2052 WINPR_ASSERT(nXSrc >= 0);
2053 WINPR_ASSERT(nXSrc <= UINT16_MAX);
2054 WINPR_ASSERT(nYSrc >= 0);
2055 WINPR_ASSERT(nYSrc <= UINT16_MAX);
2056 WINPR_ASSERT(nWidth >= 0);
2057 WINPR_ASSERT(nWidth <= UINT16_MAX);
2058 WINPR_ASSERT(nHeight >= 0);
2059 WINPR_ASSERT(nHeight <= UINT16_MAX);
2060 ret = shadow_client_send_bitmap_update(client, pSrcData, nSrcStep, (UINT16)nXSrc,
2061 (UINT16)nYSrc, (UINT16)nWidth, (UINT16)nHeight);
2065 LeaveCriticalSection(&surface->lock);
2066 region16_uninit(&invalidRegion);
2078static BOOL shadow_client_send_resize(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
2080 rdpContext* context = (rdpContext*)client;
2081 rdpSettings* settings =
nullptr;
2082 freerdp_peer* peer =
nullptr;
2084 if (!context || !pStatus)
2087 peer = context->peer;
2088 settings = context->settings;
2090 if (!peer || !settings)
2098 client->activated = FALSE;
2101 if (pStatus->gfxSurfaceCreated)
2103 if (!shadow_client_rdpgfx_release_surface(client))
2106 pStatus->gfxSurfaceCreated = FALSE;
2110 if (!shadow_send_desktop_resize(client))
2112 shadow_reset_desktop_resize(client);
2115 EnterCriticalSection(&(client->lock));
2116 region16_clear(&(client->invalidRegion));
2117 LeaveCriticalSection(&(client->lock));
2128static BOOL shadow_client_surface_update(rdpShadowClient* client,
REGION16* region)
2130 UINT32 numRects = 0;
2132 rects = region16_rects(region, &numRects);
2133 shadow_client_mark_invalid(client, numRects, rects);
2144static inline BOOL shadow_client_no_surface_update(rdpShadowClient* client,
2145 SHADOW_GFX_STATUS* pStatus)
2147 rdpShadowServer* server =
nullptr;
2148 rdpShadowSurface* surface =
nullptr;
2149 WINPR_UNUSED(pStatus);
2150 WINPR_ASSERT(client);
2151 server = client->server;
2152 WINPR_ASSERT(server);
2153 surface = client->inLobby ? server->lobby : server->surface;
2154 EnterCriticalSection(&surface->lock);
2155 const BOOL rc = shadow_client_surface_update(client, &(surface->invalidRegion));
2156 LeaveCriticalSection(&surface->lock);
2161static int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message)
2163 rdpContext* context = (rdpContext*)client;
2165 WINPR_ASSERT(message);
2166 WINPR_ASSERT(context);
2168 rdpUpdate* update = context->update;
2169 WINPR_ASSERT(update);
2173 switch (message->id)
2175 case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
2180 pointerPosition.xPos = msg->xPos;
2181 pointerPosition.yPos = msg->yPos;
2183 WINPR_ASSERT(client->server);
2184 if (client->server->shareSubRect)
2186 pointerPosition.xPos -= client->server->subRect.left;
2187 pointerPosition.yPos -= client->server->subRect.top;
2190 if (client->activated)
2192 if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY))
2194 WINPR_ASSERT(update->pointer);
2195 if (!IFCALLRESULT(TRUE, update->pointer->PointerPosition, context,
2198 client->pointerX = msg->xPos;
2199 client->pointerY = msg->yPos;
2206 case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
2215 pointerNew.xorBpp = 24;
2216 pointerColor = &(pointerNew.colorPtrAttr);
2217 pointerColor->cacheIndex = 0;
2218 pointerColor->hotSpotX = WINPR_ASSERTING_INT_CAST(UINT16, msg->xHot);
2219 pointerColor->hotSpotY = WINPR_ASSERTING_INT_CAST(UINT16, msg->yHot);
2220 pointerColor->width = WINPR_ASSERTING_INT_CAST(UINT16, msg->width);
2221 pointerColor->height = WINPR_ASSERTING_INT_CAST(UINT16, msg->height);
2222 pointerColor->lengthAndMask = WINPR_ASSERTING_INT_CAST(UINT16, msg->lengthAndMask);
2223 pointerColor->lengthXorMask = WINPR_ASSERTING_INT_CAST(UINT16, msg->lengthXorMask);
2224 pointerColor->xorMaskData = msg->xorMaskData;
2225 pointerColor->andMaskData = msg->andMaskData;
2226 pointerCached.cacheIndex = pointerColor->cacheIndex;
2228 if (client->activated)
2230 if (client->server->ShowMouseCursor)
2232 if (!IFCALLRESULT(TRUE, update->pointer->PointerNew, context, &pointerNew))
2234 if (!IFCALLRESULT(TRUE, update->pointer->PointerCached, context,
2241 pointer_system.type = SYSPTR_DEFAULT;
2242 if (!IFCALLRESULT(TRUE, update->pointer->PointerSystem, context,
2251 case SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES_ID:
2258 if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
2260 client->rdpsnd->src_format = msg->audio_format;
2263 IFCALLRESULT(CHANNEL_RC_OK, client->rdpsnd->SendSamples, client->rdpsnd,
2264 msg->buf, msg->nFrames, msg->wTimestamp);
2265 if (CHANNEL_RC_OK != error)
2272 case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
2277 if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
2279 const UINT error = IFCALLRESULT(CHANNEL_RC_OK, client->rdpsnd->SetVolume,
2280 client->rdpsnd, msg->left, msg->right);
2281 if (CHANNEL_RC_OK != error)
2289 WLog_ERR(TAG,
"Unknown message id: %" PRIu32
"", message->id);
2293 shadow_client_free_queued_message(message);
2298static DWORD WINAPI shadow_client_thread(LPVOID arg)
2300 rdpShadowClient* client = (rdpShadowClient*)arg;
2303 wMessage message = WINPR_C_ARRAY_INIT;
2304 wMessage pointerPositionMsg = WINPR_C_ARRAY_INIT;
2305 wMessage pointerAlphaMsg = WINPR_C_ARRAY_INIT;
2306 wMessage audioVolumeMsg = WINPR_C_ARRAY_INIT;
2307 HANDLE ChannelEvent =
nullptr;
2308 void* UpdateSubscriber =
nullptr;
2309 HANDLE UpdateEvent =
nullptr;
2310 freerdp_peer* peer =
nullptr;
2311 rdpContext* context =
nullptr;
2312 rdpSettings* settings =
nullptr;
2313 rdpShadowServer* server =
nullptr;
2314 rdpShadowSubsystem* subsystem =
nullptr;
2315 wMessageQueue* MsgQueue =
nullptr;
2317 SHADOW_GFX_STATUS gfxstatus = WINPR_C_ARRAY_INIT;
2318 rdpUpdate* update =
nullptr;
2320 WINPR_ASSERT(client);
2322 MsgQueue = client->MsgQueue;
2323 WINPR_ASSERT(MsgQueue);
2325 server = client->server;
2326 WINPR_ASSERT(server);
2327 subsystem = server->subsystem;
2328 context = (rdpContext*)client;
2329 peer = context->peer;
2331 WINPR_ASSERT(peer->context);
2333 settings = peer->context->settings;
2334 WINPR_ASSERT(settings);
2336 peer->Capabilities = shadow_client_capabilities;
2337 peer->PostConnect = shadow_client_post_connect;
2338 peer->Activate = shadow_client_activate;
2339 peer->Logon = shadow_client_logon;
2340 shadow_input_register_callbacks(peer->context->input);
2342 rc = peer->Initialize(peer);
2346 update = peer->context->update;
2347 WINPR_ASSERT(update);
2349 update->RefreshRect = shadow_client_refresh_rect;
2350 update->SuppressOutput = shadow_client_suppress_output;
2351 update->SurfaceFrameAcknowledge = shadow_client_surface_frame_acknowledge;
2353 if ((!client->vcm) || (!subsystem->updateEvent))
2356 UpdateSubscriber = shadow_multiclient_get_subscriber(subsystem->updateEvent);
2358 if (!UpdateSubscriber)
2361 UpdateEvent = shadow_multiclient_getevent(UpdateSubscriber);
2362 WINPR_ASSERT(UpdateEvent);
2364 ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm);
2365 WINPR_ASSERT(ChannelEvent);
2377 HANDLE events[MAXIMUM_WAIT_OBJECTS] = WINPR_C_ARRAY_INIT;
2379 events[nCount++] = UpdateEvent;
2381 DWORD tmp = peer->GetEventHandles(peer, &events[nCount], 64 - nCount);
2385 WLog_ERR(TAG,
"Failed to get FreeRDP transport event handles");
2391 events[nCount++] = ChannelEvent;
2392 events[nCount++] = MessageQueue_Event(MsgQueue);
2394#if defined(CHANNEL_RDPGFX_SERVER)
2395 HANDLE gfxevent = rdpgfx_server_get_event_handle(client->rdpgfx);
2398 events[nCount++] = gfxevent;
2401 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
2403 if (status == WAIT_FAILED)
2406 if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
2415 if (client->activated && !client->suppressOutput)
2420 if (shadow_client_recalc_desktop_size(client))
2423 if (!shadow_client_send_resize(client, &gfxstatus))
2425 WLog_ERR(TAG,
"Failed to send resize message");
2432 if (!shadow_client_send_surface_update(client, &gfxstatus))
2434 WLog_ERR(TAG,
"Failed to send surface update");
2442 if (!shadow_client_no_surface_update(client, &gfxstatus))
2444 WLog_ERR(TAG,
"Failed to handle surface update");
2453 (void)shadow_multiclient_consume(UpdateSubscriber);
2456 WINPR_ASSERT(peer->CheckFileDescriptor);
2457 if (!peer->CheckFileDescriptor(peer))
2459 WLog_ERR(TAG,
"Failed to check FreeRDP file descriptor");
2463 if (client->activated &&
2464 WTSVirtualChannelManagerIsChannelJoined(client->vcm, DRDYNVC_SVC_CHANNEL_NAME))
2466 switch (WTSVirtualChannelManagerGetDrdynvcState(client->vcm))
2469 case DRDYNVC_STATE_NONE:
2472 if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
2474 WLog_ERR(TAG,
"Failed to initialize drdynvc channel");
2480 case DRDYNVC_STATE_READY:
2481#if defined(CHANNEL_AUDIN_SERVER)
2482 if (client->audin && !IFCALLRESULT(TRUE, client->audin->IsOpen, client->audin))
2484 if (!IFCALLRESULT(FALSE, client->audin->Open, client->audin))
2486 WLog_ERR(TAG,
"Failed to initialize audin channel");
2494 client->rdpgfx && !gfxstatus.gfxOpened)
2496 client->rdpgfx->FrameAcknowledge = shadow_client_rdpgfx_frame_acknowledge;
2497 client->rdpgfx->CapsAdvertise = shadow_client_rdpgfx_caps_advertise;
2499 if (!client->rdpgfx->Open(client->rdpgfx))
2501 WLog_WARN(TAG,
"Failed to open GraphicsPipeline");
2503 FreeRDP_SupportGraphicsPipeline, FALSE))
2508 gfxstatus.gfxOpened = TRUE;
2509 WLog_INFO(TAG,
"Gfx Pipeline Opened");
2520 if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
2522 if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
2524 WLog_ERR(TAG,
"WTSVirtualChannelManagerCheckFileDescriptor failure");
2529#if defined(CHANNEL_RDPGFX_SERVER)
2532 if (WaitForSingleObject(gfxevent, 0) == WAIT_OBJECT_0)
2534 const UINT error = rdpgfx_server_handle_messages(client->rdpgfx);
2535 if (error != CHANNEL_RC_OK)
2541 if (WaitForSingleObject(MessageQueue_Event(MsgQueue), 0) == WAIT_OBJECT_0)
2544 pointerPositionMsg.id = 0;
2545 pointerPositionMsg.Free =
nullptr;
2546 pointerAlphaMsg.id = 0;
2547 pointerAlphaMsg.Free =
nullptr;
2548 audioVolumeMsg.id = 0;
2549 audioVolumeMsg.Free =
nullptr;
2551 while (MessageQueue_Peek(MsgQueue, &message, TRUE))
2553 if (message.id == WMQ_QUIT)
2560 case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
2562 shadow_client_free_queued_message(&pointerPositionMsg);
2563 pointerPositionMsg = message;
2566 case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
2568 shadow_client_free_queued_message(&pointerAlphaMsg);
2569 pointerAlphaMsg = message;
2572 case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
2574 shadow_client_free_queued_message(&audioVolumeMsg);
2575 audioVolumeMsg = message;
2579 if (!shadow_client_subsystem_process_message(client, &message))
2585 if (message.id == WMQ_QUIT)
2588 shadow_client_free_queued_message(&pointerPositionMsg);
2589 shadow_client_free_queued_message(&pointerAlphaMsg);
2590 shadow_client_free_queued_message(&audioVolumeMsg);
2596 if (pointerPositionMsg.id)
2598 if (!shadow_client_subsystem_process_message(client, &pointerPositionMsg))
2602 if (pointerAlphaMsg.id)
2604 if (!shadow_client_subsystem_process_message(client, &pointerAlphaMsg))
2608 if (audioVolumeMsg.id)
2610 if (!shadow_client_subsystem_process_message(client, &audioVolumeMsg))
2620#if defined(CHANNEL_AUDIN_SERVER)
2621 if (client->audin && !IFCALLRESULT(TRUE, client->audin->IsOpen, client->audin))
2623 if (!IFCALLRESULT(FALSE, client->audin->Close, client->audin))
2625 WLog_WARN(TAG,
"AUDIN shutdown failure!");
2630 if (gfxstatus.gfxOpened)
2632 if (gfxstatus.gfxSurfaceCreated)
2634 if (!shadow_client_rdpgfx_release_surface(client))
2635 WLog_WARN(TAG,
"GFX release surface failure!");
2638 WINPR_ASSERT(client->rdpgfx);
2639 WINPR_ASSERT(client->rdpgfx->Close);
2640 rc = client->rdpgfx->Close(client->rdpgfx);
2644 shadow_client_channels_free(client);
2646 if (UpdateSubscriber)
2648 shadow_multiclient_release_subscriber(UpdateSubscriber);
2649 UpdateSubscriber =
nullptr;
2652 if (peer->connected && subsystem->ClientDisconnect)
2654 subsystem->ClientDisconnect(subsystem, client);
2658 WINPR_ASSERT(peer->Disconnect);
2659 peer->Disconnect(peer);
2660 freerdp_peer_context_free(peer);
2661 freerdp_peer_free(peer);
2666BOOL shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
2668 rdpShadowClient* client =
nullptr;
2669 rdpShadowServer* server =
nullptr;
2671 if (!listener || !peer)
2674 server = (rdpShadowServer*)listener->info;
2675 WINPR_ASSERT(server);
2677 peer->ContextExtra = (
void*)server;
2678 peer->ContextSize =
sizeof(rdpShadowClient);
2679 peer->ContextNew = shadow_client_context_new;
2680 peer->ContextFree = shadow_client_context_free;
2682 if (!freerdp_peer_context_new_ex(peer, server->settings))
2685 client = (rdpShadowClient*)peer->context;
2686 WINPR_ASSERT(client);
2688 if (!(client->thread = CreateThread(
nullptr, 0, shadow_client_thread, client, 0,
nullptr)))
2690 freerdp_peer_context_free(peer);
2696 (void)CloseHandle(client->thread);
2697 client->thread =
nullptr;
2703static void shadow_msg_out_addref(wMessage* message)
2705 SHADOW_MSG_OUT* msg =
nullptr;
2707 WINPR_ASSERT(message);
2708 msg = (SHADOW_MSG_OUT*)message->wParam;
2711 InterlockedIncrement(&(msg->refCount));
2714static void shadow_msg_out_release(wMessage* message)
2716 SHADOW_MSG_OUT* msg =
nullptr;
2718 WINPR_ASSERT(message);
2719 msg = (SHADOW_MSG_OUT*)message->wParam;
2722 if (InterlockedDecrement(&(msg->refCount)) <= 0)
2724 IFCALL(msg->Free, message->id, msg);
2729static BOOL shadow_client_dispatch_msg(rdpShadowClient* client, wMessage* message)
2731 if (!client || !message)
2735 shadow_msg_out_addref(message);
2737 WINPR_ASSERT(client->MsgQueue);
2738 if (MessageQueue_Dispatch(client->MsgQueue, message))
2743 shadow_msg_out_release(message);
2748BOOL shadow_client_post_msg(rdpShadowClient* client,
void* context, UINT32 type,
2749 SHADOW_MSG_OUT* msg,
void* lParam)
2751 wMessage message = WINPR_C_ARRAY_INIT;
2752 message.context = context;
2754 message.wParam = (
void*)msg;
2755 message.lParam = lParam;
2756 message.Free = shadow_msg_out_release;
2757 return shadow_client_dispatch_msg(client, &message);
2760int shadow_client_boardcast_msg(rdpShadowServer* server,
void* context, UINT32 type,
2761 SHADOW_MSG_OUT* msg,
void* lParam)
2763 wMessage message = WINPR_C_ARRAY_INIT;
2766 WINPR_ASSERT(server);
2769 message.context = context;
2771 message.wParam = (
void*)msg;
2772 message.lParam = lParam;
2773 message.Free = shadow_msg_out_release;
2776 shadow_msg_out_addref(&message);
2778 WINPR_ASSERT(server->clients);
2779 ArrayList_Lock(server->clients);
2781 for (
size_t index = 0; index < ArrayList_Count(server->clients); index++)
2783 rdpShadowClient* client = (rdpShadowClient*)ArrayList_GetItem(server->clients, index);
2785 if (shadow_client_dispatch_msg(client, &message))
2791 ArrayList_Unlock(server->clients);
2793 shadow_msg_out_release(&message);
2797int shadow_client_boardcast_quit(rdpShadowServer* server,
int nExitCode)
2799 wMessageQueue* queue =
nullptr;
2802 WINPR_ASSERT(server);
2803 WINPR_ASSERT(server->clients);
2805 ArrayList_Lock(server->clients);
2807 for (
size_t index = 0; index < ArrayList_Count(server->clients); index++)
2809 queue = ((rdpShadowClient*)ArrayList_GetItem(server->clients, index))->MsgQueue;
2811 if (MessageQueue_PostQuit(queue, nExitCode))
2817 ArrayList_Unlock(server->clients);
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
This struct contains function pointer to initialize/free objects.