title: Loading thread using a second shared OpenGL context
body: <p>My plan was to create a loading thread inside of which I load resources for a game; such as 3D models, shaders, textures, etc. On the main thread I perform all the game logic and rendering. Then, on my loading thread, I create a sf::Context (SFML shared OpenGL context) which is used only for loading.</p>
  
  <p>This is working for loading shaders. However, xserver sometimes crashes when attempting to load models. I have narrowed the crash down to the glBufferData() call. I have checked that there is nothing wrong with the data that I am sending.</p>
  
  <p>Is it possible call glBufferData() from a second thread using a second OpenGL context? If not, why is it possible to load shaders in the second context? If it is possible, what could be going wrong?</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;thread&gt;
  
  #include &lt;GL/glew.h&gt;
  #include &lt;SFML/OpenGL.hpp&gt;
  #include &lt;SFML/Graphics.hpp&gt;
  #include &lt;X11/Xlib.h&gt;
  
  class ResourceLoader
  {
  public:
      void Run()
      {
          sf::Context loadingContext;
          loadingContext.setActive(true);
  
          // Some test data.
          float* testData = new float[3000];
          for (unsigned int i = 0; i &lt; 3000; ++i)
          {
              testData[i] = 0.0f;
          }
  
          // Create lots of VBOs containing our
          // test data.
          for (unsigned int i = 0; i &lt; 1000; ++i)
          {
              // Create VBO.
              GLuint testVBO = 0;
              glGenBuffers(1, &amp;testVBO);
              std::cout &lt;&lt; "Buffer ID: " &lt;&lt; testVBO &lt;&lt; std::endl;
  
              // Bind VBO.
              glBindBuffer(GL_ARRAY_BUFFER, testVBO);
  
              // Crashes on this call!
              glBufferData(
                  GL_ARRAY_BUFFER,
                  sizeof(float) * 3000,
                  &amp;testData[0],
                  GL_STATIC_DRAW
              );
  
              // Unbind VBO.
              glBindBuffer(GL_ARRAY_BUFFER, 0);
  
              // Sleep for a bit.
              std::this_thread::sleep_for(std::chrono::milliseconds(10));
          }
  
          delete[] testData;
      }
  };
  
  int main()
  {
      XInitThreads();
  
      // Create the main window.
      sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window", sf::Style::Default, sf::ContextSettings(32));
      window.setVerticalSyncEnabled(true);
  
      // Make it the active window for OpenGL calls.
      window.setActive();
  
      // Configure the OpenGL viewport to be the same size as the window.
      glViewport(0, 0, window.getSize().x, window.getSize().y);
  
      // Initialize GLEW.
      glewExperimental = GL_TRUE; // OSX fix.
      if (glewInit() != GLEW_OK)
      {
          window.close();
          exit(1); // failure
      }
  
      // Enable Z-buffer reading and writing.
      glEnable(GL_DEPTH_TEST);
      glDepthMask(GL_TRUE);
  
      // Create the resource loader.
      ResourceLoader loader;
  
      // Run the resource loader in a separate thread.
      std::thread loaderThread(&amp;ResourceLoader::Run, &amp;loader);
  
      // Detach the loading thread, allowing it to run
      // in the background.
      loaderThread.detach();
  
      // Game loop.
      while (window.isOpen())
      {
          // Event loop.
          sf::Event event;
          while (window.pollEvent(event))
          {
              if (event.type == sf::Event::Closed)
              {
                  window.close();
              }
          }
  
          // Clear scren.
          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  
          // Switch to SFML's OpenGL state.
          window.pushGLStates();
          {
              // Perform SFML drawing here...
              sf::RectangleShape rect(sf::Vector2f(100.0f, 100.0f));
              rect.setPosition(100.0f, 100.0f);
              rect.setFillColor(sf::Color(255, 255, 255));
              window.draw(rect);
          }
          // Switch back to our game rendering OpenGL state.
          window.popGLStates();
  
          // Perform OpenGL drawing here...
  
  
          // Display the rendered frame.
          window.display();
      }
  
      return 0;
  }
  </code></pre>