github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/exp/shiny/driver/gldriver/x11.c (about) 1 // Copyright 2015 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 <stdio.h> 10 #include <stdlib.h> 11 12 EGLConfig e_config; 13 EGLContext e_ctx; 14 EGLDisplay e_dpy; 15 Colormap x_colormap; 16 Display *x_dpy; 17 XVisualInfo *x_visual_info; 18 Window x_root; 19 20 char * 21 eglGetErrorStr() { 22 switch (eglGetError()) { 23 case EGL_SUCCESS: 24 return "EGL_SUCCESS"; 25 case EGL_NOT_INITIALIZED: 26 return "EGL_NOT_INITIALIZED"; 27 case EGL_BAD_ACCESS: 28 return "EGL_BAD_ACCESS"; 29 case EGL_BAD_ALLOC: 30 return "EGL_BAD_ALLOC"; 31 case EGL_BAD_ATTRIBUTE: 32 return "EGL_BAD_ATTRIBUTE"; 33 case EGL_BAD_CONFIG: 34 return "EGL_BAD_CONFIG"; 35 case EGL_BAD_CONTEXT: 36 return "EGL_BAD_CONTEXT"; 37 case EGL_BAD_CURRENT_SURFACE: 38 return "EGL_BAD_CURRENT_SURFACE"; 39 case EGL_BAD_DISPLAY: 40 return "EGL_BAD_DISPLAY"; 41 case EGL_BAD_MATCH: 42 return "EGL_BAD_MATCH"; 43 case EGL_BAD_NATIVE_PIXMAP: 44 return "EGL_BAD_NATIVE_PIXMAP"; 45 case EGL_BAD_NATIVE_WINDOW: 46 return "EGL_BAD_NATIVE_WINDOW"; 47 case EGL_BAD_PARAMETER: 48 return "EGL_BAD_PARAMETER"; 49 case EGL_BAD_SURFACE: 50 return "EGL_BAD_SURFACE"; 51 case EGL_CONTEXT_LOST: 52 return "EGL_CONTEXT_LOST"; 53 } 54 return "unknown EGL error"; 55 } 56 57 void 58 startDriver() { 59 x_dpy = XOpenDisplay(NULL); 60 if (!x_dpy) { 61 fprintf(stderr, "XOpenDisplay failed\n"); 62 exit(1); 63 } 64 e_dpy = eglGetDisplay(x_dpy); 65 if (!e_dpy) { 66 fprintf(stderr, "eglGetDisplay failed: %s\n", eglGetErrorStr()); 67 exit(1); 68 } 69 EGLint e_major, e_minor; 70 if (!eglInitialize(e_dpy, &e_major, &e_minor)) { 71 fprintf(stderr, "eglInitialize failed: %s\n", eglGetErrorStr()); 72 exit(1); 73 } 74 if (!eglBindAPI(EGL_OPENGL_ES_API)) { 75 fprintf(stderr, "eglBindAPI failed: %s\n", eglGetErrorStr()); 76 exit(1); 77 } 78 79 static const EGLint attribs[] = { 80 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 81 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 82 EGL_BLUE_SIZE, 8, 83 EGL_GREEN_SIZE, 8, 84 EGL_RED_SIZE, 8, 85 EGL_DEPTH_SIZE, 16, 86 EGL_CONFIG_CAVEAT, EGL_NONE, 87 EGL_NONE 88 }; 89 EGLint num_configs; 90 if (!eglChooseConfig(e_dpy, attribs, &e_config, 1, &num_configs)) { 91 fprintf(stderr, "eglChooseConfig failed: %s\n", eglGetErrorStr()); 92 exit(1); 93 } 94 EGLint vid; 95 if (!eglGetConfigAttrib(e_dpy, e_config, EGL_NATIVE_VISUAL_ID, &vid)) { 96 fprintf(stderr, "eglGetConfigAttrib failed: %s\n", eglGetErrorStr()); 97 exit(1); 98 } 99 100 XVisualInfo visTemplate; 101 visTemplate.visualid = vid; 102 int num_visuals; 103 x_visual_info = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals); 104 if (!x_visual_info) { 105 fprintf(stderr, "XGetVisualInfo failed\n"); 106 exit(1); 107 } 108 109 x_root = RootWindow(x_dpy, DefaultScreen(x_dpy)); 110 x_colormap = XCreateColormap(x_dpy, x_root, x_visual_info->visual, AllocNone); 111 if (!x_colormap) { 112 fprintf(stderr, "XCreateColormap failed\n"); 113 exit(1); 114 } 115 116 static const EGLint ctx_attribs[] = { 117 EGL_CONTEXT_CLIENT_VERSION, 2, 118 EGL_NONE 119 }; 120 e_ctx = eglCreateContext(e_dpy, e_config, EGL_NO_CONTEXT, ctx_attribs); 121 if (!e_ctx) { 122 fprintf(stderr, "eglCreateContext failed: %s\n", eglGetErrorStr()); 123 exit(1); 124 } 125 } 126 127 void 128 processEvents() { 129 while (XPending(x_dpy)) { 130 XEvent ev; 131 XNextEvent(x_dpy, &ev); 132 switch (ev.type) { 133 case ButtonPress: 134 case ButtonRelease: 135 onMouse(ev.xbutton.window, ev.xbutton.x, ev.xbutton.y, ev.xbutton.state, ev.xbutton.button, 136 ev.type == ButtonPress ? 1 : 2); 137 break; 138 case MotionNotify: 139 onMouse(ev.xmotion.window, ev.xmotion.x, ev.xmotion.y, ev.xmotion.state, 0, 0); 140 break; 141 case Expose: 142 // A non-zero Count means that there are more expose events coming. For 143 // example, a non-rectangular exposure (e.g. from a partially overlapped 144 // window) will result in multiple expose events whose dirty rectangles 145 // combine to define the dirty region. Go's paint events do not provide 146 // dirty regions, so we only pass on the final X11 expose event. 147 if (ev.xexpose.count == 0) { 148 onExpose(ev.xexpose.window); 149 } 150 break; 151 case ConfigureNotify: 152 onResize(ev.xconfigure.window, ev.xconfigure.width, ev.xconfigure.height); 153 break; 154 } 155 } 156 } 157 158 void 159 makeCurrent(uintptr_t surface) { 160 EGLSurface surf = (EGLSurface)(surface); 161 if (!eglMakeCurrent(e_dpy, surf, surf, e_ctx)) { 162 fprintf(stderr, "eglMakeCurrent failed: %s\n", eglGetErrorStr()); 163 exit(1); 164 } 165 } 166 167 void 168 swapBuffers(uintptr_t surface) { 169 EGLSurface surf = (EGLSurface)(surface); 170 if (!eglSwapBuffers(e_dpy, surf)) { 171 fprintf(stderr, "eglSwapBuffers failed: %s\n", eglGetErrorStr()); 172 exit(1); 173 } 174 } 175 176 uintptr_t 177 doNewWindow(int width, int height) { 178 XSetWindowAttributes attr; 179 attr.colormap = x_colormap; 180 attr.event_mask = 181 ButtonPressMask | 182 ButtonReleaseMask | 183 PointerMotionMask | 184 ButtonMotionMask | 185 ExposureMask | 186 StructureNotifyMask; 187 Window win = XCreateWindow( 188 x_dpy, x_root, 0, 0, width, height, 0, x_visual_info->depth, InputOutput, 189 x_visual_info->visual, CWColormap | CWEventMask, &attr); 190 XSizeHints sizehints; 191 sizehints.width = width; 192 sizehints.height = height; 193 sizehints.flags = USSize; 194 XSetNormalHints(x_dpy, win, &sizehints); 195 XSetStandardProperties(x_dpy, win, "App", "App", None, (char **)NULL, 0, &sizehints); 196 return win; 197 } 198 199 uintptr_t 200 doShowWindow(uintptr_t id) { 201 Window win = (Window)(id); 202 XMapWindow(x_dpy, win); 203 EGLSurface surf = eglCreateWindowSurface(e_dpy, e_config, win, NULL); 204 if (!surf) { 205 fprintf(stderr, "eglCreateWindowSurface failed: %s\n", eglGetErrorStr()); 206 exit(1); 207 } 208 return (uintptr_t)(surf); 209 }