From 4d0d86c7cb8404c4a80d6eb45285c1c815c75f2a Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 4 Feb 2009 02:53:33 +0000 Subject: [PATCH] gl-show-texture-usage --- .../src/glstuff/glGraphicsStateGuardian_src.I | 81 +++-- .../glstuff/glGraphicsStateGuardian_src.cxx | 283 ++++++++++++++++-- .../src/glstuff/glGraphicsStateGuardian_src.h | 22 ++ panda/src/glstuff/glmisc_src.cxx | 15 + panda/src/glstuff/glmisc_src.h | 2 + 5 files changed, 355 insertions(+), 48 deletions(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.I b/panda/src/glstuff/glGraphicsStateGuardian_src.I index fa5c3c2d88..24de08698e 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.I +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.I @@ -14,7 +14,7 @@ //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::draw_display_list +// Function: GLGraphicsStateGuardian::draw_display_list // Access: Public // Description: If the GeomContext is non-NULL and contains a valid // display list, uses it to draw the geometry if @@ -38,7 +38,7 @@ draw_display_list(GeomContext *gc) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::report_errors +// Function: GLGraphicsStateGuardian::report_errors // Access: Public, Static // Description: Checks for any outstanding error codes and outputs // them, if found. If NDEBUG is defined, this function @@ -61,7 +61,7 @@ report_errors(int line, const char *source_file) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::report_my_errors +// Function: GLGraphicsStateGuardian::report_my_errors // Access: Public // Description: Like report_errors(), above, but non-static so we can // throw an event on failure. @@ -79,7 +79,7 @@ report_my_errors(int line, const char *source_file) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::get_gl_vendor +// Function: GLGraphicsStateGuardian::get_gl_vendor // Access: Public // Description: Returns the GL vendor string reported by the driver. //////////////////////////////////////////////////////////////////// @@ -89,7 +89,7 @@ get_gl_vendor() const { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::get_gl_renderer +// Function: GLGraphicsStateGuardian::get_gl_renderer // Access: Public // Description: Returns the GL renderer string reported by the driver. //////////////////////////////////////////////////////////////////// @@ -99,7 +99,7 @@ get_gl_renderer() const { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::get_gl_version +// Function: GLGraphicsStateGuardian::get_gl_version // Access: Public // Description: Returns the GL version string reported by the driver. //////////////////////////////////////////////////////////////////// @@ -109,7 +109,7 @@ get_gl_version() const { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::get_gl_version_major +// Function: GLGraphicsStateGuardian::get_gl_version_major // Access: Public // Description: Returns the major part of the reported GL version // number. @@ -120,7 +120,7 @@ get_gl_version_major() const { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::get_gl_version_minor +// Function: GLGraphicsStateGuardian::get_gl_version_minor // Access: Public // Description: Returns the minor part of the reported GL version // number. @@ -131,7 +131,7 @@ get_gl_version_minor() const { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::get_gl_version_release +// Function: GLGraphicsStateGuardian::get_gl_version_release // Access: Public // Description: Returns the release part of the reported GL version // number. @@ -157,7 +157,7 @@ maybe_gl_finish() const { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_multisample_antialias +// Function: GLGraphicsStateGuardian::enable_multisample_antialias // Access: Protected // Description: Specifies whether multisample should be enabled for // antialiasing purposes. @@ -182,7 +182,7 @@ enable_multisample_antialias(bool val) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_multisample_alpha_one +// Function: GLGraphicsStateGuardian::enable_multisample_alpha_one // Access: Protected // Description: Specifies whether multisample should be enabled for // transparency purposes, using the sample_alpha_to_one @@ -210,7 +210,7 @@ enable_multisample_alpha_one(bool val) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_multisample_alpha_mask +// Function: GLGraphicsStateGuardian::enable_multisample_alpha_mask // Access: Protected // Description: Specifies whether multisample should be enabled for // transparency purposes, using the sample_alpha_to_mask @@ -238,7 +238,7 @@ enable_multisample_alpha_mask(bool val) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_line_smooth +// Function: GLGraphicsStateGuardian::enable_line_smooth // Access: // Description: //////////////////////////////////////////////////////////////////// @@ -256,7 +256,7 @@ enable_line_smooth(bool val) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_point_smooth +// Function: GLGraphicsStateGuardian::enable_point_smooth // Access: // Description: //////////////////////////////////////////////////////////////////// @@ -274,7 +274,7 @@ enable_point_smooth(bool val) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_polygon_smooth +// Function: GLGraphicsStateGuardian::enable_polygon_smooth // Access: // Description: //////////////////////////////////////////////////////////////////// @@ -291,7 +291,7 @@ enable_polygon_smooth(bool val) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::setup_antialias_line +// Function: GLGraphicsStateGuardian::setup_antialias_line // Access: Protected // Description: Sets the appropriate antialiasing modes to render a // series of line primitives, according to @@ -308,7 +308,7 @@ setup_antialias_line() { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::setup_antialias_point +// Function: GLGraphicsStateGuardian::setup_antialias_point // Access: Protected // Description: Sets the appropriate antialiasing modes to render a // series of point primitives, according to @@ -325,7 +325,7 @@ setup_antialias_point() { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::setup_antialias_polygon +// Function: GLGraphicsStateGuardian::setup_antialias_polygon // Access: Protected // Description: Sets the appropriate antialiasing modes to render a // series of point primitives, according to @@ -362,7 +362,7 @@ setup_antialias_polygon() { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_stencil_test +// Function: GLGraphicsStateGuardian::enable_stencil_test // Access: // Description: //////////////////////////////////////////////////////////////////// @@ -387,7 +387,7 @@ enable_stencil_test(bool val) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_blend +// Function: GLGraphicsStateGuardian::enable_blend // Access: // Description: //////////////////////////////////////////////////////////////////// @@ -412,7 +412,7 @@ enable_blend(bool val) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_depth_test +// Function: GLGraphicsStateGuardian::enable_depth_test // Access: // Description: //////////////////////////////////////////////////////////////////// @@ -437,7 +437,7 @@ enable_depth_test(bool val) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_fog +// Function: GLGraphicsStateGuardian::enable_fog // Access: // Description: //////////////////////////////////////////////////////////////////// @@ -462,7 +462,7 @@ enable_fog(bool val) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_alpha_test +// Function: GLGraphicsStateGuardian::enable_alpha_test // Access: // Description: //////////////////////////////////////////////////////////////////// @@ -488,7 +488,7 @@ enable_alpha_test(bool val) { //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::enable_polygon_offset +// Function: GLGraphicsStateGuardian::enable_polygon_offset // Access: // Description: //////////////////////////////////////////////////////////////////// @@ -517,7 +517,7 @@ enable_polygon_offset(bool val) { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::get_light_id +// Function: GLGraphicsStateGuardian::get_light_id // Access: Public // Description: Convert index to gl light id //////////////////////////////////////////////////////////////////// @@ -526,7 +526,7 @@ INLINE GLenum CLP(GraphicsStateGuardian)::get_light_id(int index) const { } //////////////////////////////////////////////////////////////////// -// Function: CLP(GraphicsStateGuardian)::get_clip_plane_id +// Function: GLGraphicsStateGuardian::get_clip_plane_id // Access: Public // Description: Convert index to gl clip plane id //////////////////////////////////////////////////////////////////// @@ -534,3 +534,32 @@ INLINE GLenum CLP(GraphicsStateGuardian):: get_clip_plane_id(int index) const { return GL_CLIP_PLANE0 + index; } + +#ifndef NDEBUG +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::UsageTextureKey::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CLP(GraphicsStateGuardian)::UsageTextureKey:: +UsageTextureKey(int x_size, int y_size) : + _x_size(x_size), + _y_size(y_size) +{ +} +#endif // NDEBUG + +#ifndef NDEBUG +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::UsageTextureKey::operator < +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool CLP(GraphicsStateGuardian)::UsageTextureKey:: +operator < (const CLP(GraphicsStateGuardian)::UsageTextureKey &other) const { + if (_x_size != other._x_size) { + return _x_size < other._x_size; + } + return _y_size < other._y_size; +} +#endif // NDEBUG diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 6738d27ced..51ae2ec03d 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1628,6 +1628,35 @@ begin_frame(Thread *current_thread) { _primitive_batches_display_list_pcollector.clear_level(); #endif +#ifndef NDEBUG + _show_texture_usage = false; + if (CLP(show_texture_usage)) { + // When this is true, then every other second, we show the usage + // textures instead of the real textures. + double now = ClockObject::get_global_clock()->get_frame_time(); + int this_second = (int)floor(now); + if (this_second & 1) { + _show_texture_usage = true; + _show_texture_usage_index = this_second >> 1; + + int max_size = CLP(show_texture_usage_max_size); + if (max_size != _show_texture_usage_max_size) { + // Remove the cache of usage textures; we've changed the max + // size. + UsageTextures::iterator ui; + for (ui = _usage_textures.begin(); + ui != _usage_textures.end(); + ++ui) { + GLuint index = (*ui).second; + GLP(DeleteLists)(index, 1); + } + _usage_textures.clear(); + _show_texture_usage_max_size = max_size; + } + } + } +#endif // NDEBUG + report_my_gl_errors(); return true; } @@ -2055,11 +2084,18 @@ update_standard_vertex_arrays(bool force) { _sender.add_column(_data_reader, InternalName::get_normal(), NULL, NULL, GLP(Normal3f), NULL); - if (!_sender.add_column(_data_reader, InternalName::get_color(), - NULL, NULL, GLP(Color3f), GLP(Color4f))) { - // If we didn't have a color column, the item color is white. +#ifndef NDEBUG + if (_show_texture_usage) { + // In show_texture_usage mode, all colors are white, so as not + // to contaminate the texture color. GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f); - } + } else +#endif // NDEBUG + if (!_sender.add_column(_data_reader, InternalName::get_color(), + NULL, NULL, GLP(Color3f), GLP(Color4f))) { + // If we didn't have a color column, the item color is white. + GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f); + } // Now set up each of the active texture coordinate stages--or at // least those for which we're not generating texture coordinates @@ -2140,22 +2176,30 @@ update_standard_vertex_arrays(bool force) { GLP(DisableClientState)(GL_NORMAL_ARRAY); } - if (_data_reader->get_color_info(array_reader, num_values, numeric_type, - start, stride) && - numeric_type != Geom::NT_packed_dabc) { - if (!setup_array_data(client_pointer, array_reader, force)) { - return false; - } - GLP(ColorPointer)(num_values, get_numeric_type(numeric_type), - stride, client_pointer + start); - GLP(EnableClientState)(GL_COLOR_ARRAY); - } else { +#ifndef NDEBUG + if (_show_texture_usage) { + // In show_texture_usage mode, all colors are white, so as not + // to contaminate the texture color. GLP(DisableClientState)(GL_COLOR_ARRAY); - - // Since we don't have per-vertex color, the implicit color is - // white. GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f); - } + } else +#endif // NDEBUG + if (_data_reader->get_color_info(array_reader, num_values, numeric_type, + start, stride) && + numeric_type != Geom::NT_packed_dabc) { + if (!setup_array_data(client_pointer, array_reader, force)) { + return false; + } + GLP(ColorPointer)(num_values, get_numeric_type(numeric_type), + stride, client_pointer + start); + GLP(EnableClientState)(GL_COLOR_ARRAY); + } else { + GLP(DisableClientState)(GL_COLOR_ARRAY); + + // Since we don't have per-vertex color, the implicit color is + // white. + GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f); + } // Now set up each of the active texture coordinate stages--or at // least those for which we're not generating texture coordinates @@ -4005,6 +4049,18 @@ do_issue_material() { material = target_material->get_material(); } + bool has_material_force_color = _has_material_force_color; + +#ifndef NDEBUG + if (_show_texture_usage) { + // In show_texture_usage mode, all colors are white, so as not + // to contaminate the texture color. This means we disable + // lighting materials too. + material = ∅ + has_material_force_color = false; + } +#endif // NDEBUG + GLenum face = material->get_twoside() ? GL_FRONT_AND_BACK : GL_FRONT; GLP(Materialfv)(face, GL_SPECULAR, material->get_specular().get_data()); @@ -4022,7 +4078,7 @@ do_issue_material() { // The material specifies an ambient, but not a diffuse component. // The diffuse component comes from the object's color. GLP(Materialfv)(face, GL_AMBIENT, material->get_ambient().get_data()); - if (_has_material_force_color) { + if (has_material_force_color) { GLP(Disable)(GL_COLOR_MATERIAL); GLP(Materialfv)(face, GL_DIFFUSE, _material_force_color.get_data()); } else { @@ -4034,7 +4090,7 @@ do_issue_material() { // The material specifies a diffuse, but not an ambient component. // The ambient component comes from the object's color. GLP(Materialfv)(face, GL_DIFFUSE, material->get_diffuse().get_data()); - if (_has_material_force_color) { + if (has_material_force_color) { GLP(Disable)(GL_COLOR_MATERIAL); GLP(Materialfv)(face, GL_AMBIENT, _material_force_color.get_data()); } else { @@ -4045,7 +4101,7 @@ do_issue_material() { } else { // The material specifies neither a diffuse nor an ambient // component. Both components come from the object's color. - if (_has_material_force_color) { + if (has_material_force_color) { GLP(Disable)(GL_COLOR_MATERIAL); GLP(Materialfv)(face, GL_AMBIENT, _material_force_color.get_data()); GLP(Materialfv)(face, GL_DIFFUSE, _material_force_color.get_data()); @@ -5780,6 +5836,18 @@ print_gfx_visual() { //////////////////////////////////////////////////////////////////// float *CLP(GraphicsStateGuardian):: get_light_color(float light_color[4], Light *light) const { +#ifndef NDEBUG + if (_show_texture_usage) { + // In show_texture_usage mode, all lights are white, so as not to + // contaminate the texture color. + light_color[0] = 1.0f; + light_color[1] = 1.0f; + light_color[2] = 1.0f; + light_color[3] = 1.0f; + return light_color; + } +#endif // NDEBUG + const Colorf &c = light->get_color(); light_color[0] = c[0] * _light_color_scale[0]; @@ -6347,10 +6415,19 @@ do_issue_texture() { //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::update_standard_texture_bindings // Access: Private -// Description: +// Description: Applies the appropriate set of textures for the +// current state, using the standard fixed-function +// pipeline. //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: update_standard_texture_bindings() { +#ifndef NDEBUG + if (_show_texture_usage) { + update_show_usage_texture_bindings(); + return; + } +#endif // NDEBUG + int num_stages = _target_texture->get_num_on_ff_stages(); nassertv(num_stages <= _max_texture_stages && @@ -6540,6 +6617,168 @@ update_standard_texture_bindings() { } +#ifndef NDEBUG +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::update_show_usage_texture_bindings +// Access: Private +// Description: This is a special function that loads the usage +// textures in gl-show-texture-usage mode, instead of +// loading the actual used textures. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +update_show_usage_texture_bindings() { + int num_stages = _target_texture->get_num_on_ff_stages(); + + nassertv(num_stages <= _max_texture_stages && + _num_active_texture_stages <= _max_texture_stages); + + _texture_involves_color_scale = false; + + // First, we walk through the list of textures and pretend to render + // them all, even though we don't actually render them, just so + // Panda will keep track of the list of "active" textures correctly + // during the flash. + int i; + for (i = 0; i < num_stages; i++) { + TextureStage *stage = _target_texture->get_on_ff_stage(i); + Texture *texture = _target_texture->get_on_texture(stage); + nassertv(texture != (Texture *)NULL); + + TextureContext *tc = texture->prepare_now(_prepared_objects, this); + if (tc == (TextureContext *)NULL) { + // Something wrong with this texture; skip it. + break; + } + tc->enqueue_lru(&_prepared_objects->_graphics_memory_lru); + } + + // Disable all texture stages. + for (i = 0; i < _num_active_texture_stages; i++) { + _glActiveTexture(GL_TEXTURE0 + i); + GLP(Disable)(GL_TEXTURE_1D); + GLP(Disable)(GL_TEXTURE_2D); + if (_supports_3d_texture) { + GLP(Disable)(GL_TEXTURE_3D); + } + if (_supports_cube_map) { + GLP(Disable)(GL_TEXTURE_CUBE_MAP); + } + } + + // Save the count of texture stages for next time. + _num_active_texture_stages = num_stages; + + if (num_stages > 0) { + // Now, pick just one texture stage to apply. + i = _show_texture_usage_index % num_stages; + + TextureStage *stage = _target_texture->get_on_ff_stage(i); + Texture *texture = _target_texture->get_on_texture(stage); + nassertv(texture != (Texture *)NULL); + + // Choose the corresponding usage texture and apply it. + _glActiveTexture(GL_TEXTURE0 + i); + GLP(Enable)(GL_TEXTURE_2D); + + UsageTextureKey key(texture->get_x_size(), texture->get_y_size()); + UsageTextures::iterator ui = _usage_textures.find(key); + if (ui == _usage_textures.end()) { + // Need to create a new texture for this size. + GLuint index; + GLP(GenTextures)(1, &index); + GLP(BindTexture)(GL_TEXTURE_2D, index); + upload_usage_texture(texture->get_x_size(), texture->get_y_size()); + _usage_textures[key] = index; + + } else { + // Just bind the previously-created texture. + GLuint index = (*ui).second; + GLP(BindTexture)(GL_TEXTURE_2D, index); + } + } + + report_my_gl_errors(); +} +#endif // NDEBUG + +#ifndef NDEBUG +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::upload_usage_texture +// Access: Protected +// Description: Uploads a special "usage" texture intended to be +// applied only in gl-show-texture-usage mode, to reveal +// where texure memory is being spent. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +upload_usage_texture(int width, int height) { + GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Get the color and scale appropriate to this level. + int max_size = _show_texture_usage_max_size; + float scale = (double)(width * height) / (max_size * max_size); + scale = csqrt(min(scale, 1.0f)) * 0.8f + 0.2f; + + if (GLCAT.is_debug()) { + GLCAT.debug() + << "upload_usage_texture(" << width << ", " << height + << "), scale = " << scale << "\n"; + } + + static Colorf colors[3] = { + Colorf(0.0f, 0.0f, 1.0f, 1.0f), // mipmap 0: blue + Colorf(1.0f, 1.0f, 1.0f, 1.0f), // mipmap 1: white + Colorf(1.0f, 0.0f, 0.0f, 1.0f), // mipmap 2 and higher: red + }; + + + // Allocate a temporary array large enough to contain the toplevel + // mipmap. + PN_uint32 *buffer = (PN_uint32 *)PANDA_MALLOC_ARRAY(width * height * 4); + + int n = 0; + while (true) { + // Choose the color for the nth mipmap. + Colorf c = colors[min(n, 2)] * scale; + + // A simple union to store the colors values bytewise, and get the + // answer wordwise, independently of machine byte-ordernig. + union { + struct { + char r, g, b, a; + } b; + PN_uint32 w; + } store; + + store.b.r = (int)(c[0] * 255.0f); + store.b.g = (int)(c[1] * 255.0f); + store.b.b = (int)(c[2] * 255.0f); + store.b.a = 0xff; + + // Fill in the array. + int num_pixels = width * height; + for (int p = 0; p < num_pixels; ++p) { + buffer[p] = store.w; + } + + GLP(TexImage2D)(GL_TEXTURE_2D, n, GL_RGBA, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, buffer); + if (width == 1 && height == 1) { + // That was the last mipmap level. + break; + } + + width = max(width >> 1, 1); + height = max(height >> 1, 1); + ++n; + } + + PANDA_FREE_ARRAY(buffer); +} +#endif // NDEBUG + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::disable_standard_texture_bindings // Access: Private diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 1bd68b442e..3ff8bb5eb0 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -323,6 +323,11 @@ protected: void disable_standard_texture_bindings(); void update_standard_texture_bindings(); +#ifndef NDEBUG + void update_show_usage_texture_bindings(); + void upload_usage_texture(int width, int height); +#endif // NDEBUG + void do_auto_rescale_normal(); bool specify_texture(CLP(TextureContext) *gtc); bool apply_texture(TextureContext *tc); @@ -521,6 +526,23 @@ public: RenderState::SlotMask _inv_state_mask; +#ifndef NDEBUG + bool _show_texture_usage; + int _show_texture_usage_max_size; + int _show_texture_usage_index; + + class UsageTextureKey { + public: + INLINE UsageTextureKey(int x_size, int y_size); + INLINE bool operator < (const UsageTextureKey &other) const; + + int _x_size; + int _y_size; + }; + typedef pmap UsageTextures; + UsageTextures _usage_textures; +#endif // NDEBUG + static PStatCollector _load_display_list_pcollector; static PStatCollector _primitive_batches_display_list_pcollector; static PStatCollector _vertices_display_list_pcollector; diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index 5b7b35aa96..d8c336e5c8 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -52,6 +52,21 @@ ConfigVariableBool CLP(force_mipmaps) PRC_DESC("Configure this true to enable full trilinear mipmapping on every " "texture, whether it asks for it or not.")); +ConfigVariableBool CLP(show_texture_usage) + ("gl-show-texture-usage", false, + PRC_DESC("If you set this true, the screen will flash with textures drawn " + "in a special mode that shows the mipmap detail level and texture " + "size for each texture. Textures will be drawn in blue for " + "mipmap level 0, gray for mipmap level 1, and red for all higher " + "mipmap levels. Brighter colors represent larger textures.")); + +ConfigVariableInt CLP(show_texture_usage_max_size) + ("gl-show-texture-usage-max-size", 1024, + PRC_DESC("Specifies the texture size (along one side) of the largest " + "texture expected to be loaded. This controls the assignment " + "of the texture color in gl-show-texture-usage mode; colors " + "will be fully bright for textures of this size or larger.")); + ConfigVariableBool CLP(color_mask) ("gl-color-mask", true, PRC_DESC("Configure this false if your GL's implementation of glColorMask() " diff --git a/panda/src/glstuff/glmisc_src.h b/panda/src/glstuff/glmisc_src.h index 58fb747ca9..e4df514c3c 100644 --- a/panda/src/glstuff/glmisc_src.h +++ b/panda/src/glstuff/glmisc_src.h @@ -26,6 +26,8 @@ extern ConfigVariableBool CLP(support_clamp_to_border); extern ConfigVariableBool CLP(ignore_filters); extern ConfigVariableBool CLP(ignore_mipmaps); extern ConfigVariableBool CLP(force_mipmaps); +extern ConfigVariableBool CLP(show_texture_usage); +extern ConfigVariableInt CLP(show_texture_usage_max_size); extern ConfigVariableBool CLP(color_mask); extern ConfigVariableBool CLP(support_occlusion_query); extern ConfigVariableBool CLP(compile_and_execute);