// redraw the window
void display(void)
{   
    if(glutGetWindow() == mainwinid)
    {
#ifdef OSG_WITH_NVPERFSDK
        if(nvDataProvider->nCounters())
        {
            nvDataProvider->sample();

            OSG::Char8 str[40];
            
            for(int i = 0; nvStatElems[i] != NULL; ++i)
            {
                if(collector != NULL)
                {
                    sprintf(str, "%s: %f", nvStatElems[i]->getDescription().c_str(),
                            nvDataProvider->value(i)); 

                    OSG::StatStringElem *e = dynamic_cast<OSG::StatStringElem*>(
                        collector->getElem(*nvStatElems[i]));  

                    e->set(str);
                }
            }
        }
        
        if(runExperiment)
        {
            int nCount;
            
            const char *expCounters[] = { 
                "2D Bottleneck", "2D SOL", 
                "IDX Bottleneck", "IDX SOL", 
                "GEOM Bottleneck", "GEOM SOL", 
                "ZCULL Bottleneck", "ZCULL SOL", 
                "TEX Bottleneck", "TEX SOL", 
                "ROP Bottleneck", "ROP SOL", 
                "SHD Bottleneck", "SHD SOL", 
                "FB Bottleneck", "FB SOL", 
                "GPU Bottleneck", // Needs to be last 
                NULL };
            
            for(int i = 0; expCounters[i] != NULL; ++i)
            {
                NVPMAddCounterByName(const_cast<char *>(expCounters[i]));
            }
            
            NVPMBeginExperiment(&nCount);
            
            FLOG(("NVPerfKitSDK: Running %d passes\n", nCount));
            
            for(int i = 0; i < nCount; i++)
            {
                NVPMBeginPass(i);
                mgr->redraw();
                NVPMEndPass(i);
            }
            NVPMEndExperiment();
            
            UINT64 value, cycles;
            
            for(int i = 0; expCounters[i] != NULL; ++i)
            {
                NVPMGetCounterValueByName(const_cast<char *>(expCounters[i]), 0, &value, &cycles);
                FLOG(("%s: %lld value, %lld cycles (%.4f%%)\n", 
                        expCounters[i], value, cycles, value * 100. / cycles));
            }
            
            char buffer[1000] = "";
            
            NVPMGetGPUBottleneckName(value, buffer);

            FLOG(("GPU Bottleneck: '%s'\n", buffer));

            for(int i = 0; expCounters[i] != NULL; ++i)
            {
                //NVPMRemoveCounterByName(expCounters[i]);               
            }
            
            runExperiment = false;
        }
#endif
        mgr->redraw();
    }
    else if(glutGetWindow() == debugwinid)
    {
        // Use RenderAction to prevent new occlusion culling on debug output
        debugwin->render(debugact);
    }
}
void updateScene(const std::string &filename, OSG::Image::PixelFormat compressTo = OSG::Image::OSG_INVALID_PF)
{
    // Try to create the new image
    OSG::ImageRecPtr imagePtr = 
        OSG::ImageFileHandler::the()->read(filename.c_str());

    if (imagePtr == NULL)
        return;

    if(compressTo != OSG::Image::OSG_INVALID_PF)
    {
        imagePtr->reformat(compressTo);
    }

    // Update information on the screen
    OSG::StatStringElem *statElem = 
        statfg->editCollector()->getElem(textureFormatDesc);

    switch (imagePtr->getPixelFormat())
    {
        case OSG::Image::OSG_A_PF:
            statElem->set("OSG_A_PF");
            break;
        case OSG::Image::OSG_I_PF:
            statElem->set("OSG_I_PF");
            break;
        case OSG::Image::OSG_L_PF:
            statElem->set("OSG_L_PF");
            break;
        case OSG::Image::OSG_LA_PF:
            statElem->set("OSG_LA_PF");
            break;
        case OSG::Image::OSG_RGB_PF:
            statElem->set("OSG_RGB_PF");
            break;
        case OSG::Image::OSG_RGBA_PF:
            statElem->set("OSG_RGBA_PF");
            break;
        case OSG::Image::OSG_BGR_PF:
            statElem->set("OSG_BGRA_PF");
            break;
        case OSG::Image::OSG_BGRA_PF:
            statElem->set("OSG_BGRA_PF");
            break;
        case OSG::Image::OSG_RGB_DXT1:
            statElem->set("OSG_RGB_DXT1");
            break;
        case OSG::Image::OSG_RGBA_DXT1:
            statElem->set("OSG_RGBA_DXT1");
            break;
        case OSG::Image::OSG_RGBA_DXT3:
            statElem->set("OSG_RGBA_DXT3");
            break;
        case OSG::Image::OSG_RGBA_DXT5:
            statElem->set("OSG_RGBA_DXT5");
            break;
        default:
            statElem->set("???");
            break;
    }
    statElem = statfg->editCollector()->getElem(textureDataTypeDesc);
    switch (imagePtr->getDataType())
    {
        case OSG::Image::OSG_UINT8_IMAGEDATA:
            statElem->set("OSG_UINT8_IMAGEDATA");
            break;
        case OSG::Image::OSG_UINT16_IMAGEDATA:
            statElem->set("OSG_UINT16_IMAGEDATA");
            break;
        case OSG::Image::OSG_UINT32_IMAGEDATA:
            statElem->set("OSG_UINT32_IMAGEDATA");
            break;
        case OSG::Image::OSG_FLOAT16_IMAGEDATA:
            statElem->set("OSG_FLOAT16_IMAGEDATA");
            break;
        case OSG::Image::OSG_FLOAT32_IMAGEDATA:
            statElem->set("OSG_FLOAT32_IMAGEDATA");
            break;
        case OSG::Image::OSG_INT16_IMAGEDATA:
            statElem->set("OSG_INT16_IMAGEDATA");
            break;
        case OSG::Image::OSG_INT32_IMAGEDATA:
            statElem->set("OSG_INT32_IMAGEDATA");
            break;
        default:
            statElem->set("???");
            break;
    }
    ostringstream os;
    os << imagePtr->getWidth() << 'x' << imagePtr->getHeight() << 'x' << imagePtr->getDepth();
    statfg->editCollector()->getElem(textureSizeDesc)->set(os.str());
    statfg->editCollector()->getElem(textureDimensionDesc)->set(imagePtr->getDimension());
    statfg->editCollector()->getElem(textureBPPDesc)->set(imagePtr->getBpp());
    statfg->editCollector()->getElem(textureMipMapCountDesc)->set(imagePtr->getMipMapCount());
    statfg->editCollector()->getElem(textureFrameCountDesc)->set(imagePtr->getFrameCount());

    // Put it all together into a Geometry NodeCore.
    OSG::GeometryRecPtr geo = OSG::makePlaneGeo(imagePtr->getWidth(), imagePtr->getHeight(), 1, 1);
    OSG::NodeRecPtr imageNode = OSG::Node::create();
    imageNode->setCore(geo);
    OSG::NodeRecPtr transNodePtr = OSG::Node::create();
    OSG::TransformRecPtr transPtr = OSG::Transform::create();
    OSG::Matrix transMatrix;
    transMatrix.setTranslate(0.f, 0.f, -1.f);
    transPtr->setMatrix(transMatrix);
    transNodePtr->setCore(transPtr);
    transNodePtr->addChild(imageNode);

    OSG::TextureObjChunkRecPtr texObjChunk = OSG::TextureObjChunk::create();
    texObjChunk->setImage(imagePtr);
    texObjChunk->setWrapS(GL_CLAMP);
    texObjChunk->setWrapT(GL_CLAMP);
    texObjChunk->setMagFilter(GL_NEAREST);
    texObjChunk->setMinFilter(GL_NEAREST);
    OSG::TextureEnvChunkRecPtr texEnvChunk = OSG::TextureEnvChunk::create();
    texEnvChunk->setEnvMode(GL_MODULATE);

    OSG::MaterialChunkRecPtr matChunk = OSG::MaterialChunk::create();
    matChunk->setAmbient(OSG::Color4f(1.f, 1.f, 1.f, 1.f));
    matChunk->setDiffuse(OSG::Color4f(1.f, 1.f, 1.f, 1.f));
    matChunk->setEmission(OSG::Color4f(0.f, 0.f, 0.f, 1.f));
    matChunk->setSpecular(OSG::Color4f(0.f, 0.f, 0.f, 1.f));
    matChunk->setShininess(0);

    OSG::ChunkMaterialRecPtr m = OSG::ChunkMaterial::create();
    m->addChunk(texObjChunk);
    m->addChunk(texEnvChunk);
    m->addChunk(matChunk);

    geo->setMaterial(m);

    scene->clearChildren();
    scene->addChild(transNodePtr);

    if(compressTo != OSG::Image::OSG_INVALID_PF)
    {
        OSG::SceneFileHandler::the()->write(scene->getChild(0), 
                                            "/tmp/comp.osb");
        OSG::SceneFileHandler::the()->write(scene->getChild(0), 
                                            "/tmp/comp.osg");
    }

}