summaryrefslogtreecommitdiffstats
path: root/server/Windows/wf_update.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/Windows/wf_update.c')
-rw-r--r--server/Windows/wf_update.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/server/Windows/wf_update.c b/server/Windows/wf_update.c
new file mode 100644
index 0000000..06d60c9
--- /dev/null
+++ b/server/Windows/wf_update.c
@@ -0,0 +1,251 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * FreeRDP Windows Server
+ *
+ * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2012 Corey Clayton <can.of.tuna@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <freerdp/config.h>
+
+#include <stdio.h>
+
+#include <winpr/windows.h>
+
+#include <freerdp/freerdp.h>
+#include <freerdp/listener.h>
+
+#include "wf_peer.h"
+#include "wf_info.h"
+#include "wf_mirage.h"
+
+#include "wf_update.h"
+
+#include <freerdp/log.h>
+#define TAG SERVER_TAG("windows")
+
+DWORD WINAPI wf_update_thread(LPVOID lpParam)
+{
+ DWORD fps;
+ wfInfo* wfi;
+ DWORD beg, end;
+ DWORD diff, rate;
+ wfi = (wfInfo*)lpParam;
+ fps = wfi->framesPerSecond;
+ rate = 1000 / fps;
+
+ while (1)
+ {
+ beg = GetTickCount();
+
+ if (wf_info_lock(wfi) > 0)
+ {
+ if (wfi->activePeerCount > 0)
+ {
+ wf_info_update_changes(wfi);
+
+ if (wf_info_have_updates(wfi))
+ {
+ wf_update_encode(wfi);
+ // WLog_DBG(TAG, "Start of parallel sending");
+ int index = 0;
+
+ for (int peerindex = 0; peerindex < wfi->peerCount; peerindex++)
+ {
+ for (; index < FREERDP_SERVER_WIN_INFO_MAXPEERS; index++)
+ {
+ if (wfi->peers[index] && wfi->peers[index]->activated)
+ {
+ // WLog_DBG(TAG, "Setting event for %d of %d", index + 1,
+ // wfi->activePeerCount);
+ SetEvent(((wfPeerContext*)wfi->peers[index]->context)->updateEvent);
+ }
+ }
+ }
+
+ for (int index = 0; index < wfi->activePeerCount; index++)
+ {
+ // WLog_DBG(TAG, "Waiting for %d of %d", index + 1, wfi->activePeerCount);
+ // WaitForSingleObject(wfi->updateSemaphore, INFINITE);
+ WaitForSingleObject(wfi->updateSemaphore, 1000);
+ }
+
+ // WLog_DBG(TAG, "End of parallel sending");
+ wf_info_clear_invalid_region(wfi);
+ }
+ }
+
+ wf_info_unlock(wfi);
+ }
+
+ end = GetTickCount();
+ diff = end - beg;
+
+ if (diff < rate)
+ {
+ Sleep(rate - diff);
+ }
+ }
+
+ // WLog_DBG(TAG, "Exiting Update Thread");
+ return 0;
+}
+
+void wf_update_encode(wfInfo* wfi)
+{
+ RFX_RECT rect;
+ long height, width;
+ BYTE* pDataBits = NULL;
+ int stride;
+ SURFACE_BITS_COMMAND* cmd;
+ wf_info_find_invalid_region(wfi);
+ cmd = &wfi->cmd;
+ Stream_SetPosition(wfi->s, 0);
+ wf_info_getScreenData(wfi, &width, &height, &pDataBits, &stride);
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = (UINT16)width;
+ rect.height = (UINT16)height;
+ // WLog_DBG(TAG, "x:%"PRId32" y:%"PRId32" w:%ld h:%ld", wfi->invalid.left, wfi->invalid.top,
+ // width, height);
+ Stream_Clear(wfi->s);
+
+ if (!(rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1, pDataBits, width, height,
+ stride)))
+ {
+ return;
+ }
+
+ wfi->frame_idx = rfx_context_get_frame_idx(wfi->rfx_context);
+ cmd->destLeft = wfi->invalid.left;
+ cmd->destTop = wfi->invalid.top;
+ cmd->destRight = wfi->invalid.left + width;
+ cmd->destBottom = wfi->invalid.top + height;
+ cmd->bmp.bpp = 32;
+ cmd->bmp.codecID = 3;
+ cmd->bmp.width = width;
+ cmd->bmp.height = height;
+ cmd->bmp.bitmapDataLength = Stream_GetPosition(wfi->s);
+ cmd->bmp.bitmapData = Stream_Buffer(wfi->s);
+}
+
+void wf_update_peer_send(wfInfo* wfi, wfPeerContext* context)
+{
+ freerdp_peer* client;
+
+ WINPR_ASSERT(wfi);
+ WINPR_ASSERT(context);
+
+ client = ((rdpContext*)context)->peer;
+ WINPR_ASSERT(client);
+
+ /* This happens when the RemoteFX encoder state is reset */
+
+ if (wfi->frame_idx == 1)
+ context->frame_idx = 0;
+
+ /*
+ * When a new client connects, it is possible that old frames from
+ * from a previous encoding state remain. Those frames should be discarded
+ * as they will cause an error condition in mstsc.
+ */
+
+ if ((context->frame_idx + 1) != wfi->frame_idx)
+ {
+ /* This frame is meant to be discarded */
+ if (context->frame_idx == 0)
+ return;
+
+ /* This is an unexpected error condition */
+ WLog_DBG(TAG, "Unexpected Frame Index: Actual: %d Expected: %d", wfi->frame_idx,
+ context->frame_idx + 1);
+ }
+
+ WINPR_ASSERT(client->context);
+ WINPR_ASSERT(client->context->settings);
+ WINPR_ASSERT(client->context->update);
+ WINPR_ASSERT(client->context->update->SurfaceBits);
+
+ wfi->cmd.bmp.codecID =
+ freerdp_settings_get_uint32(client->context->settings, FreeRDP_RemoteFxCodecId);
+ client->context->update->SurfaceBits(client->context, &wfi->cmd);
+ context->frame_idx++;
+}
+
+void wf_update_encoder_reset(wfInfo* wfi)
+{
+ if (wf_info_lock(wfi) > 0)
+ {
+ WLog_DBG(TAG, "Resetting encoder");
+
+ if (wfi->rfx_context)
+ {
+ rfx_context_reset(wfi->rfx_context, wfi->servscreen_width, wfi->servscreen_height);
+ }
+ else
+ {
+ /* TODO: pass ThreadingFlags somehow */
+ wfi->rfx_context = rfx_context_new(TRUE);
+ rfx_context_set_mode(wfi->rfx_context, RLGR3);
+ rfx_context_reset(wfi->rfx_context, wfi->servscreen_width, wfi->servscreen_height);
+ rfx_context_set_pixel_format(wfi->rfx_context, PIXEL_FORMAT_BGRA32);
+ wfi->s = Stream_New(NULL, 0xFFFF);
+ }
+
+ wf_info_invalidate_full_screen(wfi);
+ wf_info_unlock(wfi);
+ }
+}
+
+void wf_update_peer_activate(wfInfo* wfi, wfPeerContext* context)
+{
+ if (wf_info_lock(wfi) > 0)
+ {
+ if (wfi->activePeerCount < 1)
+ {
+#ifndef WITH_DXGI_1_2
+ wf_mirror_driver_activate(wfi);
+#endif
+ ResumeThread(wfi->updateThread);
+ }
+
+ wf_update_encoder_reset(wfi);
+ wfi->activePeerCount++;
+ WLog_DBG(TAG, "Activating Peer Updates: %d", wfi->activePeerCount);
+ wf_info_unlock(wfi);
+ }
+}
+
+void wf_update_peer_deactivate(wfInfo* wfi, wfPeerContext* context)
+{
+ if (wf_info_lock(wfi) > 0)
+ {
+ freerdp_peer* client = ((rdpContext*)context)->peer;
+
+ if (client->activated)
+ {
+ if (wfi->activePeerCount <= 1)
+ {
+ wf_mirror_driver_deactivate(wfi);
+ }
+
+ client->activated = FALSE;
+ wfi->activePeerCount--;
+ WLog_DBG(TAG, "Deactivating Peer Updates: %d", wfi->activePeerCount);
+ }
+
+ wf_info_unlock(wfi);
+ }
+}