//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2017 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// #include "MacOS/BsMacOSVideoModeInfo.h" #include namespace bs::ct { MacOSVideoModeInfo::MacOSVideoModeInfo() { VideoModeInfo info; CGDisplayCount numDisplays; CGGetOnlineDisplayList(0, nullptr, &numDisplays); auto displays = (CGDirectDisplayID*)bs_stack_alloc(sizeof(CGDirectDisplayID) * numDisplays); for(UINT32 i = 0; i < numDisplays; i++) { if(CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay) continue; CGDisplayModeRef modeRef = CGDisplayCopyDisplayMode(displays[i]); if(!modeRef) continue; VideoOutputInfo* output = bs_new(displays[i], i); // Make sure the primary output is the first in the output list if(CGDisplayIsMain(displays[i])) mOutputs.insert(mOutputs.begin(), output); else mOutputs.push_back(output); } bs_stack_free(displays); } MacOSVideoOutputInfo::MacOSVideoOutputInfo(CGDirectDisplayID displayID, UINT32 outputIdx) :mDisplayID(displayID) { CGDisplayModeRef desktopModeRef = CGDisplayCopyDisplayMode(displayID); CVDisplayLinkRef linkRef = nullptr; CVDisplayLinkCreateWithCGDisplay(displayID, &linkRef); io_service_t service = CGDisplayIOServicePort(displayID); CFDictionaryRef deviceInfo = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName); auto locNames = (CFDictionaryRef)CFDictionaryGetValue(deviceInfo, kDisplayProductName); CFIndex numNames = CFDictionaryGetCount(locNames); if(numNames > 0) { auto keys = (CFStringRef*)bs_stack_alloc(numNames * sizeof(CFTypeRef)); CFDictionaryGetKeysAndValues(locNames, (const void**)keys, nullptr); mName = CFStringGetCStringPtr(keys[0], kCFStringEncodingUTF8); bs_stack_free(keys); } mDesktopVideoMode = new (bs_alloc()) MacOSVideoMode(desktopModeRef, linkRef, outputIdx); CFArrayRef modes = CGDisplayCopyAllDisplayModes(displayID, nullptr); if(modes) { CFIndex count = CFArrayGetCount(modes); for(int i = 0; i < count; i++) { auto modeRef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); VideoMode* videoMode = new (bs_alloc()) MacOSVideoMode(modeRef, linkRef, outputIdx); mVideoModes.push_back(videoMode); } CFRelease(modes); } } MacOSVideoMode::MacOSVideoMode(UINT32 width, UINT32 height, float refreshRate, UINT32 outputIdx) :VideoMode(width, height, refreshRate, outputIdx), mModeRef(nullptr) { } MacOSVideoMode::MacOSVideoMode(CGDisplayModeRef mode, CVDisplayLinkRef linkRef, UINT32 outputIdx) :VideoMode(0, 0, 0.0f, outputIdx), mModeRef(mode) { mWidth = (UINT32)CGDisplayModeGetPixelWidth(mModeRef); mHeight = (UINT32)CGDisplayModeGetPixelHeight(mModeRef); mRefreshRate = (float)CGDisplayModeGetRefreshRate(mModeRef); if(mRefreshRate == 0.0f && linkRef != nullptr) { CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(linkRef); if((time.flags & kCVTimeIsIndefinite) == 0 && time.timeValue != 0) mRefreshRate = time.timeScale / (float)time.timeValue; } mIsCustom = false; } MacOSVideoMode::~MacOSVideoMode() { if(!mIsCustom && mModeRef) CGDisplayModeRelease(mModeRef); } }