Bug 47480

Summary: dynamically load libGL when an application requests a GL context
Product: cairo Reporter: Darxus <darxus>
Component: gl backendAssignee: cairo-bugs mailing list <cairo-bugs>
Status: RESOLVED MOVED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: normal    
Priority: medium CC: darxus, nroberts, programmer11180
Version: 1.10.3   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments: cairo-gl: Add a configure option to dlopen libGL

Description Darxus 2012-03-18 13:17:29 UTC
There is a problem where cairo-gl used with an Nvidia proprietary driver causes excessive memory usage, enough that Ubuntu deemed it unusable, and completely removed cairo-gl:  https://bugs.launchpad.net/ubuntu/+source/nvidia-graphics-drivers/+bug/725434

One suggested solution was to get cairo-gl to only load libGL when an application actually requests a GL context:  https://bugs.launchpad.net/ubuntu/+source/nvidia-graphics-drivers/+bug/725434/comments/15

This seems like a good idea in general.

I believe I just confirmed this problem still exists:  https://bugs.launchpad.net/ubuntu/+source/gtk+3.0/+bug/954352/comments/17
Comment 1 Benjamin Otte 2012-03-18 13:35:20 UTC
"Hi, I have a buggy piece of proprietary crap. Could you hack around it by writing a custom linker?"

I do think the correct solution is to ship a libGL for the nvidia drivers that dynamically loads the nvidia libGL when it's actually loads and not to break ld or cairo.

That said, I wouldn't object to splitting Cairo into multiple separate libs, one per lib. But that required too many public symbols that nobody wants to keep stable last I checked.

I do object though to adding lots of dlsym() calls to Cairo. Cairo is not a linker.
Comment 2 Neil Roberts 2012-03-28 05:31:16 UTC
I think this could be a good idea anyway because libGL is a bit of a special case. Having Cairo link directly against libGL is awkward if your application is trying to use libGLESv2 because it provides most of the same symbols as libGL. For example if the application is just trying to use Cairo for the image surface backend and it links directly against libGLES it can end up accidentally using some symbols from libGL depending on the order they are linked in. Mesa starts doing weird things when this happens.

I already hit this problem when trying to use Cogl with GLES2 because Cogl also indirectly depends on Cairo. Cogl now dlopens its GL library depending on the backend to avoid this. That also enables us to choose between the GL and GLES2 backend with a runtime configuration option. Presumably Cairo could also benefit from that seeing as it has both gl and gles surface backends?
Comment 3 Neil Roberts 2012-03-28 11:41:23 UTC
Created attachment 59169 [details] [review]
cairo-gl: Add a configure option to dlopen libGL

I went ahead and implemented a patch to make this a configure option.
Comment 4 Benjamin Otte 2012-03-28 12:09:07 UTC
You are probably aware that this is going to fail at least on Apple and Windows.
Did you test Solaris, BeOS and the other platforms Cairo runs on?
Are you sure this works with LD_LIBRARY_PATH and LD_PRELOAD the way one would expect non-dlopen to work?
Did you ensure that the same things happen when other parts of the application link against a libGL themselves? On Windows, Apple and so on? Did you investigate dlclose() doesn't have unintended side effects (like leaving around stray pointers)?
Did you add tests for this so we don't accidentally break this later?

If I wanted to get really harsh on you about this, I'd look through the bugs we closed when we still dlopen()'d libGL. Or I can just look through ld.so's bugzilla and link some of them for you to fix.

I'm sure neilld.so will be awesome once you're done!
Comment 5 Kristian Høgsberg 2012-03-28 12:16:08 UTC
(In reply to comment #4)
> You are probably aware that this is going to fail at least on Apple and
> Windows.
> Did you test Solaris, BeOS and the other platforms Cairo runs on?
> Are you sure this works with LD_LIBRARY_PATH and LD_PRELOAD the way one would
> expect non-dlopen to work?
> Did you ensure that the same things happen when other parts of the application
> link against a libGL themselves? On Windows, Apple and so on? Did you
> investigate dlclose() doesn't have unintended side effects (like leaving around
> stray pointers)?
> Did you add tests for this so we don't accidentally break this later?
> 
> If I wanted to get really harsh on you about this, I'd look through the bugs we
> closed when we still dlopen()'d libGL. Or I can just look through ld.so's
> bugzilla and link some of them for you to fix.
> 
> I'm sure neilld.so will be awesome once you're done!

Stop talking bullshit like this.  We can just disable this for crippled platforms, there's not need whatsoever to not fix a problem just because AmigaOS doesn't have a certain feature.

And yes, most people don't know this but dlopen does in fact go through the exact same logic as the regular shared linker (LD_LIBRARY_PATH, LD_PRELOAD), because it's fricking designed to be used this way.  This is not rewriting a linker, this is using dlopen in one of the ways it was designed to be used.
Comment 6 Benjamin Otte 2012-03-28 14:01:36 UTC
No, it's not. And the fact that you know that dlopen() looks at certain environment variables doesn't magically make it so either.
The fact that nobody in the real world apart from libGL ever does it could have been a very good indicator that to you that it's not the way it's designed to be used. But well, it looks at env vars, so it must be designed that way.

Now, if we wanted to fix the issues Neil has, we would split the GL using parts of cairo into a separate library and have you link against libcairo-gl.so if you wanted to use GL surfaces. In fact, that's been a long-requested feature, so that we can turn backends on (and also turn them off at will) without hurting source code or people.
But so far, nobody has figured out how to sanely do it without bleeding internal symbols so it hasn't happened. And instead people have brought down this pain again and again.
Comment 7 Neil Roberts 2012-03-29 05:13:18 UTC
I think the portability concern isn't really a major issue because the patch makes it an opt-in configure option which defaults to off. Sure it won't work on Windows and AmigaOS but if someone tried to enable it on those platforms they would know immediately at the configure phase because the configure script errors out if you enable it when libdl wasn't found. With the configure option we can just leave it up to distros to decide if they want it.

The downside of making a separate cairo-gl library would be that it doesn't help for applications that could support either cairo-gles or cairo-gl surfaces. Those applications would have to have a compile-time option to decide which library to link to because linking to both would cause problems when both libGL and libGLES provide conflicting symbols.

For what it's worth, Cogl has been doing it this way for a while now and we haven't had any people complaining about linker issues yet.
Comment 8 Uli Schlachter 2014-07-17 21:57:35 UTC
I learnt about libepox[0] today and asked its author:

<psychon> anholt: hey, would it make sense for cairo to use libepoxy? I thought about it because of https://bugs.freedesktop.org/show_bug.cgi?id=47480
<psychon> anholt: nvidia's libGL dirties lots(?) of memory when it is loaded (at least on x86? I'm not sure), which is why I ask
<anholt> psychon: yeah, it would make a lot of sense, and cairo was one of the major targets I was thinking of when I was building it.  still need to sort out win32, though.

Disclaimer: I have zero clue about GL and I am not involved in cairo-gl. Just wanted to mention this library and perhaps someone shows up and decides to experiment with it.

[0]: https://github.com/anholt/libepoxy
Comment 9 Bryce Harrington 2014-09-22 21:28:03 UTC
Anyone know what'd need to be sorted out for Win32?
Comment 10 GitLab Migration User 2018-08-25 13:47:39 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/cairo/cairo/issues/197.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.