CPUTVertexArrayOGL(GLint vertexElementCount) :
    mIndexBufferID(0), mVertexBufferID(0), mVertexElementCount(vertexElementCount)
    {
#ifdef CPUT_FOR_OGLES2
        mpVertexAttribList = new CPUTVertexAttribPointer[mVertexElementCount];
#else
        GL_CHECK(ES3_COMPAT(glGenVertexArrays(1, &mVertexArray))); 
        GL_CHECK(ES3_COMPAT(glBindVertexArray(mVertexArray)));
#endif
    }
    virtual ~CPUTVertexArrayOGL()
    {
#ifdef CPUT_FOR_OGLES2
        delete[] mpVertexAttribList;
#else
        if (mVertexArray != 0)
        {
            GL_CHECK(ES3_COMPAT(glDeleteVertexArrays(1, &mVertexArray)));
        }
#endif
    }
    void Disable()
    {
#ifdef CPUT_FOR_OGLES2
        for (GLint ii = 0; ii < mVertexElementCount; ii++)
        {
            mpVertexAttribList[ii].Disable();
        }
#else
        GL_CHECK(ES3_COMPAT(glBindVertexArray(0)));
#endif
        GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
        GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
    }
    void Enable()
    {
#ifdef CPUT_FOR_OGLES2
        GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferID));
        GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferID));
        for (GLint ii = 0; ii < mVertexElementCount; ii++)
        {
            mpVertexAttribList[ii].Enable();
        }
#else
        GL_CHECK(ES3_COMPAT(glBindVertexArray(mVertexArray)));
#endif
    }
