hostsupport/hostegl/src/win32/EGLOs.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 "EGLOs.h"
#include "EGLState.h"
#include "EGLProcess.h"
#include "EGLThread.h"
#include "EGLWindowSurface.h"
#include "EGLDisplay.h"
#include "EGLContext.h"

#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
void doBlit( EGLIOsWindowContext* context, void* buf, int width, int height, int stride )
    {
    if( !context->osBuffer || !context->pixmap || context->width != width || context->height != height )
        {
            if( context->pixmap )
                DeleteObject( context->pixmap );
            context->osBuffer = NULL;
            context->pixmap = NULL;

            context->width = width;
            context->height = height;

            struct
            {
                BITMAPINFOHEADER	header;
                DWORD				rMask;
                DWORD				gMask;
                DWORD				bMask;
            } bmi;
            bmi.header.biSize			= sizeof( BITMAPINFOHEADER );
            bmi.header.biWidth			= width;
            bmi.header.biHeight			= height;
            bmi.header.biPlanes			= 1;
            bmi.header.biBitCount		= (WORD)32;
            bmi.header.biCompression	= BI_BITFIELDS;
            bmi.rMask = 0x00FF0000;
            bmi.gMask = 0x0000FF00;
            bmi.bMask = 0x000000FF;
            
            context->pixmap = CreateDIBSection( context->vgDisplay, (BITMAPINFO*)&bmi, DIB_RGB_COLORS, (void**)&context->osBuffer, NULL, 0 );
            if( !context->pixmap )
            {
                context->osBuffer = NULL;
                return;
            }
        }
     
        if( context->osBuffer )
            {
            HDC winDC = GetDC( context->window );
			GdiFlush();
            memcpy( context->osBuffer, buf, stride*height );
            SelectObject( context->vgDisplay, context->pixmap );
            EGLI_ASSERT( BitBlt(winDC, 0, 0, width, height, context->vgDisplay, 0, 0, SRCCOPY) );
            ReleaseDC( context->window, winDC );
            SelectObject( context->vgDisplay, NULL );
        }
    }
#endif

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   switch (message)
    {
    case WM_CLOSE:
    case WM_DESTROY:
        //PostQuitMessage(0);
        return 0;
    case WM_PAINT:
        {
        /*CEGLState* state = getState();
        if( state )
            {
            CEGLThread* thread = state->GetCurrentProcess()->CurrentThread();
            if( thread && thread->CurrentVGSurface() )
                {
                if( thread->CurrentVGSurface()->Type() == CEGLSurface::WINDOW_SURFACE )
                    {
                    CEGLWindowSurface* surface = (CEGLWindowSurface*)thread->CurrentVGSurface();
                    InvalidateRect(hwnd, NULL, 0);
                    doBlit( surface->OsContext(), surface->VGColorBuffer(), surface->Width(), surface->Height(), surface->Stride() );
                    }
                }
            }*/
        return 0;
        }
    default:
        break;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
}

void CEGLOs::InitializeLock( EGLI_LOCK *lock )
    {
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    InitializeCriticalSection( lock );
#endif
    }

void CEGLOs::GetLock( EGLI_LOCK *lock )
    {
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    EnterCriticalSection( lock );
#endif
    }

void CEGLOs::ReleaseLock(EGLI_LOCK *lock )
    {
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    LeaveCriticalSection( lock );
#endif
    }

void CEGLOs::DestroyLock( EGLI_LOCK *lock )
    {
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    DeleteCriticalSection( lock );
#endif
    }

