Put X11 and EGL into the kernel leaving ES 2.0 only in driver
[cilux] / src / platform / linux / kernelplat.c
index a018dfd..d3f3db4 100644 (file)
@@ -26,247 +26,414 @@ static void set_timeval_ms(struct timeval* t, int ms);
 
 /* -------------------------------------------------------------------------- */
 
+static Window        x11Window   = 0;
+static Display*      x11Display  = 0;
+static long          x11Screen   = 0;
+static XVisualInfo*  x11Visual   = 0;
+static Colormap      x11Colormap = 0;
+static EGLNativeDisplayType eglX11Display = 0;
+static EGLNativeWindowType  eglX11Window  = 0;
+static EGLDisplay           eglDisplay    = 0;
+static EGLConfig            eglConfig     = 0;
+static EGLSurface           eglSurface    = 0;
+static EGLContext           eglContext    = 0;
+
+/* -------------------------------------------------------------------------- */
+
+static int create_gl_window();
+static int getX11Display(int windowwidth, int windowheight);
+static int setUpEGL();
+static void checkX11Events();
+
+/* -------------------------------------------------------------------------- */
+
 void init_thread(void)
 {
-       signal(SIGTERM, signal_terminate);
-       signal(SIGINT,  signal_terminate);
-       signal(SIGQUIT, signal_terminate);
-       signal(SIGALRM, signal_alarm);
-       signal(SIGPIPE, signal_other);
-       signal(SIGCHLD, SIG_IGN);
-       signal(SIGHUP,  SIG_IGN);
-       signal(SIGUSR1, SIG_IGN);
-       signal(SIGUSR2, SIG_IGN);
+    signal(SIGTERM, signal_terminate);
+    signal(SIGINT,  signal_terminate);
+    signal(SIGQUIT, signal_terminate);
+    signal(SIGALRM, signal_alarm);
+    signal(SIGPIPE, signal_other);
+    signal(SIGCHLD, SIG_IGN);
+    signal(SIGHUP,  SIG_IGN);
+    signal(SIGUSR1, SIG_IGN);
+    signal(SIGUSR2, SIG_IGN);
 }
 
 void init_gl(void)
 {
+    create_gl_window();
 }
 
 void init_net(void)
 {
-       FD_ZERO(&rd_fd_set);
-       FD_ZERO(&wr_fd_set);
-       FD_ZERO(&ex_fd_set);
+    FD_ZERO(&rd_fd_set);
+    FD_ZERO(&wr_fd_set);
+    FD_ZERO(&ex_fd_set);
 }
 
 /* -------------------------------------------------------------------------- */
 
 OTHER_THREAD void signal_terminate(int signum)
 {
-       c_running(0);
+    c_running(0);
 }
 
 OTHER_THREAD void signal_alarm(int signum)
 {
-       c_signal(signum);
+    c_signal(signum);
 }
 
 OTHER_THREAD void signal_other(int signum)
 {
-       c_signal(signum);
+    c_signal(signum);
 }
 
 /* -------------------------------------------------------------------------- */
 
 void set_callback(k_channel* chan, int rdwr)
 {
-       if(rdwr & SETCB_RD) FD_SET(chan->priv->SOCK, &rd_fd_set);
-       if(rdwr & SETCB_WR) FD_SET(chan->priv->SOCK, &wr_fd_set);
+    if(rdwr & SETCB_RD) FD_SET(chan->priv->SOCK, &rd_fd_set);
+    if(rdwr & SETCB_WR) FD_SET(chan->priv->SOCK, &wr_fd_set);
 }
 
 void un_set_callback(k_channel* chan, int rdwr)
 {
-       if(rdwr & SETCB_RD) FD_CLR(chan->priv->SOCK, &rd_fd_set);
-       if(rdwr & SETCB_WR) FD_CLR(chan->priv->SOCK, &wr_fd_set);
+    if(rdwr & SETCB_RD) FD_CLR(chan->priv->SOCK, &rd_fd_set);
+    if(rdwr & SETCB_WR) FD_CLR(chan->priv->SOCK, &wr_fd_set);
 }
 
 void poller(int no_block)
 {
-       fd_set rd=rd_fd_set;
-       fd_set wr=wr_fd_set;
-       fd_set ex=ex_fd_set;
-
-       k_channel* chan;
-
-       int highest=0;
-       for(chan=k_channels; chan; chan=chan->next){
-               if(chan->priv->state==CHAN_CLOSE) continue;
-               if(highest < chan->priv->SOCK) highest=chan->priv->SOCK;
-       }
-
-       struct timeval  t;
-       struct timeval* tp=&t;
-       set_timeval_ms(tp, no_block? 0: LOOP_TICK);
-
-       if(highest==0){
-               select(0, 0, 0, 0, tp);
-               next_keys();
-               if(!no_block) do_regular_things();
-               return;
-       }
-
-       int len=select(highest+1, &rd, &wr, &ex, tp);
-       GETERRNO(len);
-
-       next_keys();
-
-       if(len==0){
-               do_regular_things();
-               return;
-       }
-       if(len== -1){
-               if(ERRNO==INTERRUPTED) return;
-               log_net_err("select", ERRNO);
-               sleep(1);
-               do_regular_things();
-               return;
-       }
-
-       for(chan=k_channels; chan; chan=chan->next){
-               if(FD_ISSET(chan->priv->SOCK, &ex)){
-                       exception_socket(chan);
-                       continue;
-               }
-               if(FD_ISSET(chan->priv->SOCK, &wr)){
-                       int err; socklen_t len=sizeof(int);
-                       if(getsockopt(chan->priv->SOCK,
-                                     SOL_SOCKET,
-                                     SO_ERROR, &err, &len) || err){
-                               exception_socket(chan);
-                               continue;
-                       }
-                       else{
-                               writeable_socket(chan);
-                       }
-               }
-               if(FD_ISSET(chan->priv->SOCK, &rd)){
-                       readable_socket(chan);
-               }
-       }
+    fd_set rd=rd_fd_set;
+    fd_set wr=wr_fd_set;
+    fd_set ex=ex_fd_set;
+
+    k_channel* chan;
+
+    int highest=0;
+    for(chan=k_channels; chan; chan=chan->next){
+        if(chan->priv->state==CHAN_CLOSE) continue;
+        if(highest < chan->priv->SOCK) highest=chan->priv->SOCK;
+    }
+
+    struct timeval  t;
+    struct timeval* tp=&t;
+    set_timeval_ms(tp, no_block? 0: LOOP_TICK);
+
+    if(highest==0){
+        select(0, 0, 0, 0, tp);
+        next_keys();
+        if(!no_block) do_regular_things();
+        return;
+    }
+
+    int len=select(highest+1, &rd, &wr, &ex, tp);
+    GETERRNO(len);
+
+    checkX11Events();
+    next_keys();
+
+    if(len==0){
+        do_regular_things();
+        return;
+    }
+    if(len== -1){
+        if(ERRNO==INTERRUPTED) return;
+        log_net_err("select", ERRNO);
+        sleep(1);
+        do_regular_things();
+        return;
+    }
+
+    for(chan=k_channels; chan; chan=chan->next){
+        if(FD_ISSET(chan->priv->SOCK, &ex)){
+            exception_socket(chan);
+            continue;
+        }
+        if(FD_ISSET(chan->priv->SOCK, &wr)){
+            int err; socklen_t len=sizeof(int);
+            if(getsockopt(chan->priv->SOCK,
+                          SOL_SOCKET,
+                          SO_ERROR, &err, &len) || err){
+                exception_socket(chan);
+                continue;
+            }
+            else{
+                writeable_socket(chan);
+            }
+        }
+        if(FD_ISSET(chan->priv->SOCK, &rd)){
+            readable_socket(chan);
+        }
+    }
 }
 
 void set_timeval_ms(struct timeval* t, int ms)
 {
-       t->tv_sec=ms/1000;
-       t->tv_usec=(ms-(t->tv_sec)*1000)*1000;
+    t->tv_sec=ms/1000;
+    t->tv_usec=(ms-(t->tv_sec)*1000)*1000;
 }
 
 char* str_error(int e)
 {
-       return strerror(e);
+    return strerror(e);
 }
 
 /* -------------------------------------------------------------------------- */
 
 void stat_only(char* fullname, k_stat* kstat)
 {
-       kstat->type=0;
-       struct stat s;
-       if(stat(fullname, &s)) return;
-       kstat->type=s.st_mode & 0170000;
-       kstat->size=s.st_size;
-       kstat->time=s.st_mtime;
-       kstat->perm=s.st_mode & 0007777;
+    kstat->type=0;
+    struct stat s;
+    if(stat(fullname, &s)) return;
+    kstat->type=s.st_mode & 0170000;
+    kstat->size=s.st_size;
+    kstat->time=s.st_mtime;
+    kstat->perm=s.st_mode & 0007777;
 }
 
 FILE_T stat_open(char* fullname, k_stat* kstat)
 {
-       stat_only(fullname, kstat);
-       if(!kstat->type) return 0;
-       FILE_T filehandle=open(fullname, O_RDONLY);
-       if(filehandle<0) return 0;
-       return filehandle;
+    stat_only(fullname, kstat);
+    if(!kstat->type) return 0;
+    FILE_T filehandle=open(fullname, O_RDONLY);
+    if(filehandle<0) return 0;
+    return filehandle;
 }
 
 FILE_T open_only(char* fullname, int wr)
 {
-       int rw=wr? O_RDWR|O_CREAT|O_TRUNC: O_RDONLY;
-       FILE_T filehandle=open(fullname, rw, 0644);
-       if(filehandle<0) return 0;
-       return filehandle;
+    int rw=wr? O_RDWR|O_CREAT|O_TRUNC: O_RDONLY;
+    FILE_T filehandle=open(fullname, rw, 0644);
+    if(filehandle<0) return 0;
+    return filehandle;
 }
 
 void* mmap_malloc(void* s, size_t size, int prot, int f, char* fullname, int o)
 {
-       FILE_T fh=open(fullname, O_RDONLY, 0644);
-       if(fh<0) return MAP_FAILED;
-
-       char* data=k_malloc(size);
-       int charsread=0;
-       int len;
-       do{
-               len=read(fh, data+charsread, size-charsread);
-               if(len< 0 && FERRNO(len)==EINTR) continue;
-               if(len<=0) break;
-               charsread+=len;
-       } while(charsread<size);
-
-       close(fh);
-       if(len<0 || charsread!=size){ k_free(data); return MAP_FAILED; }
-       return data;
+    FILE_T fh=open(fullname, O_RDONLY, 0644);
+    if(fh<0) return MAP_FAILED;
+
+    char* data=k_malloc(size);
+    int charsread=0;
+    int len;
+    do{
+        len=read(fh, data+charsread, size-charsread);
+        if(len< 0 && FERRNO(len)==EINTR) continue;
+        if(len<=0) break;
+        charsread+=len;
+    } while(charsread<size);
+
+    close(fh);
+    if(len<0 || charsread!=size){ k_free(data); return MAP_FAILED; }
+    return data;
 }
 
 void* mmap_name(void* s, size_t size, int prot, int f, char* fullname, int o)
 {
-       if(!size) return MAP_FAILED;
-       int w=(prot & PROT_WRITE);
-       FILE_T fh=open(fullname, (w? O_RDWR|O_CREAT: O_RDONLY), 0644);
-       if(fh<0) return MAP_FAILED;
-       return mmap(s, size, prot, f, fh, o);
+    if(!size) return MAP_FAILED;
+    int w=(prot & PROT_WRITE);
+    FILE_T fh=open(fullname, (w? O_RDWR|O_CREAT: O_RDONLY), 0644);
+    if(fh<0) return MAP_FAILED;
+    return mmap(s, size, prot, f, fh, o);
 }
 
 /* -------------------------------------------------------------------------- */
 
 EXPORT void k_random_bytes(char* buf, size_t size)
 {
-       *(short*)buf=getpid();
-       if(size!=2) k_log_err("Linux randomness not implemented yet!");
+    *(short*)buf=getpid();
+    if(size!=2) k_log_err("Linux randomness not implemented yet!");
 }
 
 /* -------------------------------------------------------------------------- */
 
 EXPORT void* k_malloc(size_t size)
 {
-       void* p=malloc(size);
-       if(!p){
-               k_fatal(OOM_STRING);
-       }
-       return p;
+    void* p=malloc(size);
+    if(!p){
+        k_fatal(OOM_STRING);
+    }
+    return p;
 }
 
 EXPORT void* k_realloc(void* o, size_t size)
 {
-       void* p=realloc(o, size);
-       if(!p){
-               k_fatal(OOM_STRING);
-       }
-       return p;
+    void* p=realloc(o, size);
+    if(!p){
+        k_fatal(OOM_STRING);
+    }
+    return p;
 }
 
 EXPORT void k_free(void* o)
 {
-       if(o) free(o);
+    if(o) free(o);
 }
 
 EXPORT char* k_strdup(char* s)
 {
-       if(!s) return 0;
-       char* p=strdup(s);
-       if(!p){
-               k_fatal(OOM_STRING);
-       }
-       return p;
+    if(!s) return 0;
+    char* p=strdup(s);
+    if(!p){
+        k_fatal(OOM_STRING);
+    }
+    return p;
 }
 
 EXPORT void* k_memdup(void* s, size_t size)
 {
-       void* p=malloc(size);
-       if(!p){
-               k_fatal(OOM_STRING);
-       }
-       memcpy(p, s, size);
-       return p;
+    void* p=malloc(size);
+    if(!p){
+        k_fatal(OOM_STRING);
+    }
+    memcpy(p, s, size);
+    return p;
+}
+
+/* ------------------------------------------------------------- */
+
+#define WINDOW_WIDTH  640
+#define WINDOW_HEIGHT 480
+
+int create_gl_window()
+{
+    if(!getX11Display(WINDOW_WIDTH, WINDOW_HEIGHT)) return 0;
+    if(!setUpEGL())                                 return 0;
+    return 1;
+}
+
+/* ------------------------------------------------------------- */
+
+int getX11Display(int windowwidth, int windowheight)
+{
+    x11Display = XOpenDisplay(0);
+
+    if(!x11Display) {
+        printf("Error: Unable to open X display\n");
+        return 0;
+    }
+
+    x11Screen = XDefaultScreen(x11Display);
+    Window rootWindow = RootWindow(x11Display, x11Screen);
+    int depth = DefaultDepth(x11Display, x11Screen);
+    x11Visual = malloc(sizeof(XVisualInfo));
+    XMatchVisualInfo(x11Display, x11Screen, depth, TrueColor, x11Visual);
+
+    if(!x11Visual) {
+        printf("Error: Unable to acquire visual\n");
+        return 0;
+    }
+
+    x11Colormap = XCreateColormap(x11Display, rootWindow, x11Visual->visual, AllocNone);
+    XSetWindowAttributes XSWA;
+    XSWA.colormap = x11Colormap;
+    XSWA.event_mask = StructureNotifyMask | ExposureMask |
+                      ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask;
+    unsigned int cwmask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
+
+    x11Window = XCreateWindow(x11Display, RootWindow(x11Display, x11Screen), 0, 0, windowwidth, windowheight,
+                              0, CopyFromParent, InputOutput, CopyFromParent, cwmask, &XSWA);
+    XMapWindow(x11Display, x11Window);
+    XFlush(x11Display);
+
+    eglX11Display = (EGLNativeDisplayType)x11Display;
+    eglX11Window  = (EGLNativeWindowType) x11Window;
+
+    return 1;
+}
+
+void cleanupX11()
+{
+    if(x11Window)   XDestroyWindow(x11Display, x11Window);
+    if(x11Colormap) XFreeColormap( x11Display, x11Colormap);
+    if(x11Display)  XCloseDisplay( x11Display);
+}
+
+void checkX11Events()
+{
+    int nm = XPending(x11Display);
+    int m;
+    for(m=0; m< nm; m++) {
+        XEvent event;
+        XNextEvent(x11Display, &event);
+        switch(event.type){
+            case ButtonPress:
+            break;
+            case KeyPress:
+                c_key((unsigned char)event.xkey.keycode, 1);
+            break;
+            default:
+            break;
+        }
+    }
+}
+
+/* -------------------------------------------------------------------------- */
+
+int isEGLError(char* where)
+{
+    EGLint err = eglGetError();
+    if(err != EGL_SUCCESS) {
+        printf("EGL failed at %s (%d).\n", where, err);
+        return 1;
+    }
+    return 0;
+}
+
+int setUpEGL()
+{
+    eglDisplay = eglGetDisplay(eglX11Display);
+
+    EGLint iMajorVersion, iMinorVersion;
+    if(!eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion)) {
+        printf("Error: eglInitialize() failed.\n");
+        return 0;
+    }
+
+    EGLint pi32ConfigAttribs[5];
+    pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;
+    pi32ConfigAttribs[1] = EGL_WINDOW_BIT;
+    pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE;
+    pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT;    
+    pi32ConfigAttribs[4] = EGL_NONE;
+
+    EGLint pi32ContextAttribs[3];
+    pi32ContextAttribs[0] = EGL_CONTEXT_CLIENT_VERSION;
+    pi32ContextAttribs[1] = 2;
+    pi32ContextAttribs[2] = EGL_NONE;
+
+    int iConfigs;
+    if(!eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) {
+        printf("Error: eglChooseConfig() failed.\n");
+        return 0;
+    }
+
+    eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, eglX11Window, NULL);
+    if(isEGLError("eglCreateWindowSurface")) return 0;
+
+    eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, pi32ContextAttribs);
+    if(isEGLError("eglCreateContext")) return 0;
+
+    eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
+    if(isEGLError("eglMakeCurrent")) return 0;
+
+    return 1;
+}
+
+/* -------------------------------------------------------------------------- */
+
+EXPORT void k_gl_swap_buffers(void)
+{
+    eglSwapBuffers(eglDisplay, eglSurface);
+}
+
+EXPORT void k_gl_end(void)
+{
+    eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglTerminate(eglDisplay);
 }
 
 /* -------------------------------------------------------------------------- */