diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 64e56f19ef..6b3cf55d13 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -4268,14 +4268,15 @@ update_texture(TextureContext *tc, bool force) { // If the texture image was modified, reload the texture. apply_texture(tc); + + Texture *tex = tc->get_texture(); if (gtc->was_properties_modified()) { - Texture *tex = tc->get_texture(); specify_texture(gtc, tex->get_default_sampler()); } - bool okflag = upload_texture(gtc, force); + bool okflag = upload_texture(gtc, force, tex->uses_mipmaps()); if (!okflag) { GLCAT.error() - << "Could not load " << *gtc->get_texture() << "\n"; + << "Could not load " << *tex << "\n"; return false; } @@ -4290,7 +4291,7 @@ update_texture(TextureContext *tc, bool force) { if (specify_texture(gtc, tex->get_default_sampler())) { // Actually, looks like the texture *does* need to be reloaded. gtc->mark_needs_reload(); - bool okflag = upload_texture(gtc, force); + bool okflag = upload_texture(gtc, force, tex->uses_mipmaps()); if (!okflag) { GLCAT.error() << "Could not load " << *tex << "\n"; @@ -4398,7 +4399,7 @@ prepare_sampler(const SamplerState &sampler) { SamplerState::FilterType minfilter = sampler.get_effective_minfilter(); SamplerState::FilterType magfilter = sampler.get_effective_magfilter(); - bool uses_mipmaps = Texture::is_mipmap(minfilter) && !gl_ignore_mipmaps; + bool uses_mipmaps = SamplerState::is_mipmap(minfilter) && !gl_ignore_mipmaps; #ifndef NDEBUG if (gl_force_mipmaps) { @@ -9837,7 +9838,7 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) { SamplerState::FilterType minfilter = sampler.get_effective_minfilter(); SamplerState::FilterType magfilter = sampler.get_effective_magfilter(); - bool uses_mipmaps = Texture::is_mipmap(minfilter) && !gl_ignore_mipmaps; + bool uses_mipmaps = SamplerState::is_mipmap(minfilter) && !gl_ignore_mipmaps; #ifndef NDEBUG if (gl_force_mipmaps) { @@ -9948,6 +9949,8 @@ apply_texture(TextureContext *tc) { //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) { + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); + if (_supports_sampler_objects) { // We support sampler objects. Prepare the sampler object and // bind it to the indicated texture unit. @@ -9965,8 +9968,6 @@ apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) { } } else { - CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - // We don't support sampler objects. We'll have to bind the // texture and change the texture parameters if they don't match. if (gtc->_active_sampler != sampler) { @@ -9976,6 +9977,19 @@ apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) { } } + if (sampler.uses_mipmaps() && !gtc->_uses_mipmaps) { + // The texture wasn't created with mipmaps, but we are trying + // to sample it with mipmaps. We will need to reload it. + apply_texture(tc); + gtc->mark_needs_reload(); + bool okflag = upload_texture(gtc, false, true); + if (!okflag) { + GLCAT.error() + << "Could not load " << *gtc->get_texture() << "\n"; + return false; + } + } + report_my_gl_errors(); return true; } @@ -9990,7 +10004,7 @@ apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) { // the texture has no image. //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: -upload_texture(CLP(TextureContext) *gtc, bool force) { +upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { PStatGPUTimer timer(this, _load_texture_pcollector); Texture *tex = gtc->get_texture(); @@ -10161,7 +10175,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); GLenum target = get_texture_target(tex->get_texture_type()); - bool uses_mipmaps = (tex->uses_mipmaps() && !gl_ignore_mipmaps) || gl_force_mipmaps; + uses_mipmaps = (uses_mipmaps && !gl_ignore_mipmaps) || gl_force_mipmaps; bool needs_reload = false; if (!gtc->_has_storage || gtc->_uses_mipmaps != uses_mipmaps || @@ -11453,7 +11467,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { tex->set_ram_image(image, compression, page_size); - if (tex->uses_mipmaps()) { + if (gtc->_uses_mipmaps) { // Also get the mipmap levels. GLint num_expected_levels = tex->get_expected_num_mipmap_levels(); GLint highest_level = num_expected_levels; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index b1ec3fa1cf..bcfe2fd383 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -490,7 +490,7 @@ protected: bool specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler); bool apply_texture(TextureContext *tc); bool apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc); - bool upload_texture(CLP(TextureContext) *gtc, bool force); + bool upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps); bool upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, bool uses_mipmaps, int mipmap_bias, GLenum texture_target, GLenum page_target, diff --git a/panda/src/gobj/samplerState.I b/panda/src/gobj/samplerState.I index 2762c10ce6..f7096b0500 100644 --- a/panda/src/gobj/samplerState.I +++ b/panda/src/gobj/samplerState.I @@ -307,6 +307,38 @@ get_lod_bias() const { return _lod_bias; } +//////////////////////////////////////////////////////////////////// +// Function: SamplerState::uses_mipmaps +// Access: Public +// Description: Returns true if the minfilter settings on this +// sampler indicate the use of mipmapping, false +// otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool SamplerState:: +uses_mipmaps() const { + return is_mipmap(get_effective_minfilter()); +} + +//////////////////////////////////////////////////////////////////// +// Function: SamplerState::is_mipmap +// Access: Published, Static +// Description: Returns true if the indicated filter type requires +// the use of mipmaps, or false if it does not. +//////////////////////////////////////////////////////////////////// +INLINE bool SamplerState:: +is_mipmap(FilterType filter_type) { + switch (filter_type) { + case SamplerState::FT_nearest_mipmap_nearest: + case SamplerState::FT_linear_mipmap_nearest: + case SamplerState::FT_nearest_mipmap_linear: + case SamplerState::FT_linear_mipmap_linear: + return true; + + default: + return false; + } +} + //////////////////////////////////////////////////////////////////// // Function: SamplerState::operator == // Access: Published diff --git a/panda/src/gobj/samplerState.h b/panda/src/gobj/samplerState.h index 2d9528246a..d5c10d6a1c 100644 --- a/panda/src/gobj/samplerState.h +++ b/panda/src/gobj/samplerState.h @@ -110,6 +110,9 @@ PUBLISHED: INLINE PN_stdfloat get_max_lod() const; INLINE PN_stdfloat get_lod_bias() const; + INLINE bool uses_mipmaps() const; + INLINE static bool is_mipmap(FilterType type); + static string format_filter_type(FilterType ft); static FilterType string_filter_type(const string &str); diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 63625818cd..f075107d34 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -1223,7 +1223,7 @@ get_render_to_texture() const { //////////////////////////////////////////////////////////////////// INLINE bool Texture:: uses_mipmaps() const { - return is_mipmap(get_effective_minfilter()); + return SamplerState::is_mipmap(get_effective_minfilter()); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index ed3252f5c7..0ab909f66c 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -1804,26 +1804,6 @@ set_orig_file_size(int x, int y, int z) { nassertv(z == cdata->_z_size); } -//////////////////////////////////////////////////////////////////// -// Function: Texture::is_mipmap -// Access: Published, Static -// Description: Returns true if the indicated filter type requires -// the use of mipmaps, or false if it does not. -//////////////////////////////////////////////////////////////////// -bool Texture:: -is_mipmap(FilterType filter_type) { - switch (filter_type) { - case SamplerState::FT_nearest_mipmap_nearest: - case SamplerState::FT_linear_mipmap_nearest: - case SamplerState::FT_nearest_mipmap_linear: - case SamplerState::FT_linear_mipmap_linear: - return true; - - default: - return false; - } -} - //////////////////////////////////////////////////////////////////// // Function: Texture::prepare_now // Access: Published diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 7d4106e960..ad93f8641a 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -458,8 +458,6 @@ PUBLISHED: INLINE void set_loaded_from_txo(); INLINE bool get_loaded_from_txo() const; - static bool is_mipmap(FilterType type); - INLINE bool get_match_framebuffer_format() const; INLINE void set_match_framebuffer_format(bool flag);