void CEGLOs::ConfigToNativePixelFormat( const CEGLConfig& config, EGLINativePixelFormatType* nativeFormat )
    {
    EGLI_ASSERT( nativeFormat != NULL );
    memset( nativeFormat, 0, sizeof(PIXELFORMATDESCRIPTOR) );
    nativeFormat->nSize = sizeof( PIXELFORMATDESCRIPTOR );
    nativeFormat->nVersion = 1;
    nativeFormat->dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; // always support OGL
    
    // \todo Do we need color index?
    nativeFormat->iPixelType = PFD_TYPE_RGBA;
    
    // \todo overlay/underlay?
    nativeFormat->iLayerType = PFD_MAIN_PLANE;

    EGLint surfaceType = config.GetAttribute( EGL_SURFACE_TYPE );
    if( surfaceType & EGL_WINDOW_BIT )
        {
        nativeFormat->dwFlags |= PFD_DRAW_TO_WINDOW;
        }
    if( surfaceType & EGL_PIXMAP_BIT )
        {
        nativeFormat->dwFlags |= PFD_DRAW_TO_BITMAP;
        }
    nativeFormat->cColorBits = config.GetAttribute( EGL_RED_SIZE ) +
                               config.GetAttribute( EGL_GREEN_SIZE ) +
                               config.GetAttribute( EGL_BLUE_SIZE );

    nativeFormat->cAlphaBits = config.GetAttribute( EGL_ALPHA_SIZE );
    nativeFormat->cDepthBits = config.GetAttribute( EGL_DEPTH_SIZE );
    nativeFormat->cStencilBits = config.GetAttribute( EGL_STENCIL_SIZE );

    // \todo Aux buffers, accumulation buffers?
    }

EGLINativeContextType CEGLOs::CreateNativeContext( const CEGLConfig& config, EGLINativeDisplayType display, EGLINativeContextType shareContext )
    {
    EGLINativeContextType ret = NULL;
    DWORD error = ERROR_SUCCESS;
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
    CEGLOs::ConfigToNativePixelFormat( config, &pfd );
	int pixelFormat = ChoosePixelFormat( display, &pfd );
	if( !pixelFormat )
		{
        return ret;
		}
    int currentPixelFormat = GetPixelFormat( display );
	if( !currentPixelFormat && !SetPixelFormat( display, pixelFormat, &pfd ) )
		{
        error = GetLastError();
		return ret;
		}
    ret = wglCreateContext( display );
	if( ret != NULL && shareContext != NULL)
		{
		// Share context data
		if( !wglShareLists( shareContext, ret ) )
			{
			wglDeleteContext( ret );
			ret = NULL;
			}
		}
#endif
    return ret;
    }

EGLINativeContextType CEGLOs::CurrentNativeContext()
    {
    return wglGetCurrentContext();
    }

EGLINativeDisplayType CEGLOs::CurrentNativeSurface()
    {
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    return wglGetCurrentDC();
#else
    return NULL;
#endif
    }

bool CEGLOs::MakeNativeContextCurrent( struct EGLINativeGLFunctions* func, EGLINativeDisplayType draw, EGLINativeDisplayType read, EGLINativeContextType context )
    {
    bool ret = true;
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    DWORD err;
    EGLINativeContextType prevContext = wglGetCurrentContext();
    EGLINativeDisplayType prevDraw = wglGetCurrentDC();
    EGLINativeDisplayType prevRead = NULL;
    if( prevDraw ) prevRead = func->wglGetCurrentReadDCARB();
    if( context == NULL )
        {
        if( wglGetCurrentContext() != NULL )
            {
            //warning C4800: 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
            ret = (wglMakeCurrent( NULL, context ) != 0);
            }
        }
    else
        {
        //warning C4800: 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
        ret = (func->wglMakeContextCurrentARB( draw, read, context ) != 0);
        }
    if( !ret )
        {
        // \todo Handle error
        err = GetLastError();
        // Restore previous context/surface on failure
        func->wglMakeContextCurrentARB( prevDraw, prevRead, prevContext );        
        }
#endif
    return ret;
    }

bool CEGLOs::DestroyNativeContext( EGLINativeContextType context )
    {
    bool ret = true;
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    if( context != NULL )
        {
        //warning C4800: 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
        ret = (wglDeleteContext( context ) != 0);
        }
#endif
    return ret;
    }

