hostsupport/hostegl/src/EGLState.cpp
author Matt Plumtree <matt.plumtree@nokia.com>
Wed, 06 Oct 2010 17:59:01 +0100
branchbug235_bringup_0
changeset 53 c2ef9095503a
child 56 40cc73c24bf8
permissions -rw-r--r--
Copy code from the holdingarea into the target locations. Some initial rework of CMakeLists.txt files, but not yet tested.

/* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and /or associated documentation files
 * (the "Materials "), to deal in the Materials without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Materials,
 * and to permit persons to whom the Materials are furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Materials.
 *
 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
 * THE USE OR OTHER DEALINGS IN THE MATERIALS.
 *
 * Initial Contributors:
 * Nokia Corporation - initial contribution.
 *
 * Contributors:
 *
 * Description:
 *
 */

#include "EGLState.h"
#include "EGLDisplay.h"
#include "EGLProcess.h"
#include "EGLThread.h"
#include "EGLContext.h"
#include "EGLConfig.h"
#include "EGLOs.h"
#include "EGLImage.h"
#include "EGLPbufferSurface.h"
#include "EGLWindowSurface.h"
#include <EGL/eglext.h>

#include <string.h>

CEGLState::CEGLState(void) :
    m_initialized( false ),
    m_currentProcess( NULL ),
    m_VGLib( NULL ),
    m_VGInterface( NULL ),
    m_GLES1Lib( NULL ),
    m_GLES1Interface( NULL ),
    m_GLES2Lib( NULL ),
    m_GLES2Interface( NULL ),
	m_hostGL( NULL ),
    m_supportedApis( 0 ),
	m_defaultDisplay( NULL ),
	m_dummyWindow( NULL )
    {

#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    CEGLProcess* p = EGLI_NEW CEGLProcess(0);
    EGLI_ASSERT( p != NULL );
    AddObject<CEGLProcess>( m_processes, p );
    m_currentProcess = p;
#endif
    }

CEGLState::~CEGLState(void)
    {
    DestroyPointerVector<CEGLProcess>( m_processes );
    DestroyPointerVector<CEGLDisplay>( m_displays );
    DestroyPointerVector<CEGLConfig>( m_configs );
    if( m_VGLib ) EGLI_ASSERT( CEGLOs::FreeClientLibrary(m_VGLib) );
    if( m_GLES1Lib ) EGLI_ASSERT( CEGLOs::FreeClientLibrary(m_GLES1Lib) );
    if( m_GLES2Lib ) EGLI_ASSERT( CEGLOs::FreeClientLibrary(m_GLES2Lib) );
#if defined(_WIN32)
#   if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    if( m_defaultDisplay )
        {
        // \todo If at some point EGL_DEFAULT_DISPLAY is created
        //       with CreateDC() the DC needs to be released by
        //       calling DeleteDC().
        //CEGLOs::DestroyDefaultDisplay( m_defaultDisplay );
        ReleaseDC( m_dummyWindow, m_defaultDisplay );
        }
    // \note Dummy window created in CEGLDisplay::Initialize(). See comment
    //       in CEGLOs::CreateDefaultDisplay().
    if( m_dummyWindow )
        {
        CEGLOs::DestroyNativeWindow( m_dummyWindow );
        }
#   endif
#endif
    }

