shadow: improve Mac subsystem
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Fri, 19 Sep 2014 23:58:49 +0000 (19:58 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Fri, 19 Sep 2014 23:58:49 +0000 (19:58 -0400)
server/shadow/Mac/mac_shadow.c
server/shadow/Mac/mac_shadow.h
server/shadow/shadow_input.c
server/shadow/shadow_subsystem.c

index 9132027..7efd78b 100644 (file)
 #include <freerdp/codec/region.h>
 
 #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;
 }
index a5479d5..6acdd8b 100644 (file)
@@ -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;
 };
 
index 4f28b0b..f5cc078 100644 (file)
@@ -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);
index 0a08c7c..f0ed9b8 100644 (file)
@@ -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;
 }