Repository: fyne-io/fyne
File: internal/painter/gl/gl_gomobile.go (Go)

Code before:
var compiled []Program // avoid multiple compilations with the re-used mobile GUI context
var noBuffer = Buffer{}
var noShader = Shader{}
var textureFilterToGL = []int32{gl.Linear, gl.Nearest}

func (p *painter) glctx() gl.Context {
	return p.contextProvider.Context().(gl.Context)
}

func (p *painter) Init() {
	p.ctx = &mobileContext{glContext: p.contextProvider.Context().(gl.Context)}
	p.glctx().Disable(gl.DepthTest)
	p.glctx().Enable(gl.Blend)
	if compiled == nil {
		programs := make([]Program, 4)
		programs[0] = p.createProgram("simple_es")
		programs[1] = p.createProgram("line_es")
		programs[2] = p.createProgram("rectangle_es")
		programs[3] = p.createProgram("round_rectangle_es")

		compiled = programs
	}
	p.program = compiled[0]
	p.lineProgram = compiled[0]
	p.rectangleProgram = compiled[0]
	p.roundRectangleProgram = compiled[0]
}

// f32Bytes returns the byte representation of float32 values in the given byte
// order. byteOrder must be either binary.BigEndian or binary.LittleEndian.
func f32Bytes(byteOrder binary.ByteOrder, values ...float32) []byte {
	le := false
	switch byteOrder {
	case binary.BigEndian:
	case binary.LittleEndian:
		le = true
	default:
		panic(fmt.Sprintf("invalid byte order %v", byteOrder))
	}

	b := make([]byte, 4*len(values))
	for i, v := range values {
		u := math.Float32bits(v)
		if le {
			b[4*i+0] = byte(u >> 0)
			b[4*i+1] = byte(u >> 8)
			b[4*i+2] = byte(u >> 16)
			b[4*i+3] = byte(u >> 24)
		} else {
			b[4*i+0] = byte(u >> 24)
			b[4*i+1] = byte(u >> 16)

Review comment (bug):
We can create the slice in one go and use len() instead of checking for nil. It also seems like the code was wrong with how it used the slice indexes.
```suggestion
	if len(compiled) == 0 {
		compiled = []Program{
			p.createProgram("simple_es"),
			p.createProgram("line_es"),
			p.createProgram("rectangle_es"),
			p.createProgram("round_rectangle_es"),
		}
	}
	p.program = compiled[0]
	p.lineProgram = compiled[1]
	p.rectangleProgram = compiled[2]
	p.roundRectangleProgram = compiled[3]
```

Code after:
var compiled []Program // avoid multiple compilations with the re-used mobile GUI context
var noBuffer = Buffer{}
var noShader = Shader{}
var textureFilterToGL = []int32{gl.Linear, gl.Nearest}

func (p *painter) glctx() gl.Context {
	return p.contextProvider.Context().(gl.Context)
}

func (p *painter) Init() {
	p.ctx = &mobileContext{glContext: p.contextProvider.Context().(gl.Context)}
	p.glctx().Disable(gl.DepthTest)
	p.glctx().Enable(gl.Blend)
	if compiled == nil {
		compiled = []Program{
			p.createProgram("simple_es"),
			p.createProgram("line_es"),
			p.createProgram("rectangle_es"),
			p.createProgram("round_rectangle_es")}
	}
	p.program = compiled[0]
	p.lineProgram = compiled[1]
	p.rectangleProgram = compiled[2]
	p.roundRectangleProgram = compiled[3]
}

// f32Bytes returns the byte representation of float32 values in the given byte
// order. byteOrder must be either binary.BigEndian or binary.LittleEndian.
func f32Bytes(byteOrder binary.ByteOrder, values ...float32) []byte {
	le := false
	switch byteOrder {
	case binary.BigEndian:
	case binary.LittleEndian:
		le = true
	default:
		panic(fmt.Sprintf("invalid byte order %v", byteOrder))
	}

	b := make([]byte, 4*len(values))
	for i, v := range values {
		u := math.Float32bits(v)
		if le {
			b[4*i+0] = byte(u >> 0)
			b[4*i+1] = byte(u >> 8)
			b[4*i+2] = byte(u >> 16)
			b[4*i+3] = byte(u >> 24)
		} else {
			b[4*i+0] = byte(u >> 24)
			b[4*i+1] = byte(u >> 16)
			b[4*i+2] = byte(u >> 8)
			b[4*i+3] = byte(u >> 0)