util.go raw

   1  // SPDX-License-Identifier: Unlicense OR MIT
   2  
   3  package gl
   4  
   5  import (
   6  	"errors"
   7  	"fmt"
   8  	"strings"
   9  )
  10  
  11  func CreateProgram(ctx *Functions, vsSrc, fsSrc string, attribs []string) (Program, error) {
  12  	vs, err := createShader(ctx, VERTEX_SHADER, vsSrc)
  13  	if err != nil {
  14  		return Program{}, err
  15  	}
  16  	defer ctx.DeleteShader(vs)
  17  	fs, err := createShader(ctx, FRAGMENT_SHADER, fsSrc)
  18  	if err != nil {
  19  		return Program{}, err
  20  	}
  21  	defer ctx.DeleteShader(fs)
  22  	prog := ctx.CreateProgram()
  23  	if !prog.Valid() {
  24  		return Program{}, errors.New("glCreateProgram failed")
  25  	}
  26  	ctx.AttachShader(prog, vs)
  27  	ctx.AttachShader(prog, fs)
  28  	for i, a := range attribs {
  29  		ctx.BindAttribLocation(prog, Attrib(i), a)
  30  	}
  31  	ctx.LinkProgram(prog)
  32  	if ctx.GetProgrami(prog, LINK_STATUS) == 0 {
  33  		log := ctx.GetProgramInfoLog(prog)
  34  		ctx.DeleteProgram(prog)
  35  		return Program{}, fmt.Errorf("program link failed: %s", strings.TrimSpace(log))
  36  	}
  37  	return prog, nil
  38  }
  39  
  40  func CreateComputeProgram(ctx *Functions, src string) (Program, error) {
  41  	cs, err := createShader(ctx, COMPUTE_SHADER, src)
  42  	if err != nil {
  43  		return Program{}, err
  44  	}
  45  	defer ctx.DeleteShader(cs)
  46  	prog := ctx.CreateProgram()
  47  	if !prog.Valid() {
  48  		return Program{}, errors.New("glCreateProgram failed")
  49  	}
  50  	ctx.AttachShader(prog, cs)
  51  	ctx.LinkProgram(prog)
  52  	if ctx.GetProgrami(prog, LINK_STATUS) == 0 {
  53  		log := ctx.GetProgramInfoLog(prog)
  54  		ctx.DeleteProgram(prog)
  55  		return Program{}, fmt.Errorf("program link failed: %s", strings.TrimSpace(log))
  56  	}
  57  	return prog, nil
  58  }
  59  
  60  func createShader(ctx *Functions, typ Enum, src string) (Shader, error) {
  61  	sh := ctx.CreateShader(typ)
  62  	if !sh.Valid() {
  63  		return Shader{}, errors.New("glCreateShader failed")
  64  	}
  65  	ctx.ShaderSource(sh, src)
  66  	ctx.CompileShader(sh)
  67  	if ctx.GetShaderi(sh, COMPILE_STATUS) == 0 {
  68  		log := ctx.GetShaderInfoLog(sh)
  69  		ctx.DeleteShader(sh)
  70  		return Shader{}, fmt.Errorf("shader compilation failed: %s", strings.TrimSpace(log))
  71  	}
  72  	return sh, nil
  73  }
  74  
  75  func ParseGLVersion(glVer string) (version [2]int, gles bool, err error) {
  76  	var ver [2]int
  77  	if _, err := fmt.Sscanf(glVer, "OpenGL ES %d.%d", &ver[0], &ver[1]); err == nil {
  78  		return ver, true, nil
  79  	} else if _, err := fmt.Sscanf(glVer, "WebGL %d.%d", &ver[0], &ver[1]); err == nil {
  80  		// WebGL major version v corresponds to OpenGL ES version v + 1
  81  		ver[0]++
  82  		return ver, true, nil
  83  	} else if _, err := fmt.Sscanf(glVer, "%d.%d", &ver[0], &ver[1]); err == nil {
  84  		return ver, false, nil
  85  	}
  86  	return ver, false, fmt.Errorf("failed to parse OpenGL ES version (%s)", glVer)
  87  }
  88