From f90bba39e8d41a5d6f7a70abe8a86c5f34c3a632 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 27 Nov 2001 23:13:35 +0000 Subject: [PATCH] new texture dirty flags --- panda/src/display/Sources.pp | 11 +- panda/src/display/display_composite2.cxx | 2 - panda/src/display/textureContext.I | 29 -- panda/src/glgsg/glGraphicsStateGuardian.cxx | 32 +- panda/src/gobj/Sources.pp | 12 +- panda/src/gobj/gobj_composite2.cxx | 2 + panda/src/{display => gobj}/savedContext.I | 0 panda/src/{display => gobj}/savedContext.cxx | 0 panda/src/{display => gobj}/savedContext.h | 0 panda/src/gobj/texture.I | 58 ++-- panda/src/gobj/texture.cxx | 304 +++++++++++------- panda/src/gobj/texture.h | 107 +++--- panda/src/gobj/textureContext.I | 91 ++++++ .../src/{display => gobj}/textureContext.cxx | 4 +- panda/src/{display => gobj}/textureContext.h | 13 +- panda/src/sgraphutil/sceneGraphAnalyzer.cxx | 15 +- 16 files changed, 412 insertions(+), 268 deletions(-) delete mode 100644 panda/src/display/textureContext.I rename panda/src/{display => gobj}/savedContext.I (100%) rename panda/src/{display => gobj}/savedContext.cxx (100%) rename panda/src/{display => gobj}/savedContext.h (100%) create mode 100644 panda/src/gobj/textureContext.I rename panda/src/{display => gobj}/textureContext.cxx (98%) rename panda/src/{display => gobj}/textureContext.h (91%) diff --git a/panda/src/display/Sources.pp b/panda/src/display/Sources.pp index 9d24be387f..91eae7e761 100644 --- a/panda/src/display/Sources.pp +++ b/panda/src/display/Sources.pp @@ -21,9 +21,7 @@ hardwareChannel.h interactiveGraphicsPipe.I \ interactiveGraphicsPipe.h noninteractiveGraphicsPipe.I \ noninteractiveGraphicsPipe.h pipeSpec.I pipeSpec.h \ - savedContext.I savedContext.h \ - savedFrameBuffer.I savedFrameBuffer.h textureContext.I \ - textureContext.h + savedFrameBuffer.I savedFrameBuffer.h #define INCLUDED_SOURCES \ config_display.cxx displayRegion.cxx \ @@ -32,8 +30,7 @@ graphicsWindow.cxx graphicsWindowInputDevice.cxx \ hardwareChannel.cxx interactiveGraphicsPipe.cxx \ noninteractiveGraphicsPipe.cxx pipeSpec.cxx \ - savedContext.cxx \ - savedFrameBuffer.cxx textureContext.cxx + savedFrameBuffer.cxx #define INSTALL_HEADERS \ config_display.h \ @@ -47,9 +44,7 @@ hardwareChannel.I hardwareChannel.h interactiveGraphicsPipe.I \ interactiveGraphicsPipe.h noninteractiveGraphicsPipe.I \ noninteractiveGraphicsPipe.h pipeSpec.I pipeSpec.h renderBuffer.h \ - savedContext.I savedContext.h \ - savedFrameBuffer.I savedFrameBuffer.h textureContext.I \ - textureContext.h + savedFrameBuffer.I savedFrameBuffer.h #define IGATESCAN all diff --git a/panda/src/display/display_composite2.cxx b/panda/src/display/display_composite2.cxx index 0dfb7b9c62..4da48d0236 100644 --- a/panda/src/display/display_composite2.cxx +++ b/panda/src/display/display_composite2.cxx @@ -4,6 +4,4 @@ #include "interactiveGraphicsPipe.cxx" #include "noninteractiveGraphicsPipe.cxx" #include "pipeSpec.cxx" -#include "savedContext.cxx" #include "savedFrameBuffer.cxx" -#include "textureContext.cxx" diff --git a/panda/src/display/textureContext.I b/panda/src/display/textureContext.I deleted file mode 100644 index 54f244b432..0000000000 --- a/panda/src/display/textureContext.I +++ /dev/null @@ -1,29 +0,0 @@ -// Filename: textureContext.I -// Created by: drose (07Oct99) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: TextureContext::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE TextureContext:: -TextureContext(Texture *tex) : - _texture(tex) -{ -} diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index 627071e4f8..0bd07f38d7 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -1793,11 +1793,18 @@ apply_texture(TextureContext *tc) { add_to_texture_record(tc); bind_texture(tc); - /* - To render in immediate mode: - specify_texture(tex); - apply_texture_immediate(tex); - */ + int dirty = tc->get_dirty_flags(); + if ((dirty & (Texture::DF_wrap | Texture::DF_filter)) != 0) { + // We need to re-specify the texture properties. + specify_texture(tc->_texture); + } + if ((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) { + // We need to re-apply the image. + apply_texture_immediate(tc->_texture); + } + + tc->clear_dirty_flags(); + report_errors(); } @@ -3857,20 +3864,7 @@ apply_texture_immediate(Texture *tex) { #endif if (!gl_ignore_mipmaps || gl_force_mipmaps) { - bool use_mipmaps; - switch (tex->get_minfilter()) { - case Texture::FT_nearest_mipmap_nearest: - case Texture::FT_linear_mipmap_nearest: - case Texture::FT_nearest_mipmap_linear: - case Texture::FT_linear_mipmap_linear: - use_mipmaps = true; - break; - - default: - use_mipmaps = false; - break; - } - if (use_mipmaps || gl_force_mipmaps) { + if (tex->uses_mipmaps() || gl_force_mipmaps) { #ifndef NDEBUG if (gl_show_mipmaps) { build_phony_mipmaps(tex); diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index 7e4f408e37..5338664da6 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -16,7 +16,10 @@ material.I material.h materialPool.I materialPool.h \ orthoProjection.I orthoProjection.h perspectiveProjection.I \ perspectiveProjection.h pixelBuffer.I pixelBuffer.N \ - pixelBuffer.h projection.h texture.I texture.N texture.h \ + pixelBuffer.h projection.h \ + savedContext.I savedContext.h \ + texture.I texture.N texture.h \ + textureContext.I textureContext.h \ texturePool.I texturePool.h #define INCLUDED_SOURCES \ @@ -26,7 +29,7 @@ geomTrifan.cxx geomTristrip.cxx imageBuffer.cxx material.cxx \ materialPool.cxx orthoProjection.cxx \ perspectiveProjection.cxx pixelBuffer.cxx projection.cxx \ - texture.cxx texturePool.cxx + savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx #define INSTALL_HEADERS \ LOD.I LOD.h config_gobj.h \ @@ -37,7 +40,10 @@ materialPool.I materialPool.h \ orthoProjection.I orthoProjection.h perspectiveProjection.I \ perspectiveProjection.h pixelBuffer.I pixelBuffer.h projection.h \ - texture.I texture.h texturePool.I texturePool.h + savedContext.I savedContext.h \ + texture.I texture.h \ + textureContext.I textureContext.h \ + texturePool.I texturePool.h #define IGATESCAN all diff --git a/panda/src/gobj/gobj_composite2.cxx b/panda/src/gobj/gobj_composite2.cxx index 3f6a70348d..784e17c6c2 100644 --- a/panda/src/gobj/gobj_composite2.cxx +++ b/panda/src/gobj/gobj_composite2.cxx @@ -9,5 +9,7 @@ #include "perspectiveProjection.cxx" #include "pixelBuffer.cxx" #include "projection.cxx" +#include "savedContext.cxx" #include "texture.cxx" +#include "textureContext.cxx" #include "texturePool.cxx" diff --git a/panda/src/display/savedContext.I b/panda/src/gobj/savedContext.I similarity index 100% rename from panda/src/display/savedContext.I rename to panda/src/gobj/savedContext.I diff --git a/panda/src/display/savedContext.cxx b/panda/src/gobj/savedContext.cxx similarity index 100% rename from panda/src/display/savedContext.cxx rename to panda/src/gobj/savedContext.cxx diff --git a/panda/src/display/savedContext.h b/panda/src/gobj/savedContext.h similarity index 100% rename from panda/src/display/savedContext.h rename to panda/src/gobj/savedContext.h diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index ed28315ad8..81e7451059 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -17,29 +17,6 @@ //////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////// -// Function: Texture::has_ram_image -// Access: Public -// Description: Returns true if the Texture keeps has its image -// contents available in main RAM, false if it exists -// only in texture memory or in the prepared GSG -// context. -//////////////////////////////////////////////////////////////////// -INLINE bool Texture:: -has_ram_image() const { - return !_pbuffer->_image.empty(); -} - -//////////////////////////////////////////////////////////////////// -// Function: Texture::apply -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void Texture:: -apply(GraphicsStateGuardianBase *gsg) { - gsg->apply_texture(prepare(gsg)); -} - //////////////////////////////////////////////////////////////////// // Function: Texture::get_wrapu // Access: Published @@ -94,3 +71,38 @@ INLINE int Texture:: get_anisotropic_degree() const { return _anisotropic_degree; } + +//////////////////////////////////////////////////////////////////// +// Function: Texture::uses_mipmaps +// Access: Public +// Description: Returns true if the minfilter settings on this +// texture require the use of mipmapping, false +// otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool Texture:: +uses_mipmaps() const { + return is_mipmap(get_minfilter()); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::has_ram_image +// Access: Public +// Description: Returns true if the Texture keeps has its image +// contents available in main RAM, false if it exists +// only in texture memory or in the prepared GSG +// context. +//////////////////////////////////////////////////////////////////// +INLINE bool Texture:: +has_ram_image() const { + return !_pbuffer->_image.empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::apply +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +apply(GraphicsStateGuardianBase *gsg) { + gsg->apply_texture(prepare(gsg)); +} diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 864dcf911c..bb5b53a762 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -19,18 +19,18 @@ //////////////////////////////////////////////////////////////////// // Includes //////////////////////////////////////////////////////////////////// -#include +#include "pandabase.h" #include "texture.h" #include "config_gobj.h" +#include "texturePool.h" +#include "textureContext.h" +#include "datagram.h" +#include "datagramIterator.h" +#include "bamReader.h" +#include "bamWriter.h" #include -#include -#include -#include -#include -//Should this be here? -#include "texturePool.h" //////////////////////////////////////////////////////////////////// // Static variables @@ -123,6 +123,7 @@ Texture() : ImageBuffer() { _anisotropic_degree = 1; _pbuffer = new PixelBuffer; _has_requested_size = false; + _all_dirty_flags = 0; } //////////////////////////////////////////////////////////////////// @@ -222,6 +223,79 @@ write(const string &name) const { return _pbuffer->write(name); } +//////////////////////////////////////////////////////////////////// +// Function: set_wrapu +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void Texture:: +set_wrapu(Texture::WrapMode wrap) { + if (_wrapu != wrap) { + mark_dirty(DF_wrap); + _wrapu = wrap; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: set_wrapv +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void Texture:: +set_wrapv(Texture::WrapMode wrap) { + if (_wrapv != wrap) { + mark_dirty(DF_wrap); + _wrapv = wrap; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: set_minfilter +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void Texture:: +set_minfilter(Texture::FilterType filter) { + if (_minfilter != filter) { + if (is_mipmap(_minfilter) != is_mipmap(filter)) { + mark_dirty(DF_filter | DF_mipmap); + } else { + mark_dirty(DF_filter); + } + _minfilter = filter; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: set_magfilter +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void Texture:: +set_magfilter(Texture::FilterType filter) { + if (_magfilter != filter) { + mark_dirty(DF_filter); + _magfilter = filter; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: set_anisotropic_degree +// Access: Published +// Description: Specifies the level of anisotropic filtering to apply +// to the texture. Normally, this is 1, to indicate +// anisotropic filtering is disabled. This may be set +// to a number higher than one to enable anisotropic +// filtering, if the rendering backend supports this. +//////////////////////////////////////////////////////////////////// +void Texture:: +set_anisotropic_degree(int anisotropic_degree) { + if (_anisotropic_degree != anisotropic_degree) { + mark_dirty(DF_filter); + _anisotropic_degree = anisotropic_degree; + } +} + //////////////////////////////////////////////////////////////////// // Function: load // Access: Public @@ -232,11 +306,7 @@ load(const PNMImage &pnmimage) { if (!_pbuffer->load(pnmimage)) return false; - // It's not a good idea to call this here, since this function might - // be called from within the GSG itself--which won't expect the - // texture to suddenly unprepare itself. Better to have the user - // explicitly unprepare() the texture if she loads a new file. - // unprepare(); + mark_dirty(DF_image); return true; } @@ -252,6 +322,26 @@ store(PNMImage &pnmimage) const { return _pbuffer->store( pnmimage ); } +//////////////////////////////////////////////////////////////////// +// Function: Texture::is_mipmap +// Access: Public, 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 type) { + switch (type) { + case FT_nearest_mipmap_nearest: + case FT_linear_mipmap_nearest: + case FT_nearest_mipmap_linear: + case FT_linear_mipmap_linear: + return true; + + default: + return false; + } +} + //////////////////////////////////////////////////////////////////// // Function: prepare // Access: Public @@ -270,6 +360,12 @@ prepare(GraphicsStateGuardianBase *gsg) { TextureContext *tc = gsg->prepare_texture(this); _contexts[gsg] = tc; + // Now that we have a new TextureContext with zero dirty flags, our + // intersection of all dirty flags must be zero. This doesn't mean + // that some other contexts aren't still dirty, but at least one + // context isn't. + _all_dirty_flags = 0; + if (!keep_texture_ram) { // Once we have prepared the texture, we can generally safely // remove the pixels from main RAM. The GSG is now responsible @@ -409,72 +505,46 @@ void Texture::draw(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr, } //////////////////////////////////////////////////////////////////// -// Function: set_wrapu -// Access: Published -// Description: +// Function: Texture::mark_dirty +// Access: Public +// Description: Sets the indicated dirty bits on for all texture +// contexts that share this Texture. Does not change +// the bits that are not on. This presumably will +// inform the GSG that the texture properties have +// changed. See also TextureContext::mark_dirty(). +// +// Normally, this does not need to be called directly; +// changing the properties on the texture will +// automatically call this. However, if you fiddle with +// the texture image directly, for instance by meddling +// with the _pbuffer member, you may need to explicitly +// call mark_dirty(Texture::DF_image). //////////////////////////////////////////////////////////////////// void Texture:: -set_wrapu(Texture::WrapMode wrap) { - if (_wrapu != wrap) { - unprepare(); - _wrapu = wrap; +mark_dirty(int flags_to_set) { + if ((_all_dirty_flags & flags_to_set) == flags_to_set) { + // If all the texture contexts already share these bits, no need + // to do anything else. + return; } + + // Otherwise, iterate through the contexts and mark them all dirty. + Contexts::iterator ci; + for (ci = _contexts.begin(); ci != _contexts.end(); ++ci) { + (*ci).second->mark_dirty(flags_to_set); + } + + _all_dirty_flags |= flags_to_set; } //////////////////////////////////////////////////////////////////// -// Function: set_wrapv -// Access: Published -// Description: +// Function: Texture::register_with_read_factory +// Access: Public, Static +// Description: Factory method to generate a Texture object //////////////////////////////////////////////////////////////////// void Texture:: -set_wrapv(Texture::WrapMode wrap) { - if (_wrapv != wrap) { - unprepare(); - _wrapv = wrap; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: set_minfilter -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -void Texture:: -set_minfilter(Texture::FilterType filter) { - if (_minfilter != filter) { - unprepare(); - _minfilter = filter; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: set_magfilter -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -void Texture:: -set_magfilter(Texture::FilterType filter) { - if (_magfilter != filter) { - unprepare(); - _magfilter = filter; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: set_anisotropic_degree -// Access: Published -// Description: Specifies the level of anisotropic filtering to apply -// to the texture. Normally, this is 1, to indicate -// anisotropic filtering is disabled. This may be set -// to a number higher than one to enable anisotropic -// filtering, if the rendering backend supports this. -//////////////////////////////////////////////////////////////////// -void Texture:: -set_anisotropic_degree(int anisotropic_degree) { - if (_anisotropic_degree != anisotropic_degree) { - unprepare(); - _anisotropic_degree = anisotropic_degree; - } +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_Texture); } //////////////////////////////////////////////////////////////////// @@ -505,53 +575,6 @@ write_datagram(BamWriter *manager, Datagram &me) { } } -//////////////////////////////////////////////////////////////////// -// Function: Texture::fillin -// Access: Protected -// Description: Function that reads out of the datagram (or asks -// manager to read) all of the data that is needed to -// re-create this object and stores it in the appropiate -// place -//////////////////////////////////////////////////////////////////// -void Texture:: -fillin(DatagramIterator &scan, BamReader *manager) { - //We don't want to call ImageBuffer::fillin, like we - //would normally, since due to needing to know the name - //of the Texture before creating it, we have already read - //that name in. This is something of a problem as it forces - //Texture to know how the parent write_datagram works. And - //makes the assumption that the only data being written is - //the name - scan.get_uint32(); // For historical purposes - _wrapu = (enum WrapMode) scan.get_uint8(); - _wrapv = (enum WrapMode) scan.get_uint8(); - _minfilter = (enum FilterType) scan.get_uint8(); - _magfilter = (enum FilterType) scan.get_uint8(); - _magfiltercolor = (enum FilterType) scan.get_uint8(); - _magfilteralpha = (enum FilterType) scan.get_uint8(); - - _anisotropic_degree = scan.get_int16(); - - if (scan.get_remaining_size() > 0) { - bool has_pbuffer = scan.get_bool(); - if (has_pbuffer) { - PixelBuffer::Format format = (PixelBuffer::Format)scan.get_uint8(); - int num_components = -1; - if (scan.get_remaining_size() > 0) { - num_components = scan.get_uint8(); - } - - if (_pbuffer != (PixelBuffer *)NULL) { - if (num_components == _pbuffer->get_num_components()) { - // Only reset the format if the number of components hasn't - // changed. - _pbuffer->set_format(format); - } - } - } - } -} - //////////////////////////////////////////////////////////////////// // Function: Texture::make_Texture // Access: Protected @@ -598,13 +621,50 @@ make_Texture(const FactoryParams ¶ms) { } //////////////////////////////////////////////////////////////////// -// Function: Texture::register_with_factory -// Access: Public, Static -// Description: Factory method to generate a Texture object +// Function: Texture::fillin +// Access: Protected +// Description: Function that reads out of the datagram (or asks +// manager to read) all of the data that is needed to +// re-create this object and stores it in the appropiate +// place //////////////////////////////////////////////////////////////////// void Texture:: -register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_Texture); +fillin(DatagramIterator &scan, BamReader *manager) { + //We don't want to call ImageBuffer::fillin, like we + //would normally, since due to needing to know the name + //of the Texture before creating it, we have already read + //that name in. This is something of a problem as it forces + //Texture to know how the parent write_datagram works. And + //makes the assumption that the only data being written is + //the name + scan.get_uint32(); // For historical purposes + _wrapu = (enum WrapMode) scan.get_uint8(); + _wrapv = (enum WrapMode) scan.get_uint8(); + _minfilter = (enum FilterType) scan.get_uint8(); + _magfilter = (enum FilterType) scan.get_uint8(); + _magfiltercolor = (enum FilterType) scan.get_uint8(); + _magfilteralpha = (enum FilterType) scan.get_uint8(); + + _anisotropic_degree = scan.get_int16(); + + if (scan.get_remaining_size() > 0) { + bool has_pbuffer = scan.get_bool(); + if (has_pbuffer) { + PixelBuffer::Format format = (PixelBuffer::Format)scan.get_uint8(); + int num_components = -1; + if (scan.get_remaining_size() > 0) { + num_components = scan.get_uint8(); + } + + if (_pbuffer != (PixelBuffer *)NULL) { + if (num_components == _pbuffer->get_num_components()) { + // Only reset the format if the number of components hasn't + // changed. + _pbuffer->set_format(format); + } + } + } + } } diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 6b9b7af41d..0bdccf1e51 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -33,6 +33,7 @@ //////////////////////////////////////////////////////////////////// class PNMImage; +class TextureContext; //////////////////////////////////////////////////////////////////// // Class : Texture @@ -78,10 +79,25 @@ PUBLISHED: virtual bool read(const string &name, const string &gray); virtual bool write(const string &name = "") const; + void set_wrapu(WrapMode wrap); + void set_wrapv(WrapMode wrap); + void set_minfilter(FilterType filter); + void set_magfilter(FilterType filter); + void set_anisotropic_degree(int anisotropic_degree); + + INLINE WrapMode get_wrapu() const; + INLINE WrapMode get_wrapv() const; + INLINE FilterType get_minfilter() const; + INLINE FilterType get_magfilter() const; + INLINE int get_anisotropic_degree() const; + INLINE bool uses_mipmaps() const; + public: bool load(const PNMImage &pnmimage); bool store(PNMImage &pnmimage) const; + static bool is_mipmap(FilterType type); + TextureContext *prepare(GraphicsStateGuardianBase *gsg); void unprepare(); void unprepare(GraphicsStateGuardianBase *gsg); @@ -100,19 +116,55 @@ public: virtual void draw(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr, const RenderBuffer &rb); -PUBLISHED: - void set_wrapu(WrapMode wrap); - void set_wrapv(WrapMode wrap); - void set_minfilter(FilterType filter); - void set_magfilter(FilterType filter); - void set_anisotropic_degree(int anisotropic_degree); + // These bits are used as parameters to Texture::mark_dirty() and + // also TextureContext::mark_dirty() (and related functions in + // TextureContext). + enum DirtyFlags { + DF_image = 0x001, // The image pixels have changed. + DF_wrap = 0x002, // The wrap properties have changed. + DF_filter = 0x004, // The minfilter or magfilter have changed. + DF_mipmap = 0x008, // The use of mipmaps or not has changed. + }; - INLINE WrapMode get_wrapu() const; - INLINE WrapMode get_wrapv() const; - INLINE FilterType get_minfilter() const; - INLINE FilterType get_magfilter() const; - INLINE int get_anisotropic_degree() const; + void mark_dirty(int flags_to_set); +private: + WrapMode _wrapu; + WrapMode _wrapv; + FilterType _minfilter; + FilterType _magfilter; + FilterType _magfiltercolor; + FilterType _magfilteralpha; + int _anisotropic_degree; + + // A Texture keeps a list (actually, a map) of all the GSG's that it + // has been prepared into. Each GSG conversely keeps a list (a set) + // of all the Textures that have been prepared there. When either + // destructs, it removes itself from the other's list. + typedef pmap Contexts; + Contexts _contexts; + + // This value represents the intersection of all the dirty flags of + // the various TextureContexts that might be associated with this + // texture. + int _all_dirty_flags; + +public: + // These are public to allow direct manipulation of the underlying + // pixel buffer when needed. Know what you are doing! + PT(PixelBuffer) _pbuffer; + + // If you request a region from the framebuffer that is not a power of 2, + // we need to grab a larger region that is a power of 2 that contains the + // requested region and set the pixel buffer size accordingly. We store + // the size you requested in the members below. + bool _has_requested_size; + int _requested_w; + int _requested_h; + + + + // Datagram stuff public: static void register_with_read_factory(void); virtual void write_datagram(BamWriter* manager, Datagram &me); @@ -140,38 +192,7 @@ private: static TypeHandle _type_handle; - //////////////////////////////////////////////////////////////////// - -protected: - - WrapMode _wrapu; - WrapMode _wrapv; - FilterType _minfilter; - FilterType _magfilter; - FilterType _magfiltercolor; - FilterType _magfilteralpha; - int _anisotropic_degree; - - // A Texture keeps a list (actually, a map) of all the GSG's that it - // has been prepared into. Each GSG conversely keeps a list (a set) - // of all the Texture's that have been prepared there. When either - // destructs, it removes itself from the other's list. - typedef pmap Contexts; - Contexts _contexts; - - - // These are public to allow direct manipulation of the underlying - // pixel buffer when needed. Know what you are doing! -public: - PT(PixelBuffer) _pbuffer; - - // If you request a region from the framebuffer that is not a power of 2, - // we need to grab a larger region that is a power of 2 that contains the - // requested region and set the pixel buffer size accordingly. We store - // the size you requested in the members below. - bool _has_requested_size; - int _requested_w; - int _requested_h; + friend TextureContext; }; #include "texture.I" diff --git a/panda/src/gobj/textureContext.I b/panda/src/gobj/textureContext.I new file mode 100644 index 0000000000..602af75b6c --- /dev/null +++ b/panda/src/gobj/textureContext.I @@ -0,0 +1,91 @@ +// Filename: textureContext.I +// Created by: drose (07Oct99) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: TextureContext::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TextureContext:: +TextureContext(Texture *tex) : + _texture(tex) +{ + _dirty_flags = 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureContext::mark_dirty +// Access: Public +// Description: Marks the context "dirty", i.e. its properties are +// different from the last time the GSG has seen them. +// Presumably, the GSG will respond by updating the +// properties and clearing the dirty bits the next time +// it renders the texture. +// +// The value is the union of all the bits that are to be +// set dirty; bits that are not set in this parameter +// are left unchanged. See Texture::DirtyFlags for a +// list of available bits. +// +// Usually this function is not called directly, but +// rather is called by Texture::mark_dirty() as a result +// of changing properties directly on the texture. +//////////////////////////////////////////////////////////////////// +INLINE void TextureContext:: +mark_dirty(int flags_to_set) { + _dirty_flags |= flags_to_set; +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureContext::clear_dirty_flags +// Access: Public +// Description: Removes the indicated flags from the "dirty" bits. +// See mark_dirty(). +// +// The value is the union of all the bits that are to be +// cleared; if a bit is set in the parameter, it will be +// removed from the dirty set. Bits that are not set in +// this parameter are left unchanged. +// +// This function is intended to be called by the GSG +// after it has updated the texture parameters. +//////////////////////////////////////////////////////////////////// +INLINE void TextureContext:: +clear_dirty_flags(int flags_to_clear) { + _dirty_flags &= ~flags_to_clear; + _texture->_all_dirty_flags &= ~flags_to_clear; +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureContext::get_dirty_flags +// Access: Public +// Description: Returns the current state of the dirty flags. If +// this is non-zero, it represents the union of all +// properties that have been changed since the last call +// to clear_dirty_flags(). +// +// This function is intended to be called by the GSG to +// determine what properties need to be updated. See +// Texture::DirtyFlags for a list of possible bits. +//////////////////////////////////////////////////////////////////// +INLINE int TextureContext:: +get_dirty_flags() const { + return _dirty_flags; +} + diff --git a/panda/src/display/textureContext.cxx b/panda/src/gobj/textureContext.cxx similarity index 98% rename from panda/src/display/textureContext.cxx rename to panda/src/gobj/textureContext.cxx index 171e1b1924..f76fad01f5 100644 --- a/panda/src/display/textureContext.cxx +++ b/panda/src/gobj/textureContext.cxx @@ -18,8 +18,8 @@ #include "textureContext.h" -#include -#include +#include "pixelBuffer.h" +#include "texture.h" TypeHandle TextureContext::_type_handle; diff --git a/panda/src/display/textureContext.h b/panda/src/gobj/textureContext.h similarity index 91% rename from panda/src/display/textureContext.h rename to panda/src/gobj/textureContext.h index e3d9aa8793..dc47704d3e 100644 --- a/panda/src/display/textureContext.h +++ b/panda/src/gobj/textureContext.h @@ -19,11 +19,10 @@ #ifndef TEXTURECONTEXT_H #define TEXTURECONTEXT_H -#include +#include "pandabase.h" #include "savedContext.h" - -class Texture; +#include "texture.h" //////////////////////////////////////////////////////////////////// // Class : TextureContext @@ -49,6 +48,14 @@ public: // reference count. Texture *_texture; + INLINE void mark_dirty(int flags_to_set); + INLINE void clear_dirty_flags(int flags_to_clear = ~0); + INLINE int get_dirty_flags() const; + +private: + int _dirty_flags; + + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/sgraphutil/sceneGraphAnalyzer.cxx b/panda/src/sgraphutil/sceneGraphAnalyzer.cxx index e8e61021e6..866c1d6ca4 100644 --- a/panda/src/sgraphutil/sceneGraphAnalyzer.cxx +++ b/panda/src/sgraphutil/sceneGraphAnalyzer.cxx @@ -384,20 +384,7 @@ collect_statistics(Texture *texture) { pb->get_xsize() * pb->get_ysize() * pb->get_num_components() * pb->get_component_width(); - bool is_mipmapped = false; - switch (texture->get_minfilter()) { - case Texture::FT_nearest_mipmap_nearest: - case Texture::FT_linear_mipmap_nearest: - case Texture::FT_nearest_mipmap_linear: - case Texture::FT_linear_mipmap_linear: - is_mipmapped = true; - break; - - default: - break; - } - - if (is_mipmapped) { + if (texture->uses_mipmaps()) { bytes *= 4/3; }