github.com/gop9/olt@v0.0.0-20200202132135-d956aad50b08/gio/app/internal/egl/egl_windows.go (about)

     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/gop9/olt/gio/app/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  	loadErr := dll.Load()
    68  	if loadErr == nil {
    69  		return nil
    70  	}
    71  	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.")
    72  	ptitle := syscall.StringToUTF16Ptr("Error")
    73  	syscall.MessageBox(0 /* HWND */, pmsg, ptitle, syscall.MB_ICONERROR|syscall.MB_SYSTEMMODAL)
    74  	return fmt.Errorf("egl: failed to load %s", name)
    75  }
    76  
    77  func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) {
    78  	var cfg _EGLConfig
    79  	var ncfg _EGLint
    80  	a := &attribs[0]
    81  	r, _, _ := _eglChooseConfig.Call(uintptr(disp), uintptr(unsafe.Pointer(a)), uintptr(unsafe.Pointer(&cfg)), 1, uintptr(unsafe.Pointer(&ncfg)))
    82  	issue34474KeepAlive(a)
    83  	return cfg, r != 0
    84  }
    85  
    86  func eglCreateContext(disp _EGLDisplay, cfg _EGLConfig, shareCtx _EGLContext, attribs []_EGLint) _EGLContext {
    87  	a := &attribs[0]
    88  	c, _, _ := _eglCreateContext.Call(uintptr(disp), uintptr(cfg), uintptr(shareCtx), uintptr(unsafe.Pointer(a)))
    89  	issue34474KeepAlive(a)
    90  	return _EGLContext(c)
    91  }
    92  
    93  func eglCreateWindowSurface(disp _EGLDisplay, cfg _EGLConfig, win NativeWindowType, attribs []_EGLint) _EGLSurface {
    94  	a := &attribs[0]
    95  	s, _, _ := _eglCreateWindowSurface.Call(uintptr(disp), uintptr(cfg), uintptr(win), uintptr(unsafe.Pointer(a)))
    96  	issue34474KeepAlive(a)
    97  	return _EGLSurface(s)
    98  }
    99  
   100  func eglDestroySurface(disp _EGLDisplay, surf _EGLSurface) bool {
   101  	r, _, _ := _eglDestroySurface.Call(uintptr(disp), uintptr(surf))
   102  	return r != 0
   103  }
   104  
   105  func eglDestroyContext(disp _EGLDisplay, ctx _EGLContext) bool {
   106  	r, _, _ := _eglDestroyContext.Call(uintptr(disp), uintptr(ctx))
   107  	return r != 0
   108  }
   109  
   110  func eglGetConfigAttrib(disp _EGLDisplay, cfg _EGLConfig, attr _EGLint) (_EGLint, bool) {
   111  	var val uintptr
   112  	r, _, _ := _eglGetConfigAttrib.Call(uintptr(disp), uintptr(cfg), uintptr(attr), uintptr(unsafe.Pointer(&val)))
   113  	return _EGLint(val), r != 0
   114  }
   115  
   116  func eglGetDisplay(disp NativeDisplayType) _EGLDisplay {
   117  	d, _, _ := _eglGetDisplay.Call(uintptr(disp))
   118  	return _EGLDisplay(d)
   119  }
   120  
   121  func eglGetError() _EGLint {
   122  	e, _, _ := _eglGetError.Call()
   123  	return _EGLint(e)
   124  }
   125  
   126  func eglInitialize(disp _EGLDisplay) (_EGLint, _EGLint, bool) {
   127  	var maj, min uintptr
   128  	r, _, _ := _eglInitialize.Call(uintptr(disp), uintptr(unsafe.Pointer(&maj)), uintptr(unsafe.Pointer(&min)))
   129  	return _EGLint(maj), _EGLint(min), r != 0
   130  }
   131  
   132  func eglMakeCurrent(disp _EGLDisplay, draw, read _EGLSurface, ctx _EGLContext) bool {
   133  	r, _, _ := _eglMakeCurrent.Call(uintptr(disp), uintptr(draw), uintptr(read), uintptr(ctx))
   134  	return r != 0
   135  }
   136  
   137  func eglReleaseThread() bool {
   138  	r, _, _ := _eglReleaseThread.Call()
   139  	return r != 0
   140  }
   141  
   142  func eglSwapInterval(disp _EGLDisplay, interval _EGLint) bool {
   143  	r, _, _ := _eglSwapInterval.Call(uintptr(disp), uintptr(interval))
   144  	return r != 0
   145  }
   146  
   147  func eglSwapBuffers(disp _EGLDisplay, surf _EGLSurface) bool {
   148  	r, _, _ := _eglSwapBuffers.Call(uintptr(disp), uintptr(surf))
   149  	return r != 0
   150  }
   151  
   152  func eglTerminate(disp _EGLDisplay) bool {
   153  	r, _, _ := _eglTerminate.Call(uintptr(disp))
   154  	return r != 0
   155  }
   156  
   157  func eglQueryString(disp _EGLDisplay, name _EGLint) string {
   158  	r, _, _ := _eglQueryString.Call(uintptr(disp), uintptr(name))
   159  	return gl.GoString(gl.SliceOf(r))
   160  }
   161  
   162  // issue34474KeepAlive calls runtime.KeepAlive as a
   163  // workaround for golang.org/issue/34474.
   164  func issue34474KeepAlive(v interface{}) {
   165  	runtime.KeepAlive(v)
   166  }