Sfoglia il codice sorgente

Add GLFW_SCALE_FRAMEBUFFER window hint

This adds the GLFW_SCALE_FRAMEBUFFER window hint, enabling control of
framebuffer scaling across Wayland and macOS.  On macOS, this window
hint is a new name for GLFW_COCOA_RETINA_FRAMEBUFFER, and both hint
names will modify the same hint.

This is now a more symmetric counterpart to GLFW_SCALE_TO_MONITOR and,
weirdly, they each apply neatly to half of the supported platforms.

This commit is mostly documentation updates to better integrate and
contrast these two scaling mechanisms.
Camilla Löwy 1 anno fa
parent
commit
a9cc7c7260
12 ha cambiato i file con 92 aggiunte e 44 eliminazioni
  1. 1 0
      README.md
  2. 2 10
      docs/monitor.md
  3. 17 0
      docs/news.md
  4. 46 19
      docs/window.md
  5. 10 3
      include/GLFW/glfw3.h
  6. 1 1
      src/cocoa_platform.h
  7. 3 3
      src/cocoa_window.m
  8. 1 1
      src/internal.h
  9. 1 1
      src/nsgl_context.m
  10. 5 6
      src/window.c
  11. 1 0
      src/wl_platform.h
  12. 4 0
      src/wl_window.c

+ 1 - 0
README.md

