]> git.mxchange.org Git - flightgear.git/commitdiff
Initial stab at a threaded tile loader contributed by Bernie Bright.
authorcurt <curt>
Wed, 11 Apr 2001 02:47:15 +0000 (02:47 +0000)
committercurt <curt>
Wed, 11 Apr 2001 02:47:15 +0000 (02:47 +0000)
He writes:

Here are the final changes to add threads to the tile loading.  All the
thread related code is in the new FGTileLoader class.

./configure.in
./acconfig.h
Added --with-threads option and corresponding ENABLE_THREADS
definition.  The default is no threads.

./src/Scenery/tilemgr
Removed load_queue and associated references.  This has been replaced by
a new class FGTileLoader in FGNewCache.
Made the global variable global_tile_cache a member.
schedule_needed(): removed global_tile_cache.exists() tests since
sched_tile() effectively repeats the test.
initialize_queue(): removed code that loads tiles since this is now
performed by FGTileLoader.
update(): ditto

./src/Scenery/newcache
Added new class FGTileLoader to manage tile queuing and loading.
tile_map typedefs are private.
exists() is a const member function.
fill_in(): deleted
load_tile(): added.

./src/Scenery/FGTileLoader
The new threaded tile loader.  Maintains a queue of tiles waiting to be
loaded and an array of one or more threads to load the tiles.  Currently
only a single thread is created.  The queue is guarded by a mutex to
synchronize access.  A condition variable signals the thread when the
queue is non-empty.

CLO: I made a few tweaks to address a couple issues, hopefully what we
have is solid, but now we kick it out to the general public to see. :-)

17 files changed:
acconfig.h
src/FDM/flight.hxx
src/Include/config.h.in
src/Main/Makefile.am
src/Main/main.cxx
src/Objects/matlib.cxx
src/Objects/newmat.cxx
src/Objects/newmat.hxx
src/Scenery/FGTileLoader.cxx [new file with mode: 0644]
src/Scenery/FGTileLoader.hxx [new file with mode: 0644]
src/Scenery/Makefile.am
src/Scenery/newcache.cxx
src/Scenery/newcache.hxx
src/Scenery/tileentry.cxx
src/Scenery/tileentry.hxx
src/Scenery/tilemgr.cxx
src/Scenery/tilemgr.hxx

index b25353bc327b410f8f476b72e6ec53dcbb24a46b..94ae557f8d7b7a1ddf2dd741c4d48a7fc03c1941 100644 (file)
 /* Define if lex declares yytext as a char * by default, not a char[].  */
 #undef YYTEXT_POINTER
 
+/* Define to use tile loading threads */
+#undef ENABLE_THREADS
+
 \f
 /* Leave that blank line there!!  Autoheader needs it.
    If you're adding to this file, keep in mind:
index 20e22678098e928a6c5c9a7fc75fba30da5fbbdb..c04b12b8a00bc7abec2e8d43b058110c876c1cc4 100644 (file)
@@ -453,8 +453,8 @@ public:
     virtual void unbind ();
     virtual void update ();
     virtual bool update( int multi_loop );
-    virtual bool ToggleDataLogging(bool state) {};
-    virtual bool ToggleDataLogging(void) {};
+    virtual bool ToggleDataLogging(bool state) { return false; }
+    virtual bool ToggleDataLogging(void) { return false; }
 
     // Define the various supported flight models (many not yet implemented)
     enum {
index b1c6758c2cd1e19acda3f83b214c422d86704f1d..3c18956c748fa862c84648c611c235b2e4acbc17 100644 (file)
 /* Define if the X Window System is missing or not being used.  */
 #undef X_DISPLAY_MISSING
 
+/* Define to use tile loading threads */
+#undef ENABLE_THREADS
+
 /* Define if you have the GetLocalTime function.  */
 #undef HAVE_GETLOCALTIME
 
index 1f8250ec6646135b752339f9b18080cf27bdd191..15af75a39cbc3eac2cd6ef99c83766df3e3497df 100644 (file)
@@ -19,6 +19,12 @@ NETWORK_LIBS = \
        $(top_builddir)/src/Network/libNetwork.a
 endif
 
+if WITH_THREADS
+THREAD_LIBS = -lsgthreads
+else
+THREAD_LIBS =
+endif
+
 if OLD_AUTOMAKE
 # nothing CXXFLAGS += -DPKGLIBDIR=\"$(pkglibdir)\"
 else
