.NET Compact Framework wrapper for OpenGL ES

OpenGL Test

Around a year ago today, I began writing an extensive UI framework for Windows Mobile. It turned out great, however I continually run into the limitations and performance issues of GDI/GDI+ on mobile devices. One of the steps I wanted to take into really improving performance was to utilize the hardware acceleration that we will begin to see in the new wave of Windows Mobile devices; in my case the HTC Touch Diamond.

The first step towards that end is to utilize one of the two 3D APIs available on the Windows Mobile platform. Direct3D Mobile .NET was not a reasonable option: it has limited support and is supposedly being phased out in Windows Mobile 7. In addition, the D3DM implementation on the HTC Touch Diamond is a just a wrapper around OpenGL ES... I find it a little distasteful that than an operating system specific 3D API is actually just a wrapper around a cross platform 3D API, hehe. And on the other hand, OpenGL ES does not have a managed API.

In My Humble Opinion, UI development should generally be in managed code. Although unmanaged code undoubtedly provides superior performance, the developer sacrifices too much of the ease and speed of managed development.

For that reason, I've started work on a managed wrapper for OpenGL ES: I now have a working set of wrappers for OpenGL ES. I won't take all the credit though. Most of the PInvokes were mass imported via the PInvoke Interop Assistant written by Jared Parsons.

The screen shot above is of the sample "Hello World" application written in Managed OpenGL ES. The code download includes the full source for the wrapper and the sample.

For those wanting to learn OpenGL, I highly recommend reading the NeHe OpenGL series. It's the best OpenGL tutorial on the Internet; I've practically had it book marked for 8 years.

Future work will include converting the various OpenGL constants into enums (I.e., GL_TRIANGLES, GL_TEXTURE0, etc) so that arguments are not so loosely typed.

Notes:

  • The sample uses floating point math, so not all devices may support it.
  • If your device does not have an implementation of OpenGL ES (hardware or software), you can get the free software implementation, Vincent 3D. Just drop the libgles_cm.dll into your \Windows directory. Vincent 3D is a fixed point implementation, so it does not support the sample either. I will probably convert the sample to fixed point eventually.

55 comments:

Joel said...

Are you sure that Direct3D is being phased out in Windows Mobile 7? Windows CE 6 (which is the foundation for Windows Mobile 7) expands the capabilities of Direct3D. It is the GAPI that is being deprecated (GAPI predates Direct3D). I've not been able to find anything from Microsoft that states or suggest that Direct3D Mobile is going anywhere.

Koush said...

Nah, I'm not sure. Just rumors and comments I've heard from people on the Windows Mobile team.

Anonymous said...

hi,

can you help me out, I have a goforce5500 gpu in y windows mobile device, andI I really need to know how to get the dell axim games to work, I think the problem is this:

setting the orientation under GDI, then using the GDI hdc in a call to eglGetDisplay to initialize and connect the GLES module to the GDI display surface

The init of the gles module is done in a different somehow make this comptible with goforce so that the opengles games from x51v can be played on any HW supported windows mobile device?

Koush said...

I just double checked. Direct3D Mobile and GAPI are both removed from Windows Mobile 7.

Le Sage said...

"I just double checked. Direct3D Mobile and GAPI are both removed from Windows Mobile 7."
O_O So what would they be replaced with ?

Matthijs said...

I've just made a rotating piramid with your wrapper, it is fun!
I wrote a game in OpenGL before so I like the wrapper :) Only missed the glBegin() and glEnd() though, and the option for drawing cubes and circles :)
Keep up the goog work!

Koush said...

le sage:
WM 7 will feature hardware accelerated support of OpenGL ES 1.2 and obviously GDI.

BenPa said...

Are you sure that Direct3D is just a wrapper fo OpenGL ES? Because Direct3D works on the WM6 professional emulator but using your wrapper I get an error that the .dll is missing ...

But all in all great work ;)

Koush said...

That's just an emulator, not an actual hardware accelerated device. It's a software rasterizer running on an emulator; it's not the real thing.

On actual hardware devices, such as the HTC Touch Diamond, Omnia, or Experia, Direct3D is just a wrapper around OpenGL.

Anonymous said...

I can't open the solution file with my Visual studio 2005 and got syntax error when compiling the cs project. Is the project can only be run with vs2008?

Tony J said...

Thanks for making this wrapper. This is exactly what I was looking for! Is there any way to get this working on the Windows Mobile 6 Professional Device Emulator so I can run in debug mode using Visual Studio .NET 2008? When trying to run in Debug or Release config I get the unhandled exception:

