/***********************
* gcc -o OpenGLES20 main.cpp -lGLESv2 -lEGL -lX11
***********************/
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#ifdef __linux__
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#else
#include <Windows.h>
#endif
const GLuint GRAPHICS_ATTRIB_VERTEX = 0;
typedef struct _escontext
{
void* userData; // Put your user data here...
GLint width; // Window width
GLint height; // Window height
EGLDisplay eglDisplay; // EGL display
EGLContext eglContext; // EGL context
EGLSurface eglSurface; // EGL surface
}ESContext;
typedef struct
{
// Handle to a program object
GLuint programObject;
} UserData;
#ifdef WIN32
LRESULT WINAPI ESWindowProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
#endif
int InitEGL(ESContext * esContext)
{
NativeWindowType eglWindow = (NativeWindowType)NULL;
EGLDisplay display;
EGLContext context;
EGLSurface surface;
EGLConfig configs[2];
EGLBoolean eRetStatus;
EGLint majorVer, minorVer;
EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
EGLint numConfigs;
EGLint cfg_attribs[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_BUFFER_SIZE, EGL_DONT_CARE,
EGL_DEPTH_SIZE, 16,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
#ifdef __linux__
EGL_SAMPLES, 2,
EGL_SAMPLE_BUFFERS, 1,
#endif
EGL_NONE};
#ifdef __linux__
Window root;
XSetWindowAttributes swa;
Window win;
/*
* X11 native display initialization
*/
Display *x_display = NULL;
x_display = XOpenDisplay(NULL);
if ( x_display == NULL )
{
return EGL_FALSE;
}
root = DefaultRootWindow(x_display);
swa.event_mask = NoEventMask;
win = XCreateWindow( x_display, root,
0, 0, esContext->width, esContext->height, 0,
CopyFromParent, InputOutput,
CopyFromParent, CWEventMask,
&swa );
// make the window visible on the screen
XMapWindow (x_display, win);
XStoreName (x_display, win, "OpenGLES20");
eglWindow = (NativeWindowType)win;
display = eglGetDisplay(x_display);
if ( display == EGL_NO_DISPLAY )
{
return EGL_FALSE;
}
#endif
#ifdef WIN32
WNDCLASS wndclass = {0};
HINSTANCE hInstance = GetModuleHandle ( NULL );
wndclass.style = CS_OWNDC;
wndclass.lpfnWndProc = ( WNDPROC ) ESWindowProc;
wndclass.hInstance = hInstance;
wndclass.hbrBackground = ( HBRUSH ) GetStockObject ( BLACK_BRUSH );
wndclass.lpszClassName = TEXT("opengles2.0");
if ( !RegisterClass ( &wndclass ) )
{
return FALSE;
}
DWORD wStyle = WS_VISIBLE | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION;
eglWindow = CreateWindow(
wndclass.lpszClassName,
TEXT("opengles20"),
wStyle,
0,
0,
esContext->width,
esContext->height,
NULL,
NULL,
hInstance,
NULL);
SetWindowLongPtr ( eglWindow, GWL_USERDATA, ( LONG ) ( LONG_PTR ) esContext );
if ( eglWindow == NULL )
{
return GL_FALSE;
}
// make the window visible on the screen
ShowWindow ( eglWindow, TRUE );
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if ( display == EGL_NO_DISPLAY )
{
return EGL_FALSE;
}
#endif
// Initialize EGL display connection
eRetStatus = eglInitialize(display, &majorVer, &minorVer);
if( eRetStatus != EGL_TRUE )
{
return EGL_FALSE;
}
//Get a list of all EGL frame buffer configurations for a display
eRetStatus = eglGetConfigs (display, configs, 2, &numConfigs);
if( eRetStatus != EGL_TRUE )
{
return EGL_FALSE;
}
// Get a list of EGL frame buffer configurations that match specified attributes
eRetStatus = eglChooseConfig (display, cfg_attribs, configs, 2, &numConfigs);
if( eRetStatus != EGL_TRUE || !numConfigs)
{
return EGL_FALSE;
}
// Create a new EGL window surface
surface = eglCreateWindowSurface(display, configs[0], eglWindow, NULL);
if (surface == EGL_NO_SURFACE)
{
return EGL_FALSE;
}
// Set the current rendering API (EGL_OPENGL_API, EGL_OPENGL_ES_API,EGL_OPENVG_API)
eRetStatus = eglBindAPI(EGL_OPENGL_ES_API);
if (eRetStatus != EGL_TRUE)
{
return EGL_FALSE;
}
// Create a new EGL rendering context
context = eglCreateContext (display, configs[0], EGL_NO_CONTEXT, context_attribs);
if (context == EGL_NO_CONTEXT)
{
return EGL_FALSE;
}
// Attach an EGL rendering context to EGL surfaces
eRetStatus = eglMakeCurrent (display, surface, surface, context);
if( eRetStatus != EGL_TRUE )
{
return EGL_FALSE;
}
//If interval is set to a value of 0, buffer swaps are not synchronized to a video frame, and the swap happens as soon as the render is complete.
eglSwapInterval(display,0);
// Return the context elements
esContext->eglDisplay = display;
esContext->eglSurface = surface;
esContext->eglContext = context;
return EGL_TRUE;
}
/* type specifies the Shader type: GL_VERTEX_SHADER or GL_FRAGMENT_SHADER */
GLuint LoadShader ( GLenum type, const char *shaderSrc )
{
GLuint shader;
GLint compiled;
// Create an empty shader object, which maintain the source code strings that define a shader
shader = glCreateShader ( type );
if ( shader == 0 )
return 0;
// Replaces the source code in a shader object
glShaderSource ( shader, 1, &shaderSrc, NULL );
// Compile the shader object
glCompileShader ( shader );
// Check the shader object 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 = (char*) malloc (sizeof(char) * infoLen );
glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
printf ( "Error compiling shader:\n%s\n", infoLog );
free ( infoLog );
}
glDeleteShader ( shader );
return 0;
}
return shader;
}
GLuint LoadProgram ( const char *vShaderStr, const char *fShaderStr )
{
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;
// Attaches a shader object to a program object
glAttachShader ( programObject, vertexShader );
glAttachShader ( programObject, fragmentShader );
// Bind vPosition to attribute 0
glBindAttribLocation ( programObject, GRAPHICS_ATTRIB_VERTEX, "vPosition" );
// Link the program object
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 = (char*) malloc (sizeof(char) * infoLen );
glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
printf ( "Error linking program:\n%s\n", infoLog );