//-----------------------------------------------------------------------------
void CPUTMaterialEffectOGL::SetRenderStates(CPUTRenderParameters &renderParams)
{
    GL_CHECK(glUseProgram(mShaderProgram));

    if( mVertexShaderParameters.mTextureCount ) {
        for( unsigned int ii=0; ii < mVertexShaderParameters.mTextureCount; ii++ )
        {
            GLint bindPoint = mVertexShaderParameters.mpTextureParameterBindPoints[ii];
            GLint location = mVertexShaderParameters.mpTextureParameterLocations[ii];
            CPUTTextureOGL *pTex = (CPUTTextureOGL *)mVertexShaderParameters.mpTexture[ii];
            GL_CHECK(glActiveTexture(GL_TEXTURE0 + bindPoint));
            GL_CHECK(glBindTexture(pTex->mTextureType, pTex->mTextureID));
            glUniform1i(location, bindPoint); // set the image unit to the bindpoint I think those are unique
            
#ifndef CPUT_FOR_OGLES2
            //
            // Samplers are given in the renderstate but we need to always specify one as they can be different for each texture.
            // The renderstate won't necessarily change since it is the same material.
            // 
            GL_CHECK(ES3_COMPAT(glBindSampler(bindPoint, mSamplerIDs[ii]))); 
            // why is the texture unit here not GL_TEXTURE0 + bindpoint?
            // because uint v. enum in function signatures. more discussion in OpenGL red book Chapter 6 in Sampler Objects
            // glBindSampler(GLuint unit, GLuint sampler)
            // glBindTexture(GLActiveTexture(GLenum texture)
#else
#warning "Need to do something with samplers here"
#endif
        }
    }
    
#ifndef CPUT_FOR_OGLES2
    if ( mVertexShaderParameters.mConstantBufferCount ) {
        for (unsigned int ii=0; ii < mVertexShaderParameters.mConstantBufferCount; ii++ )
        {
            GLint bindPoint = mVertexShaderParameters.mConstantBufferBindPoints[ii];
	        GL_CHECK(ES3_COMPAT(glBindBufferBase(GL_UNIFORM_BUFFER, bindPoint, ((CPUTBufferOGL*)mVertexShaderParameters.mpConstantBuffer[ii])->GetBufferID())));
        }
        
    }
#else
#warning "Need to do something with uniform blocks here"
#endif
#ifdef CPUT_SUPPORT_IMAGE_STORE
    if( mVertexShaderParameters.mUAVCount)
        for(unsigned int ii=0; ii < mVertexShaderParameters.mUAVCount; ii++)
        {
            CPUTTextureOGL *pTex = (CPUTTextureOGL *)mVertexShaderParameters.mpUAV[ii];
            GLint mode = mVertexShaderParameters.mpUAVMode[ii];
            GL_CHECK(glBindImageTexture(0, pTex->GetTexture(), 0, GL_FALSE, 0, mode, GL_RGBA8));
        }
#endif

    // Set the render state block if it changed
    if( mpLastRenderStateBlock != mpRenderStateBlock )
    {
        mpLastRenderStateBlock = mpRenderStateBlock;
        if( mpRenderStateBlock )
        {
            // We know we have a OGL class.  Does this correctly bypass the virtual?
            // Should we move it to the OGL class.
            ((CPUTRenderStateBlockOGL*)mpRenderStateBlock)->SetRenderStates(renderParams);
        }
        else
        {
            CPUTRenderStateBlock::GetDefaultRenderStateBlock()->SetRenderStates(renderParams);
        }
    }
}
//-----------------------------------------------------------------------------
void CPUTMaterialEffectOGL::BindConstantBuffers( CPUTShaderParameters &params, const CPUTModel *pModel, int meshIndex )
{
    CPUTAssetLibraryOGL *pAssetLibrary = (CPUTAssetLibraryOGL*)CPUTAssetLibrary::GetAssetLibrary();
    
    for(params.mConstantBufferCount=0; params.mConstantBufferCount < params.mConstantBufferParameterCount; params.mConstantBufferCount++)
    {
        cString constantBufferName;
        UINT constantBufferCount = params.mConstantBufferCount;

// Dirty fix - you should work on std::string in all OS'es ! Why WSTRING ? Whyyyyyyy
#ifndef CPUT_OS_WINDOWS
        cString tagName = params.mConstantBufferParameterNames[constantBufferCount];
#else
        cString tagName = s2ws(params.mConstantBufferParameterNames[constantBufferCount].c_str());
#endif


        CPUTConfigEntry *pValue = mConfigBlock.GetValueByName(tagName);
        if( !pValue->IsValid() )
        {
            // We didn't find our property in the file.  Is it in the global config block?
            pValue = CPUTMaterial::mGlobalProperties.GetValueByName(tagName);
        }
		ASSERT( pValue->IsValid(), L"Can't find constant buffer '" + tagName + L"'." ); //  TODO: fix message
        
        constantBufferName = pValue->ValueAsString();
     
        UINT bindPoint = params.mConstantBufferBindPoints[constantBufferCount];
        ASSERT( bindPoint < CPUT_MATERIAL_MAX_CONSTANT_BUFFER_SLOTS, _L("Constant buffer bind point out of range.") );

        params.mBindConstantBufferMin = std::min( params.mBindConstantBufferMin, bindPoint );
        params.mBindConstantBufferMax = std::max( params.mBindConstantBufferMax, bindPoint );

        if( constantBufferName[0] == '@' )
        {
            constantBufferName += ptoc(pModel) + itoc(meshIndex);
        }
        else if( constantBufferName[0] == '#' )
        {
            constantBufferName += ptoc(pModel);
        }
        if( !params.mpConstantBuffer[constantBufferCount] )
        {
            params.mpConstantBuffer[constantBufferCount] = pAssetLibrary->GetConstantBuffer( constantBufferName );
            ASSERT( params.mpConstantBuffer[constantBufferCount], _L("Failed getting constant buffer ") + constantBufferName);
        }

#ifndef CPUT_FOR_OGLES2
        ES3_COMPAT(glUniformBlockBinding(mShaderProgram, bindPoint, bindPoint)); // just use the index as the binding point
#else
#warning "Need to do something with uniform buffers here"
#endif
        // If has constant buffer, then add to mppBindConstantBuffer
//        params.mppBindConstantBuffers[bindPoint]   = ((CPUTBufferOGL*)mpConstantBuffer[constantBufferCount])->GetNativeBuffer();
//        if( params.mppBindConstantBuffers[bindPoint] ) {
//            params.mppBindConstantBuffers[bindPoint]->AddRef();
//        }
    }
	  DEBUG_PRINT(_L("Exit BindConstantBuffers"));

}
//-----------------------------------------------------------------------------
void CPUTMaterialEffectOGL::ReadShaderSamplersAndTextures( GLuint shaderProgram, CPUTShaderParameters *pShaderParameter )
{
    GLint numActiveUniforms;
    GLint activeUniformMaxLength;
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &numActiveUniforms));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformMaxLength));
    
