aboutsummaryrefslogtreecommitdiff
path: root/vendor/gioui.org/internal/egl
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gioui.org/internal/egl')
-rw-r--r--vendor/gioui.org/internal/egl/egl.go253
-rw-r--r--vendor/gioui.org/internal/egl/egl_unix.go109
-rw-r--r--vendor/gioui.org/internal/egl/egl_windows.go169
3 files changed, 531 insertions, 0 deletions
diff --git a/vendor/gioui.org/internal/egl/egl.go b/vendor/gioui.org/internal/egl/egl.go
new file mode 100644
index 0000000..7d7b551
--- /dev/null
+++ b/vendor/gioui.org/internal/egl/egl.go
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build linux || windows || freebsd || openbsd
+// +build linux windows freebsd openbsd
+
+package egl
+
+import (
+ "errors"
+ "fmt"
+ "runtime"
+ "strings"
+
+ "gioui.org/gpu"
+)
+
+type Context struct {
+ disp _EGLDisplay
+ eglCtx *eglContext
+ eglSurf _EGLSurface
+ width, height int
+}
+
+type eglContext struct {
+ config _EGLConfig
+ ctx _EGLContext
+ visualID int
+ srgb bool
+ surfaceless bool
+}
+
+var (
+ nilEGLDisplay _EGLDisplay
+ nilEGLSurface _EGLSurface
+ nilEGLContext _EGLContext
+ nilEGLConfig _EGLConfig
+ EGL_DEFAULT_DISPLAY NativeDisplayType
+)
+
+const (
+ _EGL_ALPHA_SIZE = 0x3021
+ _EGL_BLUE_SIZE = 0x3022
+ _EGL_CONFIG_CAVEAT = 0x3027
+ _EGL_CONTEXT_CLIENT_VERSION = 0x3098
+ _EGL_DEPTH_SIZE = 0x3025
+ _EGL_GL_COLORSPACE_KHR = 0x309d
+ _EGL_GL_COLORSPACE_SRGB_KHR = 0x3089
+ _EGL_GREEN_SIZE = 0x3023
+ _EGL_EXTENSIONS = 0x3055
+ _EGL_NATIVE_VISUAL_ID = 0x302e
+ _EGL_NONE = 0x3038
+ _EGL_OPENGL_ES2_BIT = 0x4
+ _EGL_RED_SIZE = 0x3024
+ _EGL_RENDERABLE_TYPE = 0x3040
+ _EGL_SURFACE_TYPE = 0x3033
+ _EGL_WINDOW_BIT = 0x4
+)
+
+func (c *Context) Release() {
+ c.ReleaseSurface()
+ if c.eglCtx != nil {
+ eglDestroyContext(c.disp, c.eglCtx.ctx)
+ c.eglCtx = nil
+ }
+ c.disp = nilEGLDisplay
+}
+
+func (c *Context) Present() error {
+ if !eglSwapBuffers(c.disp, c.eglSurf) {
+ return fmt.Errorf("eglSwapBuffers failed (%x)", eglGetError())
+ }
+ return nil
+}
+
+func NewContext(disp NativeDisplayType) (*Context, error) {
+ if err := loadEGL(); err != nil {
+ return nil, err
+ }
+ eglDisp := eglGetDisplay(disp)
+ // eglGetDisplay can return EGL_NO_DISPLAY yet no error
+ // (EGL_SUCCESS), in which case a default EGL display might be
+ // available.
+ if eglDisp == nilEGLDisplay {
+ eglDisp = eglGetDisplay(EGL_DEFAULT_DISPLAY)
+ }
+ if eglDisp == nilEGLDisplay {
+ return nil, fmt.Errorf("eglGetDisplay failed: 0x%x", eglGetError())
+ }
+ eglCtx, err := createContext(eglDisp)
+ if err != nil {
+ return nil, err
+ }
+ c := &Context{
+ disp: eglDisp,
+ eglCtx: eglCtx,
+ }
+ return c, nil
+}
+
+func (c *Context) RenderTarget() (gpu.RenderTarget, error) {
+ return gpu.OpenGLRenderTarget{}, nil
+}
+
+func (c *Context) API() gpu.API {
+ return gpu.OpenGL{}
+}
+
+func (c *Context) ReleaseSurface() {
+ if c.eglSurf == nilEGLSurface {
+ return
+ }
+ // Make sure any in-flight GL commands are complete.
+ eglWaitClient()
+ c.ReleaseCurrent()
+ eglDestroySurface(c.disp, c.eglSurf)
+ c.eglSurf = nilEGLSurface
+}
+
+func (c *Context) VisualID() int {
+ return c.eglCtx.visualID
+}
+
+func (c *Context) CreateSurface(win NativeWindowType, width, height int) error {
+ eglSurf, err := createSurface(c.disp, c.eglCtx, win)
+ c.eglSurf = eglSurf
+ c.width = width
+ c.height = height
+ return err
+}
+
+func (c *Context) ReleaseCurrent() {
+ if c.disp != nilEGLDisplay {
+ eglMakeCurrent(c.disp, nilEGLSurface, nilEGLSurface, nilEGLContext)
+ }
+}
+
+func (c *Context) MakeCurrent() error {
+ // OpenGL contexts are implicit and thread-local. Lock the OS thread.
+ runtime.LockOSThread()
+
+ if c.eglSurf == nilEGLSurface && !c.eglCtx.surfaceless {
+ return errors.New("no surface created yet EGL_KHR_surfaceless_context is not supported")
+ }
+ if !eglMakeCurrent(c.disp, c.eglSurf, c.eglSurf, c.eglCtx.ctx) {
+ return fmt.Errorf("eglMakeCurrent error 0x%x", eglGetError())
+ }
+ return nil
+}
+
+func (c *Context) EnableVSync(enable bool) {
+ if enable {
+ eglSwapInterval(c.disp, 1)
+ } else {
+ eglSwapInterval(c.disp, 0)
+ }
+}
+
+func hasExtension(exts []string, ext string) bool {
+ for _, e := range exts {
+ if ext == e {
+ return true
+ }
+ }
+ return false
+}
+
+func createContext(disp _EGLDisplay) (*eglContext, error) {
+ major, minor, ret := eglInitialize(disp)
+ if !ret {
+ return nil, fmt.Errorf("eglInitialize failed: 0x%x", eglGetError())
+ }
+ // sRGB framebuffer support on EGL 1.5 or if EGL_KHR_gl_colorspace is supported.
+ exts := strings.Split(eglQueryString(disp, _EGL_EXTENSIONS), " ")
+ srgb := major > 1 || minor >= 5 || hasExtension(exts, "EGL_KHR_gl_colorspace")
+ attribs := []_EGLint{
+ _EGL_RENDERABLE_TYPE, _EGL_OPENGL_ES2_BIT,
+ _EGL_SURFACE_TYPE, _EGL_WINDOW_BIT,
+ _EGL_BLUE_SIZE, 8,
+ _EGL_GREEN_SIZE, 8,
+ _EGL_RED_SIZE, 8,
+ _EGL_CONFIG_CAVEAT, _EGL_NONE,
+ }
+ if srgb {
+ if runtime.GOOS == "linux" || runtime.GOOS == "android" {
+ // Some Mesa drivers crash if an sRGB framebuffer is requested without alpha.
+ // https://bugs.freedesktop.org/show_bug.cgi?id=107782.
+ //
+ // Also, some Android devices (Samsung S9) need alpha for sRGB to work.
+ attribs = append(attribs, _EGL_ALPHA_SIZE, 8)
+ }
+ }
+ attribs = append(attribs, _EGL_NONE)
+ eglCfg, ret := eglChooseConfig(disp, attribs)
+ if !ret {
+ return nil, fmt.Errorf("eglChooseConfig failed: 0x%x", eglGetError())
+ }
+ if eglCfg == nilEGLConfig {
+ supportsNoCfg := hasExtension(exts, "EGL_KHR_no_config_context")
+ if !supportsNoCfg {
+ return nil, errors.New("eglChooseConfig returned no configs")
+ }
+ }
+ var visID _EGLint
+ if eglCfg != nilEGLConfig {
+ var ok bool
+ visID, ok = eglGetConfigAttrib(disp, eglCfg, _EGL_NATIVE_VISUAL_ID)
+ if !ok {
+ return nil, errors.New("newContext: eglGetConfigAttrib for _EGL_NATIVE_VISUAL_ID failed")
+ }
+ }
+ ctxAttribs := []_EGLint{
+ _EGL_CONTEXT_CLIENT_VERSION, 3,
+ _EGL_NONE,
+ }
+ eglCtx := eglCreateContext(disp, eglCfg, nilEGLContext, ctxAttribs)
+ if eglCtx == nilEGLContext {
+ // Fall back to OpenGL ES 2 and rely on extensions.
+ ctxAttribs := []_EGLint{
+ _EGL_CONTEXT_CLIENT_VERSION, 2,
+ _EGL_NONE,
+ }
+ eglCtx = eglCreateContext(disp, eglCfg, nilEGLContext, ctxAttribs)
+ if eglCtx == nilEGLContext {
+ return nil, fmt.Errorf("eglCreateContext failed: 0x%x", eglGetError())
+ }
+ }
+ return &eglContext{
+ config: _EGLConfig(eglCfg),
+ ctx: _EGLContext(eglCtx),
+ visualID: int(visID),
+ srgb: srgb,
+ surfaceless: hasExtension(exts, "EGL_KHR_surfaceless_context"),
+ }, nil
+}
+
+func createSurface(disp _EGLDisplay, eglCtx *eglContext, win NativeWindowType) (_EGLSurface, error) {
+ var surfAttribs []_EGLint
+ if eglCtx.srgb {
+ surfAttribs = append(surfAttribs, _EGL_GL_COLORSPACE_KHR, _EGL_GL_COLORSPACE_SRGB_KHR)
+ }
+ surfAttribs = append(surfAttribs, _EGL_NONE)
+ eglSurf := eglCreateWindowSurface(disp, eglCtx.config, win, surfAttribs)
+ if eglSurf == nilEGLSurface && eglCtx.srgb {
+ // Try again without sRGB.
+ eglCtx.srgb = false
+ surfAttribs = []_EGLint{_EGL_NONE}
+ eglSurf = eglCreateWindowSurface(disp, eglCtx.config, win, surfAttribs)
+ }
+ if eglSurf == nilEGLSurface {
+ return nilEGLSurface, fmt.Errorf("newContext: eglCreateWindowSurface failed 0x%x (sRGB=%v)", eglGetError(), eglCtx.srgb)
+ }
+ return eglSurf, nil
+}
diff --git a/vendor/gioui.org/internal/egl/egl_unix.go b/vendor/gioui.org/internal/egl/egl_unix.go
new file mode 100644
index 0000000..bd3efa5
--- /dev/null
+++ b/vendor/gioui.org/internal/egl/egl_unix.go
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build linux || freebsd || openbsd
+// +build linux freebsd openbsd
+
+package egl
+
+/*
+#cgo linux,!android pkg-config: egl
+#cgo freebsd openbsd android LDFLAGS: -lEGL
+#cgo freebsd CFLAGS: -I/usr/local/include
+#cgo freebsd LDFLAGS: -L/usr/local/lib
+#cgo openbsd CFLAGS: -I/usr/X11R6/include
+#cgo openbsd LDFLAGS: -L/usr/X11R6/lib
+#cgo CFLAGS: -DEGL_NO_X11
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+*/
+import "C"
+
+type (
+ _EGLint = C.EGLint
+ _EGLDisplay = C.EGLDisplay
+ _EGLConfig = C.EGLConfig
+ _EGLContext = C.EGLContext
+ _EGLSurface = C.EGLSurface
+ NativeDisplayType = C.EGLNativeDisplayType
+ NativeWindowType = C.EGLNativeWindowType
+)
+
+func loadEGL() error {
+ return nil
+}
+
+func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) {
+ var cfg C.EGLConfig
+ var ncfg C.EGLint
+ if C.eglChooseConfig(disp, &attribs[0], &cfg, 1, &ncfg) != C.EGL_TRUE {
+ return nilEGLConfig, false
+ }
+ return _EGLConfig(cfg), true
+}
+
+func eglCreateContext(disp _EGLDisplay, cfg _EGLConfig, shareCtx _EGLContext, attribs []_EGLint) _EGLContext {
+ ctx := C.eglCreateContext(disp, cfg, shareCtx, &attribs[0])
+ return _EGLContext(ctx)
+}
+
+func eglDestroySurface(disp _EGLDisplay, surf _EGLSurface) bool {
+ return C.eglDestroySurface(disp, surf) == C.EGL_TRUE
+}
+
+func eglDestroyContext(disp _EGLDisplay, ctx _EGLContext) bool {
+ return C.eglDestroyContext(disp, ctx) == C.EGL_TRUE
+}
+
+func eglGetConfigAttrib(disp _EGLDisplay, cfg _EGLConfig, attr _EGLint) (_EGLint, bool) {
+ var val _EGLint
+ ret := C.eglGetConfigAttrib(disp, cfg, attr, &val)
+ return val, ret == C.EGL_TRUE
+}
+
+func eglGetError() _EGLint {
+ return C.eglGetError()
+}
+
+func eglInitialize(disp _EGLDisplay) (_EGLint, _EGLint, bool) {
+ var maj, min _EGLint
+ ret := C.eglInitialize(disp, &maj, &min)
+ return maj, min, ret == C.EGL_TRUE
+}
+
+func eglMakeCurrent(disp _EGLDisplay, draw, read _EGLSurface, ctx _EGLContext) bool {
+ return C.eglMakeCurrent(disp, draw, read, ctx) == C.EGL_TRUE
+}
+
+func eglReleaseThread() bool {
+ return C.eglReleaseThread() == C.EGL_TRUE
+}
+
+func eglSwapBuffers(disp _EGLDisplay, surf _EGLSurface) bool {
+ return C.eglSwapBuffers(disp, surf) == C.EGL_TRUE
+}
+
+func eglSwapInterval(disp _EGLDisplay, interval _EGLint) bool {
+ return C.eglSwapInterval(disp, interval) == C.EGL_TRUE
+}
+
+func eglTerminate(disp _EGLDisplay) bool {
+ return C.eglTerminate(disp) == C.EGL_TRUE
+}
+
+func eglQueryString(disp _EGLDisplay, name _EGLint) string {
+ return C.GoString(C.eglQueryString(disp, name))
+}
+
+func eglGetDisplay(disp NativeDisplayType) _EGLDisplay {
+ return C.eglGetDisplay(disp)
+}
+
+func eglCreateWindowSurface(disp _EGLDisplay, conf _EGLConfig, win NativeWindowType, attribs []_EGLint) _EGLSurface {
+ eglSurf := C.eglCreateWindowSurface(disp, conf, win, &attribs[0])
+ return eglSurf
+}
+
+func eglWaitClient() bool {
+ return C.eglWaitClient() == C.EGL_TRUE
+}
diff --git a/vendor/gioui.org/internal/egl/egl_windows.go b/vendor/gioui.org/internal/egl/egl_windows.go
new file mode 100644
index 0000000..4433dd7
--- /dev/null
+++ b/vendor/gioui.org/internal/egl/egl_windows.go
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package egl
+
+import (
+ "fmt"
+ "runtime"
+ "sync"
+ "unsafe"
+
+ syscall "golang.org/x/sys/windows"
+
+ "gioui.org/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")
+ _eglWaitClient = libEGL.NewProc("eglWaitClient")
+)
+
+var loadOnce sync.Once
+
+func loadEGL() error {
+ var err error
+ loadOnce.Do(func() {
+ err = loadDLLs()
+ })
+ return err
+}
+
+func loadDLLs() error {
+ if err := loadDLL(libEGL, "libEGL.dll"); err != nil {
+ return err
+ }
+ if err := loadDLL(gl.LibGLESv2, "libGLESv2.dll"); err != nil {
+ return err
+ }
+ // d3dcompiler_47.dll is needed internally for shader compilation to function.
+ return loadDLL(syscall.NewLazyDLL("d3dcompiler_47.dll"), "d3dcompiler_47.dll")
+}
+
+func loadDLL(dll *syscall.LazyDLL, name string) error {
+ err := dll.Load()
+ if err != nil {
+ return fmt.Errorf("egl: failed to load %s: %v", name, err)
+ }
+ return nil
+}
+
+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 syscall.BytePtrToString((*byte)(unsafe.Pointer(r)))
+}
+
+func eglWaitClient() bool {
+ r, _, _ := _eglWaitClient.Call()
+ return r != 0
+}
+
+// issue34474KeepAlive calls runtime.KeepAlive as a
+// workaround for golang.org/issue/34474.
+func issue34474KeepAlive(v interface{}) {
+ runtime.KeepAlive(v)
+}