1 // 2 // Book: OpenGL(R) ES 2.0 Programming Guide 3 // Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner 4 // ISBN-10: 0321502795 5 // ISBN-13: 9780321502797 6 // Publisher: Addison-Wesley Professional 7 // URLs: http://safari.informit.com/9780321563835 8 // http://www.opengles-book.com 9 // 10 11 // ESUtil.c 12 // 13 // A utility library for OpenGL ES. This library provides a 14 // basic common framework for the example applications in the 15 // OpenGL ES 2.0 Programming Guide. 16 // 17 18 /// 19 // Includes 20 // 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <GLES2/gl2.h> 24 #include <EGL/egl.h> 25 #include <EGL/eglext.h> 26 #include "esUtil.h" 27 #include "esUtil_win.h" 28 29 #if defined(_MSC_VER) 30 #pragma warning(disable: 4204) // nonstandard extension used : non-constant aggregate initializer 31 #endif 32 33 /// 34 // Extensions 35 // 36 37 PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; 38 PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; 39 40 PFNEGLPOSTSUBBUFFERNVPROC eglPostSubBufferNV; 41 42 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; 43 44 PFNGLDELETEFENCESNVPROC glDeleteFencesNV; 45 PFNGLGENFENCESNVPROC glGenFencesNV; 46 PFNGLGETFENCEIVNVPROC glGetFenceivNV; 47 PFNGLISFENCENVPROC glIsFenceNV; 48 PFNGLFINISHFENCENVPROC glFinishFenceNV; 49 PFNGLSETFENCENVPROC glSetFenceNV; 50 PFNGLTESTFENCENVPROC glTestFenceNV; 51 52 /// 53 // CreateEGLContext() 54 // 55 // Creates an EGL rendering context and all associated elements 56 // 57 EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay, 58 EGLContext* eglContext, EGLSurface* eglSurface, 59 EGLint* configAttribList, EGLint* surfaceAttribList) 60 { 61 EGLint numConfigs; 62 EGLint majorVersion; 63 EGLint minorVersion; 64 EGLDisplay display; 65 EGLContext context; 66 EGLSurface surface; 67 EGLConfig config; 68 EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE }; 69 70 // Get Display 71 display = eglGetDisplay(GetDC(hWnd)); 72 if ( display == EGL_NO_DISPLAY ) 73 { 74 return EGL_FALSE; 75 } 76 77 // Initialize EGL 78 if ( !eglInitialize(display, &majorVersion, &minorVersion) ) 79 { 80 return EGL_FALSE; 81 } 82 83 // Bind to extensions 84 eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR"); 85 eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR"); 86 87 eglPostSubBufferNV = (PFNEGLPOSTSUBBUFFERNVPROC) eglGetProcAddress("eglPostSubBufferNV"); 88 89 glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress("glEGLImageTargetTexture2DOES"); 90 91 glDeleteFencesNV = (PFNGLDELETEFENCESNVPROC) eglGetProcAddress("glDeleteFencesNV"); 92 glGenFencesNV = (PFNGLGENFENCESNVPROC) eglGetProcAddress("glGenFencesNV"); 93 glGetFenceivNV = (PFNGLGETFENCEIVNVPROC) eglGetProcAddress("glGetFenceivNV"); 94 glIsFenceNV = (PFNGLISFENCENVPROC) eglGetProcAddress("glIsFenceNV"); 95 glFinishFenceNV = (PFNGLFINISHFENCENVPROC) eglGetProcAddress("glFinishFenceNV"); 96 glSetFenceNV = (PFNGLSETFENCENVPROC) eglGetProcAddress("glSetFenceNV"); 97 glTestFenceNV = (PFNGLTESTFENCENVPROC) eglGetProcAddress("glTestFenceNV"); 98 99 // Get configs 100 if ( !eglGetConfigs(display, NULL, 0, &numConfigs) ) 101 { 102 return EGL_FALSE; 103 } 104 105 // Choose config 106 if ( !eglChooseConfig(display, configAttribList, &config, 1, &numConfigs) ) 107 { 108 return EGL_FALSE; 109 } 110 111 // Create a surface 112 surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, surfaceAttribList); 113 if ( surface == EGL_NO_SURFACE ) 114 { 115 return EGL_FALSE; 116 } 117 118 // Create a GL context 119 context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs ); 120 if ( context == EGL_NO_CONTEXT ) 121 { 122 return EGL_FALSE; 123 } 124 125 // Make the context current 126 if ( !eglMakeCurrent(display, surface, surface, context) ) 127 { 128 return EGL_FALSE; 129 } 130 131 *eglDisplay = display; 132 *eglSurface = surface; 133 *eglContext = context; 134 return EGL_TRUE; 135 } 136 137 ////////////////////////////////////////////////////////////////// 138 // 139 // Public Functions 140 // 141 // 142 143 /// 144 // esInitContext() 145 // 146 // Initialize ES utility context. This must be called before calling any other 147 // functions. 148 // 149 void ESUTIL_API esInitContext ( ESContext *esContext ) 150 { 151 if ( esContext != NULL ) 152 { 153 memset( esContext, 0, sizeof( ESContext) ); 154 } 155 } 156 157 /// 158 // esCreateWindow() 159 // 160 // title - name for title bar of window 161 // width - width of window to create 162 // height - height of window to create 163 // flags - bitwise or of window creation flags 164 // ES_WINDOW_ALPHA - specifies that the framebuffer should have alpha 165 // ES_WINDOW_DEPTH - specifies that a depth buffer should be created 166 // ES_WINDOW_STENCIL - specifies that a stencil buffer should be created 167 // ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created 168 // ES_WINDOW_POST_SUB_BUFFER_SUPPORTED - specifies that EGL_POST_SUB_BUFFER_NV is supported. 169 // 170 GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, LPCTSTR title, GLint width, GLint height, GLuint flags ) 171 { 172 EGLint configAttribList[] = 173 { 174 EGL_RED_SIZE, 5, 175 EGL_GREEN_SIZE, 6, 176 EGL_BLUE_SIZE, 5, 177 EGL_ALPHA_SIZE, (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE, 178 EGL_DEPTH_SIZE, (flags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE, 179 EGL_STENCIL_SIZE, (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE, 180 EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0, 181 EGL_NONE 182 }; 183 EGLint surfaceAttribList[] = 184 { 185 EGL_POST_SUB_BUFFER_SUPPORTED_NV, flags & (ES_WINDOW_POST_SUB_BUFFER_SUPPORTED) ? EGL_TRUE : EGL_FALSE, 186 EGL_NONE, EGL_NONE 187 }; 188 189 if ( esContext == NULL ) 190 { 191 return GL_FALSE; 192 } 193 194 esContext->width = width; 195 esContext->height = height; 196 197 if ( !WinCreate ( esContext, title) ) 198 { 199 return GL_FALSE; 200 } 201 202 203 if ( !CreateEGLContext ( esContext->hWnd, 204 &esContext->eglDisplay, 205 &esContext->eglContext, 206 &esContext->eglSurface, 207 configAttribList, 208 surfaceAttribList ) ) 209 { 210 return GL_FALSE; 211 } 212 213 214 return GL_TRUE; 215 } 216 217 /// 218 // esMainLoop() 219 // 220 // Start the main loop for the OpenGL ES application 221 // 222 void ESUTIL_API esMainLoop ( ESContext *esContext ) 223 { 224 WinLoop ( esContext ); 225 } 226 227 228 /// 229 // esRegisterDrawFunc() 230 // 231 void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void (ESCALLBACK *drawFunc) (ESContext* ) ) 232 { 233 esContext->drawFunc = drawFunc; 234 } 235 236 237 /// 238 // esRegisterUpdateFunc() 239 // 240 void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void (ESCALLBACK *updateFunc) ( ESContext*, float ) ) 241 { 242 esContext->updateFunc = updateFunc; 243 } 244 245 246 /// 247 // esRegisterKeyFunc() 248 // 249 void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext, 250 void (ESCALLBACK *keyFunc) (ESContext*, unsigned char, int, int ) ) 251 { 252 esContext->keyFunc = keyFunc; 253 } 254 255 256 /// 257 // esLogMessage() 258 // 259 // Log an error message to the debug output for the platform 260 // 261 void ESUTIL_API esLogMessage ( const char *formatStr, ... ) 262 { 263 va_list params; 264 char buf[BUFSIZ]; 265 266 va_start ( params, formatStr ); 267 vsprintf_s ( buf, sizeof(buf), formatStr, params ); 268 269 printf ( "%s", buf ); 270 271 va_end ( params ); 272 } 273 274 275 /// 276 // esLoadTGA() 277 // 278 // Loads a 24-bit TGA image from a file 279 // 280 char* ESUTIL_API esLoadTGA ( char *fileName, int *width, int *height ) 281 { 282 char *buffer; 283 284 if ( WinTGALoad ( fileName, &buffer, width, height ) ) 285 { 286 return buffer; 287 } 288 289 return NULL; 290 } 291