@@ -144,6 +144,7 @@ information on what to include when reporting a bug.
    content area (#58)
  - Added `GLFW_POSITION_X` and `GLFW_POSITION_Y` window hints for initial position
    (#1603,#1747)
+ - Added `GLFW_SCALE_FRAMEBUFFER` window hint for Wayland and macOS scaling (#2457)
  - Added `GLFW_ANY_POSITION` hint value for letting the window manager choose (#1603,#1747)
  - Added `GLFW_PLATFORM_UNAVAILABLE` error for platform detection failures (#1958)
  - Added `GLFW_FEATURE_UNAVAILABLE` error for platform limitations (#1692)

+ 2 - 10
docs/monitor.md

@@ -150,16 +150,8 @@ float xscale, yscale;
 glfwGetMonitorContentScale(monitor, &xscale, &yscale);
 ```
 
-The content scale is the ratio between the current DPI and the platform's
-default DPI.  This is especially important for text and any UI elements.  If the
-pixel dimensions of your UI scaled by this look appropriate on your machine then
-it should appear at a reasonable size on other machines regardless of their DPI
-and scaling settings.  This relies on the system DPI and scaling settings being
-somewhat correct.
-
-The content scale may depend on both the monitor resolution and pixel density
-and on user settings.  It may be very different from the raw DPI calculated from
-the physical size and current resolution.
+For more information on what the content scale is and how to use it, see
+[window content scale](@ref window_scale).
 
 
 ### Virtual position {#monitor_pos}

+ 17 - 0
docs/news.md

@@ -85,6 +85,22 @@ function pointers corresponding to the standard library functions `malloc`,
 For more information see @ref init_allocator.
 
 
+#### Window hint for framebuffer scaling {#scale_framebuffer_34}
+
+GLFW now allows provides the
+[GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint) window hint for
+controlling framebuffer scaling on platforms that handle scaling by keeping the
+window size the same while resizing the framebuffer.  The default value is to
+allow framebuffer scaling.
+
+This was already possible on macOS via the
+[GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint) window
+hint.  This hint is now another name for
+[GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint).
+
+For more information, see @ref window_scale.
+
+
 #### Window hints for initial position {#features_34_position_hint}
 
 GLFW now provides the @ref GLFW_POSITION_X and @ref GLFW_POSITION_Y window hints for
@@ -288,6 +304,7 @@ then GLFW will fail to initialize.
  - @ref GLFW_WAYLAND_LIBDECOR
  - @ref GLFW_WAYLAND_PREFER_LIBDECOR
  - @ref GLFW_WAYLAND_DISABLE_LIBDECOR
+ - @ref GLFW_SCALE_FRAMEBUFFER
 
 
 ## Release notes for earlier versions {#news_archive}

+ 46 - 19
docs/window.md

@@ -239,13 +239,28 @@ focus when @ref glfwShowWindow is called. Possible values are `GLFW_TRUE` and
 
 @anchor GLFW_SCALE_TO_MONITOR
 __GLFW_SCALE_TO_MONITOR__ specified whether the window content area should be
-resized based on the [monitor content scale](@ref monitor_scale) of any monitor
-it is placed on.  This includes the initial placement when the window is
-created.  Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
+resized based on [content scale](@ref window_scale) changes.  This can be
+because of a global user settings change or because the window was moved to
+a monitor with different scale settings.
 
 This hint only has an effect on platforms where screen coordinates and pixels
-always map 1:1 such as Windows and X11.  On platforms like macOS the resolution
-of the framebuffer is changed independently of the window size.
+always map 1:1, such as Windows and X11.  On platforms like macOS the resolution
+of the framebuffer can change independently of the window size.
+
+@anchor GLFW_SCALE_FRAMEBUFFER_hint
+@anchor GLFW_COCOA_RETINA_FRAMEBUFFER_hint
+__GLFW_SCALE_FRAMEBUFFER__ specifies whether the framebuffer should be resized
+based on [content scale](@ref window_scale) changes.  This can be
+because of a global user settings change or because the window was moved to
+a monitor with different scale settings.
+
+This hint only has an effect on platforms where screen coordinates can be scaled
+relative to pixel coordinates, such as macOS and Wayland.  On platforms like
+Windows and X11 the framebuffer and window content area sizes always map 1:1.
+
+This is the new name, introduced in GLFW 3.4.  The older
+`GLFW_COCOA_RETINA_FRAMEBUFFER` name is also available for compatibility.  Both
+names modify the same hint value.
 
 @anchor GLFW_MOUSE_PASSTHROUGH_hint
 __GLFW_MOUSE_PASSTHROUGH__ specifies whether the window is transparent to mouse
@@ -474,11 +489,6 @@ GLFW behaves as if this hint was set to `GLFW_FALSE`.  Possible values are
 
 #### macOS specific hints {#window_hints_osx}
 
-@anchor GLFW_COCOA_RETINA_FRAMEBUFFER_hint
-__GLFW_COCOA_RETINA_FRAMEBUFFER__ specifies whether to use full resolution
-framebuffers on Retina displays.  Possible values are `GLFW_TRUE` and
-`GLFW_FALSE`.  This is ignored on other platforms.
-
 @anchor GLFW_COCOA_FRAME_NAME_hint
 __GLFW_COCOA_FRAME_NAME__ specifies the UTF-8 encoded name to use for autosaving
 the window frame, or if empty disables frame autosaving for the window.  This is
@@ -533,6 +543,7 @@ GLFW_CENTER_CURSOR            | `GLFW_TRUE`                 | `GLFW_TRUE` or `GL
 GLFW_TRANSPARENT_FRAMEBUFFER  | `GLFW_FALSE`                | `GLFW_TRUE` or `GLFW_FALSE`
 GLFW_FOCUS_ON_SHOW            | `GLFW_TRUE`                 | `GLFW_TRUE` or `GLFW_FALSE`
 GLFW_SCALE_TO_MONITOR         | `GLFW_FALSE`                | `GLFW_TRUE` or `GLFW_FALSE`
+GLFW_SCALE_FRAMEBUFFER        | `GLFW_TRUE`                 | `GLFW_TRUE` or `GLFW_FALSE`
 GLFW_MOUSE_PASSTHROUGH        | `GLFW_FALSE`                | `GLFW_TRUE` or `GLFW_FALSE`
 GLFW_POSITION_X               | `GLFW_ANY_POSITION`         | Any valid screen x-coordinate or `GLFW_ANY_POSITION`
 GLFW_POSITION_Y               | `GLFW_ANY_POSITION`         | Any valid screen y-coordinate or `GLFW_ANY_POSITION`
@@ -563,7 +574,6 @@ GLFW_CONTEXT_DEBUG            | `GLFW_FALSE`                | `GLFW_TRUE` or `GL
 GLFW_OPENGL_PROFILE           | `GLFW_OPENGL_ANY_PROFILE`   | `GLFW_OPENGL_ANY_PROFILE`, `GLFW_OPENGL_COMPAT_PROFILE` or `GLFW_OPENGL_CORE_PROFILE`
 GLFW_WIN32_KEYBOARD_MENU      | `GLFW_FALSE`                | `GLFW_TRUE` or `GLFW_FALSE`
 GLFW_WIN32_SHOWDEFAULT        | `GLFW_FALSE`                | `GLFW_TRUE` or `GLFW_FALSE`
-GLFW_COCOA_RETINA_FRAMEBUFFER | `GLFW_TRUE`                 | `GLFW_TRUE` or `GLFW_FALSE`
 GLFW_COCOA_FRAME_NAME         | `""`                        | A UTF-8 encoded frame autosave name
 GLFW_COCOA_GRAPHICS_SWITCHING | `GLFW_FALSE`                | `GLFW_TRUE` or `GLFW_FALSE`
 GLFW_X11_CLASS_NAME           | `""`                        | An ASCII encoded `WM_CLASS` class name
@@ -736,16 +746,21 @@ float xscale, yscale;
 glfwGetWindowContentScale(window, &xscale, &yscale);
 ```
 
-The content scale is the ratio between the current DPI and the platform's
-default DPI.  This is especially important for text and any UI elements.  If the
-pixel dimensions of your UI scaled by this look appropriate on your machine then
-it should appear at a reasonable size on other machines regardless of their DPI
-and scaling settings.  This relies on the system DPI and scaling settings being
-somewhat correct.
+The content scale can be thought of as the ratio between the current DPI and the
+platform's default DPI.  It is intended to be a scaling factor to apply to the
+pixel dimensions of text and other UI elements.  If the dimensions scaled by
+this factor looks appropriate on your machine then it should appear at
+a reasonable size on other machines with different DPI and scaling settings.
+
+This relies on the DPI and scaling settings on both machines being appropriate.
+
+The content scale may depend on both the monitor resolution and pixel density
+and on user settings like DPI or a scaling percentage.  It may be very different
+from the raw DPI calculated from the physical size and current resolution.
 
 On systems where each monitors can have its own content scale, the window
-content scale will depend on which monitor the system considers the window to be
-on.
+content scale will depend on which monitor or monitors the system considers the
+window to be "on".
 
 If you wish to be notified when the content scale of a window changes, whether
 because of a system setting change or because it was moved to a monitor with
@@ -770,6 +785,18 @@ with a different content scale.  To have this done automatically both when the
 window is created and when its content scale later changes, set the @ref
 GLFW_SCALE_TO_MONITOR window hint.
 
+On platforms where pixels do not necessarily equal screen coordinates, the
+framebuffer will instead need to be sized to provide a full resolution image
+for the window.  When the window moves between monitors with different content
+scales, the window size will remain the same but the framebuffer size will
+change.  This is done automatically by default.  To disable this resizing, set
+the @ref GLFW_SCALE_FRAMEBUFFER window hint.
+
+Both of these hints also apply when the window is created.  Every window starts
+out with a content scale of one.  A window with one or both of these hints set
+will adapt to the appropriate scale in the process of being created, set up and
+shown.
+
 
 ### Window size limits {#window_sizelimits}
 

+ 10 - 3
include/GLFW/glfw3.h

@@ -1098,8 +1098,15 @@ extern "C" {
  *  [window hint](@ref GLFW_SCALE_TO_MONITOR).
  */
 #define GLFW_SCALE_TO_MONITOR       0x0002200C
-/*! @brief macOS specific
- *  [window hint](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint).
+/*! @brief Window framebuffer scaling
+ *  [window hint](@ref GLFW_SCALE_FRAMEBUFFER_hint).
+ */
+#define GLFW_SCALE_FRAMEBUFFER      0x0002200D
+/*! @brief Legacy name for compatibility.
+ *
+ *  This is an alias for the
+ *  [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint) window hint for
+ *  compatibility with earlier versions.
  */
 #define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001
 /*! @brief macOS specific
@@ -3167,7 +3174,7 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
  *
  *  @remark @macos On OS X 10.10 and later the window frame will not be rendered
  *  at full resolution on Retina displays unless the
- *  [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint)
+ *  [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint)
  *  hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the
  *  application bundle's `Info.plist`.  For more information, see
  *  [High Resolution Guidelines for OS X][hidpi-guide] in the Mac Developer

+ 1 - 1
src/cocoa_platform.h

@@ -145,7 +145,7 @@ typedef struct _GLFWwindowNS
 
     GLFWbool        maximized;
     GLFWbool        occluded;
-    GLFWbool        retina;
+    GLFWbool        scaleFramebuffer;
 
     // Cached window properties to filter out duplicate events
     int             width, height;

+ 3 - 3
src/cocoa_window.m

@@ -513,7 +513,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
 
     if (xscale != window->ns.xscale || yscale != window->ns.yscale)
     {
-        if (window->ns.retina && window->ns.layer)
+        if (window->ns.scaleFramebuffer && window->ns.layer)
             [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
 
         window->ns.xscale = xscale;
@@ -872,7 +872,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
         [window->ns.object setFrameAutosaveName:@(wndconfig->ns.frameName)];
 
     window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
-    window->ns.retina = wndconfig->ns.retina;
+    window->ns.scaleFramebuffer = wndconfig->scaleFramebuffer;
 
     if (fbconfig->transparent)
     {
@@ -1969,7 +1969,7 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance,
         return VK_ERROR_EXTENSION_NOT_PRESENT;
     }
 
-    if (window->ns.retina)
+    if (window->ns.scaleFramebuffer)
         [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
 
     [window->ns.view setLayer:window->ns.layer];

+ 1 - 1
src/internal.h

@@ -402,8 +402,8 @@ struct _GLFWwndconfig
     GLFWbool      focusOnShow;
     GLFWbool      mousePassthrough;
     GLFWbool      scaleToMonitor;
+    GLFWbool      scaleFramebuffer;
     struct {
-        GLFWbool  retina;
         char      frameName[256];
     } ns;
     struct {

+ 1 - 1
src/nsgl_context.m

@@ -333,7 +333,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
                                   forParameter:NSOpenGLContextParameterSurfaceOpacity];
     }
 
-    [window->ns.view setWantsBestResolutionOpenGLSurface:window->ns.retina];
+    [window->ns.view setWantsBestResolutionOpenGLSurface:window->ns.scaleFramebuffer];
 
     [window->context.nsgl.object setView:window->ns.view];
 

+ 5 - 6
src/window.c

@@ -274,6 +274,7 @@ void glfwDefaultWindowHints(void)
     _glfw.hints.window.focusOnShow  = GLFW_TRUE;
     _glfw.hints.window.xpos         = GLFW_ANY_POSITION;
     _glfw.hints.window.ypos         = GLFW_ANY_POSITION;
+    _glfw.hints.window.scaleFramebuffer = GLFW_TRUE;
 
     // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
     // double buffered
@@ -288,9 +289,6 @@ void glfwDefaultWindowHints(void)
 
     // The default is to select the highest available refresh rate
     _glfw.hints.refreshRate = GLFW_DONT_CARE;
-
-    // The default is to use full Retina resolution framebuffers
-    _glfw.hints.window.ns.retina = GLFW_TRUE;
 }
 
 GLFWAPI void glfwWindowHint(int hint, int value)
@@ -374,9 +372,6 @@ GLFWAPI void glfwWindowHint(int hint, int value)
         case GLFW_POSITION_Y:
             _glfw.hints.window.ypos = value;
             return;
-        case GLFW_COCOA_RETINA_FRAMEBUFFER:
-            _glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
         case GLFW_WIN32_KEYBOARD_MENU:
             _glfw.hints.window.win32.keymenu = value ? GLFW_TRUE : GLFW_FALSE;
             return;
@@ -389,6 +384,10 @@ GLFWAPI void glfwWindowHint(int hint, int value)
         case GLFW_SCALE_TO_MONITOR:
             _glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
             return;
+        case GLFW_SCALE_FRAMEBUFFER:
+        case GLFW_COCOA_RETINA_FRAMEBUFFER:
+            _glfw.hints.window.scaleFramebuffer = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
         case GLFW_CENTER_CURSOR:
             _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
             return;

+ 1 - 0
src/wl_platform.h

@@ -355,6 +355,7 @@ typedef struct _GLFWwindowWayland
     GLFWbool                    fullscreen;
     GLFWbool                    hovered;
     GLFWbool                    transparent;
+    GLFWbool                    scaleFramebuffer;
     struct wl_surface*          surface;
     struct wl_callback*         callback;
 

+ 4 - 0
src/wl_window.c

@@ -369,6 +369,9 @@ void _glfwUpdateBufferScaleFromOutputsWayland(_GLFWwindow* window)
         return;
     }
 
+    if (!window->wl.scaleFramebuffer)
+        return;
+
     // Get the scale factor from the highest scale monitor.
     int32_t maxScale = 1;
 
@@ -980,6 +983,7 @@ static GLFWbool createNativeSurface(_GLFWwindow* window,
     window->wl.bufferScale = 1;
     window->wl.title = _glfw_strdup(wndconfig->title);
     window->wl.appId = _glfw_strdup(wndconfig->wl.appId);
+    window->wl.scaleFramebuffer = wndconfig->scaleFramebuffer;
 
     window->wl.maximized = wndconfig->maximized;