github.com/as/shiny@v0.8.2/driver/gldriver/gldriver.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build darwin 6 7 // Package gldriver provides an OpenGL driver for accessing a screen. 8 package gldriver // import "github.com/as/shiny/driver/gldriver" 9 10 import ( 11 "encoding/binary" 12 "fmt" 13 "math" 14 15 "github.com/as/shiny/driver/internal/errscreen" 16 "github.com/as/shiny/gl" 17 "github.com/as/shiny/math/f64" 18 "github.com/as/shiny/screen" 19 ) 20 21 // Main is called by the program's main function to run the graphical 22 // application. 23 // 24 // It calls f on the Screen, possibly in a separate goroutine, as some OS- 25 // specific libraries require being on 'the main thread'. It returns when f 26 // returns. 27 func Main(f func(screen.Screen)) { 28 if err := main(f); err != nil { 29 f(errscreen.Stub(err)) 30 } 31 } 32 33 func mul(a, b f64.Aff3) f64.Aff3 { 34 return f64.Aff3{ 35 a[0]*b[0] + a[1]*b[3], 36 a[0]*b[1] + a[1]*b[4], 37 a[0]*b[2] + a[1]*b[5] + a[2], 38 39 a[3]*b[0] + a[4]*b[3], 40 a[3]*b[1] + a[4]*b[4], 41 a[3]*b[2] + a[4]*b[5] + a[5], 42 } 43 } 44 45 // writeAff3 must only be called while holding windowImpl.glctxMu. 46 func writeAff3(glctx gl.Context, u gl.Uniform, a f64.Aff3) { 47 var m [9]float32 48 m[0*3+0] = float32(a[0*3+0]) 49 m[0*3+1] = float32(a[1*3+0]) 50 m[0*3+2] = 0 51 m[1*3+0] = float32(a[0*3+1]) 52 m[1*3+1] = float32(a[1*3+1]) 53 m[1*3+2] = 0 54 m[2*3+0] = float32(a[0*3+2]) 55 m[2*3+1] = float32(a[1*3+2]) 56 m[2*3+2] = 1 57 glctx.UniformMatrix3fv(u, m[:]) 58 } 59 60 // f32Bytes returns the byte representation of float32 values in the given byte 61 // order. byteOrder must be either binary.BigEndian or binary.LittleEndian. 62 func f32Bytes(byteOrder binary.ByteOrder, values ...float32) []byte { 63 le := false 64 switch byteOrder { 65 case binary.BigEndian: 66 case binary.LittleEndian: 67 le = true 68 default: 69 panic(fmt.Sprintf("invalid byte order %v", byteOrder)) 70 } 71 72 b := make([]byte, 4*len(values)) 73 for i, v := range values { 74 u := math.Float32bits(v) 75 if le { 76 b[4*i+0] = byte(u >> 0) 77 b[4*i+1] = byte(u >> 8) 78 b[4*i+2] = byte(u >> 16) 79 b[4*i+3] = byte(u >> 24) 80 } else { 81 b[4*i+0] = byte(u >> 24) 82 b[4*i+1] = byte(u >> 16) 83 b[4*i+2] = byte(u >> 8) 84 b[4*i+3] = byte(u >> 0) 85 } 86 } 87 return b 88 } 89 90 // compileProgram must only be called while holding windowImpl.glctxMu. 91 func compileProgram(glctx gl.Context, vSrc, fSrc string) (gl.Program, error) { 92 program := glctx.CreateProgram() 93 if program.Value == 0 { 94 return gl.Program{}, fmt.Errorf("gldriver: no programs available") 95 } 96 97 vertexShader, err := compileShader(glctx, gl.VERTEX_SHADER, vSrc) 98 if err != nil { 99 return gl.Program{}, err 100 } 101 fragmentShader, err := compileShader(glctx, gl.FRAGMENT_SHADER, fSrc) 102 if err != nil { 103 glctx.DeleteShader(vertexShader) 104 return gl.Program{}, err 105 } 106 107 glctx.AttachShader(program, vertexShader) 108 glctx.AttachShader(program, fragmentShader) 109 glctx.LinkProgram(program) 110 111 // Flag shaders for deletion when program is unlinked. 112 glctx.DeleteShader(vertexShader) 113 glctx.DeleteShader(fragmentShader) 114 115 if glctx.GetProgrami(program, gl.LINK_STATUS) == 0 { 116 defer glctx.DeleteProgram(program) 117 return gl.Program{}, fmt.Errorf("gldriver: program compile: %s", glctx.GetProgramInfoLog(program)) 118 } 119 return program, nil 120 } 121 122 // compileShader must only be called while holding windowImpl.glctxMu. 123 func compileShader(glctx gl.Context, shaderType gl.Enum, src string) (gl.Shader, error) { 124 shader := glctx.CreateShader(shaderType) 125 if shader.Value == 0 { 126 return gl.Shader{}, fmt.Errorf("gldriver: could not create shader (type %v)", shaderType) 127 } 128 glctx.ShaderSource(shader, src) 129 glctx.CompileShader(shader) 130 if glctx.GetShaderi(shader, gl.COMPILE_STATUS) == 0 { 131 defer glctx.DeleteShader(shader) 132 return gl.Shader{}, fmt.Errorf("gldriver: shader compile: %s", glctx.GetShaderInfoLog(shader)) 133 } 134 return shader, nil 135 }