diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index cd22b64aa2..13e383e794 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/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(); diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index a3481826e9..7d79eb8ad5 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/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; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 099fc588c2..58facda9f3 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/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 diff --git a/panda/src/gobj/bufferResidencyTracker.cxx b/panda/src/gobj/bufferResidencyTracker.cxx index 1451ae29ec..5d3e8a79e9 100644 --- a/panda/src/gobj/bufferResidencyTracker.cxx +++ b/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 diff --git a/panda/src/gobj/bufferResidencyTracker.h b/panda/src/gobj/bufferResidencyTracker.h index 0d03e5fed2..786d18bc14 100644 --- a/panda/src/gobj/bufferResidencyTracker.h +++ b/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(); diff --git a/panda/src/gobj/preparedGraphicsObjects.I b/panda/src/gobj/preparedGraphicsObjects.I index d29a62b346..bef68d9178 100644 --- a/panda/src/gobj/preparedGraphicsObjects.I +++ b/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(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 1060f66ee0..51cac8dded 100644 --- a/panda/src/gobj/texture.cxx +++ b/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); diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.cxx b/panda/src/gsgbase/graphicsStateGuardianBase.cxx index ef2be5cfd8..541bdb43cc 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.cxx +++ b/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 diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index d402970e62..9223907682 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/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);