bool CEGLOs::InitializeNativeGLFunctions( struct EGLINativeGLFunctions* func, EGLINativeDisplayType display, EGLINativeContextType context )
    {
    bool ret = true;
    DWORD error = ERROR_SUCCESS;
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    HDC currentDC = wglGetCurrentDC();
    HGLRC currentContext = wglGetCurrentContext();
    
	ret = !!wglMakeCurrent( display, context );
    if( ret )
        {
        func->wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC)wglGetProcAddress( "wglMakeContextCurrentARB" );
        func->wglGetCurrentReadDCARB = (PFNWGLGETCURRENTREADDCARBPROC)wglGetProcAddress ( "wglGetCurrentReadDCARB" );
        func->wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress( "wglChoosePixelFormatARB" );
        func->wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress( "wglCreatePbufferARB" );
        func->wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)wglGetProcAddress( "wglDestroyPbufferARB" );
        func->wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress( "wglGetPbufferDCARB" );
        func->wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress( "wglReleasePbufferDCARB" );
        func->wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC)wglGetProcAddress( "wglQueryPbufferARB" );

        if( !(func->wglChoosePixelFormatARB &&
              func->wglCreatePbufferARB &&
              func->wglDestroyPbufferARB &&
              func->wglGetPbufferDCARB &&
              func->wglMakeContextCurrentARB &&
              func->wglGetCurrentReadDCARB &&
              func->wglQueryPbufferARB &&
              func->wglReleasePbufferDCARB) )
              ret = false;
        }

    // \todo Other needed extensions.

    if( !(wglMakeCurrent( currentDC, currentContext )) )
        {
        error = GetLastError();
        if( error == ERROR_INVALID_HANDLE )
            {
            // For some reason the current DC or current wgl context was invalid.
            // Just set them NULL for now.
            wglMakeCurrent(NULL, NULL);
            }
        else
            {
            ret = false;
            }
        }
#endif //EGLI_USE_PLATSIM_EXTENSIONS
    return ret;
    }

struct EGLINativePbufferContainer* CEGLOs::CreateNativePbuffer( EGLINativeDisplayType display,
        const CEGLConfig& config, EGLint width, EGLint height, EGLBoolean largestPbuffer, 
        EGLint textureFormat, EGLint textureTarget )
    {
    struct EGLINativePbufferContainer* ret = EGLI_NEW EGLINativePbufferContainer;
    if( !ret ) return NULL;
    memset( ret, 0, sizeof(struct EGLINativePbufferContainer) );
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    EGLINativeContextType context = CEGLOs::CreateNativeContext( config, display, NULL );
    if( !context )
        {
        delete ret;
        ret = NULL;
        return ret;
        }
    ret->copyContext = context;
    if( !(CEGLOs::InitializeNativeGLFunctions( &(ret->functions), display, ret->copyContext )) )
        {
        CEGLOs::DestroyNativePbuffer( ret );
        delete ret;
        ret = NULL;
        return ret;
        }
    
    int redSize = config.GetAttribute( EGL_RED_SIZE );
    int greenSize = config.GetAttribute( EGL_GREEN_SIZE );
    int blueSize = config.GetAttribute( EGL_BLUE_SIZE );
    int alphaSize = config.GetAttribute( EGL_ALPHA_SIZE );
    int depthSize = config.GetAttribute( EGL_DEPTH_SIZE );
    int stencilSize = config.GetAttribute( EGL_STENCIL_SIZE );
    
    // \todo Map EGL config properly to WGL config.
    int attributes[] =
        {
        WGL_SUPPORT_OPENGL_ARB, TRUE,
        WGL_DRAW_TO_PBUFFER_ARB, TRUE,
        WGL_RED_BITS_ARB, redSize,
        WGL_GREEN_BITS_ARB, greenSize,
        WGL_BLUE_BITS_ARB, blueSize,
        WGL_ALPHA_BITS_ARB, alphaSize,
        WGL_DEPTH_BITS_ARB, depthSize,
        WGL_STENCIL_BITS_ARB, stencilSize,
        WGL_DOUBLE_BUFFER_ARB, TRUE,
        0
        };
    unsigned int formatCount = 0;
    int pixelFormat = 0;
    if( !(ret->functions.wglChoosePixelFormatARB( display, attributes, NULL, 1, &pixelFormat, &formatCount )) )
        {
        EGLI_ASSERT(false);
        DWORD err = GetLastError();
        CEGLOs::DestroyNativePbuffer( ret );
        delete ret;
        ret = NULL;
        return ret;
        }
    if( formatCount == 0 )
        {
        EGLI_ASSERT(false);
        DWORD err = GetLastError();
        CEGLOs::DestroyNativePbuffer( ret );
        delete ret;
        ret = NULL;
        return ret;
        }
    int wglTextureFormat = WGL_NO_TEXTURE_ARB;
    switch( textureFormat )
        {
        case EGL_TEXTURE_RGB:
            {
            wglTextureFormat = WGL_TEXTURE_RGB_ARB;
            break;
            }
        case EGL_TEXTURE_RGBA:
            {
            wglTextureFormat = WGL_TEXTURE_RGBA_ARB;
            break;
            }
        }
    int wglTextureTarget = WGL_NO_TEXTURE_ARB;
    switch( textureTarget )
        {
        case EGL_TEXTURE_2D:
            {
            wglTextureTarget = WGL_TEXTURE_2D_ARB;
            break;
            }      
        }
    int pbufferAttributes[] =
        {
        WGL_TEXTURE_FORMAT_ARB, wglTextureFormat,
        WGL_TEXTURE_TARGET_ARB, wglTextureTarget,
        WGL_PBUFFER_LARGEST_ARB, largestPbuffer,
        0
        };
    ret->pbuffer = ret->functions.wglCreatePbufferARB( display, pixelFormat,
        width, height, pbufferAttributes );
    if( !(ret->pbuffer) )
        {
        EGLI_ASSERT(false);
        DWORD err = GetLastError();
        CEGLOs::DestroyNativePbuffer( ret );
        delete ret;
        ret = NULL;
        return ret;
        }
    ret->display = ret->functions.wglGetPbufferDCARB( ret->pbuffer );
    if( !(ret->display) )
        {
        EGLI_ASSERT(false);
        DWORD err = GetLastError();
        CEGLOs::DestroyNativePbuffer( ret );
        delete ret;
        ret = NULL;
        return ret;
        }
#endif // EGLI_USE_PLATSIM_EXTENSIONS
    return ret;
    }

