Преглед изворни кода

Cache CGDisplayPixelsHigh result on macOS to reduce IPC overhead

CGDisplayPixelsHigh(kCGDirectMainDisplay) involves an IPC call to the
Window Server on each invocation. Cache the main display height in
SDL_CocoaVideoData and update it only when display configuration changes,
reducing overhead during high-frequency mouse event processing.
Qiu Qiang пре 2 месеци
родитељ
комит
3ee8d1406c

+ 10 - 1
src/video/cocoa/SDL_cocoamodes.m

@@ -331,9 +331,12 @@ static bool Cocoa_GetUsableBounds(CGDirectDisplayID displayID, SDL_Rect *rect)
         return false;
     }
 
+    SDL_VideoDevice *device = SDL_GetVideoDevice();
+    SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)device->internal;
+
     const NSRect frame = [screen visibleFrame];
     rect->x = (int)frame.origin.x;
-    rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
+    rect->y = (int)(data.mainDisplayHeight - frame.origin.y - frame.size.height);
     rect->w = (int)frame.size.width;
     rect->h = (int)frame.size.height;
     return true;
@@ -493,14 +496,20 @@ static void Cocoa_DisplayReconfigurationCallback(CGDirectDisplayID displayid, CG
     if (flags & kCGDisplayDesktopShapeChangedFlag) {
         SDL_UpdateDesktopBounds();
     }
+
+    SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->internal;
+    data.mainDisplayHeight = CGDisplayPixelsHigh(kCGDirectMainDisplay);
 }
 
 void Cocoa_InitModes(SDL_VideoDevice *_this)
 {
     @autoreleasepool {
+        SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->internal;
         CGDisplayErr result;
         CGDisplayCount numDisplays = 0;
 
+        data.mainDisplayHeight = CGDisplayPixelsHigh(kCGDirectMainDisplay);
+
         result = CGGetOnlineDisplayList(0, NULL, &numDisplays);
         if (result != kCGErrorSuccess) {
             CG_SetError("CGGetOnlineDisplayList()", result);

+ 5 - 2
src/video/cocoa/SDL_cocoamouse.m

@@ -409,9 +409,11 @@ static SDL_MouseButtonFlags Cocoa_GetGlobalMouseState(float *x, float *y)
     const NSUInteger cocoaButtons = [NSEvent pressedMouseButtons];
     const NSPoint cocoaLocation = [NSEvent mouseLocation];
     SDL_MouseButtonFlags result = 0;
+    SDL_VideoDevice *device = SDL_GetVideoDevice();
+    SDL_CocoaVideoData *videodata = (__bridge SDL_CocoaVideoData *)device->internal;
 
     *x = cocoaLocation.x;
-    *y = (CGDisplayPixelsHigh(kCGDirectMainDisplay) - cocoaLocation.y);
+    *y = (videodata.mainDisplayHeight - cocoaLocation.y);
 
     result |= (cocoaButtons & (1 << 0)) ? SDL_BUTTON_LMASK : 0;
     result |= (cocoaButtons & (1 << 1)) ? SDL_BUTTON_RMASK : 0;
@@ -600,8 +602,9 @@ void Cocoa_HandleMouseEvent(SDL_VideoDevice *_this, NSEvent *event)
     deltaY = [event deltaY];
 
     if (seenWarp) {
+        SDL_CocoaVideoData *videodata = (__bridge SDL_CocoaVideoData *)_this->internal;
         deltaX += (lastMoveX - data->lastWarpX);
-        deltaY += ((CGDisplayPixelsHigh(kCGDirectMainDisplay) - lastMoveY) - data->lastWarpY);
+        deltaY += ((videodata.mainDisplayHeight - lastMoveY) - data->lastWarpY);
 
         DLog("Motion was (%g, %g), offset to (%g, %g)", [event deltaX], [event deltaY], deltaX, deltaY);
     }

+ 1 - 0
src/video/cocoa/SDL_cocoavideo.h

@@ -62,6 +62,7 @@ typedef enum
 @property(nonatomic) IOPMAssertionID screensaver_assertion;
 @property(nonatomic) SDL_Mutex *swaplock;
 @property(nonatomic) OptionAsAlt option_as_alt;
+@property(nonatomic) CGFloat mainDisplayHeight;
 @end
 
 // Utility functions

+ 4 - 2
src/video/cocoa/SDL_cocoawindow.m

@@ -507,7 +507,8 @@ static NSScreen *ScreenForRect(const NSRect *rect)
 
 static void ConvertNSRect(NSRect *r)
 {
-    r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
+    SDL_CocoaVideoData *videodata = (__bridge SDL_CocoaVideoData *)SDL_GetVideoDevice()->internal;
+    r->origin.y = videodata.mainDisplayHeight - r->origin.y - r->size.height;
 }
 
 static void ScheduleContextUpdates(SDL_CocoaWindowData *data)
@@ -2249,12 +2250,13 @@ static void Cocoa_UpdateMouseFocus()
                                   }
                                   *stop = YES;
                                   if (sdlwindow) {
+                                      SDL_CocoaVideoData *videodata = (__bridge SDL_CocoaVideoData *)vid->internal;
                                       int wx, wy;
                                       SDL_RelativeToGlobalForWindow(sdlwindow, sdlwindow->x, sdlwindow->y, &wx, &wy);
 
                                       // Calculate the cursor coordinates relative to the window.
                                       const float dx = mouseLocation.x - wx;
-                                      const float dy = (CGDisplayPixelsHigh(kCGDirectMainDisplay) - mouseLocation.y) - wy;
+                                      const float dy = (videodata.mainDisplayHeight - mouseLocation.y) - wy;
                                       SDL_SendMouseMotion(0, sdlwindow, SDL_GLOBAL_MOUSE_ID, false, dx, dy);
                                   }
                               }