Can't find PInvoke dll 'libgles_cm.dll'

...on the line "IntPtr ptr = eglGetDisplay(display_id);"

I did a little research on this exception and it looks like the Windows Mobile device emulator can't handle/support these PInvokes. I've put the libgles_cm.dll in \Windows (as well as every other bin\Debug, bin\Release folder). Any ideas? Thanks!

Koush said...

Yes, deploy the libgles_cm.dll that is also in that project. (Set the build action to Copy Always)

Tony J said...

Thanks Koush! This worked. Didn't even think to check if the libGLES_CM.dll was set to get copied.

Does the simulation run extremely slowly in the device emulator for you, too? It runs under 4 FPS for me (on a Core 2 Duo, otherwise fast computer).

Is this just a limitation of the Windows Mobile Device Emulator? I know it's doing software OpenGL emulation, but 3.3 FPS is terrible! Too bad there isn't a way for it to use my computer's 3d graphics accelerator card.

Anonymous said...

It may not be an emulator issue. I ran the sample on HTC Touch Pro and it was very slow (4,3 FPS).

Anonymous said...

I have found the reason why my device struggled at 4.3 FPS. The attached libgles_cm.dll seems to be a software implementation. Removal of this supplied library will force the sample program to use the device-specific one which is an order of magnitude faster (> 60 FPS on HTC Touch Pro).

Koush said...

Correct, the libgles_cm.dll is a software implementation. Don't use it if there is hardware acceleration available.

SirPyros said...

Any change of getting a managed version of GLUT ES as well?

MMoi said...

Hi Koush,

first of all thanks a lot for your wrapper, it works pretty well and was a lot of help... as everything on this blog.

Still, I'm working on Samsung Omnia now, which doesn't include libGLES_cm.dll, so I did deploy it by myself but without hardware acceleration, it's obviously too slow.

Do you know if there are, by any chance, some openGL ES drivers around for Omnia ? Or maybe a way to use HTC drivers for Omnia to get similar performances (I saw some guys doing it with Omnia D3D drivers, to put them on HTC device) ?

Thanks again

Suchismita said...
This comment has been removed by the author.
Suchismita said...

Hi Koushik,
I am making an application in .Net CF for rendering shape files(.shp) in the mobile device.I am very new in OpenGl. Can you plz tell me, whether I can use this wrappers for 2D graphics?

If not can you plz tell me where can I get those to download?

Alex said...

Hi,

works great on the HTC Touch HD. Great work.

Anonymous said...

Hi Koush,
thanks for the wrapper! Just one problem (more a c# question): glGetString() returns an IntPtr. How to get the string out of it?

Koush said...

You can use Marshal.PtrtoStringUnicode should do the trick:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.ptrtostringuni.aspx

Anonymous said...

Thanks, I already tried that and received 慈獮䴭牡楴楗汬 where I thought there's something wrong with unicode.

Anonymous said...

Any idea what these "symbols" mean?

Chandler said...

I'm running into the Can't find PInvoke dll 'libgles_cm.dll' error even though I've set the Copy to Output Directory option for libGLES_CM.dll to Copy Always. Any thoughts?

Koush said...

I assume you are running the test code sample "TestOpenGLES" included with the library?

I would verify that the libGLES_CM.dll is ACTUALLY on the device, in the TestOpenGLES directory.

Chandler said...

Ah, OK, I didn't notice that there was more than one libGLES_CM.dll. I had set the one in the OpenGLES project to copy always without realizing that there was another in the TestOpenGLES project.

I guess I just jumped on the first one I saw =)

Marc said...

Hi,

Just tested on Xperia X1 and works ... great !!!
I ran about 45fps which is amazing, however, this is not a solutions for all the potential WM6 devices.

I'm also looking for something universal, only for a small sprite, nothing hard ...

Thanks for teh share Koush !
Regards from Belgium !
Marc

cjcollier said...

Heya Koush,

Under what license did you release this managed wrapper? I'd like to see a managed gl es wrapper in Mono. It would be pretty easy to include this if it were released under MIT/X11.

http://anonsvn.mono-project.com/viewvc/trunk/gtkglarea-sharp/x11_license?view=markup

Cheers,

C.J.

The Fiddler said...

Hi Koush,

I have added a slightly cleaned-up version of your bindings to OpenTK (support for 1.0, 1.1 and 2.0 profiles, proper enums and inline documentation). There's still some work left to do wrt to enum parameters, context construction and extension loading, but they should be usable already.