@@ -73,6 +79,7 @@ fgfs_LDADD = \
        -lsgroute -lsgsky -lsgephem -lsgtiming -lsgio -lsgscreen \
        -lsgmath -lsgbucket -lsgdebug -lsgmagvar -lsgmisc -lsgxml \
        $(SERIAL_LIBS) \
+       $(THREAD_LIBS) \
        -lplibpu -lplibfnt -lplibssg -lplibsg \
        -lmk4 -lz \
        $(opengl_LIBS) \
index c4b6cd0def3147754d8f9ef3ec2540893de226ea..1eb0ae6858a5030b9264c856bc3b9c03bf05c399 100644 (file)
@@ -787,9 +787,9 @@ void fgUpdateTimeDepCalcs() {
        cur_fdm_state->update( 0 );
        FGSteam::update( 0 );
 
-       if ( global_tile_mgr.queue_size() == 0 ) {
+       //if ( global_tile_mgr.queue_size() == 0 ) {
            initial_freeze = false;
-       }
+           //}
     }
 
     if ( fgGetString("/sim/view-mode") == "pilot" ) {
index b1449a08e3988eb35147da6913b01b28b2442c51..25535f8f42eceee120417ef538612917065df1d0 100644 (file)
@@ -129,15 +129,16 @@ bool FGMaterialLib::load( const string& mpath ) {
                in >> m;
 
                // build the ssgSimpleState
-               SGPath tex_path( globals->get_fg_root() );
-               tex_path.append( "Textures.high" );
+               SGPath tmp_path( globals->get_fg_root() );
+               tmp_path.append( "Textures.high" );
 
-               SGPath tmp_path = tex_path;
-               tmp_path.append( m.get_texture_name() );
-               if ( ! local_file_exists(tmp_path.str())
+               SGPath tex_path = tmp_path;
+               tex_path.append( m.get_texture_name() );
+               if ( ! local_file_exists(tex_path.str())
                     || general.get_glMaxTexSize() < 512 ) {
                    tex_path = SGPath( globals->get_fg_root() );
                    tex_path.append( "Textures" );
+                   tex_path.append( m.get_texture_name() );
                }
            
                SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material " 
@@ -150,8 +151,10 @@ bool FGMaterialLib::load( const string& mpath ) {
                    shade_model = GL_FLAT;
                }
 
-               m.build_ssg_state( tex_path.str(), shade_model,
-                                  fgGetBool("/sim/rendering/textures") );
+               m.set_texture_name( tex_path.str() );
+               m.build_ssg_state( shade_model,
+                                  fgGetBool("/sim/rendering/textures"),
+                                  false );
 
 #if EXTRA_DEBUG
                m.dump_info();
@@ -201,10 +204,10 @@ bool FGMaterialLib::add_item ( const string &mat_name, const string &full_path )
     string tex_name = full_path.substr( pos + 1 );
     string tex_path = full_path.substr( 0, pos );
 
-    FGNewMat m( mat_name, tex_name );
+    FGNewMat m( mat_name, full_path );
 
     SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material " 
-           << mat_name << " (" << tex_path << ")");
+           << mat_name << " (" << full_path << ")");
 
 #if EXTRA_DEBUG
     m.dump_info();
@@ -217,8 +220,8 @@ bool FGMaterialLib::add_item ( const string &mat_name, const string &full_path )
        shade_model = GL_FLAT;
     }
 
-    m.build_ssg_state( tex_path, shade_model,
-                      fgGetBool("/sim/rendering/textures") );
+    m.build_ssg_state( shade_model, fgGetBool("/sim/rendering/textures"),
+                      true );
 
     material_lib.matlib[mat_name] = m;
 
index 15c82ad066787fb9d4bde154a26e35822293fa59..2fa702d61907d1ef04880f359ab9ff09a9a5c128 100644 (file)
@@ -70,12 +70,9 @@ FGNewMat::FGNewMat ( const string &mat_name, const string &tex_name )
 }
 
 
