BsMacOSVideoModeInfo.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2017 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "MacOS/BsMacOSVideoModeInfo.h"
  4. #include <IOKit/graphics/IOGraphicsLib.h>
  5. namespace bs::ct
  6. {
  7. MacOSVideoModeInfo::MacOSVideoModeInfo()
  8. {
  9. VideoModeInfo info;
  10. CGDisplayCount numDisplays;
  11. CGGetOnlineDisplayList(0, nullptr, &numDisplays);
  12. auto displays = (CGDirectDisplayID*)bs_stack_alloc(sizeof(CGDirectDisplayID) * numDisplays);
  13. for(UINT32 i = 0; i < numDisplays; i++)
  14. {
  15. if(CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay)
  16. continue;
  17. CGDisplayModeRef modeRef = CGDisplayCopyDisplayMode(displays[i]);
  18. if(!modeRef)
  19. continue;
  20. VideoOutputInfo* output = bs_new<MacOSVideoOutputInfo>(displays[i], i);
  21. // Make sure the primary output is the first in the output list
  22. if(CGDisplayIsMain(displays[i]))
  23. mOutputs.insert(mOutputs.begin(), output);
  24. else
  25. mOutputs.push_back(output);
  26. }
  27. bs_stack_free(displays);
  28. }
  29. MacOSVideoOutputInfo::MacOSVideoOutputInfo(CGDirectDisplayID displayID, UINT32 outputIdx)
  30. :mDisplayID(displayID)
  31. {
  32. CGDisplayModeRef desktopModeRef = CGDisplayCopyDisplayMode(displayID);
  33. CVDisplayLinkRef linkRef = nullptr;
  34. CVDisplayLinkCreateWithCGDisplay(displayID, &linkRef);
  35. io_service_t service = CGDisplayIOServicePort(displayID);
  36. CFDictionaryRef deviceInfo = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
  37. auto locNames = (CFDictionaryRef)CFDictionaryGetValue(deviceInfo, kDisplayProductName);
  38. CFIndex numNames = CFDictionaryGetCount(locNames);
  39. if(numNames > 0)
  40. {
  41. auto keys = (CFStringRef*)bs_stack_alloc(numNames * sizeof(CFTypeRef));
  42. CFDictionaryGetKeysAndValues(locNames, (const void**)keys, nullptr);
  43. mName = CFStringGetCStringPtr(keys[0], kCFStringEncodingUTF8);
  44. bs_stack_free(keys);
  45. }
  46. mDesktopVideoMode = new (bs_alloc<MacOSVideoMode>()) MacOSVideoMode(desktopModeRef, linkRef, outputIdx);
  47. CFArrayRef modes = CGDisplayCopyAllDisplayModes(displayID, nullptr);
  48. if(modes)
  49. {
  50. CFIndex count = CFArrayGetCount(modes);
  51. for(int i = 0; i < count; i++)
  52. {
  53. auto modeRef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
  54. VideoMode* videoMode = new (bs_alloc<MacOSVideoMode>()) MacOSVideoMode(modeRef, linkRef, outputIdx);
  55. mVideoModes.push_back(videoMode);
  56. }
  57. CFRelease(modes);
  58. }
  59. }
  60. MacOSVideoMode::MacOSVideoMode(UINT32 width, UINT32 height, float refreshRate, UINT32 outputIdx)
  61. :VideoMode(width, height, refreshRate, outputIdx), mModeRef(nullptr)
  62. { }
  63. MacOSVideoMode::MacOSVideoMode(CGDisplayModeRef mode, CVDisplayLinkRef linkRef, UINT32 outputIdx)
  64. :VideoMode(0, 0, 0.0f, outputIdx), mModeRef(mModeRef)
  65. {
  66. mWidth = (UINT32)CGDisplayModeGetPixelWidth(mModeRef);
  67. mHeight = (UINT32)CGDisplayModeGetPixelHeight(mModeRef);
  68. mRefreshRate = (float)CGDisplayModeGetRefreshRate(mModeRef);
  69. if(mRefreshRate == 0.0f && linkRef != nullptr)
  70. {
  71. CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(linkRef);
  72. if((time.flags & kCVTimeIsIndefinite) == 0 && time.timeValue != 0)
  73. mRefreshRate = time.timeScale / (float)time.timeValue;
  74. }
  75. mIsCustom = false;
  76. }
  77. MacOSVideoMode::~MacOSVideoMode()
  78. {
  79. if(!mIsCustom && mModeRef)
  80. CGDisplayModeRelease(mModeRef);
  81. }
  82. }