Source code (SVN): http://opentk.svn.sourceforge.net/svnroot/opentk/trunk under Source/OpenTK/Graphics/GLES[10|11|20]. The bindings should be compilable on their own.

Do you mind if I copy your work on EGL contexts?

PS: the bindings are autogenerated from the xml files in 'Source/Bind/Specifications/GLES[10|11|20]'. 'Overrides.xml' can be used to fix enum parameters. 'Bind.exe -mode:gles[10|11|20]' will regenerate the bindings (other options control the output namespace, wrapper generation process, etc.)

Could be useful for customized bindings that better your existing work (just don't look at the source of Bind.exe, if you want to keep your sanity! :) )

The Fiddler said...

Fixes to my above post:

1. Code is at: https://opentk.svn.sourceforge.net/svnroot/opentk/trunk

2. 'Could be useful for customized bindings that better your existing work' should read as 'Could be useful for customized bindings that better match your existing work' :D

Koush said...

Just took a look at the code, and that is very cool! Thanks Fiddler.

Go ahead and copy whatever you need!

Koush said...

Btw, the EGL stuff will only work on Windows Mobile (initialized via a HDC and HWND). Haven't figured out how to make it work with Android without having the framework create the window and the eglContext.

Anonymous said...

Hi Koush,

Thanks for the great OpenGL wrapper. It works really great.

Every now and then I get a funny bug though. Sometimes one or two textures that I load do not display. Instead the meshes they should be mapped to are entirely white.

The bug appears sort of randomly: sometimes all the textures load fine and the ones which fail are never the same.

I don't get an OutOfMemoryException or anything like that in my code and the Stream which I pass to the Stream always contains reasonable data.

Have you encountered something like this before? If so do you have any idea what the problem might be?

I think it is during the generation of the Texture because white objects stay white no matter how often I repaint the window.

Cheers and keep up the god work!

Anonymous said...

It's me again from the previous comment/question. I've managed to narrow down that the erroneous white textures only show up when I create textures with the isTransparent flag set to true. Again, not all the textures come out white, most are fine, and you can't predict which will be white and which will be okay, because it is always different. But when I load the textures with isTransparent set to false, they always seem to work.

It is a very strange bug. Cheers.

Anonymous said...

I compiled your example with Sharp Develop, and it works great on my HTC Fuze (~60fps). You are the man!

Haddes said...

Hi Koush,

Can you please guide me to correctly use your code? I'm not able to open your project...when i try opening OpenGL.sln, i get the following message:
"The solution appears to be under source control, but its binding information cannot be found. It is possible that the MSSCCPRJ.SCC file or another item that holds the source control settings for the solution, has been deleted.Because it is not possible to recover this missing information automatically, the projects, whose bindings are missing will be treated as not under source control."
After i click OK, VS2008 tells me the projects weren't loaded properly and there's nothing i can do from there.

Thanks.

Olivier said...

Hi Kouch

Seems to be great.

The demo also show a frame rate of 57 fps on my diamond II.
I'm new to open gl, and tried a demo of textured triangles, but they are white.
here is piece of code

gl.MatrixMode(gl.GL_PROJECTION);
gl.LoadIdentity();
gl.Orthof(0, ClientSize.Width, ClientSize.Height, 0, 0, 1);
gl.Disable(gl.GL_DEPTH_TEST);
gl.MatrixMode(gl.GL_MODELVIEW);
gl.LoadIdentity();
Texture myImage;
Bitmap Image = new Bitmap(@"\alain.jpg");
using (MemoryStream ms = new MemoryStream())
{
Image.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
myImage = Texture.LoadStream(ms, false);
}
float[] rectangle = new float[]
{ 0, 0, myImage.Width, 0, 0, myImage.Height, myImage.Width, myImage.Height };
float[] texturePosition = new float[]
{ 0, 0, myImage.Width, 0, 0, myImage.Height, myImage.Width, myImage.Height };
//Bind texture
gl.BindTexture(gl.GL_TEXTURE_2D, myImage.Name);
gl.TexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
gl.TexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
gl.EnableClientState(gl.GL_TEXTURE_COORD_ARRAY);
gl.EnableClientState(gl.GL_VERTEX_ARRAY);
//draw square and texture it.
fixed (float* rectanglePointer = &rectangle[0], positionPointer = &texturePosition[0])
{
gl.TexCoordPointer(2, gl.GL_FLOAT, 0, (IntPtr)positionPointer);
gl.VertexPointer(2, gl.GL_FLOAT, 0, (IntPtr)rectanglePointer);
gl.DrawArrays(gl.GL_TRIANGLE_STRIP, 0, 4);
}
gl.DisableClientState(gl.GL_TEXTURE_COORD_ARRAY);
gl.DisableClientState(gl.GL_VERTEX_ARRAY);


My square is completely white.

Can anyone help me ?

Regards,

Olivier

OMorando said...

Hi Koush,

Can you please guide me to correctly use your code? I'm not able to open your project... When i try opening OpenGL.sln, I get an error message of platform not supported.
I'm using VS2008 with Windonws Mobile 5 and 6 SDK installed.

After i click OK, VS2008 tells me the projects weren't loaded properly and there's nothing I can do from there.

Thanks.

Yann Droneaud said...

@olivier

You missed glEnable(GL_TEXTURE_2D);

Dax said...

Awesome work. I'm running an omap3530 eval board with b-square bsp, and this seems to work great for exactly six minutes and fifteen seconds after booting, then it hangs, no matter what I'm rendering, or even if I'm only calling gl.Clear(). Any ideas?

Aldo John said...

Sorry to bother you on this, Googled a lot but couldnt find. Does HTC Touch Elfin [P3452] (Enhanced version of the first HTC Touch) have hardware acceleration? When i ran the demo, it gave me 6-7 fps in software (with the dll) and without dll, it gave an error saying that file is missing... I am also into developing a UI framework[2d only]. Found this as great option... But stuck with this framerate.

Yann Droneaud said...

I'd like to thank you for publishing an OpenGL ES demo for Windows Mobile .NET

I've made some changes on it:
- full screen,
- gradient background,
- alpha blending,
- screen rotation support.

It was tested on HTC Touch HD and Toshiba TG01 using native OpenGL ES implementation.

When working on the demo, I've found something very strange: when not in full screen, alpha blending is not handled, thus, rendering is faster when the window has a title bar and a menu bar.

It can be downloaded from https://quoi.quest-ce.net/data/opengl/ManagedOpenGLES-opt.zip

Anonymous said...

Can your OpenGL wrapper use to make 3d carosel of SBp Shell works on Omnia i900 ?

Thanks

Dmitriy said...

Does this wrapper work under windows CE 5.0?

abc said...

Hi Koushik,

I have a problem in compiling the code in VS2005 i am getting the following error
"'OpenGLES.Animation<T>.Current.get' must declare a body because it is not marked abstract or extern"

Please help, Thanks in advance
Raghunath

nant15 said...

Hi, Koush!

I tried to also create a managed wrapper for opengles (libgles.dll) and trying your code - but I was stuck at

eglCreateContext

I always hit a native exception: ExceptionCode: 0xc0000005 - which i look up on net that it seems to be access violation. The weird thing is I have managed to run a simple program called "screentex" Do you have any suggestions?

Anonymous said...

Hi,

the code is great.

A problem though:
Running the demo multiple times, it crashes (for my HTD HD2 it always crashes at the 7th time).
It then needs a soft reset.

Seems to be at the glGenTexture call.

Any ideas?

VL said...

Hmmm, gives 25-30 fps on hd2 :(
Thanks for the tutorial :P

Anonymous said...

anyone has a hardware accelerated libGLES_CM.dll that works on htc touch2?

Or is there another dll that needs PInvoking now?

Barış İNANÇ said...

Hi thanks for great wrapper. Can you send an example for texture on 3D or 2D shapes. I am very newby on opengl so whatever I tried I got memory error or no Texture at all.

Thank you.

Baris

Anonymous said...

Great work! But as others, I've experienced stability issues with the HTC HD2 (as well as slowdown; after first run the FPS decreased from 60 to below 30). Adding the following line to the beginning of the OnClosing method, the issues were solved (the idea came from a Nokia doc):
egl.MakeCurrent(myDisplay, EGLSurface.None, EGLSurface.None, EGLContext.None);

Anonymous said...

Hi All,

I have a question about opengl ES with .NET CF. The question is ,after i swapbuffer() the texture2D to my mobile screen, how can get the framebuffer of testure2D ,and then combine with .NET CF Graphic ?
I use glReadPixel() Intpointer to my byte[] , that true?
Thank you.

Anonymous said...

Hi All,
I am post a question at last,
i want to ask if i use eglCopyBuffers() , how can i create NativePixmapType native_pixmap in my C# .NET CF?
Any sample code?
Thank you
Chen-Ming