UInt32 ShaderExecutableChunk::handleGL(DrawEnv                 *pEnv, 
                                       UInt32                   id, 
                                       Window::GLObjectStatusE  mode,
                                       UInt32                   uiOptions)
{
    UInt32  returnValue = 0;
    Window *pWin        = pEnv->getWindow();

    if(!pWin->hasExtension(_extSHL))
    {
        FWARNING(("OpenGL Shading Language is not supported, couldn't find "
                  "extension 'GL_ARB_shading_language_100'!\n"));

        pWin->setGLObjectId(getGLId(), 0);

        return returnValue;
    }

    if(mode == Window::initialize   || 
       mode == Window::reinitialize ||
       mode == Window::needrefresh   )
    {
        GLuint uiProgram = GLuint(pWin->getGLObjectId(getGLId()));;

        if(mode != Window::needrefresh)
        {
            if(uiProgram != 0)
            {
                OSGGETGLFUNC(OSGglDeleteProgramProc,
                             osgGlDeleteProgram,
                             ShaderProgram::getFuncIdDeleteProgram());

                osgGlDeleteProgram(uiProgram);
            }

            OSGGETGLFUNC(OSGglCreateProgramProc,
                         osgGlCreateProgram,
                         ShaderProgram::getFuncIdCreateProgram());

            OSGGETGLFUNC(OSGglAttachShaderProc,
                         osgGlAttachShader,
                         ShaderProgram::getFuncIdAttachShader());

            OSGGETGLFUNC(OSGglLinkProgramProc,
                         osgGlLinkProgram,
                         ShaderProgram::getFuncIdLinkProgram());

            uiProgram = osgGlCreateProgram();

            FragmentShaderIt fIt  = _mfFragmentShader.begin();
            FragmentShaderIt fEnd = _mfFragmentShader.end  ();
            
            for(; fIt != fEnd; ++fIt)
            {
                (*fIt)->validate(pEnv);

                GLuint uiShader = 
                    GLuint(pWin->getGLObjectId((*fIt)->getGLId()));

                if(uiShader != 0)
                    osgGlAttachShader(uiProgram, uiShader);
            }
    
            GeometryShaderIt gIt  = _mfGeometryShader.begin();
            GeometryShaderIt gEnd = _mfGeometryShader.end  ();
            
            for(; gIt != gEnd; ++gIt)
            {
                (*gIt)->validate(pEnv);

                GLuint uiShader = 
                    GLuint(pWin->getGLObjectId((*gIt)->getGLId()));

                if(uiShader != 0)
                    osgGlAttachShader(uiProgram, uiShader);
            }
        
            VertexShaderIt vIt  = _mfVertexShader.begin();
            VertexShaderIt vEnd = _mfVertexShader.end  ();
            
            for(; vIt != vEnd; ++vIt)
            {
                (*vIt)->validate(pEnv);

                GLuint uiShader = 
                    GLuint(pWin->getGLObjectId((*vIt)->getGLId()));

                if(uiShader != 0)
                    osgGlAttachShader(uiProgram, uiShader);
            }

            // attribute binding must be done before linking
            updateAttribBindings(pEnv, uiProgram);

            // parameters must be set before linking
            updateParameters(pEnv, uiProgram);
            
            osgGlLinkProgram(uiProgram);

            GLint  iInfoLength;
            Char8 *szInfoBuffer = NULL;

            OSGGETGLFUNC(OSGglGetProgramivProc,
                         osgGlGetProgramiv,
                         ShaderProgram::getFuncIdGetProgramiv());

            osgGlGetProgramiv(uiProgram, 
                              GL_OBJECT_INFO_LOG_LENGTH_ARB, 
                              &iInfoLength);

            if(iInfoLength > 0)
            {
                szInfoBuffer = new Char8[iInfoLength];
                szInfoBuffer[0] = '\0';

                OSGGETGLFUNC(OSGglGetProgramInfoLogProc,
                             osgGlGetProgramInfoLog,
                             ShaderProgram::getFuncIdGetProgramInfoLog());

                osgGlGetProgramInfoLog( uiProgram, 
                                        iInfoLength, 
                                       &iInfoLength, 
                                        szInfoBuffer);
            }

            GLint iStatus = 0;

            osgGlGetProgramiv(uiProgram, GL_LINK_STATUS, &iStatus);

            if(iStatus == 0)
            {
                if(szInfoBuffer != NULL && szInfoBuffer[0] != '\0')
                {
                    FFATAL(("Couldn't link vertex and fragment program!\n%s\n",
                            szInfoBuffer));
                }
                else
                {
                    FFATAL(("Couldn't link vertex and fragment program!\n"
                            "No further info available\n"));
                }

                OSGGETGLFUNC(OSGglDeleteProgramProc,
                             osgGlDeleteProgram,
                             ShaderProgram::getFuncIdDeleteProgram());

                osgGlDeleteProgram(uiProgram);

                uiProgram = 0;
            }
            else
            {
                if(szInfoBuffer != NULL && szInfoBuffer[0] != '\0')
                {
                    FWARNING(("SHLChunk: link status: %s\n", szInfoBuffer));
                }
            }

            pWin->setGLObjectId(getGLId(), uiProgram);

            updateVariableLocations(pEnv, uiProgram);
            
            delete [] szInfoBuffer;
        }

        if(uiProgram != 0)
        {
            OSGGETGLFUNC(OSGglUseProgramProc,
                         osgGlUseProgram,
                         ShaderProgram::getFuncIdUseProgram());

            pEnv->setActiveShader(uiProgram);
            osgGlUseProgram      (uiProgram);
        
            updateVariables(pEnv, uiProgram);
        
            if(0x0000 == (uiOptions & KeepProgActive))
            {
                pEnv->setActiveShader(0);
                osgGlUseProgram      (0);
            }
            else
            {
                returnValue |= ProgActive;
            }
        }
    }

    return returnValue;
}
Exemplo n.º 2
0
UInt32 ComputeShaderChunk::handleGL(DrawEnv                 *pEnv, 
                                    UInt32                   id, 
                                    Window::GLObjectStatusE  mode,
                                    UInt64                   uiOptions)
{
    UInt32  returnValue = 0;
    Window *pWin        = pEnv->getWindow();

    if(!pWin->hasExtOrVersion(_arbComputeShader, 0x0403, 0xFFFF))
    {
        FWARNING(("OpenGL compute shader is not supported, couldn't find "
                  "extension 'GL_ARB_compute_shader'!\n"));

        pWin->setGLObjectId(getGLId(), 0);

        return returnValue;
    }

    if(mode == Window::initialize   || 
       mode == Window::reinitialize ||
       mode == Window::needrefresh   )
    {
        GLuint uiProgram = GLuint(pWin->getGLObjectId(getGLId()));;

        if(mode != Window::needrefresh)
        {
            if(uiProgram != 0)
            {
                OSGGETGLFUNCBYID_GL3_ES(glDeleteProgram,
                                        osgGlDeleteProgram,
                                        ShaderProgram::getFuncIdDeleteProgram(),
                                        pWin);

                osgGlDeleteProgram(uiProgram);
            }

            OSGGETGLFUNCBYID_GL3_ES(glCreateProgram,
                                    osgGlCreateProgram,
                                    ShaderProgram::getFuncIdCreateProgram(),
                                    pWin);

            OSGGETGLFUNCBYID_GL3_ES(glAttachShader,
                                    osgGlAttachShader,
                                    ShaderProgram::getFuncIdAttachShader(),
                                    pWin);

            OSGGETGLFUNCBYID_GL3_ES(glLinkProgram,
                                    osgGlLinkProgram,
                                    ShaderProgram::getFuncIdLinkProgram(),
                                    pWin);

            uiProgram = osgGlCreateProgram();
        
            ComputeShaderIt vIt  = _mfComputeShader.begin();
            ComputeShaderIt vEnd = _mfComputeShader.end  ();
            
            for(; vIt != vEnd; ++vIt)
            {
                (*vIt)->validate(pEnv);

                GLuint uiShader = 
                    GLuint(pWin->getGLObjectId((*vIt)->getGLId()));

                if(uiShader != 0)
                    osgGlAttachShader(uiProgram, uiShader);
            }

            osgGlLinkProgram(uiProgram);

            GLint  iInfoLength;
            Char8 *szInfoBuffer = NULL;

            OSGGETGLFUNCBYID_GL3_ES(glGetProgramiv,
                                    osgGlGetProgramiv,
                                    ShaderProgram::getFuncIdGetProgramiv(),
                                    pWin);

            osgGlGetProgramiv(uiProgram, 
                              GL_OBJECT_INFO_LOG_LENGTH_ARB, 
                              &iInfoLength);

            if(iInfoLength > 0)
            {
                szInfoBuffer = new Char8[iInfoLength];
                szInfoBuffer[0] = '\0';

                OSGGETGLFUNCBYID_GL3_ES(
                    glGetProgramInfoLog,
                    osgGlGetProgramInfoLog,
                    ShaderProgram::getFuncIdGetProgramInfoLog(),
                    pWin);

                osgGlGetProgramInfoLog( uiProgram, 
                                        iInfoLength, 
                                       &iInfoLength, 
                                        szInfoBuffer);
            }

            GLint iStatus = 0;

            osgGlGetProgramiv(uiProgram, GL_LINK_STATUS, &iStatus);

            if(iStatus == 0)
            {
                if(szInfoBuffer != NULL && szInfoBuffer[0] != '\0')
                {
                    FFATAL(("Couldn't link compute program!\n%s\n",
                            szInfoBuffer));
                }
                else
                {
                    FFATAL(("Couldn't link compute program!\n"
                            "No further info available\n"));
                }

                OSGGETGLFUNCBYID_GL3_ES(glDeleteProgram,
                                        osgGlDeleteProgram,
                                        ShaderProgram::getFuncIdDeleteProgram(),
                                        pWin);

                osgGlDeleteProgram(uiProgram);

                uiProgram = 0;
            }
            else
            {
                if(szInfoBuffer != NULL && szInfoBuffer[0] != '\0')
                {
                    FWARNING(("ComputeShaderChunk: link status: %s\n", 
                              szInfoBuffer));
                }
            }

            pWin->setGLObjectId(getGLId(), uiProgram);

            updateVariableLocations(pEnv, uiProgram);
        }

        if(uiProgram != 0)
        {
            OSGGETGLFUNCBYID_GL3_ES(glUseProgram,
                                    osgGlUseProgram,
                                    ShaderProgram::getFuncIdUseProgram(),
                                    pWin);
        
            osgGlUseProgram(uiProgram);
        
            updateVariables(pEnv, uiProgram);
        
            if(0x0000 == (uiOptions & KeepProgActive))
            {
                osgGlUseProgram(0);
            }
            else
            {
                returnValue |= ProgActive;
            }
        }
    }

    return returnValue;
}