Browse Source

add GraphicsStateGuardian::panic_deactivate()

David Rose 22 years ago
parent
commit
f1ef8df820

+ 1 - 1
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();
       

+ 26 - 0
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

+ 21 - 1
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
 
 ////////////////////////////////////////////////////////////////////

+ 5 - 0
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

+ 24 - 3
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
 }

+ 60 - 53
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();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 6 - 3
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<string> _extensions;
   bool _supports_bgr;
 
+  int _error_count;
+
 public:
   static GraphicsStateGuardian *
   make_GlGraphicsStateGuardian(const FactoryParams &params);

+ 6 - 0
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__)

+ 10 - 4
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();