SimpleGL example
/* Created by exoticorn (http://talk.maemo.org/showthread.php?t=37356 */
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <math.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
const char* vertexSrc = "attribute vec4 position; varying mediump vec2 pos; uniform vec4 offset; void main() { gl_Position = position + offset; pos = position.xy; }";
const char* fragmentSrc = "varying mediump vec2 pos; uniform mediump float phase; void main() { gl_FragColor = vec4(1, 1, 1, 1) * sin((pos.x * pos.x + pos.y * pos.y) * 40.0 + phase); }";
void printShaderInfoLog(GLuint shader) {
GLint length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
if(length) {
char* buffer = new char[length];
glGetShaderInfoLog(shader, length, NULL, buffer);
printf("%s", buffer);
delete [] buffer;
GLint success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if(success != GL_TRUE) {
exit(1);
}
}
}
GLuint createShader(GLenum type, const char* pSource) {
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &pSource, NULL);
glCompileShader(shader);
printShaderInfoLog(shader);
return shader;
}
Display* dpy;
Window win;
EGLDisplay edpy;
EGLContext ectxt;
int phaseLocation;
GLfloat norm_x;
GLfloat norm_y;
GLfloat offset_x = 0.0;
GLfloat offset_y = 0.0;
GLfloat p1_pos_x;
GLfloat p1_pos_y;
GLint offset;
EGLSurface esfc;
bool update_pos = false;
const float vertexArray[] = {
-0.85, -1, 0, 1,
-1, -0.7, 0, 1,
-0.7, -0.7, 0, 1
};
void render() {
static float offset_blah = 0;
static int donesetup=0;
static XWindowAttributes gwa;
// draw
if (!donesetup) {
XWindowAttributes gwa;
XGetWindowAttributes(dpy, win, &gwa);
glViewport(0, 0, gwa.width, gwa.height);
glClearColor(0, 1, 0, 1);
donesetup = 1;
}
glClear(GL_COLOR_BUFFER_BIT);
glUniform1f(phaseLocation, offset_blah);
if (update_pos) {
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, offset_x, offset_y, 0, 0);
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, vertexArray);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
eglSwapBuffers(edpy, esfc);
offset_blah = fmodf(offset_blah + 0.5, 2*3.141f);
}
int main() {
dpy = XOpenDisplay(NULL);
if(dpy == NULL) {
printf("cannot connect to X server\n");
return 1;
}
Window root = DefaultRootWindow(dpy);
XSetWindowAttributes swa;
swa.event_mask = ExposureMask | PointerMotionMask;
win = XCreateWindow(dpy, root, 0, 0, 600, 400, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &swa);
XSetWindowAttributes xattr;
Atom atom;
int one = 1;
xattr.override_redirect = False;
XChangeWindowAttributes(dpy, win, CWOverrideRedirect, &xattr);
atom = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", True);
XChangeProperty(dpy, win, XInternAtom(dpy, "_NET_WM_STATE", True),
XA_ATOM, 32, PropModeReplace,
(unsigned char *) &atom, 1);
XChangeProperty(dpy, win, XInternAtom(dpy, "_HILDON_NON_COMPOSITED_WINDOW", True),
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &one, 1);
XMapWindow(dpy, win);
XStoreName(dpy, win, "GL test");
Atom wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
Atom fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
XEvent xev;
memset(&xev, 0, sizeof(xev));
xev.type = ClientMessage;
xev.xclient.window = win;
xev.xclient.message_type = wm_state;
xev.xclient.format = 32;
xev.xclient.data.l[0] = 1;
xev.xclient.data.l[1] = fullscreen;
XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureNotifyMask, &xev);
edpy = eglGetDisplay((EGLNativeDisplayType)dpy);
if(edpy == EGL_NO_DISPLAY) {
printf("Got no EGL display\n");
return 1;
}
if(!eglInitialize(edpy, NULL, NULL)) {
printf("Unable to initialize EGL\n");
return 1;
}
EGLint attr[] = {
EGL_BUFFER_SIZE, 16,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
EGLConfig ecfg;
EGLint num_config;
if(!eglChooseConfig(edpy, attr, &ecfg, 1, &num_config)) {
printf("Failed to choose config (%x)\n", eglGetError());
return 1;
}
if(num_config != 1) {
printf("Didn't get exactly one config, but %d\n", num_config);
return 1;
}
esfc = eglCreateWindowSurface(edpy, ecfg, (void*)win, NULL);
if(esfc == EGL_NO_SURFACE) {
printf("Unable to create EGL surface (%x)\n", eglGetError());
return 1;
}
EGLint ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
ectxt = eglCreateContext(edpy, ecfg, EGL_NO_CONTEXT, ctxattr);
if(ectxt == EGL_NO_CONTEXT) {
printf("Unable to create EGL context (%x)\n", eglGetError());
return 1;
}
eglMakeCurrent(edpy, esfc, esfc, ectxt);
GLuint shaderProgram = glCreateProgram();
GLuint vertexShader = createShader(GL_VERTEX_SHADER, vertexSrc);
GLuint fragmentShader = createShader(GL_FRAGMENT_SHADER, fragmentSrc);
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
phaseLocation = glGetUniformLocation(shaderProgram, "phase");
offset = glGetUniformLocation(shaderProgram, "offset");
if(phaseLocation < 0) {
printf("Unable to get uniform location\n");
return 1;
}
bool quit = false;
timeval startTime;
timezone tz;
gettimeofday(&startTime, &tz);
int numFrames = 0;
float window_width = 800.0;
float window_height = 480.0;
norm_x = -0.85;
norm_y = -1;
p1_pos_x = -0.85;
p1_pos_y = -1;
while(!quit) {
while(XPending(dpy)) {
XEvent xev;
XNextEvent(dpy, &xev);
if(xev.type == MotionNotify) {
//printf("move to: (%d,%d)\n", xev.xmotion.x, xev.xmotion.y);
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;
//quit = true;
}
}
render();
numFrames++;
if(numFrames % 100 == 0) {
timeval now;
gettimeofday(&now, &tz);
float delta = now.tv_sec - startTime.tv_sec + (now.tv_usec - startTime.tv_usec) * 0.000001f;
printf("fps: %f\n", numFrames / delta);
}
usleep(1000*30);
}
eglDestroyContext(edpy, ectxt);
eglDestroySurface(edpy, esfc);
eglTerminate(edpy);
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
return 0;
}