bool CEGLOs::DestroyNativePbuffer( struct EGLINativePbufferContainer* container )
    {
    // \todo Handle errors!
    bool ret = true;
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    DWORD err;
    if( container->display && container->pbuffer && container->functions.wglReleasePbufferDCARB )
        {
        if( !(container->functions.wglReleasePbufferDCARB(container->pbuffer, container->display)) )
            {
            err = GetLastError();
            ret = false;
            }
        }
    if( container->pbuffer && container->functions.wglDestroyPbufferARB )
        {
        if( !(container->functions.wglDestroyPbufferARB(container->pbuffer)) )
            {
            err = GetLastError();
            ret = false;
            }
        }
    if( container->copyContext )
        {
        ret = CEGLOs::DestroyNativeContext( container->copyContext );
        if( !ret )
            {
            err = GetLastError();
            }
        }
#endif //EGLI_USE_PLATSIM_EXTENSIONS
    return ret;
    }

EGLINativeDisplayType CEGLOs::CreateDefaultDisplay()
    {
    // \todo It seems that we can't use any of these DC-functions.
    //       Problems with pixel format selection etc. at least with
    //       NVidia and Intel GPUs, ATI/AMD seems to work with GetDC(NULL)
    //       or CreateDC(). No idea how to create EGL_DEFAULT_DISPLAY for
    //       NV/Intel GPUs. For now CEGLDisplay::Initialize() creates dummy
    //       window and uses DC from that window.
    //return (EGLINativeDisplayType)CreateDC(TEXT("DISPLAY"), TEXT("DISPLAY")/*NULL*/, NULL, NULL);
    //return (EGLINativeDisplayType)GetDC(NULL);
    //return GetWindowDC(NULL);
    return NULL;
    }

void CEGLOs::DestroyDefaultDisplay( EGLINativeDisplayType display )
    {
#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
    // no-op
#else
    DeleteDC( display );
#endif
    }

EGLINativeWindowType CEGLOs::CreateNativeWindow( int width, int height )
    {
    int xBorder = GetSystemMetrics( SM_CXBORDER );
    int yBorder = GetSystemMetrics( SM_CYBORDER );
    int caption = GetSystemMetrics( SM_CYCAPTION );
    

    WNDCLASS wndclass;
    wndclass.style		   = 0;
    wndclass.lpfnWndProc   = WndProc;
    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = 0;
    wndclass.hInstance	   = (HINSTANCE)GetModuleHandle(NULL);
    wndclass.hIcon		   = LoadIcon(wndclass.hInstance, MAKEINTRESOURCE(101));
    wndclass.hCursor	   = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = NULL;
    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = "EGLMainWndClass";
    if (!wndclass.hIcon)
        wndclass.hIcon = LoadIcon(NULL, IDI_EXCLAMATION);
    
    // \todo We should store this class somewhere
    RegisterClass(&wndclass);

    EGLINativeWindowType window = CreateWindow(
        "EGLMainWndClass",
        "Platsim EGL window",
        WS_OVERLAPPEDWINDOW,
        0, 0,
        width /*+ 2*xBorder*/,
        height /*+ 2*yBorder + caption*/,
        NULL,
        NULL,
        (HINSTANCE)GetModuleHandle(NULL),
        NULL);
    return window;
    }