-void FGNewMat::build_ssg_state( const string& path,
-                               GLenum shade_model, bool texture_default )
+void FGNewMat::build_ssg_state( GLenum shade_model, bool texture_default,
+                               bool defer_tex_load )
 {
-    SGPath tex_file( path );
-    tex_file.append( texture_name );
-
     state = new ssgStateSelector(2);
     state->ref();
 
@@ -92,7 +89,12 @@ void FGNewMat::build_ssg_state( const string& path,
     textured->enable( GL_TEXTURE_2D );
     textured->disable( GL_BLEND );
     textured->disable( GL_ALPHA_TEST );
-    textured->setTexture( (char *)tex_file.c_str(), wrapu, wrapv );
+    if ( !defer_tex_load ) {
+       textured->setTexture( (char *)texture_name.c_str(), wrapu, wrapv );
+       texture_loaded = true;
+    } else {
+       texture_loaded = false;
+    }
     // cout << "wrap u = " << wrapu << " wrapv = " << wrapv << endl;
     textured->enable( GL_COLOR_MATERIAL );
     textured->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
index 43a640ef6be1f9de093a49f599751c2ef59ea1e4..39ff8f499dc64fede67f59b5ebba7b1efecea6bf 100644 (file)
@@ -89,6 +89,9 @@ private:
     // material properties
     sgVec4 ambient, diffuse, specular, emission;
 
+    // true if texture loading deferred, and not yet loaded
+    bool texture_loaded;
+
 public:
 
     // Constructor
@@ -102,8 +105,8 @@ public:
     friend istream& operator >> ( istream& in, FGNewMat& m );
 
     // void load_texture( const string& root );
-    void build_ssg_state( const string& path, 
-                         GLenum shade_model, bool texture_default );
+    void build_ssg_state( GLenum shade_model, bool texture_default,
+                         bool defer_tex_load = false );
     void set_ssg_state( ssgSimpleState *s );
 
     inline string get_material_name() const { return material_name; }
diff --git a/src/Scenery/FGTileLoader.cxx b/src/Scenery/FGTileLoader.cxx
new file mode 100644 (file)
index 0000000..5123953
--- /dev/null
@@ -0,0 +1,141 @@
+// FGTileLoader - Queue scenery tiles for loading.
+//
+// Written by Bernie Bright, started March 2001.
+//
+// Copyright (C) 2001  Bernard Bright - bbright@bigpond.net.au
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <Main/globals.hxx>
+#include "FGTileLoader.hxx"
+#include "tileentry.hxx"
+
+/**
+ * 
+ */
+FGTileLoader::FGTileLoader()
+{
+#ifdef ENABLE_THREADS
+    // Create and start the loader threads.
+    for (int i = 0; i < MAX_THREADS; ++i)
+    {
+       threads[i] = new LoaderThread(this);
+       threads[i]->start();
+    }
+#endif // ENABLE_THREADS
+}
+
+/**
+ * Terminate all threads.
+ */
+FGTileLoader::~FGTileLoader()
+{
+#ifdef ENABLE_THREADS
+    // Wake up its time to die.
+    cond.broadcast();
+
+    for (int i = 0; i < MAX_THREADS; ++i)
+    {
+       threads[i]->cancel();
+       threads[i]->join();
+    }    
+#endif // ENABLE_THREADS
+}
+
+/**
+ * 
+ */
+void
+FGTileLoader::add( FGTileEntry* tile )
+{
+    /**
+     * Initialise tile_path here and not in ctor to avoid problems
+     * with the initialastion order of global objects.
+     */
+    static bool beenhere = false;
+    if (!beenhere)
+    {
+       if ( globals->get_fg_scenery() != (string)"" ) {
+           tile_path.set( globals->get_fg_scenery() );
+       } else {
+           tile_path.set( globals->get_fg_root() );
+           tile_path.append( "Scenery" );
+       }
+       beenhere = true;
+    }
+
+#ifdef ENABLE_THREADS
+    mutex.lock();
+    tile_queue.push( tile );
+    // Signal waiting working threads.
+    cond.signal();
+    mutex.unlock();
+#else
+    tile->load( tile_path, true );
+#endif // ENABLE_THREADS
+}
+
+#ifdef ENABLE_THREADS
+/**
+ * 
+ */
+void
+FGTileLoader::LoaderThread::run()
+{
+    pthread_cleanup_push( cleanup_handler, loader );
+    while ( true ) {
+       // Wait for a load request to be placed in the queue.
+       loader->mutex.lock();
+       while (loader->empty())
+       {
+           loader->cond.wait( loader->mutex );
+       }
+
+       // Have we been canceled - exits if yes.
+       //pthread_testcancel();
+       if (loader->empty())
+       {
+           loader->mutex.unlock();
+           pthread_exit( PTHREAD_CANCELED );
+       }
+
+       // Grab the tile to load and release the mutex.
+       FGTileEntry* tile = loader->tile_queue.front();
+       loader->tile_queue.pop();
+       loader->mutex.unlock();
+
+       set_cancel( SGThread::CANCEL_DISABLE );
+       tile->load( loader->tile_path, true );
+       set_cancel( SGThread::CANCEL_DEFERRED );
+    }
+    pthread_cleanup_pop(1);
+}
+
+/**
+ * Ensure mutex is unlocked.
+ */
+void 
+cleanup_handler( void* arg )
+{
+    FGTileLoader* loader = (FGTileLoader*) arg;
+    loader->mutex.unlock();
+}
+#endif // ENABLE_THREADS
diff --git a/src/Scenery/FGTileLoader.hxx b/src/Scenery/FGTileLoader.hxx
new file mode 100644 (file)
index 0000000..f74ac3d
--- /dev/null
@@ -0,0 +1,135 @@
+// FGTileLoader - Queue scenery tiles for loading.
+//
+// Written by Bernie Bright, started March 2001.
+//
+// Copyright (C) 2001  Bernard Bright - bbright@bigpond.net.au
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#ifndef FG_TILE_LOADER_HXX
+#define FG_TILE_LOADER_HXX
+
+#include <queue>
+#include <pthread.h>
+
+#include <simgear/bucket/newbucket.hxx>
+#include <simgear/misc/sg_path.hxx>
+
+#ifdef ENABLE_THREADS
+#  include <simgear/threads/SGThread.hxx>
+#endif
+
+// Forward reference.
+class FGTileEntry;
+
+/**
+ * Queues tiles for loading, possibly by a separate thread.
+ */
+class FGTileLoader
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    FGTileLoader();
+
+    /**
+     * Destructor.
+     */
+    ~FGTileLoader();
+
+    /**
+     * Add a tile to the end of the load queue.
+     * @param tile The tile to be loaded from disk.
+     * @param vis Current visibilty (in feet?) (see FGTileMgr::vis).
+     */
+    void add( FGTileEntry* tile );
+
+    /**
+     * Returns whether the load queue is empty (contains no elements).
+     * @return true if load queue is empty otherwise returns false.
+     */
+    bool empty() const { return tile_queue.empty(); }
+
+private:
+
+private:
+
+    /**
+     * FIFO queue of tiles to load from data files.
+     */
+    std::queue< FGTileEntry* > tile_queue;
+
+    /**
+     * Base name of directory containing tile data file.
+     */
+    SGPath tile_path;
+
+#ifdef ENABLE_THREADS
+    /**
+     * Maximum number of threads to create for loading tiles.
+     */
+    enum { MAX_THREADS = 1 };
+
+    /**
+     * This class represents the thread of execution responsible for
+     * loading a tile.
+     */
+    class LoaderThread : public SGThread
+    {
+    public:
+       LoaderThread( FGTileLoader* l ) : loader(l) {}
+       ~LoaderThread() {}
+
+       /**
+        * Reads the tile from disk.
+        */
+       void run();
+
+    private:
+       FGTileLoader* loader;
+
+    private:
+       // not implemented.
+       LoaderThread();
+       LoaderThread( const LoaderThread& );
+       LoaderThread& operator=( const LoaderThread& );
+    };
+
+    friend class LoaderThread;
+
+    /**
+     * Array of loading threads.
+     */
+    LoaderThread* threads[ MAX_THREADS ];
+    
+    /**
+     * Lock and synchronize access to tile queue.
+     */
+    SGMutex mutex;
+    SGCondition cond;
+
+    /**
+     * Thread cleanup handler.
+     */
+    friend void cleanup_handler( void* );
+#endif // ENABLE_THREADS
+};
+
+#endif // FG_TILE_LOADER_HXX
index 370762135301cbb60e464a5b7c503d106f5fcaed..c79da6009dc5a123bcf43031ce17b355b9263963 100644 (file)
@@ -1,6 +1,7 @@
 noinst_LIBRARIES = libScenery.a
 
 libScenery_a_SOURCES = \
+       FGTileLoader.cxx FGTileLoader.hxx \
        hitlist.cxx hitlist.hxx \
        newcache.cxx newcache.hxx \
        scenery.cxx scenery.hxx \
index b6d26bb7f2bc0f47f3a797f20becfeb021f2c02a..46c3ef44b743f5384f38fb65ccf05b004eff29e3 100644 (file)
 
 #include "newcache.hxx"
 #include "tileentry.hxx"
-#include "tilemgr.hxx"         // temp, need to delete later
-
-SG_USING_NAMESPACE(std);
 
 
-// the tile cache
-FGNewCache global_tile_cache;
+SG_USING_NAMESPACE(std);
 
 
 // Constructor
@@ -68,7 +64,7 @@ void FGNewCache::entry_free( long cache_index ) {
     SG_LOG( SG_TERRAIN, SG_DEBUG, "FREEING CACHE ENTRY = " << cache_index );
     FGTileEntry *e = tile_cache[cache_index];
     e->free_tile();
-    delete( e );
+    delete e;
     tile_cache.erase( cache_index );
 }
 
@@ -107,14 +103,16 @@ void FGNewCache::init( void ) {
 
 
 // Search for the specified "bucket" in the cache
-bool FGNewCache::exists( const SGBucket& b ) {
+bool FGNewCache::exists( const SGBucket& b ) const {
     long tile_index = b.gen_index();
-    tile_map_iterator it = tile_cache.find( tile_index );
+    const_tile_map_iterator it = tile_cache.find( tile_index );
 
     return ( it != tile_cache.end() );
 }
 
 
+// depricated for threading
+#if 0
 // Fill in a tile cache entry with real data for the specified bucket
 void FGNewCache::fill_in( const SGBucket& b ) {
     SG_LOG( SG_TERRAIN, SG_DEBUG, "FILL IN CACHE ENTRY = " << b.gen_index() );
@@ -140,13 +138,12 @@ void FGNewCache::fill_in( const SGBucket& b ) {
     // Load the appropriate data file
     e->load( tile_path, true );
 }
+#endif
 
 
 // Ensure at least one entry is free in the cache
 void FGNewCache::make_space() {
     SG_LOG( SG_TERRAIN, SG_DEBUG, "Make space in cache" );
-
-    
     SG_LOG( SG_TERRAIN, SG_DEBUG, "cache entries = " << tile_cache.size() );
     SG_LOG( SG_TERRAIN, SG_DEBUG, "max size = " << max_cache_size );
 
@@ -169,26 +166,29 @@ void FGNewCache::make_space() {
            long index = current->first;
            FGTileEntry *e = current->second;
 
-           // calculate approximate distance from view point
-           sgdCopyVec3( abs_view_pos,
-                        globals->get_current_view()->get_abs_view_pos() );
-
-           SG_LOG( SG_TERRAIN, SG_DEBUG, "DIST Abs view pos = " 
-                   << abs_view_pos[0] << ","
-                   << abs_view_pos[1] << ","
-                   << abs_view_pos[2] );
-           SG_LOG( SG_TERRAIN, SG_DEBUG,
-                   "    ref point = " << e->center );
-
-           sgdVec3 center;
-           sgdSetVec3( center, e->center.x(), e->center.y(), e->center.z() );
-           dist = sgdDistanceVec3( center, abs_view_pos );
-
-           SG_LOG( SG_TERRAIN, SG_DEBUG, "    distance = " << dist );
-
-           if ( dist > max_dist ) {
-               max_dist = dist;
-               max_index = index;
+           if ( e->is_loaded() ) {
+               // calculate approximate distance from view point
+               sgdCopyVec3( abs_view_pos,
+                            globals->get_current_view()->get_abs_view_pos() );
+
+               SG_LOG( SG_TERRAIN, SG_DEBUG, "DIST Abs view pos = " 
+                       << abs_view_pos[0] << ","
+                       << abs_view_pos[1] << ","
+                       << abs_view_pos[2] );
+               SG_LOG( SG_TERRAIN, SG_DEBUG,
+                       "    ref point = " << e->center );
+
+               sgdVec3 center;
+               sgdSetVec3( center,
+                           e->center.x(), e->center.y(), e->center.z() );
+               dist = sgdDistanceVec3( center, abs_view_pos );
+
+               SG_LOG( SG_TERRAIN, SG_DEBUG, "    distance = " << dist );
+
+               if ( dist > max_dist ) {
+                   max_dist = dist;
+                   max_index = index;
+               }
            }
        }
 
@@ -206,3 +206,24 @@ void FGNewCache::make_space() {
        }
     }
 }
+
+
+/**
+ * Create a new tile and schedule it for loading.
+ */
+void
+FGNewCache::load_tile( const SGBucket& b )
+{
+    // clear out a distant entry in the cache if needed.
+    make_space();
+
+    // create the entry
+    FGTileEntry *e = new FGTileEntry( b );
+
+    // register it in the cache
+    long tile_index = b.gen_index();
+    tile_cache[tile_index] = e;
+
+    // Schedule tile for loading
+    loader.add( e );
+}
index ed7486f572c19803e86ff78b760c105671ee796b..4eb92388e8c5afc99731a0885c3595b721969791 100644 (file)
 #include <simgear/math/point3d.hxx>
 
 #include "tileentry.hxx"
+#include "FGTileLoader.hxx"
 
 SG_USING_STD(map);
 
-
-typedef map < long, FGTileEntry * > tile_map;
-typedef tile_map::iterator tile_map_iterator;
-typedef tile_map::const_iterator const_tile_map_iterator;
-
-
 // A class to store and manage a pile of tiles
 class FGNewCache {
 
+    typedef map < long, FGTileEntry * > tile_map;
+    typedef tile_map::iterator tile_map_iterator;
+    typedef tile_map::const_iterator const_tile_map_iterator;
+
     // cache storage space
     tile_map tile_cache;
 
@@ -70,6 +69,11 @@ class FGNewCache {
     // Free a tile cache entry
     void entry_free( long cache_index );
 
+    /**
+     * Queue tiles for loading.
+     */
+    FGTileLoader loader;
+
 public:
 
     // Constructor
@@ -82,13 +86,13 @@ public:
     void init( void );
 
     // Check if the specified "bucket" exists in the cache
-    bool exists( const SGBucket& b );
+    bool exists( const SGBucket& b ) const;
 
     // Ensure at least one entry is free in the cache
     void make_space();
 
     // Fill in a tile cache entry with real data for the specified bucket 
-    void fill_in( const SGBucket& b );
+    // void fill_in( const SGBucket& b );
 
     // Return a pointer to the specified tile cache entry 
     inline FGTileEntry *get_tile( const long tile_index ) {
@@ -119,11 +123,13 @@ public:
 
     inline int get_max_cache_size() const { return max_cache_size; }
     inline void set_max_cache_size( int m ) { max_cache_size = m; }
-};
 
-
-// the tile cache
-extern FGNewCache global_tile_cache;
+    /**
+     * Create a new tile and enqueue it for loading.
+     * @param b 
+     */
+    void load_tile( const SGBucket& b );
+};
 
 
 #endif // _NEWCACHE_HXX 
index d6964a24e865a3fbf25dcd58cf30acade2b0b6c2..f7c2a5e057c4939d2b5cfb3d51163668b1448d7d 100644 (file)
@@ -339,7 +339,7 @@ FGTileEntry::load( const SGPath& base, bool is_base )
     basename.append( index_str );
     string path = basename.str();
 
-    SG_LOG( SG_TERRAIN, SG_INFO, "Loading tile " << path );
+    SG_LOG( SG_TERRAIN, SG_DEBUG, "Loading tile " << path );
 
     // fgObjLoad will generate ground lighting for us ...
     ssgVertexArray *light_pts = new ssgVertexArray( 100 );
index 091110212d15b8c16e26f9795092d881bab93d9e..d2ff2909f3a1de703d66a628d48168c7e6d103df 100644 (file)
@@ -160,6 +160,12 @@ public:
      *        random ground light points
      */
     void load( const SGPath& base, bool is_base );
+
+    /**
+     * Return true if the tile entry is loaded, otherwise return false
+     * indicating that the loading thread is still working on this.
+     */
+   inline bool is_loaded() const { return loaded; }
 };
 
 
index 3b1f4315e4441bad5e8f6a606d6d932dfdbdec15..4bdcfda59c7ca9d16dd6c5b6188e4cb8b9007211 100644 (file)
@@ -93,7 +93,7 @@ int FGTileMgr::init() {
     } else {
        SG_LOG( SG_TERRAIN, SG_INFO,
                "... First time through." );
-       global_tile_cache.init();
+       tile_cache.init();
     }
 
     hit_list.clear();
@@ -113,29 +113,32 @@ int FGTileMgr::init() {
 // schedule a tile for loading
 void FGTileMgr::sched_tile( const SGBucket& b ) {
     // see if tile already exists in the cache
-    FGTileEntry *t = global_tile_cache.get_tile( b );
+    FGTileEntry *t = tile_cache.get_tile( b );
 
     if ( t == NULL ) {
         // register a load request
-        load_queue.push_back( b );
+       tile_cache.load_tile( b );
     }
 }
 
 
+// depricated for threading
+#if 0
 // load a tile
 void FGTileMgr::load_tile( const SGBucket& b ) {
     // see if tile already exists in the cache
-    FGTileEntry *t = global_tile_cache.get_tile( b );
+    FGTileEntry *t = tile_cache.get_tile( b );
 
     if ( t == NULL ) {
        SG_LOG( SG_TERRAIN, SG_DEBUG, "Loading tile " << b );
-       global_tile_cache.fill_in( b );
-       t = global_tile_cache.get_tile( b );
+       tile_cache.fill_in( b );
+       t = tile_cache.get_tile( b );
        t->prep_ssg_node( scenery.center, vis);
     } else {
        SG_LOG( SG_TERRAIN, SG_DEBUG, "Tile already in cache " << b );
     }
 }
+#endif
 
 
 static void CurrentNormalInLocalPlane(sgVec3 dst, sgVec3 src) {
@@ -215,20 +218,20 @@ void FGTileMgr::schedule_needed() {
 #else
     vis = current_weather.get_visibility();
 #endif
-    cout << "visibility = " << vis << endl;
+    // cout << "visibility = " << vis << endl;
 
     double tile_width = current_bucket.get_width_m();
     double tile_height = current_bucket.get_height_m();
-    cout << "tile width = " << tile_width << "  tile_height = " << tile_height
-        << endl;
+    // cout << "tile width = " << tile_width << "  tile_height = "
+    //      << tile_height !<< endl;
 
     xrange = (int)(vis / tile_width) + 1;
     yrange = (int)(vis / tile_height) + 1;
     if ( xrange < 1 ) { xrange = 1; }
     if ( yrange < 1 ) { yrange = 1; }
-    cout << "xrange = " << xrange << "  yrange = " << yrange << endl;
+    // cout << "xrange = " << xrange << "  yrange = " << yrange << endl;
 
-    global_tile_cache.set_max_cache_size( (2*xrange + 2) * (2*yrange + 2) );
+    tile_cache.set_max_cache_size( (2*xrange + 2) * (2*yrange + 2) );
 
     SGBucket b;
 
@@ -243,9 +246,7 @@ void FGTileMgr::schedule_needed() {
        for ( y = -1; y <= 1; ++y ) {
            if ( x != 0 || y != 0 ) {
                b = sgBucketOffset( longitude, latitude, x, y );
-               if ( ! global_tile_cache.exists( b ) ) {
-                   sched_tile( b );
-               }
+               sched_tile( b );
            }
        }
     }
@@ -255,9 +256,7 @@ void FGTileMgr::schedule_needed() {
        for ( y = -yrange; y <= yrange; ++y ) {
            if ( x < -1 || x > 1 || y < -1 || y > 1 ) {
                SGBucket b = sgBucketOffset( longitude, latitude, x, y );
-               if ( ! global_tile_cache.exists( b ) ) {
-                   sched_tile( b );
-               }
+               sched_tile( b );
            }
        }
     }
@@ -270,12 +269,12 @@ void FGTileMgr::initialize_queue()
     // system and load all relavant tiles
 
     SG_LOG( SG_TERRAIN, SG_INFO, "Updating Tile list for " << current_bucket );
-    cout << "tile cache size = " << global_tile_cache.get_size() << endl;
+    // cout << "tile cache size = " << tile_cache.get_size() << endl;
 
     int i;
 
     // wipe/initialize tile cache
-    // global_tile_cache.init();
+    // tile_cache.init();
     previous_bucket.make_bad();
 
     // build the local area list and schedule tiles for loading
@@ -285,6 +284,8 @@ void FGTileMgr::initialize_queue()
 
     schedule_needed();
 
+    // do we really want to lose this? CLO
+#if 0
     // Now force a load of the center tile and inner ring so we
     // have something to see in our first frame.
     for ( i = 0; i < 9; ++i ) {
@@ -297,6 +298,7 @@ void FGTileMgr::initialize_queue()
             load_tile( pending );
         }
     }
+#endif
 }
 
 
@@ -305,7 +307,7 @@ void FGTileMgr::initialize_queue()
 // tile_cache   -- which actually handles all the
 // (de)allocations  
 void FGTileMgr::destroy_queue() {
-    load_queue.clear();
+    // load_queue.clear();
 }
 
 
@@ -328,8 +330,8 @@ int FGTileMgr::update( double lon, double lat ) {
     current_bucket.set_bucket( longitude, latitude );
     // SG_LOG( SG_TERRAIN, SG_DEBUG, "Updating Tile list for " << current_bucket );
 
-    if ( global_tile_cache.exists( current_bucket ) ) {
-        current_tile = global_tile_cache.get_tile( current_bucket );
+    if ( tile_cache.exists( current_bucket ) ) {
+        current_tile = tile_cache.get_tile( current_bucket );
         scenery.next_center = current_tile->center;
     } else {
         SG_LOG( SG_TERRAIN, SG_WARN, "Tile not found (Ok if initializing)" );
@@ -346,6 +348,8 @@ int FGTileMgr::update( double lon, double lat ) {
        state = Running;
     }
 
+    // now handled by threaded tile pager
+#if 0
     if ( load_queue.size() ) {
        SG_LOG( SG_TERRAIN, SG_INFO, "Load queue size = " << load_queue.size()
                << " loading a tile" );
@@ -354,6 +358,7 @@ int FGTileMgr::update( double lon, double lat ) {
        load_queue.pop_front();
        load_tile( pending );
     }
+#endif
 
     if ( scenery.center == Point3D(0.0) ) {
        // initializing
@@ -419,15 +424,15 @@ void FGTileMgr::prep_ssg_nodes() {
     // selector and transform
 
     FGTileEntry *e;
-    global_tile_cache.reset_traversal();
+    tile_cache.reset_traversal();
 
-    while ( ! global_tile_cache.at_end() ) {
+    while ( ! tile_cache.at_end() ) {
         // cout << "processing a tile" << endl;
-        if ( (e = global_tile_cache.get_current()) ) {
+        if ( (e = tile_cache.get_current()) ) {
            e->prep_ssg_node( scenery.center, vis);
         } else {
             cout << "warning ... empty tile in cache" << endl;
         }
-       global_tile_cache.next();
+       tile_cache.next();
    }
 }
index 49d7135a64b71f3042e0585d2839866144fc7b30..e3f49e54cec7e3ed10b893367c0a6b0f67427af6 100644 (file)
 
 #include <simgear/compiler.h>
 
-#include <list>
-
 #include <plib/ssg.h>
 
 #include <simgear/bucket/newbucket.hxx>
 
 #include "hitlist.hxx"
-
-SG_USING_STD(list);
-
+#include "newcache.hxx"
 
 #if defined(USE_MEM) || defined(WIN32)
 #  define FG_MEM_COPY(to,from,n)        memcpy(to, from, n)
@@ -66,9 +62,6 @@ private:
 
     load_state state;
 
-    // pending tile load queue
-    list < SGBucket > load_queue;
-
     // initialize the cache
     void initialize_queue();
 
@@ -80,9 +73,6 @@ private:
     // schedule a tile for loading
     void sched_tile( const SGBucket& b );
 
-    // load a tile
-    void load_tile( const SGBucket& b );
-
     // schedule a needed buckets for loading
     void schedule_needed();
 
@@ -111,6 +101,11 @@ private:
     double last_longitude;
     double last_latitude;
 
+    /**
+     * 
+     */
+    FGNewCache tile_cache;
+
 public:
 
     // Constructor
@@ -144,8 +139,6 @@ public:
     // transform and update it's range selector based on current
     // visibilty
     void prep_ssg_nodes();
-
-    inline int queue_size() const { return load_queue.size(); }
 };