Просмотр исходного кода

Made video mode retrieval dynamic.

Camilla Berglund 13 лет назад
Родитель
Сommit
871e1a70d7
9 измененных файлов с 192 добавлено и 184 удалено
  1. 1 1
      include/GL/glfw3.h
  2. 1 0
      readme.html
  3. 12 6
      src/cocoa_fullscreen.m
  4. 20 19
      src/fullscreen.c
  5. 3 0
      src/init.c
  6. 4 1
      src/internal.h
  7. 57 50
      src/win32_fullscreen.c
  8. 92 83
      src/x11_fullscreen.c
  9. 2 24
      tests/modes.c

+ 1 - 1
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 */

+ 1 - 0
readme.html

@@ -294,6 +294,7 @@ version of GLFW.</p>
   <li>Changed buffer bit depth parameters of <code>glfwOpenWindow</code> to window hints</li>
   <li>Changed <code>glfwOpenWindow</code> and <code>glfwSetWindowTitle</code> to use UTF-8 encoded strings</li>
   <li>Changed <code>glfwGetProcAddress</code> to return a (generic) function pointer</li>
+  <li>Changed <code>glfwGetVideoModes</code> to return a dynamic, unlimited number of video modes</li>
   <li>Renamed <code>glfw.h</code> to <code>glfw3.h</code> to avoid conflicts with 2.x series</li>
   <li>Renamed <code>GLFW_WINDOW</code> token to <code>GLFW_WINDOWED</code></li>
   <li>Renamed <code>GLFW_WINDOW_NO_RESIZE</code> to <code>GLFW_WINDOW_RESIZABLE</code></li>

+ 12 - 6
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;
 }
 
 

+ 20 - 19
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;
 }
 
 

+ 3 - 0
src/init.c

@@ -84,6 +84,9 @@ GLFWAPI void glfwTerminate(void)
     if (!_glfwPlatformTerminate())
         return;
 
+    if (_glfwLibrary.modes)
+        free(_glfwLibrary.modes);
+
     _glfwInitialized = GL_FALSE;
 }
 

+ 4 - 1
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)

+ 57 - 50
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;
+            // Skip modes with less than 15 BPP
+            continue;
+        }
 
-            // Mode "code" for this mode
-            m1 = (bpp << 25) | (dm.dmPelsWidth * dm.dmPelsHeight);
+        mode.width = dm.dmPelsWidth;
+        mode.height = dm.dmPelsHeight;
+        _glfwSplitBPP(dm.dmBitsPerPel,
+                        &mode.redBits,
+                        &mode.greenBits,
+                        &mode.blueBits);
 
-            // 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;
-            }
+        for (i = 0;  i < *found;  i++)
+        {
+            if (_glfwCompareVideoModes(result + i, &mode) == 0)
+                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)
+        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)
             {
-                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++;
+                free(result);
+
+                _glfwSetError(GLFW_OUT_OF_MEMORY, NULL);
+                return NULL;
             }
+
+            result = (GLFWvidmode*) larger;
         }
-        mode++;
+
+        result[*found] = mode;
+        (*found)++;
     }
-    while (success && (count < maxcount));
 
-    return count;
+    return result;
 }
 
 

+ 92 - 83
src/x11_fullscreen.c

@@ -32,6 +32,7 @@
 
 #include <limits.h>
 #include <stdlib.h>
+#include <string.h>
 
 
 //////////////////////////////////////////////////////////////////////////
@@ -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
+
+    rgbs = (int*) malloc(sizeof(int) * visualCount);
+    rgbCount = 0;
 
-    // Build RGB array
-    for (k = 0;  k < viscount;  k++)
+    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;
+            // The visual lacks OpenGL or true color, so skip it
+            continue;
+        }
 
-            // Convert to RGB
-            _glfwSplitBPP(depth, &r, &g, &b);
-            depth = (r << 16) | (g << 8) | b;
+        // Convert to RGB channel depths and encode
+        _glfwSplitBPP(visuals[i].depth, &r, &g, &b);
+        rgb = (r << 16) | (g << 8) | b;
 
-            // Is this mode unique?
-            for (l = 0;  l < rgbcount;  l++)
-            {
-                if (depth == rgbarray[l])
-                    break;
-            }
+        for (j = 0;  j < rgbCount;  j++)
+        {
+            if (rgbs[j] == rgb)
+                break;
+        }
 
-            if (l >= rgbcount)
-            {
-                rgbarray[rgbcount] = depth;
-                rgbcount++;
-            }
+        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;
 }
 
 

+ 2 - 24
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)