Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLFW v3.4 #400

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

GLFW v3.4 #400

wants to merge 8 commits into from

Conversation

Geo25rey
Copy link

@Geo25rey Geo25rey commented May 5, 2024

Overview

This is a rough implementation of go-glfw using GLFW v3.4. I have done some basic testing on Linux Wayland and XWayland. I highly recommend reviewing by commit considering the nature and size of this PR.

I am also looking for people to test the builds and functionality on the various platforms listed below. I can personally continue testing on Linux and if I have extra time, MacOS Arm.

Closes: #393
Potentially fixes: #272 @dmitshur
Requesting Review from: @Jacalz

Rundown by commit

Testing

Preamble

I used the short Custom Cursor program for testing. It would probably be a good idea to test with other programs, as well. Does anyone have such test programs?

It is especially important to get more test programs for Wayland since more features than just setting the window icon are not supported by GLFW and/or the Wayland protocols yet, and I'm not sure of other implications of the SIGABRT behavior previously mentioned. For example, I could dynamically add some element to my window at runtime, which could crash my program with a cryptic abort message with no other context. At best, developers using go-glfw can report it here, and at worst a subset of users will report the issue to downstream projects that use go-glfw and the downstream developers may not know what to do with the error message.

cd v3.4/glfw; go run testdata/customcursor/main.go

  • Linux
    • Wayland
      • OpenGL (-tags linux,wayland)
      • GLESv1 (-tags linux,wayland,gles1)
        • doesn't compile on Arch Linux with latest Mesa drivers
      • GLESv2 (-tags linux,wayland,gles2)
      • GLESv3 (-tags linux,wayland,gles3)
        • doesn't compile on Arch Linux with latest Mesa drivers
      • Vulkan (-tags linux,wayland,vulkan)
    • X11
      • OpenGL (-tags linux)
      • GLESv1 (-tags linux,gles1)
        • doesn't compile on Arch Linux with latest Mesa drivers
      • GLESv2 (-tags linux,gles2)
      • GLESv3 (-tags linux,gles3)
        • doesn't compile on Arch Linux with latest Mesa drivers
      • Vulkan (-tags linux,vulkan)
  • BSD
    • FreeBSD
      • Wayland (-tags freebsd,wayland)
      • X11 (-tags freebsd)
    • NetBSD
      • Wayland (-tags netbsd,wayland)
      • X11 (-tags netbsd)
    • OpenBSD
      • Wayland (Is this unsupported? There is no tag set for this.)
      • X11 (-tags openbsd)
  • Mac
    • Arm (I can get to this at some point, but if someone would like to get to first, feel free. I'm not sure when I'll have time for it)
      • opengl32 (-tags darwin)
      • GLESv2 (-tags darwin,gles2)
    • x86
      • opengl32 (-tags darwin)
      • GLESv2 (-tags darwin,gles2)
  • Windows (not sure if both 10 & 11 need to be tested but better safe than sorry, right?)
    • 10
      • opengl32 (-tags windows)
      • GLESv2 (-tags windows,gles2)
    • 11
      • opengl32 (-tags windows)
      • GLESv2 (-tags windows,gles2)

TODO before merge

  • Fix BSD build
  • Fix Windows build
  • Update window hints
  • Cleanup commit history (if needed)
  • Make issue for Feature Unavailable and Unimplemented errors not cause Go panic. GLFW v3.4 #400 (comment)
  • Make issue for what default build tags should be on Linux (X11, Wayland, or both)

@dmitshur
Copy link
Member

dmitshur commented May 6, 2024

Thanks for working on this.

I used the short Custom Cursor program for testing. It would probably be a good idea to test with other programs, as well. Does anyone have such test programs?

It's not much, but there are two small example programs in https://github.com/go-gl/example.


Out of the box, it fails to link on GOOS=darwin GOARCH=arm64 with:

