//-----------------------------------------------------------------------------
GLES2FrameBufferObject::GLES2FrameBufferObject(GLES2FBOManager *manager, uint fsaa):
    mManager(manager), mNumSamples(fsaa)
{
    GLES2Support* glSupport = getGLES2SupportRef();

    // Generate framebuffer object
    OGRE_CHECK_GL_ERROR(glGenFramebuffers(1, &mFB));

    if(glSupport->checkExtension("GL_EXT_debug_label"))
    {
        OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
        OGRE_CHECK_GL_ERROR(glLabelObjectEXT(GL_BUFFER_OBJECT_EXT, mFB, 0, ("FBO #" + StringConverter::toString(mFB)).c_str()));
    }

    mNumSamples = 0;
    mMultisampleFB = 0;

    // Check multisampling if supported
    if(glSupport->hasMinGLVersion(3, 0))
    {
        // Check samples supported
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mFB));
        GLint maxSamples;
        OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_SAMPLES_APPLE, &maxSamples));
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
        mNumSamples = std::min(mNumSamples, (GLsizei)maxSamples);
    }

    // Will we need a second FBO to do multisampling?
    if (mNumSamples)
    {
        OGRE_CHECK_GL_ERROR(glGenFramebuffers(1, &mMultisampleFB));
        if(glSupport->checkExtension("GL_EXT_debug_label"))
        {
            OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
            OGRE_CHECK_GL_ERROR(glLabelObjectEXT(GL_BUFFER_OBJECT_EXT, mMultisampleFB, 0, ("MSAA FBO #" + StringConverter::toString(mMultisampleFB)).c_str()));
        }
    }
    else
    {
        mMultisampleFB = 0;
    }

    // Initialise state
    mDepth.buffer = 0;
    mStencil.buffer = 0;
    for(size_t x = 0; x < OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
    {
        mColour[x].buffer=0;
    }
}
GLSLESProgramPipeline::~GLSLESProgramPipeline()
{
#if GL_EXT_separate_shader_objects && OGRE_PLATFORM != OGRE_PLATFORM_NACL
    OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
    OGRE_CHECK_GL_ERROR(glDeleteProgramPipelinesEXT(1, &mGLProgramPipelineHandle));
#endif
}
//------------------------------------------------------------------
void GLES2HardwareOcclusionQuery::endOcclusionQuery() 
{ 
#ifdef GL_EXT_occlusion_query_boolean
    OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
        OGRE_CHECK_GL_ERROR(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
#endif
}
//------------------------------------------------------------------
void GLES2HardwareOcclusionQuery::destroyQuery()
{
#ifdef GL_EXT_occlusion_query_boolean
    OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
        OGRE_CHECK_GL_ERROR(glDeleteQueriesEXT(1, &mQueryID));
#endif        
}
//------------------------------------------------------------------
bool GLES2HardwareOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments ) 
{
#ifdef GL_EXT_occlusion_query_boolean
    OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
        OGRE_CHECK_GL_ERROR(glGetQueryObjectuivEXT(mQueryID, GL_QUERY_RESULT_EXT, (GLuint*)NumOfFragments));
    mPixelCount = *NumOfFragments;
    return true;
#else
	return false;
#endif
}
//------------------------------------------------------------------
void GLES2HardwareOcclusionQuery::createQuery()
{
	// Check for hardware occlusion support
#ifdef GL_EXT_occlusion_query_boolean
    OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
        OGRE_CHECK_GL_ERROR(glGenQueriesEXT(1, &mQueryID ));
#else
    OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, 
                "Cannot allocate a Hardware query. This video card doesn't support it, sorry.", 
                "GLES2HardwareOcclusionQuery::GLES2HardwareOcclusionQuery" );
