Closed mdales closed 8 months ago
When you get a chance, could you try the following in the Python venv:
>>> import glfw
>>> glfw.init()
1
>>> glfw.get_monitors()
[<glfw.LP__GLFWmonitor object at 0x106930cb0>]
>>> for monitor in _:
... print(glfw.get_monitor_workarea(monitor))
...
(0, 25, 1792, 1095)
>>>
Thanks! I'm curious if there's some pseudo-monitor being returned by this.
Alas, there is just one monitor:
(venv) $ python3
Python 3.11.6 (main, Oct 2 2023, 13:45:54) [Clang 15.0.0 (clang-1500.0.40.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import glfw
>>> glfw.init()
1
>>> glfw.get_monitors()
[<glfw.LP__GLFWmonitor object at 0x102c4dcd0>]
>>> for monitor in _:
... print(glfw.get_monitor_workarea(monitor))
...
(0, 44, 0, 0)
Hmmm… sad news. It feels like it's a bug upstream somewhere. pyGLFW is a fairly thin shim over GLFW, so I'm guessing the latter. I suspect I'm gonna have to upgrade to Sonoma to debug it.
If fullscreen operation is working, it'd be good if you could test a few of the examples and see if they all work before I commit 😉
Note that fullscreen operation with a single monitor isn't great with GFLW – another annoying issue. Generally I let is slide because I'm usually running fullscreen on a second monitor when working in the studio or performing live.
FWIW, I tried it with another monitor plugged in and I get:
>>> import glfw
>>> glfw.init()
1
>>> glfw.get_monitors()
[<glfw.LP__GLFWmonitor object at 0x10086dcd0>, <glfw.LP__GLFWmonitor object at 0x10086dd50>]
>>> for monitor in _:
... print(glfw.get_monitor_workarea(monitor))
...
(0, 25, 0, 0)
(3360, 765, 0, 0)
So still no width/height data. FWIW, I assume this is the glfw version I'm using:
$ brew info glfw
==> glfw: stable 3.3.8 (bottled), HEAD
Multi-platform library for OpenGL applications
https://www.glfw.org/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/g/glfw.rb
License: Zlib
==> Dependencies
Build: cmake ✔
==> Options
--HEAD
Install HEAD version
==> Analytics
install: 1,820 (30 days), 5,174 (90 days), 14,666 (365 days)
install-on-request: 1,514 (30 days), 4,234 (90 days), 12,364 (365 days)
build-error: 0 (30 days)
I note that this is the latest public release of glfw, but that was published in July 2022. https://www.glfw.org
I then thought I'd see if it's a generic GLFW issue on Sonoma, so I wrote the following small Go program:
import (
"fmt"
"github.com/go-gl/glfw/v3.3/glfw"
)
func main() {
err := glfw.Init()
if err != nil {
panic(err)
}
defer glfw.Terminate()
monitors := glfw.GetMonitors()
for _, monitor := range monitors {
x, y, width, height := monitor.GetWorkarea()
fmt.Printf("%d %d %d %d\n", x, y, width, height);
}
}
This is based on the sample code provided with the go-gl/glfw library. The output of this is:
0 25 3360 1865
3360 765 1800 1125
From this I infer that the issue is perhaps related to the Python bindings on Sonoma rather than the GLFW library itself.
In response to your question @jonathanhogg about the examples working or not, I've attached a couple of screenshots for you to decide if they work (the are in a window as I commented out the window resizing code). They generally seemed to work, except:
badapple.m4v
file to let me test that one.Interesting…
So my understanding is that pyGLFW uses a built-in GLFW 3.3.8 shared library on macOS. I'll have a stare at the code and see if anything jumps out as to what is going wrong.
In terms of tests:
bloom.fl
is an include used by physics.fl
;dmx.fl
and laser.fl
both – as you supposed – depend on physical devices being present;push2.fl
is just a controller config without any visuals connected (it doesn't crash like the other two because the controller code is a bit smarter and waits for the hardware to be plugged-in);video.fl
due to space and copyright – I need to find a small public domain video to use;Of the working examples, smoke.fl
and canvas3d.fl
look as I'd expect, but the physic.fl
screenshot looks odd as it looks like there are two balls of cells overlaid on top of each other and some resulting weird artefacts from the bloom filter. Is this exactly how it looked on-screen? I'm wondering if the double-buffering has gone mad…
The pyGLFW wrapper for glfwGetMonitorWorkArea()
is pretty thin:
if hasattr(_glfw, 'glfwGetMonitorWorkarea'):
_glfw.glfwGetMonitorWorkarea.restype = None
_glfw.glfwGetMonitorWorkarea.argtypes = [ctypes.POINTER(_GLFWmonitor),
ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.c_int)]
def get_monitor_workarea(monitor):
"""
Retrives the work area of the monitor.
Wrapper for:
void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height);
"""
xpos_value = ctypes.c_int(0)
xpos = ctypes.pointer(xpos_value)
ypos_value = ctypes.c_int(0)
ypos = ctypes.pointer(ypos_value)
width_value = ctypes.c_int(0)
width = ctypes.pointer(width_value)
height_value = ctypes.c_int(0)
height = ctypes.pointer(height_value)
_glfw.glfwGetMonitorWorkarea(monitor, xpos, ypos, width, height)
return (
xpos_value.value,
ypos_value.value,
width_value.value,
height_value.value
)
I'm unclear why the width and height values wouldn't be updated on Sonoma/Apple-Silicon (not sure yet which is the root cause since I've not updated my Mac yet).
$ lsof | grep glfw
...
Python 9281 michael txt REG 1,17 233516 83660324 /Users/michael/Dev/flitter/venv/lib/python3.11/site-packages/glfw/libglfw.3.dylib
...
Looks like pip installs its own glfw lib?
Here's a video of physics.fl in action - to does look like it's doing everything twice somehow?
https://github.com/jonathanhogg/flitter/assets/28506/22b2d962-d99a-4c3e-83ab-0cfe79c1755d
Cripes. That is freaky! There appear to be – at least – two versions of the ball being rendered. It's not double-buffering as they are too far apart. It looks like the whole program is being run twice with two different beat
clocks into the same render buffer.
Reckon that's another bug report in there, though…
On the monitors thing, it occurred to me to try rule out whether it was the fact I was using a home-brew install of Python (flitter needing > 3.9 which is still the system install on Sonoma). But if I run the sample code you gave me before using glfw installed in a virtual env using the system Python I get the same result of no width/height.
Getting the video mode does seem to work:
>>> m = glfw.get_monitors()[0]
>>> glfw.get_video_mode(m)
GLFWvidmode(size=Size(width=1800, height=1169), bits=Bits(red=8, green=8, blue=8), refresh_rate=120)
Sadly, this code is working fine for me on Intel Sonoma (homebrew Python 3.11.6 and glfw
2.6.2) so it seems to be a bug that only affects ARM64.
I was about to say that this is possibly a bug in ctypes
when I noticed that the glfw
wrapper for glfwGetMonitorWorkarea()
looks to be setting up the argument types incorrectly. The wrapper has this in it (glfw/__init__.py:995
):
_glfw.glfwGetMonitorWorkarea.restype = None
_glfw.glfwGetMonitorWorkarea.argtypes = [ctypes.POINTER(_GLFWmonitor),
ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.c_int)]
but the function takes 5 arguments: the monitor and 4 pointers to integers. I wonder if you could try changing this code to:
_glfw.glfwGetMonitorWorkarea.restype = None
_glfw.glfwGetMonitorWorkarea.argtypes = [ctypes.POINTER(_GLFWmonitor),
ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.c_int)]
and see if that works? If so, then I'll raise a bug upstream on PyGLFW. I've verified that making this change doesn't affect functionality on Intel.
Ding ding ding, you have a winner:
import glfw
import types
from glfw import _GLFWmonitor
>>> glfw.library.glfw.glfwGetMonitorWorkarea.argtypes = [ctypes.POINTER(_GLFWmonitor),
... ctypes.POINTER(ctypes.c_int),
... ctypes.POINTER(ctypes.c_int),
... ctypes.POINTER(ctypes.c_int),
... ctypes.POINTER(ctypes.c_int)]
>>> glfw.init()
1
>>> glfw.get_monitors()
[<glfw.LP__GLFWmonitor object at 0x100d0dd50>, <glfw.LP__GLFWmonitor object at 0x100d0ddd0>]
>>> for m in _:
... print(glfw.get_monitor_workarea(m))
...
(0, 25, 3360, 1865)
(3360, 765, 1800, 1125)
I've opened an upstream bug report and PR (https://github.com/FlorianRhiem/pyGLFW/issues/73).
A new version of glfw
has just been released that fixes this bug. Can you confirm windows are working again on your Mac for me? Then I'll get back to staring at the 3D rendering bug…
I did a pip install --upgrade glfw
and that seems to have fixed the issue.
I checked out and tried to run flitter as described in the readme, and running the demo crashes:
The root cause of this issues is that the call to get the monitor working area returns (0, 44, 0, 0) - this is not an error (I can call glfw.get_error() and I get 0, and the 44 implies we know about the menu bar.
This response gives mw and mh as zero, which causes the following code:
to make width and height zero.
I did some spelunking, and if I comment that code out so I get a window, then even with a fully setup and working GL environment the monitor area is still wrong. In fullscreen things work, as this check then doesn't have effect.
macOS version: 14.0 (23A344 Python version: Python 3.11.6 (from home-brew) CPU: Apple M1 Pro