From f1ef8df82098f508c01ce90a952233785b2abb4b Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 18 Feb 2004 15:21:32 +0000 Subject: [PATCH] add GraphicsStateGuardian::panic_deactivate() --- panda/src/display/graphicsEngine.cxx | 2 +- panda/src/display/graphicsStateGuardian.I | 26 ++++ panda/src/display/graphicsStateGuardian.cxx | 22 +++- panda/src/display/graphicsStateGuardian.h | 5 + .../src/glstuff/glGraphicsStateGuardian_src.I | 27 ++++- .../glstuff/glGraphicsStateGuardian_src.cxx | 113 ++++++++++-------- .../src/glstuff/glGraphicsStateGuardian_src.h | 9 +- panda/src/glstuff/glmisc_src.h | 6 + panda/src/gsgbase/graphicsStateGuardianBase.h | 14 ++- 9 files changed, 159 insertions(+), 65 deletions(-) diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index bacbdf4ce4..3199add0fe 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -480,7 +480,7 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist) { Windows::const_iterator wi; for (wi = wlist.begin(); wi != wlist.end(); ++wi) { GraphicsOutput *win = (*wi); - if (win->is_active()) { + if (win->is_active() && win->get_gsg()->is_active()) { if (win->begin_frame()) { win->clear(); diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index efba2687a9..583d4a9b39 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -84,6 +84,32 @@ get_threading_model() const { return _threading_model; } + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::set_active +// Access: Published +// Description: Sets the active flag associated with the +// GraphicsStateGuardian. If the GraphicsStateGuardian +// is marked inactive, nothing is rendered. This is not +// normally turned off unless there is a problem with +// the rendering detected at a low level. +//////////////////////////////////////////////////////////////////// +INLINE void GraphicsStateGuardian:: +set_active(bool active) { + _active = active; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::is_active +// Access: Published +// Description: Returns the active flag associated with the +// GraphicsStateGuardian. +//////////////////////////////////////////////////////////////////// +INLINE bool GraphicsStateGuardian:: +is_active() const { + return _active; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::set_scene // Access: Public diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 2a8ef226a2..8beae2121b 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -34,7 +34,7 @@ #include "light.h" #include "planeNode.h" #include "ambientLight.h" - +#include "throw_event.h" #include "clockObject.h" #include "pStatTimer.h" @@ -77,6 +77,7 @@ GraphicsStateGuardian(const FrameBufferProperties &properties) { _current_lens = (Lens *)NULL; _needs_reset = true; _closing_gsg = false; + _active = true; } //////////////////////////////////////////////////////////////////// @@ -1372,6 +1373,25 @@ close_gsg() { release_all_geoms(); } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::panic_deactivate +// Access: Protected +// Description: This is called internally when it is determined that +// things are just fubar. It temporarily deactivates +// the GSG just so things don't get out of hand, and +// throws an event so the application can deal with this +// if it needs to. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +panic_deactivate() { + if (_active) { + display_cat.error() + << "Deactivating " << get_type() << ".\n"; + set_active(false); + throw_event("panic-deactivate-gsg", this); + } +} + #ifdef DO_PSTATS //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 801986f0ed..c777947585 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -78,6 +78,9 @@ public: INLINE GraphicsEngine *get_engine() const; INLINE const GraphicsThreadingModel &get_threading_model() const; + INLINE void set_active(bool active); + INLINE bool is_active() const; + INLINE void set_scene(SceneSetup *scene_setup); INLINE SceneSetup *get_scene() const; @@ -199,6 +202,7 @@ protected: virtual void free_pointers(); virtual void close_gsg(); + void panic_deactivate(); #ifdef DO_PSTATS // These functions are used to update the active texture memory @@ -269,6 +273,7 @@ protected: bool _needs_reset; bool _closing_gsg; + bool _active; public: // Statistics diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.I b/panda/src/glstuff/glGraphicsStateGuardian_src.I index 6f59b50b3f..3da2da3705 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.I +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.I @@ -22,17 +22,38 @@ // Access: Public, Static // Description: Checks for any outstanding error codes and outputs // them, if found. If NDEBUG is defined, this function -// does nothing. +// does nothing. The return value is true if everything is +// ok, or false if we should shut down. // // This is a static method so it can be called when // there's no gsg pointer around. //////////////////////////////////////////////////////////////////// -INLINE void CLP(GraphicsStateGuardian):: +INLINE bool CLP(GraphicsStateGuardian):: report_errors(int line, const char *source_file) { #ifndef NDEBUG GLenum error_code = GLP(GetError)(); if (error_code != GL_NO_ERROR) { - report_errors_loop(line, source_file, error_code); + int error_count = 0; + return report_errors_loop(line, source_file, error_code, error_count); + } +#endif + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::report_my_errors +// Access: Public +// Description: Like report_errors(), above, but non-static so we can +// throw an event on failure. +//////////////////////////////////////////////////////////////////// +INLINE void CLP(GraphicsStateGuardian):: +report_my_errors(int line, const char *source_file) { +#ifndef NDEBUG + GLenum error_code = GLP(GetError)(); + if (error_code != GL_NO_ERROR) { + if (!report_errors_loop(line, source_file, error_code, _error_count)) { + panic_deactivate(); + } } #endif } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 23ecb865ba..6df9e6caa0 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -239,6 +239,7 @@ CLP(GraphicsStateGuardian):: CLP(GraphicsStateGuardian)(const FrameBufferProperties &properties) : GraphicsStateGuardian(properties) { + _error_count = 0; } //////////////////////////////////////////////////////////////////// @@ -428,8 +429,9 @@ reset() { report_extensions(); _supports_bgr = has_extension("GL_EXT_bgra"); + _error_count = 0; - report_gl_errors(); + report_my_gl_errors(); } @@ -502,7 +504,7 @@ do_clear(const RenderBuffer &buffer) { modify_state(state); GLP(Clear)(mask); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -532,7 +534,7 @@ prepare_display_region() { call_glScissor( x, y, width, height ); call_glViewport( x, y, width, height ); } - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -577,7 +579,7 @@ prepare_lens() { #endif GLP(MatrixMode)(GL_PROJECTION); GLP(LoadMatrixf)(new_projection_mat.get_data()); - report_gl_errors(); + report_my_gl_errors(); return true; } @@ -601,7 +603,7 @@ begin_frame() { return false; } - report_gl_errors(); + report_my_gl_errors(); return true; } @@ -615,7 +617,7 @@ begin_frame() { void CLP(GraphicsStateGuardian):: end_frame() { GraphicsStateGuardian::end_frame(); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -675,7 +677,7 @@ draw_point(GeomPoint *geom, GeomContext *) { } GLP(End)(); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -746,7 +748,7 @@ draw_line(GeomLine *geom, GeomContext *) { } GLP(End)(); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -842,7 +844,7 @@ draw_linestrip(GeomLinestrip *geom, GeomContext *) { } GLP(End)(); } - report_gl_errors(); + report_my_gl_errors(); DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); } @@ -1115,7 +1117,7 @@ draw_sprite(GeomSprite *geom, GeomContext *) { if(alpha && _dithering_enabled) GLP(Enable)(GL_DITHER); - report_gl_errors(); + report_my_gl_errors(); DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); } @@ -1195,7 +1197,7 @@ draw_polygon(GeomPolygon *geom, GeomContext *) { } GLP(End)(); } - report_gl_errors(); + report_my_gl_errors(); DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); } @@ -1269,7 +1271,7 @@ draw_tri(GeomTri *geom, GeomContext *) { } GLP(End)(); - report_gl_errors(); + report_my_gl_errors(); #ifdef DO_PSTATS _draw_primitive_pcollector.stop(); #endif @@ -1345,7 +1347,7 @@ draw_quad(GeomQuad *geom, GeomContext *) { } GLP(End)(); - report_gl_errors(); + report_my_gl_errors(); DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); } @@ -1441,7 +1443,7 @@ draw_tristrip(GeomTristrip *geom, GeomContext *) { } GLP(End)(); } - report_gl_errors(); + report_my_gl_errors(); DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); } @@ -1537,7 +1539,7 @@ draw_trifan(GeomTrifan *geom, GeomContext *) { } GLP(End)(); } - report_gl_errors(); + report_my_gl_errors(); DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); } @@ -1624,7 +1626,7 @@ draw_sphere(GeomSphere *geom, GeomContext *) { } GLUP(DeleteQuadric)(sph); - report_gl_errors(); + report_my_gl_errors(); DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); } @@ -1655,7 +1657,7 @@ prepare_texture(Texture *tex) { // detect this. nassertr(inserted, gtc); - report_gl_errors(); + report_my_gl_errors(); return gtc; } @@ -1682,7 +1684,7 @@ apply_texture(TextureContext *tc) { tc->clear_dirty_flags(); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -1713,7 +1715,7 @@ release_texture(TextureContext *tc) { delete gtc; if (!_closing_gsg) { - report_gl_errors(); + report_my_gl_errors(); } } @@ -1979,7 +1981,7 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) { texture_to_pixel_buffer(tc, pb, dr); pop_frame_buffer(old_fb); - report_gl_errors(); + report_my_gl_errors(); #endif } @@ -2006,7 +2008,7 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, pb->_image = PTA_uchar::empty_array(w * h * pb->get_num_components()); copy_pixel_buffer(pb, dr); } - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2083,7 +2085,7 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { // didn't do it for us. pb->_image = fix_component_ordering(external_format, pb); - report_gl_errors(); + report_my_gl_errors(); return true; } @@ -2141,7 +2143,7 @@ void CLP(GraphicsStateGuardian)::apply_material(const Material *material) { call_glLightModelLocal(material->get_local()); call_glLightModelTwoSide(material->get_twoside()); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2166,7 +2168,7 @@ apply_fog(Fog *fog) { } call_glFogColor(fog->get_color()); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2185,7 +2187,7 @@ issue_transform(const TransformState *transform) { GLP(MatrixMode)(GL_MODELVIEW); GLP(LoadMatrixf)(transform->get_mat().get_data()); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2197,7 +2199,7 @@ void CLP(GraphicsStateGuardian):: issue_tex_matrix(const TexMatrixAttrib *attrib) { GLP(MatrixMode)(GL_TEXTURE); GLP(LoadMatrixf)(attrib->get_mat().get_data()); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2216,7 +2218,7 @@ issue_texture(const TextureAttrib *attrib) { nassertv(tex != (Texture *)NULL); tex->apply(this); } - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2234,7 +2236,7 @@ issue_material(const MaterialAttrib *attrib) { Material empty; apply_material(&empty); } - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2260,7 +2262,7 @@ issue_render_mode(const RenderModeAttrib *attrib) { GLCAT.error() << "Unknown render mode " << (int)mode << endl; } - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2272,7 +2274,7 @@ void CLP(GraphicsStateGuardian):: issue_texture_apply(const TextureApplyAttrib *attrib) { GLint glmode = get_texture_apply_mode_type(attrib->get_mode()); GLP(TexEnvi)(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, glmode); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2294,7 +2296,7 @@ issue_color_write(const ColorWriteAttrib *attrib) { } else { GLP(ColorMask)(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } - report_gl_errors(); + report_my_gl_errors(); } else { // Some implementations don't seem to handle GLP(ColorMask)() very @@ -2320,7 +2322,7 @@ issue_depth_test(const DepthTestAttrib *attrib) { enable_depth_test(true); GLP(DepthFunc)(PANDA_TO_GL_COMPAREFUNC(mode)); } - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2353,7 +2355,7 @@ issue_depth_write(const DepthWriteAttrib *attrib) { } else { GLP(DepthMask)(GL_TRUE); } - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2382,7 +2384,7 @@ issue_cull_face(const CullFaceAttrib *attrib) { << "invalid cull face mode " << (int)mode << endl; break; } - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2400,7 +2402,7 @@ issue_fog(const FogAttrib *attrib) { } else { enable_fog(false); } - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2422,7 +2424,7 @@ issue_depth_offset(const DepthOffsetAttrib *attrib) { enable_polygon_offset(false); } - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2463,7 +2465,7 @@ bind_light(PointLight *light, int light_id) { GLP(Lightf)(id, GL_LINEAR_ATTENUATION, att[1]); GLP(Lightf)(id, GL_QUADRATIC_ATTENUATION, att[2]); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2505,7 +2507,7 @@ bind_light(DirectionalLight *light, int light_id) { GLP(Lightf)(id, GL_LINEAR_ATTENUATION, 0.0f); GLP(Lightf)(id, GL_QUADRATIC_ATTENUATION, 0.0f); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2546,7 +2548,7 @@ bind_light(Spotlight *light, int light_id) { GLP(Lightf)(id, GL_LINEAR_ATTENUATION, att[1]); GLP(Lightf)(id, GL_QUADRATIC_ATTENUATION, att[2]); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2623,14 +2625,17 @@ compute_distance_to(const LPoint3f &point) const { // Access: Protected, Static // Description: The internal implementation of report_errors(). // Don't call this function; use report_errors() -// instead. +// instead. The return value is true if everything is +// ok, or false if we should shut down. //////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -report_errors_loop(int line, const char *source_file, GLenum error_code) { +bool CLP(GraphicsStateGuardian):: +report_errors_loop(int line, const char *source_file, GLenum error_code, + int &error_count) { #ifndef NDEBUG static const int max_gl_errors_reported = 20; - int count = 0; - while ((count < max_gl_errors_reported) && (error_code != GL_NO_ERROR)) { + + while ((error_count < max_gl_errors_reported) && + (error_code != GL_NO_ERROR)) { const GLubyte *error_string = GLUP(ErrorString)(error_code); if (error_string != (const GLubyte *)NULL) { GLCAT.error() @@ -2642,8 +2647,10 @@ report_errors_loop(int line, const char *source_file, GLenum error_code) { << "GL error " << (int)error_code << "\n"; } error_code = GLP(GetError)(); - count++; + error_count++; } + + return (error_code == GL_NO_ERROR); #endif } @@ -2776,7 +2783,7 @@ set_draw_buffer(const RenderBuffer &rb) { default: call_glDrawBuffer(GL_FRONT_AND_BACK); } - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2825,7 +2832,7 @@ set_read_buffer(const RenderBuffer &rb) { default: call_glReadBuffer(GL_FRONT_AND_BACK); } - report_gl_errors(); + report_my_gl_errors(); } @@ -2845,7 +2852,7 @@ bind_texture(TextureContext *tc) { << ")" << endl; #endif GLP(BindTexture)(GL_TEXTURE_2D, gtc->_index); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -2871,7 +2878,7 @@ specify_texture(Texture *tex) { GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, get_texture_filter_type(tex->get_magfilter())); } - report_gl_errors(); + report_my_gl_errors(); } #ifndef NDEBUG @@ -3003,7 +3010,7 @@ apply_texture_immediate(Texture *tex) { } #endif } - report_gl_errors(); + report_my_gl_errors(); return true; } @@ -3014,7 +3021,7 @@ apply_texture_immediate(Texture *tex) { xsize, ysize, pb->get_border(), external_format, type, image); - //report_gl_errors(); + //report_my_gl_errors(); // want to give explict error for texture creation failure GLenum error_code = GLP(GetError)(); if(error_code != GL_NO_ERROR) { @@ -3230,7 +3237,7 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { GLP(PopMatrix)(); pop_display_region(old_dr); - report_gl_errors(); + report_my_gl_errors(); #endif } @@ -3749,7 +3756,7 @@ bind_clip_plane(PlaneNode *plane, int plane_id) { Planed double_plane(LCAST(double, xformed_plane)); GLP(ClipPlane)(id, double_plane.get_data()); - report_gl_errors(); + report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 1d207b5663..f364f9fabe 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -126,11 +126,12 @@ public: void issue_transformed_color(const Colorf &color) const; - INLINE static void report_errors(int line, const char *source_file); + INLINE static bool report_errors(int line, const char *source_file); + INLINE void report_my_errors(int line, const char *source_file); protected: - static void report_errors_loop(int line, const char *source_file, - GLenum error_code); + 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); void save_extensions(const char *extensions); virtual void get_extra_extensions(); @@ -305,6 +306,8 @@ protected: pset _extensions; bool _supports_bgr; + int _error_count; + public: static GraphicsStateGuardian * make_GlGraphicsStateGuardian(const FactoryParams ¶ms); diff --git a/panda/src/glstuff/glmisc_src.h b/panda/src/glstuff/glmisc_src.h index 12aec26143..cb56e24994 100644 --- a/panda/src/glstuff/glmisc_src.h +++ b/panda/src/glstuff/glmisc_src.h @@ -57,3 +57,9 @@ INLINE ostream &operator << (ostream &out, GLenum v) { #else #define report_gl_errors() #endif + +// We have to define this whether NDEBUG is defined or not, to prevent +// syntax errors. Not to worry; the function itself does nothing in +// NDEBUG mode. +#define report_my_gl_errors() \ + report_my_errors(__LINE__, __FILE__) diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 6fe6aca23c..ff7a73df93 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -21,7 +21,7 @@ #include "pandabase.h" -#include "typedReferenceCount.h" +#include "typedWritableReferenceCount.h" #include "luse.h" // A handful of forward references. @@ -92,8 +92,14 @@ class Lens; // double-dispatch of GSG to geoms, transitions, etc. It // lives in a separate class in its own package so we // can avoid circular build dependency problems. +// +// GraphicsStateGuardians are not actually writable to +// bam files, of course, but they may be passed as event +// parameters, so they inherit from +// TypedWritableReferenceCount instead of +// TypedReferenceCount for that convenience. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA GraphicsStateGuardianBase : public TypedReferenceCount { +class EXPCL_PANDA GraphicsStateGuardianBase : public TypedWritableReferenceCount { public: // These functions will be queried by the GeomIssuer to determine if // it should issue normals, texcoords, and/or colors, based on the @@ -203,9 +209,9 @@ PUBLISHED: public: static void init_type() { - TypedReferenceCount::init_type(); + TypedWritableReferenceCount::init_type(); register_type(_type_handle, "GraphicsStateGuardianBase", - TypedReferenceCount::get_class_type()); + TypedWritableReferenceCount::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type();