void CEGLOs::DestroyNativeWindow( EGLINativeWindowType wnd )
    {
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    if( wnd )
        EGLI_ASSERT( DestroyWindow( wnd ) );
    // \todo Should use stored WNDCLASS to unregister, see CEGLOs::CreateNativeWindow()
    UnregisterClass( "EGLMainWndClass", (HINSTANCE)GetModuleHandle(NULL) );
#endif
    }

bool CEGLOs::IsValidNativeDisplay( EGLINativeDisplayType dsp )
    {
#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
    // we can't validate symbian display
    return true;
#else
    // Check if we have invalid handle or handle is not display
    bool ret = true;
    DWORD err = GetLastError();
    SetLastError( ERROR_SUCCESS );
    int technology = GetDeviceCaps( dsp, TECHNOLOGY );
    if( GetLastError() == ERROR_INVALID_HANDLE || technology != DT_RASDISPLAY )
        {
        ret = false;
        }
    SetLastError( err );
    return ret;
#endif
    }

bool CEGLOs::IsValidNativeWindow( EGLINativeWindowType wnd )
    {
#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
    // We can't validate symbian window
    return true;
#else
    bool ret = false;
    if( wnd )
        {
        // \todo should we skip thread id check?
        DWORD processId = GetCurrentProcessId();
        DWORD threadId = GetCurrentThreadId();
        DWORD windowProcessId;
        DWORD windowThreadId = GetWindowThreadProcessId( wnd, &windowProcessId );
        ret = ((threadId == windowThreadId) && (processId == windowProcessId));
        }
    return ret;
#endif //EGLI_USE_PLATSIM_EXTENSIONS
    }

bool CEGLOs::GetNativeWindowSize( EGLINativeWindowType wnd, int& width, int& height )
    {
#if defined( EGLI_USE_PLATSIM_EXTENSIONS )
    // Window size is transferred through eglPlatsimSetSurfaceParameters()
    return true;

#else
    bool ret = false;
    RECT rect;
    ret = !!GetClientRect( wnd, &rect );
    if( ret )
        {
        width = rect.right - rect.left;
        height = rect.bottom - rect.top;
        }
    return ret;
#endif
    }

EGLIOsWindowContext* CEGLOs::CreateOSWindowContext( EGLINativeWindowType wnd, const CEGLConfig& config )
    {
    EGLIOsWindowContext* ctx = NULL;
    ctx = EGLI_NEW EGLIOsWindowContext;
    if( !ctx )
        {
        return NULL;
        }
    ctx->window = wnd;
    ctx->vgDisplay = NULL;
    ctx->glesDisplay = NULL;
    ctx->pixmap = NULL;
    ctx->osBuffer = NULL;
    ctx->width = 0;
    ctx->height = 0;
    ctx->colorBuf = NULL;
#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
    // no-op
#else
    if( ctx->window )
        {
        EGLint renderableType = config.GetAttribute( EGL_RENDERABLE_TYPE );
        if( renderableType & EGL_OPENVG_BIT )
            {
            HDC winDC = GetDC(ctx->window);
            ctx->vgDisplay = CreateCompatibleDC(winDC);
            ReleaseDC(ctx->window, winDC);
            if(!ctx->vgDisplay)
                {
                delete ctx;
                return NULL;
                }
            }
        if( renderableType & EGL_OPENGL_ES_BIT )
            {
            HDC winDC = GetDC(ctx->window);
            ctx->glesDisplay = winDC;
            if(!ctx->glesDisplay)
                {
                delete ctx;
                return NULL;
                }
            PIXELFORMATDESCRIPTOR pfd;
            CEGLOs::ConfigToNativePixelFormat( config, &pfd );

	        int pixelFormat = ChoosePixelFormat( ctx->glesDisplay, &pfd );
	        if( !pixelFormat )
		        {
                EGLI_ASSERT( false );
		        }
	        if( !SetPixelFormat(ctx->glesDisplay, pixelFormat, &pfd ) )
		        {
		        EGLI_ASSERT( false );
		        }
            }
        }
#endif
    return ctx;
    }