# command-line-arguments
/usr/local/go/pkg/tool/darwin_arm64/link: running clang failed: exit status 1
Undefined symbols for architecture arm64:
  "__glfwPlatformFreeModule", referenced from:
      __glfwTerminateNull in 000002.o
      __glfwTerminateOSMesa in 000002.o
      _terminate in 000002.o
      __glfwInitVulkan in 000002.o
      __glfwTerminateVulkan in 000002.o
      __glfwInitOSMesa in 000002.o
      __glfwTerminateCocoa in 000003.o
      ...
  "__glfwPlatformGetModuleSymbol", referenced from:
      __glfwInitVulkan in 000002.o
      _glfwGetInstanceProcAddress in 000002.o
      __glfwInitOSMesa in 000002.o
      __glfwInitOSMesa in 000002.o
      __glfwInitOSMesa in 000002.o
      __glfwInitOSMesa in 000002.o
      __glfwInitOSMesa in 000002.o
      __glfwInitOSMesa in 000002.o
      __glfwInitOSMesa in 000002.o
      ...
  "__glfwPlatformLoadModule", referenced from:
      __glfwInitVulkan in 000002.o
      __glfwInitOSMesa in 000002.o
      __glfwLoadLocalVulkanLoaderCocoa in 000003.o
      __glfwInitEGL in 000003.o
      __glfwCreateContextEGL in 000003.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

That doesn't happen if this line is added to c_glfw_darwin.go:

 #include "glfw/src/cocoa_time.c"
+#include "glfw/src/posix_module.c"
 #include "glfw/src/posix_thread.c"

And with that at least basic functionality seems to work okay on macOS.

@Geo25rey
Copy link
Author

Geo25rey commented May 6, 2024

It's not much, but there are two small example programs in https://github.com/go-gl/example.

I'll go ahead and try these then.

c_glfw_darwin.go:

 #include "glfw/src/cocoa_time.c"
+#include "glfw/src/posix_module.c"
 #include "glfw/src/posix_thread.c"

Cool I'll add this in.

By the way, does this fix #272 for you? I think the upstream fix is included in GLFW v3.4.

@Geo25rey
Copy link
Author

Geo25rey commented May 6, 2024

Forgot to mention, @dmitshur can you test with -tags darwin,gles2 as well?

@Jacalz
Copy link
Collaborator

Jacalz commented May 6, 2024

Without the changes in #399 (and also defining _GNU_SOURCE for X11 compared to v3.3), I can't compile this on Fedora 40 due to implicit declarations now being treated as errors. Test results after that change:

I can replicate the same gles1 and gles3 failures on Fedora 40 (Wayland and X11) but I get the same error on v3.3 so that's fine? Compiling with -tags gles does work though.

Isn't Glfw v3.4 supposed to be able to switch between Wayland and X11 at runtime? If that is the case, should we enable that by default? Maybe have x11 and wayland tags for when you only want a single backend?

@Jacalz
Copy link
Collaborator

Jacalz commented May 6, 2024

FreeBSD X11 seems to get this error:
image

@Geo25rey
Copy link
Author

Geo25rey commented May 6, 2024

FreeBSD X11 seems to get this error: image

Does go build -tags freebsd work?

@Geo25rey
Copy link
Author

Geo25rey commented May 6, 2024

Without the changes in #399 (and also defining _GNU_SOURCE for X11 compared to v3.3), I can't compile this on Fedora 40 due to implicit declarations now being treated as errors. Test results after that change:

I can define _GNU_SOURCE, but I get this warning, which could be an error in Fedora?

In file included from ./c_glfw_lin.go:9:
./glfw/src/wl_window.c:27: warning: "_GNU_SOURCE" redefined
   27 | #define _GNU_SOURCE

I can replicate the same gles1 and gles3 failures on Fedora 40 (Wayland and X11) but I get the same error on v3.3 so that's fine? Compiling with -tags gles does work though.

I think it's fine too. To my understanding, GLES v1 & v3 are just different implementations of the OpenGL spec. So, it's probably good keeping them in, but they might be hard to test on bleeding edge distros like Arch and Fedora.

Also, I believe -tags gles is ignored when building for Linux & BSD. It would just choose the default which is -lGL implementation, right?

Isn't Glfw v3.4 supposed to be able to switch between Wayland and X11 at runtime? If that is the case, should we enable that by default? Maybe have x11 and wayland tags for when you only want a single backend?

I think it's best to keep X11 as the default to make the transition easier from v3.3 to v3.4, but if GLFW can now choose Wayland or X11 at runtime, maybe we can add support for this when both x11 and wayland tags are included.

@Geo25rey
Copy link
Author

Geo25rey commented May 6, 2024

I just pushed support for applying both X11 & Wayland on Linux with (-tags x11,wayland). I will add to BSD later, but I want to get the build working standalone on BSD first.

@Jacalz
Copy link
Collaborator

Jacalz commented May 6, 2024

Does go build -tags freebsd work?

That won't make any difference as I was building on FreeBSD. The GOOS value for the native operating system is always added automatically and the same goes for GOARCH. If you build your app on Linux for example, you don't need to pass -tags linux.

