gioui.org/ui@v0.0.0-20190926171558-ce74bc0cbaea/app/internal/gl/util.go (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  package gl
     4  
     5  import (
     6  	"errors"
     7  	"fmt"
     8  	"reflect"
     9  	"strings"
    10  	"unsafe"
    11  )
    12  
    13  func CreateProgram(ctx *Functions, vsSrc, fsSrc string, attribs []string) (Program, error) {
    14  	vs, err := createShader(ctx, VERTEX_SHADER, vsSrc)
    15  	if err != nil {
    16  		return Program{}, err
    17  	}
    18  	defer ctx.DeleteShader(vs)
    19  	fs, err := createShader(ctx, FRAGMENT_SHADER, fsSrc)
    20  	if err != nil {
    21  		return Program{}, err
    22  	}
    23  	defer ctx.DeleteShader(fs)
    24  	prog := ctx.CreateProgram()
    25  	if prog == (Program{}) {
    26  		return Program{}, errors.New("glCreateProgram failed")
    27  	}
    28  	ctx.AttachShader(prog, vs)
    29  	ctx.AttachShader(prog, fs)
    30  	for i, a := range attribs {
    31  		ctx.BindAttribLocation(prog, Attrib(i), a)
    32  	}
    33  	ctx.LinkProgram(prog)
    34  	if ctx.GetProgrami(prog, LINK_STATUS) == 0 {
    35  		log := ctx.GetProgramInfoLog(prog)
    36  		ctx.DeleteProgram(prog)
    37  		return Program{}, fmt.Errorf("program link failed: %s", strings.TrimSpace(log))
    38  	}
    39  	return prog, nil
    40  }
    41  
    42  func GetUniformLocation(ctx *Functions, prog Program, name string) Uniform {
    43  	loc := ctx.GetUniformLocation(prog, name)
    44  	if !loc.Valid() {
    45  		panic(fmt.Errorf("uniform %s not found", name))
    46  	}
    47  	return loc
    48  }
    49  
    50  func createShader(ctx *Functions, typ Enum, src string) (Shader, error) {
    51  	sh := ctx.CreateShader(typ)
    52  	if sh == (Shader{}) {
    53  		return Shader{}, errors.New("glCreateShader failed")
    54  	}
    55  	ctx.ShaderSource(sh, src)
    56  	ctx.CompileShader(sh)
    57  	if ctx.GetShaderi(sh, COMPILE_STATUS) == 0 {
    58  		log := ctx.GetShaderInfoLog(sh)
    59  		ctx.DeleteShader(sh)
    60  		return Shader{}, fmt.Errorf("shader compilation failed: %s", strings.TrimSpace(log))
    61  	}
    62  	return sh, nil
    63  }
    64  
    65  // BytesView returns a byte slice view of a slice.
    66  func BytesView(s interface{}) []byte {
    67  	v := reflect.ValueOf(s)
    68  	first := v.Index(0)
    69  	sz := int(first.Type().Size())
    70  	return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
    71  		Data: uintptr(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(first.UnsafeAddr())))),
    72  		Len:  v.Len() * sz,
    73  		Cap:  v.Cap() * sz,
    74  	}))
    75  }
    76  
    77  func ParseGLVersion(glVer string) ([2]int, error) {
    78  	var ver [2]int
    79  	if _, err := fmt.Sscanf(glVer, "OpenGL ES %d.%d", &ver[0], &ver[1]); err == nil {
    80  		return ver, nil
    81  	} else if _, err := fmt.Sscanf(glVer, "WebGL %d.%d", &ver[0], &ver[1]); err == nil {
    82  		// WebGL major version v corresponds to OpenGL ES version v + 1
    83  		ver[0]++
    84  		return ver, nil
    85  	} else if _, err := fmt.Sscanf(glVer, "%d.%d", &ver[0], &ver[1]); err == nil {
    86  		return ver, nil
    87  	}
    88  	return ver, fmt.Errorf("failed to parse OpenGL ES version (%s)", glVer)
    89  }
    90  
    91  func SliceOf(s uintptr) []byte {
    92  	if s == 0 {
    93  		return nil
    94  	}
    95  	sh := reflect.SliceHeader{
    96  		Data: s,
    97  		Len:  1 << 30,
    98  		Cap:  1 << 30,
    99  	}
   100  	return *(*[]byte)(unsafe.Pointer(&sh))
   101  }
   102  
   103  // GoString convert a NUL-terminated C string
   104  // to a Go string.
   105  func GoString(s []byte) string {
   106  	i := 0
   107  	for {
   108  		if s[i] == 0 {
   109  			break
   110  		}
   111  		i++
   112  	}
   113  	return string(s[:i])
   114  }