From 3300f02d21f86fad18445d2fc58c77528a01f6f7 Mon Sep 17 00:00:00 2001
From: faiface <faiface@ksp.sk>
Date: Sat, 11 Feb 2017 14:09:47 +0100
Subject: [PATCH] adopt github.com/faiface/glhf

---
 canvas.go            |  34 +++---
 gltriangles.go       |  14 +--
 graphics.go          |  10 +-
 picture.go           |  12 +-
 pixelgl/attr.go      |  80 ------------
 pixelgl/doc.go       |   8 --
 pixelgl/frame.go     |  75 ------------
 pixelgl/interface.go |  11 --
 pixelgl/orphan.go    |  24 ----
 pixelgl/shader.go    | 219 ---------------------------------
 pixelgl/texture.go   | 128 -------------------
 pixelgl/util.go      |  31 -----
 pixelgl/vertex.go    | 285 -------------------------------------------
 window.go            |  26 ++--
 14 files changed, 50 insertions(+), 907 deletions(-)
 delete mode 100644 pixelgl/attr.go
 delete mode 100644 pixelgl/doc.go
 delete mode 100644 pixelgl/frame.go
 delete mode 100644 pixelgl/interface.go
 delete mode 100644 pixelgl/orphan.go
 delete mode 100644 pixelgl/shader.go
 delete mode 100644 pixelgl/texture.go
 delete mode 100644 pixelgl/util.go
 delete mode 100644 pixelgl/vertex.go

diff --git a/canvas.go b/canvas.go
index c472283..b2860fa 100644
--- a/canvas.go
+++ b/canvas.go
@@ -3,8 +3,8 @@ package pixel
 import (
 	"image/color"
 
+	"github.com/faiface/glhf"
 	"github.com/faiface/mainthread"
-	"github.com/faiface/pixel/pixelgl"
 	"github.com/go-gl/mathgl/mgl32"
 	"github.com/pkg/errors"
 )
