FrameBuffer::FrameBuffer(GLuint width,GLuint height,unsigned int flags)
			:m_width(width)
			,m_height(height)
			,m_frameBuffer(0)
			,m_depthBuffer(0)
			,m_targetTexture(0)
			,m_flags(flags)
{	
	glGenFramebuffers(1,&m_frameBuffer);
	glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);

	if(m_flags & EFBT_TEXTURE)
	{
		GLuint internalFormat = (m_flags & EFBT_TEXTURE_RGB8) ? GL_RGB8:GL_RGBA8;
		GLuint textureFormat = (m_flags & EFBT_TEXTURE_RGB8) ? GL_RGB : GL_RGBA;
		int bytesPerPixel = (m_flags & EFBT_TEXTURE_RGB8) ? 3 : 4;

		glGenTextures(1, &m_targetTexture);
		glBindTexture(GL_TEXTURE_2D,m_targetTexture);
		if(m_flags & EFBT_TEXTURE_WHITE)
		{
			std::vector<GLubyte> textureData(m_width*m_height*bytesPerPixel,125);
			GLubyte* pData = new GLubyte[m_width*m_height*bytesPerPixel];
			for (int i=0; i< m_width*m_height*bytesPerPixel; ++i)
			{
				pData[i] = 255;
			}
			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
			glTexImage2D(GL_TEXTURE_2D,0,internalFormat,m_width,m_height,0,textureFormat,GL_UNSIGNED_BYTE,pData);
		}
		else
		{
			glTexImage2D(GL_TEXTURE_2D,0,internalFormat,m_width,m_height,0,textureFormat,GL_UNSIGNED_BYTE,0);
		}

		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,m_targetTexture,0);
	}

	
	if(m_flags & EFBT_TEXTURE_DEPTH)
	{
		glGenRenderbuffers(1,&m_depthBuffer);
		glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer);
		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,m_width, m_height);
		glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer);
	}

	GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	if (uStatus != GL_FRAMEBUFFER_COMPLETE)
	{
		assert(0);
	}

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	
}
/**
 *  Function for creating and holding of shared context.
 *  Generation and uploading of new textures over some period with sleep time.
 */
void AsyncFetcher::run()
{
    LBASSERT( _sharedWindow );
    if( !_sharedWindow )
        return;

    _sharedWindow->makeCurrent();
    eq::util::ObjectManager objects( glewGetContext( ));
    lunchbox::Bufferb textureData( 64*64*4 );
    LBINFO << "async fetcher initialized" << std::endl;

    bool running = true;
    lunchbox::sleep( 1000 ); // imitate loading of the first texture
    for( uint8_t* i = 0; running; ++i )
    {
        // generate new texture
        eq::util::Texture* tx = objects.newEqTexture( i, GL_TEXTURE_2D );
        tx->init( GL_RGBA8, 64, 64 );

        int j = 0;
        lunchbox::RNG rng;
        for( int y = 0; y < 64; ++y )
        {
            for( int x = 0; x < 64; ++x )
            {
                const GLbyte rnd = rng.get< uint8_t >() % 127;
                const GLbyte val = (x / 8) % 2 == (y / 8) % 2 ? rnd : 0;
                textureData[ j++ ] = val;
                textureData[ j++ ] = val;
                textureData[ j++ ] = val;
                textureData[ j++ ] = val;
            }
        }
        tx->upload( 64, 64, textureData.getData( ));
        EQ_GL_CALL( glFinish( ));

        // add new texture to the pool
        _outQueue.push( TextureId( tx->getName(), i ));

        // imitate hard work of loading something else
        lunchbox::sleep( rng.get< uint32_t >() % 5000u );

        // clean unused textures
        const void* keyToDelete = 0;
        while( _inQueue.tryPop( keyToDelete ))
        {
            if( keyToDelete )
            {
                LBWARN << "Deleting eq texture " << keyToDelete << std::endl;
                objects.deleteEqTexture( keyToDelete );
            }
            else
                running = false;
        }
    }
    objects.deleteAll();
}
void ImageManager::LoadPendingTextures()
{
	while (!pendingTextures.empty())
	{
		TextureData *textureData(pendingTextures.back());
		pendingTextures.pop_back();
		ITexture *texture = DownloadTexture(textureData);
		if (texture)
			ApplyTexture(textureData, texture);
		delete textureData;
	}
}