Begun integrating mode setting and monitor API.

This commit is contained in:
Camilla Berglund 2013-01-02 17:29:24 +01:00
parent 1bc91bfe5b
commit 46c1e4028f
13 changed files with 138 additions and 217 deletions

View File

@ -139,7 +139,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode)
// Change the current video mode
//========================================================================
GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp)
GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, int* width, int* height, int* bpp)
{
CGDisplayModeRef bestMode = NULL;
CFArrayRef modes;
@ -190,7 +190,7 @@ GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp)
return GL_FALSE;
}
_glfw.ns.previousMode = CGDisplayCopyDisplayMode(CGMainDisplayID());
monitor->ns.previousMode = CGDisplayCopyDisplayMode(CGMainDisplayID());
CGDisplayCapture(CGMainDisplayID());
CGDisplaySetDisplayMode(CGMainDisplayID(), bestMode, NULL);
@ -204,9 +204,9 @@ GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp)
// Restore the previously saved (original) video mode
//========================================================================
void _glfwRestoreVideoMode(void)
void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
{
CGDisplaySetDisplayMode(CGMainDisplayID(), _glfw.ns.previousMode, NULL);
CGDisplaySetDisplayMode(CGMainDisplayID(), monitor->ns.previousMode, NULL);
CGDisplayRelease(CGMainDisplayID());
}
@ -236,6 +236,8 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
return NULL;
}
CGGetActiveDisplayList(monitorCount, displays, &monitorCount);
monitors = (_GLFWmonitor**) calloc(monitorCount, sizeof(_GLFWmonitor*));
if (!monitors)
{

View File

@ -83,7 +83,6 @@ typedef struct _GLFWlibraryNS
double resolution;
} timer;
CGDisplayModeRef previousMode;
CGEventSourceRef eventSource;
id delegate;
id autoreleasePool;
@ -98,6 +97,7 @@ typedef struct _GLFWlibraryNS
typedef struct _GLFWmonitorNS
{
CGDirectDisplayID displayID;
CGDisplayModeRef previousMode;
} _GLFWmonitorNS;
@ -114,8 +114,8 @@ void _glfwInitJoysticks(void);
void _glfwTerminateJoysticks(void);
// Fullscreen
GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp);
void _glfwRestoreVideoMode(void);
GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, int* width, int* height, int* bpp);
void _glfwRestoreVideoMode(_GLFWmonitor* monitor);
// OpenGL support
int _glfwInitOpenGL(void);

View File

