Esempio n. 1
0
// Assemble lists of the valid buffer configurations, along with the
// possibilities for multisample coverage antialiasing, if any.
void getPossibleConfigs(GraphicsContext* gc, BufferConfigList& colorConfigs,
                        BufferConfigList& depthConfigs,
                        vector<int>& coverageConfigs)
{
    int maxSamples = 0;
    int coverageSampleConfigs = 0;
    unsigned contextID = gc->getState()->getContextID();
    colorConfigs.push_back(BufferConfig("RGBA8", GL_RGBA8, 8));
    depthConfigs.push_back(BufferConfig("D24", GL_DEPTH_COMPONENT24, 24));
    FBOExtensions* fboe = FBOExtensions::instance(contextID, true);
    if (!fboe->isSupported())
        return;
    if (fboe->isMultisampleSupported())
        glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
    // isMultisampleCoverageSupported
    if (isGLExtensionSupported(contextID,
                               "GL_NV_framebuffer_multisample_coverage"))
    {
        glGetIntegerv(GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV,
                      &coverageSampleConfigs);
        coverageConfigs.resize(coverageSampleConfigs * 2 + 4);
        glGetIntegerv(GL_MULTISAMPLE_COVERAGE_MODES_NV, &coverageConfigs[0]);
    }
    if (isGLExtensionSupported(contextID, "GL_ARB_depth_buffer_float"))
        depthConfigs.push_back(BufferConfig("D32F", GL_DEPTH_COMPONENT32F, 32));
    else if (isGLExtensionSupported(contextID, "GL_NV_depth_buffer_float"))
        depthConfigs.push_back(BufferConfig("D32F", GL_DEPTH_COMPONENT32F_NV,
                                            32));
}
Esempio n. 2
0
bool checkFramebufferStatus(GraphicsContext* gc, bool silent = false)
{
    State& state = *gc->getState();
    unsigned contextID = state.getContextID();
    FBOExtensions* fboe = FBOExtensions::instance(contextID, true);
    switch(fboe->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT)) {
        case GL_FRAMEBUFFER_COMPLETE_EXT:
            break;
        case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
            if (!silent)
                cout << "Unsupported framebuffer format\n";
            return false;
        case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
            if (!silent)
                cout << "Framebuffer incomplete, missing attachment\n";
            return false;
        case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
            if (!silent)
                cout << "Framebuffer incomplete, duplicate attachment\n";
            return false;
        case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
            if (!silent)
                cout << "Framebuffer incomplete, attached images must have same dimensions\n";
            return false;
        case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
            if (!silent)
                cout << "Framebuffer incomplete, attached images must have same format\n";
            return false;
        case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
            if (!silent)
                cout << "Framebuffer incomplete, missing draw buffer\n";
            return false;
        case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
            if (!silent)
                cout << "Framebuffer incomplete, missing read buffer\n";
            return false;
        default:
            return false;
    }
    return true;
}
Esempio n. 3
0
// Standard OSG code for initializing osgViewer::Viewer with explicit
// creation of own graphics context. This is also a good time to test
// for valid frame buffer configurations; we have a valid graphics
// context, but multithreading hasn't started, etc.
GraphicsContext* setupGC(osgViewer::Viewer& viewer, ArgumentParser& arguments)
{
    int x = -1, y = -1, width = -1, height = -1;
    while (arguments.read("--window",x,y,width,height)) {}

    GraphicsContext::WindowingSystemInterface* wsi =
        GraphicsContext::getWindowingSystemInterface();
    if (!wsi)
    {
        OSG_NOTIFY(NOTICE)<<"View::setUpViewOnSingleScreen() : Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
        return 0;
    }

    DisplaySettings* ds = viewer.getDisplaySettings() ? viewer.getDisplaySettings() : DisplaySettings::instance().get();
    GraphicsContext::ScreenIdentifier si;
    si.readDISPLAY();

    // displayNum has not been set so reset it to 0.
    if (si.displayNum<0) si.displayNum = 0;

    bool decoration = true;
    if (x < 0)
    {
        unsigned int w, h;
        wsi->getScreenResolution(si, w, h);
        x = 0;
        y = 0;
        width = w;
        height = h;
        decoration = false;
    }

    ref_ptr<GraphicsContext::Traits> traits
        = new GraphicsContext::Traits(ds);
    traits->hostName = si.hostName;
    traits->displayNum = si.displayNum;
    traits->screenNum = si.screenNum;
    traits->x = x;
    traits->y = y;
    traits->width = width;
    traits->height = height;
    traits->windowDecoration = decoration;
    traits->doubleBuffer = true;
    traits->sharedContext = 0;
    ref_ptr<GraphicsContext> gc
        = GraphicsContext::createGraphicsContext(traits.get());
    osgViewer::GraphicsWindow* gw
        = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
    if (gw)
    {
        OSG_NOTIFY(INFO)<<"View::setUpViewOnSingleScreen - GraphicsWindow has been created successfully."<<std::endl;
        gw->getEventQueue()->getCurrentEventState()
            ->setWindowRectangle(0, 0, width, height);
    }
    else
    {
        OSG_NOTIFY(NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
    }
    double fovy, aspectRatio, zNear, zFar;
    viewer.getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio,
                                                         zNear, zFar);
    double newAspectRatio = double(traits->width) / double(traits->height);
    double aspectRatioChange = newAspectRatio / aspectRatio;
    if (aspectRatioChange != 1.0)
    {
        viewer.getCamera()->getProjectionMatrix()
            *= Matrix::scale(1.0/aspectRatioChange,1.0,1.0);
    }
    // Context has to be current to test for extensions
    gc->realize();
    gc->makeCurrent();
    unsigned int contextID = gc->getState()->getContextID();
    FBOExtensions* fboe = FBOExtensions::instance(contextID, true);
    if (!fboe->isSupported())
    {
        OSG_NOTIFY(NOTICE) << "Frame buffer objects are not supported\n";
        gc->releaseContext();
        gc->close(true);
        return 0;
    }
    if (isGLExtensionSupported(contextID, "GL_ARB_depth_buffer_float"))
        depthTextureEnum = GL_DEPTH_COMPONENT32F;
    else if (isGLExtensionSupported(contextID, "GL_NV_depth_buffer_float"))
        depthTextureEnum = GL_DEPTH_COMPONENT32F_NV;
    BufferConfigList colorConfigs;
    BufferConfigList depthConfigs;
    vector<int> coverageConfigs;
    getPossibleConfigs(gc.get(), colorConfigs, depthConfigs, coverageConfigs);
    int coverageSampleConfigs = (coverageConfigs.size() - 4) / 2;
    cout << "color configs\nname\tbits\n";
    for (BufferConfigList::const_iterator colorItr = colorConfigs.begin(),
             colorEnd = colorConfigs.end();
         colorItr != colorEnd;
         ++colorItr)
    {
        for (BufferConfigList::const_iterator depthItr = depthConfigs.begin(),
             depthEnd = depthConfigs.end();
             depthItr != depthEnd;
             ++depthItr)
        {
            string root = colorItr->name + " " + depthItr->name;
            FboConfig config(root, colorItr->format, depthItr->format,
                             colorItr->bits, depthItr->bits);
            FboData data;
            if (createFBO(gc.get(), config, data))
                validConfigs.push_back(config);
            destroyFBO(gc.get(), data);
            if (coverageConfigs.size() > 0)
            {
                //CSAA provides a list of all supported AA modes for
                //quick enumeration
                for (int kk = 0; kk < coverageSampleConfigs; kk++)
                {
                    stringstream msText;
                    msText << root;
                    config.depthSamples = coverageConfigs[kk*2+1];
                    config.coverageSamples = coverageConfigs[kk*2];

                    if ( config.coverageSamples == config.depthSamples )
                    {
                        // Normal antialiasing
                        msText << " - " << config.depthSamples << " MSAA";
                    }
                    else
                    {
                        // coverage antialiasing
                        msText << " - " << config.coverageSamples << "/"
                               << config.depthSamples << " CSAA";
                    }
                    config.name = msText.str();

                    if (createFBO(gc.get(), config, data)) {
                        validConfigs.push_back( config);
                    }
                    destroyFBO(gc.get(), data);
                }
            }
        }
    }
    if (validConfigs.empty())
    {
        cout << "no valid frame buffer configurations!\n";
        return 0;
    }
    cout << "valid frame buffer configurations:\n";
    for (vector<FboConfig>::iterator itr = validConfigs.begin(),
             end = validConfigs.end();
         itr != end;
         ++itr)
        cout << itr->name << "\n";
    gc->releaseContext();

    return gc.release();
}
Esempio n. 4
0
// Attempt to create an FBO with a certain configuration. If the FBO
// is created with fewer bits in any of its parameters, the creation
// is deemed to have failed. Even though the result is a valid FBO,
// we're only interested in discrete, valid configurations.
bool createFBO(GraphicsContext* gc, FboConfig &config, FboData &data)
{
    bool result = true;
    bool multisample = config.depthSamples > 0;
    bool csaa = config.coverageSamples > config.depthSamples;
    data.fb = new FrameBufferObject;
    int texWidth = 512, texHeight = 512;
    data.tex = new Texture2D;
    data.tex->setTextureSize(texWidth, texHeight);
    data.tex->setInternalFormat(config.colorFormat);
    data.tex->setSourceFormat(GL_RGBA);
    data.tex->setSourceType(GL_FLOAT);
    data.tex->setFilter(Texture::MIN_FILTER, Texture::LINEAR_MIPMAP_LINEAR);
    data.tex->setFilter(Texture::MAG_FILTER, Texture::LINEAR);
    data.tex->setWrap(Texture::WRAP_S, Texture::CLAMP_TO_EDGE);
    data.tex->setWrap(Texture::WRAP_T, Texture::CLAMP_TO_EDGE);
    RenderBuffer* colorRB = 0;
    RenderBuffer* depthRB = 0;
    if (multisample)
    {
        data.resolveFB = new FrameBufferObject;
        data.resolveFB->setAttachment(Camera::COLOR_BUFFER,
                                      FrameBufferAttachment(data.tex.get()));
        colorRB = new RenderBuffer(texWidth, texHeight, config.colorFormat,
                                   config.coverageSamples, config.depthSamples);
        data.fb->setAttachment(Camera::COLOR_BUFFER,
                               FrameBufferAttachment(colorRB));
        depthRB = new RenderBuffer(texWidth, texHeight, config.depthFormat,
                                   config.coverageSamples, config.depthSamples);
        data.fb->setAttachment(Camera::DEPTH_BUFFER,
                               FrameBufferAttachment(depthRB));
    }
    else
    {
        data.depthTex = makeDepthTexture(texWidth, texHeight,
                                         config.depthFormat);
        data.fb->setAttachment(Camera::COLOR_BUFFER,
                               FrameBufferAttachment(data.tex.get()));
        data.fb->setAttachment(Camera::DEPTH_BUFFER,
                               FrameBufferAttachment(data.depthTex.get()));
    }
    State& state = *gc->getState();
    unsigned int contextID = state.getContextID();
    FBOExtensions* fboe = FBOExtensions::instance(contextID, true);

    data.fb->apply(state);
    result = checkFramebufferStatus(gc, true);
    if (!result)
    {
        fboe->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
        return false;
    }
    int query;
    if (multisample)
    {
        GLuint colorRBID = colorRB->getObjectID(contextID, fboe);
        fboe->glBindRenderbuffer(GL_RENDERBUFFER_EXT, colorRBID);
        if (csaa)
        {
            fboe->glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT,
                                               GL_RENDERBUFFER_COVERAGE_SAMPLES_NV,
                                               &query);
            if (query < config.coverageSamples)
                result = false;
            else
                config.coverageSamples = query;
            fboe->glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT,
                                               GL_RENDERBUFFER_COLOR_SAMPLES_NV,
                                               &query);

            if ( query < config.depthSamples)
               result = false;
            else
                config.depthSamples = query; // report back the actual number

        }
        else
        {
            fboe->glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT,
                                               GL_RENDERBUFFER_SAMPLES_EXT,
                                               &query);
            if (query < config.depthSamples)
                result = false;
            else
                config.depthSamples = query;
        }
    }
    glGetIntegerv( GL_RED_BITS, &query);
    if (query != config.redbits)
        result = false;
    glGetIntegerv(GL_DEPTH_BITS, &query);
    if ( query != config.depthBits)
        result = false;
    if (result && multisample && data.resolveFB.valid())
    {
        data.resolveFB->apply(state);
        result = checkFramebufferStatus(gc, true);
        if (result)
        {
            glGetIntegerv( GL_RED_BITS, &query);
            if (query != config.redbits)
                result = false;
        }
    }
    fboe->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
    return result;
}
Esempio n. 5
0
void FrameBufferObject::apply(State &state, BindTarget target) const
{
    unsigned int contextID = state.getContextID();

    if (_unsupported[contextID])
        return;
        
        
    FBOExtensions* ext = FBOExtensions::instance(contextID,true);
    if (!ext->isSupported())
    {
        _unsupported[contextID] = 1;
        notify(WARN) << "Warning: EXT_framebuffer_object is not supported" << std::endl;
        return;
    }

    if (_attachments.empty())
    {
        ext->glBindFramebufferEXT(target, 0);
        return;
    }

    int &dirtyAttachmentList = _dirtyAttachmentList[contextID];

    GLuint &fboID = _fboID[contextID];
    if (fboID == 0)
    {
        ext->glGenFramebuffersEXT(1, &fboID);
        if (fboID == 0)
        {
            notify(WARN) << "Warning: FrameBufferObject: could not create the FBO" << std::endl;
            return;
        }

        dirtyAttachmentList = 1;

    }

    if (dirtyAttachmentList)
    {
        // the set of of attachments appears to be thread sensitive, it shouldn't be because 
        // OpenGL FBO handles osg::FrameBufferObject has are multi-buffered...
        // so as a temporary fix will stick in a mutex to ensure that only one thread passes through here
        // at one time.
        static OpenThreads::Mutex s_mutex;
        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex);

        // create textures and mipmaps before we bind the frame buffer object
        for (AttachmentMap::const_iterator i=_attachments.begin(); i!=_attachments.end(); ++i)
        {
            const FrameBufferAttachment &fa = i->second;
            fa.createRequiredTexturesAndApplyGenerateMipMap(state, ext);
        }

    }
    
   
    ext->glBindFramebufferEXT(target, fboID);

    // enable drawing buffers to render the result to fbo
    if (_drawBuffers.size() > 0)
    {
        GL2Extensions *gl2e = GL2Extensions::Get(state.getContextID(), true );
        if (gl2e)
        {
            gl2e->glDrawBuffers(_drawBuffers.size(), &(_drawBuffers[0]));
        }
    }

    if (dirtyAttachmentList)
    {
        for (AttachmentMap::const_iterator i=_attachments.begin(); i!=_attachments.end(); ++i)
        {
            const FrameBufferAttachment &fa = i->second;
            fa.attach(state, target, convertBufferComponentToGLenum(i->first), ext);
        }        
        dirtyAttachmentList = 0;
    }

}