internal/cglfw: fix errors to be close to internal/glfw

Updates #2703
This commit is contained in:
Hajime Hoshi 2023-10-07 22:48:41 +09:00
parent 6dc375f7a6
commit ad0b61c022
3 changed files with 37 additions and 86 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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