blob: aeeee7ff8fa9bfd0ae7abde5d9e4abcec4aeb2f8 [file] [log] [blame]
//
// 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;
}