@Jacalz
Copy link
Collaborator

Jacalz commented May 6, 2024

I can define _GNU_SOURCE, but I get this warning, which could be an error in Fedora?

No, it is not an error in Fedora. It is a drawback of the solution. See #359, we need a better solution but right now that is better than not being able to compile. Implicit declarations are emitted (which is treated as an error on Fedora 40 due to stricter security settings) if your don't force _GNU_SOURCE to on but if you do, you get a warning that it is defined twice.

I think it's best to keep X11 as the default to make the transition easier from v3.3 to v3.4, but if GLFW can now choose Wayland or X11 at runtime, maybe we can add support for this when both x11 and wayland tags are included.

I'm not personally of doing that approach. Wayland is the future and I think we should enable the runtime switching support if we can. However, it is up to @dmitshur at the end of the day.

@metal3d
Copy link
Contributor

metal3d commented May 7, 2024

I can define _GNU_SOURCE, but I get this warning, which could be an error in Fedora?

In file included from ./c_glfw_lin.go:9:
./glfw/src/wl_window.c:27: warning: "_GNU_SOURCE" redefined
   27 | #define _GNU_SOURCE

Yes, this is a warning due to the manual definition inside GLFW source code. I don't understand why it's defined without a #ifndef - it could be a mistake or a wanted behavior.

// GLFW Options:
#cgo linux,!wayland CFLAGS: -D_GLFW_X11
#cgo linux,x11 CFLAGS: -D_GLFW_X11
#cgo linux,wayland CFLAGS: -D_GLFW_WAYLAND
Copy link
Contributor

@metal3d metal3d May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment on top, is it OK that _GNU_SOURCE is now globally set?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably don't want it set but I couldn't compile at all without it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no response to #400 (comment), I'll just mark this as resolved.

package glfw

