From beacbb3447e53395f29275b1589a6cf58b10da03 Mon Sep 17 00:00:00 2001 From: Marcel Metz Date: Sat, 7 May 2011 10:53:50 +0200 Subject: [PATCH] Implemented display iteration for x11. Added attributes and queries for physical size, name and logical position. Updated test executable. --- include/GL/glfw3.h | 30 ++++++++++- src/CMakeLists.txt | 6 +-- src/display.c | 111 +++++++++++++++++++++++++++++++++++++++++ src/fullscreen.c | 2 +- src/internal.h | 21 ++++++++ src/x11_display.c | 121 +++++++++++++++++++++++++++++++++++++++++++++ src/x11_init.c | 4 ++ src/x11_platform.h | 4 ++ tests/listmodes.c | 30 ++++++++--- 9 files changed, 316 insertions(+), 13 deletions(-) create mode 100644 src/display.c create mode 100644 src/x11_display.c diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 1f52e742..887540ac 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -539,8 +539,36 @@ GLFWAPI int glfwGetError(void); GLFWAPI const char* glfwErrorString(int error); GLFWAPI void glfwSetErrorCallback(GLFWerrorfun cbfun); +/* Display constants */ +#define GLFW_DISPLAY_INVALID_HANDLE (NULL) +#define GLFW_DISPLAY_CONNECTED 0 +#define GLFW_DISPLAY_DISCONNECTED 1 +#define GLFW_DISPLAY_PARAM_S_NAME 0 +#define GLFW_DISPLAY_PARAM_I_PHYS_WIDTH 1 +#define GLFW_DISPLAY_PARAM_I_PHYS_HEIGHT 2 +#define GLFW_DISPLAY_PARAM_I_SCREEN_X_POS 3 +#define GLFW_DISPLAY_PARAM_I_SCREEN_Y_POS 4 +#define GLFW_DISPLAY_PARAM_S_NAME_LEN 30 + +/* Display types */ +typedef struct _GLFWdisplay* GLFWdisplay; +typedef void (* GLFWdisplaydevicefun)(GLFWdisplay,int); /* connect / disconnect */ + +/* Display callback registration */ +GLFWAPI void glfwSetDisplayDeviceCallback(GLFWdisplaydevicefun cbfun); + +/* Display attributes */ +GLFWAPI void glfwSetDisplayUserPointer(GLFWdisplay display, void* pointer); +GLFWAPI void* glfwGetDisplayUserPointer(GLFWdisplay display); +GLFWAPI int glfwGetDisplayIntegerParam(GLFWdisplay display, int param); +GLFWAPI const char* glfwGetDisplayStringParam(GLFWdisplay display, int param); + +/* Display discovery */ +GLFWAPI GLFWdisplay glfwGetNextDisplay(GLFWdisplay iterator); + + /* Video mode functions */ -GLFWAPI int glfwGetVideoModes(GLFWvidmode* list, int maxcount); +GLFWAPI int glfwGetVideoModes(GLFWdisplay display, GLFWvidmode* list, int maxcount); GLFWAPI void glfwGetDesktopMode(GLFWvidmode* mode); /* Gamma ramp functions */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd50b41d..4d13379c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,7 +27,7 @@ include_directories(${GLFW_SOURCE_DIR}/src ${GLFW_BINARY_DIR}/src ${GLFW_INCLUDE_DIR}) -set(common_SOURCES enable.c error.c fullscreen.c gamma.c init.c input.c +set(common_SOURCES display.c enable.c error.c fullscreen.c gamma.c init.c input.c joystick.c opengl.c time.c window.c) if(_GLFW_COCOA_NSGL) @@ -43,8 +43,8 @@ elseif(_GLFW_WIN32_WGL) win32_opengl.c win32_time.c win32_window.c win32_dllmain.c) elseif(_GLFW_X11_GLX) - set(libglfw_SOURCES ${common_SOURCES} x11_enable.c x11_fullscreen.c - x11_gamma.c x11_init.c x11_joystick.c + set(libglfw_SOURCES ${common_SOURCES} x11_display.c x11_enable.c + x11_fullscreen.c x11_gamma.c x11_init.c x11_joystick.c x11_keysym2unicode.c x11_opengl.c x11_time.c x11_window.c) else() diff --git a/src/display.c b/src/display.c new file mode 100644 index 00000000..beb6f5d4 --- /dev/null +++ b/src/display.c @@ -0,0 +1,111 @@ +//======================================================================== +// GLFW - An OpenGL framework +// Platform: Any +// 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" + + +//======================================================================== +// Get a list of connected displays +//======================================================================== + +GLFWAPI GLFWdisplay glfwGetNextDisplay(GLFWdisplay iterator) +{ + GLFWdisplay result = GLFW_DISPLAY_INVALID_HANDLE; + if (!_glfwInitialized) + { + _glfwSetError(GLFW_NOT_INITIALIZED, NULL); + return result; + } + + if (iterator == GLFW_DISPLAY_INVALID_HANDLE) + { + result = _glfwLibrary.displayListHead; + } + else + { + result = iterator->next; + } + return result; +} + +GLFWAPI int glfwGetDisplayIntegerParam(GLFWdisplay display, int param) +{ + if (!_glfwInitialized) + { + _glfwSetError(GLFW_NOT_INITIALIZED, NULL); + return 0; + } + + if (display == GLFW_DISPLAY_INVALID_HANDLE) + { + _glfwSetError(GLFW_INVALID_VALUE, "Display handle is invalid."); + return 0; + } + + switch(param) + { + case GLFW_DISPLAY_PARAM_I_PHYS_WIDTH: + return display->physicalWidth; + case GLFW_DISPLAY_PARAM_I_PHYS_HEIGHT: + return display->physicalHeight; + case GLFW_DISPLAY_PARAM_I_SCREEN_X_POS: + return display->screenXPosition; + case GLFW_DISPLAY_PARAM_I_SCREEN_Y_POS: + return display->screenYPosition; + default: + _glfwSetError(GLFW_INVALID_ENUM, "Param represents not a valid integer display attribute."); + return 0; + } +} + +GLFWAPI const char* glfwGetDisplayStringParam(GLFWdisplay display, int param) +{ + if (!_glfwInitialized) + { + _glfwSetError(GLFW_NOT_INITIALIZED, NULL); + return NULL; + } + + if (display == GLFW_DISPLAY_INVALID_HANDLE) + { + _glfwSetError(GLFW_INVALID_VALUE, "display handle is invalid."); + return NULL; + } + + switch(param) + { + case GLFW_DISPLAY_PARAM_S_NAME: + return display->deviceName; + default: + _glfwSetError(GLFW_INVALID_ENUM, "Param represents not a valid string display attribute."); + return NULL; + } +} + diff --git a/src/fullscreen.c b/src/fullscreen.c index 7cc96bb7..f6cda247 100644 --- a/src/fullscreen.c +++ b/src/fullscreen.c @@ -100,7 +100,7 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue) // Get a list of available video modes //======================================================================== -GLFWAPI int glfwGetVideoModes(GLFWvidmode* list, int maxcount) +GLFWAPI int glfwGetVideoModes(GLFWdisplay display, GLFWvidmode* list, int maxcount) { int count; diff --git a/src/internal.h b/src/internal.h index c8bdb9aa..e757aaee 100644 --- a/src/internal.h +++ b/src/internal.h @@ -76,6 +76,7 @@ typedef struct _GLFWwndconfig _GLFWwndconfig; typedef struct _GLFWfbconfig _GLFWfbconfig; typedef struct _GLFWwindow _GLFWwindow; typedef struct _GLFWlibrary _GLFWlibrary; +typedef struct _GLFWdisplay _GLFWdisplay; //------------------------------------------------------------------------ @@ -215,6 +216,24 @@ struct _GLFWwindow }; +//------------------------------------------------------------------------ +// Display structure +//------------------------------------------------------------------------ +struct _GLFWdisplay +{ + struct _GLFWdisplay* next; + + void* userPointer; + + char deviceName[GLFW_DISPLAY_PARAM_S_NAME_LEN+1]; + // physical dimensions in millimeters. + int physicalWidth; + int physicalHeight; + // logical orientation of the screen on the desktop + int screenXPosition; + int screenYPosition; +}; + //------------------------------------------------------------------------ // Library global data //------------------------------------------------------------------------ @@ -225,6 +244,8 @@ struct _GLFWlibrary _GLFWwindow* windowListHead; _GLFWwindow* currentWindow; _GLFWwindow* activeWindow; + _GLFWwindow* cursorLockWindow; + _GLFWdisplay* displayListHead; GLFWwindowsizefun windowSizeCallback; GLFWwindowclosefun windowCloseCallback; diff --git a/src/x11_display.c b/src/x11_display.c new file mode 100644 index 00000000..bd4a90a4 --- /dev/null +++ b/src/x11_display.c @@ -0,0 +1,121 @@ +//======================================================================== +// GLFW - An OpenGL library +// Platform: X11 (Unix) +// 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 + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +_GLFWdisplay** _glfwCreateDisplay(_GLFWdisplay** current, XRROutputInfo* outputInfo, XRRCrtcInfo* crtcInfo) +{ + *current = _glfwMalloc(sizeof(_GLFWdisplay)); + memset(*current, 0, sizeof(_GLFWdisplay)); + + (*current)->physicalWidth = outputInfo->mm_width; + (*current)->physicalHeight = outputInfo->mm_height; + + memcpy((*current)->deviceName, outputInfo->name, GLFW_DISPLAY_PARAM_S_NAME_LEN+1); + (*current)->deviceName[GLFW_DISPLAY_PARAM_S_NAME_LEN] = '\0'; + + (*current)->screenXPosition = crtcInfo->x; + (*current)->screenYPosition = crtcInfo->y; + return &((*current)->next); +} + +_GLFWdisplay* _glfwDestroyDisplay(_GLFWdisplay* display) +{ + _GLFWdisplay* result; + + result = display->next; + + _glfwFree(display); + + return result; +} + +void _glfwInitDisplays(void) +{ + if(_glfwLibrary.X11.RandR.available == GL_TRUE) + { + XRRScreenResources* resources; + int outputIDX; + _GLFWdisplay** curDisplay; + + curDisplay = &_glfwLibrary.displayListHead; + + resources = XRRGetScreenResources(_glfwLibrary.X11.display, + _glfwLibrary.X11.root); + + for(outputIDX = 0; outputIDX < resources->noutput; outputIDX++) + { + // physical device + XRROutputInfo* outputInfo = NULL; + // logical surface + XRRCrtcInfo* crtcInfo = NULL; + int crtcIDX; + + outputInfo = XRRGetOutputInfo(_glfwLibrary.X11.display, + resources, + resources->outputs[outputIDX]); + + if(outputInfo->connection == RR_Connected) + { + for(crtcIDX = 0; crtcIDX < outputInfo->ncrtc; crtcIDX++) + { + if(outputInfo->crtc == outputInfo->crtcs[crtcIDX]) + { + crtcInfo = XRRGetCrtcInfo(_glfwLibrary.X11.display, + resources, + outputInfo->crtcs[crtcIDX]); + break; + } + } + + curDisplay = _glfwCreateDisplay(curDisplay, outputInfo, crtcInfo); + + XRRFreeCrtcInfo(crtcInfo); + } + + XRRFreeOutputInfo(outputInfo); + } + } +} + +void _glfwTerminateDisplays(void) +{ + while(_glfwLibrary.displayListHead) + _glfwLibrary.displayListHead = _glfwDestroyDisplay(_glfwLibrary.displayListHead); +} + diff --git a/src/x11_init.c b/src/x11_init.c index 2b8e3e35..a9124435 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -577,6 +577,8 @@ int _glfwPlatformInit(void) _glfwInitJoysticks(); + _glfwInitDisplays(); + // Start the timer _glfwInitTimer(); @@ -598,6 +600,8 @@ int _glfwPlatformTerminate(void) terminateDisplay(); + _glfwTerminateDisplays(); + _glfwTerminateJoysticks(); // Unload libGL.so if necessary diff --git a/src/x11_platform.h b/src/x11_platform.h index 70a57b84..ed730566 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -261,6 +261,10 @@ void _glfwRestoreVideoMode(int screen); void _glfwInitJoysticks(void); void _glfwTerminateJoysticks(void); +// Displays +void _glfwInitDisplays(void); +void _glfwTerminateDisplays(void); + // Unicode support long _glfwKeySym2Unicode(KeySym keysym); diff --git a/tests/listmodes.c b/tests/listmodes.c index a4648ef6..39edad86 100644 --- a/tests/listmodes.c +++ b/tests/listmodes.c @@ -18,6 +18,7 @@ static void print_mode(GLFWvidmode* mode) int main(void) { + GLFWdisplay displayHandle; GLFWvidmode dtmode, modes[400]; int modecount, i; @@ -32,15 +33,28 @@ int main(void) printf("Desktop mode: "); print_mode(&dtmode); - // List available video modes - modecount = glfwGetVideoModes(modes, sizeof(modes) / sizeof(GLFWvidmode)); - printf("Available modes:\n"); - for (i = 0; i < modecount; i++) - { - printf("%3i: ", i); - print_mode(modes + i); - } + displayHandle = GLFW_DISPLAY_INVALID_HANDLE; + while( GLFW_DISPLAY_INVALID_HANDLE != ( displayHandle = glfwGetNextDisplay( displayHandle ))) + { + printf( "Display name: %s\n" + "Physical dimensions: %dmm x %dmm\n" + "Logical position: (%d,%d)\n", + glfwGetDisplayStringParam( displayHandle, GLFW_DISPLAY_PARAM_S_NAME ), + glfwGetDisplayIntegerParam( displayHandle, GLFW_DISPLAY_PARAM_I_PHYS_WIDTH ), + glfwGetDisplayIntegerParam( displayHandle, GLFW_DISPLAY_PARAM_I_PHYS_HEIGHT ), + glfwGetDisplayIntegerParam( displayHandle, GLFW_DISPLAY_PARAM_I_SCREEN_X_POS ), + glfwGetDisplayIntegerParam( displayHandle, GLFW_DISPLAY_PARAM_I_SCREEN_Y_POS ) + ); + // List available video modes + modecount = glfwGetVideoModes(displayHandle, modes, sizeof(modes) / sizeof(GLFWvidmode)); + printf( "Available modes:\n" ); + for( i = 0; i < modecount; i ++ ) + { + printf("%3i: ", i); + print_mode(modes + i); + } + } glfwTerminate(); exit(EXIT_SUCCESS); }