diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h
index fd792e80..19759cb9 100644
--- a/include/GL/glfw3.h
+++ b/include/GL/glfw3.h
@@ -520,7 +520,7 @@ GLFWAPI const char* glfwErrorString(int error);
GLFWAPI void glfwSetErrorCallback(GLFWerrorfun cbfun);
/* Video mode functions */
-GLFWAPI int glfwGetVideoModes(GLFWvidmode* list, int maxcount);
+GLFWAPI GLFWvidmode* glfwGetVideoModes(int* count);
GLFWAPI void glfwGetDesktopMode(GLFWvidmode* mode);
/* Gamma ramp functions */
diff --git a/readme.html b/readme.html
index e5fa8c9d..ad62d559 100644
--- a/readme.html
+++ b/readme.html
@@ -294,6 +294,7 @@ version of GLFW.
Changed buffer bit depth parameters of glfwOpenWindow
to window hints
Changed glfwOpenWindow
and glfwSetWindowTitle
to use UTF-8 encoded strings
Changed glfwGetProcAddress
to return a (generic) function pointer
+ Changed glfwGetVideoModes
to return a dynamic, unlimited number of video modes
Renamed glfw.h
to glfw3.h
to avoid conflicts with 2.x series
Renamed GLFW_WINDOW
token to GLFW_WINDOWED
Renamed GLFW_WINDOW_NO_RESIZE
to GLFW_WINDOW_RESIZABLE
diff --git a/src/cocoa_fullscreen.m b/src/cocoa_fullscreen.m
index 147913fb..e02cb2f2 100644
--- a/src/cocoa_fullscreen.m
+++ b/src/cocoa_fullscreen.m
@@ -197,25 +197,31 @@ void _glfwRestoreVideoMode(void)
// Get a list of available video modes
//========================================================================
-int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount)
+GLFWvidmode* _glfwPlatformGetVideoModes(int* found)
{
- CGDisplayModeRef mode;
CFArrayRef modes;
CFIndex count, i;
- int stored = 0;
+ GLFWvidmode* result;
modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL);
count = CFArrayGetCount(modes);
- for (i = 0; i < count && stored < maxcount; i++)
+ result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * count);
+
+ for (i = 0; i < count; i++)
{
+ CGDisplayModeRef mode;
+
mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
if (modeIsGood(mode))
- list[stored++] = vidmodeFromCGDisplayMode(mode);
+ {
+ result[*found] vidmodeFromCGDisplayMode(mode);
+ (*found)++;
+ }
}
CFRelease(modes);
- return stored;
+ return result;
}
diff --git a/src/fullscreen.c b/src/fullscreen.c
index 631f6193..d613ab7e 100644
--- a/src/fullscreen.c
+++ b/src/fullscreen.c
@@ -68,6 +68,16 @@ static int compareVideoModes(const void* firstPtr, const void* secondPtr)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
+//========================================================================
+// Lexical comparison of GLFW video modes
+//========================================================================
+
+int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second)
+{
+ return compareVideoModes(first, second);
+}
+
+
//========================================================================
// Convert BPP to RGB bits based on "best guess"
//========================================================================
@@ -100,36 +110,27 @@ 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 GLFWvidmode* glfwGetVideoModes(int* count)
{
- int count;
-
if (!_glfwInitialized)
{
_glfwSetError(GLFW_NOT_INITIALIZED, NULL);
- return 0;
+ return NULL;
}
- if (maxcount <= 0)
+ if (count == NULL)
{
- _glfwSetError(GLFW_INVALID_VALUE,
- "glfwGetVideoModes: Parameter 'maxcount' must be "
- "greater than zero");
- return 0;
+ _glfwSetError(GLFW_INVALID_VALUE, NULL);
+ return NULL;
}
- if (list == NULL)
- {
- _glfwSetError(GLFW_INVALID_VALUE,
- "glfwGetVideoModes: Parameter 'list' cannot be NULL");
- return 0;
- }
+ free(_glfwLibrary.modes);
- count = _glfwPlatformGetVideoModes(list, maxcount);
- if (count > 0)
- qsort(list, count, sizeof(GLFWvidmode), compareVideoModes);
+ _glfwLibrary.modes = _glfwPlatformGetVideoModes(count);
+ if (_glfwLibrary.modes)
+ qsort(_glfwLibrary.modes, *count, sizeof(GLFWvidmode), compareVideoModes);
- return count;
+ return _glfwLibrary.modes;
}
diff --git a/src/init.c b/src/init.c
index 336cfe25..eab5869f 100644
--- a/src/init.c
+++ b/src/init.c
@@ -84,6 +84,9 @@ GLFWAPI void glfwTerminate(void)
if (!_glfwPlatformTerminate())
return;
+ if (_glfwLibrary.modes)
+ free(_glfwLibrary.modes);
+
_glfwInitialized = GL_FALSE;
}
diff --git a/src/internal.h b/src/internal.h
index 4e18c93c..99d74b86 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -251,6 +251,8 @@ struct _GLFWlibrary
int originalRampSize;
GLboolean rampChanged;
+ GLFWvidmode* modes;
+
// This is defined in the current port's platform.h
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
_GLFW_PLATFORM_LIBRARY_OPENGL_STATE;
@@ -287,7 +289,7 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y);
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
// Fullscreen
-int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount);
+GLFWvidmode* _glfwPlatformGetVideoModes(int* count);
void _glfwPlatformGetDesktopMode(GLFWvidmode* mode);
// Gamma ramp
@@ -335,6 +337,7 @@ void _glfwPlatformCopyContext(_GLFWwindow* src, _GLFWwindow* dst, unsigned long
//========================================================================
// Fullscren management (fullscreen.c)
+int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second);
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
// Error handling (error.c)
diff --git a/src/win32_fullscreen.c b/src/win32_fullscreen.c
index de3d898b..c04e5ff1 100644
--- a/src/win32_fullscreen.c
+++ b/src/win32_fullscreen.c
@@ -182,71 +182,78 @@ void _glfwRestoreVideoMode(void)
// Get a list of available video modes
//========================================================================
-int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount)
+GLFWvidmode* _glfwPlatformGetVideoModes(int* found)
{
- int count, success, mode, i, j;
- int m1, m2, bpp, r, g, b;
- DEVMODE dm;
+ int dmIndex = 0, count = 0;
+ GLFWvidmode* result = NULL;
- // Loop through all video modes and extract all the UNIQUE modes
- count = 0;
- mode = 0;
+ *found = 0;
- do
+ for (;;)
{
- // Get video mode properties
+ int i;
+ GLFWvidmode mode;
+ DEVMODE dm;
+
+ ZeroMemory(&dm, sizeof(DEVMODE));
dm.dmSize = sizeof(DEVMODE);
- success = EnumDisplaySettings(NULL, mode, &dm);
- // Is it a valid mode? (only list depths >= 15 bpp)
- if (success && dm.dmBitsPerPel >= 15)
+ if (!EnumDisplaySettings(NULL, dmIndex, &dm))
+ break;
+
+ dmIndex++;
+
+ if (dm.dmBitsPerPel < 15)
{
- // Convert to RGB, and back to bpp ("mask out" alpha bits etc)
- _glfwSplitBPP(dm.dmBitsPerPel, &r, &g, &b);
- bpp = r + g + b;
-
- // Mode "code" for this mode
- m1 = (bpp << 25) | (dm.dmPelsWidth * dm.dmPelsHeight);
-
- // Insert mode in list (sorted), and avoid duplicates
- for (i = 0; i < count; i++)
- {
- // Mode "code" for already listed mode
- bpp = list[i].redBits + list[i].greenBits + list[i].blueBits;
- m2 = (bpp << 25) | (list[i].width * list[i].height);
- if (m1 <= m2)
- break;
- }
-
- // New entry at the end of the list?
- if (i >= count)
- {
- list[count].width = dm.dmPelsWidth;
- list[count].height = dm.dmPelsHeight;
- list[count].redBits = r;
- list[count].greenBits = g;
- list[count].blueBits = b;
- count ++;
- }
- // Insert new entry in the list?
- else if (m1 < m2)
- {
- for (j = count; j > i; j--)
- list[j] = list[j - 1];
-
- list[i].width = dm.dmPelsWidth;
- list[i].height = dm.dmPelsHeight;
- list[i].redBits = r;
- list[i].greenBits = g;
- list[i].blueBits = b;
- count++;
- }
+ // Skip modes with less than 15 BPP
+ continue;
}
- mode++;
- }
- while (success && (count < maxcount));
- return count;
+ 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;
}
diff --git a/src/x11_fullscreen.c b/src/x11_fullscreen.c
index 7ad11ec5..34beae6a 100644
--- a/src/x11_fullscreen.c
+++ b/src/x11_fullscreen.c
@@ -32,6 +32,7 @@
#include
#include
+#include
//////////////////////////////////////////////////////////////////////////
@@ -325,92 +326,94 @@ void _glfwRestoreVideoMode(void)
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
-struct _glfwResolution
+typedef struct
{
int width;
int height;
-};
+} _GLFWvidsize;
+
//========================================================================
// List available video modes
//========================================================================
-int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount)
+GLFWvidmode* _glfwPlatformGetVideoModes(int* found)
{
- int count, k, l, r, g, b, rgba, gl;
- int depth;
- XVisualInfo* vislist;
+ XVisualInfo* visuals;
XVisualInfo dummy;
- int viscount, rgbcount, rescount;
- int* rgbarray;
- struct _glfwResolution* resarray;
+ int i, j, visualCount, sizeCount, rgbCount;
+ int* rgbs;
+ _GLFWvidsize* sizes;
+ GLFWvidmode* result;
- // Get list of visuals
- vislist = XGetVisualInfo(_glfwLibrary.X11.display, 0, &dummy, &viscount);
- if (vislist == NULL)
+ visuals = XGetVisualInfo(_glfwLibrary.X11.display, 0, &dummy, &visualCount);
+ if (visuals == NULL)
{
_glfwSetError(GLFW_PLATFORM_ERROR,
"X11/GLX: Failed to retrieve the available visuals");
return 0;
}
- rgbarray = (int*) malloc(sizeof(int) * viscount);
- rgbcount = 0;
+ // Build array of available RGB channel depths
- // Build RGB array
- for (k = 0; k < viscount; k++)
+ rgbs = (int*) malloc(sizeof(int) * visualCount);
+ rgbCount = 0;
+
+ for (i = 0; i < visualCount; i++)
{
- // Does the visual support OpenGL & true color?
- glXGetConfig(_glfwLibrary.X11.display, &vislist[k], GLX_USE_GL, &gl);
- glXGetConfig(_glfwLibrary.X11.display, &vislist[k], GLX_RGBA, &rgba);
- if (gl && rgba)
+ int gl, rgba, rgb, r, g, b;
+
+ glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_USE_GL, &gl);
+ glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_RGBA, &rgba);
+
+ if (!gl || !rgba)
{
- // Get color depth for this visual
- depth = vislist[k].depth;
-
- // Convert to RGB
- _glfwSplitBPP(depth, &r, &g, &b);
- depth = (r << 16) | (g << 8) | b;
-
- // Is this mode unique?
- for (l = 0; l < rgbcount; l++)
- {
- if (depth == rgbarray[l])
- break;
- }
-
- if (l >= rgbcount)
- {
- rgbarray[rgbcount] = depth;
- rgbcount++;
- }
+ // The visual lacks OpenGL or true color, so skip it
+ continue;
}
+
+ // Convert to RGB channel depths and encode
+ _glfwSplitBPP(visuals[i].depth, &r, &g, &b);
+ rgb = (r << 16) | (g << 8) | b;
+
+ for (j = 0; j < rgbCount; j++)
+ {
+ if (rgbs[j] == rgb)
+ break;
+ }
+
+ if (j < rgbCount)
+ {
+ // This channel depth is a duplicate, so skip it
+ continue;
+ }
+
+ rgbs[rgbCount] = rgb;
+ rgbCount++;
}
- XFree(vislist);
+ XFree(visuals);
- rescount = 0;
- resarray = NULL;
+ sizeCount = 0;
+ sizes = NULL;
- // Build resolution array
+ // Build array of available resolutions
if (_glfwLibrary.X11.RandR.available)
{
#if defined(_GLFW_HAS_XRANDR)
XRRScreenConfiguration* sc;
- XRRScreenSize* sizelist;
- int sizecount;
+ XRRScreenSize* rrSizes;
sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root);
- sizelist = XRRConfigSizes(sc, &sizecount);
+ rrSizes = XRRConfigSizes(sc, &sizeCount);
- resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * sizecount);
+ sizes = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * sizeCount);
- for (k = 0; k < sizecount; k++)
+ for (i = 0; i < sizeCount; i++)
{
- resarray[rescount].width = sizelist[k].width;
- resarray[rescount].height = sizelist[k].height;
- rescount++;
+ sizes[i].width = rrSizes[i].width;
+ sizes[i].height = rrSizes[i].height;
}
XRRFreeScreenConfigInfo(sc);
@@ -419,69 +422,75 @@ int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount)
else if (_glfwLibrary.X11.VidMode.available)
{
#if defined(_GLFW_HAS_XF86VIDMODE)
- XF86VidModeModeInfo** modelist;
- int modecount, width, height;
+ XF86VidModeModeInfo** modes;
+ int modeCount;
XF86VidModeGetAllModeLines(_glfwLibrary.X11.display,
_glfwLibrary.X11.screen,
- &modecount, &modelist);
+ &modeCount, &modes);
- resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * modecount);
+ sizes = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * modeCount);
- for (k = 0; k < modecount; k++)
+ for (i = 0; i < modeCount; i++)
{
- width = modelist[k]->hdisplay;
- height = modelist[k]->vdisplay;
+ _GLFWvidsize size;
+ size.width = modes[i]->hdisplay;
+ size.height = modes[i]->vdisplay;
- // Is this mode unique?
- for (l = 0; l < rescount; l++)
+ for (j = 0; j < sizeCount; j++)
{
- if (width == resarray[l].width && height == resarray[l].height)
+ if (memcmp(sizes + j, &size, sizeof(_GLFWvidsize)) == 0)
break;
}
- if (l >= rescount)
+ if (j < sizeCount)
{
- resarray[rescount].width = width;
- resarray[rescount].height = height;
- rescount++;
+ // This size is a duplicate, so skip it
+ continue;
}
+
+ sizes[sizeCount] = size;
+ sizeCount++;
}
- XFree(modelist);
+ XFree(modes);
#endif /*_GLFW_HAS_XF86VIDMODE*/
}
- if (!resarray)
+ if (!sizeCount)
{
- rescount = 1;
- resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * rescount);
+ sizeCount = 1;
+ sizes = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize));
- resarray[0].width = DisplayWidth(_glfwLibrary.X11.display,
- _glfwLibrary.X11.screen);
- resarray[0].height = DisplayHeight(_glfwLibrary.X11.display,
- _glfwLibrary.X11.screen);
+ sizes[0].width = DisplayWidth(_glfwLibrary.X11.display,
+ _glfwLibrary.X11.screen);
+ sizes[0].height = DisplayHeight(_glfwLibrary.X11.display,
+ _glfwLibrary.X11.screen);
}
- // Build permutations of colors and resolutions
- count = 0;
- for (k = 0; k < rgbcount && count < maxcount; k++)
+ // Build all permutations of channel depths and resolutions
+
+ result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * rgbCount * sizeCount);
+ *found = 0;
+
+ for (i = 0; i < rgbCount; i++)
{
- for (l = 0; l < rescount && count < maxcount; l++)
+ for (j = 0; j < sizeCount; j++)
{
- list[count].width = resarray[l].width;
- list[count].height = resarray[l].height;
- list[count].redBits = (rgbarray[k] >> 16) & 255;
- list[count].greenBits = (rgbarray[k] >> 8) & 255;
- list[count].blueBits = rgbarray[k] & 255;
- count++;
+ result[*found].width = sizes[j].width;
+ result[*found].height = sizes[j].height;
+ result[*found].redBits = (rgbs[i] >> 16) & 255;
+ result[*found].greenBits = (rgbs[i] >> 8) & 255;
+ result[*found].blueBits = rgbs[i] & 255;
+
+ (*found)++;
}
}
- free(resarray);
- free(rgbarray);
+ free(sizes);
+ free(rgbs);
- return count;
+ return result;
}
diff --git a/tests/modes.c b/tests/modes.c
index 3a384003..0f2452c7 100644
--- a/tests/modes.c
+++ b/tests/modes.c
@@ -90,29 +90,11 @@ static void key_callback(GLFWwindow dummy, int key, int action)
}
}
-static GLFWvidmode* get_video_modes(size_t* found)
-{
- size_t count = 0;
- GLFWvidmode* modes = NULL;
-
- for (;;)
- {
- count += 256;
- modes = realloc(modes, sizeof(GLFWvidmode) * count);
-
- *found = glfwGetVideoModes(modes, count);
- if (*found < count)
- break;
- }
-
- return modes;
-}
-
static void list_modes(void)
{
size_t count, i;
GLFWvidmode desktop_mode;
- GLFWvidmode* modes = get_video_modes(&count);
+ GLFWvidmode* modes = glfwGetVideoModes(&count);
glfwGetDesktopMode(&desktop_mode);
printf("Desktop mode: %s\n", format_mode(&desktop_mode));
@@ -128,15 +110,13 @@ static void list_modes(void)
putchar('\n');
}
-
- free(modes);
}
static void test_modes(void)
{
int width, height;
size_t i, count;
- GLFWvidmode* modes = get_video_modes(&count);
+ GLFWvidmode* modes = glfwGetVideoModes(&count);
glfwSetWindowSizeCallback(window_size_callback);
glfwSetWindowCloseCallback(window_close_callback);
@@ -207,8 +187,6 @@ static void test_modes(void)
glfwPollEvents();
window = NULL;
}
-
- free(modes);
}
int main(int argc, char** argv)