bool CEGLState::Initialize()
    {
    if( !m_initialized )
        {
        if( !(CreateConfigs()) ) return false;
        m_initialized = true;
        m_VGInterface = CEGLOs::LoadVGInterface( m_VGLib );
        if( m_VGInterface ) 
            {
            m_VGInterface->SetEGLInterface( this );
            m_supportedApis |= EGL_OPENVG_BIT;
            }

        m_GLES1Interface = CEGLOs::LoadGLES1Interface( m_GLES1Lib );
        if( m_GLES1Interface ) 
            {
            m_GLES1Interface->SetEGLInterface( this );
            m_supportedApis |= EGL_OPENGL_ES_BIT;
            }

	    m_GLES2Interface = CEGLOs::LoadGLES2Interface( m_GLES2Lib );
        if( m_GLES2Interface ) 
            {
            m_GLES2Interface->SetEGLInterface( this );
            m_supportedApis |= EGL_OPENGL_ES2_BIT;
            }

        if( m_supportedApis & EGL_OPENGL_ES_BIT || (m_supportedApis & EGL_OPENGL_ES2_BIT) )
            {
            m_hostGL = CEGLOs::LoadHostGL();
            if( !m_hostGL ) m_initialized = false;
            }
        if( !m_supportedApis )
            {
            m_initialized = false;
            }

		//m_defaultDisplay = CEGLOs::CreateDefaultDisplay();
        // \note Creating a dummy window to get DC from. See comment
        //       in CEGLOs::CreateDefaultDisplay().
		m_dummyWindow = CEGLOs::CreateNativeWindow(0, 0);
        if( m_dummyWindow )
			{
#if defined(_WIN32)
			m_defaultDisplay = (EGLINativeDisplayType)GetDC( (HWND)m_dummyWindow );
#else // Linux
			EGLI_ASSERT( false );
#endif
			if( !m_defaultDisplay )
				{
				CEGLOs::DestroyNativeWindow( m_dummyWindow );
				m_initialized = false;
				}
			}
        }
    return m_initialized;
    }

CEGLDisplay* CEGLState::AddDisplay( EGLINativeDisplayType nativeType, EGLint processId )
    {
#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
    CEGLDisplay* display = EGLI_NEW CEGLDisplay( nativeType, processId );
#else
    CEGLDisplay* display = EGLI_NEW CEGLDisplay( nativeType, m_currentProcess->Id() );
#endif
    if( display )
        {
        AddObject<CEGLDisplay>( m_displays, display );
        }
    return display;
    }

void CEGLState::RemoveDisplay( EGLDisplay display )
    {
    DeleteObjectByPointer<CEGLDisplay>( m_displays, display );
    }

CEGLDisplay* CEGLState::GetDisplayByNativeType( EGLINativeDisplayType nativeType, EGLint processId ) const
    {
    CEGLDisplay* ret = NULL;
    for( std::vector<CEGLDisplay*>::const_iterator iter = m_displays.begin();
        iter != m_displays.end();
        iter++)
        {
#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
        if( (*iter)->NativeType() == nativeType && (*iter)->ProcessId() == processId )
#else
        if( (*iter)->NativeType() == nativeType )
#endif
            {
            ret = (*iter);
            break;
            }
        }
    return ret;
    }

CEGLDisplay* CEGLState::GetDisplay( EGLDisplay display ) const
    {
    return FindObjectByPointer<CEGLDisplay>( m_displays, display, NULL);
    }

CEGLProcess* CEGLState::AddProcess( EGLint processId, bool setCurrent )
    {
#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
    CEGLProcess* process = EGLI_NEW CEGLProcess( processId );
    if( process )
        {
        AddObject<CEGLProcess>( m_processes, process );
        if( setCurrent && process )
            {
            m_currentProcess = process;
            }
        }
    return process;
#else
    EGLI_ASSERT( false );
    return NULL;
#endif
    }

void CEGLState::RemoveProcess( EGLint processId )
    {
#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
    if( m_currentProcess && m_currentProcess->Id() == processId )
        {
        m_currentProcess = NULL;
        }
    DeleteObjectById<CEGLProcess>( m_processes, processId );
#else
    EGLI_ASSERT( false );
#endif
    }

CEGLProcess* CEGLState::GetProcess( EGLint processId ) const
    {
#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
    return FindObjectById<CEGLProcess>( m_processes, processId, NULL );
#else
    return m_currentProcess;
#endif
    }