#ifndef CPUT_FOR_OGLES2
    GLint numActiveUniformBlocks;
    GLint activeUniformBlockMaxLength = 50;
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numActiveUniformBlocks));
#else
#warning "Need to do something with uniform blocks here"
#endif
	//
	// #### This parameter is currently unsupported by Intel OGL drivers.
	//
  //  GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &activeUniformBlockMaxLength));
    
    GLchar* uniformVariableName = new GLchar[activeUniformMaxLength];
    GLenum  dataType;
    GLint   size;
    for (int i = 0; i < numActiveUniforms; i++) {
        GL_CHECK(glGetActiveUniform(shaderProgram, i, activeUniformMaxLength, NULL, &size, &dataType, uniformVariableName));
        switch(dataType) {
#ifndef CPUT_FOR_OGLES
            case GL_SAMPLER_1D:
#endif
        case GL_SAMPLER_2D:
#ifndef CPUT_FOR_OGLES2
        case GL_SAMPLER_3D:
#endif
		case GL_SAMPLER_2D_SHADOW:
        case GL_SAMPLER_CUBE:
		        pShaderParameter->mpTextureParameterNames.push_back(uniformVariableName);
                pShaderParameter->mpTextureParameterLocations.push_back(glGetUniformLocation(shaderProgram, uniformVariableName));
                pShaderParameter->mTextureParameterCount++;
                break;
            default:
                // unsupported uniform type
            break;
        }
    }
	delete uniformVariableName;

#ifndef CPUT_FOR_OGLES2
    GLchar* uniformBlockName = new GLchar[activeUniformBlockMaxLength];
    for (int i = 0; i < numActiveUniformBlocks; i++) 
    {
        GL_CHECK(ES3_COMPAT(glGetActiveUniformBlockName(shaderProgram, i, activeUniformBlockMaxLength, NULL, uniformBlockName)));
        pShaderParameter->mConstantBufferParameterNames.push_back(uniformBlockName);
        pShaderParameter->mConstantBufferBindPoints.push_back(ES3_COMPAT(glGetUniformBlockIndex(shaderProgram, uniformBlockName)));
        pShaderParameter->mConstantBufferParameterCount++;
    }
    delete uniformBlockName;
#else
#warning "Need to do something with uniform blocks here"
#endif
/*    
    glUseProgram(0);
    
    GLchar activeUniformNames[10][100];
    GLchar activeUniformBlockNames[10][100];
    GLchar activeAttributeNames[10][100];
    GLint numActiveAttributes, activeAttributeMaxLength;
    GLint numActiveUniformBlocks, activeUniformBlockMaxLength;
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &numActiveUniforms));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformMaxLength));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &numActiveAttributes));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttributeMaxLength));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numActiveUniformBlocks));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &activeUniformBlockMaxLength));
    
    GLsizei numBytesWritten;
    
    
     for (int i = 0; i < numActiveUniforms; i++) {
        GL_CHECK(glGetActiveUniform(shaderProgram, i, 100, &numBytesWritten, &size, &dataType, activeUniformNames[i]));
    }
    
    for (int i = 0; i < numActiveAttributes; i++) {
        GL_CHECK(glGetActiveAttrib(shaderProgram, i, 100, &numBytesWritten, &size, &dataType, activeAttributeNames[i]));
    }
    
    for (int i = 0; i < numActiveUniformBlocks; i++) {
 //       GL_CHECK(glGetActiveUniformBlock(shaderProgram, i, ));
    }

    CheckDebugLog2();
    
    GLuint g_gaussSampler;
    glGenSamplers(1, &g_gaussSampler);
    glSamplerParameteri(g_gaussSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glSamplerParameteri(g_gaussSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glSamplerParameteri(g_gaussSampler, GL_TEXTURE_WRAP_S, GL_REPEAT);

    GLuint TextureName = gli::createTexture2D("/home/q-dawg/Develop/projects/Framework/CPUT_Linux/SampleStartCPUT/Media/Teapot/Texture/checker_20x.dds");

    
    glBindTexture(GL_TEXTURE_2D, TextureName);
    GL_CHECK(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ));
    GL_CHECK(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ));
    GL_CHECK(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ));
    GL_CHECK(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ));
    GL_CHECK(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT ));
    GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
    
    GLint diffuseTextureLocation = glGetUniformLocation(shaderProgram, "diffuseTex");
    CheckDebugLog2();
    glUseProgram(mShaderProgram);
    glUniform1i(diffuseTextureLocation, 0);
    CheckDebugLog2();
    GL_CHECK(glActiveTexture(GL_TEXTURE0 + 0));
    GL_CHECK(glBindTexture(GL_TEXTURE_2D, TextureName));
    glUseProgram(0);
*/    
}
 // Not supported in ES
 void AddVertexIPointer(GLint index, GLint count, GLenum type, GLint stride, void * offset)
 {
     GL_CHECK(glEnableVertexAttribArray(index));
     GL_CHECK(ES3_COMPAT(glVertexAttribIPointer(index, count, type, stride, offset)));
 }
