From d6250b1aec280e39f4aead94c717586669a985f0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andre=CC=81=20Moreau?= Date: Fri, 19 Sep 2014 19:58:49 -0400 Subject: [PATCH] shadow: improve Mac subsystem --- server/shadow/Mac/mac_shadow.c | 280 +++++++++++++++++++++------------------ server/shadow/Mac/mac_shadow.h | 3 - server/shadow/shadow_input.c | 2 +- server/shadow/shadow_subsystem.c | 3 +- 4 files changed, 152 insertions(+), 136 deletions(-) diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index 9132027..7efd78b 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -25,8 +25,10 @@ #include #include "../shadow_screen.h" +#include "../shadow_client.h" #include "../shadow_surface.h" #include "../shadow_capture.h" +#include "../shadow_encoder.h" #include "../shadow_subsystem.h" #include "mac_shadow.h" @@ -56,27 +58,29 @@ void mac_shadow_input_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags if (extended) vkcode |= KBDEXT; - keycode = GetKeycodeFromVirtualKeyCode(vkcode, KEYCODE_TYPE_APPLE) - 8; + keycode = GetKeycodeFromVirtualKeyCode(vkcode, KEYCODE_TYPE_APPLE); - if (keycode) - { - source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + if (keycode < 8) + return; - if (flags & KBD_FLAGS_DOWN) - { - kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, TRUE); - CGEventPost(kCGHIDEventTap, kbdEvent); - CFRelease(kbdEvent); - } - else if (flags & KBD_FLAGS_RELEASE) - { - kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, FALSE); - CGEventPost(kCGHIDEventTap, kbdEvent); - CFRelease(kbdEvent); - } + keycode -= 8; + + source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); - CFRelease(source); + if (flags & KBD_FLAGS_DOWN) + { + kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, TRUE); + CGEventPost(kCGHIDEventTap, kbdEvent); + CFRelease(kbdEvent); + } + else if (flags & KBD_FLAGS_RELEASE) + { + kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, FALSE); + CGEventPost(kCGHIDEventTap, kbdEvent); + CFRelease(kbdEvent); } + + CFRelease(source); } void mac_shadow_input_unicode_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 code) @@ -261,7 +265,7 @@ int mac_shadow_capture_stop(macShadowSubsystem* subsystem) return 1; } -int mac_shadow_capture_peek_dirty_region(macShadowSubsystem* subsystem) +int mac_shadow_capture_get_dirty_region(macShadowSubsystem* subsystem) { size_t index; size_t numRects; @@ -295,46 +299,6 @@ int mac_shadow_capture_peek_dirty_region(macShadowSubsystem* subsystem) return 0; } -int mac_shadow_capture_get_dirty_region(macShadowSubsystem* subsystem) -{ - dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER); - - if (subsystem->lastUpdate) - { - mac_shadow_capture_peek_dirty_region(subsystem); - } - - dispatch_semaphore_signal(subsystem->regionSemaphore); - - return 1; -} - -int mac_shadow_capture_clear_dirty_region(macShadowSubsystem* subsystem) -{ - dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER); - - CFRelease(subsystem->lastUpdate); - subsystem->lastUpdate = NULL; - - dispatch_semaphore_signal(subsystem->regionSemaphore); - - return 1; -} - -int mac_shadow_capture_surface_copy(macShadowSubsystem* subsystem) -{ - dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER); - subsystem->updateReady = TRUE; - - dispatch_semaphore_wait(subsystem->dataSemaphore, DISPATCH_TIME_FOREVER); - dispatch_semaphore_signal(subsystem->regionSemaphore); - - dispatch_semaphore_wait(subsystem->dataSemaphore, DISPATCH_TIME_FOREVER); - dispatch_semaphore_signal(subsystem->dataSemaphore); - - return 1; -} - void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef) = ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) { @@ -350,78 +314,80 @@ void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfa rdpShadowServer* server = subsystem->server; rdpShadowSurface* surface = server->surface; - if (ArrayList_Count(server->clients) < 1) - { - region16_clear(&(subsystem->invalidRegion)); - return; - } + count = ArrayList_Count(server->clients); - dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER); + if (count < 1) + return; - if (!subsystem->updateReady) - { - dispatch_semaphore_signal(subsystem->regionSemaphore); + if ((count == 1) && subsystem->suppressOutput) return; - } - mac_shadow_capture_peek_dirty_region(subsystem); + mac_shadow_capture_get_dirty_region(subsystem); - surfaceRect.left = surface->x; - surfaceRect.top = surface->y; - surfaceRect.right = surface->x + surface->width; - surfaceRect.bottom = surface->y + surface->height; + surfaceRect.left = 0; + surfaceRect.top = 0; + surfaceRect.right = surface->width; + surfaceRect.bottom = surface->height; region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect); - - if (region16_is_empty(&(subsystem->invalidRegion))) + + if (!region16_is_empty(&(subsystem->invalidRegion))) { + extents = region16_extents(&(subsystem->invalidRegion)); - } + x = extents->left; + y = extents->top; + width = extents->right - extents->left; + height = extents->bottom - extents->top; - extents = region16_extents(&(subsystem->invalidRegion)); - - x = extents->left; - y = extents->top; - width = extents->right - extents->left; - height = extents->bottom - extents->top; + IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL); - IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL); - - pSrcData = (BYTE*) IOSurfaceGetBaseAddress(frameSurface); - nSrcStep = (int) IOSurfaceGetBytesPerRow(frameSurface); + pSrcData = (BYTE*) IOSurfaceGetBaseAddress(frameSurface); + nSrcStep = (int) IOSurfaceGetBytesPerRow(frameSurface); - if (subsystem->retina) - { - freerdp_image_copy_from_retina(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, - x, y, width, height, pSrcData, nSrcStep, x, y); - } - else - { - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, - x, y, width, height, pSrcData, PIXEL_FORMAT_XRGB32, nSrcStep, x, y, NULL); - } - - IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL); - - subsystem->updateReady = FALSE; - dispatch_semaphore_signal(subsystem->dataSemaphore); - - ArrayList_Lock(server->clients); - - count = ArrayList_Count(server->clients); - - InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); - - SetEvent(subsystem->updateEvent); + if (subsystem->retina) + { + freerdp_image_copy_from_retina(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + x, y, width, height, pSrcData, nSrcStep, x, y); + } + else + { + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + x, y, width, height, pSrcData, PIXEL_FORMAT_XRGB32, nSrcStep, x, y, NULL); + } - EnterSynchronizationBarrier(&(subsystem->barrier), 0); - ResetEvent(subsystem->updateEvent); + IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL); + + ArrayList_Lock(server->clients); + + count = ArrayList_Count(server->clients); + + InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1); + + SetEvent(subsystem->updateEvent); + + EnterSynchronizationBarrier(&(subsystem->barrier), 0); - DeleteSynchronizationBarrier(&(subsystem->barrier)); + DeleteSynchronizationBarrier(&(subsystem->barrier)); - ArrayList_Unlock(server->clients); + if (count == 1) + { + rdpShadowClient* client; + + client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0); + + if (client) + { + subsystem->captureFrameRate = client->encoder->fps; + } + } - region16_clear(&(subsystem->invalidRegion)); + ResetEvent(subsystem->updateEvent); + + ArrayList_Unlock(server->clients); + + region16_clear(&(subsystem->invalidRegion)); + } if (status != kCGDisplayStreamFrameStatusFrameComplete) { @@ -451,8 +417,6 @@ void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfa subsystem->lastUpdate = CGDisplayStreamUpdateCreateMergedUpdate(tmpRef, updateRef); CFRelease(tmpRef); } - - dispatch_semaphore_signal(subsystem->regionSemaphore); }; int mac_shadow_capture_init(macShadowSubsystem* subsystem) @@ -464,11 +428,11 @@ int mac_shadow_capture_init(macShadowSubsystem* subsystem) displayId = CGMainDisplayID(); - subsystem->regionSemaphore = dispatch_semaphore_create(1); - subsystem->dataSemaphore = dispatch_semaphore_create(1); - subsystem->updateBuffer = (BYTE*) malloc(subsystem->pixelWidth * subsystem->pixelHeight * 4); + if (!subsystem->updateBuffer) + return -1; + subsystem->captureQueue = dispatch_queue_create("mac.shadow.capture", NULL); keys[0] = (void*) kCGDisplayStreamShowCursor; @@ -486,15 +450,58 @@ int mac_shadow_capture_init(macShadowSubsystem* subsystem) int mac_shadow_screen_grab(macShadowSubsystem* subsystem) { - mac_shadow_capture_get_dirty_region(subsystem); - mac_shadow_capture_surface_copy(subsystem); + return 1; +} + +int mac_shadow_subsystem_process_message(macShadowSubsystem* subsystem, wMessage* message) +{ + if (message->id == SHADOW_MSG_IN_REFRESH_OUTPUT_ID) + { + UINT32 index; + SHADOW_MSG_IN_REFRESH_OUTPUT* msg = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam; + + if (msg->numRects) + { + for (index = 0; index < msg->numRects; index++) + { + region16_union_rect(&(subsystem->invalidRegion), + &(subsystem->invalidRegion), &msg->rects[index]); + } + } + else + { + RECTANGLE_16 refreshRect; + + refreshRect.left = 0; + refreshRect.top = 0; + refreshRect.right = subsystem->width; + refreshRect.bottom = subsystem->height; + + region16_union_rect(&(subsystem->invalidRegion), + &(subsystem->invalidRegion), &refreshRect); + } + } + else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID) + { + SHADOW_MSG_IN_SUPPRESS_OUTPUT* msg = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam; + + subsystem->suppressOutput = (msg->allow) ? FALSE : TRUE; + + if (msg->allow) + { + region16_union_rect(&(subsystem->invalidRegion), + &(subsystem->invalidRegion), &(msg->rect)); + } + } + + if (message->Free) + message->Free(message); return 1; } void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) { - int fps; DWORD status; DWORD nCount; UINT64 cTime; @@ -502,15 +509,16 @@ void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) DWORD dwInterval; UINT64 frameTime; HANDLE events[32]; - HANDLE StopEvent; + wMessage message; + wMessagePipe* MsgPipe; - StopEvent = subsystem->server->StopEvent; + MsgPipe = subsystem->MsgPipe; nCount = 0; - events[nCount++] = StopEvent; + events[nCount++] = MessageQueue_Event(MsgPipe->In); - fps = 16; - dwInterval = 1000 / fps; + subsystem->captureFrameRate = 16; + dwInterval = 1000 / subsystem->captureFrameRate; frameTime = GetTickCount64() + dwInterval; while (1) @@ -520,16 +528,22 @@ void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem) status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout); - if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(MessageQueue_Event(MsgPipe->In), 0) == WAIT_OBJECT_0) { - break; + if (MessageQueue_Peek(MsgPipe->In, &message, TRUE)) + { + if (message.id == WMQ_QUIT) + break; + + mac_shadow_subsystem_process_message(subsystem, &message); + } } if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime)) { mac_shadow_screen_grab(subsystem); - dwInterval = 1000 / fps; + dwInterval = 1000 / subsystem->captureFrameRate; frameTime += dwInterval; } } @@ -583,6 +597,12 @@ int mac_shadow_subsystem_uninit(macShadowSubsystem* subsystem) { if (!subsystem) return -1; + + if (subsystem->lastUpdate) + { + CFRelease(subsystem->lastUpdate); + subsystem->lastUpdate = NULL; + } return 1; } diff --git a/server/shadow/Mac/mac_shadow.h b/server/shadow/Mac/mac_shadow.h index a5479d5..6acdd8b 100644 --- a/server/shadow/Mac/mac_shadow.h +++ b/server/shadow/Mac/mac_shadow.h @@ -47,12 +47,9 @@ struct mac_shadow_subsystem BOOL mouseDownLeft; BOOL mouseDownRight; BOOL mouseDownOther; - BOOL updateReady; BYTE* updateBuffer; CGDisplayStreamRef stream; dispatch_queue_t captureQueue; - dispatch_semaphore_t dataSemaphore; - dispatch_semaphore_t regionSemaphore; CGDisplayStreamUpdateRef lastUpdate; }; diff --git a/server/shadow/shadow_input.c b/server/shadow/shadow_input.c index 4f28b0b..f5cc078 100644 --- a/server/shadow/shadow_input.c +++ b/server/shadow/shadow_input.c @@ -43,7 +43,7 @@ void shadow_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) if (!client->mayInteract) return; - + if (subsystem->KeyboardEvent) { subsystem->KeyboardEvent(subsystem, flags, code); diff --git a/server/shadow/shadow_subsystem.c b/server/shadow/shadow_subsystem.c index 0a08c7c..f0ed9b8 100644 --- a/server/shadow/shadow_subsystem.c +++ b/server/shadow/shadow_subsystem.c @@ -145,8 +145,7 @@ int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server if (!subsystem->ep.Init) return -1; - if (subsystem->ep.Init) - status = subsystem->ep.Init(subsystem); + status = subsystem->ep.Init(subsystem); return status; } -- 2.7.4