egl_windows.go 5.4 KB

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