From ad0b61c0229ba7286999aa9fc527f4a1d4616155 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sat, 7 Oct 2023 22:48:41 +0900 Subject: [PATCH] internal/cglfw: fix errors to be close to internal/glfw Updates #2703 --- internal/cglfw/error_unix.go | 117 ++++++++++------------------------ internal/cglfw/glfw_unix.go | 3 +- internal/cglfw/window_unix.go | 3 +- 3 files changed, 37 insertions(+), 86 deletions(-) diff --git a/internal/cglfw/error_unix.go b/internal/cglfw/error_unix.go index e3ce8f9c4..196945c61 100644 --- a/internal/cglfw/error_unix.go +++ b/internal/cglfw/error_unix.go @@ -17,6 +17,7 @@ package cglfw import "C" import ( + "errors" "fmt" "os" ) @@ -24,107 +25,55 @@ import ( // ErrorCode corresponds to an error code. type ErrorCode int -// Error codes that are translated to panics and the programmer should not -// expect to handle. const ( - notInitialized ErrorCode = C.GLFW_NOT_INITIALIZED // GLFW has not been initialized. - noCurrentContext ErrorCode = C.GLFW_NO_CURRENT_CONTEXT // No context is current. - invalidEnum ErrorCode = C.GLFW_INVALID_ENUM // One of the enum parameters for the function was given an invalid enum. - invalidValue ErrorCode = C.GLFW_INVALID_VALUE // One of the parameters for the function was given an invalid value. - outOfMemory ErrorCode = C.GLFW_OUT_OF_MEMORY // A memory allocation failed. - platformError ErrorCode = C.GLFW_PLATFORM_ERROR // A platform-specific error occurred that does not match any of the more specific categories. + NotInitialized = ErrorCode(0x00010001) + NoCurrentContext = ErrorCode(0x00010002) + InvalidEnum = ErrorCode(0x00010003) + InvalidValue = ErrorCode(0x00010004) + OutOfMemory = ErrorCode(0x00010005) + APIUnavailable = ErrorCode(0x00010006) + VersionUnavailable = ErrorCode(0x00010007) + PlatformError = ErrorCode(0x00010008) + FormatUnavailable = ErrorCode(0x00010009) + NoWindowContext = ErrorCode(0x0001000A) ) -const ( - // APIUnavailable is the error code used when GLFW could not find support - // for the requested client API on the system. - // - // The installed graphics driver does not support the requested client API, - // or does not support it via the chosen context creation backend. Below - // are a few examples. - // - // Some pre-installed Windows graphics drivers do not support OpenGL. AMD - // only supports OpenGL ES via EGL, while Nvidia and Intel only supports it - // via a WGL or GLX extension. OS X does not provide OpenGL ES at all. The - // Mesa EGL, OpenGL and OpenGL ES libraries do not interface with the - // Nvidia binary driver. - APIUnavailable ErrorCode = C.GLFW_API_UNAVAILABLE - - // VersionUnavailable is the error code used when the requested OpenGL or - // OpenGL ES (including any requested profile or context option) is not - // available on this machine. - // - // The machine does not support your requirements. If your application is - // sufficiently flexible, downgrade your requirements and try again. - // Otherwise, inform the user that their machine does not match your - // requirements. - // - // Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if - // 5.0 comes out before the 4.x series gets that far, also fail with this - // error and not GLFW_INVALID_VALUE, because GLFW cannot know what future - // versions will exist. - VersionUnavailable ErrorCode = C.GLFW_VERSION_UNAVAILABLE - - // FormatUnavailable is the error code used for both window creation and - // clipboard querying format errors. - // - // If emitted during window creation, the requested pixel format is not - // supported. This means one or more hard constraints did not match any of - // the available pixel formats. If your application is sufficiently - // flexible, downgrade your requirements and try again. Otherwise, inform - // the user that their machine does not match your requirements. - // - // If emitted when querying the clipboard, the contents of the clipboard - // could not be converted to the requested format. You should ignore the - // error or report it to the user, as appropriate. - FormatUnavailable ErrorCode = C.GLFW_FORMAT_UNAVAILABLE -) - -func (e ErrorCode) String() string { +func (e ErrorCode) Error() string { switch e { - case notInitialized: - return "NotInitialized" - case noCurrentContext: - return "NoCurrentContext" - case invalidEnum: - return "InvalidEnum" - case invalidValue: - return "InvalidValue" - case outOfMemory: - return "OutOfMemory" - case platformError: - return "PlatformError" + case NotInitialized: + return "the GLFW library is not initialized" + case NoCurrentContext: + return "there is no current context" + case InvalidEnum: + return "invalid argument for enum parameter" + case InvalidValue: + return "invalid value for parameter" + case OutOfMemory: + return "out of memory" case APIUnavailable: - return "APIUnavailable" + return "the requested API is unavailable" case VersionUnavailable: - return "VersionUnavailable" + return "the requested API version is unavailable" + case PlatformError: + return "a platform-specific error occurred" case FormatUnavailable: - return "FormatUnavailable" + return "the requested format is unavailable" + case NoWindowContext: + return "the specified window has no context" default: - return fmt.Sprintf("ErrorCode(%d)", e) + return fmt.Sprintf("GLFW error (%d)", e) } } -// Error holds error code and description. -type Error struct { - Code ErrorCode - Desc string -} - -// Error prints the error code and description in a readable format. -func (e *Error) Error() string { - return fmt.Sprintf("%s: %s", e.Code.String(), e.Desc) -} - // Note: There are many cryptic caveats to proper error handling here. // See: https://github.com/go-gl/glfw3/pull/86 // lastError holds the value of the last error. -var lastError = make(chan *Error, 1) +var lastError = make(chan error, 1) //export goErrorCB func goErrorCB(code C.int, desc *C.char) { - err := &Error{ErrorCode(code), C.GoString(desc)} + err := fmt.Errorf("glfw: %s: %w", C.GoString(desc), ErrorCode(code)) select { case lastError <- err: default: @@ -142,7 +91,7 @@ func init() { func fetchErrorIgnoringPlatformError() error { select { case err := <-lastError: - if err.Code == platformError { + if errors.Is(err, PlatformError) { fmt.Fprintln(os.Stderr, err) return nil } diff --git a/internal/cglfw/glfw_unix.go b/internal/cglfw/glfw_unix.go index 75b010ba9..6324e03e6 100644 --- a/internal/cglfw/glfw_unix.go +++ b/internal/cglfw/glfw_unix.go @@ -12,6 +12,7 @@ package cglfw import "C" import ( + "errors" "unsafe" ) @@ -116,7 +117,7 @@ func GetClipboardString() (string, error) { cs := C.glfwGetClipboardString(nil) if cs == nil { if err := fetchErrorIgnoringPlatformError(); err != nil { - if cerr, ok := err.(*Error); ok && cerr.Code == FormatUnavailable { + if errors.Is(err, FormatUnavailable) { return "", nil } return "", err diff --git a/internal/cglfw/window_unix.go b/internal/cglfw/window_unix.go index fe9461280..2347fde64 100644 --- a/internal/cglfw/window_unix.go +++ b/internal/cglfw/window_unix.go @@ -58,6 +58,7 @@ package cglfw import "C" import ( + "errors" "image" "image/draw" "sync" @@ -1054,7 +1055,7 @@ func (w *Window) GetClipboardString() (string, error) { cs := C.glfwGetClipboardString(w.data) if cs == nil { if err := fetchErrorIgnoringPlatformError(); err != nil { - if cerr, ok := err.(*Error); ok && cerr.Code == FormatUnavailable { + if errors.Is(err, FormatUnavailable) { return "", nil } return "", err