internal/glfw: reduce TLS usages

This commit is contained in:
Hajime Hoshi 2024-10-12 23:01:59 +09:00
parent 82b8521a6c
commit 02e87d027c
7 changed files with 38 additions and 74 deletions

View File

@ -465,7 +465,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
window->context.debug = GLFW_TRUE; window->context.debug = GLFW_TRUE;
else if (glfwExtensionSupported("GL_ARB_debug_output") && else if (glfwExtensionSupported((GLFWwindow*) window, "GL_ARB_debug_output") &&
ctxconfig->debug) ctxconfig->debug)
{ {
// HACK: This is a workaround for older drivers (pre KHR_debug) // HACK: This is a workaround for older drivers (pre KHR_debug)
@ -489,7 +489,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
window->context.profile = GLFW_OPENGL_COMPAT_PROFILE; window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
else if (mask & GL_CONTEXT_CORE_PROFILE_BIT) else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
window->context.profile = GLFW_OPENGL_CORE_PROFILE; window->context.profile = GLFW_OPENGL_CORE_PROFILE;
else if (glfwExtensionSupported("GL_ARB_compatibility")) else if (glfwExtensionSupported((GLFWwindow*) window, "GL_ARB_compatibility"))
{ {
// HACK: This is a workaround for the compatibility profile bit // HACK: This is a workaround for the compatibility profile bit
// not being set in the context flags if an OpenGL 3.2+ // not being set in the context flags if an OpenGL 3.2+
@ -500,7 +500,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
} }
// Read back robustness strategy // Read back robustness strategy
if (glfwExtensionSupported("GL_ARB_robustness")) if (glfwExtensionSupported((GLFWwindow*) window, "GL_ARB_robustness"))
{ {
// NOTE: We avoid using the context flags for detection, as they are // NOTE: We avoid using the context flags for detection, as they are
// only present from 3.0 while the extension applies from 1.1 // only present from 3.0 while the extension applies from 1.1
@ -518,7 +518,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
else else
{ {
// Read back robustness strategy // Read back robustness strategy
if (glfwExtensionSupported("GL_EXT_robustness")) if (glfwExtensionSupported((GLFWwindow*) window, "GL_EXT_robustness"))
{ {
// NOTE: The values of these constants match those of the OpenGL ARB // NOTE: The values of these constants match those of the OpenGL ARB
// one, so we can reuse them here // one, so we can reuse them here
@ -534,7 +534,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
} }
} }
if (glfwExtensionSupported("GL_KHR_context_flush_control")) if (glfwExtensionSupported((GLFWwindow*) window, "GL_KHR_context_flush_control"))
{ {
GLint behavior; GLint behavior;
window->context.GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior); window->context.GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
@ -642,38 +642,24 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
window->context.swapBuffers(window); window->context.swapBuffers(window);
} }
GLFWAPI void glfwSwapInterval(int interval) GLFWAPI void glfwSwapInterval(GLFWwindow* handle, int interval)
{ {
_GLFWwindow* window; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window)
{
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
"Cannot set swap interval without a current OpenGL or OpenGL ES context");
return;
}
window->context.swapInterval(interval); window->context.swapInterval(interval);
} }
GLFWAPI int glfwExtensionSupported(const char* extension) GLFWAPI int glfwExtensionSupported(GLFWwindow* handle, const char* extension)
{ {
_GLFWwindow* window; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(extension != NULL); assert(extension != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window)
{
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
"Cannot query extension without a current OpenGL or OpenGL ES context");
return GLFW_FALSE;
}
if (*extension == '\0') if (*extension == '\0')
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string"); _glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");

View File

@ -73,8 +73,8 @@ func (w *Window) SwapBuffers() error {
// //
// Some GPU drivers do not honor the requested swap interval, either because of // Some GPU drivers do not honor the requested swap interval, either because of
// user settings that override the request or due to bugs in the driver. // user settings that override the request or due to bugs in the driver.
func SwapInterval(interval int) error { func (w *Window) SwapInterval(interval int) error {
C.glfwSwapInterval(C.int(interval)) C.glfwSwapInterval(w.data, C.int(interval))
if err := fetchErrorIgnoringPlatformError(); err != nil { if err := fetchErrorIgnoringPlatformError(); err != nil {
return err return err
} }
@ -89,10 +89,10 @@ func SwapInterval(interval int) error {
// recommended that you cache its results if it's going to be used frequently. // recommended that you cache its results if it's going to be used frequently.
// The extension strings will not change during the lifetime of a context, so // The extension strings will not change during the lifetime of a context, so
// there is no danger in doing this. // there is no danger in doing this.
func ExtensionSupported(extension string) (bool, error) { func (w *Window) ExtensionSupported(extension string) (bool, error) {
e := C.CString(extension) e := C.CString(extension)
defer C.free(unsafe.Pointer(e)) defer C.free(unsafe.Pointer(e))
ret := C.glfwExtensionSupported(e) != 0 ret := C.glfwExtensionSupported(w.data, e) != 0
if err := fetchErrorIgnoringPlatformError(); err != nil { if err := fetchErrorIgnoringPlatformError(); err != nil {
return false, err return false, err
} }

View File

@ -353,7 +353,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
if flags&GL_CONTEXT_FLAG_DEBUG_BIT != 0 { if flags&GL_CONTEXT_FLAG_DEBUG_BIT != 0 {
w.context.debug = true w.context.debug = true
} else { } else {
ok, err := ExtensionSupported("GL_ARB_debug_output") ok, err := w.ExtensionSupported("GL_ARB_debug_output")
if err != nil { if err != nil {
return err return err
} }
@ -380,7 +380,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
} else if mask&GL_CONTEXT_CORE_PROFILE_BIT != 0 { } else if mask&GL_CONTEXT_CORE_PROFILE_BIT != 0 {
w.context.profile = OpenGLCoreProfile w.context.profile = OpenGLCoreProfile
} else { } else {
ok, err := ExtensionSupported("GL_ARB_compatibility") ok, err := w.ExtensionSupported("GL_ARB_compatibility")
if err != nil { if err != nil {
return err return err
} }
@ -395,7 +395,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
} }
// Read back robustness strategy // Read back robustness strategy
ok, err := ExtensionSupported("GL_ARB_robustness") ok, err := w.ExtensionSupported("GL_ARB_robustness")
if err != nil { if err != nil {
return err return err
} }
@ -414,7 +414,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
} }
} else { } else {
// Read back robustness strategy // Read back robustness strategy
ok, err := ExtensionSupported("GL_EXT_robustness") ok, err := w.ExtensionSupported("GL_EXT_robustness")
if err != nil { if err != nil {
return err return err
} }
@ -433,7 +433,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
} }
} }
ok, err := ExtensionSupported("GL_KHR_context_flush_control") ok, err := w.ExtensionSupported("GL_KHR_context_flush_control")
if err != nil { if err != nil {
return err return err
} }
@ -519,27 +519,18 @@ func (w *Window) SwapBuffers() error {
return nil return nil
} }
func SwapInterval(interval int) error { func (w *Window) SwapInterval(interval int) error {
if !_glfw.initialized { if !_glfw.initialized {
return NotInitialized return NotInitialized
} }
ptr, err := _glfw.contextSlot.get() if err := w.context.swapInterval(interval); err != nil {
if err != nil {
return err
}
window := (*Window)(unsafe.Pointer(ptr))
if window == nil {
return fmt.Errorf("glfw: cannot set swap interval without a current OpenGL or OpenGL ES context %w", NoCurrentContext)
}
if err := window.context.swapInterval(interval); err != nil {
return err return err
} }
return nil return nil
} }
func ExtensionSupported(extension string) (bool, error) { func (w *Window) ExtensionSupported(extension string) (bool, error) {
const ( const (
GL_EXTENSIONS = 0x1F03 GL_EXTENSIONS = 0x1F03
GL_NUM_EXTENSIONS = 0x821D GL_NUM_EXTENSIONS = 0x821D
@ -549,23 +540,14 @@ func ExtensionSupported(extension string) (bool, error) {
return false, NotInitialized return false, NotInitialized
} }
ptr, err := _glfw.contextSlot.get() if w.context.major >= 3 {
if err != nil {
return false, err
}
window := (*Window)(unsafe.Pointer(ptr))
if window == nil {
return false, fmt.Errorf("glfw: cannot query extension without a current OpenGL or OpenGL ES context %w", NoCurrentContext)
}
if window.context.major >= 3 {
// Check if extension is in the modern OpenGL extensions string list // Check if extension is in the modern OpenGL extensions string list
glGetIntegerv := window.context.getProcAddress("glGetIntegerv") glGetIntegerv := w.context.getProcAddress("glGetIntegerv")
var count int32 var count int32
_, _, _ = purego.SyscallN(glGetIntegerv, GL_NUM_EXTENSIONS, uintptr(unsafe.Pointer(&count))) _, _, _ = purego.SyscallN(glGetIntegerv, GL_NUM_EXTENSIONS, uintptr(unsafe.Pointer(&count)))
glGetStringi := window.context.getProcAddress("glGetStringi") glGetStringi := w.context.getProcAddress("glGetStringi")
for i := 0; i < int(count); i++ { for i := 0; i < int(count); i++ {
r, _, _ := purego.SyscallN(glGetStringi, GL_EXTENSIONS, uintptr(i)) r, _, _ := purego.SyscallN(glGetStringi, GL_EXTENSIONS, uintptr(i))
if r == 0 { if r == 0 {
@ -580,7 +562,7 @@ func ExtensionSupported(extension string) (bool, error) {
} else { } else {
// 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 := w.context.getProcAddress("glGetString")
r, _, _ := purego.SyscallN(glGetString, GL_EXTENSIONS) r, _, _ := purego.SyscallN(glGetString, GL_EXTENSIONS)
if r == 0 { if r == 0 {
return false, fmt.Errorf("glfw: extension string retrieval is broken: %w", PlatformError) return false, fmt.Errorf("glfw: extension string retrieval is broken: %w", PlatformError)
@ -595,7 +577,7 @@ 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 w.context.extensionSupported(extension), nil
} }
// bytePtrToString takes a pointer to a sequence of text and returns the corresponding string. // bytePtrToString takes a pointer to a sequence of text and returns the corresponding string.

View File

@ -4824,9 +4824,7 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
* arrives a little bit late. You can check for these extensions with @ref * arrives a little bit late. You can check for these extensions with @ref
* glfwExtensionSupported. * glfwExtensionSupported.
* *
* A context must be current on the calling thread. Calling this function * @param[in] window The window whose context to make current.
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
*
* @param[in] interval The minimum number of screen updates to wait for * @param[in] interval The minimum number of screen updates to wait for
* until the buffers are swapped by @ref glfwSwapBuffers. * until the buffers are swapped by @ref glfwSwapBuffers.
* *
@ -4851,7 +4849,7 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
* *
* @ingroup context * @ingroup context
*/ */
GLFWAPI void glfwSwapInterval(int interval); GLFWAPI void glfwSwapInterval(GLFWwindow* window, int interval);
/*! @brief Returns whether the specified extension is available. /*! @brief Returns whether the specified extension is available.
* *
@ -4860,14 +4858,12 @@ GLFWAPI void glfwSwapInterval(int interval);
* OpenGL ES context. It searches both for client API extension and context * OpenGL ES context. It searches both for client API extension and context
* creation API extensions. * creation API extensions.
* *
* A context must be current on the calling thread. Calling this function
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
*
* As this functions retrieves and searches one or more extension strings each * As this functions retrieves and searches one or more extension strings each
* call, it is recommended that you cache its results if it is going to be used * call, it is recommended that you cache its results if it is going to be used
* frequently. The extension strings will not change during the lifetime of * frequently. The extension strings will not change during the lifetime of
* a context, so there is no danger in doing this. * a context, so there is no danger in doing this.
* *
* @param[in] window The window whose context to make current.
* @param[in] extension The ASCII encoded name of the extension. * @param[in] extension The ASCII encoded name of the extension.
* @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE`
* otherwise. * otherwise.
@ -4885,7 +4881,7 @@ GLFWAPI void glfwSwapInterval(int interval);
* *
* @ingroup context * @ingroup context
*/ */
GLFWAPI int glfwExtensionSupported(const char* extension); GLFWAPI int glfwExtensionSupported(GLFWwindow* window, const char* extension);
/*! @brief Returns the address of the specified function for the current /*! @brief Returns the address of the specified function for the current
* context. * context.

View File

@ -86,11 +86,11 @@ func (g *Graphics) swapBuffers() error {
// This needs to be called at least after SetMonitor. // This needs to be called at least after SetMonitor.
// Without SwapInterval after SetMonitor, vsynch doesn't work (#375). // Without SwapInterval after SetMonitor, vsynch doesn't work (#375).
if g.vsync { if g.vsync {
if err := glfw.SwapInterval(1); err != nil { if err := g.window.SwapInterval(1); err != nil {
return err return err
} }
} else { } else {
if err := glfw.SwapInterval(0); err != nil { if err := g.window.SwapInterval(0); err != nil {
return err return err
} }
} }

View File

@ -70,11 +70,11 @@ func (g *Graphics) swapBuffers() error {
// This needs to be called at least after SetMonitor. // This needs to be called at least after SetMonitor.
// Without SwapInterval after SetMonitor, vsynch doesn't work (#375). // Without SwapInterval after SetMonitor, vsynch doesn't work (#375).
if g.vsync { if g.vsync {
if err := glfw.SwapInterval(1); err != nil { if err := g.window.SwapInterval(1); err != nil {
return err return err
} }
} else { } else {
if err := glfw.SwapInterval(0); err != nil { if err := g.window.SwapInterval(0); err != nil {
return err return err
} }
} }

View File

@ -68,11 +68,11 @@ func (g *Graphics) swapBuffers() error {
// This needs to be called at least after SetMonitor. // This needs to be called at least after SetMonitor.
// Without SwapInterval after SetMonitor, vsynch doesn't work (#375). // Without SwapInterval after SetMonitor, vsynch doesn't work (#375).
if g.vsync { if g.vsync {
if err := glfw.SwapInterval(1); err != nil { if err := g.window.SwapInterval(1); err != nil {
return err return err
} }
} else { } else {
if err := glfw.SwapInterval(0); err != nil { if err := g.window.SwapInterval(0); err != nil {
return err return err
} }
} }