| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Go Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style | |
| 3 // license that can be found in the LICENSE file. | |
| 4 | |
| 5 // +build linux,!android | |
| 6 | |
| 7 #include "_cgo_export.h" | |
| 8 #include <EGL/egl.h> | |
| 9 #include <GLES2/gl2.h> | |
| 10 #include <X11/Xlib.h> | |
| 11 #include <stdio.h> | |
| 12 #include <stdlib.h> | |
| 13 #include <string.h> | |
| 14 | |
| 15 static Window | |
| 16 new_window(Display *x_dpy, EGLDisplay e_dpy, int w, int h, EGLContext *ctx, EGLS
urface *surf) { | |
| 17 static const EGLint attribs[] = { | |
| 18 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
| 19 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | |
| 20 EGL_BLUE_SIZE, 8, | |
| 21 EGL_GREEN_SIZE, 8, | |
| 22 EGL_RED_SIZE, 8, | |
| 23 EGL_DEPTH_SIZE, 16, | |
| 24 EGL_CONFIG_CAVEAT, EGL_NONE, | |
| 25 EGL_NONE | |
| 26 }; | |
| 27 EGLConfig config; | |
| 28 EGLint num_configs; | |
| 29 if (!eglChooseConfig(e_dpy, attribs, &config, 1, &num_configs)) { | |
| 30 fprintf(stderr, "eglChooseConfig failed\n"); | |
| 31 exit(1); | |
| 32 } | |
| 33 EGLint vid; | |
| 34 if (!eglGetConfigAttrib(e_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) { | |
| 35 fprintf(stderr, "eglGetConfigAttrib failed\n"); | |
| 36 exit(1); | |
| 37 } | |
| 38 | |
| 39 XVisualInfo visTemplate; | |
| 40 visTemplate.visualid = vid; | |
| 41 int num_visuals; | |
| 42 XVisualInfo *visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate,
&num_visuals); | |
| 43 if (!visInfo) { | |
| 44 fprintf(stderr, "XGetVisualInfo failed\n"); | |
| 45 exit(1); | |
| 46 } | |
| 47 | |
| 48 Window root = RootWindow(x_dpy, DefaultScreen(x_dpy)); | |
| 49 XSetWindowAttributes attr; | |
| 50 attr.event_mask = StructureNotifyMask | ExposureMask | | |
| 51 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask; | |
| 52 Window win = XCreateWindow( | |
| 53 x_dpy, root, 0, 0, w, h, 0, visInfo->depth, InputOutput, | |
| 54 visInfo->visual, CWEventMask, &attr); | |
| 55 XFree(visInfo); | |
| 56 | |
| 57 XSizeHints sizehints; | |
| 58 sizehints.width = w; | |
| 59 sizehints.height = h; | |
| 60 sizehints.flags = USSize; | |
| 61 XSetNormalHints(x_dpy, win, &sizehints); | |
| 62 XSetStandardProperties(x_dpy, win, "App", "App", None, (char **)NULL, 0,
&sizehints); | |
| 63 | |
| 64 static const EGLint ctx_attribs[] = { | |
| 65 EGL_CONTEXT_CLIENT_VERSION, 2, | |
| 66 EGL_NONE | |
| 67 }; | |
| 68 *ctx = eglCreateContext(e_dpy, config, EGL_NO_CONTEXT, ctx_attribs); | |
| 69 if (!*ctx) { | |
| 70 fprintf(stderr, "eglCreateContext failed\n"); | |
| 71 exit(1); | |
| 72 } | |
| 73 *surf = eglCreateWindowSurface(e_dpy, config, win, NULL); | |
| 74 if (!*surf) { | |
| 75 fprintf(stderr, "eglCreateWindowSurface failed\n"); | |
| 76 exit(1); | |
| 77 } | |
| 78 return win; | |
| 79 } | |
| 80 | |
| 81 void | |
| 82 runApp(void) { | |
| 83 Display *x_dpy = XOpenDisplay(NULL); | |
| 84 if (!x_dpy) { | |
| 85 fprintf(stderr, "XOpenDisplay failed\n"); | |
| 86 exit(1); | |
| 87 } | |
| 88 EGLDisplay e_dpy = eglGetDisplay(x_dpy); | |
| 89 if (!e_dpy) { | |
| 90 fprintf(stderr, "eglGetDisplay failed\n"); | |
| 91 exit(1); | |
| 92 } | |
| 93 EGLint e_major, e_minor; | |
| 94 if (!eglInitialize(e_dpy, &e_major, &e_minor)) { | |
| 95 fprintf(stderr, "eglInitialize failed\n"); | |
| 96 exit(1); | |
| 97 } | |
| 98 eglBindAPI(EGL_OPENGL_ES_API); | |
| 99 EGLContext e_ctx; | |
| 100 EGLSurface e_surf; | |
| 101 Window win = new_window(x_dpy, e_dpy, 400, 400, &e_ctx, &e_surf); | |
| 102 XMapWindow(x_dpy, win); | |
| 103 if (!eglMakeCurrent(e_dpy, e_surf, e_surf, e_ctx)) { | |
| 104 fprintf(stderr, "eglMakeCurrent failed\n"); | |
| 105 exit(1); | |
| 106 } | |
| 107 | |
| 108 while (1) { | |
| 109 XEvent ev; | |
| 110 XNextEvent(x_dpy, &ev); | |
| 111 switch (ev.type) { | |
| 112 case ButtonPress: | |
| 113 onTouchStart((float)ev.xbutton.x, (float)ev.xbutton.y); | |
| 114 break; | |
| 115 case ButtonRelease: | |
| 116 onTouchEnd((float)ev.xbutton.x, (float)ev.xbutton.y); | |
| 117 break; | |
| 118 case MotionNotify: | |
| 119 onTouchMove((float)ev.xmotion.x, (float)ev.xmotion.y); | |
| 120 break; | |
| 121 case Expose: | |
| 122 onDraw(); | |
| 123 eglSwapBuffers(e_dpy, e_surf); | |
| 124 | |
| 125 // TODO(nigeltao): subscribe to vblank events instead of
forcing another | |
| 126 // expose event to keep the event loop ticking over. | |
| 127 // TODO(nigeltao): no longer #include <string.h> when we
don't use memset. | |
| 128 XExposeEvent fakeEvent; | |
| 129 memset(&fakeEvent, 0, sizeof(XExposeEvent)); | |
| 130 fakeEvent.type = Expose; | |
| 131 fakeEvent.window = win; | |
| 132 XSendEvent(x_dpy, win, 0, 0, (XEvent*)&fakeEvent); | |
| 133 XFlush(x_dpy); | |
| 134 | |
| 135 break; | |
| 136 case ConfigureNotify: | |
| 137 onResize(ev.xconfigure.width, ev.xconfigure.height); | |
| 138 glViewport(0, 0, (GLint)ev.xconfigure.width, (GLint)ev.x
configure.height); | |
| 139 break; | |
| 140 } | |
| 141 } | |
| 142 } | |
| OLD | NEW |