OSGParallelComposer.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *               Copyright (C) 2000-2002 by the OpenSG Forum                 *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 
00039 //---------------------------------------------------------------------------
00040 //  Includes
00041 //---------------------------------------------------------------------------
00042 
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <iostream>
00046 
00047 #include <OSGConfig.h>
00048 
00049 #include "OSGParallelComposer.h"
00050 
00051 
00052 OSG_USING_NAMESPACE
00053 
00054 /***************************************************************************\
00055  *                            Description                                  *
00056 \***************************************************************************/
00057 
00062 /***************************************************************************\
00063  *                           Class variables                               *
00064 \***************************************************************************/
00065 
00066 /***************************************************************************\
00067  *                           Class methods                                 *
00068 \***************************************************************************/
00069 
00070 void ParallelComposer::initMethod(InitPhase ePhase)
00071 {
00072     Inherited::initMethod(ePhase);
00073 }
00074 
00075 
00076 /***************************************************************************\
00077  *                           Instance methods                              *
00078 \***************************************************************************/
00079 
00080 /*-------------------------------------------------------------------------*\
00081  -  private                                                                 -
00082 \*-------------------------------------------------------------------------*/
00083 
00084 /*----------------------- constructors & destructors ----------------------*/
00085 
00086 ParallelComposer::ParallelComposer(void) :
00087     Inherited()
00088 {
00089 }
00090 
00091 ParallelComposer::ParallelComposer(const ParallelComposer &source) :
00092     Inherited(source)
00093 {
00094 }
00095 
00096 ParallelComposer::~ParallelComposer(void)
00097 {
00098 }
00099 
00100 /*----------------------------- features ----------------------------------*/
00101 
00102 bool ParallelComposer::clientRendering(void)
00103 {
00104     return false;
00105 }
00106 
00107 bool ParallelComposer::getClientRendering(void)
00108 {
00109     return false;
00110 }
00111 
00112 UInt32 ParallelComposer::getUsableServers(void)
00113 {
00114     return _usableServers;
00115 }
00116 /*----------------------------- composition -------------------------------*/
00117 
00118 void ParallelComposer::open(void)
00119 {
00120 #ifdef OSG_WITH_PARALLEL
00121     if(getPcLibPath() != "")
00122     {
00123         pcSysInitialize(getPcLibPath().c_str(), 123458);
00124     }
00125     else
00126     {
00127         char *pc = getenv("PCLIB_PATH");
00128         if(pc!= NULL)
00129             pcSysInitialize(pc, 123458);
00130         else
00131             pcSysInitialize(".", 123458);
00132     }
00133     
00134     // Initialize buffers
00135     _bufColor      = NULL;
00136     _bufDepth      = NULL;
00137     _bufRet        = NULL;
00138     _createContext = true;
00139     
00140     // determine usable servers
00141     _usableServers = serverCount();
00142 
00143     // create server cross connection
00144     _clusterWindow->getNetwork()->connectAllPointToPoint(clusterId(),
00145                                                          "StreamSock");
00146     // do not buffer any data
00147     for(UInt32 i=0 ; i <= serverCount() ; ++i)
00148         clusterWindow()->getNetwork()->getConnection(i)->forceDirectIO();   
00149     // populate server list from inherited cluster window
00150     osgGetHostname(_serviceAddr, sizeof(_serviceAddr));
00151 
00152     _serverList = new char*[_usableServers+2];
00153     _serverList[0]  = _serviceAddr;
00154     int i = 1;
00155     for(; i<_usableServers+1; i++)
00156     {
00157         _serverList[i] = (char*)clusterWindow()->getServers(i-1).c_str();
00158     }
00159     _serverList[i]= NULL;
00160 #endif
00161 }
00162 
00163 void ParallelComposer::composeViewport(ViewportPtr port)
00164 {
00165 #ifdef OSG_WITH_PARALLEL
00166     // setup viewport
00167     GLint 
00168         pl=port->getPixelLeft(), 
00169         pr=port->getPixelRight(),
00170         pb=port->getPixelBottom(), 
00171         pt=port->getPixelTop();
00172     if(_wWidth != pr-pl+1 || _wHeight != pt-pb+1)
00173     {
00174         _wWidth = pr-pl+1;
00175         _wHeight= pt-pb+1;
00176         _createContext = true;
00177     }
00178     bool full = port->isFullWindow();
00179     glViewport(pl, pb, _wWidth, _wHeight);
00180     glScissor(pl, pb, _wWidth, _wHeight);
00181     if(! full)
00182         glEnable(GL_SCISSOR_TEST);
00183 
00184     GLboolean depth = glIsEnabled(GL_DEPTH_TEST);
00185     GLboolean blend = glIsEnabled(GL_BLEND);
00186 
00187     glDisable(GL_DEPTH_TEST);
00188     glPushMatrix();
00189     glLoadIdentity();
00190     glMatrixMode(GL_PROJECTION);
00191     glPushMatrix();
00192     glLoadIdentity();
00193     glOrtho(0, port->getPixelWidth(),
00194             0, port->getPixelHeight(),-1,1);
00195 
00196     if(_createContext)
00197     {
00198         createCtx(port);
00199         _createContext = false;
00200     }
00201 
00202     if(getAlpha())
00203     {
00204         glEnable(GL_BLEND);
00205         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00206     }
00207 
00208     if(isClient())
00209     {
00210         UInt32 id = beginFrame();
00211         renderRead();
00212         endFrame(id);
00213         drawFrame();
00214     }
00215     else
00216     {
00217         if(clusterId() < _usableServers)
00218         {
00219             UInt32 id = beginFrame();
00220             renderRead();
00221             endFrame(id);
00222             //drawFrame();
00223         }
00224     }
00225     glPopMatrix();
00226     glMatrixMode(GL_MODELVIEW);
00227     glPopMatrix();
00228     glEnable(GL_DEPTH_TEST);
00229 
00230     // reset state
00231     if(depth && !glIsEnabled(GL_DEPTH_TEST))
00232         glEnable(GL_DEPTH_TEST);
00233     if(!blend && glIsEnabled(GL_BLEND))
00234         glDisable(GL_BLEND);
00235 #endif
00236 }
00237 
00238 void ParallelComposer::close(void)
00239 {
00240 #ifdef OSG_WITH_PARALLEL
00241     pcContextDestroy(_context);
00242     pcSysFinalize();
00243 #endif
00244 }
00245 
00246 /*----------------------------- class specific ----------------------------*/
00247 
00248 void ParallelComposer::changed(ConstFieldMaskArg whichField, 
00249                                UInt32            origin,
00250                                BitVector         details)
00251 {
00252     Inherited::changed(whichField, origin, details);
00253 }
00254 
00255 void ParallelComposer::dump(      UInt32    , 
00256                          const BitVector ) const
00257 {
00258     SLOG << "Dump ParallelComposer NI" << std::endl;
00259 }
00260 
00261 /*----------------------------- helpers ----------------------------------*/
00262 
00263 void ParallelComposer::createCtx( ViewportPtr port)
00264 {
00265 #ifdef OSG_WITH_PARALLEL
00266     // get needed attributes from viewport
00267     PCint attribs[40];
00268     UInt32 i = 0;
00269     PCerr err;
00270     
00271     attribs[i++] = PC_FRAME_WIDTH;              attribs[i++] = _wWidth;
00272     attribs[i++] = PC_FRAME_HEIGHT;             attribs[i++] = _wHeight;
00273     attribs[i++] = PC_COMPOSITE_TYPE;           attribs[i++] = PC_COMP_DEPTH;
00274     attribs[i++] = PC_PIXEL_FORMAT;             attribs[i++] = PC_PF_BGRA8|PC_PF_Z32I;
00275     // maybe this will change?
00276     attribs[i++] = PC_OUTPUT_DEPTH;             attribs[i++] = 1;
00277     // maybe more, force depth? compression?
00278     attribs[i++] = PC_ATTRIB_END;
00279      
00280     if(isClient())
00281     {
00282         // we need a global context
00283         err = pcContextCreateGlobal(attribs, _serverList, _serviceAddr, &_context);
00284         if(err)
00285         {
00286             SLOG  << "Error creating global context" << std::endl;
00287         }
00288     }
00289     else
00290     {
00291         // create a local context
00292         err = pcContextCreateLocal(PC_ID_DEFAULT, _serviceAddr, &_context);
00293         if(err)
00294         {
00295             SLOG << "Error creating local context" << std::endl;
00296         }
00297     }
00298     
00299     if(isClient())
00300     {
00301         pcContextSetInteger(_context,PC_OUTPUT_LEFT,PC_LOCALHOST_INDEX,0);
00302         pcContextSetInteger(_context,PC_OUTPUT_TOP,PC_LOCALHOST_INDEX,0);
00303         pcContextSetInteger(_context,PC_OUTPUT_WIDTH,PC_LOCALHOST_INDEX,_wWidth);
00304         pcContextSetInteger(_context,PC_OUTPUT_HEIGHT,PC_LOCALHOST_INDEX,_wHeight);
00305     }
00306     
00307     if(_bufColor)
00308         delete [] _bufColor;
00309     _bufColor = new UInt8 [_wWidth * _wHeight * 4 * sizeof(GLubyte)];
00310      
00311     if(_bufDepth)
00312         delete [] _bufDepth;
00313     _bufDepth = new UInt8 [_wWidth * _wHeight  * sizeof(GLuint)];
00314 #endif
00315 }
00316 
00317 void ParallelComposer::endFrame(UInt32 id)
00318 {
00319 #ifdef OSG_WITH_PARALLEL
00320     
00321     PCerr err;
00322 
00323     /* send the pixels */
00324     err = pcFrameAddFramelet(_context,id,_bufColor,_bufDepth);
00325     if(err)
00326     {
00327         SLOG << "Error adding framelet in endFrame" << std::endl;
00328     }
00329     //}
00330     
00331     /* done with the frame */
00332     err = pcFrameEnd(_context,id);
00333     if(err)
00334     {
00335         SLOG << "Error while calling pcFrameEnd" << std::endl;
00336     }
00337     if (isClient()) 
00338     {
00339         /* grab the results */
00340         err = pcFrameResult(_context,id,0,0,_wWidth,_wHeight,reinterpret_cast<void**>(&_bufRet),NULL,
00341                           &_rowPixels);
00342         if(err)
00343         {
00344             SLOG << "Error while getting frame results" << std::endl;
00345         }
00346     }
00347 
00348 #endif
00349 }
00350 
00351 UInt32 ParallelComposer::beginFrame(void)
00352 {
00353    UInt32 id = 0;
00354 #ifdef OSG_WITH_PARALLEL
00355    PCerr err;
00356 
00357    /* start the frame (all framelets are full size thus, NULLs) */  
00358    err = pcFrameBegin(_context, &id, 1, NULL, NULL, NULL, NULL, NULL);
00359    if(err)
00360    {
00361        SLOG << "Error while calling beginFrame" << std::endl;
00362    }
00363 #endif
00364    return(id);
00365 }
00366 
00367 void ParallelComposer::drawFrame(void)
00368 {
00369 #ifdef OSG_WITH_PARALLEL
00370    if (isClient()) 
00371    {
00372        if (!_bufRet) return;
00373        glDisable(GL_DEPTH_TEST);
00374        glPixelStorei(GL_UNPACK_ROW_LENGTH,_rowPixels);
00375        glDrawPixels(_wWidth,_wHeight,GL_BGRA,GL_UNSIGNED_BYTE,_bufRet);
00376        glEnable(GL_DEPTH_TEST);
00377        // swap buffers?
00378        _bufRet = NULL;
00379    }
00380 #endif
00381 }
00382 
00383 void ParallelComposer::renderRead(void)
00384 {
00385 #ifdef OSG_WITH_PARALLEL
00386     /* readback the pixels */
00387     glPixelStorei(GL_PACK_ROW_LENGTH,_wWidth);
00388     glReadPixels(0,0,_wWidth,_wHeight,GL_BGRA,GL_UNSIGNED_BYTE,_bufColor);
00389     glReadPixels(0,0,_wWidth,_wHeight,GL_DEPTH_COMPONENT,GL_UNSIGNED_INT,
00390                    _bufDepth);
00391 #endif
00392 }
00393