Equalizer
1.2.1
|
00001 00002 /* Copyright (c) 2009-2011, Maxim Makhinya <maxmah@gmail.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 00030 #include "asyncFetcher.h" 00031 #include "eqAsync.h" 00032 00033 #include <eq/eq.h> 00034 #include <eq/client/system.h> 00035 #ifdef AGL 00036 # include "aglWindowShared.h" 00037 #endif 00038 #ifdef GLX 00039 # include "glXWindowShared.h" 00040 #endif 00041 00042 namespace eqAsync 00043 { 00044 00045 static eq::SystemWindow* initSharedContextWindow( eq::Window* wnd ) 00046 { 00047 EQASSERT( wnd ); 00048 00049 // store old drawable of window and set window's drawable to FBO, 00050 // create another (shared) osWindow and restore original drowable 00051 const int32_t drawable = 00052 wnd->getIAttribute( eq::Window::IATTR_HINT_DRAWABLE ); 00053 wnd->setIAttribute( eq::Window::IATTR_HINT_DRAWABLE, eq::FBO ); 00054 00055 const int32_t stencil = 00056 wnd->getIAttribute( eq::Window::IATTR_PLANES_STENCIL ); 00057 wnd->setIAttribute( eq::Window::IATTR_PLANES_STENCIL, eq::OFF ); 00058 00059 const eq::Pipe* pipe = wnd->getPipe(); 00060 EQASSERT( pipe ); 00061 00062 eq::SystemWindow* sharedContextWindow = 0; 00063 00064 const std::string& ws = pipe->getWindowSystem().getName(); 00065 00066 #ifdef GLX 00067 if( ws == "GLX" ) 00068 { 00069 EQINFO << "Using GLXWindow" << std::endl; 00070 sharedContextWindow = new GLXWindowShared( wnd ); 00071 } 00072 #endif 00073 #ifdef AGL 00074 if( ws == "AGL" ) 00075 { 00076 EQINFO << "Using AGLWindow" << std::endl; 00077 sharedContextWindow = new AGLWindowShared( wnd ); 00078 } 00079 #endif 00080 #ifdef WGL 00081 if( ws == "WGL" ) 00082 { 00083 EQINFO << "Using WGLWindow" << std::endl; 00084 sharedContextWindow = new eq::wgl::Window( wnd ); 00085 } 00086 #endif 00087 if( !sharedContextWindow ) 00088 { 00089 EQERROR << "Window system " << pipe->getWindowSystem() 00090 << " not implemented or supported" << std::endl; 00091 return 0; 00092 } 00093 00094 if( !sharedContextWindow->configInit( )) 00095 { 00096 EQWARN << "OS Window initialization failed: " << std::endl; 00097 delete sharedContextWindow; 00098 return 0; 00099 } 00100 00101 wnd->setIAttribute( eq::Window::IATTR_HINT_DRAWABLE, drawable ); 00102 wnd->setIAttribute( eq::Window::IATTR_PLANES_STENCIL, stencil ); 00103 00104 sharedContextWindow->makeCurrent(); 00105 00106 EQWARN << "Async fetcher initialization finished" << std::endl; 00107 return sharedContextWindow; 00108 } 00109 00110 00111 static void deleteSharedContextWindow( eq::Window* wnd, 00112 eq::SystemWindow** sharedContextWindow, 00113 eq::ObjectManager** objectManager ) 00114 { 00115 EQWARN << "Deleting shared context" << std::endl; 00116 if( !sharedContextWindow || !*sharedContextWindow ) 00117 return; 00118 00119 if( *objectManager ) 00120 { 00121 (*objectManager)->deleteAll(); 00122 delete *objectManager; 00123 *objectManager = 0; 00124 } 00125 00126 const int32_t drawable = 00127 wnd->getIAttribute( eq::Window::IATTR_HINT_DRAWABLE ); 00128 wnd->setIAttribute( eq::Window::IATTR_HINT_DRAWABLE, eq::FBO ); 00129 00130 (*sharedContextWindow)->configExit(); // mb set window to 0 before that? 00131 00132 delete *sharedContextWindow; 00133 *sharedContextWindow = 0; 00134 00135 wnd->setIAttribute( eq::Window::IATTR_HINT_DRAWABLE, drawable ); 00136 } 00137 00138 00139 AsyncFetcher::AsyncFetcher() 00140 : co::base::Thread() 00141 , _wnd( 0 ) 00142 , _objectManager( 0 ) 00143 , _sharedContextWindow( 0 ) 00144 { 00145 _tmpTexture = new GLbyte[ 64*64*4 ]; 00146 } 00147 00148 00149 AsyncFetcher::~AsyncFetcher() 00150 { 00151 if( _wnd && _sharedContextWindow ) 00152 deleteSharedContextWindow( _wnd, &_sharedContextWindow, 00153 &_objectManager ); 00154 00155 delete [] _tmpTexture; 00156 } 00157 00158 00159 const GLEWContext* AsyncFetcher::glewGetContext() const 00160 { 00161 return _sharedContextWindow->glewGetContext(); 00162 } 00163 00164 00169 void AsyncFetcher::run() 00170 { 00171 EQASSERT( !_sharedContextWindow ); 00172 _sharedContextWindow = initSharedContextWindow( _wnd ); 00173 _outQueue.push( TextureId( )); // unlock pipe thread 00174 if( !_sharedContextWindow ) 00175 return; 00176 00177 _objectManager = new eq::ObjectManager( glewGetContext( )); 00178 EQINFO << "async fetcher initialized: " << _wnd << std::endl; 00179 00180 uint8_t* i = 0; 00181 bool running = true; 00182 co::base::sleep( 1000 ); // imitate loading of the first texture 00183 while( running ) 00184 { 00185 // generate new texture 00186 eq::util::Texture* tx = _objectManager->newEqTexture( ++i, 00187 GL_TEXTURE_2D ); 00188 tx->init( GL_RGBA8, 64, 64 ); 00189 00190 int j = 0; 00191 co::base::RNG rng; 00192 for( int y = 0; y < 64; ++y ) 00193 { 00194 for( int x = 0; x < 64; ++x ) 00195 { 00196 const GLbyte rnd = rng.get< uint8_t >() % 127; 00197 const GLbyte val = (x / 8) % 2 == (y / 8) % 2 ? rnd : 0; 00198 _tmpTexture[ j++ ] = val; 00199 _tmpTexture[ j++ ] = val; 00200 _tmpTexture[ j++ ] = val; 00201 _tmpTexture[ j++ ] = val; 00202 } 00203 } 00204 tx->upload( 64, 64, _tmpTexture ); 00205 EQ_GL_CALL( glFinish( )); 00206 00207 // add new texture to the pool 00208 _outQueue.push( TextureId( tx->getName(), i )); 00209 00210 // imitate hard work of loading something else 00211 co::base::sleep( rng.get< uint32_t >() % 5000u ); 00212 00213 // clean unused textures 00214 const void* keyToDelete = 0; 00215 while( _inQueue.tryPop( keyToDelete )) 00216 { 00217 if( keyToDelete ) 00218 { 00219 EQWARN << "Deleting eq texture " << keyToDelete << std::endl; 00220 _objectManager->deleteEqTexture( keyToDelete ); 00221 } 00222 else 00223 running = false; 00224 } 00225 } 00226 deleteSharedContextWindow( _wnd, &_sharedContextWindow, &_objectManager ); 00227 } 00228 00229 } //namespace eqAsync