Equalizer  1.3.1-git
eqPixelBench/channel.cpp
00001 
00002 /* Copyright (c) 2007-2012, 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 lunchbox::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     LBASSERT( 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     lunchbox::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             glFinish();
00197             size_t nLoops = 0;
00198             clock.reset();
00199             while( clock.getTime64() < 100 /*ms*/ )
00200             {
00201                 image->startReadback( eq::Frame::BUFFER_COLOR, pvp, zoom,
00202                                       glObjects );
00203                 image->finishReadback( zoom, glObjects->glewGetContext( ));
00204                 ++nLoops;
00205             }
00206             glFinish();
00207             event.msec = clock.getTimef() / float( nLoops );
00208 
00209             const eq::PixelData& pixels =
00210                 image->getPixelData( eq::Frame::BUFFER_COLOR );
00211             event.area.x() = pixels.pvp.w;             
00212             event.area.y() = pixels.pvp.h;
00213             event.dataSizeGPU = pixels.pvp.getArea() * _enums[i].pixelSize;
00214             event.dataSizeCPU = 
00215             image->getPixelDataSize( eq::Frame::BUFFER_COLOR );
00216 
00217             GLenum error = glGetError();
00218             if( error != GL_NO_ERROR )
00219                 event.msec = -static_cast<float>( error );
00220             config->sendEvent( event );
00221 
00222             // write
00223             eq::Compositor::ImageOp op;
00224             op.channel = this;
00225             op.buffers = eq::Frame::BUFFER_COLOR;
00226             op.offset = offset;
00227             op.zoom = zoom;
00228 
00229             event.data.type = ConfigEvent::ASSEMBLE;
00230             event.dataSizeCPU = 
00231                 image->getPixelDataSize( eq::Frame::BUFFER_COLOR );
00232 
00233             clock.reset();
00234             eq::Compositor::assembleImage( image, op );
00235             event.msec = clock.getTimef();
00236 
00237             const eq::PixelData& pixelA =
00238                 image->getPixelData( eq::Frame::BUFFER_COLOR );
00239             event.area.x() = pixelA.pvp.w; 
00240             event.area.y() = pixelA.pvp.h;
00241             event.dataSizeGPU =
00242                 image->getPixelDataSize( eq::Frame::BUFFER_COLOR );
00243 
00244             error = glGetError();
00245             
00246             if( error != GL_NO_ERROR )
00247                 event.msec = -static_cast<float>( error );
00248             config->sendEvent( event );
00249         }
00250     }
00251 }
00252 
00253 void Channel::_testTiledOperations()
00254 {
00255     //----- setup constant data
00256     const eq::Images& images = _frame.getImages();
00257     LBASSERT( images[0] );
00258 
00259     eq::Config* config = getConfig();
00260     const eq::PixelViewport& pvp    = getPixelViewport();
00261     const eq::Vector2i     offset( pvp.x, pvp.y );
00262 
00263     ConfigEvent event = _createConfigEvent();
00264     event.area.x() = pvp.w;
00265 
00266     lunchbox::Clock clock;
00267     eq::Window::ObjectManager* glObjects = getObjectManager();
00268     const GLEWContext* glewContext = glewGetContext();
00269 
00270     //----- test tiled assembly algorithms
00271     eq::PixelViewport subPVP = pvp;
00272     subPVP.h /= NUM_IMAGES;
00273 
00274     for( unsigned i = 0; i < NUM_IMAGES; ++i )
00275     {
00276         LBASSERT( images[ i ] );
00277         images[ i ]->setPixelViewport( subPVP );
00278     }
00279 
00280     for( unsigned tiles = 0; tiles < NUM_IMAGES; ++tiles )
00281     {
00282         _draw( 0 );
00283 
00284         event.area.y() = subPVP.h * (tiles+1);
00285 
00286         //---- readback of 'tiles' depth images
00287         event.data.type = ConfigEvent::READBACK;
00288         snprintf( event.formatType, 32, "%d depth tiles", tiles+1 ); 
00289 
00290         event.msec = 0;
00291         for( unsigned j = 0; j <= tiles; ++j )
00292         {
00293             subPVP.y = pvp.y + j * subPVP.h;
00294             eq::Image* image = images[ j ];
00295             LBCHECK( image->allocDownloader( eq::Frame::BUFFER_DEPTH, 
00296                              EQ_COMPRESSOR_TRANSFER_DEPTH_TO_DEPTH_UNSIGNED_INT,
00297                                              glewContext ));
00298             image->clearPixelData( eq::Frame::BUFFER_DEPTH );
00299 
00300             clock.reset();
00301             image->startReadback( eq::Frame::BUFFER_DEPTH, subPVP,
00302                                   eq::Zoom::NONE, glObjects );
00303             image->finishReadback( eq::Zoom::NONE, glObjects->glewGetContext( ));
00304             event.msec += clock.getTimef();
00305             
00306         }
00307 
00308         config->sendEvent( event );
00309 
00310         if( tiles == NUM_IMAGES-1 )
00311             for( unsigned j = 0; j <= tiles; ++j )
00312                 _saveImage( images[j],
00313                             "EQ_COMPRESSOR_DATATYPE_DEPTH_UNSIGNED_INT",
00314                             "tiles" );
00315 
00316         //---- readback of 'tiles' color images
00317         event.data.type = ConfigEvent::READBACK;
00318         snprintf( event.formatType, 32, "%d color tiles", tiles+1 );
00319 
00320         event.msec = 0;
00321         for( unsigned j = 0; j <= tiles; ++j )
00322         {
00323             subPVP.y = pvp.y + j * subPVP.h;
00324             eq::Image* image = images[ j ];
00325 
00326             LBCHECK( image->allocDownloader( eq::Frame::BUFFER_COLOR, 
00327                                             EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGRA,
00328                                               glewContext ));
00329             image->clearPixelData( eq::Frame::BUFFER_COLOR );
00330 
00331             clock.reset();
00332             image->startReadback( eq::Frame::BUFFER_COLOR, subPVP,
00333                                   eq::Zoom::NONE, glObjects );
00334             image->finishReadback( eq::Zoom::NONE, glObjects->glewGetContext( ));
00335             event.msec += clock.getTimef();
00336         }
00337         config->sendEvent( event );
00338 
00339         if( tiles == NUM_IMAGES-1 )
00340             for( unsigned j = 0; j <= tiles; ++j )
00341                 _saveImage( images[j],"EQ_COMPRESSOR_DATATYPE_BGRA","tiles" );
00342 
00343         //---- benchmark assembly operations
00344         subPVP.y = pvp.y + tiles * subPVP.h;
00345 
00346         eq::Compositor::ImageOp op;
00347         op.channel = this;
00348         op.buffers = eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH;
00349         op.offset  = offset;
00350 
00351         // fixed-function
00352         event.data.type = ConfigEvent::ASSEMBLE;
00353         snprintf( event.formatType, 32, "tiles, GL1.1, %d images", tiles+1 ); 
00354 
00355         clock.reset();
00356         for( unsigned j = 0; j <= tiles; ++j )
00357             eq::Compositor::assembleImage( images[j], op );
00358 
00359         event.msec = clock.getTimef();
00360         config->sendEvent( event );
00361 
00362         // CPU
00363         snprintf( event.formatType, 32, "tiles, CPU,   %d images", tiles+1 ); 
00364 
00365         std::vector< eq::Frame* > frames;
00366         frames.push_back( &_frame );
00367 
00368         clock.reset();
00369         eq::Compositor::assembleFramesCPU( frames, this );
00370         event.msec = clock.getTimef();
00371         config->sendEvent( event );
00372     }
00373 }
00374 
00375 void Channel::_testDepthAssemble()
00376 {
00377     //----- setup constant data
00378     const eq::Images& images = _frame.getImages();
00379     eq::Image* image  = images[ 0 ];
00380     LBASSERT( image );
00381 
00382     eq::Config* config = getConfig();
00383     const eq::PixelViewport& pvp    = getPixelViewport();
00384     const eq::Vector2i offset( pvp.x, pvp.y );
00385 
00386     ConfigEvent event = _createConfigEvent();
00387     event.area.x() = pvp.w;
00388 
00389     lunchbox::Clock clock;
00390     eq::Window::ObjectManager* glObjects = getObjectManager();
00391     const GLEWContext* glewContext = glewGetContext();
00392 
00393     //----- test depth-based assembly algorithms
00394     for( unsigned i = 0; i < NUM_IMAGES; ++i )
00395     {
00396         image = images[ i ];
00397         LBASSERT( image );
00398         image->setPixelViewport( pvp );
00399     }
00400 
00401     event.area.y() = pvp.h;
00402 
00403     for( unsigned i = 0; i < NUM_IMAGES; ++i )
00404     {
00405         _draw( i );
00406 
00407         // fill depth & color image
00408         image = images[ i ];
00409 
00410         LBCHECK( image->allocDownloader( eq::Frame::BUFFER_COLOR, 
00411                                          EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGRA, 
00412                                          glewContext ));
00413 
00414         LBCHECK( image->allocDownloader( eq::Frame::BUFFER_DEPTH, 
00415                              EQ_COMPRESSOR_TRANSFER_DEPTH_TO_DEPTH_UNSIGNED_INT,
00416                                          glewContext ));
00417 
00418         image->clearPixelData( eq::Frame::BUFFER_COLOR );
00419         image->clearPixelData( eq::Frame::BUFFER_DEPTH );
00420 
00421         image->startReadback( eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH,
00422                               pvp, eq::Zoom::NONE, glObjects );
00423         image->finishReadback( eq::Zoom::NONE, glObjects->glewGetContext( ));
00424 
00425         if( i == NUM_IMAGES-1 )
00426             _saveImage( image,"EQ_COMPRESSOR_DATATYPE_DEPTH_UNSIGNED_INT",
00427                               "depthAssemble" );
00428 
00429         // benchmark
00430         eq::Compositor::ImageOp op;
00431         op.channel = this;
00432         op.buffers = eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH;
00433         op.offset  = offset;
00434 
00435         // fixed-function
00436         event.data.type = ConfigEvent::ASSEMBLE;
00437         snprintf( event.formatType, 32, "depth, GL1.1, %d images", i+1 ); 
00438 
00439         clock.reset();
00440         for( unsigned j = 0; j <= i; ++j )
00441             eq::Compositor::assembleImageDB_FF( images[j], op );
00442 
00443         event.msec = clock.getTimef();
00444         config->sendEvent( event );
00445 
00446         // GLSL
00447         if( GLEW_VERSION_2_0 )
00448         {
00449             snprintf( event.formatType, 32, "depth, GLSL,  %d images", i+1 ); 
00450 
00451             clock.reset();
00452             for( unsigned j = 0; j <= i; ++j )
00453                 eq::Compositor::assembleImageDB_GLSL( images[j], op );
00454             event.msec = clock.getTimef();
00455             config->sendEvent( event );
00456         }
00457 
00458         // CPU
00459         snprintf( event.formatType, 32, "depth, CPU,   %d images", i+1 ); 
00460 
00461         std::vector< eq::Frame* > frames;
00462         frames.push_back( &_frame );
00463 
00464         clock.reset();
00465         eq::Compositor::assembleFramesCPU( frames, this );
00466         event.msec = clock.getTimef();
00467         config->sendEvent( event );
00468     }
00469 }
00470 
00471 void Channel::_saveImage( const eq::Image* image,
00472                           const char*      externalformat,
00473                           const char*      info    )
00474 {
00475     return;
00476 
00477     static uint32_t counter = 0;
00478     std::ostringstream stringstream;
00479     stringstream << "Image_" << ++counter << "_" << externalformat << "_"
00480                  << info;
00481     image->writeImages( stringstream.str( ));
00482 }
00483 
00484 void Channel::_draw( const eq::uint128_t& spin )
00485 {
00486     glPushAttrib( GL_ALL_ATTRIB_BITS );
00487 
00488     eq::Channel::frameDraw( spin );
00489 
00490     glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
00491     glEnable( GL_DEPTH_TEST );
00492 
00493 #if 0
00494     setNearFar( 0.5f, 5.0f );
00495     const GLfloat lightPosition[]    = {5.0f, 0.0f, 5.0f, 0.0f};
00496     const GLfloat lightDiffuse[]     = {0.8f, 0.8f, 0.8f, 1.0f};
00497 
00498     const GLfloat materialDiffuse[]  = {0.8f, 0.8f, 0.8f, 1.0f};
00499 
00500     glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
00501     glLightfv( GL_LIGHT0, GL_DIFFUSE,  lightDiffuse  );
00502 
00503     glMaterialfv( GL_FRONT, GL_DIFFUSE,   materialDiffuse );
00504 
00505     eq::Matrix4f rotation;
00506     eq::Vector3f translation;
00507 
00508     translation   = eq::Vector3f::ZERO;
00509     translation.z = -2.f;
00510     rotation = eq::Matrix4f::IDENTITY;
00511     rotation.rotate_x( static_cast<float>( -M_PI_2 ));
00512     rotation.rotate_y( static_cast<float>( -M_PI_2 ));
00513 
00514     glTranslatef( translation.x, translation.y, translation.z );
00515     glMultMatrixf( rotation.ml );
00516 
00517     glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00518     glColor3f( 1.f, 1.f, 0.f );
00519     glNormal3f( 1.f, -1.f, 0.f );
00520     glBegin( GL_TRIANGLE_STRIP );
00521         glVertex3f(  1.f, 10.f,  2.5f );
00522         glVertex3f( -1.f, 10.f,  2.5f );
00523         glVertex3f(  1.f,-10.f, -2.5f );
00524         glVertex3f( -1.f,-10.f, -2.5f );
00525     glEnd();
00526 
00527 #else
00528 
00529     const float lightPos[] = { 0.0f, 0.0f, 1.0f, 0.0f };
00530     glLightfv( GL_LIGHT0, GL_POSITION, lightPos );
00531 
00532     const float lightAmbient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
00533     glLightfv( GL_LIGHT0, GL_AMBIENT, lightAmbient );
00534 
00535     // rotate scene around the origin
00536     glRotatef( static_cast< float >( spin.low() + 3 ) * 10, 1.0f, 0.5f, 0.25f );
00537 
00538     // render six axis-aligned colored quads around the origin
00539     //  front
00540     glColor3f( 1.0f, 0.5f, 0.5f );
00541     glNormal3f( 0.0f, 0.0f, 1.0f );
00542     glBegin( GL_TRIANGLE_STRIP );
00543     glVertex3f(  .7f,  .7f, -1.0f );
00544     glVertex3f( -.7f,  .7f, -1.0f );
00545     glVertex3f(  .7f, -.7f, -1.0f );
00546     glVertex3f( -.7f, -.7f, -1.0f );
00547     glEnd();
00548 
00549     //  bottom
00550     glColor3f( 0.5f, 1.0f, 0.5f );
00551     glNormal3f( 0.0f, 1.0f, 0.0f );
00552     glBegin( GL_TRIANGLE_STRIP );
00553     glVertex3f(  .7f, -1.0f,  .7f );
00554     glVertex3f( -.7f, -1.0f,  .7f );
00555     glVertex3f(  .7f, -1.0f, -.7f );
00556     glVertex3f( -.7f, -1.0f, -.7f );
00557     glEnd();
00558 
00559     //  back
00560     glColor3f( 0.5f, 0.5f, 1.0f );
00561     glNormal3f( 0.0f, 0.0f, -1.0f );
00562     glBegin( GL_TRIANGLE_STRIP );
00563     glVertex3f(  .7f,  .7f, 1.0f );
00564     glVertex3f( -.7f,  .7f, 1.0f );
00565     glVertex3f(  .7f, -.7f, 1.0f );
00566     glVertex3f( -.7f, -.7f, 1.0f );
00567     glEnd();
00568 
00569     //  top
00570     glColor3f( 1.0f, 1.0f, 0.5f );
00571     glNormal3f( 0.f, -1.f, 0.f );
00572     glBegin( GL_TRIANGLE_STRIP );
00573     glVertex3f(  .7f, 1.0f,  .7f );
00574     glVertex3f( -.7f, 1.0f,  .7f );
00575     glVertex3f(  .7f, 1.0f, -.7f );
00576     glVertex3f( -.7f, 1.0f, -.7f );
00577     glEnd();
00578 
00579     //  right
00580     glColor3f( 1.0f, 0.5f, 1.0f );
00581     glNormal3f( -1.f, 0.f, 0.f );
00582     glBegin( GL_TRIANGLE_STRIP );
00583     glVertex3f( 1.0f,  .7f,  .7f );
00584     glVertex3f( 1.0f, -.7f,  .7f );
00585     glVertex3f( 1.0f,  .7f, -.7f );
00586     glVertex3f( 1.0f, -.7f, -.7f );
00587     glEnd();
00588 
00589     //  left
00590     glColor3f( 0.5f, 1.0f, 1.0f );
00591     glNormal3f( 1.f, 0.f, 0.f );
00592     glBegin( GL_TRIANGLE_STRIP );
00593     glVertex3f( -1.0f,  .7f,  .7f );
00594     glVertex3f( -1.0f, -.7f,  .7f );
00595     glVertex3f( -1.0f,  .7f, -.7f );
00596     glVertex3f( -1.0f, -.7f, -.7f );
00597     glEnd();
00598 
00599 #endif
00600 
00601     glPopAttrib( );
00602 }
00603 
00604 
00605 }
Generated on Tue May 1 2012 15:14:24 for Equalizer 1.3.1-git by  doxygen 1.8.0