//-----------------------------------------------------------------------------
CPUTResult CPUTRenderStateBlockOGL::LoadRenderStateBlock(const cString &fileName)
{
    // TODO: If already loaded, then Release() all the old members

    // use the fileName for now, maybe we'll add names later?
    mMaterialName = fileName;

    // Open/parse the file
    CPUTConfigFile file;
    CPUTResult result = file.LoadFile(fileName);
    ASSERT( !FAILED(result), _L("Failed loading file: '") + fileName + _L("'.") );

    // Note: We ignore "not found error" results for ReadProperties() calls.
    // These blocks are optional.
//    for( UINT ii=0; ii<8; ii++ )
//    {
//        char pBlockName[64];
//#ifndef CPUT_OS_WINDOWS
//        sprintf( pBlockName, _L("RenderTargetBlendStateOGL_%d"), ii+1 );
//#else
//        sprintf( pBlockName, ("RenderTargetBlendStateOGL_%d"), ii+1 );
//#endif
//    }

//#ifndef CPUT_OS_WINDOWS
//    ReadProperties( file, "DepthStencilStateOGL", pDepthStencilDescMap, &mStateDesc.DepthStencilDesc);
//    ReadProperties( file, "RasterizerStateOGL",   pRasterizerDescMap,   &mStateDesc.RasterizerDesc);
//    ReadProperties( file, "RenderTargetBlendStateOGL",   pRenderTargetBlendDescMap,   &mStateDesc.RenderTargetBlendDesc);
//#else
    ReadProperties( file, _L("DepthStencilStateOGL"), pDepthStencilDescMap, &mStateDesc.DepthStencilDesc);
    ReadProperties( file, _L("RasterizerStateOGL"),   pRasterizerDescMap,   &mStateDesc.RasterizerDesc);
    ReadProperties( file, _L("RenderTargetBlendStateOGL"),   pRenderTargetBlendDescMap,   &mStateDesc.RenderTargetBlendDesc);
//#endif

    //
    // For each sampler we read, need to create an OGL sampler object
    //
#ifndef CPUT_FOR_OGLES2
    GL_CHECK(ES3_COMPAT(glGenSamplers(1, &mStateDesc.DefaultSamplerID)));
    GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.DefaultSamplerID, GL_TEXTURE_MIN_FILTER,   mStateDesc.DefaultSamplerDesc.MinFilter)));
    GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.DefaultSamplerID, GL_TEXTURE_MAG_FILTER,   mStateDesc.DefaultSamplerDesc.MagFilter)));
    GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.DefaultSamplerID, GL_TEXTURE_WRAP_S,       mStateDesc.DefaultSamplerDesc.AddressU)));
    GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.DefaultSamplerID, GL_TEXTURE_WRAP_T,       mStateDesc.DefaultSamplerDesc.AddressV)));
    GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.DefaultSamplerID, GL_TEXTURE_WRAP_R,       mStateDesc.DefaultSamplerDesc.AddressW)));
    GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.DefaultSamplerID, GL_TEXTURE_COMPARE_MODE, mStateDesc.DefaultSamplerDesc.ComparisonMode)));
    GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.DefaultSamplerID, GL_TEXTURE_COMPARE_FUNC, mStateDesc.DefaultSamplerDesc.ComparisonFunc)));
    GL_CHECK(ES3_COMPAT(glSamplerParameterf( mStateDesc.DefaultSamplerID, GL_TEXTURE_MIN_LOD,      mStateDesc.DefaultSamplerDesc.MinLOD)));
    GL_CHECK(ES3_COMPAT(glSamplerParameterf( mStateDesc.DefaultSamplerID, GL_TEXTURE_MAX_LOD,      mStateDesc.DefaultSamplerDesc.MaxLOD)));