@ -772,7 +772,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
{
int bpp = colorBits + fbconfig->alphaBits;
if (!_glfwSetVideoMode(&window->width, &window->height, &bpp))
if (!_glfwSetVideoMode(window->monitor, &window->width, &window->height, &bpp))
return GL_FALSE;
_glfwPlatformShowWindow(window);
@ -800,7 +800,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{
[[window->ns.object contentView] exitFullScreenModeWithOptions:nil];
_glfwRestoreVideoMode();
_glfwRestoreVideoMode(window->monitor);
}
_glfwDestroyContext(window);

View File

@ -209,6 +209,7 @@ struct _GLFWwindow
GLboolean visible;
GLboolean closeRequested;
void* userPointer;
GLFWvidmode videoMode;
_GLFWmonitor* monitor;
// Window input state
@ -639,9 +640,8 @@ void _glfwInputError(int error, const char* format, ...);
/*! @ingroup utility
*/
const GLFWvidmode* _glfwChooseVideoMode(const GLFWvidmode* desired,
const GLFWvidmode* alternatives,
unsigned int count);
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
const GLFWvidmode* desired);
/*! @brief Performs lexical comparison between two @ref GLFWvidmode structures.
* @ingroup utility

View File

@ -71,6 +71,28 @@ static int compareVideoModes(const void* firstPtr, const void* secondPtr)
}
//========================================================================
// Retrieves the available modes for the specified monitor
//========================================================================
static int refreshVideoModes(_GLFWmonitor* monitor)
{
int modeCount;
GLFWvidmode* modes = _glfwPlatformGetVideoModes(monitor, &modeCount);
if (!modes)
return GL_FALSE;
qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
free(monitor->modes);
monitor->modes = modes;
monitor->modeCount = modeCount;
return GL_TRUE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
@ -203,9 +225,8 @@ void _glfwDestroyMonitors(void)
// Returns the video mode closest to the desired one
//========================================================================
const GLFWvidmode* _glfwChooseVideoMode(const GLFWvidmode* desired,
const GLFWvidmode* alternatives,
unsigned int count)
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
const GLFWvidmode* desired)
{
unsigned int i;
unsigned int sizeDiff, leastSizeDiff = UINT_MAX;
@ -213,9 +234,12 @@ const GLFWvidmode* _glfwChooseVideoMode(const GLFWvidmode* desired,
const GLFWvidmode* current;
const GLFWvidmode* closest = NULL;
for (i = 0; i < count; i++)
if (!refreshVideoModes(monitor))
return NULL;
for (i = 0; i < monitor->modeCount; i++)
{
current = alternatives + i;
current = monitor->modes + i;
colorDiff = abs((current->redBits + current->greenBits + current->blueBits) -
(desired->redBits + desired->greenBits + desired->blueBits));
@ -440,16 +464,8 @@ GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor handle, int* count)
return NULL;
}
free(monitor->modes);
monitor->modes = _glfwPlatformGetVideoModes(monitor, &monitor->modeCount);
if (monitor->modes)
{
qsort(monitor->modes,
monitor->modeCount,
sizeof(GLFWvidmode),
compareVideoModes);
}
if (!refreshVideoModes(monitor))
return GL_FALSE;
*count = monitor->modeCount;
return monitor->modes;

View File

@ -44,60 +44,6 @@
#endif
//========================================================================
// Return closest video mode by dimensions and bits per pixel
//========================================================================
static GLboolean getClosestVideoMode(int* width, int* height,
int* bpp, GLboolean exactBPP)
{
int mode, bestWidth = 0, bestHeight = 0, bestBPP = 0;
unsigned int sizeDiff, leastSizeDiff;
GLboolean foundMode = GL_FALSE;
DEVMODE dm;
leastSizeDiff = 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));
// We match BPP first, then screen area
if ((sizeDiff < leastSizeDiff) || (sizeDiff == leastSizeDiff))
{
bestWidth = dm.dmPelsWidth;
bestHeight = dm.dmPelsHeight;
bestBPP = dm.dmBitsPerPel;
leastSizeDiff = sizeDiff;
foundMode = GL_TRUE;
}
}
if (!foundMode)
return GL_FALSE;
*width = bestWidth;
*height = bestHeight;
*bpp = bestBPP;
return GL_TRUE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
@ -106,41 +52,38 @@ static GLboolean getClosestVideoMode(int* width, int* height,
// Change the current video mode
//========================================================================
void _glfwSetVideoMode(int* width, int* height,
int* bpp, GLboolean exactBPP)
int _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* mode)
{
GLFWvidmode current;
const GLFWvidmode* best;
best = _glfwChooseVideoMode(monitor, mode);
_glfwPlatformGetVideoMode(monitor, &current);
if (_glfwCompareVideoModes(&current, best) == 0)
return GL_TRUE;
DEVMODE dm;
int closestWidth, closestHeight, closestBPP;
closestWidth = *width;
closestHeight = *height;
closestBPP = *bpp;
if (getClosestVideoMode(&closestWidth, &closestHeight,
&closestBPP, exactBPP))
{
dm.dmSize = sizeof(DEVMODE);
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
dm.dmPelsWidth = closestWidth;
dm.dmPelsHeight = closestHeight;
dm.dmBitsPerPel = closestBPP;
dm.dmPelsWidth = best->width;
dm.dmPelsHeight = best->height;
dm.dmBitsPerPel = best->redBits + best->greenBits + best->blueBits;
if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL)
{
*width = closestWidth;
*height = closestHeight;
*bpp = closestBPP;
}
}
else
{
dm.dmSize = sizeof(DEVMODE);
EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &dm);
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
dm.dmBitsPerPel = 32;
*width = dm.dmPelsWidth;
*height = dm.dmPelsHeight;
*bpp = dm.dmBitsPerPel;
if (ChangeDisplaySettingsEx(monitor->win32.name,
&dm,
NULL,
CDS_FULLSCREEN,
NULL) != DISP_CHANGE_SUCCESSFUL)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode");
return GL_FALSE;
}
return GL_TRUE;
}
@ -148,9 +91,10 @@ void _glfwSetVideoMode(int* width, int* height,
// Restore the previously saved (original) video mode
//========================================================================
void _glfwRestoreVideoMode(void)
void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
{
ChangeDisplaySettings(NULL, CDS_FULLSCREEN);
ChangeDisplaySettingsEx(monitor->win32.name,
NULL, NULL, CDS_FULLSCREEN, NULL);
}
@ -174,7 +118,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
DISPLAY_DEVICE adapter, monitor;
DEVMODE settings;
const char* name;
char* name;
HDC dc;
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICE));
@ -235,6 +179,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
settings.dmPosition.x,
settings.dmPosition.y);
free(name);
DeleteDC(dc);
if (!monitors[found])
@ -352,7 +297,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
ZeroMemory(&dm, sizeof(DEVMODE));
dm.dmSize = sizeof(DEVMODE);
EnumDisplaySettings(monitor->win32.name, ENUM_REGISTRY_SETTINGS, &dm);
EnumDisplaySettings(monitor->win32.name, ENUM_CURRENT_SETTINGS, &dm);
mode->width = dm.dmPelsWidth;
mode->height = dm.dmPelsHeight;

View File

@ -162,14 +162,6 @@ typedef struct _GLFWlibraryWin32
DWORD foregroundLockTimeout;
char* clipboardString;
// Default monitor
struct {
GLboolean modeChanged;
int width;
int height;
int bitsPerPixel;
} monitor;
// Timer data
struct {
GLboolean hasPC;
@ -231,8 +223,8 @@ int _glfwAnalyzeContext(const _GLFWwindow* window,
const _GLFWfbconfig* fbconfig);
// Fullscreen support
void _glfwSetVideoMode(int* width, int* height, int* bpp, GLboolean exactBPP);
void _glfwRestoreVideoMode(void);
int _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* mode);
void _glfwRestoreVideoMode(_GLFWmonitor* monitor);
#endif // _win32_platform_h_

View File

@ -356,11 +356,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
_glfwPlatformIconifyWindow(window);
}
if (_glfw.win32.monitor.modeChanged)
{
_glfwRestoreVideoMode();
_glfw.win32.monitor.modeChanged = GL_FALSE;
}
_glfwRestoreVideoMode(window->monitor);
}
}
else if (focused && _glfw.focusedWindow != window)
@ -371,17 +367,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
captureCursor(window);
if (window->monitor)
{
if (!_glfw.win32.monitor.modeChanged)
{
_glfwSetVideoMode(&_glfw.win32.monitor.width,
&_glfw.win32.monitor.height,
&_glfw.win32.monitor.bitsPerPixel,
GL_TRUE);
_glfw.win32.monitor.modeChanged = GL_TRUE;
}
}
_glfwSetVideoMode(window->monitor, &window->videoMode);
}
_glfwInputWindowFocus(window, focused);
@ -876,20 +862,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (window->monitor)
{
int bpp = fbconfig->redBits + fbconfig->greenBits + fbconfig->blueBits;
if (bpp < 15 || bpp >= 24)
bpp = 32;
_glfw.win32.monitor.width = window->width;
_glfw.win32.monitor.height = window->height;
_glfw.win32.monitor.bitsPerPixel = bpp;
_glfwSetVideoMode(&_glfw.win32.monitor.width,
&_glfw.win32.monitor.height,
&_glfw.win32.monitor.bitsPerPixel,
GL_FALSE);
_glfw.win32.monitor.modeChanged = GL_TRUE;
if (!_glfwSetVideoMode(window->monitor, &window->videoMode))
return GL_FALSE;
}
if (!createWindow(window, wndconfig, fbconfig))
@ -952,13 +926,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
destroyWindow(window);
if (window->monitor)
{
if (_glfw.win32.monitor.modeChanged)
{
_glfwRestoreVideoMode();
_glfw.win32.monitor.modeChanged = GL_FALSE;
}
}
_glfwRestoreVideoMode(window->monitor);
}

View File

@ -284,7 +284,16 @@ GLFWAPI GLFWwindow glfwCreateWindow(int width, int height,
window->height = height;
window->resizable = wndconfig.resizable;
window->cursorMode = GLFW_CURSOR_NORMAL;
window->monitor = (_GLFWmonitor*) monitor;
window->monitor = wndconfig.monitor;
if (window->monitor)
{
window->videoMode.width = width;
window->videoMode.height = height;
window->videoMode.redBits = fbconfig.redBits;
window->videoMode.greenBits = fbconfig.greenBits;
window->videoMode.blueBits = fbconfig.blueBits;
}
// Open the actual window and create its context
if (!_glfwPlatformCreateWindow(window, &wndconfig, &fbconfig))

View File

@ -43,7 +43,7 @@
// Finds the video mode closest in size to the specified desired size
//========================================================================
int _glfwGetClosestVideoMode(int* width, int* height)
int _glfwGetClosestVideoMode(_GLFWmonitor* monitor, int* width, int* height)
{
int i, match, bestmatch;
@ -100,7 +100,7 @@ int _glfwGetClosestVideoMode(int* width, int* height)
// Change the current video mode
//========================================================================
void _glfwSetVideoModeMODE(int mode)
void _glfwSetVideoModeMODE(_GLFWmonitor* monitor, int mode)
{
if (_glfw.x11.randr.available)
{
@ -112,15 +112,15 @@ void _glfwSetVideoModeMODE(int mode)
sc = XRRGetScreenInfo(_glfw.x11.display, root);
// Remember old size and flag that we have changed the mode
if (!_glfw.x11.fs.modeChanged)
if (!monitor->x11.modeChanged)
{
_glfw.x11.fs.oldSizeID = XRRConfigCurrentConfiguration(sc, &_glfw.x11.fs.oldRotation);
_glfw.x11.fs.oldWidth = DisplayWidth(_glfw.x11.display,
monitor->x11.oldSizeID = XRRConfigCurrentConfiguration(sc, &monitor->x11.oldRotation);
monitor->x11.oldWidth = DisplayWidth(_glfw.x11.display,
_glfw.x11.screen);
_glfw.x11.fs.oldHeight = DisplayHeight(_glfw.x11.display,
monitor->x11.oldHeight = DisplayHeight(_glfw.x11.display,
_glfw.x11.screen);
_glfw.x11.fs.modeChanged = GL_TRUE;
monitor->x11.modeChanged = GL_TRUE;
}
XRRSetScreenConfig(_glfw.x11.display,
@ -140,15 +140,15 @@ void _glfwSetVideoModeMODE(int mode)
// Change the current video mode
//========================================================================
void _glfwSetVideoMode(int* width, int* height)
void _glfwSetVideoMode(_GLFWmonitor* monitor, int* width, int* height)
{
int bestmode;
// Find a best match mode
bestmode = _glfwGetClosestVideoMode(width, height);
bestmode = _glfwGetClosestVideoMode(monitor, width, height);
// Change mode
_glfwSetVideoModeMODE(bestmode);
_glfwSetVideoModeMODE(monitor, bestmode);
}
@ -156,33 +156,30 @@ void _glfwSetVideoMode(int* width, int* height)
// Restore the previously saved (original) video mode
//========================================================================
void _glfwRestoreVideoMode(void)
void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
{
if (_glfw.x11.fs.modeChanged)
{
if (!monitor->x11.modeChanged)
return;
if (_glfw.x11.randr.available)
{
#if defined(_GLFW_HAS_XRANDR)
XRRScreenConfiguration* sc;
if (_glfw.x11.randr.available)
{
sc = XRRGetScreenInfo(_glfw.x11.display, _glfw.x11.root);
XRRSetScreenConfig(_glfw.x11.display,
sc,
_glfw.x11.root,
_glfw.x11.fs.oldSizeID,
_glfw.x11.fs.oldRotation,
monitor->x11.oldSizeID,
monitor->x11.oldRotation,
CurrentTime);
XRRFreeScreenConfigInfo(sc);
}
#endif /*_GLFW_HAS_XRANDR*/
}
_glfw.x11.fs.modeChanged = GL_FALSE;
}
monitor->x11.modeChanged = GL_FALSE;
}

