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

Using shared context in mutliple threads #393

Closed
christian-rauch opened this issue Jul 30, 2018 · 3 comments
Closed

Using shared context in mutliple threads #393

christian-rauch opened this issue Jul 30, 2018 · 3 comments

Comments

@christian-rauch
Copy link
Collaborator

christian-rauch commented Jul 30, 2018

I am trying to use Pangolin (X11+GLX) from multiple threads, i.e. I am creating a window in the main thread and drawing into this window from another thread.

Here is the modified HelloPangolin example, using a thread to draw into the window:

#include <pangolin/pangolin.h>
#include <thread>
#include <pangolin/display/display_internal.h>

void setup() {
    pangolin::CreateWindowAndBind("Main",640,480);
    glEnable(GL_DEPTH_TEST);

    std::cout << "current ctx setup: " << pangolin::GetCurrentContext() << std::endl;
}

void run() {
    std::cout << "current ctx run: " << pangolin::GetCurrentContext() << std::endl;

//    pangolin::BindToContext("Main");    // <- this blocks
    pangolin::FindContext("Main")->MakeCurrent();

    std::cout << "current ctx run: " << pangolin::GetCurrentContext() << std::endl;

    // Define Projection and initial ModelView matrix
    pangolin::OpenGlRenderState s_cam(
        pangolin::ProjectionMatrix(640,480,420,420,320,240,0.2,100),
        pangolin::ModelViewLookAt(-2,2,-2, 0,0,0, pangolin::AxisY)
    );

    // Create Interactive View in window
    pangolin::Handler3D handler(s_cam);
    pangolin::View& d_cam = pangolin::CreateDisplay()
            .SetBounds(0.0, 1.0, 0.0, 1.0, -640.0f/480.0f)
            .SetHandler(&handler);

    while( !pangolin::ShouldQuit() )
    {
        // Clear screen and activate view to render into
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        d_cam.Activate(s_cam);

        // Render OpenGL Cube
        pangolin::glDrawColouredCube();

        // Swap frames and Process Events
        pangolin::FinishFrame();
    }
}

int main( int /*argc*/, char** /*argv*/ )
{
    setup();

    std::thread render_loop;
    render_loop = std::thread(run);
    render_loop.join();

    return 0;
}

Getting the context via pangolin::BindToContext("Main") blocks the execution of run(). pangolin::FindContext("Main")->MakeCurrent() returns the same context, but the window is empty (black). Calling run() outside of a thread correctly draws the cube.

What is the right way to use Pangolin in multiple threads?

Edit: I am getting the empty/black window only on Nvidia cards (with the proprietary driver). It works correctly with Intel GPUs.

@stevenlovegrove
Copy link
Owner

Hmm - I would have expected this code to work.

Looking at the code, it looks like this logic got broke in the recent window refactor.

BindToContext() should be (but isn't) setting the global Pangolin context (https://github.com/stevenlovegrove/Pangolin/blob/master/src/display/display.cpp#L81) to the one found.

If that method blocks, then I have a silly deadlock issue - you can replace the lock with a recursive lock or comment it for a sec.

@christian-rauch
Copy link
Collaborator Author

Unblocking BindToContext and setting context = context_to_bind; behaves like pangolin::FindContext("Main")->MakeCurrent(); (blank window).

When calling MakeCurrent inside run, glXMakeCurrent() will return false.

How is MakeCurrent(glcontext ? glcontext->glcontext : global_gl_context.lock()->glcontext); supposed to behave? In which circumstances is glcontext==NULL? Since global_gl_context is only modified when calling CreateX11WindowAndBind it appeasr to me that even if glcontext==NULL, glXMakeCurrent will be called with the same context,and not a new one.

@christian-rauch
Copy link
Collaborator Author

I assume that context has to be tested against NULL since it is thread local. Creating a new context if context==nullptr fixes the issue:

// change class 'X11GlContext' to store framebuffer configuration 'chosenFbc'
if(context==nullptr) {
    auto newctx = std::make_shared<X11GlContext>(display, glcontext->chosenFbc);
    MakeCurrent(newctx->glcontext);
}
else {
    MakeCurrent(global_gl_context.lock()->glcontext);
}

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

No branches or pull requests

2 participants