#ifndef CPUT_FOR_OGLES
    GL_CHECK(glSamplerParameterf( mStateDesc.DefaultSamplerID, GL_TEXTURE_LOD_BIAS,     mStateDesc.DefaultSamplerDesc.MipLODBias));
    GL_CHECK(glSamplerParameterfv(mStateDesc.DefaultSamplerID, GL_TEXTURE_BORDER_COLOR, mStateDesc.DefaultSamplerDesc.BorderColor));
#endif
#else
#warning "Need to do something with samplers here"
#endif
        
    mNumSamplers = 0;
    for( UINT ii=0; ii<NUM_SAMPLERS_PER_RENDERSTATE; ii++ )
    {
        // TODO: Use sampler names from .fx file.  Already did this for texture names.
        // The challenge is that the renderstate file is independent from the material (and the shaders).
        // Another feature is that the artists don't name the samplers (in the CPUTSL source).  Though, arbitrary .fx files can.
        // TODO: Add sampler-state properties to CPUTSL source (e.g., filter modes).  Then, have ShaderGenerator output a .rs file.
        char pBlockName[64];
#ifndef CPUT_OS_WINDOWS
        sprintf( pBlockName, _L("SamplerOGL_%d"), ii+1 );
        CPUTResult result = ReadProperties( file, cString(pBlockName), pSamplerDescMap, &mStateDesc.SamplerDesc[ii] );
#else
        sprintf( pBlockName, ("SamplerOGL_%d"), ii+1 );
        CPUTResult result = ReadProperties( file, cString(s2ws(pBlockName)), pSamplerDescMap, &mStateDesc.SamplerDesc[ii] );
#endif

        if( CPUT_SUCCESS != result )
        {
            break; // Reached last sampler spec
        }

#ifndef CPUT_FOR_OGLES2
        //
        // For each sampler we read, need to create an OGL sampler object
        //
        GL_CHECK(ES3_COMPAT(glGenSamplers(1, &mStateDesc.SamplerIDs[ii])));
        GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.SamplerIDs[ii], GL_TEXTURE_MIN_FILTER,   mStateDesc.SamplerDesc[ii].MinFilter)));
        GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.SamplerIDs[ii], GL_TEXTURE_MAG_FILTER,   mStateDesc.SamplerDesc[ii].MagFilter)));
        GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.SamplerIDs[ii], GL_TEXTURE_WRAP_S,       mStateDesc.SamplerDesc[ii].AddressU)));
        GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.SamplerIDs[ii], GL_TEXTURE_WRAP_T,       mStateDesc.SamplerDesc[ii].AddressV)));
        GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.SamplerIDs[ii], GL_TEXTURE_WRAP_R,       mStateDesc.SamplerDesc[ii].AddressW)));
#ifndef CPUT_FOR_OGLES
        GL_CHECK(glSamplerParameterf( mStateDesc.SamplerIDs[ii], GL_TEXTURE_LOD_BIAS,     mStateDesc.SamplerDesc[ii].MipLODBias));
        GL_CHECK(glSamplerParameterfv(mStateDesc.SamplerIDs[ii], GL_TEXTURE_BORDER_COLOR, mStateDesc.SamplerDesc[ii].BorderColor));
#endif
        GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.SamplerIDs[ii], GL_TEXTURE_COMPARE_MODE, mStateDesc.SamplerDesc[ii].ComparisonMode)));
        GL_CHECK(ES3_COMPAT(glSamplerParameteri( mStateDesc.SamplerIDs[ii], GL_TEXTURE_COMPARE_FUNC, mStateDesc.SamplerDesc[ii].ComparisonFunc)));
        GL_CHECK(ES3_COMPAT(glSamplerParameterf( mStateDesc.SamplerIDs[ii], GL_TEXTURE_MIN_LOD,      mStateDesc.SamplerDesc[ii].MinLOD)));
        GL_CHECK(ES3_COMPAT(glSamplerParameterf( mStateDesc.SamplerIDs[ii], GL_TEXTURE_MAX_LOD,      mStateDesc.SamplerDesc[ii].MaxLOD)));
