diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 5f7c54090b..b9fe24f40a 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -116,7 +116,7 @@ set_active(bool active) { //////////////////////////////////////////////////////////////////// INLINE bool GraphicsStateGuardian:: is_active() const { - return _active; + return _active && _is_valid; } //////////////////////////////////////////////////////////////////// @@ -539,6 +539,19 @@ mark_new() { _needs_reset = true; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::is_valid +// Access: Public +// Description: Returns true if the GSG has been correctly +// initialized within a graphics context, false if there +// has been some problem or it hasn't been initialized +// yet. +//////////////////////////////////////////////////////////////////// +INLINE bool GraphicsStateGuardian:: +is_valid() const { + return _is_valid; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::modify_state // Access: Public diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 08291a491a..8a4a6750c8 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -105,6 +105,7 @@ GraphicsStateGuardian(const FrameBufferProperties &properties, _current_display_region = (DisplayRegion*)0L; _current_lens = (Lens *)NULL; _needs_reset = true; + _is_valid = false; _closing_gsg = false; _active = true; _prepared_objects = new PreparedGraphicsObjects; @@ -207,6 +208,7 @@ get_supported_geom_rendering() const { void GraphicsStateGuardian:: reset() { _needs_reset = false; + _is_valid = false; _display_region_stack_level = 0; _frame_buffer_stack_level = 0; @@ -261,6 +263,8 @@ reset() { _needs_tex_gen = false; _tex_gen_modifies_mat = false; _last_max_stage_index = 0; + + _is_valid = true; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 2bc03746d4..1f2f6c4aa7 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -190,6 +190,7 @@ public: INLINE bool reset_if_new(); INLINE void mark_new(); virtual void reset(); + INLINE bool is_valid() const; INLINE void modify_state(const RenderState *state); INLINE void set_state(const RenderState *state); @@ -362,6 +363,7 @@ protected: int _last_max_stage_index; bool _needs_reset; + bool _is_valid; bool _closing_gsg; bool _active; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.I b/panda/src/glstuff/glGraphicsStateGuardian_src.I index d8a5529b60..94334f9bce 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.I +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.I @@ -82,6 +82,59 @@ report_my_errors(int line, const char *source_file) { #endif } +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::get_gl_vendor +// Access: Public +// Description: Returns the GL vendor string reported by the driver. +//////////////////////////////////////////////////////////////////// +INLINE const string &CLP(GraphicsStateGuardian):: +get_gl_vendor() const { + return _gl_vendor; +} + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::get_gl_renderer +// Access: Public +// Description: Returns the GL renderer string reported by the driver. +//////////////////////////////////////////////////////////////////// +INLINE const string &CLP(GraphicsStateGuardian):: +get_gl_renderer() const { + return _gl_renderer; +} + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::get_gl_version_major +// Access: Public +// Description: Returns the major part of the reported GL version +// number. +//////////////////////////////////////////////////////////////////// +INLINE int CLP(GraphicsStateGuardian):: +get_gl_version_major() const { + return _gl_version_major; +} + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::get_gl_version_minor +// Access: Public +// Description: Returns the minor part of the reported GL version +// number. +//////////////////////////////////////////////////////////////////// +INLINE int CLP(GraphicsStateGuardian):: +get_gl_version_minor() const { + return _gl_version_minor; +} + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::get_gl_version_release +// Access: Public +// Description: Returns the release part of the reported GL version +// number. +//////////////////////////////////////////////////////////////////// +INLINE int CLP(GraphicsStateGuardian):: +get_gl_version_release() const { + return _gl_version_release; +} + //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::enable_multisample_antialias // Access: Protected diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 269f242ab0..dd623ddb48 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -304,7 +304,7 @@ reset() { GraphicsStateGuardian::reset(); // Output the vendor and version strings. - get_gl_version(); + query_gl_version(); // Save the extensions tokens. save_extensions((const char *)GLP(GetString)(GL_EXTENSIONS)); @@ -2932,31 +2932,37 @@ report_errors_loop(int line, const char *source_file, GLenum error_code, // Function: GLGraphicsStateGuardian::show_gl_string // Access: Protected // Description: Outputs the result of glGetString() on the indicated -// tag. +// tag. The output string is returned. //////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: +string CLP(GraphicsStateGuardian):: show_gl_string(const string &name, GLenum id) { - if (GLCAT.is_debug()) { - const GLubyte *text = GLP(GetString)(id); - if (text == (const GLubyte *)NULL) { + string result; + + const GLubyte *text = GLP(GetString)(id); + + if (text == (const GLubyte *)NULL) { + GLCAT.warning() + << "Unable to query " << name << "\n"; + } else { + result = (const char *)text; + if (GLCAT.is_debug()) { GLCAT.debug() - << "Unable to query " << name << "\n"; - } else { - GLCAT.debug() - << name << " = " << (const char *)text << "\n"; + << name << " = " << result << "\n"; } } + + return result; } //////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::get_gl_version +// Function: GLGraphicsStateGuardian::query_gl_version // Access: Protected, Virtual // Description: Queries the runtime version of OpenGL in use. //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: -get_gl_version() { - show_gl_string("GL_VENDOR", GL_VENDOR); - show_gl_string("GL_RENDERER", GL_RENDERER); +query_gl_version() { + _gl_vendor = show_gl_string("GL_VENDOR", GL_VENDOR); + _gl_renderer = show_gl_string("GL_RENDERER", GL_RENDERER); _gl_version_major = 0; _gl_version_minor = 0; @@ -4360,6 +4366,9 @@ finish_modify_state() { GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); got_point_sprites = true; break; + + case TexGenAttrib::M_unused: + break; } } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 40a44559bd..578e2c940f 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -158,11 +158,17 @@ public: INLINE static bool report_errors(int line, const char *source_file); INLINE void report_my_errors(int line, const char *source_file); + INLINE const string &get_gl_vendor() const; + INLINE const string &get_gl_renderer() const; + INLINE int get_gl_version_major() const; + INLINE int get_gl_version_minor() const; + INLINE int get_gl_version_release() const; + protected: static bool report_errors_loop(int line, const char *source_file, GLenum error_code, int &error_count); - void show_gl_string(const string &name, GLenum id); - virtual void get_gl_version(); + string show_gl_string(const string &name, GLenum id); + virtual void query_gl_version(); void save_extensions(const char *extensions); virtual void get_extra_extensions(); void report_extensions() const; @@ -310,6 +316,8 @@ protected: int _error_count; + string _gl_vendor; + string _gl_renderer; int _gl_version_major, _gl_version_minor, _gl_version_release; pset _extensions; diff --git a/panda/src/glxdisplay/glxGraphicsPipe.cxx b/panda/src/glxdisplay/glxGraphicsPipe.cxx index 59f577a378..a2020d8d86 100644 --- a/panda/src/glxdisplay/glxGraphicsPipe.cxx +++ b/panda/src/glxdisplay/glxGraphicsPipe.cxx @@ -191,51 +191,26 @@ make_gsg(const FrameBufferProperties &properties, share_context = share_gsg->_context; } - int frame_buffer_mode = properties.get_frame_buffer_mode(); - bool hardware = ((frame_buffer_mode & FrameBufferProperties::FM_hardware) != 0); - bool software = ((frame_buffer_mode & FrameBufferProperties::FM_software) != 0); - // If the user specified neither hardware nor software frame buffer, - // he gets either one. - if (!hardware && !software) { - hardware = true; - software = true; - } - // There's no interface in GLX to query whether we have a software // or a hardware rendering context. Fortunately, there seems to be // only one likely software GLX context, and that's Mesa; we will // assume that any Mesa GLX context is software-based, and any other // context is hardware-based. - // To determine whether we are using Mesa, we should strictly create - // a GL context, bind it to a window, and then examine the - // GL_RENDERER string, but as a cheesy shortcut to all of that hard - // work, we'll just check the X server's GLX_VERSION string to see - // if it contains "Mesa". + // Unforunately, to determine whether we are using Mesa, we need to + // create a GL context, bind it to a window, and then examine the + // GL_RENDERER string to see if it contains "Mesa". So we must + // create the GSG and its window first, and wait until the GSG has + // been reset, before we can ask this question. Therefore we don't + // deal with hardware/software at this point, but rather in + // glxGraphicsStateGuardian::reset(). + + // We do, however, need to determine ahead of time whether the user + // would prefer a hardware or software context. + int frame_buffer_mode = properties.get_frame_buffer_mode(); + int want_hardware = (frame_buffer_mode & (FrameBufferProperties::FM_hardware | + FrameBufferProperties::FM_software)); - const char *glx_version = glXQueryServerString(_display, _screen, GLX_VERSION); - if (glx_version != NULL) { - if (strstr(glx_version, "Mesa") != NULL) { - // It's Mesa, therefore probably a software context. - if (!software) { - glxdisplay_cat.error() - << "Using GLX version " << glx_version << "; it is probably a software renderer.\n"; - glxdisplay_cat.error() - << "To allow use of this display add FM_software to your frame buffer mode.\n"; - return NULL; - } - } else { - // It's some other server, therefore probably a hardware context. - if (!hardware) { - glxdisplay_cat.error() - << "Using GLX version " << glx_version << "; it is probably hardware-accelerated.\n"; - glxdisplay_cat.error() - << "To allow use of this display add FM_hardware to your frame buffer mode.\n"; - return NULL; - } - } - } - FrameBufferProperties new_properties = properties; GLXContext context = NULL; XVisualInfo *visual = NULL; @@ -278,13 +253,13 @@ make_gsg(const FrameBufferProperties &properties, // Now we can make a GSG. PT(glxGraphicsStateGuardian) gsg = - new glxGraphicsStateGuardian(new_properties, share_gsg, context, - visual, _display, _screen, fbconfig); + new glxGraphicsStateGuardian(new_properties, share_gsg, want_hardware, + context, visual, _display, _screen, fbconfig); #else PT(glxGraphicsStateGuardian) gsg = - new glxGraphicsStateGuardian(new_properties, share_gsg, context, - visual, _display, _screen); + new glxGraphicsStateGuardian(new_properties, share_gsg, want_hardware, + context, visual, _display, _screen); #endif // HAVE_GLXFBCONFIG return gsg.p(); diff --git a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx b/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx index e5d459454d..408a0d30b4 100644 --- a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx +++ b/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx @@ -33,6 +33,7 @@ TypeHandle glxGraphicsStateGuardian::_type_handle; glxGraphicsStateGuardian:: glxGraphicsStateGuardian(const FrameBufferProperties &properties, glxGraphicsStateGuardian *share_with, + int want_hardware, GLXContext context, XVisualInfo *visual, Display *display, int screen #ifdef HAVE_GLXFBCONFIG @@ -40,6 +41,7 @@ glxGraphicsStateGuardian(const FrameBufferProperties &properties, #endif // HAVE_GLXFBCONFIG ) : GLGraphicsStateGuardian(properties), + _want_hardware(want_hardware), _context(context), _visual(visual), _display(display), @@ -102,6 +104,51 @@ reset() { // that supports it. _glXSwapIntervalSGI(sync_video ? 1 : 0); } + + // Finally, check that the context is the right kind of context: + // hardware or software. This really means examining the + // _gl_renderer string for "Mesa" (see the comment in + // glxGraphicsPipe). + + bool hardware = ((_want_hardware & FrameBufferProperties::FM_hardware) != 0); + bool software = ((_want_hardware & FrameBufferProperties::FM_software) != 0); + // If the user specified neither hardware nor software frame buffer, + // he gets either one. + if (!hardware && !software) { + hardware = true; + software = true; + } + + FrameBufferProperties properties = get_properties(); + int frame_buffer_mode = properties.get_frame_buffer_mode(); + + if (_gl_renderer.find("Mesa") != string::npos) { + // It's Mesa, therefore probably a software context. + if (!software) { + glxdisplay_cat.error() + << "Using GL renderer " << _gl_renderer << "; it is probably a software renderer.\n"; + glxdisplay_cat.error() + << "To allow use of this display add FM_software to your frame buffer mode.\n"; + _is_valid = false; + } + frame_buffer_mode = (frame_buffer_mode | FrameBufferProperties::FM_software) & ~FrameBufferProperties::FM_hardware; + + } else { + // It's some other renderer, therefore probably a hardware context. + if (!hardware) { + glxdisplay_cat.error() + << "Using GL renderer " << _gl_renderer << "; it is probably hardware-accelerated.\n"; + glxdisplay_cat.error() + << "To allow use of this display add FM_hardware to your frame buffer mode.\n"; + _is_valid = false; + } + frame_buffer_mode = (frame_buffer_mode | FrameBufferProperties::FM_hardware) & ~FrameBufferProperties::FM_software; + } + + // Update the GSG's record to indicate whether we believe it is a + // hardware or software renderer. + properties.set_frame_buffer_mode(frame_buffer_mode); + set_properties(properties); } //////////////////////////////////////////////////////////////////// @@ -122,13 +169,13 @@ glx_is_at_least_version(int major_version, int minor_version) const { } //////////////////////////////////////////////////////////////////// -// Function: glxGraphicsStateGuardian::get_gl_version +// Function: glxGraphicsStateGuardian::query_gl_version // Access: Protected, Virtual // Description: Queries the runtime version of OpenGL in use. //////////////////////////////////////////////////////////////////// void glxGraphicsStateGuardian:: -get_gl_version() { - GLGraphicsStateGuardian::get_gl_version(); +query_gl_version() { + GLGraphicsStateGuardian::query_gl_version(); show_glx_client_string("GLX_VENDOR", GLX_VENDOR); show_glx_client_string("GLX_VERSION", GLX_VERSION); diff --git a/panda/src/glxdisplay/glxGraphicsStateGuardian.h b/panda/src/glxdisplay/glxGraphicsStateGuardian.h index 5ad3e39400..ddcd4d4fbe 100644 --- a/panda/src/glxdisplay/glxGraphicsStateGuardian.h +++ b/panda/src/glxdisplay/glxGraphicsStateGuardian.h @@ -56,18 +56,15 @@ typedef int (* PFNGLXSWAPINTERVALSGIPROC) (int interval); //////////////////////////////////////////////////////////////////// class glxGraphicsStateGuardian : public GLGraphicsStateGuardian { public: + glxGraphicsStateGuardian(const FrameBufferProperties &properties, + glxGraphicsStateGuardian *share_with, + int want_hardware, + GLXContext context, XVisualInfo *visual, + Display *display, int screen #ifdef HAVE_GLXFBCONFIG - glxGraphicsStateGuardian(const FrameBufferProperties &properties, - glxGraphicsStateGuardian *share_with, - GLXContext context, XVisualInfo *visual, - Display *display, int screen, - GLXFBConfig fbconfig); -#else - glxGraphicsStateGuardian(const FrameBufferProperties &properties, - glxGraphicsStateGuardian *share_with, - GLXContext context, XVisualInfo *visual, - Display *display, int screen); + , GLXFBConfig fbconfig #endif // HAVE_GLXFBCONFIG + ); virtual ~glxGraphicsStateGuardian(); @@ -75,6 +72,7 @@ public: bool glx_is_at_least_version(int major_version, int minor_version) const; + int _want_hardware; GLXContext _context; XVisualInfo *_visual; Display *_display; @@ -89,7 +87,7 @@ public: PFNGLXSWAPINTERVALSGIPROC _glXSwapIntervalSGI; protected: - virtual void get_gl_version(); + 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 ec45c8a2fd..bc3dfa8b74 100644 --- a/panda/src/glxdisplay/glxGraphicsWindow.cxx +++ b/panda/src/glxdisplay/glxGraphicsWindow.cxx @@ -122,7 +122,7 @@ make_context() { // reset() requires having a current context.) glxgsg->reset_if_new(); - return true; + return glxgsg->is_valid(); } ////////////////////////////////////////////////////////////////////