Browse Source

fix removing windows, and also gl hack for compressed mipmaps

David Rose 17 years ago
parent
commit
a398ac7517

+ 34 - 0
panda/src/display/graphicsEngine.cxx

@@ -467,6 +467,36 @@ remove_window(GraphicsOutput *window) {
 
   do_remove_window(window, current_thread);
 
+  GraphicsStateGuardian *gsg = window->get_gsg();
+  if (gsg != (GraphicsStateGuardian *)NULL) {
+    PreparedGraphicsObjects *pgo = gsg->get_prepared_objects();
+    if (pgo != (PreparedGraphicsObjects *)NULL) {
+      // Check to see if any other still-active windows share this
+      // context.
+      bool any_common = false;
+      {
+        LightReMutexHolder holder(_lock, current_thread);
+        Windows::iterator wi;
+        for (wi = _windows.begin(); wi != _windows.end() && !any_common; ++wi) {
+          GraphicsStateGuardian *gsg2 = (*wi)->get_gsg();
+          if (gsg2 != (GraphicsStateGuardian *)NULL &&
+              gsg2->get_prepared_objects() == pgo) {
+            any_common = true;
+          }
+        }
+      }
+      if (!any_common) {
+        // If no windows still use this context, release all textures,
+        // etc.  We do this in case there is a floating pointer
+        // somewhere keeping the GSG from destructing when its window
+        // goes away.  A leaked GSG pointer is bad enough, but there's
+        // no reason we also need to keep around all of the objects
+        // allocated on graphics memory.
+        pgo->release_all();
+      }
+    }
+  }
+
   nassertr(count == 1, true);
   return true;
 }
@@ -486,6 +516,10 @@ remove_all_windows() {
   for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
     GraphicsOutput *win = (*wi);
     do_remove_window(win, current_thread);
+    GraphicsStateGuardian *gsg = win->get_gsg();
+    if (gsg != (GraphicsStateGuardian *)NULL) {
+      gsg->release_all();
+    }
   }
   
   _windows.clear();

+ 1 - 0
panda/src/display/graphicsStateGuardian.cxx

@@ -139,6 +139,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
   _prepared_objects = new PreparedGraphicsObjects;
   _stereo_buffer_mask = ~0;
   _incomplete_render = allow_incomplete_render;
+  _loader = Loader::get_global_ptr();
 
   _is_hardware = false;
   _prefers_triangle_strips = false;

