Created
September 28, 2012 11:08
-
-
Save kanru/3799213 to your computer and use it in GitHub Desktop.
X11 EGL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Created by exoticorn ( http://talk.maemo.org/showthread.php?t=37356 ) | |
* edited and commented by André Bergner [endboss] | |
* | |
* libraries needed: libx11-dev, libgles2-dev | |
* | |
* compile with: g++ -lX11 -lEGL -lGLESv2 egl-example.cpp | |
*/ | |
#include <iostream> | |
using namespace std; | |
#include <cstdlib> | |
#include <cstring> | |
#include <cmath> | |
#include <sys/time.h> | |
#include <X11/Xlib.h> | |
#include <X11/Xatom.h> | |
#include <X11/Xutil.h> | |
#include <GLES2/gl2.h> | |
#include <EGL/egl.h> | |
const char vertex_src [] = | |
" \ | |
attribute vec4 position; \ | |
varying mediump vec2 pos; \ | |
uniform vec4 offset; \ | |
\ | |
void main() \ | |
{ \ | |
gl_Position = position + offset; \ | |
pos = position.xy; \ | |
} \ | |
"; | |
const char fragment_src [] = | |
" \ | |
varying mediump vec2 pos; \ | |
uniform mediump float phase; \ | |
\ | |
void main() \ | |
{ \ | |
gl_FragColor = vec4( 1., 0.9, 0.7, 1.0 ) * \ | |
cos( 30.*sqrt(pos.x*pos.x + 1.5*pos.y*pos.y) \ | |
+ atan(pos.y,pos.x) - phase ); \ | |
} \ | |
"; | |
const char vertex_src2 [] = | |
" \ | |
attribute vec4 position; \ | |
attribute vec2 aTexCoord; \ | |
varying mediump vec2 vTexCoord; \ | |
void main() \ | |
{ \ | |
gl_Position = mat4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1) * position; \ | |
vTexCoord = aTexCoord; \ | |
} \ | |
"; | |
const char fragment_src2 [] = | |
" \ | |
uniform sampler2D uTexture; \ | |
varying mediump vec2 vTexCoord; \ | |
void main() \ | |
{ \ | |
gl_FragColor = texture2D(uTexture, vTexCoord); \ | |
} \ | |
"; | |
void | |
print_shader_info_log ( | |
GLuint shader // handle to the shader | |
) | |
{ | |
GLint length = 0; | |
glGetShaderiv ( shader , GL_INFO_LOG_LENGTH , &length ); | |
if ( length ) { | |
char* buffer = new char [ length ]; | |
glGetShaderInfoLog ( shader , length , NULL , buffer ); | |
cout << "shader info: " << buffer << flush; | |
delete [] buffer; | |
GLint success; | |
glGetShaderiv( shader, GL_COMPILE_STATUS, &success ); | |
if ( success != GL_TRUE ) exit ( 1 ); | |
} | |
} | |
void | |
print_prog_info_log (GLuint prog) | |
{ | |
GLint length = 0; | |
GLchar buf[256]; | |
glGetProgramInfoLog(prog, 256, &length, buf); | |
if ( length ) { | |
cout << "prog info: " << buf << flush; | |
} | |
} | |
GLuint | |
load_shader ( | |
const char *shader_source, | |
GLenum type | |
) | |
{ | |
GLuint shader = glCreateShader( type ); | |
glShaderSource ( shader , 1 , &shader_source , NULL ); | |
glCompileShader ( shader ); | |
print_shader_info_log ( shader ); | |
return shader; | |
} | |
Display *x_display; | |
Window win; | |
EGLDisplay egl_display; | |
EGLContext egl_context; | |
GLfloat | |
norm_x = 0.0, | |
norm_y = 0.0, | |
offset_x = 0.0, | |
offset_y = 0.0, | |
p1_pos_x = 0.0, | |
p1_pos_y = 0.0; | |
GLint | |
phase_loc, | |
offset_loc, | |
position_loc; | |
GLint position_loc2; | |
GLint aTexCoord; | |
EGLSurface egl_surface; | |
bool update_pos = false; | |
const float vertexArray[] = { | |
0.0, 0.5, 0.0, | |
-0.5, 0.0, 0.0, | |
0.0, -0.5, 0.0, | |
0.5, 0.0, 0.0, | |
0.0, 0.5, 0.0 | |
}; | |
const float vertexArray2[] = { | |
0.0, 0.0, 0.0, | |
0.5, 0.0, 0.0, | |
0.0, 0.5, 0.0, | |
0.5, 0.5, 0.0, | |
}; | |
const float vertexArray3[] = { | |
0.0, 0.0, | |
1.0, 0.0, | |
0.0, 1.0, | |
1.0, 1.0 | |
}; | |
void render(GLuint shader1, GLuint shader2) | |
{ | |
static float phase = 0; | |
static int donesetup = 0; | |
static XWindowAttributes gwa; | |
//// draw | |
if ( !donesetup ) { | |
XWindowAttributes gwa; | |
XGetWindowAttributes ( x_display , win , &gwa ); | |
glViewport ( 0 , 0 , gwa.width , gwa.height ); | |
glClearColor ( 0.08 , 0.06 , 0.07 , 1.); // background color | |
donesetup = 1; | |
} | |
glClear ( GL_COLOR_BUFFER_BIT ); | |
glUseProgram ( shader1 ); | |
glUniform1f ( phase_loc , phase ); // write the value of phase to the shaders phase | |
phase = fmodf ( phase + 0.5f , 2.f * 3.141f ); // and update the local variable | |
if ( update_pos ) { // if the position of the texture has changed due to user action | |
GLfloat old_offset_x = offset_x; | |
GLfloat old_offset_y = offset_y; | |
offset_x = norm_x - p1_pos_x; | |
offset_y = norm_y - p1_pos_y; | |
p1_pos_x = norm_x; | |
p1_pos_y = norm_y; | |
offset_x += old_offset_x; | |
offset_y += old_offset_y; | |
update_pos = false; | |
} | |
glUniform4f ( offset_loc , offset_x , offset_y , 0.0 , 0.0 ); | |
glVertexAttribPointer ( position_loc, 3, GL_FLOAT, false, 0, vertexArray ); | |
glEnableVertexAttribArray ( position_loc ); | |
glDrawArrays ( GL_TRIANGLE_STRIP, 0, 5 ); | |
GLuint texture; | |
glActiveTexture(GL_TEXTURE0); | |
glGenTextures(1, &texture); | |
glBindTexture(GL_TEXTURE_2D, texture); | |
//unsigned char* buf = (unsigned char*)malloc(800 * 480 * 3); | |
// glReadPixels(0, 0, // x, y | |
// 800, 480, // w, h | |
// GL_RGB, | |
// GL_UNSIGNED_BYTE, | |
// buf); | |
glTexImage2D(GL_TEXTURE_2D, | |
0, // level | |
GL_RGB, | |
800, 480, // w, h | |
0, // border | |
GL_RGB, | |
GL_UNSIGNED_BYTE, | |
0); | |
// free(buf); | |
glCopyTexSubImage2D(GL_TEXTURE_2D, | |
0, // level | |
0, 0, // offset | |
0, 0, // x, y | |
800, 480); // w, h | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
glUseProgram ( shader2 ); | |
glVertexAttribPointer ( position_loc2, 3, GL_FLOAT, false, 0, vertexArray2 ); | |
glEnableVertexAttribArray ( position_loc2 ); | |
glVertexAttribPointer ( aTexCoord, 2, GL_FLOAT, false, 0, vertexArray3 ); | |
glEnableVertexAttribArray ( aTexCoord ); | |
glDrawArrays ( GL_TRIANGLE_STRIP, 0, 4 ); | |
glBindTexture(GL_TEXTURE_2D, 0); | |
eglSwapBuffers ( egl_display, egl_surface ); // get the rendered buffer to the screen | |
} | |
//////////////////////////////////////////////////////////////////////////////////////////// | |
int main() | |
{ | |
/////// the X11 part ////////////////////////////////////////////////////////////////// | |
// in the first part the program opens a connection to the X11 window manager | |
// | |
x_display = XOpenDisplay ( NULL ); // open the standard display (the primary screen) | |
if ( x_display == NULL ) { | |
cerr << "cannot connect to X server" << endl; | |
return 1; | |
} | |
Window root = DefaultRootWindow( x_display ); // get the root window (usually the whole screen) | |
XSetWindowAttributes swa; | |
swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask; | |
win = XCreateWindow ( // create a window with the provided parameters | |
x_display, root, | |
0, 0, 800, 480, 0, | |
CopyFromParent, InputOutput, | |
CopyFromParent, CWEventMask, | |
&swa ); | |
XSetWindowAttributes xattr; | |
Atom atom; | |
int one = 1; | |
xattr.override_redirect = False; | |
XChangeWindowAttributes ( x_display, win, CWOverrideRedirect, &xattr ); | |
XWMHints hints; | |
hints.input = True; | |
hints.flags = InputHint; | |
XSetWMHints(x_display, win, &hints); | |
XMapWindow ( x_display , win ); // make the window visible on the screen | |
XStoreName ( x_display , win , "GL test" ); // give the window a name | |
/////// the egl part ////////////////////////////////////////////////////////////////// | |
// egl provides an interface to connect the graphics related functionality of openGL ES | |
// with the windowing interface and functionality of the native operation system (X11 | |
// in our case. | |
egl_display = eglGetDisplay( (EGLNativeDisplayType) x_display ); | |
if ( egl_display == EGL_NO_DISPLAY ) { | |
cerr << "Got no EGL display." << endl; | |
return 1; | |
} | |
if ( !eglInitialize( egl_display, NULL, NULL ) ) { | |
cerr << "Unable to initialize EGL" << endl; | |
return 1; | |
} | |
EGLint attr[] = { // some attributes to set up our egl-interface | |
EGL_BUFFER_SIZE, 16, | |
EGL_RED_SIZE, 5, | |
EGL_GREEN_SIZE, 6, | |
EGL_BLUE_SIZE, 5, | |
EGL_RENDERABLE_TYPE, | |
EGL_OPENGL_ES2_BIT, | |
EGL_NONE | |
}; | |
EGLConfig ecfg; | |
EGLint num_config; | |
if ( !eglChooseConfig( egl_display, attr, &ecfg, 1, &num_config ) ) { | |
cerr << "Failed to choose config (eglError: " << eglGetError() << ")" << endl; | |
return 1; | |
} | |
if ( num_config != 1 ) { | |
cerr << "Didn't get exactly one config, but " << num_config << endl; | |
return 1; | |
} | |
egl_surface = eglCreateWindowSurface ( egl_display, ecfg, win, NULL ); | |
if ( egl_surface == EGL_NO_SURFACE ) { | |
cerr << "Unable to create EGL surface (eglError: " << eglGetError() << ")" << endl; | |
return 1; | |
} | |
//// egl-contexts collect all state descriptions needed required for operation | |
EGLint ctxattr[] = { | |
EGL_CONTEXT_CLIENT_VERSION, 2, | |
EGL_NONE | |
}; | |
egl_context = eglCreateContext ( egl_display, ecfg, EGL_NO_CONTEXT, ctxattr ); | |
if ( egl_context == EGL_NO_CONTEXT ) { | |
cerr << "Unable to create EGL context (eglError: " << eglGetError() << ")" << endl; | |
return 1; | |
} | |
//// associate the egl-context with the egl-surface | |
eglMakeCurrent( egl_display, egl_surface, egl_surface, egl_context ); | |
/////// the openGL part /////////////////////////////////////////////////////////////// | |
GLuint vertexShader = load_shader ( vertex_src , GL_VERTEX_SHADER ); // load vertex shader | |
GLuint fragmentShader = load_shader ( fragment_src , GL_FRAGMENT_SHADER ); // load fragment shader | |
GLuint shaderProgram = glCreateProgram (); // create program object | |
glAttachShader ( shaderProgram, vertexShader ); // and attach both... | |
glAttachShader ( shaderProgram, fragmentShader ); // ... shaders to it | |
glLinkProgram ( shaderProgram ); // link the program | |
//// now get the locations (kind of handle) of the shaders variables | |
position_loc = glGetAttribLocation ( shaderProgram , "position" ); | |
phase_loc = glGetUniformLocation ( shaderProgram , "phase" ); | |
offset_loc = glGetUniformLocation ( shaderProgram , "offset" ); | |
if ( position_loc < 0 || phase_loc < 0 || offset_loc < 0 ) { | |
cerr << "Unable to get uniform location" << endl; | |
return 1; | |
} | |
vertexShader = load_shader ( vertex_src2 , GL_VERTEX_SHADER ); // load vertex shader | |
fragmentShader = load_shader ( fragment_src2 , GL_FRAGMENT_SHADER ); // load fragment shader | |
GLuint shaderProgram2 = glCreateProgram (); // create program object | |
glAttachShader ( shaderProgram2, vertexShader ); // and attach both... | |
glAttachShader ( shaderProgram2, fragmentShader ); // ... shaders to it | |
glLinkProgram ( shaderProgram2 ); // link the program | |
print_prog_info_log( shaderProgram2 ); | |
position_loc2 = glGetAttribLocation ( shaderProgram2 , "position" ); | |
aTexCoord = glGetAttribLocation ( shaderProgram2 , "aTexCoord" ); | |
if ( position_loc2 < 0 || aTexCoord < 0 ) { | |
cerr << "Unable to get uniform location" << endl; | |
return 1; | |
} | |
const float | |
window_width = 800.0, | |
window_height = 480.0; | |
//// this is needed for time measuring --> frames per second | |
struct timezone tz; | |
timeval t1, t2; | |
gettimeofday ( &t1 , &tz ); | |
int num_frames = 0; | |
bool quit = false; | |
while ( !quit ) { // the main loop | |
while ( XPending ( x_display ) ) { // check for events from the x-server | |
XEvent xev; | |
XNextEvent( x_display, &xev ); | |
if ( xev.type == MotionNotify ) { // if mouse has moved | |
// cout << "move to: << xev.xmotion.x << "," << xev.xmotion.y << endl; | |
GLfloat window_y = (window_height - xev.xmotion.y) - window_height / 2.0; | |
norm_y = window_y / (window_height / 2.0); | |
GLfloat window_x = xev.xmotion.x - window_width / 2.0; | |
norm_x = window_x / (window_width / 2.0); | |
update_pos = true; | |
} | |
if ( xev.type == KeyPress ) quit = true; | |
} | |
render(shaderProgram, shaderProgram2); // now we finally put something on the screen | |
if ( ++num_frames % 100 == 0 ) { | |
gettimeofday( &t2, &tz ); | |
float dt = t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6; | |
cout << "fps: " << num_frames / dt << endl; | |
num_frames = 0; | |
t1 = t2; | |
} | |
// usleep( 1000*10 ); | |
} | |
//// cleaning up... | |
eglDestroyContext ( egl_display, egl_context ); | |
eglDestroySurface ( egl_display, egl_surface ); | |
eglTerminate ( egl_display ); | |
XDestroyWindow ( x_display, win ); | |
XCloseDisplay ( x_display ); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
all: egl | |
egl: egl.cpp | |
g++ -lX11 -lEGL -lGLESv2 egl.cpp -o egl |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment