Răsfoiți Sursa

new texture dirty flags

David Rose 24 ani în urmă
părinte
comite
f90bba39e8

+ 3 - 8
panda/src/display/Sources.pp

@@ -21,9 +21,7 @@
      hardwareChannel.h interactiveGraphicsPipe.I  \
      hardwareChannel.h interactiveGraphicsPipe.I  \
      interactiveGraphicsPipe.h noninteractiveGraphicsPipe.I  \
      interactiveGraphicsPipe.h noninteractiveGraphicsPipe.I  \
      noninteractiveGraphicsPipe.h pipeSpec.I pipeSpec.h  \
      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  \
  #define INCLUDED_SOURCES  \
      config_display.cxx displayRegion.cxx \
      config_display.cxx displayRegion.cxx \
@@ -32,8 +30,7 @@
      graphicsWindow.cxx graphicsWindowInputDevice.cxx  \
      graphicsWindow.cxx graphicsWindowInputDevice.cxx  \
      hardwareChannel.cxx interactiveGraphicsPipe.cxx  \
      hardwareChannel.cxx interactiveGraphicsPipe.cxx  \
      noninteractiveGraphicsPipe.cxx pipeSpec.cxx  \
      noninteractiveGraphicsPipe.cxx pipeSpec.cxx  \
-     savedContext.cxx \
-     savedFrameBuffer.cxx textureContext.cxx 
+     savedFrameBuffer.cxx
 
 
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \
     config_display.h \
     config_display.h \
@@ -47,9 +44,7 @@
     hardwareChannel.I hardwareChannel.h interactiveGraphicsPipe.I \
     hardwareChannel.I hardwareChannel.h interactiveGraphicsPipe.I \
     interactiveGraphicsPipe.h noninteractiveGraphicsPipe.I \
     interactiveGraphicsPipe.h noninteractiveGraphicsPipe.I \
     noninteractiveGraphicsPipe.h pipeSpec.I pipeSpec.h renderBuffer.h \
     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
   #define IGATESCAN all
 
 

+ 0 - 2
panda/src/display/display_composite2.cxx

@@ -4,6 +4,4 @@
 #include "interactiveGraphicsPipe.cxx"
 #include "interactiveGraphicsPipe.cxx"
 #include "noninteractiveGraphicsPipe.cxx"
 #include "noninteractiveGraphicsPipe.cxx"
 #include "pipeSpec.cxx"
 #include "pipeSpec.cxx"
-#include "savedContext.cxx"
 #include "savedFrameBuffer.cxx"
 #include "savedFrameBuffer.cxx"
-#include "textureContext.cxx"

+ 0 - 29
panda/src/display/textureContext.I

@@ -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
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: TextureContext::Constructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE TextureContext::
-TextureContext(Texture *tex) :
-  _texture(tex)
-{
-}

+ 13 - 19
panda/src/glgsg/glGraphicsStateGuardian.cxx

@@ -1793,11 +1793,18 @@ apply_texture(TextureContext *tc) {
   add_to_texture_record(tc);
   add_to_texture_record(tc);
   bind_texture(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();
   report_errors();
 }
 }
 
 
