egl_windows.go raw

   1  // SPDX-License-Identifier: Unlicense OR MIT
   2  
   3  package egl
   4  
   5  import (
   6  	"fmt"
   7  	"runtime"
   8  	"sync"
   9  	"unsafe"
  10  
  11  	syscall "golang.org/x/sys/windows"
  12  
  13  	"github.com/p9c/p9/pkg/gel/gio/internal/gl"
  14  )
  15  
  16  type (
  17  	_EGLint           int32
  18  	_EGLDisplay       uintptr
  19  	_EGLConfig        uintptr
  20  	_EGLContext       uintptr
  21  	_EGLSurface       uintptr
  22  	NativeDisplayType uintptr
  23  	NativeWindowType  uintptr
  24  )
  25  
  26  var (
  27  	libEGL                  = syscall.NewLazyDLL("libEGL.dll")
  28  	_eglChooseConfig        = libEGL.NewProc("eglChooseConfig")
  29  	_eglCreateContext       = libEGL.NewProc("eglCreateContext")
  30  	_eglCreateWindowSurface = libEGL.NewProc("eglCreateWindowSurface")
  31  	_eglDestroyContext      = libEGL.NewProc("eglDestroyContext")
  32  	_eglDestroySurface      = libEGL.NewProc("eglDestroySurface")
  33  	_eglGetConfigAttrib     = libEGL.NewProc("eglGetConfigAttrib")
  34  	_eglGetDisplay          = libEGL.NewProc("eglGetDisplay")
  35  	_eglGetError            = libEGL.NewProc("eglGetError")
  36  	_eglInitialize          = libEGL.NewProc("eglInitialize")
  37  	_eglMakeCurrent         = libEGL.NewProc("eglMakeCurrent")
  38  	_eglReleaseThread       = libEGL.NewProc("eglReleaseThread")
  39  	_eglSwapInterval        = libEGL.NewProc("eglSwapInterval")
  40  	_eglSwapBuffers         = libEGL.NewProc("eglSwapBuffers")
  41  	_eglTerminate           = libEGL.NewProc("eglTerminate")
  42  	_eglQueryString         = libEGL.NewProc("eglQueryString")
  43  )
  44  
  45  var loadOnce sync.Once
  46  
  47  func loadEGL() error {
  48  	var err error
  49  	loadOnce.Do(func() {
  50  		err = loadDLLs()
  51  	})
  52  	return err
  53  }
  54  
  55  func loadDLLs() error {
  56  	if err := loadDLL(libEGL, "libEGL.dll"); err != nil {
  57  		return err
  58  	}
  59  	if err := loadDLL(gl.LibGLESv2, "libGLESv2.dll"); err != nil {
  60  		return err
  61  	}
  62  	// d3dcompiler_47.dll is needed internally for shader compilation to function.
  63  	return loadDLL(syscall.NewLazyDLL("d3dcompiler_47.dll"), "d3dcompiler_47.dll")
  64  }
  65  
  66  func loadDLL(dll *syscall.LazyDLL, name string) error {
  67  	err := dll.Load()
  68  	if err != nil {
  69  		return fmt.Errorf("egl: failed to load %s: %v", name, err)
  70  	}
  71  	return nil
  72  }
  73  
  74  func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) {
  75  	var cfg _EGLConfig
  76  	var ncfg _EGLint
  77  	a := &attribs[0]
  78  	r, _, _ := _eglChooseConfig.Call(uintptr(disp), uintptr(unsafe.Pointer(a)), uintptr(unsafe.Pointer(&cfg)), 1, uintptr(unsafe.Pointer(&ncfg)))
  79  	issue34474KeepAlive(a)
  80  	return cfg, r != 0
  81  }
  82  
  83  func eglCreateContext(disp _EGLDisplay, cfg _EGLConfig, shareCtx _EGLContext, attribs []_EGLint) _EGLContext {
  84  	a := &attribs[0]
  85  	c, _, _ := _eglCreateContext.Call(uintptr(disp), uintptr(cfg), uintptr(shareCtx), uintptr(unsafe.Pointer(a)))
  86  	issue34474KeepAlive(a)
  87  	return _EGLContext(c)
  88  }
  89  
  90  func eglCreateWindowSurface(disp _EGLDisplay, cfg _EGLConfig, win NativeWindowType, attribs []_EGLint) _EGLSurface {
  91  	a := &attribs[0]
  92  	s, _, _ := _eglCreateWindowSurface.Call(uintptr(disp), uintptr(cfg), uintptr(win), uintptr(unsafe.Pointer(a)))
  93  	issue34474KeepAlive(a)
  94  	return _EGLSurface(s)
  95  }
  96  
  97  func eglDestroySurface(disp _EGLDisplay, surf _EGLSurface) bool {
  98  	r, _, _ := _eglDestroySurface.Call(uintptr(disp), uintptr(surf))
  99  	return r != 0
 100  }
 101  
 102  func eglDestroyContext(disp _EGLDisplay, ctx _EGLContext) bool {
 103  	r, _, _ := _eglDestroyContext.Call(uintptr(disp), uintptr(ctx))
 104  	return r != 0
 105  }
 106  
 107  func eglGetConfigAttrib(disp _EGLDisplay, cfg _EGLConfig, attr _EGLint) (_EGLint, bool) {
 108  	var val uintptr
 109  	r, _, _ := _eglGetConfigAttrib.Call(uintptr(disp), uintptr(cfg), uintptr(attr), uintptr(unsafe.Pointer(&val)))
 110  	return _EGLint(val), r != 0
 111  }
 112  
 113  func eglGetDisplay(disp NativeDisplayType) _EGLDisplay {
 114  	d, _, _ := _eglGetDisplay.Call(uintptr(disp))
 115  	return _EGLDisplay(d)
 116  }
 117  
 118  func eglGetError() _EGLint {
 119  	e, _, _ := _eglGetError.Call()
 120  	return _EGLint(e)
 121  }
 122  
 123  func eglInitialize(disp _EGLDisplay) (_EGLint, _EGLint, bool) {
 124  	var maj, min uintptr
 125  	r, _, _ := _eglInitialize.Call(uintptr(disp), uintptr(unsafe.Pointer(&maj)), uintptr(unsafe.Pointer(&min)))
 126  	return _EGLint(maj), _EGLint(min), r != 0
 127  }
 128  
 129  func eglMakeCurrent(disp _EGLDisplay, draw, read _EGLSurface, ctx _EGLContext) bool {
 130  	r, _, _ := _eglMakeCurrent.Call(uintptr(disp), uintptr(draw), uintptr(read), uintptr(ctx))
 131  	return r != 0
 132  }
 133  
 134  func eglReleaseThread() bool {
 135  	r, _, _ := _eglReleaseThread.Call()
 136  	return r != 0
 137  }
 138  
 139  func eglSwapInterval(disp _EGLDisplay, interval _EGLint) bool {
 140  	r, _, _ := _eglSwapInterval.Call(uintptr(disp), uintptr(interval))
 141  	return r != 0
 142  }
 143  
 144  func eglSwapBuffers(disp _EGLDisplay, surf _EGLSurface) bool {
 145  	r, _, _ := _eglSwapBuffers.Call(uintptr(disp), uintptr(surf))
 146  	return r != 0
 147  }
 148  
 149  func eglTerminate(disp _EGLDisplay) bool {
 150  	r, _, _ := _eglTerminate.Call(uintptr(disp))
 151  	return r != 0
 152  }
 153  
 154  func eglQueryString(disp _EGLDisplay, name _EGLint) string {
 155  	r, _, _ := _eglQueryString.Call(uintptr(disp), uintptr(name))
 156  	return syscall.BytePtrToString((*byte)(unsafe.Pointer(r)))
 157  }
 158  
 159  // issue34474KeepAlive calls runtime.KeepAlive as a
 160  // workaround for golang.org/issue/34474.
 161  func issue34474KeepAlive(v interface{}) {
 162  	runtime.KeepAlive(v)
 163  }
 164