adopt github.com/faiface/mainthread package + frame prototype
This commit is contained in:
parent
de21a40184
commit
7a7b2f2588
8
input.go
8
input.go
|
@ -1,7 +1,7 @@
|
||||||
package pixel
|
package pixel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/faiface/pixel/pixelgl"
|
"github.com/faiface/mainthread"
|
||||||
"github.com/go-gl/glfw/v3.2/glfw"
|
"github.com/go-gl/glfw/v3.2/glfw"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ func (w *Window) JustReleased(button Button) bool {
|
||||||
// MousePosition returns the current mouse position relative to the window.
|
// MousePosition returns the current mouse position relative to the window.
|
||||||
func (w *Window) MousePosition() Vec {
|
func (w *Window) MousePosition() Vec {
|
||||||
var x, y, width, height float64
|
var x, y, width, height float64
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
x, y = w.window.GetCursorPos()
|
x, y = w.window.GetCursorPos()
|
||||||
wi, hi := w.window.GetSize()
|
wi, hi := w.window.GetSize()
|
||||||
width, height = float64(wi), float64(hi)
|
width, height = float64(wi), float64(hi)
|
||||||
|
@ -187,7 +187,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w *Window) initInput() {
|
func (w *Window) initInput() {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.window.SetMouseButtonCallback(func(_ *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) {
|
w.window.SetMouseButtonCallback(func(_ *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) {
|
||||||
switch action {
|
switch action {
|
||||||
case glfw.Press:
|
case glfw.Press:
|
||||||
|
@ -220,7 +220,7 @@ func (w *Window) updateInput() {
|
||||||
w.currInp.scroll -= w.tempInp.scroll
|
w.currInp.scroll -= w.tempInp.scroll
|
||||||
|
|
||||||
// get events (usually calls callbacks, but callbacks can be called outside too)
|
// get events (usually calls callbacks, but callbacks can be called outside too)
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
glfw.PollEvents()
|
glfw.PollEvents()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
18
monitor.go
18
monitor.go
|
@ -1,7 +1,7 @@
|
||||||
package pixel
|
package pixel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/faiface/pixel/pixelgl"
|
"github.com/faiface/mainthread"
|
||||||
"github.com/go-gl/glfw/v3.2/glfw"
|
"github.com/go-gl/glfw/v3.2/glfw"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ type Monitor struct {
|
||||||
|
|
||||||
// PrimaryMonitor returns the main monitor (usually the one with the taskbar and stuff).
|
// PrimaryMonitor returns the main monitor (usually the one with the taskbar and stuff).
|
||||||
func PrimaryMonitor() *Monitor {
|
func PrimaryMonitor() *Monitor {
|
||||||
monitor := pixelgl.DoVal(func() interface{} {
|
monitor := mainthread.CallVal(func() interface{} {
|
||||||
return glfw.GetPrimaryMonitor()
|
return glfw.GetPrimaryMonitor()
|
||||||
}).(*glfw.Monitor)
|
}).(*glfw.Monitor)
|
||||||
return &Monitor{
|
return &Monitor{
|
||||||
|
@ -23,7 +23,7 @@ func PrimaryMonitor() *Monitor {
|
||||||
// Monitors returns a slice of all currently available monitors.
|
// Monitors returns a slice of all currently available monitors.
|
||||||
func Monitors() []*Monitor {
|
func Monitors() []*Monitor {
|
||||||
var monitors []*Monitor
|
var monitors []*Monitor
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
for _, monitor := range glfw.GetMonitors() {
|
for _, monitor := range glfw.GetMonitors() {
|
||||||
monitors = append(monitors, &Monitor{monitor: monitor})
|
monitors = append(monitors, &Monitor{monitor: monitor})
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ func Monitors() []*Monitor {
|
||||||
|
|
||||||
// Name returns a human-readable name of a monitor.
|
// Name returns a human-readable name of a monitor.
|
||||||
func (m *Monitor) Name() string {
|
func (m *Monitor) Name() string {
|
||||||
name := pixelgl.DoVal(func() interface{} {
|
name := mainthread.CallVal(func() interface{} {
|
||||||
return m.monitor.GetName()
|
return m.monitor.GetName()
|
||||||
}).(string)
|
}).(string)
|
||||||
return name
|
return name
|
||||||
|
@ -42,7 +42,7 @@ func (m *Monitor) Name() string {
|
||||||
// PhysicalSize returns the size of the display area of a monitor in millimeters.
|
// PhysicalSize returns the size of the display area of a monitor in millimeters.
|
||||||
func (m *Monitor) PhysicalSize() (width, height float64) {
|
func (m *Monitor) PhysicalSize() (width, height float64) {
|
||||||
var wi, hi int
|
var wi, hi int
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
wi, hi = m.monitor.GetPhysicalSize()
|
wi, hi = m.monitor.GetPhysicalSize()
|
||||||
})
|
})
|
||||||
width = float64(wi)
|
width = float64(wi)
|
||||||
|
@ -53,7 +53,7 @@ func (m *Monitor) PhysicalSize() (width, height float64) {
|
||||||
// Position returns the position of the upper-left corner of a monitor in screen coordinates.
|
// Position returns the position of the upper-left corner of a monitor in screen coordinates.
|
||||||
func (m *Monitor) Position() (x, y float64) {
|
func (m *Monitor) Position() (x, y float64) {
|
||||||
var xi, yi int
|
var xi, yi int
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
xi, yi = m.monitor.GetPos()
|
xi, yi = m.monitor.GetPos()
|
||||||
})
|
})
|
||||||
x = float64(xi)
|
x = float64(xi)
|
||||||
|
@ -63,7 +63,7 @@ func (m *Monitor) Position() (x, y float64) {
|
||||||
|
|
||||||
// Size returns the resolution of a monitor in pixels.
|
// Size returns the resolution of a monitor in pixels.
|
||||||
func (m *Monitor) Size() (width, height float64) {
|
func (m *Monitor) Size() (width, height float64) {
|
||||||
mode := pixelgl.DoVal(func() interface{} {
|
mode := mainthread.CallVal(func() interface{} {
|
||||||
return m.monitor.GetVideoMode()
|
return m.monitor.GetVideoMode()
|
||||||
}).(*glfw.VidMode)
|
}).(*glfw.VidMode)
|
||||||
width = float64(mode.Width)
|
width = float64(mode.Width)
|
||||||
|
@ -73,7 +73,7 @@ func (m *Monitor) Size() (width, height float64) {
|
||||||
|
|
||||||
// BitDepth returns the number of bits per color of a monitor.
|
// BitDepth returns the number of bits per color of a monitor.
|
||||||
func (m *Monitor) BitDepth() (red, green, blue int) {
|
func (m *Monitor) BitDepth() (red, green, blue int) {
|
||||||
mode := pixelgl.DoVal(func() interface{} {
|
mode := mainthread.CallVal(func() interface{} {
|
||||||
return m.monitor.GetVideoMode()
|
return m.monitor.GetVideoMode()
|
||||||
}).(*glfw.VidMode)
|
}).(*glfw.VidMode)
|
||||||
red = mode.RedBits
|
red = mode.RedBits
|
||||||
|
@ -84,7 +84,7 @@ func (m *Monitor) BitDepth() (red, green, blue int) {
|
||||||
|
|
||||||
// RefreshRate returns the refresh frequency of a monitor in Hz (refreshes/second).
|
// RefreshRate returns the refresh frequency of a monitor in Hz (refreshes/second).
|
||||||
func (m *Monitor) RefreshRate() (rate float64) {
|
func (m *Monitor) RefreshRate() (rate float64) {
|
||||||
mode := pixelgl.DoVal(func() interface{} {
|
mode := mainthread.CallVal(func() interface{} {
|
||||||
return m.monitor.GetVideoMode()
|
return m.monitor.GetVideoMode()
|
||||||
}).(*glfw.VidMode)
|
}).(*glfw.VidMode)
|
||||||
rate = float64(mode.RefreshRate)
|
rate = float64(mode.RefreshRate)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"image"
|
"image"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
|
|
||||||
|
"github.com/faiface/mainthread"
|
||||||
"github.com/faiface/pixel/pixelgl"
|
"github.com/faiface/pixel/pixelgl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ func NewPicture(img image.Image, smooth bool) *Picture {
|
||||||
}
|
}
|
||||||
|
|
||||||
var texture *pixelgl.Texture
|
var texture *pixelgl.Texture
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
texture = pixelgl.NewTexture(
|
texture = pixelgl.NewTexture(
|
||||||
img.Bounds().Dx(),
|
img.Bounds().Dx(),
|
||||||
img.Bounds().Dy(),
|
img.Bounds().Dy(),
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
package pixelgl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/faiface/mainthread"
|
||||||
|
"github.com/go-gl/gl/v3.3-core/gl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Frame struct {
|
||||||
|
fb binder
|
||||||
|
tex *Texture
|
||||||
|
width, height int
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
fmt.Println(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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Frame) Width() int {
|
||||||
|
return f.width
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Frame) Height() int {
|
||||||
|
return f.height
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Frame) Begin() {
|
||||||
|
f.fb.bind()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Frame) End() {
|
||||||
|
f.fb.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Frame) Texture() *Texture {
|
||||||
|
return f.tex
|
||||||
|
}
|
|
@ -2,6 +2,20 @@ package pixelgl
|
||||||
|
|
||||||
import "github.com/go-gl/gl/v3.3-core/gl"
|
import "github.com/go-gl/gl/v3.3-core/gl"
|
||||||
|
|
||||||
|
// Init initializes OpenGL by loading the function pointers from the active OpenGL context.
|
||||||
|
// This function must be manually run inside the main thread (Do, DoErr, DoVal, etc.).
|
||||||
|
//
|
||||||
|
// 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.
|
// Clear clears the current framebuffer or window with the given color.
|
||||||
func Clear(r, g, b, a float32) {
|
func Clear(r, g, b, a float32) {
|
||||||
gl.ClearColor(r, g, b, a)
|
gl.ClearColor(r, g, b, a)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/faiface/mainthread"
|
||||||
"github.com/go-gl/gl/v3.3-core/gl"
|
"github.com/go-gl/gl/v3.3-core/gl"
|
||||||
"github.com/go-gl/mathgl/mgl32"
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
)
|
)
|
||||||
|
@ -110,7 +111,7 @@ func NewShader(vertexFmt, uniformFmt AttrFormat, vertexShader, fragmentShader st
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Shader) delete() {
|
func (s *Shader) delete() {
|
||||||
DoNoBlock(func() {
|
mainthread.CallNonBlock(func() {
|
||||||
gl.DeleteProgram(s.program.obj)
|
gl.DeleteProgram(s.program.obj)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package pixelgl
|
||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/faiface/mainthread"
|
||||||
"github.com/go-gl/gl/v3.3-core/gl"
|
"github.com/go-gl/gl/v3.3-core/gl"
|
||||||
"github.com/go-gl/mathgl/mgl32"
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
)
|
)
|
||||||
|
@ -67,7 +68,7 @@ func NewTexture(width, height int, smooth bool, pixels []uint8) *Texture {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Texture) delete() {
|
func (t *Texture) delete() {
|
||||||
DoNoBlock(func() {
|
mainthread.CallNonBlock(func() {
|
||||||
gl.DeleteTextures(1, &t.tex.obj)
|
gl.DeleteTextures(1, &t.tex.obj)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
package pixelgl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/go-gl/gl/v3.3-core/gl"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Due to the limitations of OpenGL and operating systems, all OpenGL related calls must be
|
|
||||||
// done from the main thread.
|
|
||||||
|
|
||||||
var (
|
|
||||||
callQueue = make(chan func(), 8)
|
|
||||||
respChan = make(chan interface{}, 4)
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
runtime.LockOSThread()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run is essentialy the "main" function of the pixelgl package. Run this function from the
|
|
||||||
// main function (because that's guaranteed to run in the main thread).
|
|
||||||
//
|
|
||||||
// This function reserves the main thread for the OpenGL stuff and runs a supplied run function
|
|
||||||
// in a separate goroutine.
|
|
||||||
//
|
|
||||||
// Run returns when the provided run function finishes.
|
|
||||||
func Run(run func()) {
|
|
||||||
done := make(chan struct{})
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
run()
|
|
||||||
close(done)
|
|
||||||
}()
|
|
||||||
|
|
||||||
loop:
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case f := <-callQueue:
|
|
||||||
f()
|
|
||||||
case <-done:
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init initializes OpenGL by loading the function pointers from the active OpenGL context.
|
|
||||||
// This function must be manually run inside the main thread (Do, DoErr, DoVal, etc.).
|
|
||||||
//
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoNoBlock executes a function inside the main OpenGL thread. DoNoBlock does not wait until
|
|
||||||
// the function finishes.
|
|
||||||
func DoNoBlock(f func()) {
|
|
||||||
callQueue <- f
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do executes a function inside the main OpenGL thread. Do blocks until the function finishes.
|
|
||||||
//
|
|
||||||
// All OpenGL calls must be done in the dedicated thread.
|
|
||||||
func Do(f func()) {
|
|
||||||
callQueue <- func() {
|
|
||||||
f()
|
|
||||||
respChan <- struct{}{}
|
|
||||||
}
|
|
||||||
<-respChan
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoErr executes a function inside the main OpenGL thread and returns an error to the called.
|
|
||||||
// DoErr blocks until the function finishes.
|
|
||||||
//
|
|
||||||
// All OpenGL calls must be done in the dedicated thread.
|
|
||||||
func DoErr(f func() error) error {
|
|
||||||
callQueue <- func() {
|
|
||||||
respChan <- f()
|
|
||||||
}
|
|
||||||
err := <-respChan
|
|
||||||
if err != nil {
|
|
||||||
return err.(error)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoVal executes a function inside the main OpenGL thread and returns a value to the caller.
|
|
||||||
// DoVal blocks until the function finishes.
|
|
||||||
//
|
|
||||||
// All OpenGL calls must be done in the main thread.
|
|
||||||
func DoVal(f func() interface{}) interface{} {
|
|
||||||
callQueue <- func() {
|
|
||||||
respChan <- f()
|
|
||||||
}
|
|
||||||
return <-respChan
|
|
||||||
}
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/faiface/mainthread"
|
||||||
"github.com/go-gl/gl/v3.3-core/gl"
|
"github.com/go-gl/gl/v3.3-core/gl"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
@ -252,7 +253,7 @@ func newVertexArray(shader *Shader, cap int) *vertexArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (va *vertexArray) delete() {
|
func (va *vertexArray) delete() {
|
||||||
DoNoBlock(func() {
|
mainthread.CallNonBlock(func() {
|
||||||
gl.DeleteVertexArrays(1, &va.vao.obj)
|
gl.DeleteVertexArrays(1, &va.vao.obj)
|
||||||
gl.DeleteBuffers(1, &va.vbo.obj)
|
gl.DeleteBuffers(1, &va.vbo.obj)
|
||||||
})
|
})
|
||||||
|
|
4
run.go
4
run.go
|
@ -1,7 +1,7 @@
|
||||||
package pixel
|
package pixel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/faiface/pixel/pixelgl"
|
"github.com/faiface/mainthread"
|
||||||
"github.com/go-gl/glfw/v3.2/glfw"
|
"github.com/go-gl/glfw/v3.2/glfw"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,5 +28,5 @@ import (
|
||||||
// function.
|
// function.
|
||||||
func Run(run func()) {
|
func Run(run func()) {
|
||||||
defer glfw.Terminate()
|
defer glfw.Terminate()
|
||||||
pixelgl.Run(run)
|
mainthread.Run(run)
|
||||||
}
|
}
|
||||||
|
|
64
window.go
64
window.go
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/faiface/mainthread"
|
||||||
"github.com/faiface/pixel/pixelgl"
|
"github.com/faiface/pixel/pixelgl"
|
||||||
"github.com/go-gl/glfw/v3.2/glfw"
|
"github.com/go-gl/glfw/v3.2/glfw"
|
||||||
"github.com/go-gl/mathgl/mgl32"
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
|
@ -79,6 +80,9 @@ type Window struct {
|
||||||
buttons [KeyLast + 1]bool
|
buttons [KeyLast + 1]bool
|
||||||
scroll Vec
|
scroll Vec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//DEBUG
|
||||||
|
Frame *pixelgl.Frame
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentWindow *Window
|
var currentWindow *Window
|
||||||
|
@ -94,7 +98,7 @@ func NewWindow(config WindowConfig) (*Window, error) {
|
||||||
|
|
||||||
w := &Window{config: config}
|
w := &Window{config: config}
|
||||||
|
|
||||||
err := pixelgl.DoErr(func() error {
|
err := mainthread.CallErr(func() error {
|
||||||
err := glfw.Init()
|
err := glfw.Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -127,7 +131,7 @@ func NewWindow(config WindowConfig) (*Window, error) {
|
||||||
return nil, errors.Wrap(err, "creating window failed")
|
return nil, errors.Wrap(err, "creating window failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.begin()
|
w.begin()
|
||||||
w.end()
|
w.end()
|
||||||
|
|
||||||
|
@ -160,25 +164,24 @@ func NewWindow(config WindowConfig) (*Window, error) {
|
||||||
|
|
||||||
// Destroy destroys a window. The window can't be used any further.
|
// Destroy destroys a window. The window can't be used any further.
|
||||||
func (w *Window) Destroy() {
|
func (w *Window) Destroy() {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.window.Destroy()
|
w.window.Destroy()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear clears the window with a color.
|
// Clear clears the window with a color.
|
||||||
func (w *Window) Clear(c color.Color) {
|
func (w *Window) Clear(c color.Color) {
|
||||||
pixelgl.DoNoBlock(func() {
|
mainthread.CallNonBlock(func() {
|
||||||
w.begin()
|
w.begin()
|
||||||
defer w.end()
|
|
||||||
|
|
||||||
c := NRGBAModel.Convert(c).(NRGBA)
|
c := NRGBAModel.Convert(c).(NRGBA)
|
||||||
pixelgl.Clear(float32(c.R), float32(c.G), float32(c.B), float32(c.A))
|
pixelgl.Clear(float32(c.R), float32(c.G), float32(c.B), float32(c.A))
|
||||||
|
w.end()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update swaps buffers and polls events.
|
// Update swaps buffers and polls events.
|
||||||
func (w *Window) Update() {
|
func (w *Window) Update() {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.begin()
|
w.begin()
|
||||||
if w.config.VSync {
|
if w.config.VSync {
|
||||||
glfw.SwapInterval(1)
|
glfw.SwapInterval(1)
|
||||||
|
@ -197,7 +200,7 @@ func (w *Window) Update() {
|
||||||
// This is usefull when overriding the user's attempt to close a window, or just to close a
|
// This is usefull when overriding the user's attempt to close a window, or just to close a
|
||||||
// window from within a program.
|
// window from within a program.
|
||||||
func (w *Window) SetClosed(closed bool) {
|
func (w *Window) SetClosed(closed bool) {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.window.SetShouldClose(closed)
|
w.window.SetShouldClose(closed)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -206,14 +209,14 @@ func (w *Window) SetClosed(closed bool) {
|
||||||
//
|
//
|
||||||
// The closed flag is automatically set when a user attempts to close a window.
|
// The closed flag is automatically set when a user attempts to close a window.
|
||||||
func (w *Window) Closed() bool {
|
func (w *Window) Closed() bool {
|
||||||
return pixelgl.DoVal(func() interface{} {
|
return mainthread.CallVal(func() interface{} {
|
||||||
return w.window.ShouldClose()
|
return w.window.ShouldClose()
|
||||||
}).(bool)
|
}).(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTitle changes the title of a window.
|
// SetTitle changes the title of a window.
|
||||||
func (w *Window) SetTitle(title string) {
|
func (w *Window) SetTitle(title string) {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.window.SetTitle(title)
|
w.window.SetTitle(title)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -221,14 +224,14 @@ func (w *Window) SetTitle(title string) {
|
||||||
// SetSize resizes a window to the specified size in pixels. In case of a fullscreen window,
|
// SetSize resizes a window to the specified size in pixels. In case of a fullscreen window,
|
||||||
// it changes the resolution of that window.
|
// it changes the resolution of that window.
|
||||||
func (w *Window) SetSize(width, height float64) {
|
func (w *Window) SetSize(width, height float64) {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.window.SetSize(int(width), int(height))
|
w.window.SetSize(int(width), int(height))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the size of the client area of a window (the part you can draw on).
|
// Size returns the size of the client area of a window (the part you can draw on).
|
||||||
func (w *Window) Size() (width, height float64) {
|
func (w *Window) Size() (width, height float64) {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
wi, hi := w.window.GetSize()
|
wi, hi := w.window.GetSize()
|
||||||
width = float64(wi)
|
width = float64(wi)
|
||||||
height = float64(hi)
|
height = float64(hi)
|
||||||
|
@ -238,14 +241,14 @@ func (w *Window) Size() (width, height float64) {
|
||||||
|
|
||||||
// Show makes a window visible if it was hidden.
|
// Show makes a window visible if it was hidden.
|
||||||
func (w *Window) Show() {
|
func (w *Window) Show() {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.window.Show()
|
w.window.Show()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide hides a window if it was visible.
|
// Hide hides a window if it was visible.
|
||||||
func (w *Window) Hide() {
|
func (w *Window) Hide() {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.window.Hide()
|
w.window.Hide()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -259,7 +262,7 @@ func (w *Window) Hide() {
|
||||||
func (w *Window) SetFullscreen(monitor *Monitor) {
|
func (w *Window) SetFullscreen(monitor *Monitor) {
|
||||||
if w.Monitor() != monitor {
|
if w.Monitor() != monitor {
|
||||||
if monitor == nil {
|
if monitor == nil {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.window.SetMonitor(
|
w.window.SetMonitor(
|
||||||
nil,
|
nil,
|
||||||
w.restore.xpos,
|
w.restore.xpos,
|
||||||
|
@ -270,7 +273,7 @@ func (w *Window) SetFullscreen(monitor *Monitor) {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.restore.xpos, w.restore.ypos = w.window.GetPos()
|
w.restore.xpos, w.restore.ypos = w.window.GetPos()
|
||||||
w.restore.width, w.restore.height = w.window.GetSize()
|
w.restore.width, w.restore.height = w.window.GetSize()
|
||||||
|
|
||||||
|
@ -297,7 +300,7 @@ func (w *Window) IsFullscreen() bool {
|
||||||
// Monitor returns a monitor a fullscreen window is on. If the window is not fullscreen, this
|
// Monitor returns a monitor a fullscreen window is on. If the window is not fullscreen, this
|
||||||
// function returns nil.
|
// function returns nil.
|
||||||
func (w *Window) Monitor() *Monitor {
|
func (w *Window) Monitor() *Monitor {
|
||||||
monitor := pixelgl.DoVal(func() interface{} {
|
monitor := mainthread.CallVal(func() interface{} {
|
||||||
return w.window.GetMonitor()
|
return w.window.GetMonitor()
|
||||||
}).(*glfw.Monitor)
|
}).(*glfw.Monitor)
|
||||||
if monitor == nil {
|
if monitor == nil {
|
||||||
|
@ -310,28 +313,28 @@ func (w *Window) Monitor() *Monitor {
|
||||||
|
|
||||||
// Focus brings a window to the front and sets input focus.
|
// Focus brings a window to the front and sets input focus.
|
||||||
func (w *Window) Focus() {
|
func (w *Window) Focus() {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.window.Focus()
|
w.window.Focus()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Focused returns true if a window has input focus.
|
// Focused returns true if a window has input focus.
|
||||||
func (w *Window) Focused() bool {
|
func (w *Window) Focused() bool {
|
||||||
return pixelgl.DoVal(func() interface{} {
|
return mainthread.CallVal(func() interface{} {
|
||||||
return w.window.GetAttrib(glfw.Focused) == glfw.True
|
return w.window.GetAttrib(glfw.Focused) == glfw.True
|
||||||
}).(bool)
|
}).(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maximize puts a windowed window to a maximized state.
|
// Maximize puts a windowed window to a maximized state.
|
||||||
func (w *Window) Maximize() {
|
func (w *Window) Maximize() {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.window.Maximize()
|
w.window.Maximize()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore restores a windowed window from a maximized state.
|
// Restore restores a windowed window from a maximized state.
|
||||||
func (w *Window) Restore() {
|
func (w *Window) Restore() {
|
||||||
pixelgl.Do(func() {
|
mainthread.Call(func() {
|
||||||
w.window.Restore()
|
w.window.Restore()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -346,11 +349,19 @@ func (w *Window) begin() {
|
||||||
if w.shader != nil {
|
if w.shader != nil {
|
||||||
w.shader.Begin()
|
w.shader.Begin()
|
||||||
}
|
}
|
||||||
pixelgl.Viewport(0, 0, int32(w.width), int32(w.height))
|
if w.Frame != nil {
|
||||||
|
w.Frame.Begin()
|
||||||
|
pixelgl.Viewport(0, 0, int32(w.Frame.Width()), int32(w.Frame.Height()))
|
||||||
|
} else {
|
||||||
|
pixelgl.Viewport(0, 0, int32(w.width), int32(w.height))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: must be called inside the main thread.
|
// Note: must be called inside the main thread.
|
||||||
func (w *Window) end() {
|
func (w *Window) end() {
|
||||||
|
if w.Frame != nil {
|
||||||
|
w.Frame.End()
|
||||||
|
}
|
||||||
if w.shader != nil {
|
if w.shader != nil {
|
||||||
w.shader.End()
|
w.shader.End()
|
||||||
}
|
}
|
||||||
|
@ -373,7 +384,7 @@ func (wt *windowTriangles) Draw() {
|
||||||
col := wt.w.col
|
col := wt.w.col
|
||||||
bnd := wt.w.bnd
|
bnd := wt.w.bnd
|
||||||
|
|
||||||
pixelgl.DoNoBlock(func() {
|
mainthread.CallNonBlock(func() {
|
||||||
wt.w.begin()
|
wt.w.begin()
|
||||||
|
|
||||||
wt.w.shader.SetUniformAttr(transformMat3, mat)
|
wt.w.shader.SetUniformAttr(transformMat3, mat)
|
||||||
|
@ -438,7 +449,7 @@ func (wt *windowTriangles) updateData(offset int, t Triangles) {
|
||||||
|
|
||||||
func (wt *windowTriangles) submitData() {
|
func (wt *windowTriangles) submitData() {
|
||||||
data := wt.data // avoid race condition
|
data := wt.data // avoid race condition
|
||||||
pixelgl.DoNoBlock(func() {
|
mainthread.CallNonBlock(func() {
|
||||||
wt.vs.Begin()
|
wt.vs.Begin()
|
||||||
dataLen := len(data) / wt.vs.Stride()
|
dataLen := len(data) / wt.vs.Stride()
|
||||||
if dataLen > wt.vs.Len() {
|
if dataLen > wt.vs.Len() {
|
||||||
|
@ -603,12 +614,11 @@ void main() {
|
||||||
vec2 boundsMin = bounds.xy;
|
vec2 boundsMin = bounds.xy;
|
||||||
vec2 boundsMax = bounds.zw;
|
vec2 boundsMax = bounds.zw;
|
||||||
|
|
||||||
float tx = boundsMin.x * (1 - Texture.x) + boundsMax.x * Texture.x;
|
|
||||||
float ty = boundsMin.y * (1 - Texture.y) + boundsMax.y * Texture.y;
|
|
||||||
|
|
||||||
if (Texture == vec2(-1, -1)) {
|
if (Texture == vec2(-1, -1)) {
|
||||||
color = maskColor * Color;
|
color = maskColor * Color;
|
||||||
} else {
|
} else {
|
||||||
|
float tx = boundsMin.x * (1 - Texture.x) + boundsMax.x * Texture.x;
|
||||||
|
float ty = boundsMin.y * (1 - Texture.y) + boundsMax.y * Texture.y;
|
||||||
color = maskColor * Color * texture(tex, vec2(tx, 1 - ty));
|
color = maskColor * Color * texture(tex, vec2(tx, 1 - ty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue