Detect native panel resolution on Retina displays. Fixes #59

This commit is contained in:
Cameron Gutman
2018-09-04 00:21:37 -04:00
parent af6e99cbac
commit dae21f2638
7 changed files with 145 additions and 39 deletions

View File

@@ -1,5 +1,6 @@
#include "session.hpp"
#include "settings/streamingpreferences.h"
#include "streaming/streamutils.h"
#include <Limelight.h>
#include <SDL.h>
@@ -544,7 +545,7 @@ void Session::getWindowDimensions(bool fullScreen,
else if (fullScreen) {
for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
SDL_DisplayMode mode;
if (SDL_GetDesktopDisplayMode(i, &mode) == 0 &&
if (StreamUtils::getRealDesktopMode(i, &mode) &&
m_ActiveVideoWidth == mode.w &&
m_ActiveVideoHeight == mode.h) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
@@ -603,7 +604,7 @@ void Session::updateOptimalWindowDisplayMode()
int displayIndex = SDL_GetWindowDisplayIndex(m_Window);
// Get the native desktop resolution
if (SDL_GetDesktopDisplayMode(displayIndex, &desktopMode) == 0) {
if (StreamUtils::getRealDesktopMode(displayIndex, &desktopMode)) {
// Start with the native desktop resolution and try to find
// the highest refresh rate that our stream FPS evenly divides.
bestMode = desktopMode;
@@ -757,7 +758,7 @@ void Session::exec()
y,
width,
height,
0);
SDL_WINDOW_ALLOW_HIGHDPI);
if (!m_Window) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_CreateWindow() failed: %s",

View File

@@ -1,5 +1,11 @@
#include "streamutils.h"
#include <Qt>
#ifdef Q_OS_DARWIN
#include <ApplicationServices/ApplicationServices.h>
#endif
void StreamUtils::scaleSourceToDestinationSurface(SDL_Rect* src, SDL_Rect* dst)
{
int dstH = dst->w * src->h / src->w;
@@ -18,3 +24,58 @@ void StreamUtils::scaleSourceToDestinationSurface(SDL_Rect* src, SDL_Rect* dst)
SDL_assert(dst->h * src->w / src->h <= dst->w);
}
}
bool StreamUtils::getRealDesktopMode(int displayIndex, SDL_DisplayMode* mode)
{
#ifdef Q_OS_DARWIN
#define MAX_DISPLAYS 16
CGDirectDisplayID displayIds[MAX_DISPLAYS];
uint32_t displayCount = 0;
CGGetActiveDisplayList(MAX_DISPLAYS, displayIds, &displayCount);
if (displayIndex >= displayCount) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Too many displays: %d vs %d",
displayIndex, displayCount);
return false;
}
SDL_zerop(mode);
// Retina displays have non-native resolutions both below and above (!) their
// native resolution, so it's impossible for us to figure out what's actually
// native on macOS using the SDL API alone. We'll talk to CoreGraphics to
// find the correct resolution and match it in our SDL list.
CFArrayRef modeList = CGDisplayCopyAllDisplayModes(displayIds[displayIndex], nullptr);
CFIndex count = CFArrayGetCount(modeList);
for (CFIndex i = 0; i < count; i++) {
auto cgMode = (CGDisplayModeRef)(CFArrayGetValueAtIndex(modeList, i));
if ((CGDisplayModeGetIOFlags(cgMode) & kDisplayModeNativeFlag) != 0) {
mode->w = static_cast<int>(CGDisplayModeGetWidth(cgMode));
mode->h = static_cast<int>(CGDisplayModeGetHeight(cgMode));
break;
}
}
CFRelease(modeList);
// Now find the SDL mode that matches the CG native mode
for (int i = 0; i < SDL_GetNumDisplayModes(displayIndex); i++) {
SDL_DisplayMode thisMode;
if (SDL_GetDisplayMode(displayIndex, i, &thisMode) == 0) {
if (thisMode.w == mode->w && thisMode.h == mode->h &&
thisMode.refresh_rate >= mode->refresh_rate) {
*mode = thisMode;
break;
}
}
}
#else
if (SDL_GetDesktopDisplayMode(displayIndex, mode) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetDesktopDisplayMode() failed: %s",
SDL_GetError());
return false;
}
#endif
return true;
}

View File

@@ -7,4 +7,7 @@ class StreamUtils
public:
static
void scaleSourceToDestinationSurface(SDL_Rect* src, SDL_Rect* dst);
static
bool getRealDesktopMode(int displayIndex, SDL_DisplayMode* mode);
};

View File

@@ -1,4 +1,5 @@
#include "pacer.h"
#include "streaming/streamutils.h"
#include "nullthreadedvsyncsource.h"
@@ -143,10 +144,7 @@ bool Pacer::initialize(SDL_Window* window, int maxVideoFps, bool enableVsync)
}
else {
// Use the current display mode for windowed and borderless
if (SDL_GetCurrentDisplayMode(displayIndex, &mode) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetCurrentDisplayMode() failed: %s",
SDL_GetError());
if (!StreamUtils::getRealDesktopMode(displayIndex, &mode)) {
return false;
}
}