SimpleGL example

Line 266: Line 266:
         return 0;
         return 0;
  }
  }
 +
 +
[[Category:Development]]
 +
[[Category:Fremantle]]

Revision as of 14:54, 11 February 2010

/* 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;
}