| // |
| // Book: OpenGL(R) ES 2.0 Programming Guide |
| // Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner |
| // ISBN-10: 0321502795 |
| // ISBN-13: 9780321502797 |
| // Publisher: Addison-Wesley Professional |
| // URLs: http://safari.informit.com/9780321563835 |
| // http://www.opengles-book.com |
| // |
| |
| // ESUtil.c |
| // |
| // A utility library for OpenGL ES. This library provides a |
| // basic common framework for the example applications in the |
| // OpenGL ES 2.0 Programming Guide. |
| // |
| |
| /// |
| // Includes |
| // |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <GLES2/gl2.h> |
| #include <EGL/egl.h> |
| #include <EGL/eglext.h> |
| #include "esUtil.h" |
| #include "esUtil_win.h" |
| |
| #if defined(_MSC_VER) |
| #pragma warning(disable: 4204) // nonstandard extension used : non-constant aggregate initializer |
| #endif |
| |
| /// |
| // Extensions |
| // |
| |
| PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; |
| PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; |
| |
| PFNEGLPOSTSUBBUFFERNVPROC eglPostSubBufferNV; |
| |
| PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; |
| |
| PFNGLDELETEFENCESNVPROC glDeleteFencesNV; |
| PFNGLGENFENCESNVPROC glGenFencesNV; |
| PFNGLGETFENCEIVNVPROC glGetFenceivNV; |
| PFNGLISFENCENVPROC glIsFenceNV; |
| PFNGLFINISHFENCENVPROC glFinishFenceNV; |
| PFNGLSETFENCENVPROC glSetFenceNV; |
| PFNGLTESTFENCENVPROC glTestFenceNV; |
| |
| /// |
| // CreateEGLContext() |
| // |
| // Creates an EGL rendering context and all associated elements |
| // |
| EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay, |
| EGLContext* eglContext, EGLSurface* eglSurface, |
| EGLint* configAttribList, EGLint* surfaceAttribList) |
| { |
| EGLint numConfigs; |
| EGLint majorVersion; |
| EGLint minorVersion; |
| EGLDisplay display; |
| EGLContext context; |
| EGLSurface surface; |
| EGLConfig config; |
| EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE }; |
| |
| // Get Display |
| display = eglGetDisplay(GetDC(hWnd)); |
| if ( display == EGL_NO_DISPLAY ) |
| { |
| return EGL_FALSE; |
| } |
| |
| // Initialize EGL |
| if ( !eglInitialize(display, &majorVersion, &minorVersion) ) |
| { |
| return EGL_FALSE; |
| } |
| |
| // Bind to extensions |
| eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR"); |
| eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR"); |
| |
| eglPostSubBufferNV = (PFNEGLPOSTSUBBUFFERNVPROC) eglGetProcAddress("eglPostSubBufferNV"); |
| |
| glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress("glEGLImageTargetTexture2DOES"); |
| |
| glDeleteFencesNV = (PFNGLDELETEFENCESNVPROC) eglGetProcAddress("glDeleteFencesNV"); |
| glGenFencesNV = (PFNGLGENFENCESNVPROC) eglGetProcAddress("glGenFencesNV"); |
| glGetFenceivNV = (PFNGLGETFENCEIVNVPROC) eglGetProcAddress("glGetFenceivNV"); |
| glIsFenceNV = (PFNGLISFENCENVPROC) eglGetProcAddress("glIsFenceNV"); |
| glFinishFenceNV = (PFNGLFINISHFENCENVPROC) eglGetProcAddress("glFinishFenceNV"); |
| glSetFenceNV = (PFNGLSETFENCENVPROC) eglGetProcAddress("glSetFenceNV"); |
| glTestFenceNV = (PFNGLTESTFENCENVPROC) eglGetProcAddress("glTestFenceNV"); |
| |
| // Get configs |
| if ( !eglGetConfigs(display, NULL, 0, &numConfigs) ) |
| { |
| return EGL_FALSE; |
| } |
| |
| // Choose config |
| if ( !eglChooseConfig(display, configAttribList, &config, 1, &numConfigs) ) |
| { |
| return EGL_FALSE; |
| } |
| |
| // Create a surface |
| surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, surfaceAttribList); |
| if ( surface == EGL_NO_SURFACE ) |
| { |
| return EGL_FALSE; |
| } |
| |
| // Create a GL context |
| context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs ); |
| if ( context == EGL_NO_CONTEXT ) |
| { |
| return EGL_FALSE; |
| } |
| |
| // Make the context current |
| if ( !eglMakeCurrent(display, surface, surface, context) ) |
| { |
| return EGL_FALSE; |
| } |
| |
| *eglDisplay = display; |
| *eglSurface = surface; |
| *eglContext = context; |
| return EGL_TRUE; |
| } |
| |
| ////////////////////////////////////////////////////////////////// |
| // |
| // Public Functions |
| // |
| // |
| |
| /// |
| // esInitContext() |
| // |
| // Initialize ES utility context. This must be called before calling any other |
| // functions. |
| // |
| void ESUTIL_API esInitContext ( ESContext *esContext ) |
| { |
| if ( esContext != NULL ) |
| { |
| memset( esContext, 0, sizeof( ESContext) ); |
| } |
| } |
| |
| /// |
| // esCreateWindow() |
| // |
| // title - name for title bar of window |
| // width - width of window to create |
| // height - height of window to create |
| // flags - bitwise or of window creation flags |
| // ES_WINDOW_ALPHA - specifies that the framebuffer should have alpha |
| // ES_WINDOW_DEPTH - specifies that a depth buffer should be created |
| // ES_WINDOW_STENCIL - specifies that a stencil buffer should be created |
| // ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created |
| // ES_WINDOW_POST_SUB_BUFFER_SUPPORTED - specifies that EGL_POST_SUB_BUFFER_NV is supported. |
| // |
| GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint width, GLint height, GLuint flags ) |
| { |
| EGLint configAttribList[] = |
| { |
| EGL_RED_SIZE, 5, |
| EGL_GREEN_SIZE, 6, |
| EGL_BLUE_SIZE, 5, |
| EGL_ALPHA_SIZE, (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE, |
| EGL_DEPTH_SIZE, (flags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE, |
| EGL_STENCIL_SIZE, (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE, |
| EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0, |
| EGL_NONE |
| }; |
| EGLint surfaceAttribList[] = |
| { |
| EGL_POST_SUB_BUFFER_SUPPORTED_NV, flags & (ES_WINDOW_POST_SUB_BUFFER_SUPPORTED) ? EGL_TRUE : EGL_FALSE, |
| EGL_NONE, EGL_NONE |
| }; |
| |
| if ( esContext == NULL ) |
| { |
| return GL_FALSE; |
| } |
| |
| esContext->width = width; |
| esContext->height = height; |
| |
| if ( !WinCreate ( esContext, title) ) |
| { |
| return GL_FALSE; |
| } |
| |
| |
| if ( !CreateEGLContext ( esContext->hWnd, |
| &esContext->eglDisplay, |
| &esContext->eglContext, |
| &esContext->eglSurface, |
| configAttribList, |
| surfaceAttribList ) ) |
| { |
| return GL_FALSE; |
| } |
| |
| |
| return GL_TRUE; |
| } |
| |
| /// |
| // esMainLoop() |
| // |
| // Start the main loop for the OpenGL ES application |
| // |
| void ESUTIL_API esMainLoop ( ESContext *esContext ) |
| { |
| WinLoop ( esContext ); |
| } |
| |
| |
| /// |
| // esRegisterDrawFunc() |
| // |
| void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void (ESCALLBACK *drawFunc) (ESContext* ) ) |
| { |
| esContext->drawFunc = drawFunc; |
| } |
| |
| |
| /// |
| // esRegisterUpdateFunc() |
| // |
| void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void (ESCALLBACK *updateFunc) ( ESContext*, float ) ) |
| { |
| esContext->updateFunc = updateFunc; |
| } |
| |
| |
| /// |
| // esRegisterKeyFunc() |
| // |
| void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext, |
| void (ESCALLBACK *keyFunc) (ESContext*, unsigned char, int, int ) ) |
| { |
| esContext->keyFunc = keyFunc; |
| } |
| |
| |
| /// |
| // esLogMessage() |
| // |
| // Log an error message to the debug output for the platform |
| // |
| void ESUTIL_API esLogMessage ( const char *formatStr, ... ) |
| { |
| va_list params; |
| char buf[BUFSIZ]; |
| |
| va_start ( params, formatStr ); |
| vsprintf_s ( buf, sizeof(buf), formatStr, params ); |
| |
| printf ( "%s", buf ); |
| |
| va_end ( params ); |
| } |
| |
| |
| /// |
| // esLoadTGA() |
| // |
| // Loads a 24-bit TGA image from a file |
| // |
| char* ESUTIL_API esLoadTGA ( char *fileName, int *width, int *height ) |
| { |
| char *buffer; |
| |
| if ( WinTGALoad ( fileName, &buffer, width, height ) ) |
| { |
| return buffer; |
| } |
| |
| return NULL; |
| } |