app: confine the eglWindow indirection to the Wayland backend

Only the Wayland backend needs an wl_egl_window between the wl_surface
and EGL. Move code dealing with the indirection to Wayland specific
code.

Then, introduce the eglDriver interface instead of referencing the
native window type directly. This will help when multiple backends are
supported at runtime (e.g. Wayland+X11).

Finally, move the eglDriver implementation methods from GOOS-specific
code to separate EGL-specific files, allowing EGL types to be used
directly instead of unsafe.Pointer and uinptr.

The result is simpler generic EGL code, and easier path towards X11
support.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-10-02 23:07:54 +02:00
parent 32bda106e7
commit 2dcbf6fe3c
8 changed files with 97 additions and 85 deletions
+27 -34
View File
@@ -15,16 +15,21 @@ import (
type context struct { type context struct {
c *gl.Functions c *gl.Functions
driver *window driver eglDriver
eglCtx *eglContext eglCtx *eglContext
nwindow _EGLNativeWindowType eglWin _EGLNativeWindowType
eglWin *eglWindow
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 {
eglDisplay() _EGLNativeDisplayType
eglWindow(visID int) (_EGLNativeWindowType, int, int, error)
eglDestroy()
}
type eglContext struct { type eglContext struct {
disp _EGLDisplay disp _EGLDisplay
config _EGLConfig config _EGLConfig
@@ -62,27 +67,28 @@ const (
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
} }
if c.eglSurf != nilEGLSurface { if c.eglSurf != nilEGLSurface {
eglMakeCurrent(c.eglCtx.disp, nilEGLSurface, nilEGLSurface, nilEGLContext) eglMakeCurrent(c.eglCtx.disp, nilEGLSurface, nilEGLSurface, nilEGLContext)
eglDestroySurface(c.eglCtx.disp, c.eglSurf) eglDestroySurface(c.eglCtx.disp, c.eglSurf)
c.eglSurf = nilEGLSurface c.eglSurf = nilEGLSurface
} }
if c.eglWin != nil { c.eglWin = nilEGLNativeWindowType
c.eglWin.destroy()
c.eglWin = nil
}
if c.eglCtx != nil { if c.eglCtx != nil {
eglDestroyContext(c.eglCtx.disp, c.eglCtx.ctx) eglDestroyContext(c.eglCtx.disp, c.eglCtx.ctx)
eglTerminate(c.eglCtx.disp) eglTerminate(c.eglCtx.disp)
eglReleaseThread() eglReleaseThread()
c.eglCtx = nil c.eglCtx = nil
} }
c.driver = nil if c.driver != nil {
c.driver.eglDestroy()
c.driver = nil
}
} }
func (c *context) Present() error { func (c *context) Present() error {
if c.eglWin == nil { if c.eglWin == nilEGLNativeWindowType {
panic("context is not active") panic("context is not active")
} }
if c.srgbFBO != nil { if c.srgbFBO != nil {
@@ -97,13 +103,13 @@ func (c *context) Present() error {
return nil return nil
} }
func newContext(w *window) (*context, error) { func newContext(d eglDriver) (*context, error) {
eglCtx, err := createContext(_EGLNativeDisplayType(w.display())) eglCtx, err := createContext(d.eglDisplay())
if err != nil { if err != nil {
return nil, err return nil, err
} }
c := &context{ c := &context{
driver: w, driver: d,
eglCtx: eglCtx, eglCtx: eglCtx,
c: new(gl.Functions), c: new(gl.Functions),
} }
@@ -119,9 +125,11 @@ func (c *context) Lock() {}
func (c *context) Unlock() {} func (c *context) Unlock() {}
func (c *context) MakeCurrent() error { func (c *context) MakeCurrent() error {
w, width, height := c.driver.nativeWindow(int(c.eglCtx.visualID)) win, width, height, err := c.driver.eglWindow(int(c.eglCtx.visualID))
win := _EGLNativeWindowType(w) if err != nil {
if c.nwindow == win && width == c.width && height == c.height { return err
}
if c.eglWin == win && width == c.width && height == c.height {
return nil return nil
} }
if win == nilEGLNativeWindowType { if win == nilEGLNativeWindowType {
@@ -138,29 +146,14 @@ func (c *context) MakeCurrent() error {
c.eglSurf = nilEGLSurface c.eglSurf = nilEGLSurface
} }
c.width, c.height = width, height c.width, c.height = width, height
c.nwindow = win c.eglWin = win
if c.nwindow == nilEGLNativeWindowType { if c.eglWin == nilEGLNativeWindowType {
if c.eglWin != nil {
c.eglWin.destroy()
c.eglWin = nil
}
return nil return nil
} }
if c.eglWin == nil { eglSurf, err := createSurfaceAndMakeCurrent(c.eglCtx, win)
var err error
c.eglWin, err = newEGLWindow(win, width, height)
if err != nil {
return err
}
} else {
c.eglWin.resize(width, height)
}
eglSurf, err := createSurfaceAndMakeCurrent(c.eglCtx, c.eglWin.window())
c.eglSurf = eglSurf c.eglSurf = eglSurf
if err != nil { if err != nil {
c.eglWin.destroy() c.eglWin = nilEGLNativeWindowType
c.eglWin = nil
c.nwindow = nilEGLNativeWindowType
return err return err
} }
if c.eglCtx.srgb { if c.eglCtx.srgb {
+12
View File
@@ -20,3 +20,15 @@ func eglCreateWindowSurface(disp _EGLDisplay, conf _EGLConfig, win _EGLNativeWin
eglSurf := C.eglCreateWindowSurface(disp, conf, win, &attribs[0]) eglSurf := C.eglCreateWindowSurface(disp, conf, win, &attribs[0])
return eglSurf return eglSurf
} }
func (w *window) eglDestroy() {
}
func (w *window) eglDisplay() _EGLNativeDisplayType {
return nil
}
func (w *window) eglWindow(visID int) (_EGLNativeWindowType, int, int, error) {
win, width, height := w.nativeWindow(visID)
return _EGLNativeWindowType(win), width, height, nil
}
+36 -17
View File
@@ -6,7 +6,7 @@ package app
import ( import (
"errors" "errors"
"unsafe" "sync"
) )
/* /*
@@ -24,29 +24,48 @@ type (
_EGLNativeWindowType = C.EGLNativeWindowType _EGLNativeWindowType = C.EGLNativeWindowType
) )
type eglWindow struct { var eglWindows struct {
w *C.struct_wl_egl_window mu sync.Mutex
windows map[*C.struct_wl_surface]*C.struct_wl_egl_window
} }
func newEGLWindow(w _EGLNativeWindowType, width, height int) (*eglWindow, error) { func (w *window) eglDestroy() {
surf := (*C.struct_wl_surface)(unsafe.Pointer(w)) surf, _, _ := w.surface()
win := C.wl_egl_window_create(surf, C.int(width), C.int(height)) if surf == nil {
if win == nil { return
return nil, errors.New("wl_egl_create_window failed") }
eglWindows.mu.Lock()
defer eglWindows.mu.Unlock()
if eglWin, ok := eglWindows.windows[surf]; ok {
C.wl_egl_window_destroy(eglWin)
delete(eglWindows.windows, surf)
} }
return &eglWindow{win}, nil
} }
func (w *eglWindow) window() _EGLNativeWindowType { func (w *window) eglDisplay() _EGLNativeDisplayType {
return w.w return w.display()
} }
func (w *eglWindow) resize(width, height int) { func (w *window) eglWindow(visID int) (_EGLNativeWindowType, int, int, error) {
C.wl_egl_window_resize(w.w, C.int(width), C.int(height), 0, 0) surf, width, height := w.surface()
} if surf == nil {
return nilEGLNativeWindowType, 0, 0, errors.New("wayland: no surface")
func (w *eglWindow) destroy() { }
C.wl_egl_window_destroy(w.w) eglWindows.mu.Lock()
defer eglWindows.mu.Unlock()
eglWin, ok := eglWindows.windows[surf]
if !ok {
if eglWindows.windows == nil {
eglWindows.windows = make(map[*C.struct_wl_surface]*C.struct_wl_egl_window)
}
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")
}
eglWindows.windows[surf] = eglWin
}
C.wl_egl_window_resize(eglWin, C.int(width), C.int(height), 0, 0)
return eglWin, width, height, nil
} }
func eglGetDisplay(disp _EGLNativeDisplayType) _EGLDisplay { func eglGetDisplay(disp _EGLNativeDisplayType) _EGLDisplay {
-20
View File
@@ -1,20 +0,0 @@
// SPDX-License-Identifier: Unlicense OR MIT
// +build android windows
package app
type eglWindow struct {
w _EGLNativeWindowType
}
func newEGLWindow(w _EGLNativeWindowType, width, height int) (*eglWindow, error) {
return &eglWindow{w}, nil
}
func (w *eglWindow) window() _EGLNativeWindowType {
return w.w
}
func (w *eglWindow) resize(width, height int) {}
func (w *eglWindow) destroy() {}
+12
View File
@@ -142,3 +142,15 @@ func eglQueryString(disp _EGLDisplay, name _EGLint) string {
r, _, _ := _eglQueryString.Call(uintptr(disp), uintptr(name)) r, _, _ := _eglQueryString.Call(uintptr(disp), uintptr(name))
return gl.GoString(gl.SliceOf(r)) 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()
return _EGLNativeWindowType(hwnd), width, height, nil
}
+2 -6
View File
@@ -245,11 +245,7 @@ func (w *window) setStage(stage Stage) {
w.event(StageEvent{stage}) w.event(StageEvent{stage})
} }
func (w *window) display() unsafe.Pointer { func (w *window) nativeWindow(visID int) (*C.ANativeWindow, int, int) {
return nil
}
func (w *window) nativeWindow(visID int) (unsafe.Pointer, int, int) {
win := w.aNativeWindow() win := w.aNativeWindow()
var width, height int var width, height int
if win != nil { if win != nil {
@@ -259,7 +255,7 @@ func (w *window) nativeWindow(visID int) (unsafe.Pointer, int, int) {
w, h := C.ANativeWindow_getWidth(win), C.ANativeWindow_getHeight(win) w, h := C.ANativeWindow_getWidth(win), C.ANativeWindow_getHeight(win)
width, height = int(w), int(h) width, height = int(w), int(h)
} }
return unsafe.Pointer(win), width, height return win, width, height
} }
func (w *window) aNativeWindow() *C.ANativeWindow { func (w *window) aNativeWindow() *C.ANativeWindow {
+4 -4
View File
@@ -1036,11 +1036,11 @@ func (w *window) setStage(s Stage) {
w.w.event(StageEvent{s}) w.w.event(StageEvent{s})
} }
func (w *window) display() unsafe.Pointer { func (w *window) display() *C.struct_wl_display {
return unsafe.Pointer(w.disp) return w.disp
} }
func (w *window) nativeWindow(visID int) (unsafe.Pointer, int, int) { func (w *window) surface() (*C.struct_wl_surface, int, int) {
w.mu.Lock() w.mu.Lock()
defer w.mu.Unlock() defer w.mu.Unlock()
if w.needAck { if w.needAck {
@@ -1052,7 +1052,7 @@ func (w *window) nativeWindow(visID int) (unsafe.Pointer, int, int) {
C.wl_surface_set_buffer_scale(w.surf, C.int32_t(scale)) C.wl_surface_set_buffer_scale(w.surf, C.int32_t(scale))
w.newScale = false w.newScale = false
} }
return unsafe.Pointer(w.surf), width * scale, height * scale return w.surf, width * scale, height * scale
} }
func (w *window) showTextInput(show bool) {} func (w *window) showTextInput(show bool) {}
+4 -4
View File
@@ -430,12 +430,12 @@ func (w *window) destroy() {
func (w *window) showTextInput(show bool) {} func (w *window) showTextInput(show bool) {}
func (w *window) display() uintptr { func (w *window) HDC() syscall.Handle {
return uintptr(w.hdc) return w.hdc
} }
func (w *window) nativeWindow(visID int) (uintptr, int, int) { func (w *window) HWND() (syscall.Handle, int, int) {
return uintptr(w.hwnd), w.width, w.height return w.hwnd, w.width, w.height
} }
func convertKeyCode(code uintptr) (rune, bool) { func convertKeyCode(code uintptr) (rune, bool) {