mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-12-13 21:02:28 +00:00
127 lines
4.1 KiB
C++
127 lines
4.1 KiB
C++
#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;
|
|
int dstW = dst->h * src->w / src->h;
|
|
|
|
if (dstH > dst->h) {
|
|
dst->y = 0;
|
|
dst->x = (dst->w - dstW) / 2;
|
|
dst->w = dstW;
|
|
SDL_assert(dst->w * src->h / src->w <= dst->h);
|
|
}
|
|
else {
|
|
dst->x = 0;
|
|
dst->y = (dst->h - dstH) / 2;
|
|
dst->h = dstH;
|
|
SDL_assert(dst->h * src->w / src->h <= dst->w);
|
|
}
|
|
}
|
|
|
|
int StreamUtils::getDisplayRefreshRate(SDL_Window* window)
|
|
{
|
|
int displayIndex = SDL_GetWindowDisplayIndex(window);
|
|
if (displayIndex < 0) {
|
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
"Failed to get current display: %s",
|
|
SDL_GetError());
|
|
|
|
// Assume display 0 if it fails
|
|
displayIndex = 0;
|
|
}
|
|
|
|
SDL_DisplayMode mode;
|
|
if ((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN) {
|
|
// Use the window display mode for full-screen exclusive mode
|
|
if (SDL_GetWindowDisplayMode(window, &mode) != 0) {
|
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
"SDL_GetWindowDisplayMode() failed: %s",
|
|
SDL_GetError());
|
|
|
|
// Assume 60 Hz
|
|
return 60;
|
|
}
|
|
}
|
|
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());
|
|
|
|
// Assume 60 Hz
|
|
return 60;
|
|
}
|
|
}
|
|
|
|
// May be zero if undefined
|
|
if (mode.refresh_rate == 0) {
|
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
"Refresh rate unknown; assuming 60 Hz");
|
|
mode.refresh_rate = 60;
|
|
}
|
|
|
|
return mode.refresh_rate;
|
|
}
|
|
|
|
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;
|
|
}
|