void CEGLState::SetCurrentProcessThread( EGLint processId, EGLI_THREAD_ID threadId )
    {
#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
    if( m_currentProcess && m_currentProcess->Id() == processId )
        {
        m_currentProcess->SetCurrentThread( threadId );
        }
    else
        {
        CEGLProcess* process = FindObjectById<CEGLProcess>( m_processes, processId, NULL);
        // processes are created in eglPlatsimSetProcessInformation()
        EGLI_ASSERT( process != NULL );
        process->SetCurrentThread( threadId );
        m_currentProcess = process;
        }
#else
    EGLI_ASSERT( false );
#endif
    }

void CEGLState::FillConfigs( EGLConfig* configs, EGLint size ) const
    {
    EGLI_ASSERT( size <= ConfigCount() );
    for( EGLint i=0; i < size; i++ )
        {
        configs[i] = (EGLConfig)m_configs[i];
        }
    }

CEGLConfig* CEGLState::FindConfigById( EGLint id ) const
    {
    return FindObjectById<CEGLConfig>( m_configs, id, NULL );
    }

EGLint CEGLState::MatchConfigs( CEGLConfig* filter, EGLConfig* configs, EGLint maxCount ) const
    {
    maxCount = EGLI_MIN( m_configs.size(), (unsigned int)maxCount );
    EGLint count = 0;
    std::vector<CEGLConfig*>::const_iterator iter = m_configs.begin();
    while( iter != m_configs.end() )
        {
        if( (*iter)->Match( *filter ) )
            {
            if( configs && count < maxCount )
                configs[count++] = (EGLConfig)(*iter);
            else if( configs )
                break;
            else
                count++;
            }
        iter++;
        }
    if( configs && count > 1 )
        {
        for( int i=0; i < count-1; i++ )
            for( int j=i+1; j < count; j++ )
                {
                if( *((CEGLConfig*)configs[j]) > *((CEGLConfig*)configs[i]) )
                    {
                    EGLConfig tmp = configs[i];
                    configs[i] = configs[j];
                    configs[j] = tmp;
                    }
                }
        }
    return count;
    }

CEGLConfig* CEGLState::GetConfig( EGLConfig config ) const
    {
    return FindObjectByPointer<CEGLConfig>( m_configs, config, NULL );
    }

void* CEGLState::GetVGContext()
    {
    CEGLOs::GetLock( &g_eglLock );
    void* ret = NULL;
    if( m_currentProcess &&
        m_currentProcess->CurrentThread() &&
        m_currentProcess->CurrentThread()->CurrentVGContext() )
        {
        ret = m_currentProcess->CurrentThread()->CurrentVGContext()->ClientContext();
        }
    CEGLOs::ReleaseLock( &g_eglLock );
    return ret;
    }

void* CEGLState::GetHostProcAddress(const char* proc)
	{
    return CEGLOs::GetGLProcAddress(m_hostGL, proc);
	}

void* CEGLState::GetGLESContext()
    {
    CEGLOs::GetLock( &g_eglLock );
    void* ret = NULL;
    if( m_currentProcess &&
        m_currentProcess->CurrentThread() &&
        m_currentProcess->CurrentThread()->CurrentGLESContext() )
        {
        ret = m_currentProcess->CurrentThread()->CurrentGLESContext()->ClientContext();
        }
    CEGLOs::ReleaseLock( &g_eglLock );
    return ret;
    }

bool CEGLState::IsImageInUse( void* image )
    {
    //TODO
    return false;
    }

bool CEGLState::LockVGSurface( bool read, bool write )
    {
    return LockSurface( EGL_OPENVG_API, read, write );
    }

bool CEGLState::UnlockVGSurface()
    {
    return UnlockSurface( EGL_OPENVG_API );
    }

