Explorar el Código

fix multithreading issues with X

David Rose hace 19 años
padre
commit
91b341dafb

+ 1 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.I

@@ -73,7 +73,7 @@ report_errors(int line, const char *source_file) {
 INLINE void CLP(GraphicsStateGuardian)::
 report_my_errors(int line, const char *source_file) {
 #ifndef NDEBUG
-  GLenum error_code = GLP(GetError)();
+  GLenum error_code = gl_get_error();
   if (error_code != GL_NO_ERROR) {
     if (!report_errors_loop(line, source_file, error_code, _error_count)) {
       panic_deactivate();

+ 26 - 8
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1524,14 +1524,11 @@ end_frame(Thread *current_thread) {
     }
   }
 
-  {
-    PStatTimer timer(_flush_pcollector);
-    // Calling glFlush() at the end of the frame is particularly
-    // necessary if this is a single-buffered visual, so that the frame
-    // will be finished drawing before we return to the application.
-    // It's not clear what effect this has on our total frame time.
-    GLP(Flush)();
-  }
+  // Calling glFlush() at the end of the frame is particularly
+  // necessary if this is a single-buffered visual, so that the frame
+  // will be finished drawing before we return to the application.
+  // It's not clear what effect this has on our total frame time.
+  gl_flush();
 
   report_my_gl_errors();
 }
@@ -4188,6 +4185,27 @@ draw_immediate_composite_primitives(const GeomPrimitivePipelineReader *reader, G
 }
 #endif  // SUPPORT_IMMEDIATE_MODE
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::gl_flush
+//       Access: Protected, Virtual
+//  Description: Calls glFlush().
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+gl_flush() const {
+  PStatTimer timer(_flush_pcollector);
+  GLP(Flush)();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::gl_get_error
+//       Access: Protected, Virtual
+//  Description: Returns the result of glGetError().
+////////////////////////////////////////////////////////////////////
+GLenum CLP(GraphicsStateGuardian)::
+gl_get_error() const {
+  return GLP(GetError)();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::report_errors_loop
 //       Access: Protected, Static

+ 3 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -208,6 +208,9 @@ protected:
   void do_issue_tex_gen();
   void do_issue_tex_matrix();
 
+  virtual void gl_flush() const;
+  virtual GLenum gl_get_error() const;
+
   static bool report_errors_loop(int line, const char *source_file,
                                  GLenum error_code, int &error_count);
   static string get_error_string(GLenum error_code);

+ 2 - 0
panda/src/glxdisplay/glxGraphicsPipe.cxx

@@ -30,6 +30,8 @@ bool glxGraphicsPipe::_error_handlers_installed = false;
 glxGraphicsPipe::ErrorHandlerFunc *glxGraphicsPipe::_prev_error_handler;
 glxGraphicsPipe::IOErrorHandlerFunc *glxGraphicsPipe::_prev_io_error_handler;
 
+Mutex glxGraphicsPipe::_x_mutex;
+
 ////////////////////////////////////////////////////////////////////
 //     Function: glxGraphicsPipe::Constructor
 //       Access: Public

+ 6 - 0
panda/src/glxdisplay/glxGraphicsPipe.h

@@ -23,6 +23,7 @@
 #include "graphicsWindow.h"
 #include "graphicsPipe.h"
 #include "glgsg.h"
+#include "pmutex.h"
 
 class FrameBufferProperties;
 
@@ -160,6 +161,11 @@ private:
   static ErrorHandlerFunc *_prev_error_handler;
   static IOErrorHandlerFunc *_prev_io_error_handler;
 
+public:
+  // This Mutex protects any X library calls, which all have to be
+  // single-threaded.  In particular, it protects glXMakeCurrent().
+  static Mutex _x_mutex;
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 24 - 0
panda/src/glxdisplay/glxGraphicsStateGuardian.cxx

@@ -183,6 +183,30 @@ glx_is_at_least_version(int major_version, int minor_version) const {
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsStateGuardian::gl_flush
+//       Access: Protected, Virtual
+//  Description: Calls glFlush().
+////////////////////////////////////////////////////////////////////
+void glxGraphicsStateGuardian::
+gl_flush() const {
+  // This call requires synchronization with X.
+  MutexHolder holder(glxGraphicsPipe::_x_mutex);
+  GLGraphicsStateGuardian::gl_flush();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsStateGuardian::gl_get_error
+//       Access: Protected, Virtual
+//  Description: Returns the result of glGetError().
+////////////////////////////////////////////////////////////////////
+GLenum glxGraphicsStateGuardian::
+gl_get_error() const {
+  // This call requires synchronization with X.
+  MutexHolder holder(glxGraphicsPipe::_x_mutex);
+  return GLGraphicsStateGuardian::gl_get_error();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: glxGraphicsStateGuardian::query_gl_version
 //       Access: Protected, Virtual

+ 3 - 0
panda/src/glxdisplay/glxGraphicsStateGuardian.h

@@ -104,6 +104,9 @@ public:
   PFNGLXSWAPINTERVALSGIPROC _glXSwapIntervalSGI;
 
 protected:
+  virtual void gl_flush() const;
+  virtual GLenum gl_get_error() const;
+
   virtual void query_gl_version();
   virtual void get_extra_extensions();
   virtual void *get_extension_func(const char *prefix, const char *name);

+ 7 - 1
panda/src/glxdisplay/glxGraphicsWindow.cxx

@@ -131,7 +131,10 @@ begin_frame(FrameMode mode, Thread *current_thread) {
 
   glxGraphicsStateGuardian *glxgsg;
   DCAST_INTO_R(glxgsg, _gsg, false);
-  glXMakeCurrent(_display, _xwindow, glxgsg->_context);
+  {
+    MutexHolder holder(glxGraphicsPipe::_x_mutex);
+    glXMakeCurrent(_display, _xwindow, glxgsg->_context);
+  }
   
   // Now that we have made the context current to a window, we can
   // reset the GSG state if this is the first time it has been used.
@@ -200,6 +203,7 @@ begin_flip() {
 
     //make_current();
 
+    MutexHolder holder(glxGraphicsPipe::_x_mutex);
     glXSwapBuffers(_display, _xwindow);
   }
 }
@@ -216,6 +220,8 @@ begin_flip() {
 ////////////////////////////////////////////////////////////////////
 void glxGraphicsWindow::
 process_events() {
+  MutexHolder holder(glxGraphicsPipe::_x_mutex);
+
   GraphicsWindow::process_events();
 
   if (_xwindow == (Window)0) {