hostsupport/hostopenvg/src/src/win32/riEGLOS.cpp
branchbug235_bringup_0
changeset 53 c2ef9095503a
parent 24 a3f46bb01be2
equal deleted inserted replaced
52:39e5f73667ba 53:c2ef9095503a
       
     1 /*------------------------------------------------------------------------
       
     2  *
       
     3  * EGL 1.3
       
     4  * -------
       
     5  *
       
     6  * Copyright (c) 2007 The Khronos Group Inc.
       
     7  * Portions copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     8  *
       
     9  * Permission is hereby granted, free of charge, to any person obtaining a
       
    10  * copy of this software and /or associated documentation files
       
    11  * (the "Materials "), to deal in the Materials without restriction,
       
    12  * including without limitation the rights to use, copy, modify, merge,
       
    13  * publish, distribute, sublicense, and/or sell copies of the Materials,
       
    14  * and to permit persons to whom the Materials are furnished to do so,
       
    15  * subject to the following conditions: 
       
    16  *
       
    17  * The above copyright notice and this permission notice shall be included 
       
    18  * in all copies or substantial portions of the Materials. 
       
    19  *
       
    20  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       
    21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       
    22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
       
    23  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
       
    24  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
       
    25  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
       
    26  * THE USE OR OTHER DEALINGS IN THE MATERIALS.
       
    27  *
       
    28  *//**
       
    29  * \file
       
    30  * \brief	Simple implementation of EGL 1.3
       
    31  * \note	caveats:
       
    32 			- always renders into the backbuffer and blits it to window (no single buffered rendering)
       
    33 			- no native Windows or Mac OS X pixmap support
       
    34 			- no power management events
       
    35 			- no support for swap interval
       
    36  * \todo	what happens in egl functions when eglTerminate has been called but the context and surface are still in use?
       
    37  * \todo	OSDeinitMutex should be called in case getEGL fails.
       
    38  * \todo	clarify getThread and getCurrentThread distinction.
       
    39  *//*-------------------------------------------------------------------*/
       
    40 
       
    41 #include "EGL/egl.h"
       
    42 #include "openvg.h"
       
    43 #include "riArray.h"
       
    44 #include "riMath.h"
       
    45 #include "riContext.h"
       
    46 #include "riImage.h"
       
    47 
       
    48 namespace OpenVGRI
       
    49 {
       
    50 
       
    51 #include <windows.h>
       
    52 
       
    53 void* OSGetCurrentThreadID(void)
       
    54 {
       
    55 	return (void*)GetCurrentThreadId();	//TODO this is not safe
       
    56 }
       
    57 
       
    58 static HANDLE mutex = NULL;
       
    59 static int mutexRefCount = 0;
       
    60 //acquired mutex cannot be deinited.
       
    61 void OSDeinitMutex(void)
       
    62 {
       
    63 	RI_ASSERT(mutex);
       
    64 	RI_ASSERT(mutexRefCount == 0);
       
    65 	BOOL ret = CloseHandle(mutex);
       
    66 	RI_ASSERT(ret);
       
    67 	RI_UNREF(ret);
       
    68 }
       
    69 void OSAcquireMutex(void)
       
    70 {
       
    71 	if(!mutex)
       
    72     {
       
    73         mutex = CreateMutex(NULL, FALSE, NULL);	//initially not locked
       
    74         mutexRefCount = 0;
       
    75     }
       
    76 	RI_ASSERT(mutex);
       
    77 	DWORD ret = WaitForSingleObject(mutex, INFINITE);
       
    78 	RI_ASSERT(ret != WAIT_FAILED);
       
    79 	RI_UNREF(ret);
       
    80 	mutexRefCount++;
       
    81 }
       
    82 void OSReleaseMutex(void)
       
    83 {
       
    84 	RI_ASSERT(mutex);
       
    85 	mutexRefCount--;
       
    86 	RI_ASSERT(mutexRefCount >= 0);
       
    87 	BOOL ret = ReleaseMutex(mutex);
       
    88 	RI_ASSERT(ret);
       
    89 	RI_UNREF(ret);
       
    90 }
       
    91 
       
    92 static bool isBigEndian()
       
    93 {
       
    94 	static const RIuint32 v = 0x12345678u;
       
    95 	const RIuint8* p = (const RIuint8*)&v;
       
    96 	RI_ASSERT (*p == (RIuint8)0x12u || *p == (RIuint8)0x78u);
       
    97 	return (*p == (RIuint8)(0x12)) ? true : false;
       
    98 }
       
    99 
       
   100 
       
   101 #ifdef RI_USE_GLUT
       
   102 #	include <GL/gl.h>
       
   103 #	define GLUT_DISABLE_ATEXIT_HACK
       
   104 #	include "glut.h"
       
   105 
       
   106 struct OSWindowContext
       
   107 {
       
   108     int                 window;
       
   109     unsigned int*       tmp;
       
   110     int                 tmpWidth;
       
   111     int                 tmpHeight;
       
   112 };
       
   113 
       
   114 void* OSCreateWindowContext(EGLNativeWindowType window)
       
   115 {
       
   116     try
       
   117     {
       
   118         OSWindowContext* ctx = RI_NEW(OSWindowContext, ());
       
   119         ctx->window = (int)window;
       
   120         ctx->tmp = NULL;
       
   121         ctx->tmpWidth = 0;
       
   122         ctx->tmpHeight = 0;
       
   123         return ctx;
       
   124     }
       
   125 	catch(std::bad_alloc)
       
   126 	{
       
   127 		return NULL;
       
   128 	}
       
   129 }
       
   130 
       
   131 void OSDestroyWindowContext(void* context)
       
   132 {
       
   133     OSWindowContext* ctx = (OSWindowContext*)context;
       
   134     if(ctx)
       
   135     {
       
   136         RI_DELETE_ARRAY(ctx->tmp);
       
   137         RI_DELETE(ctx);
       
   138     }
       
   139 }
       
   140 
       
   141 bool OSIsWindow(const void* context)
       
   142 {
       
   143     OSWindowContext* ctx = (OSWindowContext*)context;
       
   144     if(ctx)
       
   145     {
       
   146 		//TODO implement
       
   147         return true;
       
   148     }
       
   149     return false;
       
   150 }
       
   151 
       
   152 void OSGetWindowSize(const void* context, int& width, int& height)
       
   153 {
       
   154     OSWindowContext* ctx = (OSWindowContext*)context;
       
   155     if(ctx)
       
   156     {
       
   157         int currWin = glutGetWindow();
       
   158         glutSetWindow(ctx->window);
       
   159         width = glutGet(GLUT_WINDOW_WIDTH);
       
   160         height = glutGet(GLUT_WINDOW_HEIGHT);
       
   161         glutSetWindow(currWin);
       
   162     }
       
   163     else
       
   164     {
       
   165         width = 0;
       
   166         height = 0;
       
   167     }
       
   168 }
       
   169 
       
   170 void OSBlitToWindow(void* context, const Drawable* drawable)
       
   171 {
       
   172     OSWindowContext* ctx = (OSWindowContext*)context;
       
   173     if(ctx)
       
   174     {
       
   175         int w = drawable->getWidth();
       
   176         int h = drawable->getHeight();
       
   177 
       
   178         int currWin = glutGetWindow();
       
   179         glutSetWindow(ctx->window);
       
   180 
       
   181         if(!ctx->tmp || ctx->tmpWidth != w || ctx->tmpHeight != h)
       
   182         {
       
   183             RI_DELETE_ARRAY(ctx->tmp);
       
   184             ctx->tmp = NULL;
       
   185             try
       
   186             {
       
   187                 ctx->tmp = RI_NEW_ARRAY(unsigned int, w*h);	//throws bad_alloc
       
   188                 ctx->tmpWidth = w;
       
   189                 ctx->tmpHeight = h;
       
   190             }
       
   191             catch(std::bad_alloc)
       
   192             {
       
   193                 //do nothing
       
   194             }
       
   195         }
       
   196 
       
   197         if(ctx->tmp)
       
   198         {
       
   199             glViewport(0, 0, w, h);
       
   200             glDisable(GL_DEPTH_TEST);
       
   201             glMatrixMode(GL_PROJECTION);
       
   202             glLoadIdentity();
       
   203             glMatrixMode(GL_MODELVIEW);
       
   204             glLoadIdentity();
       
   205             //NOTE: we assume here that the display is always in sRGB color space
       
   206             VGImageFormat f = VG_sXBGR_8888;
       
   207             if(isBigEndian())
       
   208                 f = VG_sRGBX_8888;
       
   209             vgReadPixels(ctx->tmp, w*sizeof(unsigned int), f, 0, 0, w, h);
       
   210             glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, ctx->tmp);
       
   211         }
       
   212 
       
   213         glutSwapBuffers();	//shows the OpenGL frame buffer
       
   214         glutSetWindow(currWin);		//restore the current window
       
   215     }
       
   216 }
       
   217 
       
   218 EGLDisplay OSGetDisplay(EGLNativeDisplayType display_id)
       
   219 {
       
   220     return (EGLDisplay)display_id;  //just casting to (EGLDisplay) should be enough to make a unique identifier out of this
       
   221 }
       
   222 
       
   223 #else
       
   224 //Windows native
       
   225 #ifndef _WINDOWS_
       
   226 #	define _WIN32_WINNT 0x0400
       
   227 #	define WIN32_LEAN_AND_MEAN
       
   228 #	include <windows.h>
       
   229 #endif
       
   230 
       
   231 struct OSWindowContext
       
   232 {
       
   233     HWND                window;
       
   234 	HDC					bufDC;
       
   235 	HBITMAP				bufDIB;
       
   236     unsigned int*       tmp;
       
   237     int                 tmpWidth;
       
   238     int                 tmpHeight;
       
   239 };
       
   240 
       
   241 OSWindowContext* OSCreateWindowContext(EGLNativeWindowType window)
       
   242 {
       
   243     OSWindowContext* ctx = NULL;
       
   244     try
       
   245     {
       
   246         ctx = RI_NEW(OSWindowContext, ());
       
   247     }
       
   248 	catch(std::bad_alloc)
       
   249 	{
       
   250 		return NULL;
       
   251 	}
       
   252 
       
   253     ctx->window = (HWND)window;
       
   254     HDC winDC = GetDC(ctx->window);
       
   255     ctx->bufDC = CreateCompatibleDC(winDC);
       
   256     ReleaseDC(ctx->window, winDC);
       
   257     if(!ctx->bufDC)
       
   258     {
       
   259         RI_DELETE(ctx);
       
   260         return NULL;
       
   261     }
       
   262 
       
   263     ctx->bufDIB = NULL;
       
   264     ctx->tmp = NULL;
       
   265     ctx->tmpWidth = 0;
       
   266     ctx->tmpHeight = 0;
       
   267     return ctx;
       
   268 }
       
   269 
       
   270 void OSDestroyWindowContext(OSWindowContext* context)
       
   271 {
       
   272     OSWindowContext* ctx = (OSWindowContext*)context;
       
   273     if(ctx)
       
   274     {
       
   275         if(ctx->bufDC)
       
   276         {
       
   277             SelectObject(ctx->bufDC, NULL);
       
   278             DeleteDC(ctx->bufDC);
       
   279         }
       
   280         if(ctx->bufDIB)
       
   281             DeleteObject(ctx->bufDIB);
       
   282         RI_DELETE(ctx);
       
   283     }
       
   284 }
       
   285 
       
   286 bool OSIsWindow(const OSWindowContext* context)
       
   287 {
       
   288     OSWindowContext* ctx = (OSWindowContext*)context;
       
   289     if(ctx)
       
   290     {
       
   291 		if(IsWindow(ctx->window))
       
   292 			return true;
       
   293     }
       
   294     return false;
       
   295 }
       
   296 
       
   297 void OSGetWindowSize(const OSWindowContext* context, int& width, int& height)
       
   298 {
       
   299     OSWindowContext* ctx = (OSWindowContext*)context;
       
   300     if(ctx)
       
   301     {
       
   302 		RECT rect;
       
   303 		GetClientRect(ctx->window, &rect);
       
   304 		width = rect.right - rect.left;
       
   305 		height = rect.bottom - rect.top;
       
   306     }
       
   307     else
       
   308     {
       
   309         width = 0;
       
   310         height = 0;
       
   311     }
       
   312 }
       
   313 
       
   314 void OSBlitToWindow(OSWindowContext* context, const Drawable* drawable)
       
   315 {
       
   316     OSWindowContext* ctx = (OSWindowContext*)context;
       
   317     if(ctx)
       
   318     {
       
   319         int w = drawable->getWidth();
       
   320         int h = drawable->getHeight();
       
   321 
       
   322         if(!ctx->tmp || !ctx->bufDIB || ctx->tmpWidth != w || ctx->tmpHeight != h)
       
   323         {
       
   324             if(ctx->bufDIB)
       
   325                 DeleteObject(ctx->bufDIB);
       
   326             ctx->tmp = NULL;
       
   327             ctx->bufDIB = NULL;
       
   328 
       
   329             ctx->tmpWidth = w;
       
   330             ctx->tmpHeight = h;
       
   331 
       
   332             struct
       
   333             {
       
   334                 BITMAPINFOHEADER	header;
       
   335                 DWORD				rMask;
       
   336                 DWORD				gMask;
       
   337                 DWORD				bMask;
       
   338             } bmi;
       
   339             bmi.header.biSize			= sizeof(BITMAPINFOHEADER);
       
   340             bmi.header.biWidth			= w;
       
   341             bmi.header.biHeight			= h;
       
   342             bmi.header.biPlanes			= 1;
       
   343             bmi.header.biBitCount		= (WORD)32;
       
   344             bmi.header.biCompression	= BI_BITFIELDS;
       
   345             bmi.rMask = 0x000000ff;
       
   346             bmi.gMask = 0x0000ff00;
       
   347             bmi.bMask = 0x00ff0000;
       
   348             ctx->bufDIB = CreateDIBSection(ctx->bufDC, (BITMAPINFO*)&bmi, DIB_RGB_COLORS, (void**)&ctx->tmp, NULL, 0);
       
   349             if(!ctx->bufDIB)
       
   350             {
       
   351                 ctx->tmp = NULL;
       
   352                 return;
       
   353             }
       
   354         }
       
   355 
       
   356         if(ctx->tmp)
       
   357         {
       
   358             //NOTE: we assume here that the display is always in sRGB color space
       
   359 			GdiFlush();
       
   360             VGImageFormat f = VG_sABGR_8888_PRE;
       
   361             if(isBigEndian())
       
   362                 f = VG_sRGBA_8888_PRE;
       
   363             vgReadPixels(ctx->tmp, w*sizeof(unsigned int), f, 0, 0, w, h);
       
   364 
       
   365             SelectObject(ctx->bufDC, ctx->bufDIB);
       
   366             HDC winDC = GetDC(ctx->window);
       
   367             BitBlt(winDC, 0, 0, w, h, ctx->bufDC, 0, 0, SRCCOPY);
       
   368             ReleaseDC(ctx->window, winDC);
       
   369             SelectObject(ctx->bufDC, NULL);
       
   370         }
       
   371     }
       
   372 }
       
   373 
       
   374 EGLDisplay OSGetDisplay(EGLNativeDisplayType display_id)
       
   375 {
       
   376     RI_UNREF(display_id);
       
   377     return (EGLDisplay)1;    //support only a single display
       
   378 }
       
   379 
       
   380 #endif
       
   381 
       
   382 }   //namespace OpenVGRI