+ 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);