mirror of
https://github.com/glfw/glfw.git
synced 2026-09-17 22:32:50 +00:00
Merged fullscreen and monitor modules.
This commit is contained in:
@@ -32,6 +32,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <malloc.h>
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user