mirror of https://github.com/miguelmota/cointop
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
3.4 KiB
Go
150 lines
3.4 KiB
Go
// Copyright 2015 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package gldriver
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"sync"
|
|
|
|
"golang.org/x/exp/shiny/screen"
|
|
"golang.org/x/mobile/gl"
|
|
)
|
|
|
|
var theScreen = &screenImpl{
|
|
windows: make(map[uintptr]*windowImpl),
|
|
}
|
|
|
|
type screenImpl struct {
|
|
texture struct {
|
|
program gl.Program
|
|
pos gl.Attrib
|
|
mvp gl.Uniform
|
|
uvp gl.Uniform
|
|
inUV gl.Attrib
|
|
sample gl.Uniform
|
|
quad gl.Buffer
|
|
}
|
|
fill struct {
|
|
program gl.Program
|
|
pos gl.Attrib
|
|
mvp gl.Uniform
|
|
color gl.Uniform
|
|
quad gl.Buffer
|
|
}
|
|
|
|
mu sync.Mutex
|
|
windows map[uintptr]*windowImpl
|
|
}
|
|
|
|
func (s *screenImpl) NewBuffer(size image.Point) (retBuf screen.Buffer, retErr error) {
|
|
m := image.NewRGBA(image.Rectangle{Max: size})
|
|
return &bufferImpl{
|
|
buf: m.Pix,
|
|
rgba: *m,
|
|
size: size,
|
|
}, nil
|
|
}
|
|
|
|
func (s *screenImpl) NewTexture(size image.Point) (screen.Texture, error) {
|
|
// TODO: can we compile these programs eagerly instead of lazily?
|
|
|
|
// Find a GL context for this texture.
|
|
// TODO: this might be correct. Some GL objects can be shared
|
|
// across contexts. But this needs a review of the spec to make
|
|
// sure it's correct, and some testing would be nice.
|
|
var w *windowImpl
|
|
|
|
s.mu.Lock()
|
|
for _, window := range s.windows {
|
|
w = window
|
|
break
|
|
}
|
|
s.mu.Unlock()
|
|
|
|
if w == nil {
|
|
return nil, fmt.Errorf("gldriver: no window available")
|
|
}
|
|
|
|
w.glctxMu.Lock()
|
|
defer w.glctxMu.Unlock()
|
|
glctx := w.glctx
|
|
if glctx == nil {
|
|
return nil, fmt.Errorf("gldriver: no GL context available")
|
|
}
|
|
|
|
if !glctx.IsProgram(s.texture.program) {
|
|
p, err := compileProgram(glctx, textureVertexSrc, textureFragmentSrc)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s.texture.program = p
|
|
s.texture.pos = glctx.GetAttribLocation(p, "pos")
|
|
s.texture.mvp = glctx.GetUniformLocation(p, "mvp")
|
|
s.texture.uvp = glctx.GetUniformLocation(p, "uvp")
|
|
s.texture.inUV = glctx.GetAttribLocation(p, "inUV")
|
|
s.texture.sample = glctx.GetUniformLocation(p, "sample")
|
|
s.texture.quad = glctx.CreateBuffer()
|
|
|
|
glctx.BindBuffer(gl.ARRAY_BUFFER, s.texture.quad)
|
|
glctx.BufferData(gl.ARRAY_BUFFER, quadCoords, gl.STATIC_DRAW)
|
|
}
|
|
|
|
t := &textureImpl{
|
|
w: w,
|
|
id: glctx.CreateTexture(),
|
|
size: size,
|
|
}
|
|
|
|
glctx.BindTexture(gl.TEXTURE_2D, t.id)
|
|
glctx.TexImage2D(gl.TEXTURE_2D, 0, size.X, size.Y, gl.RGBA, gl.UNSIGNED_BYTE, nil)
|
|
glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
|
glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
|
glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
|
|
glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
|
|
|
|
return t, nil
|
|
}
|
|
|
|
func optsSize(opts *screen.NewWindowOptions) (width, height int) {
|
|
width, height = 1024, 768
|
|
if opts != nil {
|
|
if opts.Width > 0 {
|
|
width = opts.Width
|
|
}
|
|
if opts.Height > 0 {
|
|
height = opts.Height
|
|
}
|
|
}
|
|
return width, height
|
|
}
|
|
|
|
func (s *screenImpl) NewWindow(opts *screen.NewWindowOptions) (screen.Window, error) {
|
|
id, err := newWindow(opts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
w := &windowImpl{
|
|
s: s,
|
|
id: id,
|
|
publish: make(chan struct{}),
|
|
publishDone: make(chan screen.PublishResult),
|
|
drawDone: make(chan struct{}),
|
|
}
|
|
initWindow(w)
|
|
|
|
s.mu.Lock()
|
|
s.windows[id] = w
|
|
s.mu.Unlock()
|
|
|
|
if useLifecycler {
|
|
w.lifecycler.SendEvent(w, nil)
|
|
}
|
|
|
|
showWindow(w)
|
|
|
|
return w, nil
|
|
}
|