--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hostsupport/hostegl/src/win32/EGLOs.cpp Wed Oct 06 17:59:01 2010 +0100
@@ -0,0 +1,807 @@
+/* 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;
+ }