app/internal/egl: move EGL interface to its own package

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-11-28 15:03:13 +01:00
parent 9528a6e0d4
commit 99b6ad09e5
8 changed files with 230 additions and 203 deletions
@@ -2,7 +2,7 @@
// +build linux windows freebsd
package window
package egl
import (
"errors"
@@ -13,22 +13,22 @@ import (
"gioui.org/app/internal/gl"
)
type context struct {
type Context struct {
c *gl.Functions
driver eglDriver
driver Driver
eglCtx *eglContext
eglWin _EGLNativeWindowType
eglWin NativeWindowType
eglSurf _EGLSurface
width, height int
// For sRGB emulation.
srgbFBO *gl.SRGBFBO
}
type eglDriver interface {
eglDisplay() _EGLNativeDisplayType
eglWindow(visID int) (_EGLNativeWindowType, int, int, error)
eglDestroy()
needVSync() bool
type Driver interface {
EGLDisplay() NativeDisplayType
EGLWindow(visID int) (NativeWindowType, int, int, error)
EGLDestroy()
NeedVSync() bool
}
type eglContext struct {
@@ -44,7 +44,7 @@ var (
nilEGLSurface _EGLSurface
nilEGLContext _EGLContext
nilEGLConfig _EGLConfig
nilEGLNativeWindowType _EGLNativeWindowType
nilEGLNativeWindowType NativeWindowType
)
const (
@@ -66,7 +66,7 @@ const (
_EGL_WINDOW_BIT = 0x4
)
func (c *context) Release() {
func (c *Context) Release() {
if c.srgbFBO != nil {
c.srgbFBO.Release()
c.srgbFBO = nil
@@ -80,12 +80,12 @@ func (c *context) Release() {
c.eglCtx = nil
}
if c.driver != nil {
c.driver.eglDestroy()
c.driver.EGLDestroy()
c.driver = nil
}
}
func (c *context) Present() error {
func (c *Context) Present() error {
if c.eglWin == nilEGLNativeWindowType {
panic("context is not active")
}
@@ -101,12 +101,12 @@ func (c *context) Present() error {
return nil
}
func newContext(d eglDriver) (*context, error) {
eglCtx, err := createContext(d.eglDisplay())
func NewContext(d Driver) (*Context, error) {
eglCtx, err := createContext(d.EGLDisplay())
if err != nil {
return nil, err
}
c := &context{
c := &Context{
driver: d,
eglCtx: eglCtx,
c: new(gl.Functions),
@@ -114,15 +114,15 @@ func newContext(d eglDriver) (*context, error) {
return c, nil
}
func (c *context) Functions() *gl.Functions {
func (c *Context) Functions() *gl.Functions {
return c.c
}
func (c *context) Lock() {}
func (c *Context) Lock() {}
func (c *context) Unlock() {}
func (c *Context) Unlock() {}
func (c *context) destroySurface() {
func (c *Context) destroySurface() {
if c.eglSurf == nilEGLSurface {
return
}
@@ -133,8 +133,8 @@ func (c *context) destroySurface() {
c.eglSurf = nilEGLSurface
}
func (c *context) MakeCurrent() error {
win, width, height, err := c.driver.eglWindow(int(c.eglCtx.visualID))
func (c *Context) MakeCurrent() error {
win, width, height, err := c.driver.EGLWindow(int(c.eglCtx.visualID))
if err != nil {
return err
}
@@ -160,7 +160,7 @@ func (c *context) MakeCurrent() error {
// eglSwapInterval 1 leads to erratic frame rates and unnecessary blocking.
// We rely on platform specific frame rate limiting instead, except on Windows
// and X11 where eglSwapInterval is all there is.
if c.driver.needVSync() {
if c.driver.NeedVSync() {
eglSwapInterval(c.eglCtx.disp, 1)
} else {
eglSwapInterval(c.eglCtx.disp, 0)
@@ -192,7 +192,7 @@ func hasExtension(exts []string, ext string) bool {
return false
}
func createContext(disp _EGLNativeDisplayType) (*eglContext, error) {
func createContext(disp NativeDisplayType) (*eglContext, error) {
eglDisp := eglGetDisplay(disp)
if eglDisp == nilEGLDisplay {
return nil, fmt.Errorf("eglGetDisplay(_EGL_DEFAULT_DISPLAY) failed: 0x%x", eglGetError())
@@ -258,7 +258,7 @@ func createContext(disp _EGLNativeDisplayType) (*eglContext, error) {
}, nil
}
func createSurfaceAndMakeCurrent(eglCtx *eglContext, win _EGLNativeWindowType) (_EGLSurface, error) {
func createSurfaceAndMakeCurrent(eglCtx *eglContext, win NativeWindowType) (_EGLSurface, error) {
var surfAttribs []_EGLint
if eglCtx.srgb {
surfAttribs = append(surfAttribs, _EGL_GL_COLORSPACE_KHR, _EGL_GL_COLORSPACE_SRGB_KHR)
@@ -2,7 +2,7 @@
// +build linux freebsd
package window
package egl
/*
#cgo LDFLAGS: -lEGL
@@ -17,13 +17,13 @@ package window
import "C"
type (
_EGLint = C.EGLint
_EGLDisplay = C.EGLDisplay
_EGLConfig = C.EGLConfig
_EGLContext = C.EGLContext
_EGLSurface = C.EGLSurface
_EGLNativeDisplayType = C.EGLNativeDisplayType
_EGLNativeWindowType = C.EGLNativeWindowType
_EGLint = C.EGLint
_EGLDisplay = C.EGLDisplay
_EGLConfig = C.EGLConfig
_EGLContext = C.EGLContext
_EGLSurface = C.EGLSurface
NativeDisplayType = C.EGLNativeDisplayType
NativeWindowType = C.EGLNativeWindowType
)
func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) {
@@ -88,11 +88,11 @@ func eglQueryString(disp _EGLDisplay, name _EGLint) string {
return C.GoString(C.eglQueryString(disp, name))
}
func eglGetDisplay(disp _EGLNativeDisplayType) _EGLDisplay {
func eglGetDisplay(disp NativeDisplayType) _EGLDisplay {
return C.eglGetDisplay(disp)
}
func eglCreateWindowSurface(disp _EGLDisplay, conf _EGLConfig, win _EGLNativeWindowType, attribs []_EGLint) _EGLSurface {
func eglCreateWindowSurface(disp _EGLDisplay, conf _EGLConfig, win NativeWindowType, attribs []_EGLint) _EGLSurface {
eglSurf := C.eglCreateWindowSurface(disp, conf, win, &attribs[0])
return eglSurf
}
+151
View File
@@ -0,0 +1,151 @@
// SPDX-License-Identifier: Unlicense OR MIT
package egl
import (
"os"
"runtime"
"unsafe"
syscall "golang.org/x/sys/windows"
"gioui.org/app/internal/gl"
)
type (
_EGLint int32
_EGLDisplay uintptr
_EGLConfig uintptr
_EGLContext uintptr
_EGLSurface uintptr
NativeDisplayType uintptr
NativeWindowType uintptr
)
var (
libEGL = syscall.NewLazyDLL("libEGL.dll")
_eglChooseConfig = libEGL.NewProc("eglChooseConfig")
_eglCreateContext = libEGL.NewProc("eglCreateContext")
_eglCreateWindowSurface = libEGL.NewProc("eglCreateWindowSurface")
_eglDestroyContext = libEGL.NewProc("eglDestroyContext")
_eglDestroySurface = libEGL.NewProc("eglDestroySurface")
_eglGetConfigAttrib = libEGL.NewProc("eglGetConfigAttrib")
_eglGetDisplay = libEGL.NewProc("eglGetDisplay")
_eglGetError = libEGL.NewProc("eglGetError")
_eglInitialize = libEGL.NewProc("eglInitialize")
_eglMakeCurrent = libEGL.NewProc("eglMakeCurrent")
_eglReleaseThread = libEGL.NewProc("eglReleaseThread")
_eglSwapInterval = libEGL.NewProc("eglSwapInterval")
_eglSwapBuffers = libEGL.NewProc("eglSwapBuffers")
_eglTerminate = libEGL.NewProc("eglTerminate")
_eglQueryString = libEGL.NewProc("eglQueryString")
)
func init() {
mustLoadDLL(libEGL, "libEGL.dll")
mustLoadDLL(gl.LibGLESv2, "libGLESv2.dll")
// d3dcompiler_47.dll is needed internally for shader compilation to function.
mustLoadDLL(syscall.NewLazyDLL("d3dcompiler_47.dll"), "d3dcompiler_47.dll")
}
func mustLoadDLL(dll *syscall.LazyDLL, name string) {
loadErr := dll.Load()
if loadErr == nil {
return
}
pmsg := syscall.StringToUTF16Ptr("Failed to load " + name + ". Gio requires the ANGLE OpenGL ES driver to run. A prebuilt version can be downloaded from https://gioui.org/doc/install.")
ptitle := syscall.StringToUTF16Ptr("Error")
syscall.MessageBox(0 /* HWND */, pmsg, ptitle, syscall.MB_ICONERROR|syscall.MB_SYSTEMMODAL)
os.Exit(1)
}
func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) {
var cfg _EGLConfig
var ncfg _EGLint
a := &attribs[0]
r, _, _ := _eglChooseConfig.Call(uintptr(disp), uintptr(unsafe.Pointer(a)), uintptr(unsafe.Pointer(&cfg)), 1, uintptr(unsafe.Pointer(&ncfg)))
issue34474KeepAlive(a)
return cfg, r != 0
}
func eglCreateContext(disp _EGLDisplay, cfg _EGLConfig, shareCtx _EGLContext, attribs []_EGLint) _EGLContext {
a := &attribs[0]
c, _, _ := _eglCreateContext.Call(uintptr(disp), uintptr(cfg), uintptr(shareCtx), uintptr(unsafe.Pointer(a)))
issue34474KeepAlive(a)
return _EGLContext(c)
}
func eglCreateWindowSurface(disp _EGLDisplay, cfg _EGLConfig, win NativeWindowType, attribs []_EGLint) _EGLSurface {
a := &attribs[0]
s, _, _ := _eglCreateWindowSurface.Call(uintptr(disp), uintptr(cfg), uintptr(win), uintptr(unsafe.Pointer(a)))
issue34474KeepAlive(a)
return _EGLSurface(s)
}
func eglDestroySurface(disp _EGLDisplay, surf _EGLSurface) bool {
r, _, _ := _eglDestroySurface.Call(uintptr(disp), uintptr(surf))
return r != 0
}
func eglDestroyContext(disp _EGLDisplay, ctx _EGLContext) bool {
r, _, _ := _eglDestroyContext.Call(uintptr(disp), uintptr(ctx))
return r != 0
}
func eglGetConfigAttrib(disp _EGLDisplay, cfg _EGLConfig, attr _EGLint) (_EGLint, bool) {
var val uintptr
r, _, _ := _eglGetConfigAttrib.Call(uintptr(disp), uintptr(cfg), uintptr(attr), uintptr(unsafe.Pointer(&val)))
return _EGLint(val), r != 0
}
func eglGetDisplay(disp NativeDisplayType) _EGLDisplay {
d, _, _ := _eglGetDisplay.Call(uintptr(disp))
return _EGLDisplay(d)
}
func eglGetError() _EGLint {
e, _, _ := _eglGetError.Call()
return _EGLint(e)
}
func eglInitialize(disp _EGLDisplay) (_EGLint, _EGLint, bool) {
var maj, min uintptr
r, _, _ := _eglInitialize.Call(uintptr(disp), uintptr(unsafe.Pointer(&maj)), uintptr(unsafe.Pointer(&min)))
return _EGLint(maj), _EGLint(min), r != 0
}
func eglMakeCurrent(disp _EGLDisplay, draw, read _EGLSurface, ctx _EGLContext) bool {
r, _, _ := _eglMakeCurrent.Call(uintptr(disp), uintptr(draw), uintptr(read), uintptr(ctx))
return r != 0
}
func eglReleaseThread() bool {
r, _, _ := _eglReleaseThread.Call()
return r != 0
}
func eglSwapInterval(disp _EGLDisplay, interval _EGLint) bool {
r, _, _ := _eglSwapInterval.Call(uintptr(disp), uintptr(interval))
return r != 0
}
func eglSwapBuffers(disp _EGLDisplay, surf _EGLSurface) bool {
r, _, _ := _eglSwapBuffers.Call(uintptr(disp), uintptr(surf))
return r != 0
}
func eglTerminate(disp _EGLDisplay) bool {
r, _, _ := _eglTerminate.Call(uintptr(disp))
return r != 0
}
func eglQueryString(disp _EGLDisplay, name _EGLint) string {
r, _, _ := _eglQueryString.Call(uintptr(disp), uintptr(name))
return gl.GoString(gl.SliceOf(r))
}
// issue34474KeepAlive calls runtime.KeepAlive as a
// workaround for golang.org/issue/34474.
func issue34474KeepAlive(v interface{}) {
runtime.KeepAlive(v)
}
+13 -7
View File
@@ -6,22 +6,28 @@ package window
#include <EGL/egl.h>
*/
import "C"
import "gioui.org/app/internal/gl"
func (w *window) eglDestroy() {
import (
"unsafe"
"gioui.org/app/internal/egl"
"gioui.org/app/internal/gl"
)
func (w *window) EGLDestroy() {
}
func (w *window) eglDisplay() _EGLNativeDisplayType {
func (w *window) EGLDisplay() egl.NativeDisplayType {
return nil
}
func (w *window) eglWindow(visID int) (_EGLNativeWindowType, int, int, error) {
func (w *window) EGLWindow(visID int) (egl.NativeWindowType, int, int, error) {
win, width, height := w.nativeWindow(visID)
return _EGLNativeWindowType(win), width, height, nil
return egl.NativeWindowType(unsafe.Pointer(win)), width, height, nil
}
func (w *window) NewContext() (gl.Context, error) {
return newContext(w)
return egl.NewContext(w)
}
func (w *window) needVSync() bool { return false }
func (w *window) NeedVSync() bool { return false }
+10 -9
View File
@@ -9,6 +9,7 @@ import (
"sync"
"unsafe"
"gioui.org/app/internal/egl"
"gioui.org/app/internal/gl"
)
@@ -26,7 +27,7 @@ var eglWindows struct {
windows map[*C.struct_wl_surface]*C.struct_wl_egl_window
}
func (w *window) eglDestroy() {
func (w *window) EGLDestroy() {
surf, _, _ := w.surface()
if surf == nil {
return
@@ -39,14 +40,14 @@ func (w *window) eglDestroy() {
}
}
func (w *window) eglDisplay() _EGLNativeDisplayType {
return _EGLNativeDisplayType(unsafe.Pointer(w.display()))
func (w *window) EGLDisplay() egl.NativeDisplayType {
return egl.NativeDisplayType(unsafe.Pointer(w.display()))
}
func (w *window) eglWindow(visID int) (_EGLNativeWindowType, int, int, error) {
func (w *window) EGLWindow(visID int) (egl.NativeWindowType, int, int, error) {
surf, width, height := w.surface()
if surf == nil {
return nilEGLNativeWindowType, 0, 0, errors.New("wayland: no surface")
return 0, 0, 0, errors.New("wayland: no surface")
}
eglWindows.mu.Lock()
defer eglWindows.mu.Unlock()
@@ -57,16 +58,16 @@ func (w *window) eglWindow(visID int) (_EGLNativeWindowType, int, int, error) {
}
eglWin = C.wl_egl_window_create(surf, C.int(width), C.int(height))
if eglWin == nil {
return nilEGLNativeWindowType, 0, 0, errors.New("wayland: wl_egl_create_window failed")
return 0, 0, 0, errors.New("wayland: wl_egl_create_window failed")
}
eglWindows.windows[surf] = eglWin
}
C.wl_egl_window_resize(eglWin, C.int(width), C.int(height), 0, 0)
return _EGLNativeWindowType(uintptr(unsafe.Pointer(eglWin))), width, height, nil
return egl.NativeWindowType(uintptr(unsafe.Pointer(eglWin))), width, height, nil
}
func (w *window) NewContext() (gl.Context, error) {
return newContext(w)
return egl.NewContext(w)
}
func (w *window) needVSync() bool { return false }
func (w *window) NeedVSync() bool { return false }
+8 -144
View File
@@ -3,160 +3,24 @@
package window
import (
"os"
"unsafe"
syscall "golang.org/x/sys/windows"
"gioui.org/app/internal/egl"
"gioui.org/app/internal/gl"
)
type (
_EGLint int32
_EGLDisplay uintptr
_EGLConfig uintptr
_EGLContext uintptr
_EGLSurface uintptr
_EGLNativeDisplayType uintptr
_EGLNativeWindowType uintptr
)
var (
libEGL = syscall.NewLazyDLL("libEGL.dll")
_eglChooseConfig = libEGL.NewProc("eglChooseConfig")
_eglCreateContext = libEGL.NewProc("eglCreateContext")
_eglCreateWindowSurface = libEGL.NewProc("eglCreateWindowSurface")
_eglDestroyContext = libEGL.NewProc("eglDestroyContext")
_eglDestroySurface = libEGL.NewProc("eglDestroySurface")
_eglGetConfigAttrib = libEGL.NewProc("eglGetConfigAttrib")
_eglGetDisplay = libEGL.NewProc("eglGetDisplay")
_eglGetError = libEGL.NewProc("eglGetError")
_eglInitialize = libEGL.NewProc("eglInitialize")
_eglMakeCurrent = libEGL.NewProc("eglMakeCurrent")
_eglReleaseThread = libEGL.NewProc("eglReleaseThread")
_eglSwapInterval = libEGL.NewProc("eglSwapInterval")
_eglSwapBuffers = libEGL.NewProc("eglSwapBuffers")
_eglTerminate = libEGL.NewProc("eglTerminate")
_eglQueryString = libEGL.NewProc("eglQueryString")
)
func init() {
mustLoadDLL(libEGL, "libEGL.dll")
mustLoadDLL(gl.LibGLESv2, "libGLESv2.dll")
// d3dcompiler_47.dll is needed internally for shader compilation to function.
mustLoadDLL(syscall.NewLazyDLL("d3dcompiler_47.dll"), "d3dcompiler_47.dll")
func (w *window) EGLDestroy() {
}
func mustLoadDLL(dll *syscall.LazyDLL, name string) {
loadErr := dll.Load()
if loadErr == nil {
return
}
pmsg := syscall.StringToUTF16Ptr("Failed to load " + name + ". Gio requires the ANGLE OpenGL ES driver to run. A prebuilt version can be downloaded from https://gioui.org/doc/install.")
ptitle := syscall.StringToUTF16Ptr("Error")
syscall.MessageBox(0 /* HWND */, pmsg, ptitle, syscall.MB_ICONERROR|syscall.MB_SYSTEMMODAL)
os.Exit(1)
func (w *window) EGLDisplay() egl.NativeDisplayType {
return egl.NativeDisplayType(w.HDC())
}
func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) {
var cfg _EGLConfig
var ncfg _EGLint
a := &attribs[0]
r, _, _ := _eglChooseConfig.Call(uintptr(disp), uintptr(unsafe.Pointer(a)), uintptr(unsafe.Pointer(&cfg)), 1, uintptr(unsafe.Pointer(&ncfg)))
issue34474KeepAlive(a)
return cfg, r != 0
}
func eglCreateContext(disp _EGLDisplay, cfg _EGLConfig, shareCtx _EGLContext, attribs []_EGLint) _EGLContext {
a := &attribs[0]
c, _, _ := _eglCreateContext.Call(uintptr(disp), uintptr(cfg), uintptr(shareCtx), uintptr(unsafe.Pointer(a)))
issue34474KeepAlive(a)
return _EGLContext(c)
}
func eglCreateWindowSurface(disp _EGLDisplay, cfg _EGLConfig, win _EGLNativeWindowType, attribs []_EGLint) _EGLSurface {
a := &attribs[0]
s, _, _ := _eglCreateWindowSurface.Call(uintptr(disp), uintptr(cfg), uintptr(win), uintptr(unsafe.Pointer(a)))
issue34474KeepAlive(a)
return _EGLSurface(s)
}
func eglDestroySurface(disp _EGLDisplay, surf _EGLSurface) bool {
r, _, _ := _eglDestroySurface.Call(uintptr(disp), uintptr(surf))
return r != 0
}
func eglDestroyContext(disp _EGLDisplay, ctx _EGLContext) bool {
r, _, _ := _eglDestroyContext.Call(uintptr(disp), uintptr(ctx))
return r != 0
}
func eglGetConfigAttrib(disp _EGLDisplay, cfg _EGLConfig, attr _EGLint) (_EGLint, bool) {
var val uintptr
r, _, _ := _eglGetConfigAttrib.Call(uintptr(disp), uintptr(cfg), uintptr(attr), uintptr(unsafe.Pointer(&val)))
return _EGLint(val), r != 0
}
func eglGetDisplay(disp _EGLNativeDisplayType) _EGLDisplay {
d, _, _ := _eglGetDisplay.Call(uintptr(disp))
return _EGLDisplay(d)
}
func eglGetError() _EGLint {
e, _, _ := _eglGetError.Call()
return _EGLint(e)
}
func eglInitialize(disp _EGLDisplay) (_EGLint, _EGLint, bool) {
var maj, min uintptr
r, _, _ := _eglInitialize.Call(uintptr(disp), uintptr(unsafe.Pointer(&maj)), uintptr(unsafe.Pointer(&min)))
return _EGLint(maj), _EGLint(min), r != 0
}
func eglMakeCurrent(disp _EGLDisplay, draw, read _EGLSurface, ctx _EGLContext) bool {
r, _, _ := _eglMakeCurrent.Call(uintptr(disp), uintptr(draw), uintptr(read), uintptr(ctx))
return r != 0
}
func eglReleaseThread() bool {
r, _, _ := _eglReleaseThread.Call()
return r != 0
}
func eglSwapInterval(disp _EGLDisplay, interval _EGLint) bool {
r, _, _ := _eglSwapInterval.Call(uintptr(disp), uintptr(interval))
return r != 0
}
func eglSwapBuffers(disp _EGLDisplay, surf _EGLSurface) bool {
r, _, _ := _eglSwapBuffers.Call(uintptr(disp), uintptr(surf))
return r != 0
}
func eglTerminate(disp _EGLDisplay) bool {
r, _, _ := _eglTerminate.Call(uintptr(disp))
return r != 0
}
func eglQueryString(disp _EGLDisplay, name _EGLint) string {
r, _, _ := _eglQueryString.Call(uintptr(disp), uintptr(name))
return gl.GoString(gl.SliceOf(r))
}
func (w *window) eglDestroy() {
}
func (w *window) eglDisplay() _EGLNativeDisplayType {
return _EGLNativeDisplayType(w.HDC())
}
func (w *window) eglWindow(visID int) (_EGLNativeWindowType, int, int, error) {
func (w *window) EGLWindow(visID int) (egl.NativeWindowType, int, int, error) {
hwnd, width, height := w.HWND()
return _EGLNativeWindowType(hwnd), width, height, nil
return egl.NativeWindowType(hwnd), width, height, nil
}
func (w *window) NewContext() (gl.Context, error) {
return newContext(w)
return egl.NewContext(w)
}
func (w *window) needVSync() bool { return true }
func (w *window) NeedVSync() bool { return true }
+11 -8
View File
@@ -4,21 +4,24 @@
package window
import "gioui.org/app/internal/gl"
import (
"gioui.org/app/internal/egl"
"gioui.org/app/internal/gl"
)
func (w *x11Window) NewContext() (gl.Context, error) {
return newContext(w)
return egl.NewContext(w)
}
func (w *x11Window) eglDestroy() {
func (w *x11Window) EGLDestroy() {
}
func (w *x11Window) eglDisplay() _EGLNativeDisplayType {
return _EGLNativeDisplayType(w.display())
func (w *x11Window) EGLDisplay() egl.NativeDisplayType {
return egl.NativeDisplayType(w.display())
}
func (w *x11Window) eglWindow(visID int) (_EGLNativeWindowType, int, int, error) {
return _EGLNativeWindowType(uintptr(w.xw)), w.width, w.height, nil
func (w *x11Window) EGLWindow(visID int) (egl.NativeWindowType, int, int, error) {
return egl.NativeWindowType(uintptr(w.xw)), w.width, w.height, nil
}
func (w *x11Window) needVSync() bool { return true }
func (w *x11Window) NeedVSync() bool { return true }
+2
View File
@@ -41,6 +41,8 @@ import (
/*
#cgo LDFLAGS: -lwayland-client -lwayland-cursor
#cgo freebsd CFLAGS: -I/usr/local/include
#cgo freebsd LDFLAGS: -L/usr/local/lib
#include <stdlib.h>
#include <wayland-client.h>