#endif        
}
//------------------------------------------------------------------
bool GLES2HardwareOcclusionQuery::isStillOutstanding(void)
{    
    GLuint available = GL_FALSE;

#ifdef GL_EXT_occlusion_query_boolean
    OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
        OGRE_CHECK_GL_ERROR(glGetQueryObjectuivEXT(mQueryID, GL_QUERY_RESULT_AVAILABLE_EXT, &available));
#endif

	// GL_TRUE means a wait would occur
    return !(available == GL_TRUE);  
} 
    void GLES2HardwareVertexBuffer::createBuffer()
    {
        OGRE_CHECK_GL_ERROR(glGenBuffers(1, &mBufferId));
        if(getGLES2SupportRef()->checkExtension("GL_EXT_debug_label"))
        {
            OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
            OGRE_CHECK_GL_ERROR(glLabelObjectEXT(GL_BUFFER_OBJECT_EXT, mBufferId, 0, ("Vertex Buffer #" + StringConverter::toString(mBufferId)).c_str()));
        }

        if (!mBufferId)
        {
            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
                        "Cannot create GL ES vertex buffer",
                        "GLES2HardwareVertexBuffer::GLES2HardwareVertexBuffer");
        }
        
		static_cast<GLES2HardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER, mBufferId);
        OGRE_CHECK_GL_ERROR(glBufferData(GL_ARRAY_BUFFER, mSizeInBytes, NULL,
                                         GLES2HardwareBufferManager::getGLUsage(mUsage)));
    }
Esempio n. 9
0
bool GLSLESProgram::compile(const bool checkErrors)
{
    if (mCompiled == 1)
    {
        return true;
    }
    // Only create a shader object if glsl es is supported
    if (isSupported())
    {
        // Create shader object
        GLenum shaderType = 0x0000;
        if (mType == GPT_VERTEX_PROGRAM)
        {
            shaderType = GL_VERTEX_SHADER;
        }
        else if (mType == GPT_FRAGMENT_PROGRAM)
        {
            shaderType = GL_FRAGMENT_SHADER;
        }
        OGRE_CHECK_GL_ERROR(mGLShaderHandle = glCreateShader(shaderType));

#if OGRE_PLATFORM != OGRE_PLATFORM_NACL
        if(getGLES2SupportRef()->checkExtension("GL_EXT_debug_label"))
        {
            OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
            glLabelObjectEXT(GL_SHADER_OBJECT_EXT, mGLShaderHandle, 0, mName.c_str());
        }
#endif

        if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS))
        {
            OGRE_CHECK_GL_ERROR(mGLProgramHandle = glCreateProgram());
#if OGRE_PLATFORM != OGRE_PLATFORM_NACL
            if(getGLES2SupportRef()->checkExtension("GL_EXT_debug_label"))
            {
                OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
                glLabelObjectEXT(GL_PROGRAM_OBJECT_EXT, mGLProgramHandle, 0, mName.c_str());
            }
#endif
        }
    }

    // Add preprocessor extras and main source
    if (!mSource.empty())
    {
        // Fix up the source in case someone forgot to redeclare gl_Position
        if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS) &&
                mType == GPT_VERTEX_PROGRAM)
        {
            size_t versionPos = mSource.find("#version");
            int shaderVersion = StringConverter::parseInt(mSource.substr(versionPos+9, 3));

            // Check that it's missing and that this shader has a main function, ie. not a child shader.
            if(mSource.find("out highp vec4 gl_Position") == String::npos)
            {
                if(shaderVersion >= 300)
                    mSource.insert(versionPos+16, "out highp vec4 gl_Position;\nout highp float gl_PointSize;\n");
            }
            if(mSource.find("#extension GL_EXT_separate_shader_objects : require") == String::npos)
            {
                if(shaderVersion >= 300)
                    mSource.insert(versionPos+16, "#extension GL_EXT_separate_shader_objects : require\n");
            }
        }

#if !OGRE_NO_GLES2_GLSL_OPTIMISER
        const char *source = (getOptimiserEnabled() && getIsOptimised()) ? mOptimisedSource.c_str() : mSource.c_str();
#else
        const char *source = mSource.c_str();