@@ -3857,20 +3864,7 @@ apply_texture_immediate(Texture *tex) {
 #endif
 #endif
 
 
   if (!gl_ignore_mipmaps || gl_force_mipmaps) {
   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
 #ifndef NDEBUG
       if (gl_show_mipmaps) {
       if (gl_show_mipmaps) {
         build_phony_mipmaps(tex);
         build_phony_mipmaps(tex);

+ 9 - 3
panda/src/gobj/Sources.pp

@@ -16,7 +16,10 @@
      material.I material.h materialPool.I materialPool.h  \
      material.I material.h materialPool.I materialPool.h  \
      orthoProjection.I orthoProjection.h perspectiveProjection.I  \
      orthoProjection.I orthoProjection.h perspectiveProjection.I  \
      perspectiveProjection.h pixelBuffer.I pixelBuffer.N  \
      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
      texturePool.I texturePool.h
     
     
   #define INCLUDED_SOURCES \
   #define INCLUDED_SOURCES \
@@ -26,7 +29,7 @@
      geomTrifan.cxx geomTristrip.cxx imageBuffer.cxx material.cxx  \
      geomTrifan.cxx geomTristrip.cxx imageBuffer.cxx material.cxx  \
      materialPool.cxx orthoProjection.cxx  \
      materialPool.cxx orthoProjection.cxx  \
      perspectiveProjection.cxx pixelBuffer.cxx projection.cxx  \
      perspectiveProjection.cxx pixelBuffer.cxx projection.cxx  \
-     texture.cxx texturePool.cxx
+     savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx
 
 
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \
     LOD.I LOD.h config_gobj.h \
     LOD.I LOD.h config_gobj.h \
@@ -37,7 +40,10 @@
     materialPool.I materialPool.h \
     materialPool.I materialPool.h \
     orthoProjection.I orthoProjection.h perspectiveProjection.I \
     orthoProjection.I orthoProjection.h perspectiveProjection.I \
     perspectiveProjection.h pixelBuffer.I pixelBuffer.h projection.h \
     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
   #define IGATESCAN all
 
 

+ 2 - 0
panda/src/gobj/gobj_composite2.cxx

@@ -9,5 +9,7 @@
 #include "perspectiveProjection.cxx"
 #include "perspectiveProjection.cxx"
 #include "pixelBuffer.cxx"
 #include "pixelBuffer.cxx"
 #include "projection.cxx"
 #include "projection.cxx"
+#include "savedContext.cxx"
 #include "texture.cxx"
 #include "texture.cxx"
+#include "textureContext.cxx"
 #include "texturePool.cxx"
 #include "texturePool.cxx"

+ 0 - 0
panda/src/display/savedContext.I → panda/src/gobj/savedContext.I


+ 0 - 0
panda/src/display/savedContext.cxx → panda/src/gobj/savedContext.cxx


+ 0 - 0
panda/src/display/savedContext.h → panda/src/gobj/savedContext.h


+ 35 - 23
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
 //     Function: Texture::get_wrapu
 //       Access: Published
 //       Access: Published
@@ -94,3 +71,38 @@ INLINE int Texture::
 get_anisotropic_degree() const {
 get_anisotropic_degree() const {
   return _anisotropic_degree;
   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));
+}

+ 179 - 119
panda/src/gobj/texture.cxx

@@ -19,18 +19,18 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // Includes
 // Includes
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-#include <pandabase.h>
+#include "pandabase.h"
 #include "texture.h"
 #include "texture.h"
 #include "config_gobj.h"
 #include "config_gobj.h"
+#include "texturePool.h"
+#include "textureContext.h"
+#include "datagram.h"
+#include "datagramIterator.h"
+#include "bamReader.h"
+#include "bamWriter.h"
 
 
 #include <stddef.h>
 #include <stddef.h>
-#include <datagram.h>
-#include <datagramIterator.h>
-#include <bamReader.h>
-#include <bamWriter.h>
 
 
-//Should this be here?
-#include "texturePool.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // Static variables
 // Static variables
@@ -123,6 +123,7 @@ Texture() : ImageBuffer() {
   _anisotropic_degree = 1;
   _anisotropic_degree = 1;
   _pbuffer = new PixelBuffer;
   _pbuffer = new PixelBuffer;
   _has_requested_size = false;
   _has_requested_size = false;
+  _all_dirty_flags = 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -222,6 +223,79 @@ write(const string &name) const {
   return _pbuffer->write(name);
   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
 //     Function: load
 //       Access: Public
 //       Access: Public
@@ -232,11 +306,7 @@ load(const PNMImage &pnmimage) {
   if (!_pbuffer->load(pnmimage))
   if (!_pbuffer->load(pnmimage))
     return false;
     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;
   return true;
 }
 }
@@ -252,6 +322,26 @@ store(PNMImage &pnmimage) const {
   return _pbuffer->store( pnmimage );
   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
 //     Function: prepare
 //       Access: Public
 //       Access: Public
@@ -270,6 +360,12 @@ prepare(GraphicsStateGuardianBase *gsg) {
   TextureContext *tc = gsg->prepare_texture(this);
   TextureContext *tc = gsg->prepare_texture(this);
   _contexts[gsg] = tc;
   _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) {
   if (!keep_texture_ram) {
     // Once we have prepared the texture, we can generally safely
     // Once we have prepared the texture, we can generally safely
     // remove the pixels from main RAM.  The GSG is now responsible
     // 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::
 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;
   }
   }
-}
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: set_wrapv
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-void Texture::
-set_wrapv(Texture::WrapMode wrap) {
-  if (_wrapv != wrap) {
-    unprepare();
-    _wrapv = wrap;
+  // 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);
   }
   }
-}
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: set_minfilter
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-void Texture::
-set_minfilter(Texture::FilterType filter) {
-  if (_minfilter != filter) {
-    unprepare();
-    _minfilter = filter;
-  }
+  _all_dirty_flags |= flags_to_set;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     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.
+//     Function: Texture::register_with_read_factory
+//       Access: Public, Static
+//  Description: Factory method to generate a Texture object
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void Texture::
 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
 //     Function: Texture::make_Texture
 //       Access: Protected
 //       Access: Protected
@@ -598,13 +621,50 @@ make_Texture(const FactoryParams &params) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     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::
 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);
+        }
+      }
+    }
+  }
 }
 }
 
 
 
 

+ 64 - 43
panda/src/gobj/texture.h

@@ -33,6 +33,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 class PNMImage;
 class PNMImage;
+class TextureContext;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : Texture
 //       Class : Texture
@@ -78,10 +79,25 @@ PUBLISHED:
   virtual bool read(const string &name, const string &gray);
   virtual bool read(const string &name, const string &gray);
   virtual bool write(const string &name = "") const;
   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:
 public:
   bool load(const PNMImage &pnmimage);
   bool load(const PNMImage &pnmimage);
   bool store(PNMImage &pnmimage) const;
   bool store(PNMImage &pnmimage) const;
 
 
