Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

GlDrawManager.cpp

Go to the documentation of this file.
00001 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00002  *
00003  * VR Juggler is (C) Copyright 1998-2003 by Iowa State University
00004  *
00005  * Original Authors:
00006  *   Allen Bierbaum, Christopher Just,
00007  *   Patrick Hartling, Kevin Meinert,
00008  *   Carolina Cruz-Neira, Albert Baker
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Library General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Library General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Library General Public
00021  * License along with this library; if not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00023  * Boston, MA 02111-1307, USA.
00024  *
00025  * -----------------------------------------------------------------
00026  * File:          $RCSfile: GlDrawManager.cpp,v $
00027  * Date modified: $Date: 2004/04/28 17:57:43 $
00028  * Version:       $Revision: 1.113 $
00029  * -----------------------------------------------------------------
00030  *
00031  *************** <auto-copyright.pl END do not edit this line> ***************/
00032 
00033 #include <vrj/vrjConfig.h>
00034 
00035 #include <stdlib.h>
00036 #include <boost/concept_check.hpp>
00037 
00038 #include <cluster/ClusterManager.h>
00039 
00040 #include <vrj/Display/DisplayManager.h>
00041 #include <vrj/Kernel/Kernel.h>
00042 
00043 #include <vrj/Display/Display.h>
00044 #include <vrj/Display/Viewport.h>
00045 #include <vrj/Display/SimViewport.h>
00046 #include <vrj/Display/SurfaceViewport.h>
00047 
00048 #include <vrj/Draw/OGL/GlApp.h>
00049 
00050 #include <vrj/Draw/OGL/GlPipe.h>
00051 #include <vrj/Draw/OGL/GlWindow.h>
00052 #include <vrj/Draw/OGL/GlSimInterfaceFactory.h>
00053 
00054 #include <gmtl/Vec.h>
00055 #include <gmtl/Output.h>
00056 
00057 //#include <gadget/Type/Glove.h>
00058 //#include <gadget/Type/GloveProxy.h>
00059 
00060 #include <vrj/Draw/OGL/GlDrawManager.h>
00061 
00062 
00063 namespace vrj
00064 {
00065 
00066 vprSingletonImp(GlDrawManager);
00067 
00068 GlDrawManager::GlDrawManager()
00069    : mApp(NULL)
00070    , drawTriggerSema(0)
00071    , drawDoneSema(0)
00072 //   , mRuntimeConfigSema(0)
00073    , mRunning(false)
00074    , mMemberFunctor(NULL)
00075    , mControlThread(NULL)
00076 {
00077 }
00078 
00080 void GlDrawManager::setApp(App* _app)
00081 {
00082    mApp = dynamic_cast<GlApp*>(_app);
00083 
00084    // We have a new app, so the contexts must be re-initialized
00085    // so... dirty them all.
00086    dirtyAllWindows();
00087    vprASSERT(mApp != NULL);
00088 }
00089 
00091 GlApp* GlDrawManager::getApp()
00092 {
00093    return mApp;
00094 }
00095 
00100 /*
00101 void GlDrawManager::configInitial(jccl::Configuration* cfg)
00102 {
00103     // Setup any config data
00104 }
00105 */
00106 
00108 void GlDrawManager::start()
00109 {
00110    // --- Setup Multi-Process stuff --- //
00111    // Create a new thread to handle the control
00112    mRunning = true;
00113 
00114    mMemberFunctor =
00115       new vpr::ThreadMemberFunctor<GlDrawManager>(this, &GlDrawManager::main,
00116                                                   NULL);
00117    mControlThread = new vpr::Thread(mMemberFunctor);
00118 
00119    vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00120       << "vrj::GlDrawManager started (thread: " << mControlThread << ")\n"
00121       << vprDEBUG_FLUSH;
00122 }
00123 
00124 
00125     // Enable a frame to be drawn
00126     // Trigger draw
00127 void GlDrawManager::draw()
00128 {
00129    drawTriggerSema.release();
00130 }
00131 
00132 
00137 void GlDrawManager::sync()
00138 {
00139    drawDoneSema.acquire();
00140 }
00141 
00142 
00144 void GlDrawManager::main(void* nullParam)
00145 {
00146    boost::ignore_unused_variable_warning(nullParam);
00147 
00148    while(mRunning)
00149    {
00150       //**// Runtime config will happen here
00151       // Because the kernel is the only one that can trigger it
00152       // we will be waiting here at that time
00153 
00154       // Wait for trigger
00155       drawTriggerSema.acquire();
00156 
00157       // While closing the GlDrawManager this thread will be waiting at
00158       // drawTriggerSema.acquire(). To properly stop this thread we must
00159       // allow it to fall through the semaphore and not execute drawAllPipes()
00160       if (mRunning)
00161       {
00162          // THEN --- Do Rendering --- //
00163          drawAllPipes();
00164       }
00165 
00166       // -- Done rendering --- //
00167       drawDoneSema.release();
00168 
00169       // Allow run-time config
00170       //**//mRuntimeConfigSema.release();
00171          // This is the time that reconfig can happen
00172       // configProcessPending();
00173       //**//mRuntimeConfigSema.acquire();
00174    }
00175 }
00176 
00177 void GlDrawManager::drawAllPipes()
00178 {
00179    vprDEBUG_BEGIN(vrjDBG_DRAW_MGR,vprDBG_HVERB_LVL)
00180       << "vjGLDrawManager::drawAllPipes: " << std::endl << std::flush
00181       << vprDEBUG_FLUSH;
00182    unsigned int pipeNum;
00183 
00184    // RENDER
00185       // Start rendering all the pipes
00186    for(pipeNum=0; pipeNum<pipes.size(); pipeNum++)
00187       pipes[pipeNum]->triggerRender();
00188 
00189       // Wait for rendering to finish on all the pipes
00190    for(pipeNum=0; pipeNum<pipes.size(); pipeNum++)
00191       pipes[pipeNum]->completeRender();
00192 
00193    // Barrier for Cluster
00194    //vprDEBUG(vprDBG_ALL, vprDBG_STATE_LVL) <<  "BARRIER: Going to sleep for: " << num << std::endl << vprDEBUG_FLUSH;
00195    cluster::ClusterManager::instance()->createBarrier();
00196    //vprDEBUG(vprDBG_ALL, vprDBG_STATE_LVL) <<  "BARRIER: IS DONE" << std::endl << vprDEBUG_FLUSH;
00197 
00198 
00199    // SWAP
00200       // Start swapping all the pipes
00201    for(pipeNum=0; pipeNum<pipes.size(); pipeNum++)
00202       pipes[pipeNum]->triggerSwap();
00203 
00204       // Wait for swapping to finish on all the pipes
00205    for(pipeNum=0; pipeNum<pipes.size(); pipeNum++)
00206       pipes[pipeNum]->completeSwap();
00207 
00208 
00209    vprDEBUG_END(vrjDBG_DRAW_MGR,vprDBG_HVERB_LVL)
00210       << "vjGLDrawManager::drawAllPipes: Done" << std::endl << std::flush
00211       << vprDEBUG_FLUSH;
00212 }
00213 
00218 void GlDrawManager::initAPI()
00219 {
00220    start();
00221 }
00222 
00223 
00233 void GlDrawManager::addDisplay(Display* disp)
00234 {
00235    vprASSERT(disp != NULL);    // Can't add a null display
00236 
00237    vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_STATE_LVL)
00238       << "vrj::GlDrawManager:addDisplay: " << disp
00239       << std::endl << vprDEBUG_FLUSH;
00240 
00241 
00242    // -- Finish Simulator setup
00243    int num_vp(disp->getNumViewports());
00244 
00245    for (int i = 0 ; i < num_vp ; i++)
00246    {
00247       Viewport* vp = disp->getViewport(i);
00248 
00249       if (vp->isSimulator())
00250       {
00251          jccl::ConfigElementPtr vp_element = vp->getConfigElement();
00252 
00253          SimViewport* sim_vp(NULL);
00254          sim_vp = dynamic_cast<SimViewport*>(vp);
00255          vprASSERT(NULL != sim_vp);
00256 
00257          sim_vp->setDrawSimInterface(NULL);
00258 
00259          // Create the simulator stuff
00260          vprASSERT(1 == vp_element->getNum("simulator_plugin") && "You must supply a simulator plugin.");
00261 
00262          // Create the simulator stuff
00263          jccl::ConfigElementPtr sim_element =
00264             vp_element->getProperty<jccl::ConfigElementPtr>("simulator_plugin");
00265 
00266          vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_CONFIG_LVL)
00267             << "GlDrawManager::addDisplay() creating simulator of type '"
00268             << sim_element->getID() << "'\n" << vprDEBUG_FLUSH;
00269 
00270          DrawSimInterface* new_sim_i =
00271             GlSimInterfaceFactory::instance()->createObject(sim_element->getID());
00272 
00273          // XXX: Change this to an error once the new simulator loading code is
00274          // more robust.  -PH (4/13/2003)
00275          vprASSERT(NULL != new_sim_i && "Failed to create draw simulator");
00276          sim_vp->setDrawSimInterface(new_sim_i);
00277          new_sim_i->initialize(sim_vp);
00278          new_sim_i->config(sim_element);
00279       }
00280    }
00281 
00282 
00283    // -- Create a window for new display
00284    // -- Store the window in the wins vector
00285    // Create the gl window object.  NOTE: The glPipe actually "creates" the opengl window and context later
00286    GlWindow* new_win = getGLWindow();
00287    new_win->configWindow(disp);                                            // Configure it
00288    mWins.push_back(new_win);                                         // Add to our local window list
00289 
00290    // -- Create any needed Pipes & Start them
00291    unsigned int pipe_num = new_win->getDisplay()->getPipe();    // Find pipe to add it too
00292 
00293    if(pipes.size() < (pipe_num+1))           // ASSERT: Max index of pipes is < our pipe
00294    {                                         // +1 because if pipeNum = 0, I still need size() == 1
00295       while(pipes.size() < (pipe_num+1))     // While we need more pipes
00296       {
00297          GlPipe* new_pipe = new GlPipe(pipes.size(), this);  // Create a new pipe to use
00298          pipes.push_back(new_pipe);                          // Add the pipe
00299          new_pipe->start();                                  // Start the pipe running
00300                                                              // NOTE: Run pipe even if no windows.  Then it waits for windows.
00301       }
00302    }
00303 
00304    // -- Add window to the correct pipe
00305    GlPipe* pipe;                           // The pipe to assign it to
00306    pipe = pipes[pipe_num];                    // ASSERT: pipeNum is in the valid range
00307    pipe->addWindow(new_win);              // Window has been added
00308 
00309    vprASSERT(isValidWindow(new_win));      // Make sure it was added to draw manager
00310 }
00311 
00312 
00318 void GlDrawManager::removeDisplay(Display* disp)
00319 {
00320    GlPipe* pipe;  pipe = NULL;
00321    GlWindow* win; win = NULL;     // Window to remove
00322 
00323    for(unsigned int i=0;i<mWins.size();i++)
00324    {
00325       if(mWins[i]->getDisplay() == disp)      // FOUND it
00326       {
00327          win = mWins[i];
00328          pipe = pipes[win->getDisplay()->getPipe()];
00329       }
00330    }
00331 
00332    // Remove the window from the pipe and our local list
00333    if(win != NULL)
00334    {
00335       vprASSERT(pipe != NULL);
00336       vprASSERT(isValidWindow(win));
00337       pipe->removeWindow(win);                                                   // Remove from pipe
00338       mWins.erase(std::remove(mWins.begin(),mWins.end(),win), mWins.end());      // Remove from draw manager
00339       vprASSERT(!isValidWindow(win));
00340    }
00341    else
00342    {
00343       vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL) << clrOutNORM(clrRED,"ERROR:") << "vrj::GlDrawManager::removeDisplay: Attempted to remove a display that was not found.\n" << vprDEBUG_FLUSH;
00344       vprASSERT(false);
00345    }
00346 
00347 }
00348 
00349 
00351 void GlDrawManager::closeAPI()
00352 {
00353    vprDEBUG(vrjDBG_DRAW_MGR, vprDBG_STATE_LVL) << "vrj::GlDrawManager::closeAPI\n" << vprDEBUG_FLUSH;
00354 
00355    mRunning = false;
00356 
00357    drawTriggerSema.release();
00358    drawDoneSema.acquire();
00359 
00360    // TODO: Must shutdown and delete all pipes.
00361    // Stop and delete all pipes
00362 
00363    // TODO: We must fix the closing of EventWindows and GlWindows before we can do this.
00364    // Close and delete all glWindows
00365 }
00366 
00372 bool GlDrawManager::configAdd(jccl::ConfigElementPtr element)
00373 {
00374    boost::ignore_unused_variable_warning(element);
00375    return false;
00376 }
00377 
00383 bool GlDrawManager::configRemove(jccl::ConfigElementPtr element)
00384 {
00385    boost::ignore_unused_variable_warning(element);
00386    return false;
00387 }
00388 
00393 bool GlDrawManager::configCanHandle(jccl::ConfigElementPtr element)
00394 {
00395    boost::ignore_unused_variable_warning(element);
00396    return false;
00397 }
00398 
00399 
00404 void GlDrawManager::dirtyAllWindows()
00405 {
00406     // Create Pipes & Add all windows to the correct pipe
00407    for(unsigned int winId=0;winId<mWins.size();winId++)   // For each window we created
00408    {
00409       mWins[winId]->setDirtyContext(true);
00410    }
00411 }
00412 
00413 
00414 bool GlDrawManager::isValidWindow(GlWindow* win)
00415 {
00416    bool ret_val = false;
00417    for(unsigned int i=0;i<mWins.size();i++)
00418       if(mWins[i] == win)
00419          ret_val = true;
00420 
00421    return ret_val;
00422 }
00423 
00424 
00426 void GlDrawManager::outStream(std::ostream& out)
00427 {
00428     out     << clrSetNORM(clrGREEN)
00429             << "========== GlDrawManager: " << (void*)this << " ========="
00430             << clrRESET << std::endl
00431             << clrOutNORM(clrCYAN,"\tapp: ") << (void*)mApp << std::endl
00432             << clrOutNORM(clrCYAN,"\tWindow count: ") << mWins.size()
00433             << std::endl << std::flush;
00434 
00435     for(unsigned int i = 0; i < mWins.size(); i++)
00436     {
00437        vprASSERT(mWins[i] != NULL);
00438        out << clrOutNORM(clrCYAN,"\tGlWindow:\n") << *(mWins[i]) << std::endl;
00439     }
00440     out << "=======================================" << std::endl;
00441 }
00442 
00443 } // end vrj namespace
00444 
00445 
00446 #if  defined(VPR_OS_Win32)
00447 #  include <vrj/Draw/OGL/GlWindowWin32.h>
00448 #elif defined(VPR_OS_Darwin) && ! defined(VRJ_USE_X11)
00449 #  include <vrj/Draw/OGL/GlWindowOSX.h>
00450 #else
00451 #  include <vrj/Draw/OGL/GlWindowXWin.h>
00452 #endif
00453 
00454 namespace vrj
00455 {
00456 
00457 vrj::GlWindow* GlDrawManager::getGLWindow()
00458 {
00459 #if  defined(VPR_OS_Win32)
00460    return new vrj::GlWindowWin32;
00461 #elif defined(VPR_OS_Darwin) && ! defined(VRJ_USE_X11)
00462    return new vrj::GlWindowOSX;
00463 #else
00464    return new vrj::GlWindowXWin;
00465 #endif
00466 }
00467 
00468 } // end vrj namespace

Generated on Sun May 2 15:10:17 2004 for VR Juggler by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002