added golang.org/x/mobile/gl implementation and an example using shiny
This commit is contained in:
parent
61ad4d0dc2
commit
60be0b7d92
2 changed files with 294 additions and 0 deletions
51
examples/shiny/shiny.go
Normal file
51
examples/shiny/shiny.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/tfriedel6/canvas"
|
||||
"github.com/tfriedel6/canvas/glimpl/xmobile"
|
||||
"golang.org/x/exp/shiny/driver/gldriver"
|
||||
"golang.org/x/exp/shiny/screen"
|
||||
"golang.org/x/exp/shiny/widget"
|
||||
"golang.org/x/exp/shiny/widget/glwidget"
|
||||
"golang.org/x/exp/shiny/widget/node"
|
||||
)
|
||||
|
||||
var cv *canvas.Canvas
|
||||
var sheet *widget.Sheet
|
||||
|
||||
func main() {
|
||||
gldriver.Main(func(s screen.Screen) {
|
||||
glw := glwidget.NewGL(draw)
|
||||
sheet = widget.NewSheet(glw)
|
||||
canvas.LoadGL(glimplxmobile.New(glw.Ctx))
|
||||
cv = canvas.New(0, 0, 600, 600)
|
||||
|
||||
err := widget.RunWindow(s, sheet, &widget.RunWindowOptions{
|
||||
NewWindowOptions: screen.NewWindowOptions{
|
||||
Title: "Shiny Canvas Example",
|
||||
Width: 600,
|
||||
Height: 600,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func draw(w *glwidget.GL) {
|
||||
cv.Save()
|
||||
defer cv.Restore()
|
||||
|
||||
cv.Translate(0, 600)
|
||||
cv.Scale(1, -1)
|
||||
|
||||
cv.ClearRect(0, 0, 600, 600)
|
||||
cv.SetFillStyle("#FF00FF")
|
||||
cv.FillRect(100, 100, 200, 200)
|
||||
|
||||
w.Publish()
|
||||
w.Mark(node.MarkNeedsPaintBase)
|
||||
}
|
243
glimpl/xmobile/xmobile.go
Normal file
243
glimpl/xmobile/xmobile.go
Normal file
|
@ -0,0 +1,243 @@
|
|||
package glimplxmobile
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/tfriedel6/canvas"
|
||||
"golang.org/x/mobile/gl"
|
||||
)
|
||||
|
||||
type GLImpl struct {
|
||||
gl gl.Context
|
||||
programs map[uint32]gl.Program
|
||||
}
|
||||
|
||||
var _ canvas.GL = GLImpl{}
|
||||
|
||||
func New(ctx gl.Context) *GLImpl {
|
||||
return &GLImpl{
|
||||
gl: ctx,
|
||||
programs: make(map[uint32]gl.Program),
|
||||
}
|
||||
}
|
||||
|
||||
func (gli GLImpl) Ptr(data interface{}) unsafe.Pointer {
|
||||
if data == nil {
|
||||
return unsafe.Pointer(nil)
|
||||
}
|
||||
var addr unsafe.Pointer
|
||||
v := reflect.ValueOf(data)
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Ptr:
|
||||
e := v.Elem()
|
||||
switch e.Kind() {
|
||||
case
|
||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64:
|
||||
addr = unsafe.Pointer(e.UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind()))
|
||||
}
|
||||
case reflect.Uintptr:
|
||||
addr = unsafe.Pointer(v.Pointer())
|
||||
case reflect.Slice:
|
||||
addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type()))
|
||||
}
|
||||
return addr
|
||||
}
|
||||
func (gli GLImpl) ActiveTexture(texture uint32) {
|
||||
gli.gl.ActiveTexture(gl.Enum(texture))
|
||||
}
|
||||
func (gli GLImpl) AttachShader(program uint32, shader uint32) {
|
||||
gli.gl.AttachShader(gli.programs[program], gl.Shader{Value: shader})
|
||||
}
|
||||
func (gli GLImpl) BindBuffer(target uint32, buffer uint32) {
|
||||
gli.gl.BindBuffer(gl.Enum(target), gl.Buffer{Value: buffer})
|
||||
}
|
||||
func (gli GLImpl) BindTexture(target uint32, texture uint32) {
|
||||
gli.gl.BindTexture(gl.Enum(target), gl.Texture{Value: texture})
|
||||
}
|
||||
func (gli GLImpl) BlendFunc(sfactor uint32, dfactor uint32) {
|
||||
gli.gl.BlendFunc(gl.Enum(sfactor), gl.Enum(dfactor))
|
||||
}
|
||||
func (gli GLImpl) BufferData(target uint32, size int, data unsafe.Pointer, usage uint32) {
|
||||
var buf []byte
|
||||
sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
|
||||
sh.Cap = size
|
||||
sh.Len = size
|
||||
sh.Data = uintptr(data)
|
||||
gli.gl.BufferData(gl.Enum(target), buf, gl.Enum(usage))
|
||||
}
|
||||
func (gli GLImpl) Clear(mask uint32) {
|
||||
gli.gl.Clear(gl.Enum(mask))
|
||||
}
|
||||
func (gli GLImpl) ClearColor(red float32, green float32, blue float32, alpha float32) {
|
||||
gli.gl.ClearColor(red, green, blue, alpha)
|
||||
}
|
||||
func (gli GLImpl) ColorMask(red bool, green bool, blue bool, alpha bool) {
|
||||
gli.gl.ColorMask(red, green, blue, alpha)
|
||||
}
|
||||
func (gli GLImpl) CompileShader(shader uint32) {
|
||||
gli.gl.CompileShader(gl.Shader{Value: shader})
|
||||
}
|
||||
func (gli GLImpl) CreateProgram() uint32 {
|
||||
program := gli.gl.CreateProgram()
|
||||
gli.programs[program.Value] = program
|
||||
return program.Value
|
||||
}
|
||||
func (gli GLImpl) CreateShader(xtype uint32) uint32 {
|
||||
return gli.gl.CreateShader(gl.Enum(xtype)).Value
|
||||
}
|
||||
func (gli GLImpl) DeleteShader(shader uint32) {
|
||||
gli.gl.DeleteShader(gl.Shader{Value: shader})
|
||||
}
|
||||
func (gli GLImpl) DeleteTextures(n int32, textures *uint32) {
|
||||
var buf []uint32
|
||||
sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
|
||||
sh.Cap = int(n)
|
||||
sh.Len = int(n)
|
||||
sh.Data = uintptr(unsafe.Pointer(textures))
|
||||
for i := 0; i < int(n); i++ {
|
||||
gli.gl.DeleteTexture(gl.Texture{Value: buf[i]})
|
||||
}
|
||||
}
|
||||
func (gli GLImpl) Disable(cap uint32) {
|
||||
gli.gl.Disable(gl.Enum(cap))
|
||||
}
|
||||
func (gli GLImpl) DisableVertexAttribArray(index uint32) {
|
||||
gli.gl.DisableVertexAttribArray(gl.Attrib{Value: uint(index)})
|
||||
}
|
||||
func (gli GLImpl) DrawArrays(mode uint32, first int32, count int32) {
|
||||
gli.gl.DrawArrays(gl.Enum(mode), int(first), int(count))
|
||||
}
|
||||
func (gli GLImpl) Enable(cap uint32) {
|
||||
gli.gl.Enable(gl.Enum(cap))
|
||||
}
|
||||
func (gli GLImpl) EnableVertexAttribArray(index uint32) {
|
||||
gli.gl.EnableVertexAttribArray(gl.Attrib{Value: uint(index)})
|
||||
}
|
||||
func (gli GLImpl) GenBuffers(n int32, buffers *uint32) {
|
||||
var buf []uint32
|
||||
sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
|
||||
sh.Cap = int(n)
|
||||
sh.Len = int(n)
|
||||
sh.Data = uintptr(unsafe.Pointer(buffers))
|
||||
for i := 0; i < int(n); i++ {
|
||||
buf[i] = gli.gl.CreateBuffer().Value
|
||||
}
|
||||
}
|
||||
func (gli GLImpl) GenTextures(n int32, textures *uint32) {
|
||||
var buf []uint32
|
||||
sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
|
||||
sh.Cap = int(n)
|
||||
sh.Len = int(n)
|
||||
sh.Data = uintptr(unsafe.Pointer(textures))
|
||||
for i := 0; i < int(n); i++ {
|
||||
buf[i] = gli.gl.CreateTexture().Value
|
||||
}
|
||||
}
|
||||
func (gli GLImpl) GenerateMipmap(target uint32) {
|
||||
gli.gl.GenerateMipmap(gl.Enum(target))
|
||||
}
|
||||
func (gli GLImpl) GetAttribLocation(program uint32, name string) int32 {
|
||||
return int32(gli.gl.GetAttribLocation(gli.programs[program], name).Value)
|
||||
}
|
||||
func (gli GLImpl) GetError() uint32 {
|
||||
return uint32(gli.gl.GetError())
|
||||
}
|
||||
func (gli GLImpl) GetProgramInfoLog(program uint32) string {
|
||||
return gli.gl.GetProgramInfoLog(gli.programs[program])
|
||||
}
|
||||
func (gli GLImpl) GetProgramiv(program uint32, pname uint32, params *int32) {
|
||||
i := gli.gl.GetProgrami(gli.programs[program], gl.Enum(pname))
|
||||
*params = int32(i)
|
||||
}
|
||||
func (gli GLImpl) GetShaderInfoLog(program uint32) string {
|
||||
return gli.gl.GetShaderInfoLog(gl.Shader{Value: program})
|
||||
}
|
||||
func (gli GLImpl) GetShaderiv(shader uint32, pname uint32, params *int32) {
|
||||
i := gli.gl.GetShaderi(gl.Shader{Value: shader}, gl.Enum(pname))
|
||||
*params = int32(i)
|
||||
}
|
||||
func (gli GLImpl) GetUniformLocation(program uint32, name string) int32 {
|
||||
return gli.gl.GetUniformLocation(gli.programs[program], name).Value
|
||||
}
|
||||
func (gli GLImpl) LinkProgram(program uint32) {
|
||||
gli.gl.LinkProgram(gli.programs[program])
|
||||
}
|
||||
func (gli GLImpl) ReadPixels(x int32, y int32, width int32, height int32, format uint32, xtype uint32, pixels unsafe.Pointer) {
|
||||
var buf []byte
|
||||
sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
|
||||
sh.Cap = int(width * height * 4)
|
||||
sh.Len = int(width * height * 4)
|
||||
sh.Data = uintptr(pixels)
|
||||
gli.gl.ReadPixels(buf, int(x), int(y), int(width), int(height), gl.Enum(format), gl.Enum(xtype))
|
||||
}
|
||||
func (gli GLImpl) Scissor(x int32, y int32, width int32, height int32) {
|
||||
gli.gl.Scissor(x, y, width, height)
|
||||
}
|
||||
func (gli GLImpl) ShaderSource(shader uint32, source string) {
|
||||
gli.gl.ShaderSource(gl.Shader{Value: shader}, source)
|
||||
}
|
||||
func (gli GLImpl) StencilFunc(xfunc uint32, ref int32, mask uint32) {
|
||||
gli.gl.StencilFunc(gl.Enum(xfunc), int(ref), mask)
|
||||
}
|
||||
func (gli GLImpl) StencilMask(mask uint32) {
|
||||
gli.gl.StencilMask(mask)
|
||||
}
|
||||
func (gli GLImpl) StencilOp(fail uint32, zfail uint32, zpass uint32) {
|
||||
gli.gl.StencilOp(gl.Enum(fail), gl.Enum(zfail), gl.Enum(zpass))
|
||||
}
|
||||
func (gli GLImpl) TexImage2D(target uint32, level int32, internalformat int32, width int32, height int32, border int32, format uint32, xtype uint32, pixels unsafe.Pointer) {
|
||||
var buf []byte
|
||||
sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
|
||||
sh.Cap = int(width * height * 4)
|
||||
sh.Len = int(width * height * 4)
|
||||
sh.Data = uintptr(pixels)
|
||||
gli.gl.TexImage2D(gl.Enum(target), int(level), int(width), int(height), gl.Enum(format), gl.Enum(xtype), buf)
|
||||
}
|
||||
func (gli GLImpl) TexParameteri(target uint32, pname uint32, param int32) {
|
||||
gli.gl.TexParameteri(gl.Enum(target), gl.Enum(pname), int(param))
|
||||
}
|
||||
func (gli GLImpl) TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, width int32, height int32, format uint32, xtype uint32, pixels unsafe.Pointer) {
|
||||
var buf []byte
|
||||
sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
|
||||
sh.Cap = int(width * height * 4)
|
||||
sh.Len = int(width * height * 4)
|
||||
sh.Data = uintptr(pixels)
|
||||
gli.gl.TexSubImage2D(gl.Enum(target), int(level), int(xoffset), int(yoffset), int(width), int(height), gl.Enum(format), gl.Enum(xtype), buf)
|
||||
}
|
||||
func (gli GLImpl) Uniform1f(location int32, v0 float32) {
|
||||
gli.gl.Uniform1f(gl.Uniform{Value: location}, v0)
|
||||
}
|
||||
func (gli GLImpl) Uniform1i(location int32, v0 int32) {
|
||||
gli.gl.Uniform1i(gl.Uniform{Value: location}, int(v0))
|
||||
}
|
||||
func (gli GLImpl) Uniform2f(location int32, v0 float32, v1 float32) {
|
||||
gli.gl.Uniform2f(gl.Uniform{Value: location}, v0, v1)
|
||||
}
|
||||
func (gli GLImpl) Uniform4f(location int32, v0 float32, v1 float32, v2 float32, v3 float32) {
|
||||
gli.gl.Uniform4f(gl.Uniform{Value: location}, v0, v1, v2, v3)
|
||||
}
|
||||
func (gli GLImpl) UniformMatrix3fv(location int32, count int32, transpose bool, value *float32) {
|
||||
var buf []float32
|
||||
sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
|
||||
sh.Cap = 9
|
||||
sh.Len = 9
|
||||
sh.Data = uintptr(unsafe.Pointer(value))
|
||||
gli.gl.UniformMatrix3fv(gl.Uniform{Value: location}, buf)
|
||||
}
|
||||
func (gli GLImpl) UseProgram(program uint32) {
|
||||
gli.gl.UseProgram(gli.programs[program])
|
||||
}
|
||||
func (gli GLImpl) VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset uint32) {
|
||||
gli.gl.VertexAttribPointer(gl.Attrib{Value: uint(index)}, int(size), gl.Enum(xtype), normalized, int(stride), int(offset))
|
||||
}
|
||||
func (gli GLImpl) Viewport(x int32, y int32, width int32, height int32) {
|
||||
gli.gl.Viewport(int(x), int(y), int(width), int(height))
|
||||
}
|
Loading…
Reference in a new issue