void CEGLState::GetDescForImage( void* image, SurfaceDescriptor& ImageDesc )
    {
    CEGLImage* eglImage = (CEGLImage*)image;
    ImageDesc.m_stride = -1;
    ImageDesc.m_height = -1;
    ImageDesc.m_width  = -1;
    // Check that image is not null.
    if( !eglImage )
        {        
        return;
        }

    // Check that image is not from VGImage target. -> EGL_VG_PARENT_IMAGE_KHR
    if( eglImage->Target() == EGL_VG_PARENT_IMAGE_KHR )
        {
        return;
        }

	memcpy(&ImageDesc, &eglImage->SurfaceDesc(), sizeof(ImageDesc));
    }


void* CEGLState::GetDataForImage( void* image )
    {
    CEGLImage* eglImage = (CEGLImage*)image;
    // Check that image is not null.
    if( !eglImage )
        {
        // if null then error
        return NULL;
        }
	return eglImage->Data();
    }

void CEGLState::RegisterImageTarget( void* image, EImageTarget target, void* buffer )
	{
	// \todo Implement
	}

void CEGLState::UnregisterImageTarget( void* image, EImageTarget target, void* buffer )
	{
	// \todo Implement
	}

void CEGLState::UpdateImageSiblings( void* image, EImageTarget target, void* buffer )
	{
	// \todo Implement
	}

void CEGLState::ReleaseTexImage(void* surface, int name, int level)
{
	CEGLSurface* eglSurface = (CEGLSurface*)surface;
	EGLITextureBinding& binding = eglSurface->TextureBinding();
	if(binding.name == name && binding.level == level)
	{
		eglSurface->Unlock();
		binding.name = 0;
	}
}

bool CEGLState::LockGLESSurface( bool read, bool write )
    {
    return LockSurface( EGL_OPENGL_ES_API, read, write );
    }
bool CEGLState::UnlockGLESSurface()
    {
    return UnlockSurface( EGL_OPENGL_ES_API );
    }

bool CEGLState::SyncSurface( EGLenum api, EGLint apiVersion, CEGLSurface* surface, CEGLSurface* currentGLESReadSurface )
	{
	switch( api )
		{
		case EGL_OPENVG_API:
			{
			EGLint glesVersion = 0;
			if( surface->IsGLES1Dirty() )
				{
				glesVersion = 1;
				}
			else if( surface->IsGLES2Dirty() )
				{
				glesVersion = 2;
				}
			if( glesVersion )
				{
				if( surface != currentGLESReadSurface )
					{
					EGLINativeContextType glesCopyContext = NULL;
                    EGLINativeDisplayType glesCopyDisplay = NULL;
                    EGLINativeGLFunctions* funcs = NULL;
					bool pbuffer = ( surface->Type() == CEGLSurface::PBUFFER_SURFACE );
					if( pbuffer )
						{
						if( !(((CEGLPbufferSurface*)surface)->BindCopyContext()) )
							{
							((CEGLPbufferSurface*)surface)->ReleaseCopyContext();
							
							return false;
							}
						}
					else if( surface->Type() == CEGLSurface::WINDOW_SURFACE )
						{
						// \todo Remove this or handle window surface sync properly
						/*
						funcs = thread->CurrentGLESContext()->NativeGLFunctions();
						glesCopyContext = thread->CurrentGLESContext()->NativeContext();
						glesCopyDisplay = ((CEGLWindowSurface*)surface)->OsContext()->glesDisplay;
						*/
						}
					if( !(GLESInterface(glesVersion)->CopyBuffers(surface->GLESColorBuffer(), surface->Descriptor())) )
						{
						if( pbuffer )
							{
							((CEGLPbufferSurface*)surface)->ReleaseCopyContext();
							}
						return false;
						}
					if( pbuffer )
						{
						((CEGLPbufferSurface*)surface)->ReleaseCopyContext();
						}
					else if( surface->Type() == CEGLSurface::WINDOW_SURFACE )
						{
						// \todo Remove this or handle window surface sync properly
						//EGLI_ASSERT( false );
						}
					}
				else
					{
					if( !(GLESInterface(glesVersion)->CopyBuffers(surface->GLESColorBuffer(), surface->Descriptor())) )
						return false;
					}

				if( VGInterface() )
                    {
                    VGInterface()->UpdateBuffers(surface->GLESColorBuffer(), surface->Stride(), surface->Descriptor());
                    }
                surface->SetGLES1Dirty( false );
				surface->SetGLES2Dirty( false );
				}
			break;
			}

		case EGL_OPENGL_ES_API:
			{
			if( surface->IsVGDirty() )
                {
				if( !(GLESInterface(apiVersion)->UpdateBuffers(surface->VGColorBuffer(), surface->Descriptor())) )
                    {
                    return false;
                    }
                surface->SetVGDirty( false );
                }
			break;
			}
		}

	return true;
	}