+  static bool is_mipmap(FilterType type);
+
   TextureContext *prepare(GraphicsStateGuardianBase *gsg);
   TextureContext *prepare(GraphicsStateGuardianBase *gsg);
   void unprepare();
   void unprepare();
   void unprepare(GraphicsStateGuardianBase *gsg);
   void unprepare(GraphicsStateGuardianBase *gsg);
@@ -100,50 +116,19 @@ public:
   virtual void draw(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
   virtual void draw(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
                     const RenderBuffer &rb);
                     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);
-
-  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;
-
-public:
-  static void register_with_read_factory(void);
-  virtual void write_datagram(BamWriter* manager, Datagram &me);
-
-  static TypedWritable *make_Texture(const FactoryParams &params);
-
-protected:
-  void fillin(DatagramIterator& scan, BamReader* manager);
+  // 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.
+  };
 
 
-public:
-  static TypeHandle get_class_type() {
-    return _type_handle;
-  }
-  static void init_type() {
-    ImageBuffer::init_type();
-    register_type(_type_handle, "Texture",
-                  ImageBuffer::get_class_type());
-  }
-  virtual TypeHandle get_type() const {
-    return get_class_type();
-  }
-  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+  void mark_dirty(int flags_to_set);
 
 
 private:
 private:
-
-  static TypeHandle _type_handle;
-
-  ////////////////////////////////////////////////////////////////////
-
-protected:
-
   WrapMode _wrapu;
   WrapMode _wrapu;
   WrapMode _wrapv;
   WrapMode _wrapv;
   FilterType _minfilter;
   FilterType _minfilter;
@@ -154,15 +139,19 @@ protected:
 
 
   // A Texture keeps a list (actually, a map) of all the GSG's that it
   // 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)
   // has been prepared into.  Each GSG conversely keeps a list (a set)
-  // of all the Texture's that have been prepared there.  When either
+  // of all the Textures that have been prepared there.  When either
   // destructs, it removes itself from the other's list.
   // destructs, it removes itself from the other's list.
   typedef pmap<GraphicsStateGuardianBase *, TextureContext *> Contexts;
   typedef pmap<GraphicsStateGuardianBase *, TextureContext *> Contexts;
   Contexts _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
   // These are public to allow direct manipulation of the underlying
   // pixel buffer when needed.  Know what you are doing!
   // pixel buffer when needed.  Know what you are doing!
-public:
   PT(PixelBuffer) _pbuffer;
   PT(PixelBuffer) _pbuffer;
 
 
   // If you request a region from the framebuffer that is not a power of 2,
   // If you request a region from the framebuffer that is not a power of 2,
@@ -172,6 +161,38 @@ public:
   bool _has_requested_size;
   bool _has_requested_size;
   int _requested_w;
   int _requested_w;
   int _requested_h;
   int _requested_h;
+
+
+
+  // Datagram stuff
+public:
+  static void register_with_read_factory(void);
+  virtual void write_datagram(BamWriter* manager, Datagram &me);
+
+  static TypedWritable *make_Texture(const FactoryParams &params);
+
+protected:
+  void fillin(DatagramIterator& scan, BamReader* manager);
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    ImageBuffer::init_type();
+    register_type(_type_handle, "Texture",
+                  ImageBuffer::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+
+  static TypeHandle _type_handle;
+
+  friend TextureContext;
 };
 };
 
 
 #include "texture.I"
 #include "texture.I"

+ 91 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     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;
+}
+

+ 2 - 2
panda/src/display/textureContext.cxx → panda/src/gobj/textureContext.cxx

@@ -18,8 +18,8 @@
 
 
 #include "textureContext.h"
 #include "textureContext.h"
 
 
-#include <pixelBuffer.h>
-#include <texture.h>
+#include "pixelBuffer.h"
+#include "texture.h"
 
 
 TypeHandle TextureContext::_type_handle;
 TypeHandle TextureContext::_type_handle;
 
 

+ 10 - 3
panda/src/display/textureContext.h → panda/src/gobj/textureContext.h

@@ -19,11 +19,10 @@
 #ifndef TEXTURECONTEXT_H
 #ifndef TEXTURECONTEXT_H
 #define TEXTURECONTEXT_H
 #define TEXTURECONTEXT_H
 
 
-#include <pandabase.h>
+#include "pandabase.h"
 
 
 #include "savedContext.h"
 #include "savedContext.h"
-
-class Texture;
+#include "texture.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : TextureContext
 //       Class : TextureContext
@@ -49,6 +48,14 @@ public:
   // reference count.
   // reference count.
   Texture *_texture;
   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:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 1 - 14
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_xsize() * pb->get_ysize() * pb->get_num_components() *
         pb->get_component_width();
         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;
         bytes *= 4/3;
       }
       }