mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
internal/goglfw: use platform agnostic functions for context_windows.go (#2570)
context_windows.go is used for all the platforms. However, it used syscall.Syscall which behaves differently on macOS and Windows as well as windows.BytePtrToString which isn't available on Linux or macOS. This commit replaces syscall.Syscall with purego.SyscallN and windows.BytePtrToString with a copied version called bytePtrToString. Updates #2546
This commit is contained in:
parent
b359985e97
commit
93537650c0
@ -11,10 +11,9 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"github.com/ebitengine/purego"
|
||||||
)
|
)
|
||||||
|
|
||||||
func checkValidContextConfig(ctxconfig *ctxconfig) error {
|
func checkValidContextConfig(ctxconfig *ctxconfig) error {
|
||||||
@ -271,8 +270,8 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
|
|||||||
return fmt.Errorf("goglfw: entry point retrieval is broken: %w", PlatformError)
|
return fmt.Errorf("goglfw: entry point retrieval is broken: %w", PlatformError)
|
||||||
}
|
}
|
||||||
|
|
||||||
r, _, _ := syscall.Syscall(getString, 1, GL_VERSION, 0, 0)
|
r, _, _ := purego.SyscallN(getString, GL_VERSION)
|
||||||
version := windows.BytePtrToString((*byte)(unsafe.Pointer(r)))
|
version := bytePtrToString((*byte)(unsafe.Pointer(r)))
|
||||||
if version == "" {
|
if version == "" {
|
||||||
if ctxconfig.client == OpenGLAPI {
|
if ctxconfig.client == OpenGLAPI {
|
||||||
return fmt.Errorf("goglfw: OpenGL version string retrieval is broken: %w", PlatformError)
|
return fmt.Errorf("goglfw: OpenGL version string retrieval is broken: %w", PlatformError)
|
||||||
@ -334,7 +333,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
|
|||||||
// Read back context flags (OpenGL 3.0 and above)
|
// Read back context flags (OpenGL 3.0 and above)
|
||||||
if w.context.major >= 3 {
|
if w.context.major >= 3 {
|
||||||
var flags int32
|
var flags int32
|
||||||
_, _, _ = syscall.Syscall(getIntegerv, 2, GL_CONTEXT_FLAGS, uintptr(unsafe.Pointer(&flags)), 0)
|
_, _, _ = purego.SyscallN(getIntegerv, GL_CONTEXT_FLAGS, uintptr(unsafe.Pointer(&flags)))
|
||||||
|
|
||||||
if flags&GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT != 0 {
|
if flags&GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT != 0 {
|
||||||
w.context.forward = true
|
w.context.forward = true
|
||||||
@ -363,7 +362,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
|
|||||||
// Read back OpenGL context profile (OpenGL 3.2 and above)
|
// Read back OpenGL context profile (OpenGL 3.2 and above)
|
||||||
if w.context.major >= 4 || (w.context.major == 3 && w.context.minor >= 2) {
|
if w.context.major >= 4 || (w.context.major == 3 && w.context.minor >= 2) {
|
||||||
var mask int32
|
var mask int32
|
||||||
_, _, _ = syscall.Syscall(getIntegerv, 2, GL_CONTEXT_PROFILE_MASK, uintptr(unsafe.Pointer(&mask)), 0)
|
_, _, _ = purego.SyscallN(getIntegerv, GL_CONTEXT_PROFILE_MASK, uintptr(unsafe.Pointer(&mask)))
|
||||||
|
|
||||||
if mask&GL_CONTEXT_COMPATIBILITY_PROFILE_BIT != 0 {
|
if mask&GL_CONTEXT_COMPATIBILITY_PROFILE_BIT != 0 {
|
||||||
w.context.profile = OpenGLCompatProfile
|
w.context.profile = OpenGLCompatProfile
|
||||||
@ -394,7 +393,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
|
|||||||
// only present from 3.0 while the extension applies from 1.1
|
// only present from 3.0 while the extension applies from 1.1
|
||||||
|
|
||||||
var strategy int32
|
var strategy int32
|
||||||
_, _, _ = syscall.Syscall(getIntegerv, 2, GL_RESET_NOTIFICATION_STRATEGY_ARB, uintptr(unsafe.Pointer(&strategy)), 0)
|
_, _, _ = purego.SyscallN(getIntegerv, GL_RESET_NOTIFICATION_STRATEGY_ARB, uintptr(unsafe.Pointer(&strategy)))
|
||||||
|
|
||||||
if strategy == GL_LOSE_CONTEXT_ON_RESET_ARB {
|
if strategy == GL_LOSE_CONTEXT_ON_RESET_ARB {
|
||||||
w.context.robustness = LoseContextOnReset
|
w.context.robustness = LoseContextOnReset
|
||||||
@ -413,7 +412,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
|
|||||||
// one, so we can reuse them here
|
// one, so we can reuse them here
|
||||||
|
|
||||||
var strategy int32
|
var strategy int32
|
||||||
_, _, _ = syscall.Syscall(getIntegerv, 2, GL_RESET_NOTIFICATION_STRATEGY_ARB, uintptr(unsafe.Pointer(&strategy)), 0)
|
_, _, _ = purego.SyscallN(getIntegerv, GL_RESET_NOTIFICATION_STRATEGY_ARB, uintptr(unsafe.Pointer(&strategy)))
|
||||||
|
|
||||||
if strategy == GL_LOSE_CONTEXT_ON_RESET_ARB {
|
if strategy == GL_LOSE_CONTEXT_ON_RESET_ARB {
|
||||||
w.context.robustness = LoseContextOnReset
|
w.context.robustness = LoseContextOnReset
|
||||||
@ -429,7 +428,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
|
|||||||
}
|
}
|
||||||
if ok {
|
if ok {
|
||||||
var behavior int32
|
var behavior int32
|
||||||
_, _, _ = syscall.Syscall(getIntegerv, 2, GL_CONTEXT_RELEASE_BEHAVIOR, uintptr(unsafe.Pointer(&behavior)), 0)
|
_, _, _ = purego.SyscallN(getIntegerv, GL_CONTEXT_RELEASE_BEHAVIOR, uintptr(unsafe.Pointer(&behavior)))
|
||||||
|
|
||||||
if behavior == GL_NONE {
|
if behavior == GL_NONE {
|
||||||
w.context.release = ReleaseBehaviorNone
|
w.context.release = ReleaseBehaviorNone
|
||||||
@ -441,7 +440,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
|
|||||||
// Clearing the front buffer to black to avoid garbage pixels left over from
|
// Clearing the front buffer to black to avoid garbage pixels left over from
|
||||||
// previous uses of our bit of VRAM
|
// previous uses of our bit of VRAM
|
||||||
glClear := w.context.getProcAddress("glClear")
|
glClear := w.context.getProcAddress("glClear")
|
||||||
_, _, _ = syscall.Syscall(glClear, 1, GL_COLOR_BUFFER_BIT, 0, 0)
|
_, _, _ = purego.SyscallN(glClear, GL_COLOR_BUFFER_BIT)
|
||||||
|
|
||||||
if w.doublebuffer {
|
if w.doublebuffer {
|
||||||
if err := w.context.swapBuffers(w); err != nil {
|
if err := w.context.swapBuffers(w); err != nil {
|
||||||
@ -553,16 +552,16 @@ func ExtensionSupported(extension string) (bool, error) {
|
|||||||
|
|
||||||
glGetIntegerv := window.context.getProcAddress("glGetIntegerv")
|
glGetIntegerv := window.context.getProcAddress("glGetIntegerv")
|
||||||
var count int32
|
var count int32
|
||||||
_, _, _ = syscall.Syscall(glGetIntegerv, 2, GL_NUM_EXTENSIONS, uintptr(unsafe.Pointer(&count)), 0)
|
_, _, _ = purego.SyscallN(glGetIntegerv, GL_NUM_EXTENSIONS, uintptr(unsafe.Pointer(&count)))
|
||||||
|
|
||||||
glGetStringi := window.context.getProcAddress("glGetStringi")
|
glGetStringi := window.context.getProcAddress("glGetStringi")
|
||||||
for i := 0; i < int(count); i++ {
|
for i := 0; i < int(count); i++ {
|
||||||
r, _, _ := syscall.Syscall(glGetStringi, 2, GL_EXTENSIONS, uintptr(i), 0)
|
r, _, _ := purego.SyscallN(glGetStringi, GL_EXTENSIONS, uintptr(i))
|
||||||
if r == 0 {
|
if r == 0 {
|
||||||
return false, fmt.Errorf("goglfw: extension string retrieval is broken: %w", PlatformError)
|
return false, fmt.Errorf("goglfw: extension string retrieval is broken: %w", PlatformError)
|
||||||
}
|
}
|
||||||
|
|
||||||
en := windows.BytePtrToString((*byte)(unsafe.Pointer(r)))
|
en := bytePtrToString((*byte)(unsafe.Pointer(r)))
|
||||||
if en == extension {
|
if en == extension {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
@ -571,12 +570,12 @@ func ExtensionSupported(extension string) (bool, error) {
|
|||||||
// Check if extension is in the old style OpenGL extensions string
|
// Check if extension is in the old style OpenGL extensions string
|
||||||
|
|
||||||
glGetString := window.context.getProcAddress("glGetString")
|
glGetString := window.context.getProcAddress("glGetString")
|
||||||
r, _, _ := syscall.Syscall(glGetString, 1, GL_EXTENSIONS, 0, 0)
|
r, _, _ := purego.SyscallN(glGetString, GL_EXTENSIONS)
|
||||||
if r == 0 {
|
if r == 0 {
|
||||||
return false, fmt.Errorf("goglfw: extension string retrieval is broken: %w", PlatformError)
|
return false, fmt.Errorf("goglfw: extension string retrieval is broken: %w", PlatformError)
|
||||||
}
|
}
|
||||||
|
|
||||||
extensions := windows.BytePtrToString((*byte)(unsafe.Pointer(r)))
|
extensions := bytePtrToString((*byte)(unsafe.Pointer(r)))
|
||||||
for _, str := range strings.Split(extensions, " ") {
|
for _, str := range strings.Split(extensions, " ") {
|
||||||
if str == extension {
|
if str == extension {
|
||||||
return true, nil
|
return true, nil
|
||||||
@ -587,3 +586,24 @@ func ExtensionSupported(extension string) (bool, error) {
|
|||||||
// Check if extension is in the platform-specific string
|
// Check if extension is in the platform-specific string
|
||||||
return window.context.extensionSupported(extension), nil
|
return window.context.extensionSupported(extension), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bytePtrToString takes a pointer to a sequence of text and returns the corresponding string.
|
||||||
|
// If the pointer is nil, it returns the empty string. It assumes that the text sequence is
|
||||||
|
// terminated at a zero byte; if the zero byte is not present, the program may crash.
|
||||||
|
// It is copied from golang.org/x/sys/windows/syscall.go for use on macOS, Linux and Windows
|
||||||
|
func bytePtrToString(p *byte) string {
|
||||||
|
if p == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if *p == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find NUL terminator.
|
||||||
|
n := 0
|
||||||
|
for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ {
|
||||||
|
ptr = unsafe.Pointer(uintptr(ptr) + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(unsafe.Slice(p, n))
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user