void CEGLOs::DestroyOSWindowContext( EGLIOsWindowContext* context )
    {
#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
    if(!context->vgDisplay)
        {
        SelectObject(context->vgDisplay, NULL);
        DeleteDC(context->vgDisplay);
        }
    if( context->glesDisplay )
        {
        ReleaseDC( context->window, context->glesDisplay );
        }
    if( context->pixmap )
        DeleteObject( context->pixmap );
    if( context->colorBuf )
        free( context->colorBuf );
    delete context;
#else
    delete context;
#endif
    }

void CEGLOs::BlitToOSWindow( EGLenum api, CEGLDisplay* display, EGLIOsWindowContext* context, void* buf, int width, int height, int stride )
    {
#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
    // \todo GLES
    CEGLState* state = getState();
    if( !state )
        return;
    CEGLThread* thread = state->GetCurrentProcess()->CurrentThread();
    switch( api )
        {
        case EGL_OPENVG_API:
            {
            if( thread && state->VGInterface() )
                {                
                if( thread->CurrentVGSurface() )
                    {
                    CEGLSurface* surface = thread->CurrentVGSurface();
                    EGLI_ASSERT( surface->Type() == CEGLSurface::WINDOW_SURFACE );
                    state->VGInterface()->CopyBuffers( buf, -stride, surface->VGClientSurface() );
                    }
                }
            break;
            }
        case EGL_OPENGL_ES_API:
            {
                if (state->GLESInterface(thread->CurrentGLESContext()->ClientVersion()))
                {
                // \todo
                }
            break;
            }
        }
#else
    if( api == EGL_OPENGL_ES_API )
        {
        SwapBuffers( context->glesDisplay );
        }
    else
        {
        doBlit(context, buf, width, height, stride);
        }
#endif
    }

EGLILibraryHandle CEGLOs::LoadHostGL()
    {
    return LoadLibrary( TEXT("opengl32.dll") );
    }

void* CEGLOs::GetGLProcAddress(EGLILibraryHandle& libraryHandle, const char* proc)
    {
    void* addr = GetProcAddress(libraryHandle, proc);
	if(!addr)
		{
		addr = wglGetProcAddress(proc);
		}

	return addr;
    }

bool CEGLOs::FreeClientLibrary(EGLILibraryHandle& libraryHandle)
    {
    // != 0 added to expression below because of
    // warning C4800: 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
    return (FreeLibrary( libraryHandle ) != 0);
    }

IEGLtoVGInterface* CEGLOs::LoadVGInterface( EGLILibraryHandle& libraryHandle )
    {
    IEGLtoVGInterface* iFace = NULL;
    fpGetVGInterface proc;
    libraryHandle = LoadLibrary( TEXT("libOpenVG.dll") );
    if( libraryHandle != NULL )
        {
        proc = (fpGetVGInterface)GetProcAddress( libraryHandle, "getVGInterface" );
        if( proc != NULL )
            {
            iFace = proc();
            }
        }
    return iFace;
    }

IEGLtoGLESInterface* CEGLOs::LoadGLES1Interface( EGLILibraryHandle& libraryHandle )
    {
    IEGLtoGLESInterface* iFace = NULL;
    fpGetGLES1Interface proc;
    libraryHandle = LoadLibrary( TEXT("libGLESv1.dll") );
    if( libraryHandle != NULL )
        {
        proc = (fpGetGLES1Interface)GetProcAddress( libraryHandle, "getGLESInterface" );
        if( proc != NULL )
            {
            iFace = proc();
            }
        }
    return iFace;
    }

IEGLtoGLES2Interface* CEGLOs::LoadGLES2Interface( EGLILibraryHandle& libraryHandle )
    {
    IEGLtoGLES2Interface* iFace = NULL;
    fpGetGLES2Interface proc;
    libraryHandle = LoadLibrary( TEXT("libGLESv2.dll") );
    if( libraryHandle != NULL )
        {
        proc = (fpGetGLES2Interface)GetProcAddress( libraryHandle, "getGLES2Interface" );
        if( proc != NULL )
            {
            iFace = proc();
            }
        }
    return iFace;
    }