/*
#cgo CFLAGS: -Iglfw/include -D_GNU_SOURCE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So then, _GNU_SOURCE is now globally set?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no response to #400 (comment), I'll just mark this as resolved.

@Geo25rey
Copy link
Author

Geo25rey commented May 7, 2024

@metal3d I think _GNU_SOURCE is better to be set for all platforms since GLFW already handles cross-platform functionality. Ideally, _GNU_SOURCE should be set directly before the required #include, but it seems that there is an issue with the order the C source files are included into Go code. I think this is the most robust solution rather than hoping someone doesn't reorder the C source files in the future.

@Geo25rey
Copy link
Author

Geo25rey commented May 7, 2024

Wayland is the future

@Jacalz I completely agree, but this isn't about ideologies. This is about what is best for the users of this library.

we should enable the runtime switching support if we can.

I have added support for this on Linux like I said previously (-tags x11,wayland). Right now, I just have it setup as an opt-in feature rather than replacing the X11 default.

@Jacalz
Copy link
Collaborator

Jacalz commented May 7, 2024

@Jacalz I completely agree, but this isn't about ideologies. This is about what is best for the users of this library.

My point has nothing to do with ideologies. You are taking things out of context and I don't agree that being X11-only would be helpful in the long run. Enabling Wayland-only by default would be stupid but supporting dynamic switching between the two is a good compromise that we should try to make use of now that we can.

Enabling runtime switching by default is the best path forward given how quickly Wayland is getting adopted and some distros like Fedora are even disabling Xorg support (XWayland works yes, but you see the direction we are heading). Making the switch to enable Wayland support by default now is going to be the better option as a future-proof setting and that switch will be much harder to make down the line. Remember that v3.4 is an entirely new module import and it would be problematic to suddenly enable Wayland support and require an extra dependency when compiling later in the lifecycle of that existing in the repository. If we are to stay up to date with the times, that support needs to be enabled from the start. If you still want to have X11-only, I see no reason why people can't still use v3.3 given that it still will be maintained some time forward.

We have seen in Fyne that the community cares very much for Wayland support to be enabled and Flathub even marks an X11-only application as unsafe nowadays (https://flathub.org/apps/io.github.jacalz.rymdport). Having dynamic runtime switching gets us both X11 and Wayland support and a lot more people will actually use it instead of having to enable an obscure build tag combination.

@J7mbo
Copy link

J7mbo commented May 18, 2024

Hey @Geo25rey, given that Mac --> opengl32 is checked here, I tried building on an M3 with:

go build -tags darwin

And then running ./customcursor.

I had to comment out:

window.SetIcon([]image.Image{whiteTriangle})

in v3.4/glfw/testdata/customcursor/main.go:36, as it was complaining about Cocoa:

go-gl/glfw: internal error: an invalid error was not accepted by the caller: ErrorCode(65548): Cocoa: Regular windows do not have icons on macOS
go-gl/glfw: Please report this in the Go package issue tracker.
panic: ErrorCode(65548): Cocoa: Regular windows do not have icons on macOS

Given the above being commented out, the mouse passthrough I was looking for worked (with floating), after adding the Hint to window.go, so thanks a lot for that! :)

@Geo25rey
Copy link
Author

@J7mbo Thx for testing this out according to LWJGL/lwjgl3#695, this commit glfw/glfw@9a87c2a introduced 2 new errors affecting macOS and Wayland, so I think we should pass both GLFW_FEATURE_UNAVAILABLE and GLFW_FEATURE_UNIMPLEMENTED back as go errors instead of panicking

@Geo25rey
Copy link
Author

@J7mbo I just looked at your issue #375 (comment) and it looks like all the hints are out of date or have out of date descriptions so I will add them from here https://www.glfw.org/docs/3.4/window_guide.html#window_hints_wnd

Copy link
Member

@dmitshur dmitshur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for getting it this far. I've been using this locally on macOS and haven't spotted any more issues on this platform and in my usage.


Forgot to mention, @dmitshur can you test with -tags darwin,gles2 as well?

I gave it a try:

$ go run -tags=gles2 .
# github.com/go-gl/example/trygles2
/usr/local/go/pkg/tool/darwin_arm64/link: running clang failed: exit status 1
ld: warning: ignoring duplicate libraries: '-lGLESv2'
ld: library 'GLESv2' not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)

It's the same error as I get with glfw/v3.3. I've never tried to use OpenGL ES on macOS, and I don't think it's supported. Maybe it is on iOS, but I don't think go-gl/glfw (or upstream GLFW) tries to support iOS at this time.

https://www.glfw.org/docs/latest/window_guide.html#GLFW_CONTEXT_VERSION_MAJOR_hint includes:

macOS: The OS only supports core profile contexts for OpenGL versions 3.2 and later.


I have added support for this on Linux like I said previously (-tags x11,wayland). Right now, I just have it setup as an opt-in feature rather than replacing the X11 default.

Thanks for working on this and getting this work at all, that's great. There was a question of what would be preferred default behavior.

My general approach to answering these kinds of questions is to try to follow the upstream GLFW decisions whenever viable, with a balance of satisfying constraints on the Go side. Since GLFW v3.4 changed its default compared to GLFW v3.3 from X11 (with Wayland selected at compile-time) to X11+Wayland selected at runtime, if we can make that the default for glfw/v3.4, that seems optimal to me. That is, based on my current understanding, having what is currently selected with -tags=x11,wayland be selected with -tags= (no custom tags) instead seems optimal for the eventual glfw/v3.4 version. I'm certainly open to being convinced otherwise if there are reasons this doesn't work well.

If we think more discussion is needed, I also think it's fine to leave it as is and make it a follow up issue instead of trying to resolve it as part of this PR.

@@ -0,0 +1,6 @@
//go:build !((linux && wayland) || (freebsd && wayland) || (netbsd && wayland) || (openbsd && wayland))
// -build linux,wayland freebsd,wayland netbsd,wayland openbsd,wayland
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I thought I left this review comment before, but it doesn't seem to show up. Trying it again.)

This line seems to be malformed. Maybe it was intended to be // +build. I think it'd be fine not to include it at all, since all versions of Go since Go 1.17 can handle build constraints specified via just the //go:build lines.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. I'll go ahead and fix this. I'll look at the docs. Do you have a link to the relevant docs?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build constraints are documented at https://pkg.go.dev/cmd/go#hdr-Build_constraints.

@DownloadableFox
Copy link

Are there any extra steps or requirements for building in Windows? I have tried to build in both Windows 10 and 11 with different results, but failing in both. I tried the same steps in my Arch Linux machine and it worked first try.

@Geo25rey
Copy link
Author

Thx for testing on Windows @DownloadableFox

Please share the build errors you have found so they can be fixed.

@Geo25rey
Copy link
Author

@dmitshur I have added a TODO list for items I'd like to get done before merging this in the PR description #400 (comment)

If we think more discussion is needed, I also think it's fine to leave it as is and make it a follow up issue instead of trying to resolve it as part of this PR.

I agree. We should probably pull in someone from the Fyne team, as well. I'm sure they'd have some useful insights on this.

@DownloadableFox
Copy link

Thx for testing on Windows @DownloadableFox

Please share the build errors you have found so they can be fixed.

I don't have my Windows 11 computer with me at the moment, but this is the output from Windows 10:
image

It appears to be several lines of linker problems. If you want the full log I'd be happy to share it with you, though it's pretty big. I tried building v3.3 and it built with no problems under the same environment. Currently using Go 1.22.1 and MINGW64 through MSYS2.

@Jacalz
Copy link
Collaborator

Jacalz commented May 27, 2024

I agree. We should probably pull in someone from the Fyne team, as well. I'm sure they'd have some useful insights on this.

I am part of the Fyne team. That's where my insights and opinions on Wayland come from

@Geo25rey
Copy link
Author

Geo25rey commented May 27, 2024

@DownloadableFox please provide the full plain text output either here in a < summary > < details > HTML tag or in a public gist.

@Geo25rey
Copy link
Author

@Jacalz How about we discuss in a voice call in the Fyne Discord server? Do you have availability this weekend?

Also, I'd like to include someone from the Fyne team that is not opinionated about Wayland itself to hopefully prevent any stalemates, if that is alright with you.

@Jacalz
Copy link
Collaborator

Jacalz commented May 27, 2024

@Jacalz How about we discuss in a voice call in the Fyne Discord server? Do you have availability this weekend?

Voice call sounds like a good plan. I won't be available this weekend unfortunately but the next one or next week should hopefully be a better option.

Also, I'd like to include someone from the Fyne team that is not opinionated about Wayland itself to hopefully prevent any stalemates, if that is alright with you.

Sure. If you say so.

@Geo25rey
Copy link
Author

@Jacalz how about 1pm EDT on Monday, May 3?

@Jacalz
Copy link
Collaborator

Jacalz commented May 27, 2024

That works well for me. Should we check on Discord if someone more from our team is available?

@Geo25rey
Copy link
Author

Yeah sounds good. @Jacalz

Can you ask around?

@DownloadableFox
Copy link

DownloadableFox commented May 27, 2024

@DownloadableFox please provide the full plain text output either here in a < summary > < details > HTML tag or in a public gist.

As a correction to my previous comment, both Windows 11 and 10 share the same output. I might have not looked at it correctly last time I tried to build. Here's the log:

https://gist.github.com/DownloadableFox/33c16e3e26566a1eb1252454a0b1e87d

EDIT: Ended up making it a Gist instead due to formatting issues.

@DownloadableFox
Copy link

DownloadableFox commented May 28, 2024

@DownloadableFox please provide the full plain text output either here in a < summary > < details > HTML tag or in a public gist.

As a correction to my previous comment, both Windows 11 and 10 share the same output. I might have not looked at it correctly last time I tried to build. Here's the log:

https://gist.github.com/DownloadableFox/33c16e3e26566a1eb1252454a0b1e87d

EDIT: Ended up making it a Gist instead due to formatting issues.

I was actually able to fix this after a couple of hours tampering with the code. I was able to build and run in both Windows 10 and 11 by adding this line to g_glfw_windows.go.

#include "glfw/src/win32_module.c"

@Jacalz
Copy link
Collaborator

Jacalz commented May 28, 2024

Yeah sounds good. @Jacalz

Can you ask around?

Absolutely. Andrew (@andydotxyz here on GitHub), the founder and team leader of Fyne, is on board as well 👍

@J7mbo
Copy link

J7mbo commented Jun 1, 2024

Did this happen in the end? Any update?

@Jacalz
Copy link
Collaborator

Jacalz commented Jun 1, 2024

The meeting on the third of June hasn't happened yet

@DownloadableFox
Copy link

Any updates on this?

@Jacalz
Copy link
Collaborator

Jacalz commented Jun 14, 2024

We had a discussion and came to the conclusion that X11 + Wayland is the way to go. It is the default upstream and what the whole ecosystem is pushing for. It is a change that will be harder to implement in the future.

@dmitshur
Copy link
Member

Checking in on the status. @Geo25rey, would you like to keep pushing this forward? If so, there are some unresolved review comments that need to be addressed, otherwise this seems close. I've been using this locally for a while without uncovering new issues.

@Geo25rey
Copy link
Author

@dmitshur I can work on it tomorrow. I have a patch for Windows support to finish and I need to update the Linux default build tags.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants