Equalizer 1.0

eqPixelBench/channel.cpp

00001 
00002 /* Copyright (c) 2007-2010, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions are met:
00006  *
00007  * - Redistributions of source code must retain the above copyright notice, this
00008  *   list of conditions and the following disclaimer.
00009  * - Redistributions in binary form must reproduce the above copyright notice,
00010  *   this list of conditions and the following disclaimer in the documentation
00011  *   and/or other materials provided with the distribution.
00012  * - Neither the name of Eyescale Software GmbH nor the names of its
00013  *   contributors may be used to endorse or promote products derived from this
00014  *   software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00026  * POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00029 #include "channel.h"
00030 
00031 #include "config.h"
00032 #include "configEvent.h"
00033 
00034 #include <co/plugins/compressor.h>
00035 
00036 #ifdef WIN32_API
00037 #  define snprintf _snprintf
00038 #endif
00039 
00040 namespace eqPixelBench
00041 {
00042 namespace
00043 {
00044 #pragma warning(disable: 411) // class defines no constructor to initialize ...
00045 struct EnumMap
00046 {
00047     const char*    internalFormatString;
00048     const uint32_t internalFormat;
00049     const size_t   pixelSize;
00050 };
00051 
00052 #pragma warning(default: 411)
00053 
00054 #define ENUM_MAP_ITEM( internalFormat, pixelSize )  \
00055     { #internalFormat, EQ_COMPRESSOR_DATATYPE_ ## internalFormat, pixelSize }
00056 
00057 static EnumMap _enums[] = {
00058     ENUM_MAP_ITEM( RGBA32F, 16 ), // initial buffer resize
00059     ENUM_MAP_ITEM( RGBA, 4 ),
00060     ENUM_MAP_ITEM( RGB10_A2, 4 ),
00061     ENUM_MAP_ITEM( RGBA16F, 8 ),
00062     ENUM_MAP_ITEM( RGBA32F, 16 ),
00063     ENUM_MAP_ITEM( DEPTH, 4 ),
00064     { 0, 0, 0 }};
00065 #define NUM_IMAGES 8
00066 }
00067 
00068 Channel::Channel( eq::Window* parent )
00069         : eq::Channel( parent )
00070 {
00071     eq::FrameData* frameData = new eq::FrameData;
00072     _frame.setData( frameData );
00073 
00074     for( unsigned i = 0; i < NUM_IMAGES; ++i )
00075         frameData->newImage( eq::Frame::TYPE_MEMORY, getDrawableConfig( ));
00076 }
00077 
00078 void Channel::frameStart( const eq::uint128_t& frameID, const uint32_t frameNumber ) 
00079 {
00080     Config* config = static_cast< Config* >( getConfig( ));
00081     const co::base::Clock* clock  = config->getClock();
00082 
00083     if( clock )
00084     {
00085         ConfigEvent   event;
00086         event.msec = clock->getTimef();
00087 
00088         const std::string& name  = getName();
00089         if( name.empty( ))    
00090             snprintf( event.data.user.data, 32, "%p", this);
00091         else
00092             snprintf( event.data.user.data, 32, "%s", name.c_str( ));
00093 
00094         event.data.user.data[31] = 0;
00095         event.area.x() = 0;
00096         event.area.y() = 0;
00097 
00098         snprintf( event.formatType, 32, "app->pipe thread latency");
00099         event.data.type = ConfigEvent::START_LATENCY;
00100 
00101         config->sendEvent( event );
00102     }
00103 
00104     eq::Channel::frameStart( frameID, frameNumber );
00105 }
00106 
00107 void Channel::frameDraw( const eq::uint128_t& frameID )
00108 {
00109     //----- setup GL state
00110     applyBuffer();
00111     applyViewport();
00112 
00113     glMatrixMode( GL_PROJECTION );
00114     glLoadIdentity();
00115 
00116     applyFrustum();
00117 
00118     glMatrixMode( GL_MODELVIEW );
00119     glLoadIdentity();
00120     applyHeadTransform();
00121 
00122     setupAssemblyState();
00123 
00124     _testFormats( 1.0f );
00125     _testFormats( 0.5f );
00126     _testFormats( 2.0f );
00127     _testTiledOperations();
00128     _testDepthAssemble();
00129 
00130     resetAssemblyState();
00131 }
00132 
00133 ConfigEvent Channel::_createConfigEvent()
00134 {
00135     ConfigEvent   event;
00136     const std::string& name = getName();
00137 
00138     if( name.empty( ))    
00139         snprintf( event.data.user.data, 32, "%p", this );
00140     else
00141         snprintf( event.data.user.data, 32, "%s", name.c_str( ));
00142 
00143     event.data.user.data[31] = 0;
00144     return event;
00145 }
00146 
00147 void Channel::_testFormats( float applyZoom )
00148 {
00149     //----- setup constant data
00150     const eq::Images& images = _frame.getImages();
00151     eq::Image*        image  = images[ 0 ];
00152     EQASSERT( image );
00153 
00154     Config* config = static_cast< Config* >( getConfig( ));
00155     const eq::PixelViewport& pvp = getPixelViewport();
00156     const eq::Vector2i offset( pvp.x, pvp.y );
00157     const eq::Zoom zoom( applyZoom, applyZoom );
00158 
00159     co::base::Clock clock;
00160     eq::Window::ObjectManager* glObjects = getObjectManager();
00161 
00162     //----- test all default format/type combinations
00163     ConfigEvent event = _createConfigEvent();
00164     glGetError();
00165     for( uint32_t i=0; _enums[i].internalFormatString; ++i )
00166     {
00167         const uint32_t internalFormat = _enums[i].internalFormat;
00168         image->flush();
00169         image->setInternalFormat( eq::Frame::BUFFER_COLOR, internalFormat );
00170         image->setQuality( eq::Frame::BUFFER_COLOR, 0.f );
00171         image->setAlphaUsage( false );
00172 
00173         const GLEWContext* glewContext = glewGetContext();
00174         std::vector< uint32_t > names;
00175         image->findTransferers( eq::Frame::BUFFER_COLOR, glewContext, names );
00176 
00177         for( std::vector< uint32_t >::const_iterator j = names.begin();
00178              j != names.end(); ++j )
00179         {
00180             _draw( 0 );
00181 
00182             // setup
00183             event.formatType[31] = '\0';
00184             event.data.type = ConfigEvent::READBACK;
00185 
00186             image->allocDownloader( eq::Frame::BUFFER_COLOR, *j, glewContext );
00187             image->setPixelViewport( pvp );
00188 
00189             const uint32_t outputToken = 
00190                 image->getExternalFormat( eq::Frame::BUFFER_COLOR );
00191             snprintf( event.formatType, 32, "%s/%x/%x", 
00192                 _enums[i].internalFormatString, outputToken, *j );
00193 
00194 
00195             // read
00196             clock.reset();
00197             image->readback( eq::Frame::BUFFER_COLOR, pvp, zoom, glObjects );
00198             event.msec = clock.getTimef();
00199 
00200             const eq::PixelData& pixels =
00201                 image->getPixelData( eq::Frame::BUFFER_COLOR );
00202             event.area.x() = pixels.pvp.w;             
00203             event.area.y() = pixels.pvp.h;
00204             event.dataSizeGPU = pixels.pvp.getArea() * _enums[i].pixelSize;
00205             event.dataSizeCPU = 
00206                 image->getPixelDataSize( eq::Frame::BUFFER_COLOR );
00207 
00208             GLenum error = glGetError();
00209             if( error != GL_NO_ERROR )
00210                 event.msec = -static_cast<float>( error );
00211             config->sendEvent( event );
00212 
00213             eq::Compositor::ImageOp op;
00214             op.channel = this;
00215             op.buffers = eq::Frame::BUFFER_COLOR;
00216             op.offset = offset;
00217             op.zoom = zoom;
00218 
00219             event.data.type = ConfigEvent::ASSEMBLE;
00220             event.dataSizeCPU = 
00221                 image->getPixelDataSize( eq::Frame::BUFFER_COLOR );
00222 
00223             clock.reset();
00224             eq::Compositor::assembleImage( image, op );
00225             event.msec = clock.getTimef();
00226 
00227             const eq::PixelData& pixelA =
00228                 image->getPixelData( eq::Frame::BUFFER_COLOR );
00229             event.area.x() = pixelA.pvp.w; 
00230             event.area.y() = pixelA.pvp.h;
00231             event.dataSizeGPU =
00232                 image->getPixelDataSize( eq::Frame::BUFFER_COLOR );
00233 
00234             error = glGetError();
00235             
00236             if( error != GL_NO_ERROR )
00237                 event.msec = -static_cast<float>( error );
00238             config->sendEvent( event );
00239         }
00240     }
00241 }
00242 
00243 void Channel::_testTiledOperations()
00244 {
00245     //----- setup constant data
00246     const eq::Images& images = _frame.getImages();
00247     EQASSERT( images[0] );
00248 
00249     eq::Config* config = getConfig();
00250     const eq::PixelViewport& pvp    = getPixelViewport();
00251     const eq::Vector2i     offset( pvp.x, pvp.y );
00252 
00253     ConfigEvent event = _createConfigEvent();
00254     event.area.x() = pvp.w;
00255 
00256     co::base::Clock clock;
00257     eq::Window::ObjectManager* glObjects = getObjectManager();
00258     const GLEWContext* glewContext = glewGetContext();
00259 
00260     //----- test tiled assembly algorithms
00261     eq::PixelViewport subPVP = pvp;
00262     subPVP.h /= NUM_IMAGES;
00263 
00264     for( unsigned i = 0; i < NUM_IMAGES; ++i )
00265     {
00266         EQASSERT( images[ i ] );
00267         images[ i ]->setPixelViewport( subPVP );
00268     }
00269 
00270     for( unsigned tiles = 0; tiles < NUM_IMAGES; ++tiles )
00271     {
00272         _draw( 0 );
00273 
00274         event.area.y() = subPVP.h * (tiles+1);
00275 
00276         //---- readback of 'tiles' depth images
00277         event.data.type = ConfigEvent::READBACK;
00278         snprintf( event.formatType, 32, "%d depth tiles", tiles+1 ); 
00279 
00280         event.msec = 0;
00281         for( unsigned j = 0; j <= tiles; ++j )
00282         {
00283             subPVP.y = pvp.y + j * subPVP.h;
00284             eq::Image* image = images[ j ];
00285             EQCHECK( image->allocDownloader( eq::Frame::BUFFER_DEPTH, 
00286                              EQ_COMPRESSOR_TRANSFER_DEPTH_TO_DEPTH_UNSIGNED_INT,
00287                                              glewContext ));
00288             image->clearPixelData( eq::Frame::BUFFER_DEPTH );
00289 
00290             clock.reset();
00291             image->readback( eq::Frame::BUFFER_DEPTH, subPVP, eq::Zoom(),
00292                              glObjects );
00293             event.msec += clock.getTimef();
00294             
00295         }
00296 
00297         config->sendEvent( event );
00298 
00299         if( tiles == NUM_IMAGES-1 )
00300             for( unsigned j = 0; j <= tiles; ++j )
00301                 _saveImage( images[j],
00302                             "EQ_COMPRESSOR_DATATYPE_DEPTH_UNSIGNED_INT",
00303                             "tiles" );
00304 
00305         //---- readback of 'tiles' color images
00306         event.data.type = ConfigEvent::READBACK;
00307         snprintf( event.formatType, 32, "%d color tiles", tiles+1 );
00308 
00309         event.msec = 0;
00310         for( unsigned j = 0; j <= tiles; ++j )
00311         {
00312             subPVP.y = pvp.y + j * subPVP.h;
00313             eq::Image* image = images[ j ];
00314 
00315             EQCHECK( image->allocDownloader( eq::Frame::BUFFER_COLOR, 
00316                                             EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGRA,
00317                                               glewContext ));
00318             image->clearPixelData( eq::Frame::BUFFER_COLOR );
00319 
00320             clock.reset();
00321             image->readback( eq::Frame::BUFFER_COLOR, subPVP, eq::Zoom(),
00322                              glObjects );
00323             event.msec += clock.getTimef();
00324         }
00325         config->sendEvent( event );
00326 
00327         if( tiles == NUM_IMAGES-1 )
00328             for( unsigned j = 0; j <= tiles; ++j )
00329                 _saveImage( images[j],"EQ_COMPRESSOR_DATATYPE_BGRA","tiles" );
00330 
00331         //---- benchmark assembly operations
00332         subPVP.y = pvp.y + tiles * subPVP.h;
00333 
00334         eq::Compositor::ImageOp op;
00335         op.channel = this;
00336         op.buffers = eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH;
00337         op.offset  = offset;
00338 
00339         // fixed-function
00340         event.data.type = ConfigEvent::ASSEMBLE;
00341         snprintf( event.formatType, 32, "tiles, GL1.1, %d images", tiles+1 ); 
00342 
00343         clock.reset();
00344         for( unsigned j = 0; j <= tiles; ++j )
00345             eq::Compositor::assembleImage( images[j], op );
00346 
00347         event.msec = clock.getTimef();
00348         config->sendEvent( event );
00349 
00350         // CPU
00351         snprintf( event.formatType, 32, "tiles, CPU,   %d images", tiles+1 ); 
00352 
00353         std::vector< eq::Frame* > frames;
00354         frames.push_back( &_frame );
00355 
00356         clock.reset();
00357         eq::Compositor::assembleFramesCPU( frames, this );
00358         event.msec = clock.getTimef();
00359         config->sendEvent( event );
00360     }
00361 }
00362 
00363 void Channel::_testDepthAssemble()
00364 {
00365     //----- setup constant data
00366     const eq::Images& images = _frame.getImages();
00367     eq::Image* image  = images[ 0 ];
00368     EQASSERT( image );
00369 
00370     eq::Config* config = getConfig();
00371     const eq::PixelViewport& pvp    = getPixelViewport();
00372     const eq::Vector2i offset( pvp.x, pvp.y );
00373 
00374     ConfigEvent event = _createConfigEvent();
00375     event.area.x() = pvp.w;
00376 
00377     co::base::Clock clock;
00378     eq::Window::ObjectManager* glObjects = getObjectManager();
00379     const GLEWContext* glewContext = glewGetContext();
00380 
00381     //----- test depth-based assembly algorithms
00382     for( unsigned i = 0; i < NUM_IMAGES; ++i )
00383     {
00384         image = images[ i ];
00385         EQASSERT( image );
00386         image->setPixelViewport( pvp );
00387     }
00388 
00389     event.area.y() = pvp.h;
00390 
00391     for( unsigned i = 0; i < NUM_IMAGES; ++i )
00392     {
00393         _draw( i );
00394 
00395         // fill depth & color image
00396         image = images[ i ];
00397 
00398         EQCHECK( image->allocDownloader( eq::Frame::BUFFER_COLOR, 
00399                                          EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGRA, 
00400                                          glewContext ));
00401 
00402         EQCHECK( image->allocDownloader( eq::Frame::BUFFER_DEPTH, 
00403                              EQ_COMPRESSOR_TRANSFER_DEPTH_TO_DEPTH_UNSIGNED_INT,
00404                                          glewContext ));
00405 
00406         image->clearPixelData( eq::Frame::BUFFER_COLOR );
00407         image->clearPixelData( eq::Frame::BUFFER_DEPTH );
00408 
00409         image->readback( eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH,
00410                          pvp, eq::Zoom(), glObjects );
00411 
00412         if( i == NUM_IMAGES-1 )
00413             _saveImage( image,"EQ_COMPRESSOR_DATATYPE_DEPTH_UNSIGNED_INT",
00414                               "depthAssemble" );
00415 
00416         // benchmark
00417         eq::Compositor::ImageOp op;
00418         op.channel = this;
00419         op.buffers = eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH;
00420         op.offset  = offset;
00421 
00422         // fixed-function
00423         event.data.type = ConfigEvent::ASSEMBLE;
00424         snprintf( event.formatType, 32, "depth, GL1.1, %d images", i+1 ); 
00425 
00426         clock.reset();
00427         for( unsigned j = 0; j <= i; ++j )
00428             eq::Compositor::assembleImageDB_FF( images[j], op );
00429 
00430         event.msec = clock.getTimef();
00431         config->sendEvent( event );
00432 
00433         // GLSL
00434         if( GLEW_VERSION_2_0 )
00435         {
00436             snprintf( event.formatType, 32, "depth, GLSL,  %d images", i+1 ); 
00437 
00438             clock.reset();
00439             for( unsigned j = 0; j <= i; ++j )
00440                 eq::Compositor::assembleImageDB_GLSL( images[j], op );
00441             event.msec = clock.getTimef();
00442             config->sendEvent( event );
00443         }
00444 
00445         // CPU
00446         snprintf( event.formatType, 32, "depth, CPU,   %d images", i+1 ); 
00447 
00448         std::vector< eq::Frame* > frames;
00449         frames.push_back( &_frame );
00450 
00451         clock.reset();
00452         eq::Compositor::assembleFramesCPU( frames, this );
00453         event.msec = clock.getTimef();
00454         config->sendEvent( event );
00455     }
00456 }
00457 
00458 void Channel::_saveImage( const eq::Image* image,
00459                           const char*      externalformat,
00460                           const char*      info    )
00461 {
00462     return;
00463 
00464     static uint32_t counter = 0;
00465     std::ostringstream stringstream;
00466     stringstream << "Image_" << ++counter << "_" << externalformat << "_"
00467                  << info;
00468     image->writeImages( stringstream.str( ));
00469 }
00470 
00471 void Channel::_draw( const eq::uint128_t& spin )
00472 {
00473     glPushAttrib( GL_ALL_ATTRIB_BITS );
00474 
00475     eq::Channel::frameDraw( spin );
00476 
00477     glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
00478     glEnable( GL_DEPTH_TEST );
00479 
00480 #if 0
00481     setNearFar( 0.5f, 5.0f );
00482     const GLfloat lightPosition[]    = {5.0f, 0.0f, 5.0f, 0.0f};
00483     const GLfloat lightDiffuse[]     = {0.8f, 0.8f, 0.8f, 1.0f};
00484 
00485     const GLfloat materialDiffuse[]  = {0.8f, 0.8f, 0.8f, 1.0f};
00486 
00487     glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
00488     glLightfv( GL_LIGHT0, GL_DIFFUSE,  lightDiffuse  );
00489 
00490     glMaterialfv( GL_FRONT, GL_DIFFUSE,   materialDiffuse );
00491 
00492     eq::Matrix4f rotation;
00493     eq::Vector3f translation;
00494 
00495     translation   = eq::Vector3f::ZERO;
00496     translation.z = -2.f;
00497     rotation = eq::Matrix4f::IDENTITY;
00498     rotation.rotate_x( static_cast<float>( -M_PI_2 ));
00499     rotation.rotate_y( static_cast<float>( -M_PI_2 ));
00500 
00501     glTranslatef( translation.x, translation.y, translation.z );
00502     glMultMatrixf( rotation.ml );
00503 
00504     glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00505     glColor3f( 1.f, 1.f, 0.f );
00506     glNormal3f( 1.f, -1.f, 0.f );
00507     glBegin( GL_TRIANGLE_STRIP );
00508         glVertex3f(  1.f, 10.f,  2.5f );
00509         glVertex3f( -1.f, 10.f,  2.5f );
00510         glVertex3f(  1.f,-10.f, -2.5f );
00511         glVertex3f( -1.f,-10.f, -2.5f );
00512     glEnd();
00513 
00514 #else
00515 
00516     const float lightPos[] = { 0.0f, 0.0f, 1.0f, 0.0f };
00517     glLightfv( GL_LIGHT0, GL_POSITION, lightPos );
00518 
00519     const float lightAmbient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
00520     glLightfv( GL_LIGHT0, GL_AMBIENT, lightAmbient );
00521 
00522     // rotate scene around the origin
00523     glRotatef( static_cast< float >( spin.low() + 3 ) * 10, 1.0f, 0.5f, 0.25f );
00524 
00525     // render six axis-aligned colored quads around the origin
00526     //  front
00527     glColor3f( 1.0f, 0.5f, 0.5f );
00528     glNormal3f( 0.0f, 0.0f, 1.0f );
00529     glBegin( GL_TRIANGLE_STRIP );
00530     glVertex3f(  .7f,  .7f, -1.0f );
00531     glVertex3f( -.7f,  .7f, -1.0f );
00532     glVertex3f(  .7f, -.7f, -1.0f );
00533     glVertex3f( -.7f, -.7f, -1.0f );
00534     glEnd();
00535 
00536     //  bottom
00537     glColor3f( 0.5f, 1.0f, 0.5f );
00538     glNormal3f( 0.0f, 1.0f, 0.0f );
00539     glBegin( GL_TRIANGLE_STRIP );
00540     glVertex3f(  .7f, -1.0f,  .7f );
00541     glVertex3f( -.7f, -1.0f,  .7f );
00542     glVertex3f(  .7f, -1.0f, -.7f );
00543     glVertex3f( -.7f, -1.0f, -.7f );
00544     glEnd();
00545 
00546     //  back
00547     glColor3f( 0.5f, 0.5f, 1.0f );
00548     glNormal3f( 0.0f, 0.0f, -1.0f );
00549     glBegin( GL_TRIANGLE_STRIP );
00550     glVertex3f(  .7f,  .7f, 1.0f );
00551     glVertex3f( -.7f,  .7f, 1.0f );
00552     glVertex3f(  .7f, -.7f, 1.0f );
00553     glVertex3f( -.7f, -.7f, 1.0f );
00554     glEnd();
00555 
00556     //  top
00557     glColor3f( 1.0f, 1.0f, 0.5f );
00558     glNormal3f( 0.f, -1.f, 0.f );
00559     glBegin( GL_TRIANGLE_STRIP );
00560     glVertex3f(  .7f, 1.0f,  .7f );
00561     glVertex3f( -.7f, 1.0f,  .7f );
00562     glVertex3f(  .7f, 1.0f, -.7f );
00563     glVertex3f( -.7f, 1.0f, -.7f );
00564     glEnd();
00565 
00566     //  right
00567     glColor3f( 1.0f, 0.5f, 1.0f );
00568     glNormal3f( -1.f, 0.f, 0.f );
00569     glBegin( GL_TRIANGLE_STRIP );
00570     glVertex3f( 1.0f,  .7f,  .7f );
00571     glVertex3f( 1.0f, -.7f,  .7f );
00572     glVertex3f( 1.0f,  .7f, -.7f );
00573     glVertex3f( 1.0f, -.7f, -.7f );
00574     glEnd();
00575 
00576     //  left
00577     glColor3f( 0.5f, 1.0f, 1.0f );
00578     glNormal3f( 1.f, 0.f, 0.f );
00579     glBegin( GL_TRIANGLE_STRIP );
00580     glVertex3f( -1.0f,  .7f,  .7f );
00581     glVertex3f( -1.0f, -.7f,  .7f );
00582     glVertex3f( -1.0f,  .7f, -.7f );
00583     glVertex3f( -1.0f, -.7f, -.7f );
00584     glEnd();
00585 
00586 #endif
00587 
00588     glPopAttrib( );
00589 }
00590 
00591 
00592 }
Generated on Sun May 8 2011 19:11:05 for Equalizer 1.0 by  doxygen 1.7.3