@@ -13,10 +13,10 @@ import (
 //
 // Canvas supports TrianglesPosition, TrianglesColor and TrianglesTexture.
 type Canvas struct {
-	f *pixelgl.Frame
-	s *pixelgl.Shader
+	f *glhf.Frame
+	s *glhf.Shader
 
-	copyVs *pixelgl.VertexSlice
+	copyVs *glhf.VertexSlice
 	smooth bool
 
 	drawTd TrianglesDrawer
@@ -32,8 +32,8 @@ func NewCanvas(width, height float64, smooth bool) *Canvas {
 	c := &Canvas{smooth: smooth}
 	mainthread.Call(func() {
 		var err error
-		c.f = pixelgl.NewFrame(int(width), int(height), smooth)
-		c.s, err = pixelgl.NewShader(
+		c.f = glhf.NewFrame(int(width), int(height), smooth)
+		c.s, err = glhf.NewShader(
 			canvasVertexFormat,
 			canvasUniformFormat,
 			canvasVertexShader,
@@ -43,7 +43,7 @@ func NewCanvas(width, height float64, smooth bool) *Canvas {
 			panic(errors.Wrap(err, "failed to create canvas"))
 		}
 
-		c.copyVs = pixelgl.MakeVertexSlice(c.s, 6, 6)
+		c.copyVs = glhf.MakeVertexSlice(c.s, 6, 6)
 		c.copyVs.Begin()
 		c.copyVs.SetVertexData([]float32{
 			-1, -1, 1, 1, 1, 1, 0, 0,
@@ -79,7 +79,7 @@ func (c *Canvas) SetSize(width, height float64) {
 	}
 	mainthread.Call(func() {
 		oldF := c.f
-		c.f = pixelgl.NewFrame(int(width), int(height), c.smooth)
+		c.f = glhf.NewFrame(int(width), int(height), c.smooth)
 
 		c.f.Begin()
 		c.s.Begin()
@@ -116,7 +116,7 @@ func (c *Canvas) Clear(col color.Color) {
 	mainthread.CallNonBlock(func() {
 		c.f.Begin()
 		col := NRGBAModel.Convert(col).(NRGBA)
-		pixelgl.Clear(float32(col.R), float32(col.G), float32(col.B), float32(col.A))
+		glhf.Clear(float32(col.R), float32(col.G), float32(col.B), float32(col.A))
 		c.f.End()
 	})
 }
@@ -209,10 +209,10 @@ const (
 	canvasTextureVec2
 )
 
-var canvasVertexFormat = pixelgl.AttrFormat{
-	canvasPositionVec2: {Name: "position", Type: pixelgl.Vec2},
-	canvasColorVec4:    {Name: "color", Type: pixelgl.Vec4},
-	canvasTextureVec2:  {Name: "texture", Type: pixelgl.Vec2},
+var canvasVertexFormat = glhf.AttrFormat{
+	canvasPositionVec2: {Name: "position", Type: glhf.Vec2},
+	canvasColorVec4:    {Name: "color", Type: glhf.Vec4},
+	canvasTextureVec2:  {Name: "texture", Type: glhf.Vec2},
 }
 
 const (
@@ -221,10 +221,10 @@ const (
 	canvasBoundsVec4
 )
 
-var canvasUniformFormat = pixelgl.AttrFormat{
-	{Name: "maskColor", Type: pixelgl.Vec4},
-	{Name: "transform", Type: pixelgl.Mat3},
-	{Name: "bounds", Type: pixelgl.Vec4},
+var canvasUniformFormat = glhf.AttrFormat{
+	{Name: "maskColor", Type: glhf.Vec4},
+	{Name: "transform", Type: glhf.Mat3},
+	{Name: "bounds", Type: glhf.Vec4},
 }
 
 var canvasVertexShader = `
diff --git a/gltriangles.go b/gltriangles.go
index 73654dd..b2648a3 100644
--- a/gltriangles.go
+++ b/gltriangles.go
@@ -3,23 +3,23 @@ package pixel
 import (
 	"fmt"
 
+	"github.com/faiface/glhf"
 	"github.com/faiface/mainthread"
-	"github.com/faiface/pixel/pixelgl"
 )
 
-// NewGLTriangles returns OpenGL triangles implemented using pixelgl.VertexSlice. A few notes.
+// NewGLTriangles returns OpenGL triangles implemented using glhf.VertexSlice. A few notes.
 //
 // Triangles returned from this function support TrianglesPosition, TrianglesColor and
 // TrianglesTexture. If you need to support more, you can "override" SetLen and Update method.
 //
-// Draw method simply draws the underlying pixelgl.VertexSlice. It needs to be called in the main
+// Draw method simply draws the underlying glhf.VertexSlice. It needs to be called in the main
 // thread manually. Also, you need to take care of additional Target initialization or setting of
 // uniform attributes.
-func NewGLTriangles(shader *pixelgl.Shader, t Triangles) TargetTriangles {
+func NewGLTriangles(shader *glhf.Shader, t Triangles) TargetTriangles {
 	var gt *glTriangles
 	mainthread.Call(func() {
 		gt = &glTriangles{
-			vs:     pixelgl.MakeVertexSlice(shader, 0, t.Len()),
+			vs:     glhf.MakeVertexSlice(shader, 0, t.Len()),
 			shader: shader,
 		}
 	})
@@ -29,9 +29,9 @@ func NewGLTriangles(shader *pixelgl.Shader, t Triangles) TargetTriangles {
 }
 
 type glTriangles struct {
-	vs     *pixelgl.VertexSlice
+	vs     *glhf.VertexSlice
 	data   []float32
-	shader *pixelgl.Shader
+	shader *glhf.Shader
 }
 
 func (gt *glTriangles) Len() int {
diff --git a/graphics.go b/graphics.go
index 85c5a26..ded74b3 100644
--- a/graphics.go
+++ b/graphics.go
@@ -254,9 +254,13 @@ func (p *Polygon) Color() NRGBA {
 //
 // However, it is less expensive than using a transform on a Target.
 func (p *Polygon) SetPoints(points ...Vec) {
-	p.data.SetLen(len(points))
-	for i, pt := range points {
-		p.data[i].Position = pt
+	p.data.SetLen(3 * (len(points) - 2))
+	for i := 2; i < len(points); i++ {
+		p.data[(i-2)*3+0].Position = points[0]
+		p.data[(i-2)*3+1].Position = points[i-1]
+		p.data[(i-2)*3+2].Position = points[i]
+	}
+	for i := range p.data {
 		p.data[i].Color = p.col
 	}
 	p.td.Dirty()
diff --git a/picture.go b/picture.go
index db35f28..2a6129a 100644
--- a/picture.go
+++ b/picture.go
@@ -4,8 +4,8 @@ import (
 	"image"
 	"image/draw"
 
+	"github.com/faiface/glhf"
 	"github.com/faiface/mainthread"
-	"github.com/faiface/pixel/pixelgl"
 )
 
 // Picture is a raster picture. It is usually used with sprites.
@@ -14,7 +14,7 @@ import (
 // generated. After the creation, Pictures can be sliced (slicing creates a "sub-Picture"
 // from a Picture) into smaller Pictures.
 type Picture struct {
-	tex    *pixelgl.Texture
+	tex    *glhf.Texture
 	bounds Rect
 }
 
@@ -35,9 +35,9 @@ func NewPicture(img image.Image, smooth bool) *Picture {
 		copy(jSlice, tmp)
 	}
 
-	var tex *pixelgl.Texture
+	var tex *glhf.Texture
 	mainthread.Call(func() {
-		tex = pixelgl.NewTexture(
+		tex = glhf.NewTexture(
 			img.Bounds().Dx(),
 			img.Bounds().Dy(),
 			smooth,
@@ -49,7 +49,7 @@ func NewPicture(img image.Image, smooth bool) *Picture {
 }
 
 // PictureFromTexture returns a new Picture that spans the whole supplied Texture.
-func PictureFromTexture(tex *pixelgl.Texture) *Picture {
+func PictureFromTexture(tex *glhf.Texture) *Picture {
 	return &Picture{
 		tex:    tex,
 		bounds: R(0, 0, float64(tex.Width()), float64(tex.Height())),
@@ -88,7 +88,7 @@ func (p *Picture) Image() *image.NRGBA {
 }
 
 // Texture returns a pointer to the underlying OpenGL texture of the Picture.
-func (p *Picture) Texture() *pixelgl.Texture {
+func (p *Picture) Texture() *glhf.Texture {
 	return p.tex
 }
 
diff --git a/pixelgl/attr.go b/pixelgl/attr.go
deleted file mode 100644
index 7f78d23..0000000
--- a/pixelgl/attr.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package pixelgl
-
-// AttrFormat defines names and types of OpenGL attributes (vertex format, uniform format, etc.).
-//
-// Example:
-//   AttrFormat{{"position", Vec2}, {"color", Vec4}, {"texCoord": Vec2}}
-type AttrFormat []Attr
-
-// Size returns the total size of all attributes of the AttrFormat.
-func (af AttrFormat) Size() int {
-	total := 0
-	for _, attr := range af {
-		total += attr.Type.Size()
-	}
-	return total
-}
-
-// Attr represents an arbitrary OpenGL attribute, such as a vertex attribute or a shader
-// uniform attribute.
-type Attr struct {
-	Name string
-	Type AttrType
-}
-
-// AttrType represents the type of an OpenGL attribute.
-type AttrType int
-
-// List of all possible attribute types.
-const (
-	Int AttrType = iota
-	Float
-	Vec2
-	Vec3
-	Vec4
-	Mat2
-	Mat23
-	Mat24
-	Mat3
-	Mat32
-	Mat34
-	Mat4
-	Mat42
-	Mat43
-)
-
-// Size returns the size of a type in bytes.
-func (at AttrType) Size() int {
-	switch at {
-	case Int:
-		return 4
-	case Float:
-		return 4
-	case Vec2:
-		return 2 * 4
-	case Vec3:
-		return 3 * 4
-	case Vec4:
-		return 4 * 4
-	case Mat2:
-		return 2 * 2 * 4
-	case Mat23:
-		return 2 * 3 * 4
-	case Mat24:
-		return 2 * 4 * 4
-	case Mat3:
-		return 3 * 3 * 4
-	case Mat32:
-		return 3 * 2 * 4
-	case Mat34:
-		return 3 * 4 * 4
-	case Mat4:
-		return 4 * 4 * 4
-	case Mat42:
-		return 4 * 2 * 4
-	case Mat43:
-		return 4 * 3 * 4
-	default:
-		panic("size of vertex attribute type: invalid type")
-	}
-}
diff --git a/pixelgl/doc.go b/pixelgl/doc.go
deleted file mode 100644
index e28bdfb..0000000
--- a/pixelgl/doc.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Package pixelgl provides some abstractions around the basic OpenGL primitives and
-// operations.
-//
-// All calls should be done from the main thread using "github.com/faiface/mainthread" package.
-//
-// This package deliberately does not handle nor report OpenGL errors, it's up to you to
-// cause none.
-package pixelgl
diff --git a/pixelgl/frame.go b/pixelgl/frame.go
deleted file mode 100644
index c2ca761..0000000
--- a/pixelgl/frame.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package pixelgl
-
-import (
-	"runtime"
-
-	"github.com/faiface/mainthread"
-	"github.com/go-gl/gl/v3.3-core/gl"
-)
-
-// Frame is a fixed resolution texture that you can draw on.
-type Frame struct {
-	fb            binder
-	tex           *Texture
-	width, height int
-}
-
-// NewFrame creates a new fully transparent Frame with given dimensions in pixels.
-func NewFrame(width, height int, smooth bool) *Frame {
-	f := &Frame{
-		fb: binder{
-			restoreLoc: gl.FRAMEBUFFER_BINDING,
-			bindFunc: func(obj uint32) {
-				gl.BindFramebuffer(gl.FRAMEBUFFER, obj)
-			},
-		},
-		width:  width,
-		height: height,
-	}
-
-	gl.GenFramebuffers(1, &f.fb.obj)
-
-	f.tex = NewTexture(width, height, smooth, make([]uint8, width*height*4))
-
-	f.fb.bind()
-	gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, f.tex.tex.obj, 0)
-	f.fb.restore()
-
-	runtime.SetFinalizer(f, (*Frame).delete)
-
-	return f
-}
-
-func (f *Frame) delete() {
-	mainthread.CallNonBlock(func() {
-		gl.DeleteFramebuffers(1, &f.fb.obj)
-	})
-}
-
-// Width returns the width of the Frame in pixels.
-func (f *Frame) Width() int {
-	return f.width
-}
-
-// Height returns the height of the Frame in pixels.
-func (f *Frame) Height() int {
-	return f.height
-}
-
-// Begin binds the Frame. All draw operations will target this Frame until End is called.
-func (f *Frame) Begin() {
-	f.fb.bind()
-	gl.Viewport(0, 0, int32(f.width), int32(f.height))
-}
-
-// End unbinds the Frame. All draw operations will go to whatever was bound before this Frame.
-func (f *Frame) End() {
-	f.fb.restore()
-}
-
-// Texture returns the Texture that this Frame draws to. The Texture changes as you use the Frame.
-//
-// The Texture pointer returned from this method is always the same.
-func (f *Frame) Texture() *Texture {
-	return f.tex
-}
diff --git a/pixelgl/interface.go b/pixelgl/interface.go
deleted file mode 100644
index f651189..0000000
--- a/pixelgl/interface.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package pixelgl
-
-// BeginEnder is an interface for manipulating OpenGL state.
-//
-// OpenGL is a state machine. Every object can 'enter' it's state and 'leave' it's state. For
-// example, you can bind a buffer and unbind a buffer, bind a texture and unbind it, use shader
-// and unuse it, and so on.
-type BeginEnder interface {
-	Begin()
-	End()
-}
diff --git a/pixelgl/orphan.go b/pixelgl/orphan.go
deleted file mode 100644
index eba99bc..0000000
--- a/pixelgl/orphan.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package pixelgl
-
-import "github.com/go-gl/gl/v3.3-core/gl"
-
-// Init initializes OpenGL by loading function pointers from the active OpenGL context.
-// This function must be manually run inside the main thread (using "github.com/faiface/mainthread"
-// package).
-//
-// It must be called under the presence of an active OpenGL context, e.g., always after calling
-// window.MakeContextCurrent(). Also, always call this function when switching contexts.
-func Init() {
-	err := gl.Init()
-	if err != nil {
-		panic(err)
-	}
-	gl.Enable(gl.BLEND)
-	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
-}
-
-// Clear clears the current framebuffer or window with the given color.
-func Clear(r, g, b, a float32) {
-	gl.ClearColor(r, g, b, a)
-	gl.Clear(gl.COLOR_BUFFER_BIT)
-}
diff --git a/pixelgl/shader.go b/pixelgl/shader.go
deleted file mode 100644
index 81f8218..0000000
--- a/pixelgl/shader.go
+++ /dev/null
@@ -1,219 +0,0 @@
-package pixelgl
-
-import (
-	"fmt"
-	"runtime"
-
-	"github.com/faiface/mainthread"
-	"github.com/go-gl/gl/v3.3-core/gl"
-	"github.com/go-gl/mathgl/mgl32"
-)
-
-// Shader is an OpenGL shader program.
-type Shader struct {
-	program    binder
-	vertexFmt  AttrFormat
-	uniformFmt AttrFormat
-	uniformLoc []int32
-}
-
-// NewShader creates a new shader program from the specified vertex shader and fragment shader
-// sources.
-//
-// Note that vertexShader and fragmentShader parameters must contain the source code, they're
-// not filenames.
-func NewShader(vertexFmt, uniformFmt AttrFormat, vertexShader, fragmentShader string) (*Shader, error) {
-	shader := &Shader{
-		program: binder{
-			restoreLoc: gl.CURRENT_PROGRAM,
-			bindFunc: func(obj uint32) {
-				gl.UseProgram(obj)
-			},
-		},
-		vertexFmt:  vertexFmt,
-		uniformFmt: uniformFmt,
-		uniformLoc: make([]int32, len(uniformFmt)),
-	}
-
-	var vshader, fshader uint32
-
-	// vertex shader
-	{
-		vshader = gl.CreateShader(gl.VERTEX_SHADER)
-		src, free := gl.Strs(vertexShader)
-		defer free()
-		length := int32(len(vertexShader))
-		gl.ShaderSource(vshader, 1, src, &length)
-		gl.CompileShader(vshader)
-
-		var success int32
-		gl.GetShaderiv(vshader, gl.COMPILE_STATUS, &success)
-		if success == gl.FALSE {
-			var logLen int32
-			gl.GetShaderiv(vshader, gl.INFO_LOG_LENGTH, &logLen)
-
-			infoLog := make([]byte, logLen)
-			gl.GetShaderInfoLog(vshader, logLen, nil, &infoLog[0])
-			return nil, fmt.Errorf("error compiling vertex shader: %s", string(infoLog))
-		}
-
-		defer gl.DeleteShader(vshader)
-	}
-
-	// fragment shader
-	{
-		fshader = gl.CreateShader(gl.FRAGMENT_SHADER)
-		src, free := gl.Strs(fragmentShader)
-		defer free()
-		length := int32(len(fragmentShader))
-		gl.ShaderSource(fshader, 1, src, &length)
-		gl.CompileShader(fshader)
-
-		var success int32
-		gl.GetShaderiv(fshader, gl.COMPILE_STATUS, &success)
-		if success == gl.FALSE {
-			var logLen int32
-			gl.GetShaderiv(fshader, gl.INFO_LOG_LENGTH, &logLen)
-
-			infoLog := make([]byte, logLen)
-			gl.GetShaderInfoLog(fshader, logLen, nil, &infoLog[0])
-			return nil, fmt.Errorf("error compiling fragment shader: %s", string(infoLog))
-		}
-
-		defer gl.DeleteShader(fshader)
-	}
-
-	// shader program
-	{
-		shader.program.obj = gl.CreateProgram()
-		gl.AttachShader(shader.program.obj, vshader)
-		gl.AttachShader(shader.program.obj, fshader)
-		gl.LinkProgram(shader.program.obj)
-
-		var success int32
-		gl.GetProgramiv(shader.program.obj, gl.LINK_STATUS, &success)
-		if success == gl.FALSE {
-			var logLen int32
-			gl.GetProgramiv(shader.program.obj, gl.INFO_LOG_LENGTH, &logLen)
-
-			infoLog := make([]byte, logLen)
-			gl.GetProgramInfoLog(shader.program.obj, logLen, nil, &infoLog[0])
-			return nil, fmt.Errorf("error linking shader program: %s", string(infoLog))
-		}
-	}
-
-	// uniforms
-	for i, uniform := range uniformFmt {
-		loc := gl.GetUniformLocation(shader.program.obj, gl.Str(uniform.Name+"\x00"))
-		shader.uniformLoc[i] = loc
-	}
-
-	runtime.SetFinalizer(shader, (*Shader).delete)
-
-	return shader, nil
-}
-
-func (s *Shader) delete() {
-	mainthread.CallNonBlock(func() {
-		gl.DeleteProgram(s.program.obj)
-	})
-}
-
-// VertexFormat returns the vertex attribute format of this Shader. Do not change it.
-func (s *Shader) VertexFormat() AttrFormat {
-	return s.vertexFmt
-}
-
-// UniformFormat returns the uniform attribute format of this Shader. Do not change it.
-func (s *Shader) UniformFormat() AttrFormat {
-	return s.uniformFmt
-}
-
-// SetUniformAttr sets the value of a uniform attribute of this Shader. The attribute is
-// specified by the index in the Shader's uniform format.
-//
-// If the uniform attribute does not exist in the Shader, this method returns false.
-//
-// Supplied value must correspond to the type of the attribute. Correct types are these
-// (right-hand is the type of the value):
-//   Attr{Type: Int}:   int32
-//   Attr{Type: Float}: float32
-//   Attr{Type: Vec2}:  mgl32.Vec2
-//   Attr{Type: Vec3}:  mgl32.Vec3
-//   Attr{Type: Vec4}:  mgl32.Vec4
-//   Attr{Type: Mat2}:  mgl32.Mat2
-//   Attr{Type: Mat23}: mgl32.Mat2x3
-//   Attr{Type: Mat24}: mgl32.Mat2x4
-//   Attr{Type: Mat3}:  mgl32.Mat3
-//   Attr{Type: Mat32}: mgl32.Mat3x2
-//   Attr{Type: Mat34}: mgl32.Mat3x4
-//   Attr{Type: Mat4}:  mgl32.Mat4
-//   Attr{Type: Mat42}: mgl32.Mat4x2
-//   Attr{Type: Mat43}: mgl32.Mat4x3
-// No other types are supported.
-//
-// The Shader must be bound before calling this method.
-func (s *Shader) SetUniformAttr(uniform int, value interface{}) (ok bool) {
-	if s.uniformLoc[uniform] < 0 {
-		return false
-	}
-
-	switch s.uniformFmt[uniform].Type {
-	case Int:
-		value := value.(int32)
-		gl.Uniform1iv(s.uniformLoc[uniform], 1, &value)
-	case Float:
-		value := value.(float32)
-		gl.Uniform1fv(s.uniformLoc[uniform], 1, &value)
-	case Vec2:
-		value := value.(mgl32.Vec2)
-		gl.Uniform2fv(s.uniformLoc[uniform], 1, &value[0])
-	case Vec3:
-		value := value.(mgl32.Vec3)
-		gl.Uniform3fv(s.uniformLoc[uniform], 1, &value[0])
-	case Vec4:
-		value := value.(mgl32.Vec4)
-		gl.Uniform4fv(s.uniformLoc[uniform], 1, &value[0])
-	case Mat2:
-		value := value.(mgl32.Mat2)
-		gl.UniformMatrix2fv(s.uniformLoc[uniform], 1, false, &value[0])
-	case Mat23:
-		value := value.(mgl32.Mat2x3)
-		gl.UniformMatrix2x3fv(s.uniformLoc[uniform], 1, false, &value[0])
-	case Mat24:
-		value := value.(mgl32.Mat2x4)
-		gl.UniformMatrix2x4fv(s.uniformLoc[uniform], 1, false, &value[0])
-	case Mat3:
-		value := value.(mgl32.Mat3)
-		gl.UniformMatrix3fv(s.uniformLoc[uniform], 1, false, &value[0])
-	case Mat32:
-		value := value.(mgl32.Mat3x2)
-		gl.UniformMatrix3x2fv(s.uniformLoc[uniform], 1, false, &value[0])
-	case Mat34:
-		value := value.(mgl32.Mat3x4)
-		gl.UniformMatrix3x4fv(s.uniformLoc[uniform], 1, false, &value[0])
-	case Mat4:
-		value := value.(mgl32.Mat4)
-		gl.UniformMatrix4fv(s.uniformLoc[uniform], 1, false, &value[0])
-	case Mat42:
-		value := value.(mgl32.Mat4x2)
-		gl.UniformMatrix4x2fv(s.uniformLoc[uniform], 1, false, &value[0])
-	case Mat43:
-		value := value.(mgl32.Mat4x3)
-		gl.UniformMatrix4x3fv(s.uniformLoc[uniform], 1, false, &value[0])
-	default:
-		panic("set uniform attr: invalid attribute type")
-	}
-
-	return true
-}
-
-// Begin binds the Shader program. This is necessary before using the Shader.
-func (s *Shader) Begin() {
-	s.program.bind()
-}
-
-// End unbinds the Shader program and restores the previous one.
-func (s *Shader) End() {
-	s.program.restore()
-}
diff --git a/pixelgl/texture.go b/pixelgl/texture.go
deleted file mode 100644
index eba9fef..0000000
--- a/pixelgl/texture.go
+++ /dev/null
@@ -1,128 +0,0 @@
-package pixelgl
-
-import (
-	"runtime"
-
-	"github.com/faiface/mainthread"
-	"github.com/go-gl/gl/v3.3-core/gl"
-	"github.com/go-gl/mathgl/mgl32"
-)
-
-// Texture is an OpenGL texture.
-type Texture struct {
-	tex           binder
-	width, height int
-}
-
-// NewTexture creates a new texture with the specified width and height with some initial
-// pixel values. The pixels must be a sequence of RGBA values (one byte per component).
-func NewTexture(width, height int, smooth bool, pixels []uint8) *Texture {
-	tex := &Texture{
-		tex: binder{
-			restoreLoc: gl.TEXTURE_BINDING_2D,
-			bindFunc: func(obj uint32) {
-				gl.BindTexture(gl.TEXTURE_2D, obj)
-			},
-		},
-		width:  width,
-		height: height,
-	}
-
-	gl.GenTextures(1, &tex.tex.obj)
-
-	tex.Begin()
-	defer tex.End()
-
-	// initial data
-	gl.TexImage2D(
-		gl.TEXTURE_2D,
-		0,
-		gl.RGBA,
-		int32(width),
-		int32(height),
-		0,
-		gl.RGBA,
-		gl.UNSIGNED_BYTE,
-		gl.Ptr(pixels),
-	)
-
-	borderColor := mgl32.Vec4{0, 0, 0, 0}
-	gl.TexParameterfv(gl.TEXTURE_2D, gl.TEXTURE_BORDER_COLOR, &borderColor[0])
-	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_BORDER)
-	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_BORDER)
-
-	if smooth {
-		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
-		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
-	} else {
-		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
-		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
-	}
-
-	runtime.SetFinalizer(tex, (*Texture).delete)
-
-	return tex
-}
-
-func (t *Texture) delete() {
-	mainthread.CallNonBlock(func() {
-		gl.DeleteTextures(1, &t.tex.obj)
-	})
-}
-
-// Width returns the width of the Texture in pixels.
-func (t *Texture) Width() int {
-	return t.width
-}
-
-// Height returns the height of the Texture in pixels.
-func (t *Texture) Height() int {
-	return t.height
-}
-
-// SetPixels sets the content of a sub-region of the Texture. Pixels must be an RGBA byte sequence.
-func (t *Texture) SetPixels(x, y, w, h int, pixels []uint8) {
-	if len(pixels) != w*h*4 {
-		panic("set pixels: wrong number of pixels")
-	}
-	gl.TexSubImage2D(
-		gl.TEXTURE_2D,
-		0,
-		int32(x),
-		int32(y),
-		int32(w),
-		int32(h),
-		gl.RGBA,
-		gl.UNSIGNED_BYTE,
-		gl.Ptr(pixels),
-	)
-}
-
-// Pixels returns the content of a sub-region of the Texture as an RGBA byte sequence.
-func (t *Texture) Pixels(x, y, w, h int) []uint8 {
-	pixels := make([]uint8, t.width*t.height*4)
-	gl.GetTexImage(
-		gl.TEXTURE_2D,
-		0,
-		gl.RGBA,
-		gl.UNSIGNED_BYTE,
-		gl.Ptr(pixels),
-	)
-	subPixels := make([]uint8, w*h*4)
-	for i := 0; i < h; i++ {
-		row := pixels[(i+y)*t.width*4+x*4 : (i+y)*t.width*4+(x+w)*4]
-		subRow := subPixels[i*w*4 : (i+1)*w*4]
-		copy(subRow, row)
-	}
-	return subPixels
-}
-
-// Begin binds the Texture. This is necessary before using the Texture.
-func (t *Texture) Begin() {
-	t.tex.bind()
-}
-
-// End unbinds the Texture and restores the previous one.
-func (t *Texture) End() {
-	t.tex.restore()
-}
diff --git a/pixelgl/util.go b/pixelgl/util.go
deleted file mode 100644
index 4792d55..0000000
--- a/pixelgl/util.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package pixelgl
-
-import "github.com/go-gl/gl/v3.3-core/gl"
-
-type binder struct {
-	restoreLoc uint32
-	bindFunc   func(uint32)
-
-	obj uint32
-
-	prev []uint32
-}
-
-func (b *binder) bind() *binder {
-	var prev int32
-	gl.GetIntegerv(b.restoreLoc, &prev)
-	b.prev = append(b.prev, uint32(prev))
-
-	if b.prev[len(b.prev)-1] != b.obj {
-		b.bindFunc(b.obj)
-	}
-	return b
-}
-
-func (b *binder) restore() *binder {
-	if b.prev[len(b.prev)-1] != b.obj {
-		b.bindFunc(b.prev[len(b.prev)-1])
-	}
-	b.prev = b.prev[:len(b.prev)-1]
-	return b
-}
diff --git a/pixelgl/vertex.go b/pixelgl/vertex.go
deleted file mode 100644
index a1d70e1..0000000
--- a/pixelgl/vertex.go
+++ /dev/null
@@ -1,285 +0,0 @@
-package pixelgl
-
-import (
-	"fmt"
-	"runtime"
-
-	"github.com/faiface/mainthread"
-	"github.com/go-gl/gl/v3.3-core/gl"
-	"github.com/pkg/errors"
-)
-
-// VertexSlice points to a portion of (or possibly whole) vertex array. It is used as a pointer,
-// contrary to Go's builtin slices. This is, so that append can be 'in-place'. That's for the good,
-// because Begin/End-ing a VertexSlice would become super confusing, if append returned a new
-// VertexSlice.
-//
-// It also implements all basic slice-like operations: appending, sub-slicing, etc.
-//
-// Note that you need to Begin a VertexSlice before getting or updating it's elements or drawing it.
-// After you're done with it, you need to End it.
-type VertexSlice struct {
-	va   *vertexArray
-	i, j int
-}
-
-// MakeVertexSlice allocates a new vertex array with specified capacity and returns a VertexSlice
-// that points to it's first len elements.
-//
-// Note, that a vertex array is specialized for a specific shader and can't be used with another
-// shader.
-func MakeVertexSlice(shader *Shader, len, cap int) *VertexSlice {
-	if len > cap {
-		panic("failed to make vertex slice: len > cap")
-	}
-	return &VertexSlice{
-		va: newVertexArray(shader, cap),
-		i:  0,
-		j:  len,
-	}
-}
-
-// VertexFormat returns the format of vertex attributes inside the underlying vertex array of this
-// VertexSlice.
-func (vs *VertexSlice) VertexFormat() AttrFormat {
-	return vs.va.format
-}
-
-// Stride returns the number of float32 elements occupied by one vertex.
-func (vs *VertexSlice) Stride() int {
-	return vs.va.stride / 4
-}
-
-// Len returns the length of the VertexSlice (number of vertices).
-func (vs *VertexSlice) Len() int {
-	return vs.j - vs.i
-}
-
-// Cap returns the capacity of an underlying vertex array.
-func (vs *VertexSlice) Cap() int {
-	return vs.va.cap - vs.i
-}
-
-// SetLen resizes the VertexSlice to length len.
-func (vs *VertexSlice) SetLen(len int) {
-	vs.End() // vs must have been Begin-ed before calling this method
-	*vs = vs.grow(len)
-	vs.Begin()
-}
-
-// grow returns supplied vs with length changed to len. Allocates new underlying vertex array if
-// necessary. The original content is preserved.
-func (vs VertexSlice) grow(len int) VertexSlice {
-	if len <= vs.Cap() {
-		// capacity sufficient
-		return VertexSlice{
-			va: vs.va,
-			i:  vs.i,
-			j:  vs.i + len,
-		}
-	}
-
-	// grow the capacity
-	newCap := vs.Cap()
-	if newCap < 1024 {
-		newCap += newCap
-	} else {
-		newCap += newCap / 4
-	}
-	if newCap < len {
-		newCap = len
-	}
-	newVs := VertexSlice{
-		va: newVertexArray(vs.va.shader, newCap),
-		i:  0,
-		j:  len,
-	}
-	// preserve the original content
-	newVs.Begin()
-	newVs.Slice(0, vs.Len()).SetVertexData(vs.VertexData())
-	newVs.End()
-	return newVs
-}
-
-// Slice returns a sub-slice of this VertexSlice covering the range [i, j) (relative to this
-// VertexSlice).
-//
-// Note, that the returned VertexSlice shares an underlying vertex array with the original
-// VertexSlice. Modifying the contents of one modifies corresponding contents of the other.
-func (vs *VertexSlice) Slice(i, j int) *VertexSlice {
-	if i < 0 || j < i || j > vs.va.cap {
-		panic("failed to slice vertex slice: index out of range")
-	}
-	return &VertexSlice{
-		va: vs.va,
-		i:  vs.i + i,
-		j:  vs.i + j,
-	}
-}
-
-// SetVertexData sets the contents of the VertexSlice.
-//
-// The data is a slice of float32's, where each vertex attribute occupies a certain number of
-// elements. Namely, Float occupies 1, Vec2 occupies 2, Vec3 occupies 3 and Vec4 occupies 4. The
-// attribues in the data slice must be in the same order as in the vertex format of this Vertex
-// Slice.
-//
-// If the length of vertices does not match the length of the VertexSlice, this methdo panics.
-func (vs *VertexSlice) SetVertexData(data []float32) {
-	if len(data)/vs.Stride() != vs.Len() {
-		fmt.Println(len(data)/vs.Stride(), vs.Len())
-		panic("set vertex data: wrong length of vertices")
-	}
-	vs.va.setVertexData(vs.i, vs.j, data)
-}
-
-// VertexData returns the contents of the VertexSlice.
-//
-// The data is in the same format as with SetVertexData.
-func (vs *VertexSlice) VertexData() []float32 {
-	return vs.va.vertexData(vs.i, vs.j)
-}
-
-// Draw draws the content of the VertexSlice.
-func (vs *VertexSlice) Draw() {
-	vs.va.draw(vs.i, vs.j)
-}
-
-// Begin binds the underlying vertex array. Calling this method is necessary before using the VertexSlice.
-func (vs *VertexSlice) Begin() {
-	vs.va.begin()
-}
-
-// End unbinds the underlying vertex array. Call this method when you're done with VertexSlice.
-func (vs *VertexSlice) End() {
-	vs.va.end()
-}
-
-type vertexArray struct {
-	vao, vbo binder
-	cap      int
-	format   AttrFormat
-	stride   int
-	offset   []int
-	shader   *Shader
-}
-
-const vertexArrayMinCap = 4
-
-func newVertexArray(shader *Shader, cap int) *vertexArray {
-	if cap < vertexArrayMinCap {
-		cap = vertexArrayMinCap
-	}
-
-	va := &vertexArray{
-		vao: binder{
-			restoreLoc: gl.VERTEX_ARRAY_BINDING,
-			bindFunc: func(obj uint32) {
-				gl.BindVertexArray(obj)
-			},
-		},
-		vbo: binder{
-			restoreLoc: gl.ARRAY_BUFFER_BINDING,
-			bindFunc: func(obj uint32) {
-				gl.BindBuffer(gl.ARRAY_BUFFER, obj)
-			},
-		},
-		cap:    cap,
-		format: shader.VertexFormat(),
-		stride: shader.VertexFormat().Size(),
-		offset: make([]int, len(shader.VertexFormat())),
-		shader: shader,
-	}
-
-	offset := 0
-	for i, attr := range va.format {
-		switch attr.Type {
-		case Float, Vec2, Vec3, Vec4:
-		default:
-			panic(errors.New("failed to create vertex array: invalid attribute type"))
-		}
-		va.offset[i] = offset
-		offset += attr.Type.Size()
-	}
-
-	gl.GenVertexArrays(1, &va.vao.obj)
-
-	va.vao.bind()
-
-	gl.GenBuffers(1, &va.vbo.obj)
-	defer va.vbo.bind().restore()
-
-	emptyData := make([]byte, cap*va.stride)
-	gl.BufferData(gl.ARRAY_BUFFER, len(emptyData), gl.Ptr(emptyData), gl.DYNAMIC_DRAW)
-
-	for i, attr := range va.format {
-		loc := gl.GetAttribLocation(shader.program.obj, gl.Str(attr.Name+"\x00"))
-
-		var size int32
-		switch attr.Type {
-		case Float:
-			size = 1
-		case Vec2:
-			size = 2
-		case Vec3:
-			size = 3
-		case Vec4:
-			size = 4
-		}
-
-		gl.VertexAttribPointer(
-			uint32(loc),
-			size,
-			gl.FLOAT,
-			false,
-			int32(va.stride),
-			gl.PtrOffset(va.offset[i]),
-		)
-		gl.EnableVertexAttribArray(uint32(loc))
-	}
-
-	va.vao.restore()
-
-	runtime.SetFinalizer(va, (*vertexArray).delete)
-
-	return va
-}
-
-func (va *vertexArray) delete() {
-	mainthread.CallNonBlock(func() {
-		gl.DeleteVertexArrays(1, &va.vao.obj)
-		gl.DeleteBuffers(1, &va.vbo.obj)
-	})
-}
-
-func (va *vertexArray) begin() {
-	va.vao.bind()
-	va.vbo.bind()
-}
-
-func (va *vertexArray) end() {
-	va.vbo.restore()
-	va.vao.restore()
-}
-
-func (va *vertexArray) draw(i, j int) {
-	gl.DrawArrays(gl.TRIANGLES, int32(i), int32(i+j))
-}
-
-func (va *vertexArray) setVertexData(i, j int, data []float32) {
-	if j-i == 0 {
-		// avoid setting 0 bytes of buffer data
-		return
-	}
-	gl.BufferSubData(gl.ARRAY_BUFFER, i*va.stride, len(data)*4, gl.Ptr(data))
-}
-
-func (va *vertexArray) vertexData(i, j int) []float32 {
-	if j-i == 0 {
-		// avoid getting 0 bytes of buffer data
-		return nil
-	}
-	data := make([]float32, (j-i)*va.stride/4)
-	gl.GetBufferSubData(gl.ARRAY_BUFFER, i*va.stride, len(data)*4, gl.Ptr(data))
-	return data
-}
diff --git a/window.go b/window.go
index c962602..5600f25 100644
--- a/window.go
+++ b/window.go
@@ -5,8 +5,8 @@ import (
 
 	"runtime"
 
+	"github.com/faiface/glhf"
 	"github.com/faiface/mainthread"
-	"github.com/faiface/pixel/pixelgl"
 	"github.com/go-gl/glfw/v3.2/glfw"
 	"github.com/pkg/errors"
 )
@@ -56,12 +56,12 @@ type WindowConfig struct {
 
 // Window is a window handler. Use this type to manipulate a window (input, drawing, ...).
 type Window struct {
-	window  *glfw.Window
-	config  WindowConfig
+	window *glfw.Window
+	config WindowConfig
 
 	canvas   *Canvas
-	canvasVs *pixelgl.VertexSlice
-	shader   *pixelgl.Shader
+	canvasVs *glhf.VertexSlice
+	shader   *glhf.Shader
 
 	// need to save these to correctly restore a fullscreen window
 	restore struct {
@@ -121,7 +121,7 @@ func NewWindow(config WindowConfig) (*Window, error) {
 		w.begin()
 		w.end()
 
-		w.shader, err = pixelgl.NewShader(
+		w.shader, err = glhf.NewShader(
 			windowVertexFormat,
 			windowUniformFormat,
 			windowVertexShader,
@@ -131,7 +131,7 @@ func NewWindow(config WindowConfig) (*Window, error) {
 			return err
 		}
 
-		w.canvasVs = pixelgl.MakeVertexSlice(w.shader, 6, 6)
+		w.canvasVs = glhf.MakeVertexSlice(w.shader, 6, 6)
 		w.canvasVs.Begin()
 		w.canvasVs.SetVertexData([]float32{
 			-1, -1, 0, 0,
@@ -179,7 +179,7 @@ func (w *Window) Update() {
 	mainthread.Call(func() {
 		w.begin()
 
-		pixelgl.Clear(0, 0, 0, 0)
+		glhf.Clear(0, 0, 0, 0)
 		w.shader.Begin()
 		w.canvas.f.Texture().Begin()
 		w.canvasVs.Begin()
@@ -354,7 +354,7 @@ func (w *Window) Restore() {
 func (w *Window) begin() {
 	if currentWindow != w {
 		w.window.MakeContextCurrent()
-		pixelgl.Init()
+		glhf.Init()
 		currentWindow = w
 	}
 }
@@ -394,12 +394,12 @@ const (
 	windowTextureVec2
 )
 
-var windowVertexFormat = pixelgl.AttrFormat{
-	windowPositionVec2: {Name: "position", Type: pixelgl.Vec2},
-	windowTextureVec2:  {Name: "texture", Type: pixelgl.Vec2},
+var windowVertexFormat = glhf.AttrFormat{
+	windowPositionVec2: {Name: "position", Type: glhf.Vec2},
+	windowTextureVec2:  {Name: "texture", Type: glhf.Vec2},
 }
 
-var windowUniformFormat = pixelgl.AttrFormat{}
+var windowUniformFormat = glhf.AttrFormat{}
 
 var windowVertexShader = `
 #version 330 core
-- 
GitLab