void TorcQMLDisplayOSX::RefreshScreenModes(void) { if (!m_window) return; // release existing modes if (m_displayModes) CFRelease(m_displayModes); m_displayModes = NULL; m_modes.clear(); // retrieve new list of modes CGDirectDisplayID display = GetOSXDisplay(m_window->winId()); if (!display) return; CGDisplayModeRef current = CGDisplayCopyDisplayMode(display); m_displayModes = CGDisplayCopyAllDisplayModes(display, NULL); if (m_displayModes) { for (int i = 0; i < CFArrayGetCount(m_displayModes); ++i) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(m_displayModes, i); int modewidth = CGDisplayModeGetWidth(mode); int modeheight = CGDisplayModeGetHeight(mode); double moderate = CGDisplayModeGetRefreshRate(mode); // internal OSX displays have 'flexible' refresh rates, with a max of 60Hz - but report 0hz if (moderate < 0.1f) moderate = 60.0f; int32_t flags = CGDisplayModeGetIOFlags(mode); bool interlaced = flags & kDisplayModeInterlacedFlag; CFStringRef fmt = CGDisplayModeCopyPixelEncoding(mode); int depth = DepthFromStringRef(fmt); CFRelease(fmt); bool ignore = modewidth != screenPixelSize.width() || modeheight != screenPixelSize.height() || (flags & kDisplayModeNotGraphicsQualityFlag) || !(flags & kDisplayModeSafetyFlags) || depth < 32 || moderate < 10.0f || moderate > 121.0f; LOG(VB_GENERAL, LOG_INFO, QString("Mode %1x%2@%3Hz %4bpp%5%6%7") .arg(modewidth).arg(modeheight).arg(moderate).arg(depth) .arg(interlaced ? QString(" Interlaced") : "") .arg(ignore ? QString(" Ignoring") : "") .arg(mode == current ? QString(" CURRENT"): "")); if (!ignore) { if (mode == current) { setScreenInterlaced(interlaced); setScreenRefreshRate(moderate); } m_modes.append(TorcDisplayMode(modewidth, modeheight, depth, moderate, interlaced, i)); } } } }
/*********************************************************************** * macdrv_displays_changed * * Handler for DISPLAYS_CHANGED events. */ void macdrv_displays_changed(const macdrv_event *event) { HWND hwnd = GetDesktopWindow(); /* A system display change will get delivered to all GUI-attached threads, so the desktop-window-owning thread will get it and all others should ignore it. A synthesized display change event due to activation will only get delivered to the activated process. So, it needs to process it (by sending it to the desktop window). */ if (event->displays_changed.activating || GetWindowThreadProcessId(hwnd, NULL) == GetCurrentThreadId()) { CGDirectDisplayID mainDisplay = CGMainDisplayID(); CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay); size_t width = CGDisplayModeGetWidth(mode); size_t height = CGDisplayModeGetHeight(mode); int mode_bpp = display_mode_bits_per_pixel(mode); struct display_mode_descriptor* desc = create_original_display_mode_descriptor(mainDisplay); BOOL is_original = display_mode_matches_descriptor(mode, desc); free_display_mode_descriptor(desc); CGDisplayModeRelease(mode); if (is_original && retina_enabled) { width *= 2; height *= 2; } SendMessageW(hwnd, WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp, MAKELPARAM(width, height)); } }
static BOOL display_mode_matches_descriptor(CGDisplayModeRef mode, const struct display_mode_descriptor* desc) { DWORD mode_io_flags; double mode_refresh; CFStringRef mode_pixel_encoding; if (!desc) return FALSE; if (CGDisplayModeGetWidth(mode) != desc->width || CGDisplayModeGetHeight(mode) != desc->height) return FALSE; mode_io_flags = CGDisplayModeGetIOFlags(mode); if ((desc->io_flags ^ mode_io_flags) & (kDisplayModeValidFlag | kDisplayModeSafeFlag | kDisplayModeStretchedFlag | kDisplayModeInterlacedFlag | kDisplayModeTelevisionFlag)) return FALSE; mode_refresh = CGDisplayModeGetRefreshRate(mode); if (!mode_refresh) mode_refresh = 60; if (fabs(desc->refresh - mode_refresh) > 0.1) return FALSE; #if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 if (CGDisplayModeGetPixelWidth != NULL && CGDisplayModeGetPixelHeight != NULL) { if (CGDisplayModeGetPixelWidth(mode) != desc->pixel_width || CGDisplayModeGetPixelHeight(mode) != desc->pixel_height) return FALSE; } else #endif if (CGDisplayModeGetWidth(mode) != desc->pixel_width || CGDisplayModeGetHeight(mode) != desc->pixel_height) return FALSE; mode_pixel_encoding = CGDisplayModeCopyPixelEncoding(mode); if (!CFEqual(mode_pixel_encoding, desc->pixel_encoding)) { CFRelease(mode_pixel_encoding); return FALSE; } CFRelease(mode_pixel_encoding); return TRUE; }
// Search for available resolutions - TODO: Move to Common? static wxArrayString GetListOfResolutions() { wxArrayString retlist; retlist.Add(_("Auto")); #ifdef _WIN32 DWORD iModeNum = 0; DEVMODE dmi; ZeroMemory(&dmi, sizeof(dmi)); dmi.dmSize = sizeof(dmi); std::vector<std::string> resos; while (EnumDisplaySettings(nullptr, iModeNum++, &dmi) != 0) { char res[100]; sprintf(res, "%dx%d", dmi.dmPelsWidth, dmi.dmPelsHeight); std::string strRes(res); // Only add unique resolutions if (std::find(resos.begin(), resos.end(), strRes) == resos.end()) { resos.push_back(strRes); retlist.Add(StrToWxStr(res)); } ZeroMemory(&dmi, sizeof(dmi)); } #elif defined(HAVE_XRANDR) && HAVE_XRANDR std::vector<std::string> resos; main_frame->m_XRRConfig->AddResolutions(resos); for (auto res : resos) retlist.Add(StrToWxStr(res)); #elif defined(__APPLE__) CFArrayRef modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), nullptr); for (CFIndex i = 0; i < CFArrayGetCount(modes); i++) { std::stringstream res; CGDisplayModeRef mode; CFStringRef encoding; size_t w, h; bool is32; mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); w = CGDisplayModeGetWidth(mode); h = CGDisplayModeGetHeight(mode); encoding = CGDisplayModeCopyPixelEncoding(mode); is32 = CFEqual(encoding, CFSTR(IO32BitDirectPixels)); CFRelease(encoding); if (!is32) continue; if (CGDisplayModeGetIOFlags(mode) & kDisplayModeStretchedFlag) continue; res << w << "x" << h; retlist.Add(res.str()); } CFRelease(modes); #endif return retlist; }
static void QuartzRandRGetModeInfo(CGDisplayModeRef modeRef, QuartzModeInfoPtr pMode) { pMode->width = CGDisplayModeGetWidth(modeRef); pMode->height = CGDisplayModeGetHeight(modeRef); pMode->refresh = (int)(CGDisplayModeGetRefreshRate(modeRef) + 0.5); if (pMode->refresh == 0) pMode->refresh = DEFAULT_REFRESH; pMode->ref = NULL; pMode->pSize = NULL; }
/********************************************************************** * device_init * * Perform initializations needed upon creation of the first device. */ static void device_init(void) { CGDirectDisplayID mainDisplay = CGMainDisplayID(); CGSize size_mm = CGDisplayScreenSize(mainDisplay); CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay); check_retina_status(); /* Initialize device caps */ horz_size = size_mm.width; vert_size = size_mm.height; bits_per_pixel = 32; if (mode) { CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); horz_res = CGDisplayModeGetWidth(mode); vert_res = CGDisplayModeGetHeight(mode); if (pixelEncoding) { if (CFEqual(pixelEncoding, CFSTR(IO32BitDirectPixels))) bits_per_pixel = 32; else if (CFEqual(pixelEncoding, CFSTR(IO16BitDirectPixels))) bits_per_pixel = 16; else if (CFEqual(pixelEncoding, CFSTR(IO8BitIndexedPixels))) bits_per_pixel = 8; CFRelease(pixelEncoding); } CGDisplayModeRelease(mode); } else { horz_res = CGDisplayPixelsWide(mainDisplay); vert_res = CGDisplayPixelsHigh(mainDisplay); } if (retina_on) { horz_res *= 2; vert_res *= 2; } compute_desktop_rect(); desktop_horz_res = desktop_rect.size.width; desktop_vert_res = desktop_rect.size.height; device_data_valid = TRUE; }
static CFDictionaryRef create_mode_dict(CGDisplayModeRef display_mode, BOOL is_original) { CFDictionaryRef ret; SInt32 io_flags = CGDisplayModeGetIOFlags(display_mode); SInt64 width = CGDisplayModeGetWidth(display_mode); SInt64 height = CGDisplayModeGetHeight(display_mode); double refresh_rate = CGDisplayModeGetRefreshRate(display_mode); CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(display_mode); CFNumberRef cf_io_flags, cf_width, cf_height, cf_refresh; if (retina_enabled && is_original) { width *= 2; height *= 2; } io_flags &= kDisplayModeValidFlag | kDisplayModeSafeFlag | kDisplayModeInterlacedFlag | kDisplayModeStretchedFlag | kDisplayModeTelevisionFlag; cf_io_flags = CFNumberCreate(NULL, kCFNumberSInt32Type, &io_flags); cf_width = CFNumberCreate(NULL, kCFNumberSInt64Type, &width); cf_height = CFNumberCreate(NULL, kCFNumberSInt64Type, &height); cf_refresh = CFNumberCreate(NULL, kCFNumberDoubleType, &refresh_rate); { static const CFStringRef keys[] = { CFSTR("io_flags"), CFSTR("width"), CFSTR("height"), CFSTR("pixel_encoding"), CFSTR("refresh_rate"), }; const void* values[sizeof(keys) / sizeof(keys[0])] = { cf_io_flags, cf_width, cf_height, pixel_encoding, cf_refresh, }; ret = CFDictionaryCreate(NULL, (const void**)keys, (const void**)values, sizeof(keys) / sizeof(keys[0]), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } CFRelease(pixel_encoding); CFRelease(cf_io_flags); CFRelease(cf_width); CFRelease(cf_height); CFRelease(cf_refresh); return ret; }
unsigned int listCurrentMode(CGDirectDisplayID display, int displayNum) { unsigned int returncode = 1; CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(display); if (currentMode == NULL) { NSLog(CFSTR("%s"), "Error: unable to copy current display mode"); returncode = 0; } NSLog(CFSTR("Display %d: %ux%ux%u@%.0f"), displayNum, CGDisplayModeGetWidth(currentMode), CGDisplayModeGetHeight(currentMode), bitDepth(currentMode), CGDisplayModeGetRefreshRate(currentMode)); CGDisplayModeRelease(currentMode); return returncode; }
int fs_ml_video_mode_get_current(fs_ml_video_mode *mode) { mode->width = 0; mode->height = 0; mode->fps = 0; mode->bpp = 0; mode->flags = 0; #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 // CGDisplayCurrentMode is deprecated in Mac OS X 10.6, so we use // the new API here CGDirectDisplayID currentDisplay = CGDisplayPrimaryDisplay( kCGDirectMainDisplay); CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode( currentDisplay); mode->width = CGDisplayModeGetWidth(currentMode); mode->height = CGDisplayModeGetHeight(currentMode); mode->fps = CGDisplayModeGetRefreshRate(currentMode); CGDisplayModeRelease(currentMode); #else CFNumberRef number; long refresh, width, height; CFDictionaryRef currentMode = CGDisplayCurrentMode(kCGDirectMainDisplay); number = CFDictionaryGetValue(currentMode, kCGDisplayWidth); CFNumberGetValue(number, kCFNumberLongType, &width); number = CFDictionaryGetValue(currentMode, kCGDisplayHeight); CFNumberGetValue(number, kCFNumberLongType, &height); number = CFDictionaryGetValue(currentMode, kCGDisplayRefreshRate); CFNumberGetValue(number, kCFNumberLongType, &refresh); mode->width = width; mode->height = height; mode->fps = refresh; #endif //fs_log("WARNING: assuming 60 Hz refresh rate on Mac OS X\n"); //mode->fps = 60; if (mode->fps == 0) { fs_log("WARNING: refresh rate was not detected\n"); fs_log("full video sync will not be enabled automatically, but can " "be forced\n"); } return 0; }
unsigned int configureDisplay(CGDirectDisplayID display, struct config *config, int displayNum) { unsigned int returncode = 1; CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); if (allModes == NULL) { NSLog(CFSTR("Error: failed trying to look up modes for display %u"), displayNum); } CGDisplayModeRef newMode = NULL; CGDisplayModeRef possibleMode; size_t pw; // possible width. size_t ph; // possible height. size_t pd; // possible depth. double pr; // possible refresh rate int looking = 1; // used to decide whether to continue looking for modes. int i; for (i = 0 ; i < CFArrayGetCount(allModes) && looking; i++) { possibleMode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); pw = CGDisplayModeGetWidth(possibleMode); ph = CGDisplayModeGetHeight(possibleMode); pd = bitDepth(possibleMode); pr = CGDisplayModeGetRefreshRate(possibleMode); if (pw == config->w && ph == config->h && pd == config->d && pr == config->r) { looking = 0; // Stop looking for more modes! newMode = possibleMode; } } CFRelease(allModes); if (newMode != NULL) { NSLog(CFSTR("set mode on display %u to %ux%ux%u@%.0f"), displayNum, pw, ph, pd, pr); setDisplayToMode(display,newMode); } else { NSLog(CFSTR("Error: mode %ux%ux%u@%f not available on display %u"), config->w, config->h, config->d, config->r, displayNum); returncode = 0; } return returncode; }
bool DisplayManagerOSX::initialize() { int totalModes = 0; m_displays.clear(); for (int i = 0; i < m_osxDisplayModes.size(); i++) { if (m_osxDisplayModes[i]) CFRelease(m_osxDisplayModes[i]); } m_osxDisplayModes.clear(); CGError err = CGGetActiveDisplayList(MAX_DISPLAYS, m_osxDisplays, &m_osxnumDisplays); if (err) { m_osxnumDisplays = 0; QLOG_ERROR() << "CGGetActiveDisplayList returned failure:" << err; return false; } for (int displayid = 0; displayid < m_osxnumDisplays; displayid++) { // add the display to the list DMDisplayPtr display = DMDisplayPtr(new DMDisplay); display->m_id = displayid; display->m_name = QString("Display %1").arg(displayid); m_displays[display->m_id] = display; m_osxDisplayModes[displayid] = CGDisplayCopyAllDisplayModes(m_osxDisplays[displayid], nullptr); if (!m_osxDisplayModes[displayid]) continue; int numModes = (int)CFArrayGetCount(m_osxDisplayModes[displayid]); for (int modeid = 0; modeid < numModes; modeid++) { totalModes++; // add the videomode to the display DMVideoModePtr mode = DMVideoModePtr(new DMVideoMode); mode->m_id = modeid; display->m_videoModes[modeid] = mode; // grab videomode info CGDisplayModeRef displayMode = (CGDisplayModeRef)CFArrayGetValueAtIndex(m_osxDisplayModes[displayid], modeid); mode->m_height = CGDisplayModeGetHeight(displayMode); mode->m_width = CGDisplayModeGetWidth(displayMode); mode->m_refreshRate = CGDisplayModeGetRefreshRate(displayMode); CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(displayMode); if (CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) mode->m_bitsPerPixel = 32; else if (CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) mode->m_bitsPerPixel = 16; else if (CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) mode->m_bitsPerPixel = 8; CFRelease(pixEnc); mode->m_interlaced = (CGDisplayModeGetIOFlags(displayMode) & kDisplayModeInterlacedFlag) > 0; if (mode->m_refreshRate == 0) mode->m_refreshRate = 60; } } if (totalModes == 0) return false; else return DisplayManager::initialize(); }
VideoMode convertCGModeToSFMode(CGDisplayModeRef cgmode) { return VideoMode(CGDisplayModeGetWidth(cgmode), CGDisplayModeGetHeight(cgmode), modeBitsPerPixel(cgmode)); }
//-------------------------------------------------------------------------------------------------// void OSXWindow::createCGLFullscreen(unsigned int width, unsigned int height, unsigned int depth, unsigned int fsaa, CGLContextObj sharedContext) { // Find the best match to what was requested boolean_t exactMatch = 0; int reqWidth, reqHeight, reqDepth; #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 // Get a copy of the current display mode CGDisplayModeRef displayMode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay); // Loop through all display modes to determine the closest match. // CGDisplayBestModeForParameters is deprecated on 10.6 so we will emulate it's behavior // Try to find a mode with the requested depth and equal or greater dimensions first. // If no match is found, try to find a mode with greater depth and same or greater dimensions. // If still no match is found, just use the current mode. CFArrayRef allModes = CGDisplayCopyAllDisplayModes(kCGDirectMainDisplay, NULL); for(int i = 0; i < CFArrayGetCount(allModes); i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); String modeString = StringConverter::toString(CGDisplayModeGetWidth(mode)) + String(" x ") + StringConverter::toString(CGDisplayModeGetHeight(mode)) + String(" @ ") + StringConverter::toString(bitDepthFromDisplayMode(mode)) + "bpp."; LogManager::getSingleton().logMessage(modeString); if(bitDepthFromDisplayMode(mode) != depth) continue; if((CGDisplayModeGetWidth(mode) >= width) && (CGDisplayModeGetHeight(mode) >= height)) { displayMode = mode; exactMatch = 1; break; } } // No depth match was found if(!exactMatch) { for(int i = 0; i < CFArrayGetCount(allModes); i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); if(bitDepthFromDisplayMode(mode) >= depth) continue; if((CGDisplayModeGetWidth(mode) >= width) && (CGDisplayModeGetHeight(mode) >= height)) { displayMode = mode; exactMatch = 1; break; } } } reqWidth = CGDisplayModeGetWidth(displayMode); reqHeight = CGDisplayModeGetHeight(displayMode); reqDepth = bitDepthFromDisplayMode(displayMode); #else CFDictionaryRef displayMode = CGDisplayBestModeForParameters(kCGDirectMainDisplay, depth, width, height, &exactMatch); const void *value = NULL; value = CFDictionaryGetValue(displayMode, kCGDisplayWidth); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &reqWidth); value = CFDictionaryGetValue(displayMode, kCGDisplayHeight); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &reqHeight); value = CFDictionaryGetValue(displayMode, kCGDisplayBitsPerPixel); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &reqDepth); #endif if(!exactMatch) { // TODO: Report the size difference // That mode is not available, using the closest match String request = StringConverter::toString(width) + String(" x ") + StringConverter::toString(height) + String(" @ ") + StringConverter::toString(depth) + "bpp. "; String received = StringConverter::toString(reqWidth) + String(" x ") + StringConverter::toString(reqHeight) + String(" @ ") + StringConverter::toString(reqDepth) + "bpp. "; LogManager::getSingleton().logMessage(String("RenderSystem Warning: You requested a fullscreen mode of ") + request + String(" This mode is not available and you will receive the closest match. The best display mode for the parameters requested is: ") + received); } // Do the fancy display fading CGDisplayFadeReservationToken reservationToken; CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &reservationToken); CGDisplayFade(reservationToken, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true); // Grab the main display and save it for later. // You could render to any display, but picking what display // to render to could be interesting. CGDisplayCapture(kCGDirectMainDisplay); // Switch to the correct resolution #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 CGDisplaySetDisplayMode(kCGDirectMainDisplay, displayMode, NULL); #else CGDisplaySwitchToMode(kCGDirectMainDisplay, displayMode); #endif // Get a pixel format that best matches what we are looking for CGLPixelFormatAttribute attribs[] = { kCGLPFADoubleBuffer, kCGLPFAAlphaSize, (CGLPixelFormatAttribute)8, kCGLPFADepthSize, (CGLPixelFormatAttribute)reqDepth, kCGLPFAStencilSize, (CGLPixelFormatAttribute)8, kCGLPFASampleBuffers, (CGLPixelFormatAttribute)0, kCGLPFASamples, (CGLPixelFormatAttribute)0, kCGLPFAFullScreen, kCGLPFASingleRenderer, kCGLPFAAccelerated, kCGLPFADisplayMask, (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), (CGLPixelFormatAttribute)0 }; // Set up FSAA if it was requested if(fsaa > 1) { // turn on kCGLPFASampleBuffers attribs[8] = (CGLPixelFormatAttribute)1; // set the samples for kCGLPFASamples attribs[10] = (CGLPixelFormatAttribute)fsaa; } CGLError err; CGLPixelFormatObj pixelFormatObj; #if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4) GLint numPixelFormats = 0; err = CGLChoosePixelFormat(attribs, &pixelFormatObj, &numPixelFormats); #else long numPixelFormats = 0; err = CGLChoosePixelFormat(attribs, &pixelFormatObj, &numPixelFormats); #endif if(err != 0) { CGReleaseAllDisplays(); OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, String("CGL Error: " + String(CGLErrorString(err))), "OSXWindow::createCGLFullscreen"); } // Create the CGLcontext from our pixel format, share it with the sharedContext passed in err = CGLCreateContext(pixelFormatObj, sharedContext, &mCGLContext); if(err != 0) { CGReleaseAllDisplays(); OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, String("CGL Error: " + String(CGLErrorString(err))), "OSXWindow::createCGLFullscreen"); } // Once we have the context we can destroy the pixel format // In order to share contexts you must keep a pointer to the context object around // Our context class will now manage the life of the pixelFormatObj //CGLDestroyPixelFormat(pixelFormatObj); // Set the context to full screen #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 CGLSetFullScreenOnDisplay(mCGLContext, CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay)); #else CGLSetFullScreen(mCGLContext); #endif // Set the context as current CGLSetCurrentContext(mCGLContext); // This synchronizes CGL with the vertical retrace // Apple docs suggest that OpenGL blocks rendering calls when waiting for // a vertical retrace anyhow. #if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4) GLint swapInterval = 1; CGLSetParameter(mCGLContext, kCGLCPSwapInterval, &swapInterval); #else long swapInterval = 1; CGLSetParameter(mCGLContext, kCGLCPSwapInterval, &swapInterval); #endif // Give a copy of our context to the rendersystem mContext = new OSXCGLContext(mCGLContext, pixelFormatObj); // Let everyone know we are fullscreen now mIsFullScreen = true; // Set some other variables. Just in case we got a different value from CGDisplayBestModeForParameters than we requested mWidth = reqWidth; mHeight = reqHeight; mColourDepth = reqDepth; CGDisplayFade(reservationToken, 2.0, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false); CGReleaseDisplayFadeReservation(reservationToken); }
/********************************************************************** * device_init * * Perform initializations needed upon creation of the first device. */ static void device_init(void) { CGDirectDisplayID mainDisplay = CGMainDisplayID(); CGSize size_mm = CGDisplayScreenSize(mainDisplay); CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay); CGDirectPaletteRef palette; /* Initialize device caps */ log_pixels_x = log_pixels_y = get_dpi(); if (!log_pixels_x) { size_t width = CGDisplayPixelsWide(mainDisplay); size_t height = CGDisplayPixelsHigh(mainDisplay); log_pixels_x = MulDiv(width, 254, size_mm.width * 10); log_pixels_y = MulDiv(height, 254, size_mm.height * 10); } horz_size = size_mm.width; vert_size = size_mm.height; bits_per_pixel = 32; if (mode) { CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); horz_res = CGDisplayModeGetWidth(mode); vert_res = CGDisplayModeGetHeight(mode); if (pixelEncoding) { if (CFEqual(pixelEncoding, CFSTR(IO32BitDirectPixels))) bits_per_pixel = 32; else if (CFEqual(pixelEncoding, CFSTR(IO16BitDirectPixels))) bits_per_pixel = 16; else if (CFEqual(pixelEncoding, CFSTR(IO8BitIndexedPixels))) bits_per_pixel = 8; CFRelease(pixelEncoding); } CGDisplayModeRelease(mode); } else { horz_res = CGDisplayPixelsWide(mainDisplay); vert_res = CGDisplayPixelsHigh(mainDisplay); } macdrv_get_desktop_rect(); desktop_horz_res = desktop_rect.size.width; desktop_vert_res = desktop_rect.size.height; palette = CGPaletteCreateWithDisplay(mainDisplay); if (palette) { palette_size = CGPaletteGetNumberOfSamples(palette); CGPaletteRelease(palette); } else palette_size = 0; device_data_valid = TRUE; }
bool macosxSetScreenResolution(QSize resolution, QPoint screenPoint) { CGDirectDisplayID display = displayAtPoint(screenPoint); if (display == kCGNullDirectDisplay) { return false; } #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 if (CGDisplayCopyAllDisplayModes != NULL) { bool ok = false; CGDisplayModeRef currentMainDisplayMode = CGDisplayCopyDisplayMode(display); CFStringRef currentPixelEncoding = CGDisplayModeCopyPixelEncoding(currentMainDisplayMode); CFArrayRef displayModes = CGDisplayCopyAllDisplayModes(display, NULL); for (CFIndex i = 0, c = CFArrayGetCount(displayModes); i < c; i++) { bool isEqual = false; CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(displayModes, i); CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); if (CFStringCompare(pixelEncoding, currentPixelEncoding, 0) == kCFCompareEqualTo && CGDisplayModeGetWidth(mode) == (size_t)resolution.width() && CGDisplayModeGetHeight(mode) == (size_t)resolution.height()) { isEqual = true; } CFRelease(pixelEncoding); if (isEqual) { CGDisplaySetDisplayMode(display, mode, NULL); ok = true; break; } } CFRelease(currentPixelEncoding); CFRelease(displayModes); return ok; } else #endif { CFDictionaryRef currentMainDisplayMode = CGDisplayCurrentMode(display); int bpp; dictget(currentMainDisplayMode, Int, kCGDisplayBitsPerPixel, &bpp); boolean_t exactMatch = false; CFDictionaryRef bestMode = CGDisplayBestModeForParameters(display, bpp, resolution.width(), resolution.height(), &exactMatch); if (bestMode != NULL) { if (!exactMatch) { qWarning("No optimal display mode for requested parameters."); } CGDisplaySwitchToMode(display, bestMode); return true; } else { qWarning("Bad resolution change: Invalid display."); return false; } } }
/*********************************************************************** * EnumDisplaySettingsEx (MACDRV.@) * */ BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmode, DWORD flags) { static const WCHAR dev_name[CCHDEVICENAME] = { 'W','i','n','e',' ','M','a','c',' ','d','r','i','v','e','r',0 }; struct macdrv_display *displays = NULL; int num_displays; CGDisplayModeRef display_mode; int display_mode_bpp; BOOL synthesized = FALSE; double rotation; uint32_t io_flags; TRACE("%s, %u, %p + %hu, %08x\n", debugstr_w(devname), mode, devmode, devmode->dmSize, flags); init_original_display_mode(); memcpy(devmode->dmDeviceName, dev_name, sizeof(dev_name)); devmode->dmSpecVersion = DM_SPECVERSION; devmode->dmDriverVersion = DM_SPECVERSION; devmode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod); devmode->dmDriverExtra = 0; memset(&devmode->dmFields, 0, devmode->dmSize - FIELD_OFFSET(DEVMODEW, dmFields)); if (mode == ENUM_REGISTRY_SETTINGS) { TRACE("mode %d (registry) -- getting default mode\n", mode); return read_registry_settings(devmode); } if (macdrv_get_displays(&displays, &num_displays)) goto failed; if (mode == ENUM_CURRENT_SETTINGS) { TRACE("mode %d (current) -- getting current mode\n", mode); display_mode = CGDisplayCopyDisplayMode(displays[0].displayID); display_mode_bpp = display_mode_bits_per_pixel(display_mode); } else { DWORD count, i; EnterCriticalSection(&modes_section); if (mode == 0 || !modes) { if (modes) CFRelease(modes); modes = copy_display_modes(displays[0].displayID); modes_has_8bpp = modes_has_16bpp = FALSE; if (modes) { count = CFArrayGetCount(modes); for (i = 0; i < count && !(modes_has_8bpp && modes_has_16bpp); i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); int bpp = display_mode_bits_per_pixel(mode); if (bpp == 8) modes_has_8bpp = TRUE; else if (bpp == 16) modes_has_16bpp = TRUE; } } } display_mode = NULL; if (modes) { int default_bpp = get_default_bpp(); DWORD seen_modes = 0; count = CFArrayGetCount(modes); for (i = 0; i < count; i++) { CGDisplayModeRef candidate = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); io_flags = CGDisplayModeGetIOFlags(candidate); if (!(flags & EDS_RAWMODE) && (!(io_flags & kDisplayModeValidFlag) || !(io_flags & kDisplayModeSafeFlag))) continue; seen_modes++; if (seen_modes > mode) { display_mode = (CGDisplayModeRef)CFRetain(candidate); display_mode_bpp = display_mode_bits_per_pixel(display_mode); break; } /* We only synthesize modes from those having the default bpp. */ if (display_mode_bits_per_pixel(candidate) != default_bpp) continue; if (!modes_has_8bpp) { seen_modes++; if (seen_modes > mode) { display_mode = (CGDisplayModeRef)CFRetain(candidate); display_mode_bpp = 8; synthesized = TRUE; break; } } if (!modes_has_16bpp) { seen_modes++; if (seen_modes > mode) { display_mode = (CGDisplayModeRef)CFRetain(candidate); display_mode_bpp = 16; synthesized = TRUE; break; } } } } LeaveCriticalSection(&modes_section); } if (!display_mode) goto failed; /* We currently only report modes for the primary display, so it's at (0, 0). */ devmode->dmPosition.x = 0; devmode->dmPosition.y = 0; devmode->dmFields |= DM_POSITION; rotation = CGDisplayRotation(displays[0].displayID); devmode->dmDisplayOrientation = ((int)((rotation / 90) + 0.5)) % 4; devmode->dmFields |= DM_DISPLAYORIENTATION; io_flags = CGDisplayModeGetIOFlags(display_mode); if (io_flags & kDisplayModeStretchedFlag) devmode->dmDisplayFixedOutput = DMDFO_STRETCH; else devmode->dmDisplayFixedOutput = DMDFO_CENTER; devmode->dmFields |= DM_DISPLAYFIXEDOUTPUT; devmode->dmBitsPerPel = display_mode_bpp; if (devmode->dmBitsPerPel) devmode->dmFields |= DM_BITSPERPEL; devmode->dmPelsWidth = CGDisplayModeGetWidth(display_mode); devmode->dmPelsHeight = CGDisplayModeGetHeight(display_mode); devmode->dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT; devmode->dmDisplayFlags = 0; if (io_flags & kDisplayModeInterlacedFlag) devmode->dmDisplayFlags |= DM_INTERLACED; devmode->dmFields |= DM_DISPLAYFLAGS; devmode->dmDisplayFrequency = CGDisplayModeGetRefreshRate(display_mode); if (!devmode->dmDisplayFrequency) devmode->dmDisplayFrequency = 60; devmode->dmFields |= DM_DISPLAYFREQUENCY; CFRelease(display_mode); macdrv_free_displays(displays); TRACE("mode %d -- %dx%dx%dbpp @%d Hz", mode, devmode->dmPelsWidth, devmode->dmPelsHeight, devmode->dmBitsPerPel, devmode->dmDisplayFrequency); if (devmode->dmDisplayOrientation) TRACE(" rotated %u degrees", devmode->dmDisplayOrientation * 90); if (devmode->dmDisplayFixedOutput == DMDFO_STRETCH) TRACE(" stretched"); if (devmode->dmDisplayFlags & DM_INTERLACED) TRACE(" interlaced"); if (synthesized) TRACE(" (synthesized)"); TRACE("\n"); return TRUE; failed: TRACE("mode %d -- not present\n", mode); if (displays) macdrv_free_displays(displays); SetLastError(ERROR_NO_MORE_FILES); return FALSE; }
bool macosxAppendAvailableScreenResolutions(QList<QSize> &resolutions, QSize minSize, QPoint screenPoint) { CGDirectDisplayID display = displayAtPoint(screenPoint); if (display == kCGNullDirectDisplay) { return false; } #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 bool modern = (CGDisplayCopyAllDisplayModes != NULL); // where 'modern' means >= 10.6 #endif CFArrayRef displayModes; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 if (modern) { displayModes = CGDisplayCopyAllDisplayModes(display, NULL); } else #endif { displayModes = CGDisplayAvailableModes(display); } #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 CFStringRef currentPixelEncoding = NULL; #endif double currentRefreshRate; int curBPP, curBPS, curSPP; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 if (modern) { CGDisplayModeRef currentDisplayMode = CGDisplayCopyDisplayMode(display); currentRefreshRate = CGDisplayModeGetRefreshRate(currentDisplayMode); currentPixelEncoding = CGDisplayModeCopyPixelEncoding(currentDisplayMode); CFRelease(currentDisplayMode); } else #endif { CFDictionaryRef currentDisplayMode = CGDisplayCurrentMode(display); dictget(currentDisplayMode, Double, kCGDisplayRefreshRate, ¤tRefreshRate); dictget(currentDisplayMode, Int, kCGDisplayBitsPerPixel, &curBPP); dictget(currentDisplayMode, Int, kCGDisplayBitsPerSample, &curBPS); dictget(currentDisplayMode, Int, kCGDisplaySamplesPerPixel, &curSPP); } for (CFIndex j = 0, c = CFArrayGetCount(displayModes); j < c; j++) { int width, height; double refreshRate; bool pixelEncodingsEqual; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 if (modern) { CGDisplayModeRef displayMode = (CGDisplayModeRef)CFArrayGetValueAtIndex(displayModes, j); width = (int)CGDisplayModeGetWidth(displayMode); height = (int)CGDisplayModeGetHeight(displayMode); refreshRate = CGDisplayModeGetRefreshRate(displayMode); CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(displayMode); pixelEncodingsEqual = (CFStringCompare(pixelEncoding, currentPixelEncoding, 0) == kCFCompareEqualTo); CFRelease(pixelEncoding); } else #endif { CFDictionaryRef displayMode = (CFDictionaryRef)CFArrayGetValueAtIndex(displayModes, j); dictget(displayMode, Int, kCGDisplayWidth, &width); dictget(displayMode, Int, kCGDisplayHeight, &height); dictget(displayMode, Double, kCGDisplayRefreshRate, &refreshRate); int bpp, bps, spp; dictget(displayMode, Int, kCGDisplayBitsPerPixel, &bpp); dictget(displayMode, Int, kCGDisplayBitsPerSample, &bps); dictget(displayMode, Int, kCGDisplaySamplesPerPixel, &spp); pixelEncodingsEqual = (bpp == curBPP && bps == curBPS && spp == curSPP); } QSize res(width, height); if (!resolutions.contains(res) && width >= minSize.width() && height >= minSize.height() && refreshRate == currentRefreshRate && pixelEncodingsEqual) { resolutions += res; } } #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 if (modern) { CFRelease(currentPixelEncoding); CFRelease(displayModes); } #endif return true; }
unsigned int listAvailableModes(CGDirectDisplayID display, int displayNum) { unsigned int returncode = 1; int i; CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); if (allModes == NULL) { returncode = 0; } #ifndef LIST_DEBUG printf("Available Modes on Display %d\n", displayNum); #endif CGDisplayModeRef mode; for (i = 0; i < CFArrayGetCount(allModes) && returncode; i++) { mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(allModes, i); // This formatting is functional but it ought to be done less poorly. #ifndef LIST_DEBUG if (i % MODES_PER_LINE == 0) { printf(" "); } else { printf("\t"); } char modestr [50]; sprintf(modestr, "%lux%lux%lu@%.0f", CGDisplayModeGetWidth(mode), CGDisplayModeGetHeight(mode), bitDepth(mode), CGDisplayModeGetRefreshRate(mode)); printf("%-20s ", modestr); if (i % MODES_PER_LINE == MODES_PER_LINE - 1) { printf("\n"); } #else uint32_t ioflags = CGDisplayModeGetIOFlags(mode); printf("display: %d %4lux%4lux%2lu@%.0f usable:%u ioflags:%4x valid:%u safe:%u default:%u", displayNum, CGDisplayModeGetWidth(mode), CGDisplayModeGetHeight(mode), bitDepth(mode), CGDisplayModeGetRefreshRate(mode), CGDisplayModeIsUsableForDesktopGUI(mode), ioflags, ioflags & kDisplayModeValidFlag ?1:0, ioflags & kDisplayModeSafeFlag ?1:0, ioflags & kDisplayModeDefaultFlag ?1:0 ); printf(" safety:%u alwaysshow:%u nevershow:%u notresize:%u requirepan:%u int:%u simul:%u", ioflags & kDisplayModeSafetyFlags ?1:0, ioflags & kDisplayModeAlwaysShowFlag ?1:0, ioflags & kDisplayModeNeverShowFlag ?1:0, ioflags & kDisplayModeNotResizeFlag ?1:0, ioflags & kDisplayModeRequiresPanFlag ?1:0, ioflags & kDisplayModeInterlacedFlag ?1:0, ioflags & kDisplayModeSimulscanFlag ?1:0 ); printf(" builtin:%u notpreset:%u stretched:%u notgfxqual:%u valagnstdisp:%u tv:%u vldmirror:%u\n", ioflags & kDisplayModeBuiltInFlag ?1:0, ioflags & kDisplayModeNotPresetFlag ?1:0, ioflags & kDisplayModeStretchedFlag ?1:0, ioflags & kDisplayModeNotGraphicsQualityFlag ?1:0, ioflags & kDisplayModeValidateAgainstDisplay ?1:0, ioflags & kDisplayModeTelevisionFlag ?1:0, ioflags & kDisplayModeValidForMirroringFlag ?1:0 ); #endif } CFRelease(allModes); return returncode; }
static BOOL write_display_settings(HKEY parent_hkey, CGDirectDisplayID displayID) { BOOL ret = FALSE; char display_key_name[19]; HKEY display_hkey; CGDisplayModeRef display_mode; DWORD val; CFStringRef pixel_encoding; size_t len; WCHAR* buf = NULL; snprintf(display_key_name, sizeof(display_key_name), "Display 0x%08x", CGDisplayUnitNumber(displayID)); /* @@ Wine registry key: HKLM\Software\Wine\Mac Driver\Initial Display Mode\Display 0xnnnnnnnn */ if (RegCreateKeyExA(parent_hkey, display_key_name, 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &display_hkey, NULL)) return FALSE; display_mode = CGDisplayCopyDisplayMode(displayID); if (!display_mode) goto fail; val = CGDisplayModeGetWidth(display_mode); if (RegSetValueExA(display_hkey, "Width", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; val = CGDisplayModeGetHeight(display_mode); if (RegSetValueExA(display_hkey, "Height", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; val = CGDisplayModeGetRefreshRate(display_mode) * 100; if (RegSetValueExA(display_hkey, "RefreshRateTimes100", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; val = CGDisplayModeGetIOFlags(display_mode); if (RegSetValueExA(display_hkey, "IOFlags", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; #if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 if (CGDisplayModeGetPixelWidth != NULL && CGDisplayModeGetPixelHeight != NULL) { val = CGDisplayModeGetPixelWidth(display_mode); if (RegSetValueExA(display_hkey, "PixelWidth", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; val = CGDisplayModeGetPixelHeight(display_mode); if (RegSetValueExA(display_hkey, "PixelHeight", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; } #endif pixel_encoding = CGDisplayModeCopyPixelEncoding(display_mode); len = CFStringGetLength(pixel_encoding); buf = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); CFStringGetCharacters(pixel_encoding, CFRangeMake(0, len), (UniChar*)buf); buf[len] = 0; CFRelease(pixel_encoding); if (RegSetValueExW(display_hkey, pixelencodingW, 0, REG_SZ, (const BYTE*)buf, (len + 1) * sizeof(WCHAR))) goto fail; ret = TRUE; fail: HeapFree(GetProcessHeap(), 0, buf); if (display_mode) CGDisplayModeRelease(display_mode); RegCloseKey(display_hkey); if (!ret) RegDeleteKeyA(parent_hkey, display_key_name); return ret; }
/*********************************************************************** * copy_display_modes * * Wrapper around CGDisplayCopyAllDisplayModes() to include additional * modes on Retina-capable systems, but filter those which would confuse * Windows apps (basically duplicates at different DPIs). * * For example, some Retina Macs support a 1920x1200 mode, but it's not * returned from CGDisplayCopyAllDisplayModes() without special options. * This is especially bad if that's the user's default mode, since then * no "available" mode matches the initial settings. */ static CFArrayRef copy_display_modes(CGDirectDisplayID display) { CFArrayRef modes = NULL; #if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 if (&kCGDisplayShowDuplicateLowResolutionModes != NULL && CGDisplayModeGetPixelWidth != NULL && CGDisplayModeGetPixelHeight != NULL) { CFDictionaryRef options; struct display_mode_descriptor* desc; CFMutableDictionaryRef modes_by_size; CFIndex i, count; CGDisplayModeRef* mode_array; options = CFDictionaryCreate(NULL, (const void**)&kCGDisplayShowDuplicateLowResolutionModes, (const void**)&kCFBooleanTrue, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); modes = CGDisplayCopyAllDisplayModes(display, options); if (options) CFRelease(options); if (!modes) return NULL; desc = create_original_display_mode_descriptor(display); modes_by_size = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); count = CFArrayGetCount(modes); for (i = 0; i < count; i++) { BOOL better = TRUE; CGDisplayModeRef new_mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); BOOL new_is_original = display_mode_matches_descriptor(new_mode, desc); CFDictionaryRef key = create_mode_dict(new_mode); /* If a given mode is the user's default, then always list it in preference to any similar modes that may exist. */ if (new_is_original) better = TRUE; else { CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(new_mode); CGDisplayModeRef old_mode; if (pixel_encoding) { BOOL bpp30 = CFEqual(pixel_encoding, CFSTR(kIO30BitDirectPixels)); CFRelease(pixel_encoding); if (bpp30) { /* This is an odd pixel encoding. It seems it's only returned when using kCGDisplayShowDuplicateLowResolutionModes. It's 32bpp in terms of the actual raster layout, but it's 10 bits per component. I think that no Windows program is likely to need it and they will probably be confused by it. Skip it. */ CFRelease(key); continue; } } old_mode = (CGDisplayModeRef)CFDictionaryGetValue(modes_by_size, key); if (old_mode) { BOOL old_is_original = display_mode_matches_descriptor(old_mode, desc); if (old_is_original) better = FALSE; else { /* Otherwise, prefer a mode whose pixel size equals its point size over one which is scaled. */ size_t width_points = CGDisplayModeGetWidth(new_mode); size_t height_points = CGDisplayModeGetHeight(new_mode); size_t new_width_pixels = CGDisplayModeGetPixelWidth(new_mode); size_t new_height_pixels = CGDisplayModeGetPixelHeight(new_mode); size_t old_width_pixels = CGDisplayModeGetPixelWidth(old_mode); size_t old_height_pixels = CGDisplayModeGetPixelHeight(old_mode); BOOL new_size_same = (new_width_pixels == width_points && new_height_pixels == height_points); BOOL old_size_same = (old_width_pixels == width_points && old_height_pixels == height_points); if (new_size_same && !old_size_same) better = TRUE; else if (!new_size_same && old_size_same) better = FALSE; else { /* Otherwise, prefer the mode with the smaller pixel size. */ if (old_width_pixels < new_width_pixels || old_height_pixels < new_height_pixels) better = FALSE; } } } } if (better) CFDictionarySetValue(modes_by_size, key, new_mode); CFRelease(key); } free_display_mode_descriptor(desc); CFRelease(modes); count = CFDictionaryGetCount(modes_by_size); mode_array = HeapAlloc(GetProcessHeap(), 0, count * sizeof(mode_array[0])); CFDictionaryGetKeysAndValues(modes_by_size, NULL, (const void **)mode_array); modes = CFArrayCreate(NULL, (const void **)mode_array, count, &kCFTypeArrayCallBacks); HeapFree(GetProcessHeap(), 0, mode_array); CFRelease(modes_by_size); } else #endif modes = CGDisplayCopyAllDisplayModes(display, NULL); return modes; }
/*********************************************************************** * ChangeDisplaySettingsEx (MACDRV.@) * */ LONG CDECL macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, HWND hwnd, DWORD flags, LPVOID lpvoid) { LONG ret = DISP_CHANGE_BADMODE; int bpp; DEVMODEW dm; BOOL def_mode = TRUE; struct macdrv_display *displays; int num_displays; CFArrayRef display_modes; CFIndex count, i, safe, best; CGDisplayModeRef best_display_mode; uint32_t best_io_flags; TRACE("%s %p %p 0x%08x %p\n", debugstr_w(devname), devmode, hwnd, flags, lpvoid); init_original_display_mode(); if (devmode) { /* this is the minimal dmSize that XP accepts */ if (devmode->dmSize < FIELD_OFFSET(DEVMODEW, dmFields)) return DISP_CHANGE_FAILED; if (devmode->dmSize >= FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(devmode->dmFields)) { if (((devmode->dmFields & DM_BITSPERPEL) && devmode->dmBitsPerPel) || ((devmode->dmFields & DM_PELSWIDTH) && devmode->dmPelsWidth) || ((devmode->dmFields & DM_PELSHEIGHT) && devmode->dmPelsHeight) || ((devmode->dmFields & DM_DISPLAYFREQUENCY) && devmode->dmDisplayFrequency)) def_mode = FALSE; } } if (def_mode) { if (!macdrv_EnumDisplaySettingsEx(devname, ENUM_REGISTRY_SETTINGS, &dm, 0)) { ERR("Default mode not found!\n"); return DISP_CHANGE_BADMODE; } TRACE("Return to original display mode\n"); devmode = &dm; } if ((devmode->dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != (DM_PELSWIDTH | DM_PELSHEIGHT)) { WARN("devmode doesn't specify the resolution: %04x\n", devmode->dmFields); return DISP_CHANGE_BADMODE; } if (macdrv_get_displays(&displays, &num_displays)) return DISP_CHANGE_FAILED; display_modes = copy_display_modes(displays[0].displayID); if (!display_modes) { macdrv_free_displays(displays); return DISP_CHANGE_FAILED; } bpp = get_default_bpp(); if ((devmode->dmFields & DM_BITSPERPEL) && devmode->dmBitsPerPel != bpp) TRACE("using default %d bpp instead of caller's request %d bpp\n", bpp, devmode->dmBitsPerPel); TRACE("looking for %dx%dx%dbpp @%d Hz", (devmode->dmFields & DM_PELSWIDTH ? devmode->dmPelsWidth : 0), (devmode->dmFields & DM_PELSHEIGHT ? devmode->dmPelsHeight : 0), bpp, (devmode->dmFields & DM_DISPLAYFREQUENCY ? devmode->dmDisplayFrequency : 0)); if (devmode->dmFields & DM_DISPLAYFIXEDOUTPUT) TRACE(" %sstretched", devmode->dmDisplayFixedOutput == DMDFO_STRETCH ? "" : "un"); if (devmode->dmFields & DM_DISPLAYFLAGS) TRACE(" %sinterlaced", devmode->dmDisplayFlags & DM_INTERLACED ? "" : "non-"); TRACE("\n"); safe = -1; best_display_mode = NULL; count = CFArrayGetCount(display_modes); for (i = 0; i < count; i++) { CGDisplayModeRef display_mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(display_modes, i); uint32_t io_flags = CGDisplayModeGetIOFlags(display_mode); int mode_bpp = display_mode_bits_per_pixel(display_mode); size_t width = CGDisplayModeGetWidth(display_mode); size_t height = CGDisplayModeGetHeight(display_mode); if (!(io_flags & kDisplayModeValidFlag) || !(io_flags & kDisplayModeSafeFlag)) continue; safe++; if (bpp != mode_bpp) continue; if (devmode->dmFields & DM_PELSWIDTH) { if (devmode->dmPelsWidth != width) continue; } if (devmode->dmFields & DM_PELSHEIGHT) { if (devmode->dmPelsHeight != height) continue; } if ((devmode->dmFields & DM_DISPLAYFREQUENCY) && devmode->dmDisplayFrequency != 0) { double refresh_rate = CGDisplayModeGetRefreshRate(display_mode); if (!refresh_rate) refresh_rate = 60; if (devmode->dmDisplayFrequency != (DWORD)refresh_rate) continue; } if (devmode->dmFields & DM_DISPLAYFLAGS) { if (!(devmode->dmDisplayFlags & DM_INTERLACED) != !(io_flags & kDisplayModeInterlacedFlag)) continue; } else if (best_display_mode) { if (io_flags & kDisplayModeInterlacedFlag && !(best_io_flags & kDisplayModeInterlacedFlag)) continue; else if (!(io_flags & kDisplayModeInterlacedFlag) && best_io_flags & kDisplayModeInterlacedFlag) goto better; } if (devmode->dmFields & DM_DISPLAYFIXEDOUTPUT) { if (!(devmode->dmDisplayFixedOutput == DMDFO_STRETCH) != !(io_flags & kDisplayModeStretchedFlag)) continue; } else if (best_display_mode) { if (io_flags & kDisplayModeStretchedFlag && !(best_io_flags & kDisplayModeStretchedFlag)) continue; else if (!(io_flags & kDisplayModeStretchedFlag) && best_io_flags & kDisplayModeStretchedFlag) goto better; } if (best_display_mode) continue; better: best_display_mode = display_mode; best = safe; best_io_flags = io_flags; } if (best_display_mode) { /* we have a valid mode */ TRACE("Requested display settings match mode %ld\n", best); if ((flags & CDS_UPDATEREGISTRY) && !write_registry_settings(devmode)) { WARN("Failed to update registry\n"); ret = DISP_CHANGE_NOTUPDATED; } else if (flags & (CDS_TEST | CDS_NORESET)) ret = DISP_CHANGE_SUCCESSFUL; else if (macdrv_set_display_mode(&displays[0], best_display_mode)) { int mode_bpp = display_mode_bits_per_pixel(best_display_mode); size_t width = CGDisplayModeGetWidth(best_display_mode); size_t height = CGDisplayModeGetHeight(best_display_mode); SendMessageW(GetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp, MAKELPARAM(width, height)); ret = DISP_CHANGE_SUCCESSFUL; } else { WARN("Failed to set display mode\n"); ret = DISP_CHANGE_FAILED; } } else { /* no valid modes found */ ERR("No matching mode found %ux%ux%d @%u!\n", devmode->dmPelsWidth, devmode->dmPelsHeight, bpp, devmode->dmDisplayFrequency); } CFRelease(display_modes); macdrv_free_displays(displays); return ret; }
double UIDisplay::GetRefreshRatePriv(void) { CocoaAutoReleasePool pool; double rate = 0.0f; CGDirectDisplayID disp = GetOSXDisplay(m_widget->winId()); if (!disp) { LOG(VB_GENERAL, LOG_WARNING, "Failed to get OS X display"); return rate; } CGDisplayModeRef current = CGDisplayCopyDisplayMode(disp); if (current) { rate = CGDisplayModeGetRefreshRate(current); if (qFuzzyCompare((double)1.0f, rate + 1.0f)) m_variableRefreshRate = true; } else { LOG(VB_GENERAL, LOG_WARNING, "Failed to get current display mode"); return rate; } if (m_variableRefreshRate) { CGDisplayModeRelease(current); return rate; } // if we've run this already, release the modes m_modes.clear(); m_originalModeIndex = -1; if (gDisplayModes) CFRelease(gDisplayModes); gDisplayModes = CGDisplayCopyAllDisplayModes(disp, NULL); if (gDisplayModes) { for (int i = 0; i < CFArrayGetCount(gDisplayModes); ++i) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(gDisplayModes, i); int modewidth = CGDisplayModeGetWidth(mode); int modeheight = CGDisplayModeGetHeight(mode); double moderate = CGDisplayModeGetRefreshRate(mode); int32_t flags = CGDisplayModeGetIOFlags(mode); bool interlaced = flags & kDisplayModeInterlacedFlag; CFStringRef fmt = CGDisplayModeCopyPixelEncoding(mode); int depth = DepthFromStringRef(fmt); CFRelease(fmt); bool ignore = modewidth != m_pixelSize.width() || modeheight != m_pixelSize.height() || (flags & kDisplayModeNotGraphicsQualityFlag) || !(flags & kDisplayModeSafetyFlags) || depth < 32 || moderate < 10.0f || moderate > 121.0f; LOG(VB_GUI, LOG_INFO, QString("Mode %1x%2@%3Hz %4bpp%5%6%7") .arg(modewidth).arg(modeheight).arg(moderate).arg(depth) .arg(interlaced ? QString(" Interlaced") : "") .arg(ignore ? QString(" Ignoring") : "") .arg(mode == current ? QString(" CURRENT"): "")); if (!ignore) { m_modes.append(UIDisplayMode(modewidth, modeheight, depth, moderate, interlaced, i)); if (mode == current) m_originalModeIndex = m_modes.size() - 1; } } } CGDisplayModeRelease(current); return rate; }
unsigned int listAvailableModes(CGDirectDisplayID display, int displayNum) { unsigned int returncode = 1; int numModes = 0; int i; CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); if (allModes == NULL) { returncode = 0; } numModes = CFArrayGetCount(allModes); // sort the array of display modes CFMutableArrayRef allModesSorted = CFArrayCreateMutableCopy( kCFAllocatorDefault, numModes, allModes ); CFArraySortValues( allModesSorted, CFRangeMake(0, CFArrayGetCount(allModesSorted)), (CFComparatorFunction) _compareCFDisplayModes, NULL ); #ifndef LIST_DEBUG if(displayNum != 0) printf("\n\n"); printf("Available Modes on Display %d\n", displayNum); #endif CGDisplayModeRef mode; int modesPerColumn = numModes / MODES_PER_LINE; for (i = 0; (i < numModes) && returncode; i++) { int rowNumber = (i / MODES_PER_LINE); int idxDisplayMode = (i % MODES_PER_LINE) * modesPerColumn + rowNumber; // if there are an even number of display modes to display, // the last mode must have it's index decremented by 1 idxDisplayMode = MIN(idxDisplayMode, numModes - 1); mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(allModesSorted, idxDisplayMode); // This formatting is functional but it ought to be done less poorly. #ifndef LIST_DEBUG if (i % MODES_PER_LINE == 0) { printf(" "); } else { printf("\t"); } char modestr [50]; sprintf(modestr, "%4lux%4lux%lu@%.0f", CGDisplayModeGetWidth(mode), CGDisplayModeGetHeight(mode), bitDepth(mode), CGDisplayModeGetRefreshRate(mode)); printf("%-20s ", modestr); if(i % MODES_PER_LINE == MODES_PER_LINE - 1) printf("\n"); #else uint32_t ioflags = CGDisplayModeGetIOFlags(mode); printf("display: %d %4lux%4lux%2lu@%.0f usable:%u ioflags:%4x valid:%u safe:%u default:%u", displayNum, CGDisplayModeGetWidth(mode), CGDisplayModeGetHeight(mode), bitDepth(mode), CGDisplayModeGetRefreshRate(mode), CGDisplayModeIsUsableForDesktopGUI(mode), ioflags, ioflags & kDisplayModeValidFlag ?1:0, ioflags & kDisplayModeSafeFlag ?1:0, ioflags & kDisplayModeDefaultFlag ?1:0 ); printf(" safety:%u alwaysshow:%u nevershow:%u notresize:%u requirepan:%u int:%u simul:%u", ioflags & kDisplayModeSafetyFlags ?1:0, ioflags & kDisplayModeAlwaysShowFlag ?1:0, ioflags & kDisplayModeNeverShowFlag ?1:0, ioflags & kDisplayModeNotResizeFlag ?1:0, ioflags & kDisplayModeRequiresPanFlag ?1:0, ioflags & kDisplayModeInterlacedFlag ?1:0, ioflags & kDisplayModeSimulscanFlag ?1:0 ); printf(" builtin:%u notpreset:%u stretched:%u notgfxqual:%u valagnstdisp:%u tv:%u vldmirror:%u\n", ioflags & kDisplayModeBuiltInFlag ?1:0, ioflags & kDisplayModeNotPresetFlag ?1:0, ioflags & kDisplayModeStretchedFlag ?1:0, ioflags & kDisplayModeNotGraphicsQualityFlag ?1:0, ioflags & kDisplayModeValidateAgainstDisplay ?1:0, ioflags & kDisplayModeTelevisionFlag ?1:0, ioflags & kDisplayModeValidForMirroringFlag ?1:0 ); #endif } CFRelease(allModes); CFRelease(allModesSorted); return returncode; }