GLX context sharing ?

Does anyone have a working example of sharing a GLX rendering context ? I’ve got it working in a single process with 2 (or more) contexts, but I’m trying to use it by 2 different processes.

So, I broke down the canonical glxgears.c, and I’d like one process (called creator) to create the display lists, and another process (called renderer) to display the scene (calling the defined display lists).

As I have it now, the creator does:

    ctx = glXCreateContext(dpy, visinfo, NULL, False);
    ctxid = glXGetContextIDEXT(ctx);

and creates the display lists;
then it communicates the values of ctxid and the display lists to renderer, who does:

    ctx = glXImportContextEXT(dpy, SHARED_contextID);

and then calls the display lists that it has received.

Unfortunately, this doesn’t work: the renderer dies with a GLXBadDrawable error while attempting GLXSwapBuffers.

So, I must be doing something wrong…
Any help greatly appreciated.

Don’t know about Linux, but under Windows it’s illegal to access OpenGL state of a separate process. Don’t do this. I bet the system’s memory manager throws his hands up, too.
Think what malicious programs could do with this! GetCurrent context of another process and render into its windows…

Don’t know about Linux, but under Windows it’s illegal to access OpenGL state of a separate process. Don’t do this.

No, that’s perfectly all right. It’s not direct rendering, but indirect, so it’s all in the X server’s address space, not in the process’s.

And I suppose that’s why these functions exist, in the first place.

Relic is correct. You cannot share contexts across multiple address spaces. I believe the GLX spec speaks directly to this, though I’d have to dig around to find the actual wording.

If you think about it, this makes sense. There is a lot of state, even for indirect rendering, that is client-side. Things like all the vertex array state, the currently active texture unit, etc. are all client-side. If you could some how magically share the contexts, there would be no way to have a call to glVertexPointer in one process do the right thing in another process. With threads that share the same address space, you can.

You cannot share contexts across multiple address spaces. I believe the GLX spec speaks directly to this
This is only for direct contexts. For indirect ones, that’s what glXImportContextEXT() is supposed to do…

From the man page:

glXImportContextEXT creates a GLXContext given the XID of an existing GLXContext. It may be used in place of glXCreateContext, to share another process’s indirect rendering context.

Ah…I see. I guess I learn something new everyday. :wink:

I did some research on this, and it looks like what you’re doing should work. Based on the error you’re getting (and without seeing your code), I can only guess that you’re not making the context current with a valid drawable in the process that’s call glXSwapBuffers. Purely server-side state (e.g., display lists and texture objects) are shared by all processes, but the drawable associated with a context appears to still be per-process data. Hmm…that doesn’t seem right, though.

Is there any chance you could post your modified version of glxgears on the web somewhere?

If I understood well all what you said: you have 2 different windows, one is creating display lists, and the second should render them, isn’t it ?

I don’t know for multi-processes, but here is how I do it for multithreading, hoping that could help you (I might forget some steps):

  1. create your context C1, enabling a shared context C2.
  2. from the main thread, use C1, making it current each time it’s necessary. Create the lists.
  3. from another thread, use C2, making it current each time it’s necessary too. Render the lists.

I think, you should import ‘C2’ from your second process. I also think that you need to share the display too, otherwise you might not be able to share anything at all.

The glx spec that can be found on this site is interresting about sharing context, and explains all what I might have had missed.

Hope this helps you a bit.

PS: did you load properly the glx extension functions ?

I got it to work!

The trick was that both processes must be using the same visualid (part of the XVisinfo structure), so all that was needed (at the end) was to pass this around, together with the context id.

Many thanks to everybody for the ideas!