#else
#warning "Need to do something with samplers here"
#endif

        ++mNumSamplers;
    }
 //   CreateNativeResources();

    return CPUT_SUCCESS;
} // CPUTRenderStateBlockOGL::LoadRenderStateBlock()
// Create a window context
//-----------------------------------------------------------------------------
CPUTResult CPUT_OGL::CPUTCreateWindowAndContext(const cString WindowTitle, CPUTWindowCreationParams windowParams)
{
    CPUTResult result = CPUT_SUCCESS;

    HEAPCHECK;

    // We shouldn't destroy old window if it already exist, 
    // Framework user should do this by himself to be aware
    // of what he is doing.
    if( mpWindow )
    {
        return CPUT_ERROR_WINDOW_ALREADY_EXISTS;
    }

    result = MakeWindow(WindowTitle, windowParams);
    if(CPUTFAILED(result))
    {
        return result;
    }


    HEAPCHECK;

    // create the GL context
    result = CreateOGLContext(windowParams.deviceParams);
    if(CPUTFAILED(result))
    {
        return result;
    }


    HEAPCHECK;

    result = CreateContext();

    CPUTRenderStateBlock *pBlock = new CPUTRenderStateBlockOGL();
    CPUTRenderStateBlock::SetDefaultRenderStateBlock( pBlock );

    cString name = _L("$cbPerFrameValues");
    mpPerFrameConstantBuffer = new CPUTBufferOGL(name);
    GLuint id = mpPerFrameConstantBuffer->GetBufferID();
#ifndef CPUT_FOR_OGLES2
    GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, mpPerFrameConstantBuffer->GetBufferID()));
    GL_CHECK(glBufferData(GL_UNIFORM_BUFFER, sizeof(CPUTFrameConstantBuffer), NULL, GL_DYNAMIC_DRAW)); // NULL to just init buffer size
    DEBUG_PRINT(_L("bind per frame buffer buffer %d\n"), id);
//FIXME: constant buffer binding
    GL_CHECK(ES3_COMPAT(glBindBufferBase(GL_UNIFORM_BUFFER, id, id)));
    DEBUG_PRINT(_L("completed - bind buffer %d\n"), id);
    GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, 0));
#else
#warning "Need to do something with uniform buffers here"
#endif
    CPUTAssetLibrary::GetAssetLibrary()->AddConstantBuffer(_L(""), name, _L(""), mpPerFrameConstantBuffer);
    
    name = _L("$cbPerModelValues");
    mpPerModelConstantBuffer = new CPUTBufferOGL(name, GL_UNIFORM_BUFFER, GL_DYNAMIC_DRAW, sizeof(CPUTModelConstantBuffer), NULL);
    
    id = mpPerModelConstantBuffer->GetBufferID();
#ifndef CPUT_FOR_OGLES2
    DEBUG_PRINT(_L("Bind per model values %d"), id);
    GL_CHECK(ES3_COMPAT(glBindBufferBase(GL_UNIFORM_BUFFER, id, id)));
    DEBUG_PRINT(_L("Completed bind per model values"));
    GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, 0));
#else
#warning "Need to do something with uniform buffers here"
#endif
    CPUTAssetLibrary::GetAssetLibrary()->AddConstantBuffer(_L(""), name, _L(""), mpPerModelConstantBuffer);

    name = _L("$cbGUIConstants");
    CPUTBuffer* pBuffer = new CPUTBufferOGL(name, GL_UNIFORM_BUFFER, GL_DYNAMIC_DRAW, sizeof(GUIConstants), NULL);
    
    CPUTAssetLibrary::GetAssetLibrary()->AddConstantBuffer(_L(""), name, _L(""), pBuffer);
    SAFE_RELEASE(pBuffer);
	// Add our programatic (and global) material parameters
    CPUTMaterial::mGlobalProperties.AddValue( _L("cbPerFrameValues"), _L("$cbPerFrameValues") );
    CPUTMaterial::mGlobalProperties.AddValue( _L("cbPerModelValues"), _L("$cbPerModelValues") );
    CPUTMaterial::mGlobalProperties.AddValue( _L("cbGUIValues"), _L("$cbGUIValues") );
    HEAPCHECK;

    // Trigger a post-create user callback event
    Create();
    HEAPCHECK;

    //
    // Start the timer after everything is initialized and assets have been loaded
    //
    mpTimer->StartTimer();

    int x,y,width,height;
    mpWindow->GetClientDimensions(&x, &y, &width, &height);

    ResizeWindow(width,height);

    return result;
}