Skip to content

(master) glamor: glamor_egl.c do not call xorgGlxCreateVendor()#3174

Merged
metux merged 2 commits into
X11Libre:masterfrom
cepelinas9000:fix/2949
Jun 30, 2026
Merged

(master) glamor: glamor_egl.c do not call xorgGlxCreateVendor()#3174
metux merged 2 commits into
X11Libre:masterfrom
cepelinas9000:fix/2949

Conversation

@cepelinas9000

@cepelinas9000 cepelinas9000 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Not 100% sure if it impacts kdrive


Backport dashboard

Target branch Backport PR Status
release/25.2 #3187 🔄 Open
release/25.1 #3188 🔄 Open
release/25.0 #3189 🔄 Open

The xorgGlxCreateVendor() call is present in glamor_egl.c on all three release lines, so the one-line removal applies cleanly to each. Release-line merges are manual/maintainer-only.

Add warning, that xorgGlxCreateVendor need to be called once

Signed-off-by: Tautvis <gtautvis@gmail.com>
This calls installed default glx vendor at top of callback chain,
which causes problem with other glx vendors, because it always succeds
and set same vendor for screen.

Signed-off-by: Tautvis <gtautvis@gmail.com>
@stefan11111

Copy link
Copy Markdown
Contributor

Is the problem caused by the multiple calls to that function? I remember looking into this some time ago, but I figured it's only effect is a duplicate vendor message in the log output, and is not worth patching.

@cepelinas9000

cepelinas9000 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

Is the problem caused by the multiple calls to that function? I remember looking into this some time ago, but I figured it's only effect is a duplicate vendor message in the log output, and is not worth patching.

As far as I testing, problem is here.

And I agree that duplicate vendor message looks harmless, But when nvidia proprietary driver involved it looks doing essentially what is in :

Bool GlxSetScreenVendor(ScreenPtr screen, GlxServerVendor *vendor)

That bug surfaces only when nvidia is drivers are loaded before glamor.

@stefan11111 stefan11111 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, assuming this works fine on xf86.
This change matches what I tested some time ago.

SInce https://gitlab.freedesktop.org/xorg/xserver/-/commit/d8ec33fe0542141aed1d9016d2ecaf52da944b4b , all X server call xorgGlxCreateVendor themselves, except xf86, which does it when loading the glx extension module.

Should not negatively affect kdrive or Xvfb, and it should fix the:

(II) GLX: Another vendor is already registered for screen 0

in the X server logs.

@stefan11111

Copy link
Copy Markdown
Contributor

@metux When I looked into this some time ago, I also tried fixing the log message by adding a static variable to the function, to ensure it only gets called once. However, that didn't work for xf86. From what gdb said, xf86 calls 2 functions that are at different addrsses, but both are named xorgGlxCreateVendor. Any idea why it's doing that?

Xfbdev did not have such behavior, everything worked as expected there.

@metux metux merged commit ad1d4a2 into X11Libre:master Jun 30, 2026
@metux

metux commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

🤖 Automated review — generated by Claude Code on behalf of @metux. Not a human review.

Verdict: ✅ passed — correct, no blocking findings.

xorgGlxCreateVendor() installs the catch-all GLX vendor and is meant to be called once. Every DDX that uses glamor already calls it from its own init path — hw/kdrive/src/kdrive.c:1137, hw/vfb/InitOutput.c, hw/xfree86/dixmods/glxmodule.c, hw/xquartz/darwin.c, hw/xwin/InitOutput.c — so glamor_egl_screen_init() calling it again was redundant (a second catch-all install, e.g. twice on Xorg + glamor). Dropping the glamor-side call is safe.

  • Re the author's note "not sure if it impacts kdrive": it doesn't — hw/kdrive/src/kdrive.c:1137 calls xorgGlxCreateVendor() itself, so Xephyr/kdrive still registers the vendor independently of glamor.
  • ABI / nvidia: none — the include/glx_extinit.h change is a doc-comment only; the xorgGlxCreateVendor(void) signature is unchanged, and the function is server-internal GLX vendor registration, not driver/blob-facing.
  • Backport: not warranted — this removes a redundant duplicate call (cleanup), not a crash / security / data-corruption fix.

@metux metux added the bot-review-passed Automated bot review found no blocking issues label Jun 30, 2026
@metux

metux commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

@metux When I looked into this some time ago, I also tried fixing the log message by adding a static variable to the function, to ensure it only gets called once. However, that didn't work for xf86. From what gdb said, xf86 calls 2 functions that are at different addrsses, but both are named xorgGlxCreateVendor. Any idea why it's doing that?

