From c5c93d94426746cde675fbf2551d6981c0a7f294 Mon Sep 17 00:00:00 2001 From: faiface Date: Wed, 23 Nov 2016 18:06:55 +0100 Subject: [PATCH] add error handling --- pixelgl/error.go | 41 +++++++++++++++++++++++++++++++++++++++++ pixelgl/texture.go | 18 ++++++++++++++---- pixelgl/thread.go | 1 + pixelgl/vertex.go | 25 +++++++++++++++++++------ 4 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 pixelgl/error.go diff --git a/pixelgl/error.go b/pixelgl/error.go new file mode 100644 index 0000000..9077856 --- /dev/null +++ b/pixelgl/error.go @@ -0,0 +1,41 @@ +package pixelgl + +import ( + "github.com/go-gl/gl/v3.3-core/gl" + "github.com/pkg/errors" +) + +// GetLastError returns (and consumes) the last error generated by OpenGL. +// If no error has been generated, this function returns nil. +// +// Call this function only inside the OpenGL thread (Do, DoErr or DoVal function). It's not guaranteed +// to work correctly outside of it, because the thread swallows extra unchecked errors. +func GetLastError() error { + err := uint32(gl.NO_ERROR) + for e := gl.GetError(); e != gl.NO_ERROR; e = gl.GetError() { + err = e + } + if err == gl.NO_ERROR { + return nil + } + switch err { + case gl.INVALID_ENUM: + return errors.New("invalid enum") + case gl.INVALID_VALUE: + return errors.New("invalid value") + case gl.INVALID_OPERATION: + return errors.New("invalid operation") + case gl.STACK_OVERFLOW: + return errors.New("stack overflow") + case gl.STACK_UNDERFLOW: + return errors.New("stack underflow") + case gl.OUT_OF_MEMORY: + return errors.New("out of memory") + case gl.INVALID_FRAMEBUFFER_OPERATION: + return errors.New("invalid framebuffer operation") + case gl.CONTEXT_LOST: + return errors.New("context lost") + default: + return errors.New("unknown error") + } +} diff --git a/pixelgl/texture.go b/pixelgl/texture.go index e56395b..06211f9 100644 --- a/pixelgl/texture.go +++ b/pixelgl/texture.go @@ -1,6 +1,9 @@ package pixelgl -import "github.com/go-gl/gl/v3.3-core/gl" +import ( + "github.com/go-gl/gl/v3.3-core/gl" + "github.com/pkg/errors" +) // Texture is an OpenGL texture. type Texture struct { @@ -10,11 +13,12 @@ type Texture struct { // NewTexture creates a new texture with the specified width and height. // The pixels must be a sequence of RGBA values. -func NewTexture(parent BeginEnder, width, height int, pixels []uint8) *Texture { +func NewTexture(parent BeginEnder, width, height int, pixels []uint8) (*Texture, error) { texture := &Texture{parent: parent} - Do(func() { + err := DoErr(func() error { gl.GenTextures(1, &texture.tex) gl.BindTexture(gl.TEXTURE_2D, texture.tex) + gl.TexImage2D( gl.TEXTURE_2D, 0, @@ -27,9 +31,15 @@ func NewTexture(parent BeginEnder, width, height int, pixels []uint8) *Texture { gl.Ptr(pixels), ) gl.GenerateMipmap(gl.TEXTURE_2D) + gl.BindTexture(gl.TEXTURE_2D, 0) + + return GetLastError() }) - return texture + if err != nil { + return nil, errors.Wrap(err, "failed to create a texture") + } + return texture, nil } // Begin binds a texture. diff --git a/pixelgl/thread.go b/pixelgl/thread.go index ffb2a61..555faef 100644 --- a/pixelgl/thread.go +++ b/pixelgl/thread.go @@ -16,6 +16,7 @@ func init() { go func() { runtime.LockOSThread() for f := range callQueue { + GetLastError() // swallow unchecked errors f() } }() diff --git a/pixelgl/vertex.go b/pixelgl/vertex.go index 836df5b..d46919a 100644 --- a/pixelgl/vertex.go +++ b/pixelgl/vertex.go @@ -1,6 +1,9 @@ package pixelgl -import "github.com/go-gl/gl/v3.3-core/gl" +import ( + "github.com/go-gl/gl/v3.3-core/gl" + "github.com/pkg/errors" +) // VertexFormat defines a data format in a vertex buffer. // @@ -96,13 +99,13 @@ type VertexArray struct { } // NewVertexArray creates a new vertex array and wraps another BeginEnder around it. -func NewVertexArray(parent BeginEnder, format VertexFormat, mode VertexDrawMode, usage VertexUsage, data []float64) *VertexArray { +func NewVertexArray(parent BeginEnder, format VertexFormat, mode VertexDrawMode, usage VertexUsage, data []float64) (*VertexArray, error) { va := &VertexArray{ parent: parent, format: format, mode: mode, } - Do(func() { + err := DoErr(func() error { gl.GenVertexArrays(1, &va.vao) gl.BindVertexArray(va.vao) @@ -129,8 +132,13 @@ func NewVertexArray(parent BeginEnder, format VertexFormat, mode VertexDrawMode, gl.BindBuffer(gl.ARRAY_BUFFER, 0) gl.BindVertexArray(0) + + return GetLastError() }) - return va + if err != nil { + return nil, errors.Wrap(err, "failed to create a vertex array") + } + return va, nil } // VertexFormat returns the format of the vertices inside a vertex array. @@ -164,12 +172,17 @@ func (va *VertexArray) Draw() { // UpdateData overwrites the current vertex array data starting at the index offset. // // Offset is not a number of bytes, instead, it's an index in the array. -func (va *VertexArray) UpdateData(offset int, data []float64) { - Do(func() { +func (va *VertexArray) UpdateData(offset int, data []float64) error { + err := DoErr(func() error { gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo) gl.BufferSubData(gl.ARRAY_BUFFER, 8*offset, 8*len(data), gl.Ptr(data)) gl.BindBuffer(gl.ARRAY_BUFFER, 0) + return GetLastError() }) + if err != nil { + return errors.Wrap(err, "failed to update vertex array") + } + return nil } // Begin binds a vertex array and it's associated vertex buffer.