#endif

        OGRE_CHECK_GL_ERROR(glShaderSource(mGLShaderHandle, 1, &source, NULL));
    }

    if (checkErrors)
        logObjectInfo("GLSL ES compiling: " + mName, mGLShaderHandle);

    OGRE_CHECK_GL_ERROR(glCompileShader(mGLShaderHandle));

    // Check for compile errors
    OGRE_CHECK_GL_ERROR(glGetShaderiv(mGLShaderHandle, GL_COMPILE_STATUS, &mCompiled));
    if(!mCompiled && checkErrors)
    {
        String message = logObjectInfo("GLSL ES compile log: " + mName, mGLShaderHandle);
        checkAndFixInvalidDefaultPrecisionError(message);
    }

    // Log a message that the shader compiled successfully.
    if (mCompiled && checkErrors)
        logObjectInfo("GLSL ES compiled: " + mName, mGLShaderHandle);

    if(!mCompiled)
    {
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                    ((mType == GPT_VERTEX_PROGRAM) ? "Vertex Program " : "Fragment Program ") + mName +
                    " failed to compile. See compile log above for details.",
                    "GLSLESProgram::compile");
    }

    return (mCompiled == 1);
}
void GLSLESProgramPipeline::compileAndLink()
{
#if GL_EXT_separate_shader_objects && OGRE_PLATFORM != OGRE_PLATFORM_NACL
    GLint linkStatus = 0;

    OGRE_CHECK_GL_ERROR(glGenProgramPipelinesEXT(1, &mGLProgramPipelineHandle));
    OGRE_CHECK_GL_ERROR(glBindProgramPipelineEXT(mGLProgramPipelineHandle));

    // Compile and attach Vertex Program
    if(mVertexProgram && !mVertexProgram->isLinked())
    {
        try
        {
            mVertexProgram->getGLSLProgram()->compile(true);
        }
        catch (Exception& e)
        {
            LogManager::getSingleton().stream() << e.getDescription();
            mTriedToLinkAndFailed = true;
            return;
        }
        GLuint programHandle = mVertexProgram->getGLSLProgram()->getGLProgramHandle();
        OGRE_CHECK_GL_ERROR(glProgramParameteriEXT(programHandle, GL_PROGRAM_SEPARABLE_EXT, GL_TRUE));
        mVertexProgram->getGLSLProgram()->attachToProgramObject(programHandle);
        OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle));
        OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus));

        if(linkStatus)
        {
            mVertexProgram->setLinked(linkStatus);
            mLinked |= VERTEX_PROGRAM_LINKED;
        }

        mTriedToLinkAndFailed = !linkStatus;

        logObjectInfo( getCombinedName() + String("GLSL vertex program result : "), programHandle );

        setSkeletalAnimationIncluded(mVertexProgram->isSkeletalAnimationIncluded());
    }

    // Compile and attach Fragment Program
    if(mFragmentProgram && !mFragmentProgram->isLinked())
    {
        try
        {
            mFragmentProgram->getGLSLProgram()->compile(true);
        }
        catch (Exception& e)
        {
            LogManager::getSingleton().stream() << e.getDescription();
            mTriedToLinkAndFailed = true;
            return;
        }

        GLuint programHandle = mFragmentProgram->getGLSLProgram()->getGLProgramHandle();
        OGRE_CHECK_GL_ERROR(glProgramParameteriEXT(programHandle, GL_PROGRAM_SEPARABLE_EXT, GL_TRUE));
        mFragmentProgram->getGLSLProgram()->attachToProgramObject(programHandle);
        OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle));
        OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus));

        if(linkStatus)
        {
            mFragmentProgram->setLinked(linkStatus);
            mLinked |= FRAGMENT_PROGRAM_LINKED;
        }

        mTriedToLinkAndFailed = !linkStatus;

        logObjectInfo( getCombinedName() + String("GLSL fragment program result : "), programHandle );
    }

    if(mLinked)
    {
        if(mVertexProgram && mVertexProgram->isLinked())
        {
            OGRE_CHECK_GL_ERROR(glUseProgramStagesEXT(mGLProgramPipelineHandle, GL_VERTEX_SHADER_BIT_EXT, mVertexProgram->getGLSLProgram()->getGLProgramHandle()));
        }
        if(mFragmentProgram && mFragmentProgram->isLinked())
        {
            OGRE_CHECK_GL_ERROR(glUseProgramStagesEXT(mGLProgramPipelineHandle, GL_FRAGMENT_SHADER_BIT_EXT, mFragmentProgram->getGLSLProgram()->getGLProgramHandle()));
        }

        // Validate pipeline
        logObjectInfo( getCombinedName() + String("GLSL program pipeline result : "), mGLProgramPipelineHandle );
#if GL_EXT_debug_label && OGRE_PLATFORM != OGRE_PLATFORM_NACL
        if(mVertexProgram && mFragmentProgram)
            OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0)
            glLabelObjectEXT(GL_PROGRAM_PIPELINE_OBJECT_EXT, mGLProgramPipelineHandle, 0,
                             (mVertexProgram->getName() + "/" + mFragmentProgram->getName()).c_str());
#endif
    }
#endif
}