You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.8 KiB
Go
165 lines
4.8 KiB
Go
// SPDX-License-Identifier: Unlicense OR MIT
|
|
|
|
package egl
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"sync"
|
|
"unsafe"
|
|
|
|
syscall "golang.org/x/sys/windows"
|
|
|
|
"gioui.org/app/internal/glimpl"
|
|
gunsafe "gioui.org/internal/unsafe"
|
|
)
|
|
|
|
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")
|
|
)
|
|
|
|
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(glimpl.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 gunsafe.GoString(gunsafe.SliceOf(r))
|
|
}
|
|
|
|
// issue34474KeepAlive calls runtime.KeepAlive as a
|
|
// workaround for golang.org/issue/34474.
|
|
func issue34474KeepAlive(v interface{}) {
|
|
runtime.KeepAlive(v)
|
|
}
|