diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e2eb45cc..f2b0a538 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,13 +3,13 @@ include_directories(${GLFW_SOURCE_DIR}/src ${glfw_INCLUDE_DIRS}) set(common_HEADERS ${GLFW_SOURCE_DIR}/include/GL/glfw3.h internal.h) -set(common_SOURCES clipboard.c fullscreen.c gamma.c init.c input.c - joystick.c monitor.c opengl.c time.c window.c) +set(common_SOURCES clipboard.c gamma.c init.c input.c joystick.c monitor.c + opengl.c time.c window.c) if (_GLFW_COCOA_NSGL) set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h) - set(glfw_SOURCES ${common_SOURCES} cocoa_clipboard.m cocoa_fullscreen.m - cocoa_gamma.c cocoa_init.m cocoa_input.m cocoa_joystick.m + set(glfw_SOURCES ${common_SOURCES} cocoa_clipboard.m cocoa_gamma.c + cocoa_init.m cocoa_input.m cocoa_joystick.m cocoa_monitor.m cocoa_opengl.m cocoa_time.c cocoa_window.m) if (GLFW_NATIVE_API) @@ -20,20 +20,18 @@ if (_GLFW_COCOA_NSGL) set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C) elseif (_GLFW_WIN32_WGL) set(glfw_HEADERS ${common_HEADERS} win32_platform.h) - set(glfw_SOURCES ${common_SOURCES} win32_clipboard.c win32_fullscreen.c - win32_gamma.c win32_init.c win32_input.c win32_joystick.c - win32_monitor.c win32_opengl.c win32_time.c win32_window.c - win32_dllmain.c) + set(glfw_SOURCES ${common_SOURCES} win32_clipboard.c win32_gamma.c + win32_init.c win32_input.c win32_joystick.c win32_monitor.c + win32_opengl.c win32_time.c win32_window.c win32_dllmain.c) if (GLFW_NATIVE_API) list(APPEND glfw_SOURCES win32_native.c) endif() elseif (_GLFW_X11_GLX) set(glfw_HEADERS ${common_HEADERS} x11_platform.h) - set(glfw_SOURCES ${common_SOURCES} x11_clipboard.c x11_fullscreen.c - x11_gamma.c x11_init.c x11_input.c x11_joystick.c - x11_keysym2unicode.c x11_monitor.c x11_opengl.c x11_time.c - x11_window.c) + set(glfw_SOURCES ${common_SOURCES} x11_clipboard.c x11_gamma.c x11_init.c + x11_input.c x11_joystick.c x11_keysym2unicode.c + x11_monitor.c x11_opengl.c x11_time.c x11_window.c) if (GLFW_NATIVE_API) list(APPEND glfw_SOURCES x11_native.c) diff --git a/src/cocoa_fullscreen.m b/src/cocoa_fullscreen.m deleted file mode 100644 index 581d2d54..00000000 --- a/src/cocoa_fullscreen.m +++ /dev/null @@ -1,243 +0,0 @@ -//======================================================================== -// GLFW - An OpenGL library -// Platform: Cocoa -// API Version: 3.0 -// WWW: http://www.glfw.org/ -//------------------------------------------------------------------------ -// Copyright (c) 2009-2010 Camilla Berglund -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== - -#include "internal.h" - -#include -#include - - -//======================================================================== -// Check whether the display mode should be included in enumeration -//======================================================================== - -static GLboolean modeIsGood(CGDisplayModeRef mode) -{ - uint32_t flags = CGDisplayModeGetIOFlags(mode); - if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag)) - return GL_FALSE; - - if (flags & kDisplayModeInterlacedFlag) - return GL_FALSE; - - if (flags & kDisplayModeTelevisionFlag) - return GL_FALSE; - - if (flags & kDisplayModeStretchedFlag) - return GL_FALSE; - - CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); - if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) && - CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0)) - { - CFRelease(format); - return GL_FALSE; - } - - CFRelease(format); - return GL_TRUE; -} - - -//======================================================================== -// Convert Core Graphics display mode to GLFW video mode -//======================================================================== - -static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode) -{ - GLFWvidmode result; - result.width = CGDisplayModeGetWidth(mode); - result.height = CGDisplayModeGetHeight(mode); - - CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); - - if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0) - { - result.redBits = 5; - result.greenBits = 5; - result.blueBits = 5; - } - else - { - result.redBits = 8; - result.greenBits = 8; - result.blueBits = 8; - } - - CFRelease(format); - return result; -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Change the current video mode -//======================================================================== - -GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp, int* refreshRate) -{ - CGDisplayModeRef bestMode = NULL; - CFArrayRef modes; - CFIndex count, i; - unsigned int leastSizeDiff = UINT_MAX; - double leastRateDiff = DBL_MAX; - - modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL); - count = CFArrayGetCount(modes); - - for (i = 0; i < count; i++) - { - CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); - if (!modeIsGood(mode)) - continue; - - int modeBPP; - - // Identify display mode pixel encoding - { - CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); - - if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0) - modeBPP = 16; - else - modeBPP = 32; - - CFRelease(format); - } - - int modeWidth = (int) CGDisplayModeGetWidth(mode); - int modeHeight = (int) CGDisplayModeGetHeight(mode); - - unsigned int sizeDiff = (abs(modeBPP - *bpp) << 25) | - ((modeWidth - *width) * (modeWidth - *width) + - (modeHeight - *height) * (modeHeight - *height)); - - double rateDiff; - - if (*refreshRate > 0) - rateDiff = fabs(CGDisplayModeGetRefreshRate(mode) - *refreshRate); - else - { - // If no refresh rate was specified, then they're all the same - rateDiff = 0; - } - - if ((sizeDiff < leastSizeDiff) || - (sizeDiff == leastSizeDiff && (rateDiff < leastRateDiff))) - { - bestMode = mode; - - leastSizeDiff = sizeDiff; - leastRateDiff = rateDiff; - } - } - - if (!bestMode) - { - CFRelease(modes); - return GL_FALSE; - } - - _glfwLibrary.NS.previousMode = CGDisplayCopyDisplayMode(CGMainDisplayID()); - - CGDisplayCapture(CGMainDisplayID()); - CGDisplaySetDisplayMode(CGMainDisplayID(), bestMode, NULL); - - CFRelease(modes); - return GL_TRUE; -} - - -//======================================================================== -// Restore the previously saved (original) video mode -//======================================================================== - -void _glfwRestoreVideoMode(void) -{ - CGDisplaySetDisplayMode(CGMainDisplayID(), - _glfwLibrary.NS.previousMode, - NULL); - - CGDisplayRelease(CGMainDisplayID()); -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Get a list of available video modes -//======================================================================== - -GLFWvidmode* _glfwPlatformGetVideoModes(int* found) -{ - CFArrayRef modes; - CFIndex count, i; - GLFWvidmode* result; - - modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL); - count = CFArrayGetCount(modes); - - result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * count); - *found = 0; - - for (i = 0; i < count; i++) - { - CGDisplayModeRef mode; - - mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); - if (modeIsGood(mode)) - { - result[*found] = vidmodeFromCGDisplayMode(mode); - (*found)++; - } - } - - CFRelease(modes); - return result; -} - - -//======================================================================== -// Get the current video mode for the specified monitor -//======================================================================== - -void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode) -{ - CGDisplayModeRef displayMode; - - displayMode = CGDisplayCopyDisplayMode(CGMainDisplayID()); - *mode = vidmodeFromCGDisplayMode(displayMode); - CGDisplayModeRelease(displayMode); -} - diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 970e6d92..f3416f52 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -30,6 +30,167 @@ #include "internal.h" +#include +#include + + +//======================================================================== +// Check whether the display mode should be included in enumeration +//======================================================================== + +static GLboolean modeIsGood(CGDisplayModeRef mode) +{ + uint32_t flags = CGDisplayModeGetIOFlags(mode); + if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag)) + return GL_FALSE; + + if (flags & kDisplayModeInterlacedFlag) + return GL_FALSE; + + if (flags & kDisplayModeTelevisionFlag) + return GL_FALSE; + + if (flags & kDisplayModeStretchedFlag) + return GL_FALSE; + + CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); + if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) && + CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0)) + { + CFRelease(format); + return GL_FALSE; + } + + CFRelease(format); + return GL_TRUE; +} + + +//======================================================================== +// Convert Core Graphics display mode to GLFW video mode +//======================================================================== + +static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode) +{ + GLFWvidmode result; + result.width = CGDisplayModeGetWidth(mode); + result.height = CGDisplayModeGetHeight(mode); + + CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); + + if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0) + { + result.redBits = 5; + result.greenBits = 5; + result.blueBits = 5; + } + else + { + result.redBits = 8; + result.greenBits = 8; + result.blueBits = 8; + } + + CFRelease(format); + return result; +} + + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Change the current video mode +//======================================================================== + +GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp, int* refreshRate) +{ + CGDisplayModeRef bestMode = NULL; + CFArrayRef modes; + CFIndex count, i; + unsigned int leastSizeDiff = UINT_MAX; + double leastRateDiff = DBL_MAX; + + modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL); + count = CFArrayGetCount(modes); + + for (i = 0; i < count; i++) + { + CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); + if (!modeIsGood(mode)) + continue; + + int modeBPP; + + // Identify display mode pixel encoding + { + CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); + + if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0) + modeBPP = 16; + else + modeBPP = 32; + + CFRelease(format); + } + + int modeWidth = (int) CGDisplayModeGetWidth(mode); + int modeHeight = (int) CGDisplayModeGetHeight(mode); + + unsigned int sizeDiff = (abs(modeBPP - *bpp) << 25) | + ((modeWidth - *width) * (modeWidth - *width) + + (modeHeight - *height) * (modeHeight - *height)); + + double rateDiff; + + if (*refreshRate > 0) + rateDiff = fabs(CGDisplayModeGetRefreshRate(mode) - *refreshRate); + else + { + // If no refresh rate was specified, then they're all the same + rateDiff = 0; + } + + if ((sizeDiff < leastSizeDiff) || + (sizeDiff == leastSizeDiff && (rateDiff < leastRateDiff))) + { + bestMode = mode; + + leastSizeDiff = sizeDiff; + leastRateDiff = rateDiff; + } + } + + if (!bestMode) + { + CFRelease(modes); + return GL_FALSE; + } + + _glfwLibrary.NS.previousMode = CGDisplayCopyDisplayMode(CGMainDisplayID()); + + CGDisplayCapture(CGMainDisplayID()); + CGDisplaySetDisplayMode(CGMainDisplayID(), bestMode, NULL); + + CFRelease(modes); + return GL_TRUE; +} + + +//======================================================================== +// Restore the previously saved (original) video mode +//======================================================================== + +void _glfwRestoreVideoMode(void) +{ + CGDisplaySetDisplayMode(CGMainDisplayID(), + _glfwLibrary.NS.previousMode, + NULL); + + CGDisplayRelease(CGMainDisplayID()); +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// @@ -54,3 +215,50 @@ void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor) { } + +//======================================================================== +// Get a list of available video modes +//======================================================================== + +GLFWvidmode* _glfwPlatformGetVideoModes(int* found) +{ + CFArrayRef modes; + CFIndex count, i; + GLFWvidmode* result; + + modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL); + count = CFArrayGetCount(modes); + + result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * count); + *found = 0; + + for (i = 0; i < count; i++) + { + CGDisplayModeRef mode; + + mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); + if (modeIsGood(mode)) + { + result[*found] = vidmodeFromCGDisplayMode(mode); + (*found)++; + } + } + + CFRelease(modes); + return result; +} + + +//======================================================================== +// Get the current video mode for the specified monitor +//======================================================================== + +void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode) +{ + CGDisplayModeRef displayMode; + + displayMode = CGDisplayCopyDisplayMode(CGMainDisplayID()); + *mode = vidmodeFromCGDisplayMode(displayMode); + CGDisplayModeRelease(displayMode); +} + diff --git a/src/fullscreen.c b/src/fullscreen.c deleted file mode 100644 index 6d8ada66..00000000 --- a/src/fullscreen.c +++ /dev/null @@ -1,172 +0,0 @@ -//======================================================================== -// GLFW - An OpenGL library -// Platform: Any -// API version: 3.0 -// WWW: http://www.glfw.org/ -//------------------------------------------------------------------------ -// Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2010 Camilla Berglund -// Copyright (c) 2012 Torsten Walluhn -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== - -#include "internal.h" - -#include -#if _WIN32 - #include -#endif - - -//======================================================================== -// Lexical comparison function for GLFW video modes, used by qsort -//======================================================================== - -int compareVideoModes(const void* firstPtr, const void* secondPtr) -{ - int firstBPP, secondBPP, firstSize, secondSize; - GLFWvidmode* first = (GLFWvidmode*) firstPtr; - GLFWvidmode* second = (GLFWvidmode*) secondPtr; - - // First sort on color bits per pixel - - firstBPP = first->redBits + - first->greenBits + - first->blueBits; - secondBPP = second->redBits + - second->greenBits + - second->blueBits; - - if (firstBPP != secondBPP) - return firstBPP - secondBPP; - - // Then sort on screen area, in pixels - - firstSize = first->width * first->height; - secondSize = second->width * second->height; - - return firstSize - secondSize; -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Lexical comparison of GLFW video modes -//======================================================================== - -int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second) -{ - return compareVideoModes(first, second); -} - - -//======================================================================== -// Convert BPP to RGB bits based on "best guess" -//======================================================================== - -void _glfwSplitBPP(int bpp, int* red, int* green, int* blue) -{ - int delta; - - // We assume that by 32 the user really meant 24 - if (bpp == 32) - bpp = 24; - - // Convert "bits per pixel" to red, green & blue sizes - - *red = *green = *blue = bpp / 3; - delta = bpp - (*red * 3); - if (delta >= 1) - *green = *green + 1; - - if (delta == 2) - *red = *red + 1; -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW public API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Get a list of available video modes -//======================================================================== - -GLFWAPI GLFWvidmode* glfwGetVideoModes(GLFWmonitor handle, int* count) -{ - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; - - if (!_glfwInitialized) - { - _glfwSetError(GLFW_NOT_INITIALIZED, NULL); - return NULL; - } - - if (monitor == NULL) - { - _glfwSetError(GLFW_INVALID_VALUE, - "glfwGetVideoModes: Invalid monitor handle"); - return 0; - } - - if (count == NULL) - { - _glfwSetError(GLFW_INVALID_VALUE, NULL); - return NULL; - } - - free(monitor->modes); - - monitor->modes = _glfwPlatformGetVideoModes(monitor, count); - if (monitor->modes) - qsort(monitor->modes, *count, sizeof(GLFWvidmode), compareVideoModes); - - return monitor->modes; -} - - -//======================================================================== -// Get the current video mode for the specified monitor -//======================================================================== - -GLFWAPI void glfwGetVideoMode(GLFWmonitor handle, GLFWvidmode* mode) -{ - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; - - if (!_glfwInitialized) - { - _glfwSetError(GLFW_NOT_INITIALIZED, NULL); - return; - } - - if (mode == NULL) - { - _glfwSetError(GLFW_INVALID_VALUE, NULL); - return; - } - - _glfwPlatformGetVideoMode(monitor, mode); -} - diff --git a/src/monitor.c b/src/monitor.c index 65a41cbb..b53da2db 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -32,6 +32,40 @@ #include #include +#if _WIN32 + #include +#endif + + +//======================================================================== +// Lexical comparison function for GLFW video modes, used by qsort +//======================================================================== + +int compareVideoModes(const void* firstPtr, const void* secondPtr) +{ + int firstBPP, secondBPP, firstSize, secondSize; + GLFWvidmode* first = (GLFWvidmode*) firstPtr; + GLFWvidmode* second = (GLFWvidmode*) secondPtr; + + // First sort on color bits per pixel + + firstBPP = first->redBits + + first->greenBits + + first->blueBits; + secondBPP = second->redBits + + second->greenBits + + second->blueBits; + + if (firstBPP != secondBPP) + return firstBPP - secondBPP; + + // Then sort on screen area, in pixels + + firstSize = first->width * first->height; + secondSize = second->width * second->height; + + return firstSize - secondSize; +} ////////////////////////////////////////////////////////////////////////// @@ -151,6 +185,40 @@ void _glfwDestroyMonitors(void) } +//======================================================================== +// Lexical comparison of GLFW video modes +//======================================================================== + +int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second) +{ + return compareVideoModes(first, second); +} + + +//======================================================================== +// Convert BPP to RGB bits based on "best guess" +//======================================================================== + +void _glfwSplitBPP(int bpp, int* red, int* green, int* blue) +{ + int delta; + + // We assume that by 32 the user really meant 24 + if (bpp == 32) + bpp = 24; + + // Convert "bits per pixel" to red, green & blue sizes + + *red = *green = *blue = bpp / 3; + delta = bpp - (*red * 3); + if (delta >= 1) + *green = *green + 1; + + if (delta == 2) + *red = *red + 1; +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// @@ -281,3 +349,64 @@ GLFWAPI void glfwSetMonitorCallback(GLFWmonitorfun cbfun) _glfwLibrary.monitorCallback= cbfun; } + +//======================================================================== +// Get a list of available video modes +//======================================================================== + +GLFWAPI GLFWvidmode* glfwGetVideoModes(GLFWmonitor handle, int* count) +{ + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + + if (!_glfwInitialized) + { + _glfwSetError(GLFW_NOT_INITIALIZED, NULL); + return NULL; + } + + if (monitor == NULL) + { + _glfwSetError(GLFW_INVALID_VALUE, + "glfwGetVideoModes: Invalid monitor handle"); + return 0; + } + + if (count == NULL) + { + _glfwSetError(GLFW_INVALID_VALUE, NULL); + return NULL; + } + + free(monitor->modes); + + monitor->modes = _glfwPlatformGetVideoModes(monitor, count); + if (monitor->modes) + qsort(monitor->modes, *count, sizeof(GLFWvidmode), compareVideoModes); + + return monitor->modes; +} + + +//======================================================================== +// Get the current video mode for the specified monitor +//======================================================================== + +GLFWAPI void glfwGetVideoMode(GLFWmonitor handle, GLFWvidmode* mode) +{ + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + + if (!_glfwInitialized) + { + _glfwSetError(GLFW_NOT_INITIALIZED, NULL); + return; + } + + if (mode == NULL) + { + _glfwSetError(GLFW_INVALID_VALUE, NULL); + return; + } + + _glfwPlatformGetVideoMode(monitor, mode); +} + diff --git a/src/win32_fullscreen.c b/src/win32_fullscreen.c deleted file mode 100644 index 4eb65cb0..00000000 --- a/src/win32_fullscreen.c +++ /dev/null @@ -1,281 +0,0 @@ -//======================================================================== -// GLFW - An OpenGL library -// Platform: Win32 -// API version: 3.0 -// WWW: http://www.glfw.org/ -//------------------------------------------------------------------------ -// Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2010 Camilla Berglund -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== - -#include "internal.h" - -#include -#include -#include - - -//======================================================================== -// Return closest video mode by dimensions, refresh rate and bits per pixel -//======================================================================== - -static GLboolean getClosestVideoMode(int* width, int* height, - int* bpp, int* refreshRate, - GLboolean exactBPP) -{ - int mode, bestWidth, bestHeight, bestBPP, bestRate; - unsigned int sizeDiff, rateDiff, leastSizeDiff, leastRateDiff; - GLboolean foundMode = GL_FALSE; - DEVMODE dm; - - leastSizeDiff = leastRateDiff = UINT_MAX; - - for (mode = 0; ; mode++) - { - dm.dmSize = sizeof(DEVMODE); - if (!EnumDisplaySettings(NULL, mode, &dm)) - break; - - if (exactBPP && dm.dmBitsPerPel != *bpp) - continue; - - sizeDiff = (abs(dm.dmBitsPerPel - *bpp) << 25) | - ((dm.dmPelsWidth - *width) * - (dm.dmPelsWidth - *width) + - (dm.dmPelsHeight - *height) * - (dm.dmPelsHeight - *height)); - - if (*refreshRate > 0) - { - rateDiff = (dm.dmDisplayFrequency - *refreshRate) * - (dm.dmDisplayFrequency - *refreshRate); - } - else - { - // If no refresh rate was specified, then they're all the same - rateDiff = 0; - } - - // We match first BPP, then screen area and last refresh rate - - if ((sizeDiff < leastSizeDiff) || - (sizeDiff == leastSizeDiff && (rateDiff < leastRateDiff))) - { - bestWidth = dm.dmPelsWidth; - bestHeight = dm.dmPelsHeight; - bestBPP = dm.dmBitsPerPel; - bestRate = dm.dmDisplayFrequency; - - leastSizeDiff = sizeDiff; - leastRateDiff = rateDiff; - - foundMode = GL_TRUE; - } - } - - if (!foundMode) - return GL_FALSE; - - *width = bestWidth; - *height = bestHeight; - *bpp = bestBPP; - - // Only save the found refresh rate if the client requested a specific - // rate; otherwise keep it at zero to let Windows select the best rate - if (*refreshRate > 0) - *refreshRate = bestRate; - - return GL_TRUE; -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Change the current video mode -//======================================================================== - -void _glfwSetVideoMode(int* width, int* height, - int* bpp, int* refreshRate, - GLboolean exactBPP) -{ - DEVMODE dm; - int closestWidth, closestHeight, closestBPP, closestRate; - - closestWidth = *width; - closestHeight = *height; - closestBPP = *bpp; - closestRate = *refreshRate; - - if (getClosestVideoMode(&closestWidth, &closestHeight, - &closestBPP, &closestRate, GL_FALSE)) - { - dm.dmSize = sizeof(DEVMODE); - dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; - dm.dmPelsWidth = closestWidth; - dm.dmPelsHeight = closestHeight; - dm.dmBitsPerPel = closestBPP; - - if (*refreshRate > 0) - { - dm.dmFields |= DM_DISPLAYFREQUENCY; - dm.dmDisplayFrequency = closestRate; - } - - if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL) - { - *width = closestWidth; - *height = closestHeight; - *bpp = closestBPP; - *refreshRate = closestRate; - } - } - else - { - dm.dmSize = sizeof(DEVMODE); - EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &dm); - - *width = dm.dmPelsWidth; - *height = dm.dmPelsHeight; - *bpp = dm.dmBitsPerPel; - *refreshRate = dm.dmDisplayFrequency; - } -} - - -//======================================================================== -// Restore the previously saved (original) video mode -//======================================================================== - -void _glfwRestoreVideoMode(void) -{ - ChangeDisplaySettings(NULL, CDS_FULLSCREEN); -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Get a list of available video modes -//======================================================================== - -GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) -{ - int modeIndex = 0, count = 0; - GLFWvidmode* result = NULL; - - *found = 0; - - for (;;) - { - int i; - GLFWvidmode mode; - DEVMODE dm; - - ZeroMemory(&dm, sizeof(DEVMODE)); - dm.dmSize = sizeof(DEVMODE); - - if (!EnumDisplaySettings(monitor->Win32.name, modeIndex, &dm)) - break; - - modeIndex++; - - if (dm.dmBitsPerPel < 15) - { - // Skip modes with less than 15 BPP - continue; - } - - mode.width = dm.dmPelsWidth; - mode.height = dm.dmPelsHeight; - _glfwSplitBPP(dm.dmBitsPerPel, - &mode.redBits, - &mode.greenBits, - &mode.blueBits); - - for (i = 0; i < *found; i++) - { - if (_glfwCompareVideoModes(result + i, &mode) == 0) - break; - } - - if (i < *found) - { - // This is a duplicate, so skip it - continue; - } - - if (*found == count) - { - void* larger; - - if (count) - count *= 2; - else - count = 128; - - larger = realloc(result, count * sizeof(GLFWvidmode)); - if (!larger) - { - free(result); - - _glfwSetError(GLFW_OUT_OF_MEMORY, NULL); - return NULL; - } - - result = (GLFWvidmode*) larger; - } - - result[*found] = mode; - (*found)++; - } - - return result; -} - - -//======================================================================== -// Get the current video mode for the specified monitor -//======================================================================== - -void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) -{ - DEVMODE dm; - - ZeroMemory(&dm, sizeof(DEVMODE)); - dm.dmSize = sizeof(DEVMODE); - - EnumDisplaySettings(monitor->Win32.name, ENUM_REGISTRY_SETTINGS, &dm); - - mode->width = dm.dmPelsWidth; - mode->height = dm.dmPelsHeight; - _glfwSplitBPP(dm.dmBitsPerPel, - &mode->redBits, - &mode->greenBits, - &mode->blueBits); -} - diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 527e4e6f..a6609c61 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -32,6 +32,8 @@ #include #include +#include +#include // These constants are missing on MinGW #ifndef EDS_ROTATEDMODE @@ -42,6 +44,146 @@ #endif +//======================================================================== +// Return closest video mode by dimensions, refresh rate and bits per pixel +//======================================================================== + +static GLboolean getClosestVideoMode(int* width, int* height, + int* bpp, int* refreshRate, + GLboolean exactBPP) +{ + int mode, bestWidth, bestHeight, bestBPP, bestRate; + unsigned int sizeDiff, rateDiff, leastSizeDiff, leastRateDiff; + GLboolean foundMode = GL_FALSE; + DEVMODE dm; + + leastSizeDiff = leastRateDiff = UINT_MAX; + + for (mode = 0; ; mode++) + { + dm.dmSize = sizeof(DEVMODE); + if (!EnumDisplaySettings(NULL, mode, &dm)) + break; + + if (exactBPP && dm.dmBitsPerPel != *bpp) + continue; + + sizeDiff = (abs(dm.dmBitsPerPel - *bpp) << 25) | + ((dm.dmPelsWidth - *width) * + (dm.dmPelsWidth - *width) + + (dm.dmPelsHeight - *height) * + (dm.dmPelsHeight - *height)); + + if (*refreshRate > 0) + { + rateDiff = (dm.dmDisplayFrequency - *refreshRate) * + (dm.dmDisplayFrequency - *refreshRate); + } + else + { + // If no refresh rate was specified, then they're all the same + rateDiff = 0; + } + + // We match first BPP, then screen area and last refresh rate + + if ((sizeDiff < leastSizeDiff) || + (sizeDiff == leastSizeDiff && (rateDiff < leastRateDiff))) + { + bestWidth = dm.dmPelsWidth; + bestHeight = dm.dmPelsHeight; + bestBPP = dm.dmBitsPerPel; + bestRate = dm.dmDisplayFrequency; + + leastSizeDiff = sizeDiff; + leastRateDiff = rateDiff; + + foundMode = GL_TRUE; + } + } + + if (!foundMode) + return GL_FALSE; + + *width = bestWidth; + *height = bestHeight; + *bpp = bestBPP; + + // Only save the found refresh rate if the client requested a specific + // rate; otherwise keep it at zero to let Windows select the best rate + if (*refreshRate > 0) + *refreshRate = bestRate; + + return GL_TRUE; +} + + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Change the current video mode +//======================================================================== + +void _glfwSetVideoMode(int* width, int* height, + int* bpp, int* refreshRate, + GLboolean exactBPP) +{ + DEVMODE dm; + int closestWidth, closestHeight, closestBPP, closestRate; + + closestWidth = *width; + closestHeight = *height; + closestBPP = *bpp; + closestRate = *refreshRate; + + if (getClosestVideoMode(&closestWidth, &closestHeight, + &closestBPP, &closestRate, GL_FALSE)) + { + dm.dmSize = sizeof(DEVMODE); + dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + dm.dmPelsWidth = closestWidth; + dm.dmPelsHeight = closestHeight; + dm.dmBitsPerPel = closestBPP; + + if (*refreshRate > 0) + { + dm.dmFields |= DM_DISPLAYFREQUENCY; + dm.dmDisplayFrequency = closestRate; + } + + if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL) + { + *width = closestWidth; + *height = closestHeight; + *bpp = closestBPP; + *refreshRate = closestRate; + } + } + else + { + dm.dmSize = sizeof(DEVMODE); + EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &dm); + + *width = dm.dmPelsWidth; + *height = dm.dmPelsHeight; + *bpp = dm.dmBitsPerPel; + *refreshRate = dm.dmDisplayFrequency; + } +} + + +//======================================================================== +// Restore the previously saved (original) video mode +//======================================================================== + +void _glfwRestoreVideoMode(void) +{ + ChangeDisplaySettings(NULL, CDS_FULLSCREEN); +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// @@ -164,3 +306,104 @@ void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor) free(monitor->Win32.name); } + +//======================================================================== +// Get a list of available video modes +//======================================================================== + +GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) +{ + int modeIndex = 0, count = 0; + GLFWvidmode* result = NULL; + + *found = 0; + + for (;;) + { + int i; + GLFWvidmode mode; + DEVMODE dm; + + ZeroMemory(&dm, sizeof(DEVMODE)); + dm.dmSize = sizeof(DEVMODE); + + if (!EnumDisplaySettings(monitor->Win32.name, modeIndex, &dm)) + break; + + modeIndex++; + + if (dm.dmBitsPerPel < 15) + { + // Skip modes with less than 15 BPP + continue; + } + + mode.width = dm.dmPelsWidth; + mode.height = dm.dmPelsHeight; + _glfwSplitBPP(dm.dmBitsPerPel, + &mode.redBits, + &mode.greenBits, + &mode.blueBits); + + for (i = 0; i < *found; i++) + { + if (_glfwCompareVideoModes(result + i, &mode) == 0) + break; + } + + if (i < *found) + { + // This is a duplicate, so skip it + continue; + } + + if (*found == count) + { + void* larger; + + if (count) + count *= 2; + else + count = 128; + + larger = realloc(result, count * sizeof(GLFWvidmode)); + if (!larger) + { + free(result); + + _glfwSetError(GLFW_OUT_OF_MEMORY, NULL); + return NULL; + } + + result = (GLFWvidmode*) larger; + } + + result[*found] = mode; + (*found)++; + } + + return result; +} + + +//======================================================================== +// Get the current video mode for the specified monitor +//======================================================================== + +void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) +{ + DEVMODE dm; + + ZeroMemory(&dm, sizeof(DEVMODE)); + dm.dmSize = sizeof(DEVMODE); + + EnumDisplaySettings(monitor->Win32.name, ENUM_REGISTRY_SETTINGS, &dm); + + mode->width = dm.dmPelsWidth; + mode->height = dm.dmPelsHeight; + _glfwSplitBPP(dm.dmBitsPerPel, + &mode->redBits, + &mode->greenBits, + &mode->blueBits); +} + diff --git a/src/x11_fullscreen.c b/src/x11_fullscreen.c deleted file mode 100644 index 5848b296..00000000 --- a/src/x11_fullscreen.c +++ /dev/null @@ -1,531 +0,0 @@ -//======================================================================== -// GLFW - An OpenGL library -// Platform: X11 -// API version: 3.0 -// WWW: http://www.glfw.org/ -//------------------------------------------------------------------------ -// Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2010 Camilla Berglund -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== - -#include "internal.h" - -#include -#include -#include - - -//------------------------------------------------------------------------ -// Display resolution -//------------------------------------------------------------------------ - -typedef struct -{ - int width; - int height; -} _GLFWvidsize; - - -//======================================================================== -// List available resolutions -//======================================================================== - -static _GLFWvidsize* getResolutions(_GLFWmonitor* monitor, int* found) -{ - int i, j; - _GLFWvidsize* result = NULL; - - *found = 0; - - // Build array of available resolutions - - if (_glfwLibrary.X11.RandR.available) - { -#if defined(_GLFW_HAS_XRANDR) - XRRScreenConfiguration* sc; - XRRScreenSize* sizes; - - sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root); - sizes = XRRConfigSizes(sc, found); - - result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * *found); - - for (i = 0; i < *found; i++) - { - result[i].width = sizes[i].width; - result[i].height = sizes[i].height; - } - - XRRFreeScreenConfigInfo(sc); -#endif /*_GLFW_HAS_XRANDR*/ - } - else if (_glfwLibrary.X11.VidMode.available) - { -#if defined(_GLFW_HAS_XF86VIDMODE) - XF86VidModeModeInfo** modes; - int modeCount; - - XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - &modeCount, &modes); - - result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * modeCount); - - for (i = 0; i < modeCount; i++) - { - _GLFWvidsize size; - size.width = modes[i]->hdisplay; - size.height = modes[i]->vdisplay; - - for (j = 0; j < *found; j++) - { - if (memcmp(result + j, &size, sizeof(_GLFWvidsize)) == 0) - break; - } - - if (j < *found) - { - // This size is a duplicate, so skip it - continue; - } - - result[*found] = size; - (*found)++; - } - - XFree(modes); -#endif /*_GLFW_HAS_XF86VIDMODE*/ - } - - if (result == NULL) - { - *found = 1; - result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize)); - - result[0].width = DisplayWidth(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen); - result[0].height = DisplayHeight(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen); - } - - return result; -} - - - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Finds the video mode closest in size to the specified desired size -//======================================================================== - -int _glfwGetClosestVideoMode(int* width, int* height, int* rate) -{ - int i, match, bestmatch; - - if (_glfwLibrary.X11.RandR.available) - { -#if defined(_GLFW_HAS_XRANDR) - int sizecount, bestsize; - int ratecount, bestrate; - short* ratelist; - XRRScreenConfiguration* sc; - XRRScreenSize* sizelist; - - sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root); - - sizelist = XRRConfigSizes(sc, &sizecount); - - // Find the best matching mode - bestsize = -1; - bestmatch = INT_MAX; - for (i = 0; i < sizecount; i++) - { - match = (*width - sizelist[i].width) * - (*width - sizelist[i].width) + - (*height - sizelist[i].height) * - (*height - sizelist[i].height); - if (match < bestmatch) - { - bestmatch = match; - bestsize = i; - } - } - - if (bestsize != -1) - { - // Report width & height of best matching mode - *width = sizelist[bestsize].width; - *height = sizelist[bestsize].height; - - if (*rate > 0) - { - ratelist = XRRConfigRates(sc, bestsize, &ratecount); - - bestrate = -1; - bestmatch = INT_MAX; - for (i = 0; i < ratecount; i++) - { - match = abs(ratelist[i] - *rate); - if (match < bestmatch) - { - bestmatch = match; - bestrate = ratelist[i]; - } - } - - if (bestrate != -1) - *rate = bestrate; - } - } - - XRRFreeScreenConfigInfo(sc); - - if (bestsize != -1) - return bestsize; -#endif /*_GLFW_HAS_XRANDR*/ - } - else if (_glfwLibrary.X11.VidMode.available) - { -#if defined(_GLFW_HAS_XF86VIDMODE) - XF86VidModeModeInfo** modelist; - int bestmode, modecount; - - // Get a list of all available display modes - XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - &modecount, &modelist); - - // Find the best matching mode - bestmode = -1; - bestmatch = INT_MAX; - for (i = 0; i < modecount; i++) - { - match = (*width - modelist[i]->hdisplay) * - (*width - modelist[i]->hdisplay) + - (*height - modelist[i]->vdisplay) * - (*height - modelist[i]->vdisplay); - if (match < bestmatch) - { - bestmatch = match; - bestmode = i; - } - } - - if (bestmode != -1) - { - // Report width & height of best matching mode - *width = modelist[bestmode]->hdisplay; - *height = modelist[bestmode]->vdisplay; - } - - XFree(modelist); - - if (bestmode != -1) - return bestmode; -#endif /*_GLFW_HAS_XF86VIDMODE*/ - } - - // Default: Simply use the screen resolution - *width = DisplayWidth(_glfwLibrary.X11.display, _glfwLibrary.X11.screen); - *height = DisplayHeight(_glfwLibrary.X11.display, _glfwLibrary.X11.screen); - - return 0; -} - - -//======================================================================== -// Change the current video mode -//======================================================================== - -void _glfwSetVideoModeMODE(int mode, int rate) -{ - if (_glfwLibrary.X11.RandR.available) - { -#if defined(_GLFW_HAS_XRANDR) - XRRScreenConfiguration* sc; - Window root; - - root = _glfwLibrary.X11.root; - sc = XRRGetScreenInfo(_glfwLibrary.X11.display, root); - - // Remember old size and flag that we have changed the mode - if (!_glfwLibrary.X11.FS.modeChanged) - { - _glfwLibrary.X11.FS.oldSizeID = XRRConfigCurrentConfiguration(sc, &_glfwLibrary.X11.FS.oldRotation); - _glfwLibrary.X11.FS.oldWidth = DisplayWidth(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen); - _glfwLibrary.X11.FS.oldHeight = DisplayHeight(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen); - - _glfwLibrary.X11.FS.modeChanged = GL_TRUE; - } - - if (rate > 0) - { - // Set desired configuration - XRRSetScreenConfigAndRate(_glfwLibrary.X11.display, - sc, - root, - mode, - RR_Rotate_0, - (short) rate, - CurrentTime); - } - else - { - // Set desired configuration - XRRSetScreenConfig(_glfwLibrary.X11.display, - sc, - root, - mode, - RR_Rotate_0, - CurrentTime); - } - - XRRFreeScreenConfigInfo(sc); -#endif /*_GLFW_HAS_XRANDR*/ - } - else if (_glfwLibrary.X11.VidMode.available) - { -#if defined(_GLFW_HAS_XF86VIDMODE) - XF86VidModeModeInfo **modelist; - int modecount; - - // Get a list of all available display modes - XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - &modecount, &modelist); - - // Unlock mode switch if necessary - if (_glfwLibrary.X11.FS.modeChanged) - { - XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - 0); - } - - // Change the video mode to the desired mode - XF86VidModeSwitchToMode(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - modelist[mode]); - - // Set viewport to upper left corner (where our window will be) - XF86VidModeSetViewPort(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - 0, 0); - - // Lock mode switch - XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - 1); - - // Remember old mode and flag that we have changed the mode - if (!_glfwLibrary.X11.FS.modeChanged) - { - _glfwLibrary.X11.FS.oldMode = *modelist[0]; - _glfwLibrary.X11.FS.modeChanged = GL_TRUE; - } - - XFree(modelist); -#endif /*_GLFW_HAS_XF86VIDMODE*/ - } -} - - -//======================================================================== -// Change the current video mode -//======================================================================== - -void _glfwSetVideoMode(int* width, int* height, int* rate) -{ - int bestmode; - - // Find a best match mode - bestmode = _glfwGetClosestVideoMode(width, height, rate); - - // Change mode - _glfwSetVideoModeMODE(bestmode, *rate); -} - - -//======================================================================== -// Restore the previously saved (original) video mode -//======================================================================== - -void _glfwRestoreVideoMode(void) -{ - if (_glfwLibrary.X11.FS.modeChanged) - { - if (_glfwLibrary.X11.RandR.available) - { -#if defined(_GLFW_HAS_XRANDR) - XRRScreenConfiguration* sc; - - if (_glfwLibrary.X11.RandR.available) - { - sc = XRRGetScreenInfo(_glfwLibrary.X11.display, - _glfwLibrary.X11.root); - - XRRSetScreenConfig(_glfwLibrary.X11.display, - sc, - _glfwLibrary.X11.root, - _glfwLibrary.X11.FS.oldSizeID, - _glfwLibrary.X11.FS.oldRotation, - CurrentTime); - - XRRFreeScreenConfigInfo(sc); - } -#endif /*_GLFW_HAS_XRANDR*/ - } - else if (_glfwLibrary.X11.VidMode.available) - { -#if defined(_GLFW_HAS_XF86VIDMODE) - // Unlock mode switch - XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - 0); - - // Change the video mode back to the old mode - XF86VidModeSwitchToMode(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - &_glfwLibrary.X11.FS.oldMode); -#endif /*_GLFW_HAS_XF86VIDMODE*/ - } - - _glfwLibrary.X11.FS.modeChanged = GL_FALSE; - } -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// List available video modes -//======================================================================== - -GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) -{ - XVisualInfo* visuals; - XVisualInfo dummy; - int i, j, visualCount, sizeCount, rgbCount; - int* rgbs; - _GLFWvidsize* sizes; - GLFWvidmode* result; - - visuals = XGetVisualInfo(_glfwLibrary.X11.display, 0, &dummy, &visualCount); - if (visuals == NULL) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11: Failed to retrieve the available visuals"); - return 0; - } - - // Build array of available RGB channel depths - - rgbs = (int*) malloc(sizeof(int) * visualCount); - rgbCount = 0; - - for (i = 0; i < visualCount; i++) - { - int gl, rgba, rgb, r, g, b; - - glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_USE_GL, &gl); - glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_RGBA, &rgba); - - if (!gl || !rgba) - { - // The visual lacks OpenGL or true color, so skip it - continue; - } - - // Convert to RGB channel depths and encode - _glfwSplitBPP(visuals[i].depth, &r, &g, &b); - rgb = (r << 16) | (g << 8) | b; - - for (j = 0; j < rgbCount; j++) - { - if (rgbs[j] == rgb) - break; - } - - if (j < rgbCount) - { - // This channel depth is a duplicate, so skip it - continue; - } - - rgbs[rgbCount] = rgb; - rgbCount++; - } - - XFree(visuals); - - // Build all permutations of channel depths and resolutions - - sizes = getResolutions(monitor, &sizeCount); - - result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * rgbCount * sizeCount); - *found = 0; - - for (i = 0; i < rgbCount; i++) - { - for (j = 0; j < sizeCount; j++) - { - result[*found].width = sizes[j].width; - result[*found].height = sizes[j].height; - result[*found].redBits = (rgbs[i] >> 16) & 255; - result[*found].greenBits = (rgbs[i] >> 8) & 255; - result[*found].blueBits = rgbs[i] & 255; - - (*found)++; - } - } - - free(sizes); - free(rgbs); - - return result; -} - - -//======================================================================== -// Get the current video mode for the specified monitor -//======================================================================== - -void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) -{ - _glfwSplitBPP(DefaultDepth(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen), - &mode->redBits, &mode->greenBits, &mode->blueBits); - - mode->width = DisplayWidth(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen); - mode->height = DisplayHeight(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen); -} - diff --git a/src/x11_monitor.c b/src/x11_monitor.c index fafe971f..39a7be82 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -30,10 +30,396 @@ #include "internal.h" +#include #include #include +//------------------------------------------------------------------------ +// Display resolution +//------------------------------------------------------------------------ + +typedef struct +{ + int width; + int height; +} _GLFWvidsize; + + +//======================================================================== +// List available resolutions +//======================================================================== + +static _GLFWvidsize* getResolutions(_GLFWmonitor* monitor, int* found) +{ + int i, j; + _GLFWvidsize* result = NULL; + + *found = 0; + + // Build array of available resolutions + + if (_glfwLibrary.X11.RandR.available) + { +#if defined(_GLFW_HAS_XRANDR) + XRRScreenConfiguration* sc; + XRRScreenSize* sizes; + + sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root); + sizes = XRRConfigSizes(sc, found); + + result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * *found); + + for (i = 0; i < *found; i++) + { + result[i].width = sizes[i].width; + result[i].height = sizes[i].height; + } + + XRRFreeScreenConfigInfo(sc); +#endif /*_GLFW_HAS_XRANDR*/ + } + else if (_glfwLibrary.X11.VidMode.available) + { +#if defined(_GLFW_HAS_XF86VIDMODE) + XF86VidModeModeInfo** modes; + int modeCount; + + XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + &modeCount, &modes); + + result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * modeCount); + + for (i = 0; i < modeCount; i++) + { + _GLFWvidsize size; + size.width = modes[i]->hdisplay; + size.height = modes[i]->vdisplay; + + for (j = 0; j < *found; j++) + { + if (memcmp(result + j, &size, sizeof(_GLFWvidsize)) == 0) + break; + } + + if (j < *found) + { + // This size is a duplicate, so skip it + continue; + } + + result[*found] = size; + (*found)++; + } + + XFree(modes); +#endif /*_GLFW_HAS_XF86VIDMODE*/ + } + + if (result == NULL) + { + *found = 1; + result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize)); + + result[0].width = DisplayWidth(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); + result[0].height = DisplayHeight(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); + } + + return result; +} + + + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Finds the video mode closest in size to the specified desired size +//======================================================================== + +int _glfwGetClosestVideoMode(int* width, int* height, int* rate) +{ + int i, match, bestmatch; + + if (_glfwLibrary.X11.RandR.available) + { +#if defined(_GLFW_HAS_XRANDR) + int sizecount, bestsize; + int ratecount, bestrate; + short* ratelist; + XRRScreenConfiguration* sc; + XRRScreenSize* sizelist; + + sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root); + + sizelist = XRRConfigSizes(sc, &sizecount); + + // Find the best matching mode + bestsize = -1; + bestmatch = INT_MAX; + for (i = 0; i < sizecount; i++) + { + match = (*width - sizelist[i].width) * + (*width - sizelist[i].width) + + (*height - sizelist[i].height) * + (*height - sizelist[i].height); + if (match < bestmatch) + { + bestmatch = match; + bestsize = i; + } + } + + if (bestsize != -1) + { + // Report width & height of best matching mode + *width = sizelist[bestsize].width; + *height = sizelist[bestsize].height; + + if (*rate > 0) + { + ratelist = XRRConfigRates(sc, bestsize, &ratecount); + + bestrate = -1; + bestmatch = INT_MAX; + for (i = 0; i < ratecount; i++) + { + match = abs(ratelist[i] - *rate); + if (match < bestmatch) + { + bestmatch = match; + bestrate = ratelist[i]; + } + } + + if (bestrate != -1) + *rate = bestrate; + } + } + + XRRFreeScreenConfigInfo(sc); + + if (bestsize != -1) + return bestsize; +#endif /*_GLFW_HAS_XRANDR*/ + } + else if (_glfwLibrary.X11.VidMode.available) + { +#if defined(_GLFW_HAS_XF86VIDMODE) + XF86VidModeModeInfo** modelist; + int bestmode, modecount; + + // Get a list of all available display modes + XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + &modecount, &modelist); + + // Find the best matching mode + bestmode = -1; + bestmatch = INT_MAX; + for (i = 0; i < modecount; i++) + { + match = (*width - modelist[i]->hdisplay) * + (*width - modelist[i]->hdisplay) + + (*height - modelist[i]->vdisplay) * + (*height - modelist[i]->vdisplay); + if (match < bestmatch) + { + bestmatch = match; + bestmode = i; + } + } + + if (bestmode != -1) + { + // Report width & height of best matching mode + *width = modelist[bestmode]->hdisplay; + *height = modelist[bestmode]->vdisplay; + } + + XFree(modelist); + + if (bestmode != -1) + return bestmode; +#endif /*_GLFW_HAS_XF86VIDMODE*/ + } + + // Default: Simply use the screen resolution + *width = DisplayWidth(_glfwLibrary.X11.display, _glfwLibrary.X11.screen); + *height = DisplayHeight(_glfwLibrary.X11.display, _glfwLibrary.X11.screen); + + return 0; +} + + +//======================================================================== +// Change the current video mode +//======================================================================== + +void _glfwSetVideoModeMODE(int mode, int rate) +{ + if (_glfwLibrary.X11.RandR.available) + { +#if defined(_GLFW_HAS_XRANDR) + XRRScreenConfiguration* sc; + Window root; + + root = _glfwLibrary.X11.root; + sc = XRRGetScreenInfo(_glfwLibrary.X11.display, root); + + // Remember old size and flag that we have changed the mode + if (!_glfwLibrary.X11.FS.modeChanged) + { + _glfwLibrary.X11.FS.oldSizeID = XRRConfigCurrentConfiguration(sc, &_glfwLibrary.X11.FS.oldRotation); + _glfwLibrary.X11.FS.oldWidth = DisplayWidth(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); + _glfwLibrary.X11.FS.oldHeight = DisplayHeight(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); + + _glfwLibrary.X11.FS.modeChanged = GL_TRUE; + } + + if (rate > 0) + { + // Set desired configuration + XRRSetScreenConfigAndRate(_glfwLibrary.X11.display, + sc, + root, + mode, + RR_Rotate_0, + (short) rate, + CurrentTime); + } + else + { + // Set desired configuration + XRRSetScreenConfig(_glfwLibrary.X11.display, + sc, + root, + mode, + RR_Rotate_0, + CurrentTime); + } + + XRRFreeScreenConfigInfo(sc); +#endif /*_GLFW_HAS_XRANDR*/ + } + else if (_glfwLibrary.X11.VidMode.available) + { +#if defined(_GLFW_HAS_XF86VIDMODE) + XF86VidModeModeInfo **modelist; + int modecount; + + // Get a list of all available display modes + XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + &modecount, &modelist); + + // Unlock mode switch if necessary + if (_glfwLibrary.X11.FS.modeChanged) + { + XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + 0); + } + + // Change the video mode to the desired mode + XF86VidModeSwitchToMode(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + modelist[mode]); + + // Set viewport to upper left corner (where our window will be) + XF86VidModeSetViewPort(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + 0, 0); + + // Lock mode switch + XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + 1); + + // Remember old mode and flag that we have changed the mode + if (!_glfwLibrary.X11.FS.modeChanged) + { + _glfwLibrary.X11.FS.oldMode = *modelist[0]; + _glfwLibrary.X11.FS.modeChanged = GL_TRUE; + } + + XFree(modelist); +#endif /*_GLFW_HAS_XF86VIDMODE*/ + } +} + + +//======================================================================== +// Change the current video mode +//======================================================================== + +void _glfwSetVideoMode(int* width, int* height, int* rate) +{ + int bestmode; + + // Find a best match mode + bestmode = _glfwGetClosestVideoMode(width, height, rate); + + // Change mode + _glfwSetVideoModeMODE(bestmode, *rate); +} + + +//======================================================================== +// Restore the previously saved (original) video mode +//======================================================================== + +void _glfwRestoreVideoMode(void) +{ + if (_glfwLibrary.X11.FS.modeChanged) + { + if (_glfwLibrary.X11.RandR.available) + { +#if defined(_GLFW_HAS_XRANDR) + XRRScreenConfiguration* sc; + + if (_glfwLibrary.X11.RandR.available) + { + sc = XRRGetScreenInfo(_glfwLibrary.X11.display, + _glfwLibrary.X11.root); + + XRRSetScreenConfig(_glfwLibrary.X11.display, + sc, + _glfwLibrary.X11.root, + _glfwLibrary.X11.FS.oldSizeID, + _glfwLibrary.X11.FS.oldRotation, + CurrentTime); + + XRRFreeScreenConfigInfo(sc); + } +#endif /*_GLFW_HAS_XRANDR*/ + } + else if (_glfwLibrary.X11.VidMode.available) + { +#if defined(_GLFW_HAS_XF86VIDMODE) + // Unlock mode switch + XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + 0); + + // Change the video mode back to the old mode + XF86VidModeSwitchToMode(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + &_glfwLibrary.X11.FS.oldMode); +#endif /*_GLFW_HAS_XF86VIDMODE*/ + } + + _glfwLibrary.X11.FS.modeChanged = GL_FALSE; + } +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// @@ -113,3 +499,109 @@ void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor) #endif /*_GLFW_HAS_XRANDR*/ } + +//======================================================================== +// List available video modes +//======================================================================== + +GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) +{ + XVisualInfo* visuals; + XVisualInfo dummy; + int i, j, visualCount, sizeCount, rgbCount; + int* rgbs; + _GLFWvidsize* sizes; + GLFWvidmode* result; + + visuals = XGetVisualInfo(_glfwLibrary.X11.display, 0, &dummy, &visualCount); + if (visuals == NULL) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11: Failed to retrieve the available visuals"); + return 0; + } + + // Build array of available RGB channel depths + + rgbs = (int*) malloc(sizeof(int) * visualCount); + rgbCount = 0; + + for (i = 0; i < visualCount; i++) + { + int gl, rgba, rgb, r, g, b; + + glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_USE_GL, &gl); + glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_RGBA, &rgba); + + if (!gl || !rgba) + { + // The visual lacks OpenGL or true color, so skip it + continue; + } + + // Convert to RGB channel depths and encode + _glfwSplitBPP(visuals[i].depth, &r, &g, &b); + rgb = (r << 16) | (g << 8) | b; + + for (j = 0; j < rgbCount; j++) + { + if (rgbs[j] == rgb) + break; + } + + if (j < rgbCount) + { + // This channel depth is a duplicate, so skip it + continue; + } + + rgbs[rgbCount] = rgb; + rgbCount++; + } + + XFree(visuals); + + // Build all permutations of channel depths and resolutions + + sizes = getResolutions(monitor, &sizeCount); + + result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * rgbCount * sizeCount); + *found = 0; + + for (i = 0; i < rgbCount; i++) + { + for (j = 0; j < sizeCount; j++) + { + result[*found].width = sizes[j].width; + result[*found].height = sizes[j].height; + result[*found].redBits = (rgbs[i] >> 16) & 255; + result[*found].greenBits = (rgbs[i] >> 8) & 255; + result[*found].blueBits = rgbs[i] & 255; + + (*found)++; + } + } + + free(sizes); + free(rgbs); + + return result; +} + + +//======================================================================== +// Get the current video mode for the specified monitor +//======================================================================== + +void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) +{ + _glfwSplitBPP(DefaultDepth(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen), + &mode->redBits, &mode->greenBits, &mode->blueBits); + + mode->width = DisplayWidth(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); + mode->height = DisplayHeight(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); +} +