From 91b341dafb394111fd3ab8485779dcd332c11d12 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 23 May 2006 14:16:38 +0000 Subject: [PATCH] fix multithreading issues with X --- .../src/glstuff/glGraphicsStateGuardian_src.I | 2 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 34 ++++++++++++++----- .../src/glstuff/glGraphicsStateGuardian_src.h | 3 ++ panda/src/glxdisplay/glxGraphicsPipe.cxx | 2 ++ panda/src/glxdisplay/glxGraphicsPipe.h | 6 ++++ .../glxdisplay/glxGraphicsStateGuardian.cxx | 24 +++++++++++++ .../src/glxdisplay/glxGraphicsStateGuardian.h | 3 ++ panda/src/glxdisplay/glxGraphicsWindow.cxx | 8 ++++- 8 files changed, 72 insertions(+), 10 deletions(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.I b/panda/src/glstuff/glGraphicsStateGuardian_src.I index 3b258a2c64..674aa26a20 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.I +++ b/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(); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 55e2da35f8..2a5644fe16 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/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 diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 212d91f2a8..4238a45fee 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/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); diff --git a/panda/src/glxdisplay/glxGraphicsPipe.cxx b/panda/src/glxdisplay/glxGraphicsPipe.cxx index b96d55c09c..b5e809255e 100644 --- a/panda/src/glxdisplay/glxGraphicsPipe.cxx +++ b/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 diff --git a/panda/src/glxdisplay/glxGraphicsPipe.h b/panda/src/glxdisplay/glxGraphicsPipe.h index 2be1b9d335..90f2710601 100644 --- a/panda/src/glxdisplay/glxGraphicsPipe.h +++ b/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; diff --git a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx b/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx index 2133707872..89a5a8c326 100644 --- a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx +++ b/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 diff --git a/panda/src/glxdisplay/glxGraphicsStateGuardian.h b/panda/src/glxdisplay/glxGraphicsStateGuardian.h index 8d237a515d..9c8cd9e028 100644 --- a/panda/src/glxdisplay/glxGraphicsStateGuardian.h +++ b/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); diff --git a/panda/src/glxdisplay/glxGraphicsWindow.cxx b/panda/src/glxdisplay/glxGraphicsWindow.cxx index 2d0af74551..e8d6167806 100644 --- a/panda/src/glxdisplay/glxGraphicsWindow.cxx +++ b/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) {