#include "streamutils.h" #include #ifdef Q_OS_DARWIN #include #endif Uint32 StreamUtils::getPlatformWindowFlags() { #ifdef Q_OS_DARWIN return SDL_WINDOW_METAL; #else return 0; #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->x += (dst->w - dstW) / 2; dst->w = dstW; SDL_assert(dst->w * src->h / src->w <= dst->h); } else { dst->y += (dst->h - dstH) / 2; dst->h = dstH; SDL_assert(dst->h * src->w / src->h <= dst->w); } } void StreamUtils::screenSpaceToNormalizedDeviceCoords(SDL_FRect* rect, int viewportWidth, int viewportHeight) { rect->x = (rect->x / (viewportWidth / 2.0f)) - 1.0f; rect->y = (rect->y / (viewportHeight / 2.0f)) - 1.0f; rect->w = rect->w / (viewportWidth / 2.0f); rect->h = rect->h / (viewportHeight / 2.0f); } void StreamUtils::screenSpaceToNormalizedDeviceCoords(SDL_Rect* src, SDL_FRect* dst, int viewportWidth, int viewportHeight) { dst->x = ((float)src->x / (viewportWidth / 2.0f)) - 1.0f; dst->y = ((float)src->y / (viewportHeight / 2.0f)) - 1.0f; dst->w = (float)src->w / (viewportWidth / 2.0f); dst->h = (float)src->h / (viewportHeight / 2.0f); } 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(CGDisplayModeGetWidth(cgMode)); mode->h = static_cast(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; }