20 #include <dispatch/dispatch.h>
21 #include <CoreGraphics/CoreGraphics.h>
22 #include <CoreVideo/CoreVideo.h>
23 #include <IOKit/IOKitLib.h>
24 #include <IOSurface/IOSurface.h>
26 #include "mf_mountain_lion.h"
28 dispatch_semaphore_t region_sem;
29 dispatch_semaphore_t data_sem;
30 dispatch_queue_t screen_update_q;
31 CGDisplayStreamRef stream;
33 CGDisplayStreamUpdateRef lastUpdate = NULL;
35 BYTE* localBuf = NULL;
39 void (^streamHandler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef,
40 CGDisplayStreamUpdateRef) = ^(CGDisplayStreamFrameStatus status,
41 uint64_t displayTime, IOSurfaceRef frameSurface,
42 CGDisplayStreamUpdateRef updateRef) {
43 dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
50 unsigned long offset_beg;
57 mf_mlion_peek_dirty_region(&rect);
60 IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL);
62 void* baseAddress = IOSurfaceGetBaseAddress(frameSurface);
65 stride = IOSurfaceGetBytesPerRow(frameSurface);
67 for (
int i = 0; i < rect.height; i++)
69 offset_beg = (stride * (rect.y + i) + (rect.x * 4));
70 memcpy(localBuf + offset_beg, baseAddress + offset_beg, rect.width * 4);
74 IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL);
77 dispatch_semaphore_signal(data_sem);
80 if (status != kCGDisplayStreamFrameStatusFrameComplete)
84 case kCGDisplayStreamFrameStatusFrameIdle:
87 case kCGDisplayStreamFrameStatusStopped:
90 case kCGDisplayStreamFrameStatusFrameBlank:
97 else if (lastUpdate == NULL)
100 lastUpdate = updateRef;
104 CGDisplayStreamUpdateRef tmpRef;
106 lastUpdate = CGDisplayStreamUpdateCreateMergedUpdate(tmpRef, updateRef);
110 dispatch_semaphore_signal(region_sem);
113 int mf_mlion_display_info(UINT32* disp_width, UINT32* disp_height, UINT32* scale)
115 CGDirectDisplayID display_id;
117 display_id = CGMainDisplayID();
119 CGDisplayModeRef mode = CGDisplayCopyDisplayMode(display_id);
121 size_t pixelWidth = CGDisplayModeGetPixelWidth(mode);
124 size_t wide = CGDisplayPixelsWide(display_id);
125 size_t high = CGDisplayPixelsHigh(display_id);
127 CGDisplayModeRelease(mode);
131 *scale = pixelWidth / wide;
136 int mf_mlion_screen_updates_init()
138 CGDirectDisplayID display_id;
140 display_id = CGMainDisplayID();
142 screen_update_q = dispatch_queue_create(
"mfreerdp.server.screenUpdate", NULL);
144 region_sem = dispatch_semaphore_create(1);
145 data_sem = dispatch_semaphore_create(1);
151 mf_mlion_display_info(&pixelWidth, &pixelHeight, &scale);
153 localBuf = malloc(pixelWidth * pixelHeight * 4);
157 CFDictionaryRef opts;
162 keys[0] = (
void*)kCGDisplayStreamShowCursor;
163 values[0] = (
void*)kCFBooleanFalse;
165 opts = CFDictionaryCreate(kCFAllocatorDefault, (
const void**)keys, (
const void**)values, 1,
168 stream = CGDisplayStreamCreateWithDispatchQueue(display_id, pixelWidth, pixelHeight,
'BGRA',
169 opts, screen_update_q, streamHandler);
176 int mf_mlion_start_getting_screen_updates()
180 err = CGDisplayStreamStart(stream);
182 if (err != kCGErrorSuccess)
189 int mf_mlion_stop_getting_screen_updates()
193 err = CGDisplayStreamStop(stream);
195 if (err != kCGErrorSuccess)
203 int mf_mlion_get_dirty_region(
RFX_RECT* invalid)
205 dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
207 if (lastUpdate != NULL)
209 mf_mlion_peek_dirty_region(invalid);
212 dispatch_semaphore_signal(region_sem);
217 int mf_mlion_peek_dirty_region(
RFX_RECT* invalid)
222 const CGRect* rects =
223 CGDisplayStreamUpdateGetRects(lastUpdate, kCGDisplayStreamUpdateDirtyRects, &num_rects);
230 dirtyRegion = *rects;
231 for (
size_t i = 0; i < num_rects; i++)
233 dirtyRegion = CGRectUnion(dirtyRegion, *(rects + i));
236 invalid->x = dirtyRegion.origin.x;
237 invalid->y = dirtyRegion.origin.y;
238 invalid->height = dirtyRegion.size.height;
239 invalid->width = dirtyRegion.size.width;
244 int mf_mlion_clear_dirty_region()
246 dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
248 CFRelease(lastUpdate);
251 dispatch_semaphore_signal(region_sem);
256 int mf_mlion_get_pixelData(
long x,
long y,
long width,
long height, BYTE** pxData)
258 dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
260 dispatch_semaphore_wait(data_sem, DISPATCH_TIME_FOREVER);
261 dispatch_semaphore_signal(region_sem);
264 dispatch_semaphore_wait(data_sem, DISPATCH_TIME_FOREVER);
266 dispatch_semaphore_signal(data_sem);