bool CEGLState::LockSurface( EGLenum api, bool read, bool write )
    {
    CEGLOs::GetLock( &g_eglLock );
    CEGLSurface* readSurface = NULL;
    CEGLSurface* drawSurface = NULL;
	CEGLSurface* glesReadSurface = NULL;
	EGLint apiVersion;
    CEGLThread* thread = m_currentProcess->CurrentThread();
    if( !thread )
        {
        CEGLOs::ReleaseLock( &g_eglLock );
        return false;
        }
    switch( api )
        {
        case EGL_OPENVG_API:
            {
            drawSurface = thread->CurrentVGSurface();
            readSurface = drawSurface;
			apiVersion = 0;
            break;
            }
        case EGL_OPENGL_ES_API:
            {
            thread->CurrentGLESSurfaces( &readSurface, &drawSurface );
			apiVersion = thread->CurrentGLESContext()->ClientVersion();
            break;
            }
        }
    if( !readSurface && !drawSurface )
        {
        CEGLOs::ReleaseLock( &g_eglLock );
        return false;
        }

	if( api == EGL_OPENVG_API )
		{
		thread->CurrentGLESSurfaces( &readSurface, NULL );
		}
    
    if( read && readSurface )
        {
        readSurface->Lock();
		if( !SyncSurface( api, apiVersion, readSurface, glesReadSurface ) )
			{
			CEGLOs::ReleaseLock( &g_eglLock );
			return false;
			}
        }
    if( write && drawSurface && (!read || drawSurface != readSurface) )
        {
        drawSurface->Lock();
		if( !SyncSurface( api, apiVersion, drawSurface, glesReadSurface ) )
			{
			CEGLOs::ReleaseLock( &g_eglLock );
			return false;
			}
        }
    CEGLOs::ReleaseLock( &g_eglLock );
    return true;
    }

bool CEGLState::UnlockSurface( EGLenum api )
    {
    CEGLOs::GetLock( &g_eglLock );
    CEGLSurface* drawSurface = NULL;
	CEGLSurface* readSurface = NULL;
    CEGLThread* thread = m_currentProcess->CurrentThread();
    if( !thread )
        {
        CEGLOs::ReleaseLock( &g_eglLock );
        return false;
        }
    switch( api )
        {
        case EGL_OPENVG_API:
            {
            drawSurface = thread->CurrentVGSurface();
			readSurface = drawSurface;
			if( drawSurface && drawSurface->IsLocked() )
                drawSurface->SetVGDirty( true );
            break;
            }
        case EGL_OPENGL_ES_API:
            {
            thread->CurrentGLESSurfaces( &readSurface, &drawSurface );
			if( drawSurface && drawSurface->IsLocked() )
				{
				EGLint glesVersion = thread->CurrentGLESContext()->ClientVersion();
				if(glesVersion == 1)
					{
					drawSurface->SetGLES1Dirty( true );
					}
				else
					{
					EGLI_ASSERT(glesVersion == 2);
					drawSurface->SetGLES2Dirty( true );
					}
				}
            break;
            }
        }
    if( drawSurface && drawSurface->IsLocked() )
        {
        drawSurface->Unlock();
        }
    if( readSurface && readSurface->IsLocked() )
        {
        readSurface->Unlock();
        }

    CEGLOs::ReleaseLock( &g_eglLock );
    return true;
    }

