mirror of https://github.com/glfw/glfw.git
RandR monitor work.
Moved to CRTC plus usable output for native representation of monitors. Moved to CRTCs for mode setting and simplified mode setting interface.
This commit is contained in:
parent
065858e185
commit
954d6383ee
|
@ -514,6 +514,12 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
|
|||
if (width == window->width && height == window->height)
|
||||
return;
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
window->videoMode.width = width;
|
||||
window->videoMode.height = height;
|
||||
}
|
||||
|
||||
_glfwPlatformSetWindowSize(window, width, height);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,140 +40,105 @@
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//========================================================================
|
||||
// Finds the video mode closest in size to the specified desired size
|
||||
// Set the current video mode for the specified monitor
|
||||
//========================================================================
|
||||
|
||||
int _glfwGetClosestVideoMode(_GLFWmonitor* monitor, int* width, int* height)
|
||||
void _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* mode)
|
||||
{
|
||||
int i, match, bestmatch;
|
||||
|
||||
if (_glfw.x11.randr.available)
|
||||
{
|
||||
int sizecount, bestsize;
|
||||
XRRScreenConfiguration* sc;
|
||||
XRRScreenSize* sizelist;
|
||||
int i, j, k;
|
||||
XRRScreenResources* sr;
|
||||
XRRCrtcInfo* ci;
|
||||
RRMode bestMode = 0;
|
||||
unsigned int leastSizeDiff = UINT_MAX;
|
||||
|
||||
sc = XRRGetScreenInfo(_glfw.x11.display, _glfw.x11.root);
|
||||
sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root);
|
||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||
|
||||
sizelist = XRRConfigSizes(sc, &sizecount);
|
||||
|
||||
// Find the best matching mode
|
||||
bestsize = -1;
|
||||
bestmatch = INT_MAX;
|
||||
for (i = 0; i < sizecount; i++)
|
||||
for (i = 0; i < sr->nmode; i++)
|
||||
{
|
||||
match = (*width - sizelist[i].width) *
|
||||
(*width - sizelist[i].width) +
|
||||
(*height - sizelist[i].height) *
|
||||
(*height - sizelist[i].height);
|
||||
if (match < bestmatch)
|
||||
GLboolean usable = GL_TRUE;
|
||||
XRRModeInfo* mi = sr->modes + i;
|
||||
|
||||
for (j = 0; j < ci->noutput; j++)
|
||||
{
|
||||
bestmatch = match;
|
||||
bestsize = i;
|
||||
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display,
|
||||
sr, ci->outputs[j]);
|
||||
|
||||
for (k = 0; k < oi->nmode; k++)
|
||||
{
|
||||
if (oi->modes[k] == mi->id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (k == oi->nmode)
|
||||
usable = GL_FALSE;
|
||||
|
||||
XRRFreeOutputInfo(oi);
|
||||
}
|
||||
|
||||
if (!usable)
|
||||
continue;
|
||||
|
||||
if (mi->modeFlags & RR_Interlace)
|
||||
continue;
|
||||
|
||||
unsigned int sizeDiff = (mi->width - mode->width) *
|
||||
(mi->width - mode->width) +
|
||||
(mi->height - mode->height) *
|
||||
(mi->height - mode->height);
|
||||
|
||||
if (sizeDiff < leastSizeDiff)
|
||||
{
|
||||
bestMode = mi->id;
|
||||
leastSizeDiff = sizeDiff;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestsize != -1)
|
||||
{
|
||||
// Report width & height of best matching mode
|
||||
*width = sizelist[bestsize].width;
|
||||
*height = sizelist[bestsize].height;
|
||||
}
|
||||
monitor->x11.oldMode = ci->mode;
|
||||
|
||||
XRRFreeScreenConfigInfo(sc);
|
||||
XRRSetCrtcConfig(_glfw.x11.display,
|
||||
sr, monitor->x11.crtc,
|
||||
CurrentTime,
|
||||
ci->x, ci->y,
|
||||
bestMode,
|
||||
ci->rotation,
|
||||
ci->outputs,
|
||||
ci->noutput);
|
||||
|
||||
if (bestsize != -1)
|
||||
return bestsize;
|
||||
}
|
||||
|
||||
// Default: Simply use the screen resolution
|
||||
*width = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
|
||||
*height = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Change the current video mode
|
||||
//========================================================================
|
||||
|
||||
void _glfwSetVideoModeMODE(_GLFWmonitor* monitor, int mode)
|
||||
{
|
||||
if (_glfw.x11.randr.available)
|
||||
{
|
||||
XRRScreenConfiguration* sc;
|
||||
Window root;
|
||||
|
||||
root = _glfw.x11.root;
|
||||
sc = XRRGetScreenInfo(_glfw.x11.display, root);
|
||||
|
||||
// Remember old size and flag that we have changed the mode
|
||||
if (!monitor->x11.modeChanged)
|
||||
{
|
||||
monitor->x11.oldSizeID = XRRConfigCurrentConfiguration(sc, &monitor->x11.oldRotation);
|
||||
monitor->x11.oldWidth = DisplayWidth(_glfw.x11.display,
|
||||
_glfw.x11.screen);
|
||||
monitor->x11.oldHeight = DisplayHeight(_glfw.x11.display,
|
||||
_glfw.x11.screen);
|
||||
|
||||
monitor->x11.modeChanged = GL_TRUE;
|
||||
}
|
||||
|
||||
XRRSetScreenConfig(_glfw.x11.display,
|
||||
sc,
|
||||
root,
|
||||
mode,
|
||||
RR_Rotate_0,
|
||||
CurrentTime);
|
||||
|
||||
XRRFreeScreenConfigInfo(sc);
|
||||
XRRFreeCrtcInfo(ci);
|
||||
XRRFreeScreenResources(sr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Change the current video mode
|
||||
//========================================================================
|
||||
|
||||
void _glfwSetVideoMode(_GLFWmonitor* monitor, int* width, int* height)
|
||||
{
|
||||
int bestmode;
|
||||
|
||||
// Find a best match mode
|
||||
bestmode = _glfwGetClosestVideoMode(monitor, width, height);
|
||||
|
||||
// Change mode
|
||||
_glfwSetVideoModeMODE(monitor, bestmode);
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Restore the previously saved (original) video mode
|
||||
// Restore the saved (original) video mode for the specified monitor
|
||||
//========================================================================
|
||||
|
||||
void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
|
||||
{
|
||||
if (!monitor->x11.modeChanged)
|
||||
return;
|
||||
|
||||
if (_glfw.x11.randr.available)
|
||||
{
|
||||
XRRScreenConfiguration* sc;
|
||||
XRRScreenResources* sr;
|
||||
XRRCrtcInfo* ci;
|
||||
|
||||
sc = XRRGetScreenInfo(_glfw.x11.display, _glfw.x11.root);
|
||||
sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root);
|
||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||
|
||||
XRRSetScreenConfig(_glfw.x11.display,
|
||||
sc,
|
||||
_glfw.x11.root,
|
||||
monitor->x11.oldSizeID,
|
||||
monitor->x11.oldRotation,
|
||||
CurrentTime);
|
||||
XRRSetCrtcConfig(_glfw.x11.display,
|
||||
sr, monitor->x11.crtc,
|
||||
CurrentTime,
|
||||
ci->x, ci->y,
|
||||
monitor->x11.oldMode,
|
||||
ci->rotation,
|
||||
ci->outputs,
|
||||
ci->noutput);
|
||||
|
||||
XRRFreeScreenConfigInfo(sc);
|
||||
XRRFreeCrtcInfo(ci);
|
||||
XRRFreeScreenResources(sr);
|
||||
}
|
||||
|
||||
monitor->x11.modeChanged = GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,7 +159,6 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* found)
|
|||
XRRScreenResources* sr;
|
||||
|
||||
sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root);
|
||||
|
||||
primary = XRRGetOutputPrimary(_glfw.x11.display, _glfw.x11.root);
|
||||
|
||||
monitors = (_GLFWmonitor**) calloc(sr->noutput, sizeof(_GLFWmonitor*));
|
||||
|
@ -206,37 +170,48 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* found)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < sr->noutput; i++)
|
||||
for (i = 0; i < sr->ncrtc; i++)
|
||||
{
|
||||
int j;
|
||||
XRROutputInfo* oi;
|
||||
XRRCrtcInfo* ci;
|
||||
RROutput output;
|
||||
|
||||
oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
|
||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, sr->crtcs[i]);
|
||||
output = ci->outputs[i];
|
||||
|
||||
for (j = 0; j < ci->noutput; j++)
|
||||
{
|
||||
if (ci->outputs[i] == primary)
|
||||
{
|
||||
output = primary;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
oi = XRRGetOutputInfo(_glfw.x11.display, sr, output);
|
||||
if (oi->connection != RR_Connected)
|
||||
{
|
||||
XRRFreeOutputInfo(oi);
|
||||
XRRFreeCrtcInfo(ci);
|
||||
continue;
|
||||
}
|
||||
|
||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
|
||||
|
||||
monitors[*found] = _glfwCreateMonitor(oi->name,
|
||||
sr->outputs[i] == primary,
|
||||
output == primary,
|
||||
oi->mm_width, oi->mm_height,
|
||||
ci->x, ci->y);
|
||||
|
||||
monitors[*found]->x11.output = output;
|
||||
monitors[*found]->x11.crtc = oi->crtc;
|
||||
|
||||
XRRFreeOutputInfo(oi);
|
||||
XRRFreeCrtcInfo(ci);
|
||||
|
||||
if (!monitors[*found])
|
||||
{
|
||||
// TODO: wat
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This is retained until the monitor object is destroyed
|
||||
monitors[*found]->x11.output = oi;
|
||||
(*found)++;
|
||||
}
|
||||
|
||||
XRRFreeScreenResources(sr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -265,8 +240,6 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* found)
|
|||
|
||||
void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor)
|
||||
{
|
||||
if (_glfw.x11.randr.available)
|
||||
XRRFreeOutputInfo(monitor->x11.output);
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
|
@ -283,25 +256,27 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||
|
||||
if (_glfw.x11.randr.available)
|
||||
{
|
||||
int i, j;
|
||||
XRRScreenResources* sr;
|
||||
int i, j, count = monitor->x11.output->nmode;
|
||||
XRROutputInfo* oi;
|
||||
|
||||
sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root);
|
||||
oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
|
||||
|
||||
result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * count);
|
||||
result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * oi->nmode);
|
||||
if (!result)
|
||||
{
|
||||
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
for (i = 0; i < oi->nmode; i++)
|
||||
{
|
||||
GLFWvidmode mode;
|
||||
|
||||
for (j = 0; j < sr->nmode; j++)
|
||||
{
|
||||
if (sr->modes[j].id == monitor->x11.output->modes[i])
|
||||
if (sr->modes[j].id == oi->modes[i])
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -334,6 +309,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||
(*found)++;
|
||||
}
|
||||
|
||||
XRRFreeOutputInfo(oi);
|
||||
XRRFreeScreenResources(sr);
|
||||
}
|
||||
else
|
||||
|
@ -365,22 +341,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|||
XRRCrtcInfo* ci;
|
||||
|
||||
sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root);
|
||||
if (!sr)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to retrieve RandR screen resources");
|
||||
return;
|
||||
}
|
||||
|
||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.output->crtc);
|
||||
if (!ci)
|
||||
{
|
||||
XRRFreeScreenResources(sr);
|
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to retrieve RandR crtc info");
|
||||
return;
|
||||
}
|
||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||
|
||||
mode->width = ci->width;
|
||||
mode->height = ci->height;
|
||||
|
|
|
@ -200,13 +200,9 @@ typedef struct _GLFWlibraryX11
|
|||
//------------------------------------------------------------------------
|
||||
typedef struct _GLFWmonitorX11
|
||||
{
|
||||
GLboolean modeChanged;
|
||||
|
||||
XRROutputInfo* output;
|
||||
SizeID oldSizeID;
|
||||
int oldWidth;
|
||||
int oldHeight;
|
||||
Rotation oldRotation;
|
||||
RROutput output;
|
||||
RRCrtc crtc;
|
||||
RRMode oldMode;
|
||||
|
||||
} _GLFWmonitorX11;
|
||||
|
||||
|
@ -231,9 +227,7 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||
void _glfwDestroyContext(_GLFWwindow* window);
|
||||
|
||||
// Fullscreen support
|
||||
int _glfwGetClosestVideoMode(_GLFWmonitor* monitor, int* width, int* height);
|
||||
void _glfwSetVideoModeMODE(_GLFWmonitor* monitor, int mode);
|
||||
void _glfwSetVideoMode(_GLFWmonitor* monitor, int* width, int* height);
|
||||
void _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* mode);
|
||||
void _glfwRestoreVideoMode(_GLFWmonitor* monitor);
|
||||
|
||||
// Joystick input
|
||||
|
|
|
@ -237,6 +237,9 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||
|
||||
_glfwPlatformSetWindowTitle(window, wndconfig->title);
|
||||
|
||||
XRRSelectInput(_glfw.x11.display, window->x11.handle,
|
||||
RRScreenChangeNotifyMask);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
@ -333,7 +336,7 @@ static void enterFullscreenMode(_GLFWwindow* window)
|
|||
_glfw.x11.saver.changed = GL_TRUE;
|
||||
}
|
||||
|
||||
_glfwSetVideoMode(window->monitor, &window->width, &window->height);
|
||||
_glfwSetVideoMode(window->monitor, &window->videoMode);
|
||||
|
||||
if (_glfw.x11.hasEWMH &&
|
||||
_glfw.x11.NET_WM_STATE != None &&
|
||||
|
@ -743,7 +746,6 @@ static void processEvent(XEvent *event)
|
|||
case RRScreenChangeNotify:
|
||||
{
|
||||
XRRUpdateConfiguration(event);
|
||||
_glfwInputMonitorChange();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -893,13 +895,7 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
|||
|
||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
int mode = 0, sizeChanged = GL_FALSE;
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
// Get the closest matching video mode for the specified window size
|
||||
mode = _glfwGetClosestVideoMode(window->monitor, &width, &height);
|
||||
}
|
||||
GLboolean sizeChanged = GL_FALSE;
|
||||
|
||||
if (!window->resizable)
|
||||
{
|
||||
|
@ -924,7 +920,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
|||
sizeChanged = GL_TRUE;
|
||||
}
|
||||
|
||||
_glfwSetVideoModeMODE(window->monitor, mode);
|
||||
_glfwSetVideoMode(window->monitor, &window->videoMode);
|
||||
}
|
||||
|
||||
// Set window size (if not already changed)
|
||||
|
|
Loading…
Reference in New Issue