| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- package glfw
- //#define GLFW_INCLUDE_NONE
- //#include "glfw/include/GLFW/glfw3.h"
- //void glfwSetErrorCallbackCB();
- import "C"
- import (
- "fmt"
- "log"
- )
- // 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.
- )
- 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 {
- 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 APIUnavailable:
- return "APIUnavailable"
- case VersionUnavailable:
- return "VersionUnavailable"
- case FormatUnavailable:
- return "FormatUnavailable"
- default:
- return fmt.Sprintf("ErrorCode(%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
- // Holds the value of the last error.
- var lastError = make(chan *Error, 1)
- //export goErrorCB
- func goErrorCB(code C.int, desc *C.char) {
- flushErrors()
- err := &Error{ErrorCode(code), C.GoString(desc)}
- select {
- case lastError <- err:
- default:
- fmt.Println("GLFW: An uncaught error has occurred:", err)
- fmt.Println("GLFW: Please report this bug in the Go package immediately.")
- }
- }
- // Set the glfw callback internally
- func init() {
- C.glfwSetErrorCallbackCB()
- }
- // flushErrors is called by Terminate before it actually calls C.glfwTerminate,
- // this ensures that any uncaught errors buffered in lastError are printed
- // before the program exits.
- func flushErrors() {
- err := fetchError()
- if err != nil {
- fmt.Println("GLFW: An uncaught error has occurred:", err)
- fmt.Println("GLFW: Please report this bug in the Go package immediately.")
- }
- }
- // acceptError fetches the next error from the error channel, it accepts only
- // errors with one of the given error codes. If any other error is encountered,
- // a panic will occur.
- //
- // Platform errors are always printed, for information why please see:
- //
- // https://github.com/go-gl/glfw/issues/127
- //
- func acceptError(codes ...ErrorCode) error {
- // Grab the next error, if there is one.
- err := fetchError()
- if err == nil {
- return nil
- }
- // Only if the error has the specific error code accepted by the caller, do
- // we return the error.
- for _, code := range codes {
- if err.Code == code {
- return err
- }
- }
- // The error isn't accepted by the caller. If the error code is not a code
- // defined in the GLFW C documentation as a programmer error, then the
- // caller should have accepted it. This is effectively a bug in this
- // package.
- switch err.Code {
- case platformError:
- log.Println(err)
- return nil
- case notInitialized, noCurrentContext, invalidEnum, invalidValue, outOfMemory:
- panic(err)
- default:
- fmt.Println("GLFW: An invalid error was not accepted by the caller:", err)
- fmt.Println("GLFW: Please report this bug in the Go package immediately.")
- panic(err)
- }
- }
- // panicError is a helper used by functions which expect no errors (except
- // programmer errors) to occur. It will panic if it finds any such error.
- func panicError() {
- err := acceptError()
- if err != nil {
- panic(err)
- }
- }
- // fetchError fetches the next error from the error channel, it does not block
- // and returns nil if there is no error present.
- func fetchError() *Error {
- select {
- case err := <-lastError:
- return err
- default:
- return nil
- }
- }
|