+ 32 - 3
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -660,6 +660,11 @@ reset() {
   _supports_generate_mipmap =
     has_extension("GL_SGIS_generate_mipmap") || is_at_least_version(1, 4);
 
+  // Temporary hack.  There is an issue with auto-generating mipmaps
+  // for pre-compressed images, on certain drivers.  Until I check in
+  // a fix, let's turn off this feature in general.
+  _supports_generate_mipmap = false;
+
   _supports_multitexture = false;
 
   _supports_mesa_6 = false;
@@ -7313,6 +7318,13 @@ upload_texture_image(CLP(TextureContext) *gtc,
       gtc->_depth != depth) {
     // We need to reload a new image.
 
+    if (GLCAT.is_debug()) {
+      GLCAT.debug()
+        << "loading new texture object, " << width << " x " << height
+        << " x " << depth << ", mipmaps " << mipmap_bias << " - " 
+        << num_ram_mipmap_levels << "\n";
+    }
+
     if (num_ram_mipmap_levels == 0) {
       if (external_format == GL_DEPTH_STENCIL_EXT) {
         GLP(TexImage2D)(page_target, 0, internal_format,
@@ -7404,6 +7416,14 @@ upload_texture_image(CLP(TextureContext) *gtc,
   } else {
     // We can reload the image over the previous image, possibly
     // saving on texture memory fragmentation.
+
+    if (GLCAT.is_debug()) {
+      GLCAT.debug()
+        << "subloading existing texture object, " << width << " x " << height
+        << " x " << depth << ", mipmaps " << mipmap_bias << " - " 
+        << num_ram_mipmap_levels << "\n";
+    }
+
     for (int n = mipmap_bias; n < num_ram_mipmap_levels; ++n) {
       const unsigned char *image_ptr = tex->get_ram_mipmap_image(n);
       if (image_ptr == (const unsigned char *)NULL) {
@@ -7747,13 +7767,17 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
 
   GLint width = 1, height = 1, depth = 1;
   GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_WIDTH, &width);
-  GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_HEIGHT, &height);
-  if (_supports_3d_texture) {
+  if (target != GL_TEXTURE_1D) {
+    GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_HEIGHT, &height);
+  }
+  if (_supports_3d_texture && target == GL_TEXTURE_3D) {
     GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_DEPTH, &depth);
+  } else if (target == GL_TEXTURE_CUBE_MAP) {
+    depth = 6;
   }
   report_my_gl_errors();
 
-  GLint internal_format;
+  GLint internal_format = 0;
   GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format);
 
   // Make sure we were able to query those parameters properly.
@@ -7875,6 +7899,11 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
     format = Texture::F_rgba;
     compression = Texture::CM_fxt1;
     break;
+
+  default:
+    GLCAT.warning()
+      << "Unhandled internal format for " << tex->get_name()
+      << " : " << hex << "0x" << internal_format << dec << "\n";
   }
 
   // We don't want to call setup_texture() again; that resets too

+ 27 - 0
panda/src/gobj/bufferResidencyTracker.cxx

@@ -35,6 +35,19 @@ BufferResidencyTracker(const string &pgo_name, const string &type_name) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: BufferResidencyTracker::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+BufferResidencyTracker::
+~BufferResidencyTracker() {
+  _inactive_nonresident_collector.set_level(0);
+  _active_nonresident_collector.set_level(0);
+  _inactive_resident_collector.set_level(0);
+  _active_resident_collector.set_level(0);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: BufferResidencyTracker::begin_frame
 //       Access: Public
@@ -72,6 +85,20 @@ end_frame(Thread *current_thread) {
   _active_resident_collector.set_level(_chains[S_active_resident].get_total_size());
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: BufferResidencyTracker::set_levels
+//       Access: Public
+//  Description: Resets the pstats levels to their appropriate values,
+//               possibly in the middle of a frame.
+////////////////////////////////////////////////////////////////////
+void BufferResidencyTracker::
+set_levels() {
+  _inactive_nonresident_collector.set_level(_chains[S_inactive_nonresident].get_total_size());
+  _active_nonresident_collector.set_level(_chains[S_active_nonresident].get_total_size());
+  _inactive_resident_collector.set_level(_chains[S_inactive_resident].get_total_size());
+  _active_resident_collector.set_level(_chains[S_active_resident].get_total_size());
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: BufferResidencyTracker::write
 //       Access: Public

+ 2 - 0
panda/src/gobj/bufferResidencyTracker.h

@@ -36,9 +36,11 @@ class BufferContext;
 class EXPCL_PANDA_GOBJ BufferResidencyTracker {
 public:
   BufferResidencyTracker(const string &pgo_name, const string &type_name);
+  ~BufferResidencyTracker();
 
   void begin_frame(Thread *current_thread);
   void end_frame(Thread *current_thread);
+  void set_levels();
 
   INLINE BufferContextChain &get_inactive_nonresident();
   INLINE BufferContextChain &get_active_nonresident();

+ 4 - 0
panda/src/gobj/preparedGraphicsObjects.I

@@ -69,6 +69,10 @@ release_all() {
   release_all_shaders();
   release_all_vertex_buffers();
   release_all_index_buffers();
+
+  _texture_residency.set_levels();
+  _vbuffer_residency.set_levels();
+  _ibuffer_residency.set_levels();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 5 - 2
panda/src/gobj/texture.cxx

@@ -964,8 +964,9 @@ clear_ram_mipmap_image(int n) {
 //       Access: Published
 //  Description: Automatically fills in the n mipmap levels of the
 //               Texture, based on the texture's source image.  This
-//               requires the texture's ram image to be available in
-//               system memory.
+//               requires the texture's uncompressed ram image to be
+//               available in system memory.  If it is not already, it
+//               will be fetched if possible.
 //
 //               This call is not normally necessary, since the mipmap
 //               levels will be generated automatically if needed.
@@ -975,6 +976,8 @@ clear_ram_mipmap_image(int n) {
 void Texture::
 generate_ram_mipmap_images() {
   MutexHolder holder(_lock);
+
+  do_get_uncompressed_ram_image();
   nassertv(do_has_ram_image());
   nassertv(_ram_image_compression == CM_off);
   nassertv(_component_type != T_float);

+ 23 - 0
panda/src/gsgbase/graphicsStateGuardianBase.cxx

@@ -57,6 +57,29 @@ set_default_gsg(GraphicsStateGuardianBase *default_gsg) {
   _default_gsg = default_gsg;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardianBase::get_num_gsgs
+//       Access: Published, Static
+//  Description: Returns the total number of GSG's in the universe.
+////////////////////////////////////////////////////////////////////
+int GraphicsStateGuardianBase::
+get_num_gsgs() {
+  return _gsgs.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardianBase::get_gsg
+//       Access: Published, Static
+//  Description: Returns the nth GSG in the universe.  GSG's
+//               automatically add themselves and remove themselves
+//               from this list as they are created and destroyed.
+////////////////////////////////////////////////////////////////////
+GraphicsStateGuardianBase *GraphicsStateGuardianBase::
+get_gsg(int n) {
+  nassertr(n >= 0 && n < (int)_gsgs.size(), NULL);
+  return _gsgs[n];
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardianBase::add_gsg
 //       Access: Public, Static

+ 4 - 0
panda/src/gsgbase/graphicsStateGuardianBase.h

@@ -215,6 +215,10 @@ PUBLISHED:
   static GraphicsStateGuardianBase *get_default_gsg();
   static void set_default_gsg(GraphicsStateGuardianBase *default_gsg);
 
+  static int get_num_gsgs();
+  static GraphicsStateGuardianBase *get_gsg(int n);
+  MAKE_SEQ(get_gsgs, get_num_gsgs, get_gsg);
+
 public:
   static void add_gsg(GraphicsStateGuardianBase *gsg);
   static void remove_gsg(GraphicsStateGuardianBase *gsg);