shadow: improve Mac subsystem
This commit is contained in:
parent
c4588fb14f
commit
d6250b1aec
@ -25,8 +25,10 @@
|
||||
#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)
|
||||
if (keycode < 8)
|
||||
return;
|
||||
|
||||
keycode -= 8;
|
||||
|
||||
source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
|
||||
if (flags & KBD_FLAGS_DOWN)
|
||||
{
|
||||
source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
|
||||
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);
|
||||
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));
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
if (count < 1)
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER);
|
||||
|
||||
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));
|
||||
IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL);
|
||||
|
||||
pSrcData = (BYTE*) IOSurfaceGetBaseAddress(frameSurface);
|
||||
nSrcStep = (int) IOSurfaceGetBytesPerRow(frameSurface);
|
||||
|
||||
x = extents->left;
|
||||
y = extents->top;
|
||||
width = extents->right - extents->left;
|
||||
height = extents->bottom - extents->top;
|
||||
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);
|
||||
}
|
||||
|
||||
IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL);
|
||||
|
||||
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);
|
||||
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));
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
rdpShadowClient* client;
|
||||
|
||||
client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0);
|
||||
|
||||
if (client)
|
||||
{
|
||||
subsystem->captureFrameRate = client->encoder->fps;
|
||||
}
|
||||
}
|
||||
|
||||
ResetEvent(subsystem->updateEvent);
|
||||
|
||||
ArrayList_Unlock(server->clients);
|
||||
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
}
|
||||
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);
|
||||
|
||||
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
|
||||
ResetEvent(subsystem->updateEvent);
|
||||
|
||||
DeleteSynchronizationBarrier(&(subsystem->barrier));
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user