bool CEGLState::CreateConfigs()
    {    
    // ** Config list START **
    // Initial config count. If adding configs to the list below
    // remember to add this count too.
    int count = 21;
    for( int i=0; i < count; i++ )
        {        
        CEGLConfig* config = EGLI_NEW CEGLConfig();
        // \note AddObject destroys the object if fails to take ownership 
        AddObject<CEGLConfig>( m_configs, config );
        if( !config )
            {
            DestroyPointerVector<CEGLConfig>( m_configs );
            return false;
            }
        }
    int configId = 0;
    CEGLConfig* config = m_configs[configId];
    //                                                 r, g, b, l, a, am, s, bpp, id
    // XRGB_8888 and ARGB_8888
                                  config->SetUpConfig( 8, 8, 8, 0, 8, 0,  0, 32,  ++configId ); //  1
    config = m_configs[configId]; config->SetUpConfig( 8, 8, 8, 0, 8, 1,  0, 32,  ++configId ); //  2
    config = m_configs[configId]; config->SetUpConfig( 8, 8, 8, 0, 8, 4,  0, 32,  ++configId ); //  3
    config = m_configs[configId]; config->SetUpConfig( 8, 8, 8, 0, 8, 8,  0, 32,  ++configId ); //  4    
    config = m_configs[configId]; config->SetUpConfig( 8, 8, 8, 0, 0, 0,  0, 32,  ++configId ); //  5
    config = m_configs[configId]; config->SetUpConfig( 8, 8, 8, 0, 0, 1,  0, 32,  ++configId ); //  6
    config = m_configs[configId]; config->SetUpConfig( 8, 8, 8, 0, 0, 4,  0, 32,  ++configId ); //  7
    config = m_configs[configId]; config->SetUpConfig( 8, 8, 8, 0, 0, 8,  0, 32,  ++configId ); //  8
    // RGB_565
    config = m_configs[configId]; config->SetUpConfig( 5, 6, 5, 0, 0, 0,  0, 16,  ++configId ); //  9
    config = m_configs[configId]; config->SetUpConfig( 5, 6, 5, 0, 0, 1,  0, 16,  ++configId ); // 10
    config = m_configs[configId]; config->SetUpConfig( 5, 6, 5, 0, 0, 4,  0, 16,  ++configId ); // 11
    config = m_configs[configId]; config->SetUpConfig( 5, 6, 5, 0, 0, 8,  0, 16,  ++configId ); // 12
    // LA_88
    config = m_configs[configId]; config->SetUpConfig( 0, 0, 0, 8, 8, 0,  0, 16,  ++configId ); // 13
    config = m_configs[configId]; config->SetUpConfig( 0, 0, 0, 8, 8, 1,  0, 16,  ++configId ); // 14
    config = m_configs[configId]; config->SetUpConfig( 0, 0, 0, 8, 8, 4,  0, 16,  ++configId ); // 15
    config = m_configs[configId]; config->SetUpConfig( 0, 0, 0, 8, 8, 8,  0, 16,  ++configId ); // 16
    // L_8
    config = m_configs[configId]; config->SetUpConfig( 0, 0, 0, 8, 0, 0,  0,  8,  ++configId ); // 17
    config = m_configs[configId]; config->SetUpConfig( 0, 0, 0, 8, 0, 1,  0,  8,  ++configId ); // 18
    config = m_configs[configId]; config->SetUpConfig( 0, 0, 0, 8, 0, 4,  0,  8,  ++configId ); // 19
    config = m_configs[configId]; config->SetUpConfig( 0, 0, 0, 8, 0, 8,  0,  8,  ++configId ); // 20
    // A_8
    config = m_configs[configId]; config->SetUpConfig( 0, 0, 0, 0, 8, 0,  0,  8,  ++configId ); // 21
    // ** Config list END **
    
    std::vector<CEGLConfig*> newConfigs;

    // stencil buffers
    std::vector<CEGLConfig*>::const_iterator iter = m_configs.begin();
    while( iter != m_configs.end() )
        {
        config = EGLI_NEW CEGLConfig();
        if( config )
            {
            *config = *(*iter);
            config->SetId( ++configId );
            config->SetAttribute( EGL_STENCIL_SIZE, 8 );
            }
        // \note AddObject destroys the object if fails to take ownership 
        AddObject<CEGLConfig>( newConfigs, config );
        if( !config )
            {
            DestroyPointerVector<CEGLConfig>( newConfigs );
            DestroyPointerVector<CEGLConfig>( m_configs );
            return false;
            }
        iter++;
        }
    try
        {
        m_configs.insert( m_configs.end(), newConfigs.begin(), newConfigs.end() );
        }
    catch( std::exception )
        {
        DestroyPointerVector<CEGLConfig>( newConfigs );
        DestroyPointerVector<CEGLConfig>( m_configs );
        return false;
        }
    newConfigs.clear();

    // depth buffers
    // 32bpp, 24bpp and 16bpp support
    for(int depthSize = 32; depthSize >= 16; depthSize -= 8 )
        {
        iter = m_configs.begin();
        while( iter != m_configs.end() )
            {
            config = EGLI_NEW CEGLConfig();
            if( config )
                {
                *config = *(*iter);
                config->SetId( ++configId );
                config->SetAttribute( EGL_DEPTH_SIZE, depthSize );
                }            
            // \note AddObject destroys the object if fails to take ownership    
            AddObject<CEGLConfig>( newConfigs, config );
            if( !config )
                {
                DestroyPointerVector<CEGLConfig>( newConfigs );
                DestroyPointerVector<CEGLConfig>( m_configs );
                return false;
                }
            iter++;
            }
        }
    try
        {
        m_configs.insert( m_configs.end(), newConfigs.begin(), newConfigs.end() );
        }
    catch( std::exception )
        {
        DestroyPointerVector<CEGLConfig>( newConfigs );
        DestroyPointerVector<CEGLConfig>( m_configs );
        return false;
        }
    newConfigs.clear();

    // multi sampling
    for( int samples = 16; samples >= 4; samples -= 12 )
        {
        iter = m_configs.begin();
        while( iter != m_configs.end() )
            {
            config = EGLI_NEW CEGLConfig();
            if( config )
                {
                *config = *(*iter);
                config->SetId( ++configId );
                config->SetAttribute( EGL_SAMPLES, samples );
                config->SetAttribute( EGL_SAMPLE_BUFFERS, 1 );
                }
            // \note AddObject destroys the object if fails to take ownership
            AddObject<CEGLConfig>( newConfigs, config );
            if( !config )
                {
                DestroyPointerVector<CEGLConfig>( newConfigs );
                DestroyPointerVector<CEGLConfig>( m_configs );
                return false;
                }
            iter++;
            }
        }
    try
        {
        m_configs.insert( m_configs.end(), newConfigs.begin(), newConfigs.end() );
        }
    catch( std::exception )
        {
        DestroyPointerVector<CEGLConfig>( newConfigs );
        DestroyPointerVector<CEGLConfig>( m_configs );
        return false;
        }
    newConfigs.clear();  
    return true;
    }

IEGLtoGLESInterface* CEGLState::GLESInterface( EGLint clientVersion ) const
	{
	EGLI_ASSERT(clientVersion == 1 || clientVersion == 2);
	return clientVersion == 1 ? m_GLES1Interface : m_GLES2Interface;
	}