View File

@ -173,20 +173,6 @@ typedef struct _GLFWlibraryX11
int exposure;
} saver;
// Fullscreen data
struct {
GLboolean modeChanged;
#if defined(_GLFW_HAS_XRANDR)
SizeID oldSizeID;
int oldWidth;
int oldHeight;
Rotation oldRotation;
#endif /*_GLFW_HAS_XRANDR*/
#if defined(_GLFW_HAS_XF86VIDMODE)
XF86VidModeModeInfo oldMode;
#endif /*_GLFW_HAS_XF86VIDMODE*/
} fs;
// Timer data
struct {
GLboolean monotonic;
@ -223,10 +209,14 @@ typedef struct _GLFWlibraryX11
//------------------------------------------------------------------------
typedef struct _GLFWmonitorX11
{
GLboolean modeChanged;
#if defined(_GLFW_HAS_XRANDR)
XRROutputInfo* output;
#else
int dummy;
SizeID oldSizeID;
int oldWidth;
int oldHeight;
Rotation oldRotation;
#endif /*_GLFW_HAS_XRANDR*/
} _GLFWmonitorX11;
@ -252,10 +242,10 @@ int _glfwCreateContext(_GLFWwindow* window,
void _glfwDestroyContext(_GLFWwindow* window);
// Fullscreen support
int _glfwGetClosestVideoMode(int* width, int* height);
void _glfwSetVideoModeMODE(int mode);
void _glfwSetVideoMode(int* width, int* height);
void _glfwRestoreVideoMode(void);
int _glfwGetClosestVideoMode(_GLFWmonitor* monitor, int* width, int* height);
void _glfwSetVideoModeMODE(_GLFWmonitor* monitor, int mode);
void _glfwSetVideoMode(_GLFWmonitor* monitor, int* width, int* height);
void _glfwRestoreVideoMode(_GLFWmonitor* monitor);
// Joystick input
int _glfwInitJoysticks(void);

View File

@ -337,7 +337,7 @@ static void enterFullscreenMode(_GLFWwindow* window)
_glfw.x11.saver.changed = GL_TRUE;
}
_glfwSetVideoMode(&window->width, &window->height);
_glfwSetVideoMode(window->monitor, &window->width, &window->height);
if (_glfw.x11.hasEWMH &&
_glfw.x11.wmState != None &&
@ -416,7 +416,7 @@ static void enterFullscreenMode(_GLFWwindow* window)
static void leaveFullscreenMode(_GLFWwindow* window)
{
_glfwRestoreVideoMode();
_glfwRestoreVideoMode(window->monitor);
if (_glfw.x11.saver.changed)
{
@ -977,7 +977,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
if (window->monitor)
{
// Get the closest matching video mode for the specified window size
mode = _glfwGetClosestVideoMode(&width, &height);
mode = _glfwGetClosestVideoMode(window->monitor, &width, &height);
}
if (!window->resizable)
@ -1003,7 +1003,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
sizeChanged = GL_TRUE;
}
_glfwSetVideoModeMODE(mode);
_glfwSetVideoModeMODE(window->monitor, mode);
}
// Set window size (if not already changed)

View File

@ -76,9 +76,6 @@ static GLboolean open_window(int width, int height, GLFWmonitor monitor)
{
double base;
if (!glfwInit())
return GL_FALSE;
base = glfwGetTime();
window_handle = glfwCreateWindow(width, height, "Window Re-opener", monitor, NULL);
@ -115,6 +112,9 @@ int main(int argc, char** argv)
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
for (;;)
{
GLFWmonitor monitor = NULL;
@ -161,5 +161,7 @@ int main(int argc, char** argv)
count++;
}
glfwTerminate();
}