mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-07 10:25:37 +00:00
app/internal/egl: move EGL interface to its own package
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
// +build linux windows freebsd
|
// +build linux windows freebsd
|
||||||
|
|
||||||
package window
|
package egl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -13,22 +13,22 @@ import (
|
|||||||
"gioui.org/app/internal/gl"
|
"gioui.org/app/internal/gl"
|
||||||
)
|
)
|
||||||
|
|
||||||
type context struct {
|
type Context struct {
|
||||||
c *gl.Functions
|
c *gl.Functions
|
||||||
driver eglDriver
|
driver Driver
|
||||||
eglCtx *eglContext
|
eglCtx *eglContext
|
||||||
eglWin _EGLNativeWindowType
|
eglWin NativeWindowType
|
||||||
eglSurf _EGLSurface
|
eglSurf _EGLSurface
|
||||||
width, height int
|
width, height int
|
||||||
// For sRGB emulation.
|
// For sRGB emulation.
|
||||||
srgbFBO *gl.SRGBFBO
|
srgbFBO *gl.SRGBFBO
|
||||||
}
|
}
|
||||||
|
|
||||||
type eglDriver interface {
|
type Driver interface {
|
||||||
eglDisplay() _EGLNativeDisplayType
|
EGLDisplay() NativeDisplayType
|
||||||
eglWindow(visID int) (_EGLNativeWindowType, int, int, error)
|
EGLWindow(visID int) (NativeWindowType, int, int, error)
|
||||||
eglDestroy()
|
EGLDestroy()
|
||||||
needVSync() bool
|
NeedVSync() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type eglContext struct {
|
type eglContext struct {
|
||||||
@@ -44,7 +44,7 @@ var (
|
|||||||
nilEGLSurface _EGLSurface
|
nilEGLSurface _EGLSurface
|
||||||
nilEGLContext _EGLContext
|
nilEGLContext _EGLContext
|
||||||
nilEGLConfig _EGLConfig
|
nilEGLConfig _EGLConfig
|
||||||
nilEGLNativeWindowType _EGLNativeWindowType
|
nilEGLNativeWindowType NativeWindowType
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -66,7 +66,7 @@ const (
|
|||||||
_EGL_WINDOW_BIT = 0x4
|
_EGL_WINDOW_BIT = 0x4
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *context) Release() {
|
func (c *Context) Release() {
|
||||||
if c.srgbFBO != nil {
|
if c.srgbFBO != nil {
|
||||||
c.srgbFBO.Release()
|
c.srgbFBO.Release()
|
||||||
c.srgbFBO = nil
|
c.srgbFBO = nil
|
||||||
@@ -80,12 +80,12 @@ func (c *context) Release() {
|
|||||||
c.eglCtx = nil
|
c.eglCtx = nil
|
||||||
}
|
}
|
||||||
if c.driver != nil {
|
if c.driver != nil {
|
||||||
c.driver.eglDestroy()
|
c.driver.EGLDestroy()
|
||||||
c.driver = nil
|
c.driver = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Present() error {
|
func (c *Context) Present() error {
|
||||||
if c.eglWin == nilEGLNativeWindowType {
|
if c.eglWin == nilEGLNativeWindowType {
|
||||||
panic("context is not active")
|
panic("context is not active")
|
||||||
}
|
}
|
||||||
@@ -101,12 +101,12 @@ func (c *context) Present() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContext(d eglDriver) (*context, error) {
|
func NewContext(d Driver) (*Context, error) {
|
||||||
eglCtx, err := createContext(d.eglDisplay())
|
eglCtx, err := createContext(d.EGLDisplay())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
c := &context{
|
c := &Context{
|
||||||
driver: d,
|
driver: d,
|
||||||
eglCtx: eglCtx,
|
eglCtx: eglCtx,
|
||||||
c: new(gl.Functions),
|
c: new(gl.Functions),
|
||||||
@@ -114,15 +114,15 @@ func newContext(d eglDriver) (*context, error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Functions() *gl.Functions {
|
func (c *Context) Functions() *gl.Functions {
|
||||||
return c.c
|
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 {
|
if c.eglSurf == nilEGLSurface {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -133,8 +133,8 @@ func (c *context) destroySurface() {
|
|||||||
c.eglSurf = nilEGLSurface
|
c.eglSurf = nilEGLSurface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) MakeCurrent() error {
|
func (c *Context) MakeCurrent() error {
|
||||||
win, width, height, err := c.driver.eglWindow(int(c.eglCtx.visualID))
|
win, width, height, err := c.driver.EGLWindow(int(c.eglCtx.visualID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ func (c *context) MakeCurrent() error {
|
|||||||
// eglSwapInterval 1 leads to erratic frame rates and unnecessary blocking.
|
// eglSwapInterval 1 leads to erratic frame rates and unnecessary blocking.
|
||||||
// We rely on platform specific frame rate limiting instead, except on Windows
|
// We rely on platform specific frame rate limiting instead, except on Windows
|
||||||
// and X11 where eglSwapInterval is all there is.
|
// and X11 where eglSwapInterval is all there is.
|
||||||
if c.driver.needVSync() {
|
if c.driver.NeedVSync() {
|
||||||
eglSwapInterval(c.eglCtx.disp, 1)
|
eglSwapInterval(c.eglCtx.disp, 1)
|
||||||
} else {
|
} else {
|
||||||
eglSwapInterval(c.eglCtx.disp, 0)
|
eglSwapInterval(c.eglCtx.disp, 0)
|
||||||
@@ -192,7 +192,7 @@ func hasExtension(exts []string, ext string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func createContext(disp _EGLNativeDisplayType) (*eglContext, error) {
|
func createContext(disp NativeDisplayType) (*eglContext, error) {
|
||||||
eglDisp := eglGetDisplay(disp)
|
eglDisp := eglGetDisplay(disp)
|
||||||
if eglDisp == nilEGLDisplay {
|
if eglDisp == nilEGLDisplay {
|
||||||
return nil, fmt.Errorf("eglGetDisplay(_EGL_DEFAULT_DISPLAY) failed: 0x%x", eglGetError())
|
return nil, fmt.Errorf("eglGetDisplay(_EGL_DEFAULT_DISPLAY) failed: 0x%x", eglGetError())
|
||||||
@@ -258,7 +258,7 @@ func createContext(disp _EGLNativeDisplayType) (*eglContext, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSurfaceAndMakeCurrent(eglCtx *eglContext, win _EGLNativeWindowType) (_EGLSurface, error) {
|
func createSurfaceAndMakeCurrent(eglCtx *eglContext, win NativeWindowType) (_EGLSurface, error) {
|
||||||
var surfAttribs []_EGLint
|
var surfAttribs []_EGLint
|
||||||
if eglCtx.srgb {
|
if eglCtx.srgb {
|
||||||
surfAttribs = append(surfAttribs, _EGL_GL_COLORSPACE_KHR, _EGL_GL_COLORSPACE_SRGB_KHR)
|
surfAttribs = append(surfAttribs, _EGL_GL_COLORSPACE_KHR, _EGL_GL_COLORSPACE_SRGB_KHR)
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
// +build linux freebsd
|
// +build linux freebsd
|
||||||
|
|
||||||
package window
|
package egl
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo LDFLAGS: -lEGL
|
#cgo LDFLAGS: -lEGL
|
||||||
@@ -17,13 +17,13 @@ package window
|
|||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
type (
|
type (
|
||||||
_EGLint = C.EGLint
|
_EGLint = C.EGLint
|
||||||
_EGLDisplay = C.EGLDisplay
|
_EGLDisplay = C.EGLDisplay
|
||||||
_EGLConfig = C.EGLConfig
|
_EGLConfig = C.EGLConfig
|
||||||
_EGLContext = C.EGLContext
|
_EGLContext = C.EGLContext
|
||||||
_EGLSurface = C.EGLSurface
|
_EGLSurface = C.EGLSurface
|
||||||
_EGLNativeDisplayType = C.EGLNativeDisplayType
|
NativeDisplayType = C.EGLNativeDisplayType
|
||||||
_EGLNativeWindowType = C.EGLNativeWindowType
|
NativeWindowType = C.EGLNativeWindowType
|
||||||
)
|
)
|
||||||
|
|
||||||
func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) {
|
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))
|
return C.GoString(C.eglQueryString(disp, name))
|
||||||
}
|
}
|
||||||
|
|
||||||
func eglGetDisplay(disp _EGLNativeDisplayType) _EGLDisplay {
|
func eglGetDisplay(disp NativeDisplayType) _EGLDisplay {
|
||||||
return C.eglGetDisplay(disp)
|
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])
|
eglSurf := C.eglCreateWindowSurface(disp, conf, win, &attribs[0])
|
||||||
return eglSurf
|
return eglSurf
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -6,22 +6,28 @@ package window
|
|||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
*/
|
*/
|
||||||
import "C"
|
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
|
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)
|
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) {
|
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 }
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"gioui.org/app/internal/egl"
|
||||||
"gioui.org/app/internal/gl"
|
"gioui.org/app/internal/gl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ var eglWindows struct {
|
|||||||
windows map[*C.struct_wl_surface]*C.struct_wl_egl_window
|
windows map[*C.struct_wl_surface]*C.struct_wl_egl_window
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) eglDestroy() {
|
func (w *window) EGLDestroy() {
|
||||||
surf, _, _ := w.surface()
|
surf, _, _ := w.surface()
|
||||||
if surf == nil {
|
if surf == nil {
|
||||||
return
|
return
|
||||||
@@ -39,14 +40,14 @@ func (w *window) eglDestroy() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) eglDisplay() _EGLNativeDisplayType {
|
func (w *window) EGLDisplay() egl.NativeDisplayType {
|
||||||
return _EGLNativeDisplayType(unsafe.Pointer(w.display()))
|
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()
|
surf, width, height := w.surface()
|
||||||
if surf == nil {
|
if surf == nil {
|
||||||
return nilEGLNativeWindowType, 0, 0, errors.New("wayland: no surface")
|
return 0, 0, 0, errors.New("wayland: no surface")
|
||||||
}
|
}
|
||||||
eglWindows.mu.Lock()
|
eglWindows.mu.Lock()
|
||||||
defer eglWindows.mu.Unlock()
|
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))
|
eglWin = C.wl_egl_window_create(surf, C.int(width), C.int(height))
|
||||||
if eglWin == nil {
|
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
|
eglWindows.windows[surf] = eglWin
|
||||||
}
|
}
|
||||||
C.wl_egl_window_resize(eglWin, C.int(width), C.int(height), 0, 0)
|
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) {
|
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 }
|
||||||
|
|||||||
@@ -3,160 +3,24 @@
|
|||||||
package window
|
package window
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"gioui.org/app/internal/egl"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
syscall "golang.org/x/sys/windows"
|
|
||||||
|
|
||||||
"gioui.org/app/internal/gl"
|
"gioui.org/app/internal/gl"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
func (w *window) EGLDestroy() {
|
||||||
_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 mustLoadDLL(dll *syscall.LazyDLL, name string) {
|
func (w *window) EGLDisplay() egl.NativeDisplayType {
|
||||||
loadErr := dll.Load()
|
return egl.NativeDisplayType(w.HDC())
|
||||||
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) {
|
func (w *window) EGLWindow(visID int) (egl.NativeWindowType, int, int, error) {
|
||||||
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) {
|
|
||||||
hwnd, width, height := w.HWND()
|
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) {
|
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 }
|
||||||
|
|||||||
@@ -4,21 +4,24 @@
|
|||||||
|
|
||||||
package window
|
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) {
|
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 {
|
func (w *x11Window) EGLDisplay() egl.NativeDisplayType {
|
||||||
return _EGLNativeDisplayType(w.display())
|
return egl.NativeDisplayType(w.display())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *x11Window) eglWindow(visID int) (_EGLNativeWindowType, int, int, error) {
|
func (w *x11Window) EGLWindow(visID int) (egl.NativeWindowType, int, int, error) {
|
||||||
return _EGLNativeWindowType(uintptr(w.xw)), w.width, w.height, nil
|
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 }
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ import (
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo LDFLAGS: -lwayland-client -lwayland-cursor
|
#cgo LDFLAGS: -lwayland-client -lwayland-cursor
|
||||||
|
#cgo freebsd CFLAGS: -I/usr/local/include
|
||||||
|
#cgo freebsd LDFLAGS: -L/usr/local/lib
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user