1
0
Fork 0
mirror of https://github.com/gwm17/glfw.git synced 2024-10-08 23:27:25 -04:00
glfw/src/win32/win32_fullscreen.c

312 lines
9.6 KiB
C
Raw Normal View History

2010-09-07 11:34:51 -04:00
//========================================================================
// GLFW - An OpenGL framework
// Platform: Win32/WGL
2010-09-07 11:41:26 -04:00
// API version: 3.0
2010-09-07 11:34:51 -04:00
// WWW: http://www.glfw.org/
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
//
// 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"
//========================================================================
// Convert BPP to RGB bits based on "best guess"
//========================================================================
2010-09-10 16:03:36 -04:00
static void bpp2rgb(int bpp, int* r, int* g, int* b)
2010-09-07 11:34:51 -04:00
{
int delta;
// We assume that by 32 they really meant 24
2010-09-10 16:03:36 -04:00
if (bpp == 32)
2010-09-07 11:34:51 -04:00
bpp = 24;
// Convert "bits per pixel" to red, green & blue sizes
*r = *g = *b = bpp / 3;
delta = bpp - (*r * 3);
2010-09-10 16:03:36 -04:00
if (delta >= 1)
2010-09-07 11:34:51 -04:00
*g = *g + 1;
2010-09-10 16:03:36 -04:00
if (delta == 2)
2010-09-07 11:34:51 -04:00
*r = *r + 1;
}
2010-09-10 16:03:36 -04:00
//========================================================================
// Return closest video mode by dimensions, refresh rate and channel sizes
//========================================================================
static int getClosestVideoMode(int* w, int* h,
int* r, int* g, int* b,
int* refresh)
{
int bpp, bestmode;
// Colorbits = sum of red/green/blue bits
bpp = *r + *g + *b;
// If colorbits < 15 (e.g. 0) or >= 24, default to 32 bpp
if (bpp < 15 || bpp >= 24)
bpp = 32;
// Find best match
bestmode = _glfwGetClosestVideoModeBPP(w, h, &bpp, refresh);
// Convert "bits per pixel" to red, green & blue sizes
bpp2rgb(bpp, r, g, b);
return bestmode;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
2010-09-07 11:34:51 -04:00
//========================================================================
// Return closest video mode by dimensions, refresh rate and bits per pixel
//========================================================================
2010-09-10 16:03:36 -04:00
int _glfwGetClosestVideoModeBPP(int* w, int* h, int* bpp, int* refresh)
2010-09-07 11:34:51 -04:00
{
2010-09-10 16:03:36 -04:00
int mode, bestmode, match, bestmatch, rr, bestrr, success;
2010-09-07 11:34:51 -04:00
DEVMODE dm;
// Find best match
bestmatch = 0x7fffffff;
bestrr = 0x7fffffff;
mode = bestmode = 0;
2010-09-10 16:03:36 -04:00
2010-09-07 11:34:51 -04:00
do
{
2010-09-10 16:03:36 -04:00
dm.dmSize = sizeof(DEVMODE);
success = EnumDisplaySettings(NULL, mode, &dm);
if (success)
2010-09-07 11:34:51 -04:00
{
match = dm.dmBitsPerPel - *bpp;
2010-09-10 16:03:36 -04:00
if (match < 0)
match = -match;
match = (match << 25) |
((dm.dmPelsWidth - *w) *
(dm.dmPelsWidth - *w) +
(dm.dmPelsHeight - *h) *
(dm.dmPelsHeight - *h));
if (match < bestmatch)
2010-09-07 11:34:51 -04:00
{
bestmatch = match;
bestmode = mode;
bestrr = (dm.dmDisplayFrequency - *refresh) *
(dm.dmDisplayFrequency - *refresh);
}
2010-09-10 16:03:36 -04:00
else if (match == bestmatch && *refresh > 0)
2010-09-07 11:34:51 -04:00
{
rr = (dm.dmDisplayFrequency - *refresh) *
(dm.dmDisplayFrequency - *refresh);
2010-09-10 16:03:36 -04:00
if (rr < bestrr)
2010-09-07 11:34:51 -04:00
{
bestmatch = match;
bestmode = mode;
bestrr = rr;
}
}
}
2010-09-10 16:03:36 -04:00
mode++;
2010-09-07 11:34:51 -04:00
}
2010-09-10 16:03:36 -04:00
while (success);
2010-09-07 11:34:51 -04:00
// Get the parameters for the best matching display mode
2010-09-10 16:03:36 -04:00
dm.dmSize = sizeof(DEVMODE);
EnumDisplaySettings(NULL, bestmode, &dm);
2010-09-07 11:34:51 -04:00
// Fill out actual width and height
*w = dm.dmPelsWidth;
*h = dm.dmPelsHeight;
// Return bits per pixel
*bpp = dm.dmBitsPerPel;
// Return vertical refresh rate
*refresh = dm.dmDisplayFrequency;
return bestmode;
}
//========================================================================
// Change the current video mode
//========================================================================
2010-09-10 16:03:36 -04:00
void _glfwSetVideoModeMODE(int mode)
2010-09-07 11:34:51 -04:00
{
DEVMODE dm;
int success;
// Get the parameters for the best matching display mode
2010-09-10 16:03:36 -04:00
dm.dmSize = sizeof(DEVMODE);
EnumDisplaySettings(NULL, mode, &dm);
2010-09-07 11:34:51 -04:00
// Set which fields we want to specify
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
// Do we have a prefered refresh rate?
2010-09-10 16:03:36 -04:00
if (_glfwWin.desiredRefreshRate > 0)
2010-09-07 11:34:51 -04:00
{
dm.dmFields = dm.dmFields | DM_DISPLAYFREQUENCY;
dm.dmDisplayFrequency = _glfwWin.desiredRefreshRate;
}
// Change display setting
2010-09-10 16:03:36 -04:00
dm.dmSize = sizeof(DEVMODE);
success = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
2010-09-07 11:34:51 -04:00
// If the mode change was not possible, query the current display
// settings (we'll use the desktop resolution for fullscreen mode)
2010-09-10 16:03:36 -04:00
if (success == DISP_CHANGE_SUCCESSFUL)
2010-09-07 11:34:51 -04:00
_glfwWin.modeID = mode;
else
{
_glfwWin.modeID = ENUM_REGISTRY_SETTINGS;
2010-09-10 16:03:36 -04:00
EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &dm);
2010-09-07 11:34:51 -04:00
}
// Set the window size to that of the display mode
_glfwWin.width = dm.dmPelsWidth;
_glfwWin.height = dm.dmPelsHeight;
}
//========================================================================
2010-09-07 11:50:43 -04:00
// Change the current video mode
2010-09-07 11:34:51 -04:00
//========================================================================
2010-09-10 16:03:36 -04:00
void _glfwSetVideoMode(int* w, int* h, int r, int g, int b, int refresh)
2010-09-07 11:34:51 -04:00
{
2010-09-10 16:03:36 -04:00
int bestmode;
2010-09-07 11:34:51 -04:00
// Find a best match mode
2010-09-10 16:03:36 -04:00
bestmode = getClosestVideoMode(w, h, &r, &g, &b, &refresh);
2010-09-07 11:34:51 -04:00
// Change mode
2010-09-10 16:03:36 -04:00
_glfwSetVideoModeMODE(bestmode);
2010-09-07 11:34:51 -04:00
}
2010-09-10 16:03:36 -04:00
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
2010-09-07 11:34:51 -04:00
//========================================================================
2010-09-07 11:50:43 -04:00
// Get a list of available video modes
2010-09-07 11:34:51 -04:00
//========================================================================
2010-09-10 16:03:36 -04:00
int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount)
2010-09-07 11:34:51 -04:00
{
int count, success, mode, i, j;
int m1, m2, bpp, r, g, b;
DEVMODE dm;
// Loop through all video modes and extract all the UNIQUE modes
count = 0;
mode = 0;
2010-09-10 16:03:36 -04:00
2010-09-07 11:34:51 -04:00
do
{
// Get video mode properties
2010-09-10 16:03:36 -04:00
dm.dmSize = sizeof(DEVMODE);
success = EnumDisplaySettings(NULL, mode, &dm);
2010-09-07 11:34:51 -04:00
// Is it a valid mode? (only list depths >= 15 bpp)
2010-09-10 16:03:36 -04:00
if (success && dm.dmBitsPerPel >= 15)
2010-09-07 11:34:51 -04:00
{
// Convert to RGB, and back to bpp ("mask out" alpha bits etc)
2010-09-10 16:03:36 -04:00
bpp2rgb(dm.dmBitsPerPel, &r, &g, &b);
2010-09-07 11:34:51 -04:00
bpp = r + g + b;
// Mode "code" for this mode
m1 = (bpp << 25) | (dm.dmPelsWidth * dm.dmPelsHeight);
// Insert mode in list (sorted), and avoid duplicates
2010-09-10 16:03:36 -04:00
for (i = 0; i < count; i++)
2010-09-07 11:34:51 -04:00
{
// Mode "code" for already listed mode
2010-09-10 16:03:36 -04:00
bpp = list[i].redBits + list[i].greenBits + list[i].blueBits;
2010-09-08 10:50:50 -04:00
m2 = (bpp << 25) | (list[i].width * list[i].height);
2010-09-10 16:03:36 -04:00
if (m1 <= m2)
2010-09-07 11:34:51 -04:00
break;
}
// New entry at the end of the list?
2010-09-10 16:03:36 -04:00
if (i >= count)
2010-09-07 11:34:51 -04:00
{
2010-09-08 10:50:50 -04:00
list[count].width = dm.dmPelsWidth;
list[count].height = dm.dmPelsHeight;
list[count].redBits = r;
list[count].greenBits = g;
list[count].blueBits = b;
2010-09-07 11:34:51 -04:00
count ++;
}
// Insert new entry in the list?
2010-09-10 16:03:36 -04:00
else if (m1 < m2)
2010-09-07 11:34:51 -04:00
{
2010-09-10 16:03:36 -04:00
for (j = count; j > i; j--)
list[j] = list[j - 1];
2010-09-08 10:50:50 -04:00
list[i].width = dm.dmPelsWidth;
list[i].height = dm.dmPelsHeight;
list[i].redBits = r;
list[i].greenBits = g;
list[i].blueBits = b;
2010-09-10 16:03:36 -04:00
count++;
2010-09-07 11:34:51 -04:00
}
}
2010-09-10 16:03:36 -04:00
mode++;
2010-09-07 11:34:51 -04:00
}
2010-09-10 16:03:36 -04:00
while (success && (count < maxcount));
2010-09-07 11:34:51 -04:00
return count;
}
//========================================================================
// Get the desktop video mode
//========================================================================
2010-09-10 16:03:36 -04:00
void _glfwPlatformGetDesktopMode(GLFWvidmode* mode)
2010-09-07 11:34:51 -04:00
{
DEVMODE dm;
// Get desktop display mode
2010-09-10 16:03:36 -04:00
dm.dmSize = sizeof(DEVMODE);
EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &dm);
2010-09-07 11:34:51 -04:00
// Return desktop mode parameters
2010-09-08 10:50:50 -04:00
mode->width = dm.dmPelsWidth;
mode->height = dm.dmPelsHeight;
2010-09-10 16:03:36 -04:00
bpp2rgb(dm.dmBitsPerPel, &mode->redBits, &mode->greenBits, &mode->blueBits);
2010-09-07 11:34:51 -04:00
}