uh ? can you please explain in more detail what change you've tried and what happened there ?

@stefan11111

Copy link
Copy Markdown
Contributor

uh ? can you please explain in more detail what change you've tried and what happened there ?

From memory, it was something like this:

diff --git a/Xext/glx/glxext.c b/Xext/glx/glxext.c
index 1ae7a4ffb..fca693929 100644
--- a/Xext/glx/glxext.c
+++ b/Xext/glx/glxext.c
@@ -515,6 +515,12 @@ xorgGlxServerInit(CallbackListPtr *pcbl, void *param, void *ext)
 {
     const ExtensionEntry *extEntry = ext;

+    static Bool called = FALSE;
+    if (called) {
+        return;
+    }
+    called = TRUE;
+
     if (!xorgGlxServerPreInit(extEntry)) {
         return;
     }

This stopped the log message error in Xfbdev, but not in Xorg.
When I looked into it with gdb, it showed that this function was getting called twice in xf86, but that at each call, the function had a different address, and the static called variable was also at 2 addresses, and hence was unset in both function calls.

@metux

metux commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

This stopped the log message error in Xfbdev, but not in Xorg. When I looked into it with gdb, it showed that this function was getting called twice in xf86, but that at each call, the function had a different address, and the static called variable was also at 2 addresses, and hence was unset in both function calls.

Uh, that is strange. Could it somehow happen that this file is compiled twice ?

@metux

metux commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

🤖 Automated review — generated by Claude Code on behalf of @metux. Not a human review.

@stefan11111 @metux — re "xf86 calls two functions at different addresses, both named xorgGlxCreateVendor… could this file be compiled twice?": yes, in effect it is. Here's the mechanism.

Root cause: glxext.c ends up in two separately-dlopen'd Xorg modules

xorgGlxServerInit / xorgGlxCreateVendor live in Xext/glx/glxext.c, which is compiled into the static lib libxserver_glx. On the xfree86 (Xorg) build that archive is pulled into two loadable modules:

  1. extensions/libglx.sohw/xfree86/dixmods/meson.build links it with link_whole: libxserver_glx, so it contains the entire glx archive incl. glxext.c.ocopy #1.
  2. libglamoregl.sohw/xfree86/glamor_egl/meson.build links it with link_with: [glamor, libxserver_glx]. The glamor static lib's glamor_egl.c called xorgGlxCreateVendor(); that undefined reference made the linker pull glxext.c.o out of libxserver_glx into the glamoregl module → copy make the xlibre/master branch the main branch #2.

Xorg dlopens both modules at startup, so you get two independent copies of xorgGlxServerInit/xorgGlxCreateVendor, each with its own file-scope static storage. That's exactly your gdb observation — two addresses, and a static called guard that never trips because each copy has its own called. The function isn't "called twice" so much as two different functions of the same name are each called once.

Why Xfbdev behaved correctly

kdrive Xfbdev is a single monolithic executable: hw/kdrive/fbdev/meson.build links glamor + libxserver_glx directly into the one binary, so glxext.c.o appears exactly once → one copy → your static guard worked. The split of glx and glamor into separate loadable modules is specific to the xfree86/Xorg DDX, which is why only Xorg showed the duplicate.

This PR (#3174) already fixes it

Removing the xorgGlxCreateVendor() call from glamor_egl.c removes the only cross-reference that dragged glxext.c.o into libglamoregl.so. On current master the glamoregl module no longer carries its own glx copy, so the duplicate is gone — and a "call once" static guard in xorgGlxServerInit would now work on Xorg too. So the change you were unsure about ("not sure if it impacts kdrive") turns out to be the fix for the behavior you described, not just the duplicate-log-line cosmetic.

Verifying / optional follow-up

@cepelinas9000

Copy link
Copy Markdown
Contributor Author

This stopped the log message error in Xfbdev, but not in Xorg. When I looked into it with gdb, it showed that this function was getting called twice in xf86, but that at each call, the function had a different address, and the static called variable was also at 2 addresses, and hence was unset in both function calls.

Uh, that is strange. Could it somehow happen that this file is compiled twice ?

We need to untwist this (@metux please do not release new version) - when not repeating xorgGlxCreateVendor() the propertary nvidia driver with amd gpu worked correctly. But on other system with two nvidia cards using modesetting it stopped working.

These calls look like this with my patch :

(gdb) b xorgGlxServerInit                                                                                                                                                                     
Function "xorgGlxServerInit" not defined.                                                                                                                                                     
Make breakpoint pending on future shared library load? (y or [n]) y                                                                                                                           
Breakpoint 1 (xorgGlxServerInit) pending.                                                                                                                                                     
(gdb) b egl_screen_probe                                                                                                                                                                      
Function "egl_screen_probe" not defined.                                                                                                                                                      
Make breakpoint pending on future shared library load? (y or [n]) y                                                                                                                           
Breakpoint 2 (egl_screen_probe) pending.                            

Breakpoint 1.3, xorgGlxServerInit (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, param=0x0, ext=0x555557c5ede0) at ../xlibre-server-9999/Xext/glx/glxext.c:515
515     {                                                                                      
(gdb) bt                                                                                       
#0  xorgGlxServerInit (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, param=0x0, ext=0x555557c5ede0) at ../xlibre-server-9999/Xext/glx/glxext.c:515
#1  0x00005555555b135c in _CallCallbacks (pcbl=pcbl@entry=0x5555557915c0 <vndInitCallbackListPtr>, call_data=call_data@entry=0x555557c5ede0) at ../xlibre-server-9999/dix/dixutils.c:692
#2  0x00005555556abf8b in CallCallbacks (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, call_data=0x555557c5ede0) at ../xlibre-server-9999/include/callback.h:79
#3  GlxExtensionInit () at ../xlibre-server-9999/Xext/glx/vndext.c:244
#4  0x0000555555571a2d in InitExtensions (argc=argc@entry=2, argv=argv@entry=0x7fffffffda68) at ../xlibre-server-9999/mi/miinitext.c:264
#5  0x00005555555aff55 in dix_main (argc=2, argv=0x7fffffffda68, envp=<optimized out>) at ../xlibre-server-9999/dix/main.c:199
#6  0x00007ffff75223fb in ?? () from /usr/lib64/libc.so.6    
#7  0x00007ffff75224ab in __libc_start_main () from /usr/lib64/libc.so.6
#8  0x0000555555571595 in _start ()     
(gdb) c
Continuing.                                                                                    
                                                                                               
Breakpoint 1.4, xorgGlxServerInit (pcbl=<optimized out>, param=<optimized out>, ext=<optimized out>) at ../xlibre-server-9999/Xext/glx/glxext.c:527
527         DIX_FOR_EACH_SCREEN({
(gdb) bt
#0  xorgGlxServerInit (pcbl=<optimized out>, param=<optimized out>, ext=<optimized out>) at ../xlibre-server-9999/Xext/glx/glxext.c:527
#1  xorgGlxServerInit (pcbl=<optimized out>, param=<optimized out>, ext=<optimized out>) at ../xlibre-server-9999/Xext/glx/glxext.c:514
#2  0x00005555555b135c in _CallCallbacks (pcbl=pcbl@entry=0x5555557915c0 <vndInitCallbackListPtr>, call_data=call_data@entry=0x555557c5ede0) at ../xlibre-server-9999/dix/dixutils.c:692
#3  0x00005555556abf8b in CallCallbacks (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, call_data=0x555557c5ede0) at ../xlibre-server-9999/include/callback.h:79
#4  GlxExtensionInit () at ../xlibre-server-9999/Xext/glx/vndext.c:244
#5  0x0000555555571a2d in InitExtensions (argc=argc@entry=2, argv=argv@entry=0x7fffffffda68) at ../xlibre-server-9999/mi/miinitext.c:264
#6  0x00005555555aff55 in dix_main (argc=2, argv=0x7fffffffda68, envp=<optimized out>) at ../xlibre-server-9999/dix/main.c:199
#7  0x00007ffff75223fb in ?? () from /usr/lib64/libc.so.6
#8  0x00007ffff75224ab in __libc_start_main () from /usr/lib64/libc.so.6
#9  0x0000555555571595 in _start ()
(gdb) c

After reverting patch these functions called twice and between egl_screen_probe called.

Breakpoint 2.1, xorgGlxServerInit (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, param=0x0, ext=0x555557c14eb0) at ../xlibre-server-9999/Xext/glx/glxext.c:515
515     {                                                                                      
(gdb) bt                                                                                                                                                                                      
#0  xorgGlxServerInit (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, param=0x0, ext=0x555557c14eb0) at ../xlibre-server-9999/Xext/glx/glxext.c:515                                      
#1  0x00005555555b135c in _CallCallbacks (pcbl=pcbl@entry=0x5555557915c0 <vndInitCallbackListPtr>, call_data=call_data@entry=0x555557c14eb0) at ../xlibre-server-9999/dix/dixutils.c:692
#2  0x00005555556abf8b in CallCallbacks (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, call_data=0x555557c14eb0) at ../xlibre-server-9999/include/callback.h:79
#3  GlxExtensionInit () at ../xlibre-server-9999/Xext/glx/vndext.c:244                                                                                                                        
#4  0x0000555555571a2d in InitExtensions (argc=argc@entry=2, argv=argv@entry=0x7fffffffda68) at ../xlibre-server-9999/mi/miinitext.c:264
#5  0x00005555555aff55 in dix_main (argc=2, argv=0x7fffffffda68, envp=<optimized out>) at ../xlibre-server-9999/dix/main.c:199
#6  0x00007ffff75223fb in ?? () from /usr/lib64/libc.so.6               
#7  0x00007ffff75224ab in __libc_start_main () from /usr/lib64/libc.so.6
#8  0x0000555555571595 in _start ()
(gdb) c
Continuing.

Breakpoint 2.2, xorgGlxServerInit (pcbl=<optimized out>, param=<optimized out>, ext=<optimized out>) at ../xlibre-server-9999/Xext/glx/glxext.c:527
527         DIX_FOR_EACH_SCREEN({
(gdb) bt
#0  xorgGlxServerInit (pcbl=<optimized out>, param=<optimized out>, ext=<optimized out>) at ../xlibre-server-9999/Xext/glx/glxext.c:527
#1  xorgGlxServerInit (pcbl=<optimized out>, param=<optimized out>, ext=<optimized out>) at ../xlibre-server-9999/Xext/glx/glxext.c:514
#2  0x00005555555b135c in _CallCallbacks (pcbl=pcbl@entry=0x5555557915c0 <vndInitCallbackListPtr>, call_data=call_data@entry=0x555557c14eb0) at ../xlibre-server-9999/dix/dixutils.c:692
#3  0x00005555556abf8b in CallCallbacks (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, call_data=0x555557c14eb0) at ../xlibre-server-9999/include/callback.h:79
#4  GlxExtensionInit () at ../xlibre-server-9999/Xext/glx/vndext.c:244
#5  0x0000555555571a2d in InitExtensions (argc=argc@entry=2, argv=argv@entry=0x7fffffffda68) at ../xlibre-server-9999/mi/miinitext.c:264
#6  0x00005555555aff55 in dix_main (argc=2, argv=0x7fffffffda68, envp=<optimized out>) at ../xlibre-server-9999/dix/main.c:199
#7  0x00007ffff75223fb in ?? () from /usr/lib64/libc.so.6
#8  0x00007ffff75224ab in __libc_start_main () from /usr/lib64/libc.so.6
#9  0x0000555555571595 in _start ()
(gdb) c
Continuing.
Breakpoint 3, egl_screen_probe (pScreen=0x555555b18710) at ../xlibre-server-9999/glamor/glamor_glx_provider.c:379
379     {
(gdb) bt
#0  egl_screen_probe (pScreen=0x555555b18710) at ../xlibre-server-9999/glamor/glamor_glx_provider.c:379
#1  0x00007ffff6fab8df in xorgGlxServerInit (pcbl=<optimized out>, param=<optimized out>, ext=<optimized out>) at ../xlibre-server-9999/Xext/glx/glxext.c:527
#2  xorgGlxServerInit (pcbl=<optimized out>, param=<optimized out>, ext=<optimized out>) at ../xlibre-server-9999/Xext/glx/glxext.c:514
#3  0x00005555555b135c in _CallCallbacks (pcbl=pcbl@entry=0x5555557915c0 <vndInitCallbackListPtr>, call_data=call_data@entry=0x555557c14eb0) at ../xlibre-server-9999/dix/dixutils.c:692
#4  0x00005555556abf8b in CallCallbacks (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, call_data=0x555557c14eb0) at ../xlibre-server-9999/include/callback.h:79
#5  GlxExtensionInit () at ../xlibre-server-9999/Xext/glx/vndext.c:244
#6  0x0000555555571a2d in InitExtensions (argc=argc@entry=2, argv=argv@entry=0x7fffffffda68) at ../xlibre-server-9999/mi/miinitext.c:264
#7  0x00005555555aff55 in dix_main (argc=2, argv=0x7fffffffda68, envp=<optimized out>) at ../xlibre-server-9999/dix/main.c:199
#8  0x00007ffff75223fb in ?? () from /usr/lib64/libc.so.6
#9  0x00007ffff75224ab in __libc_start_main () from /usr/lib64/libc.so.6
#10 0x0000555555571595 in _start ()
(gdb) c
Continuing.
Breakpoint 2.3, xorgGlxServerInit (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, param=0x0, ext=0x555557c14eb0) at ../xlibre-server-9999/Xext/glx/glxext.c:515                                
515     {                                                                                                                                                                                     
(gdb) bt                                                                                                                                                                                      
#0  xorgGlxServerInit (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, param=0x0, ext=0x555557c14eb0) at ../xlibre-server-9999/Xext/glx/glxext.c:515
#1  0x00005555555b135c in _CallCallbacks (pcbl=pcbl@entry=0x5555557915c0 <vndInitCallbackListPtr>, call_data=call_data@entry=0x555557c14eb0) at ../xlibre-server-9999/dix/dixutils.c:692
#2  0x00005555556abf8b in CallCallbacks (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, call_data=0x555557c14eb0) at ../xlibre-server-9999/include/callback.h:79
#3  GlxExtensionInit () at ../xlibre-server-9999/Xext/glx/vndext.c:244
#4  0x0000555555571a2d in InitExtensions (argc=argc@entry=2, argv=argv@entry=0x7fffffffda68) at ../xlibre-server-9999/mi/miinitext.c:264
#5  0x00005555555aff55 in dix_main (argc=2, argv=0x7fffffffda68, envp=<optimized out>) at ../xlibre-server-9999/dix/main.c:199
#6  0x00007ffff75223fb in ?? () from /usr/lib64/libc.so.6
#7  0x00007ffff75224ab in __libc_start_main () from /usr/lib64/libc.so.6
#8  0x0000555555571595 in _start ()
(gdb) c
Continuing.

Breakpoint 2.4, xorgGlxServerInit (pcbl=<optimized out>, param=<optimized out>, ext=<optimized out>) at ../xlibre-server-9999/Xext/glx/glxext.c:527
527         DIX_FOR_EACH_SCREEN({
(gdb) bt
#0  xorgGlxServerInit (pcbl=<optimized out>, param=<optimized out>, ext=<optimized out>) at ../xlibre-server-9999/Xext/glx/glxext.c:527
#1  xorgGlxServerInit (pcbl=<optimized out>, param=<optimized out>, ext=<optimized out>) at ../xlibre-server-9999/Xext/glx/glxext.c:514
#2  0x00005555555b135c in _CallCallbacks (pcbl=pcbl@entry=0x5555557915c0 <vndInitCallbackListPtr>, call_data=call_data@entry=0x555557c14eb0) at ../xlibre-server-9999/dix/dixutils.c:692
#3  0x00005555556abf8b in CallCallbacks (pcbl=0x5555557915c0 <vndInitCallbackListPtr>, call_data=0x555557c14eb0) at ../xlibre-server-9999/include/callback.h:79
#4  GlxExtensionInit () at ../xlibre-server-9999/Xext/glx/vndext.c:244
#5  0x0000555555571a2d in InitExtensions (argc=argc@entry=2, argv=argv@entry=0x7fffffffda68) at ../xlibre-server-9999/mi/miinitext.c:264
#6  0x00005555555aff55 in dix_main (argc=2, argv=0x7fffffffda68, envp=<optimized out>) at ../xlibre-server-9999/dix/main.c:199
#7  0x00007ffff75223fb in ?? () from /usr/lib64/libc.so.6
#8  0x00007ffff75224ab in __libc_start_main () from /usr/lib64/libc.so.6
#9  0x0000555555571595 in _start ()
(gdb) c

Didn't investigate deep , it looks xorgGlxServerInit have some sort not trivial interaction with callcallbacks

@cepelinas9000

Copy link
Copy Markdown
Contributor Author

@stefan11111 This is linking problem?

Breakpoint 1, glamor_egl_screen_init (screen=0x555555b18770, glamor_ctx=0x555555b1ee58) at ../xlibre-server-9999/glamor/glamor_egl.c:1692

1740        if (!vendor_initialized) {
(gdb) 
1741            GlxPushProvider(&glamor_provider);
(gdb) p __glXProviderStack
$1 = (__GLXprovider *) 0x7ffff7327090 <__glXDRI2Provider>
(gdb) info symbol __glXProviderStack
__glXDRI2Provider in section .data of /usr/lib64/xorg/modules/xlibre-25/extensions/libglx.so
(gdb) s
GlxPushProvider (provider=0x7ffff6feb160 <glamor_provider>) at ../xlibre-server-9999/Xext/glx/glxext.c:284
284     {
(gdb) p __glXProviderStack
$2 = (__GLXprovider *) 0x7ffff6feb650 <__glXDRISWRastProvider>
(gdb) info symbol __glXProviderStack
__glXDRISWRastProvider in section .data of /usr/lib64/xorg/modules/xlibre-25/libglamoregl.so

notice how info symbol __glXProviderStack point in different files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot-review-passed Automated bot review found no blocking issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants