diff --git a/panda/src/osxdisplay/osxGraphicsPipe.cxx b/panda/src/osxdisplay/osxGraphicsPipe.cxx index 94a8e413de..91a9181175 100644 --- a/panda/src/osxdisplay/osxGraphicsPipe.cxx +++ b/panda/src/osxdisplay/osxGraphicsPipe.cxx @@ -17,6 +17,145 @@ #include "pnmImage.h" #include "subprocessWindow.h" #include "nativeWindowHandle.h" +#import + +// some macros to make code more readable. +#define GetModeWidth(mode) GetDictionaryLong((mode), kCGDisplayWidth) +#define GetModeHeight(mode) GetDictionaryLong((mode), kCGDisplayHeight) +#define GetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate) +#define GetModeBitsPerPixel(mode) GetDictionaryLong((mode), kCGDisplayBitsPerPixel) +#define GetModeSafeForHardware(mode) GetDictionaryBoolean((mode), kCGDisplayModeIsSafeForHardware) +#define GetModeStretched(mode) GetDictionaryBoolean((mode), kCGDisplayModeIsStretched) +#define MAX_DISPLAYS 32 + +Boolean GetDictionaryBoolean(CFDictionaryRef theDict, const void* key) { + // get a boolean from the dictionary + Boolean value = false; + CFBooleanRef boolRef; + boolRef = (CFBooleanRef)CFDictionaryGetValue(theDict, key); + if (boolRef != NULL) + value = CFBooleanGetValue(boolRef); + return value; +} + +long GetDictionaryLong(CFDictionaryRef theDict, const void* key) { + // get a long from the dictionary + long value = 0; + CFNumberRef numRef; + numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key); + if (numRef != NULL) + CFNumberGetValue(numRef, kCFNumberLongType, &value); + return value; +} + +static CFComparisonResult CompareModes (const void *val1,const void *val2,void *context) { + // CFArray comparison callback for sorting display modes. +#pragma unused(context) + CFDictionaryRef thisMode = (CFDictionaryRef)val1; + CFDictionaryRef otherMode = (CFDictionaryRef)val2; + + long width = GetModeWidth(thisMode); + long otherWidth = GetModeWidth(otherMode); + long height = GetModeHeight(thisMode); + long otherHeight = GetModeHeight(otherMode); + + // sort modes in screen size order + if (width * height < otherWidth * otherHeight) { + return kCFCompareLessThan; + } else if (width * height > otherWidth * otherHeight) { + return kCFCompareGreaterThan; + } + + // sort modes by bits per pixel + long bitsPerPixel = GetModeBitsPerPixel(thisMode); + long otherBitsPerPixel = GetModeBitsPerPixel(otherMode); + if (bitsPerPixel < otherBitsPerPixel) { + return kCFCompareLessThan; + } else if (bitsPerPixel > otherBitsPerPixel) { + return kCFCompareGreaterThan; + } + + // sort modes by refresh rate. + long refreshRate = GetModeRefreshRate(thisMode); + long otherRefreshRate = GetModeRefreshRate(otherMode); + if (refreshRate < otherRefreshRate) { + return kCFCompareLessThan; + } else if (refreshRate > otherRefreshRate) { + return kCFCompareGreaterThan; + } + + return kCFCompareEqualTo; +} + +CFArrayRef GSCGDisplayAvailableModesUsefulForOpenGL(CGDirectDisplayID display) { + // get a list of all possible display modes for this system. + CFArrayRef availableModes = CGDisplayAvailableModes(display); + unsigned int numberOfAvailableModes = CFArrayGetCount(availableModes); + + // creat mutable array to hold the display modes we are interested int. + CFMutableArrayRef usefulModes = CFArrayCreateMutable(kCFAllocatorDefault, numberOfAvailableModes, NULL); + + // get the current bits per pixel. + long currentModeBitsPerPixel = GetModeBitsPerPixel(CGDisplayCurrentMode(display)); + + unsigned int i; + for (i= 0; i refreshRate) { + skipped = true; + break; + } + } + } + // this is a useful mode so add it to the array. + if (!replaced && !skipped) { + CFArrayAppendValue(usefulModes, mode); + } + } + // now sort the useful mode array, using the comparison callback. + CFArraySortValues( usefulModes, + CFRangeMake(0, CFArrayGetCount(usefulModes)), + (CFComparatorFunction) CompareModes, NULL); + // return the CFArray of the useful display modes. + return usefulModes; +} TypeHandle osxGraphicsPipe::_type_handle; @@ -30,6 +169,26 @@ osxGraphicsPipe() { CGRect display_bounds = CGDisplayBounds(kCGDirectMainDisplay); _display_width = CGRectGetWidth(display_bounds); _display_height = CGRectGetHeight(display_bounds); + + CGDirectDisplayID display, displayArray[MAX_DISPLAYS] ; + CGDisplayCount numDisplays; + CFDictionaryRef displayMode; + CFArrayRef displayModeArray; + int number, i; + CGGetActiveDisplayList (MAX_DISPLAYS, displayArray, &numDisplays); + display = displayArray [numDisplays - 1]; + displayModeArray = GSCGDisplayAvailableModesUsefulForOpenGL( display ); + number = CFArrayGetCount( displayModeArray ); + DisplayMode *displays = new DisplayMode[ number ]; + for(i = 0; i < number; i++) { + displayMode = (CFDictionaryRef) CFArrayGetValueAtIndex (displayModeArray, i); + _display_information -> _total_display_modes++; + displays[i].width = (signed int)GetModeWidth (displayMode); + displays[i].height = (signed int)GetModeHeight (displayMode); + displays[i].bits_per_pixel = (signed int)GetModeBitsPerPixel (displayMode); + displays[i].refresh_rate = (signed int)GetModeRefreshRate (displayMode); + } + _display_information -> _display_mode_array = displays; } ////////////////////////////////////////////////////////////////////