blob: 8477159fa6733d835236d5576f73937ace79a608 [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
//
// Hello_Triangle_KD.c
//
// This is a simple example that draws a single triangle with
// a minimal vertex/fragment shader using OpenKODE.
//
#include <KD/kd.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
typedef struct
{
// Handle to a program object
GLuint programObject;
// EGL handles
EGLDisplay eglDisplay;
EGLContext eglContext;
EGLSurface eglSurface;
} UserData;
///
// Create a shader object, load the shader source, and
// compile the shader.
//
GLuint LoadShader ( GLenum type, const char *shaderSrc )
{
GLuint shader;
GLint compiled;
// Create the shader object
shader = glCreateShader ( type );
if ( shader == 0 )
return 0;
// Load the shader source
glShaderSource ( shader, 1, &shaderSrc, NULL );
// Compile the shader
glCompileShader ( shader );
// Check the compile status
glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled )
{
GLint infoLen = 0;
glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
if ( infoLen > 1 )
{
char* infoLog = kdMalloc (sizeof(char) * infoLen );
glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
kdLogMessage ( infoLog );
kdFree ( infoLog );
}
glDeleteShader ( shader );
return 0;
}
return shader;
}
///
// Initialize the shader and program object
//
int Init ( UserData *userData )
{
GLbyte vShaderStr[] =
"attribute vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
GLbyte fShaderStr[] =
"precision mediump float;\n"\
"void main() \n"
"{ \n"
" gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
"} \n";
GLuint vertexShader;
GLuint fragmentShader;
GLuint programObject;
GLint linked;
// Load the vertex/fragment shaders
vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
// Create the program object
programObject = glCreateProgram ( );
if ( programObject == 0 )
return 0;
glAttachShader ( programObject, vertexShader );
glAttachShader ( programObject, fragmentShader );
// Bind vPosition to attribute 0
glBindAttribLocation ( programObject, 0, "vPosition" );
// Link the program
glLinkProgram ( programObject );
// Check the link status
glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
if ( !linked )
{
GLint infoLen = 0;
glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
if ( infoLen > 1 )
{
char* infoLog = kdMalloc (sizeof(char) * infoLen );
glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
kdLogMessage ( infoLog );
kdFree ( infoLog );
}
glDeleteProgram ( programObject );
return FALSE;
}
// Store the program object
userData->programObject = programObject;
glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
return TRUE;
}
///
// Draw a triangle using the shader pair created in Init()
//
void Draw ( UserData *userData )
{
GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f };
// Set the viewport
glViewport ( 0, 0, 320, 240 );
// Clear the color buffer
glClear ( GL_COLOR_BUFFER_BIT );
// Use the program object
glUseProgram ( userData->programObject );
// Load the vertex data
glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
glEnableVertexAttribArray ( 0 );
glDrawArrays ( GL_TRIANGLES, 0, 3 );
eglSwapBuffers ( userData->eglDisplay, userData->eglSurface );
}
///
// InitEGLContext()
//
// Initialize an EGL rendering context and all associated elements
//
EGLBoolean InitEGLContext ( UserData *userData,
KDWindow *window,
EGLConfig config )
{
EGLContext context;
EGLSurface surface;
EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
// Get native window handle
EGLNativeWindowType hWnd;
if(kdRealizeWindow(window, &hWnd) != 0)
{
return EGL_FALSE;
}
surface = eglCreateWindowSurface(userData->eglDisplay, config, hWnd, NULL);
if ( surface == EGL_NO_SURFACE )
{
return EGL_FALSE;
}
// Create a GL context
context = eglCreateContext(userData->eglDisplay, config, EGL_NO_CONTEXT, contextAttribs );
if ( context == EGL_NO_CONTEXT )
{
return EGL_FALSE;
}
// Make the context current
if ( !eglMakeCurrent(userData->eglDisplay, surface, surface, context) )
{
return EGL_FALSE;
}
userData->eglContext = context;
userData->eglSurface = surface;
return EGL_TRUE;
}
///
// kdMain()
//
// Main function for OpenKODE application
//
KDint kdMain ( KDint argc, const KDchar *const *argv )
{
EGLint attribList[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, EGL_DONT_CARE,
EGL_DEPTH_SIZE, EGL_DONT_CARE,
EGL_STENCIL_SIZE, EGL_DONT_CARE,
EGL_NONE
};
EGLint majorVersion,
minorVersion;
UserData userData;
EGLint numConfigs;
EGLConfig config;
KDWindow *window = KD_NULL;
userData.eglDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
// Initialize EGL
if ( !eglInitialize(userData.eglDisplay, &majorVersion, &minorVersion) )
{
return EGL_FALSE;
}
// Get configs
if ( !eglGetConfigs(userData.eglDisplay, NULL, 0, &numConfigs) )
{
return EGL_FALSE;
}
// Choose config
if ( !eglChooseConfig(userData.eglDisplay, attribList, &config, 1, &numConfigs) )
{
return EGL_FALSE;
}
// Use OpenKODE to create a Window
window = kdCreateWindow ( userData.eglDisplay, config, KD_NULL );
if( !window )
kdExit ( 0 );
if ( !InitEGLContext ( &userData, window, config ) )
kdExit ( 0 );
if ( !Init ( &userData ) )
kdExit ( 0 );
// Main Loop
while ( 1 )
{
// Wait for an event
const KDEvent *evt = kdWaitEvent ( 0 );
if ( evt )
{
// Exit app
if ( evt->type == KD_EVENT_WINDOW_CLOSE)
break;
}
// Draw frame
Draw ( &userData );
}
// EGL clean up
eglMakeCurrent ( 0, 0, 0, 0 );
eglDestroySurface ( userData.eglDisplay, userData.eglSurface );
eglDestroyContext ( userData.eglDisplay, userData.eglContext );
// Destroy the window
kdDestroyWindow(window);
return 0;
}