Using the EGL Interface
The EGL API was designed to be a platform-independent way to interface OpenGL ES with the underlying window or display system. A single evening was all I needed to get an OpenGL ES buffer up and ready for rendering. Dave Astle and Dave Durnil's book OpenGL ES Game Development
(PTR, 2004) was invaluable, covering many aspects of OpenGL ES game development, and NVidia provided the headers and libraries:
#include <gl/egl.h> #include <gl/egltypes.h> #include <gl/gl.h>
for bringing in the EGL interface and OpenGL ES functions.
The EGL interface works much like desktop binding interfaces, in that you need handles to the display contexts, arrays of attribute flags for your buffer, and so on. Here are the variable declarations needed for these settings:
EGLDisplay hDisplay = NULL; EGLint attrs[3] = { EGL_DEPTH_SIZE, 16, EGL_NONE }; EGLint nConfigs; EGLConfig *pConfigs; EGLSurface hSurface; EGLContext hContext;
Listing One is the skeleton code for initialization when the window is created, and the cleanup code for when the window is destroyed. The SetupRC()
and ShutdownRC()
functions are my own for regular one-time OpenGL setup and cleanup, such as loading and freeing textures, and the like. Also included are the WM_PAINT
and WM_SIZE
message handlers. These handle the standard tasks of setting up the projection and rendering. The paint handler renders, does the buffer swap, and then invalidates the window, creating a looping behavior useful for animation on Windows' event-driven architecture. (The complete code for this project is available at http://www.ddj.com/code/.)
Listing One
case WM_CREATE: { hDisplay = eglGetDisplay(EGL_NO_DISPLAY); eglInitialize(hDisplay, NULL, NULL); eglChooseConfig( hDisplay, attrs, NULL, 0, &nConfigs); pConfigs = (EGLConfig *)malloc(nConfigs * sizeof(EGLConfig)); eglChooseConfig(hDisplay, attrs, pConfigs, nConfigs, &nConfigs); hSurface = e glCreateWindowSurface(hDisplay, *pConfigs, hWnd, NULL);hContext = eglCreateContext(hDisplay, *pConfigs, 0, 0); eglMakeCurrent (hDisplay, hSurface, hSurface, hContext); SetupRC(); } case WM_DESTROY: ShutdownRC(); eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(hDisplay, hContext); eglDestroySurface(hDisplay, hSurface); eglTerminate(hDisplay); free(pConfigs); PostQuitMessage(0); break; case WM_SIZE: { int iWidth = LOWORD(lParam); int iHeight = HIWORD(lParam); ChangeSize(iWidth, iHeight); } break; case WM_PAINT: { Render(); eglSwapBuffers(hDisplay, hSurface); InvalidateRect(hWnd, NULL, FALSE); } break;