aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/obscuren/qml/gl/gengl/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/github.com/obscuren/qml/gl/gengl/main.go')
-rw-r--r--Godeps/_workspace/src/github.com/obscuren/qml/gl/gengl/main.go1283
1 files changed, 0 insertions, 1283 deletions
diff --git a/Godeps/_workspace/src/github.com/obscuren/qml/gl/gengl/main.go b/Godeps/_workspace/src/github.com/obscuren/qml/gl/gengl/main.go
deleted file mode 100644
index e92e861f7..000000000
--- a/Godeps/_workspace/src/github.com/obscuren/qml/gl/gengl/main.go
+++ /dev/null
@@ -1,1283 +0,0 @@
-package main
-
-import (
- "bufio"
- "bytes"
- "encoding/xml"
- "flag"
- "fmt"
- "go/format"
- "go/token"
- "io/ioutil"
- "os"
- "path/filepath"
- "regexp"
- "strconv"
- "strings"
- "text/template"
-)
-
-type Header struct {
- Class string
- Const []Const
- Func []Func
- Type []Type
-
- FeatureFlags []Const
-
- GLVersionName string
- GLVersionLabel string
-}
-
-type Const struct {
- Name string
- Value string
- Heading string
- Comment string
- LineBlock int
- Disabled bool
-
- GoName string
-}
-
-type Func struct {
- Name string
- Type string
- Addr int
- Param []Param
-
- GoName string
- GoType string
- DocName string
-
- Missing bool
-}
-
-type Param struct {
- Name string
- Type string
- Addr int
- Array int
- Const bool
-
- GoName string
- GoNameOrig string
- GoType string
-}
-
-type Type struct {
- Name string
- Type string
- Comment string
-
- GoName string
-}
-
-type glVersion struct {
- api, number, profile string
-}
-
-var glVersions = []glVersion{
- {"gl", "1.0", ""},
- {"gl", "1.1", ""},
- {"gl", "1.2", ""},
- {"gl", "1.3", ""},
- {"gl", "1.4", ""},
- {"gl", "1.5", ""},
- {"gl", "2.0", ""},
- {"gl", "2.1", ""},
- {"gl", "3.0", ""},
- {"gl", "3.1", ""},
- {"gl", "3.2", "core"},
- {"gl", "3.2", "compatibility"},
- {"gl", "3.3", "core"},
- {"gl", "3.3", "compatibility"},
- {"gl", "4.0", "core"},
- {"gl", "4.0", "compatibility"},
- {"gl", "4.1", "core"},
- {"gl", "4.1", "compatibility"},
- {"gl", "4.2", "core"},
- {"gl", "4.2", "compatibility"},
- {"gl", "4.3", "core"},
- {"gl", "4.3", "compatibility"},
- {"gles2", "2.0", ""},
-}
-
-func (v glVersion) name() string {
- if v.api == "gles2" {
- return "ES2"
- }
- return v.number
-}
-
-func (v glVersion) label() string {
- if v.api == "gles2" {
- return "es2"
- }
- name := strings.Replace(v.number, ".", "_", -1)
- if v.profile == "compatibility" {
- return name + "compat"
- }
- return name + v.profile
-}
-
-func (v glVersion) qtheader() string {
- if v.api == "gles2" {
- return "qopenglfunctions.h"
- }
- s := "qopenglfunctions_" + strings.Replace(v.number, ".", "_", -1)
- if v.profile != "" {
- s += "_" + v.profile
- }
- return s + ".h"
-}
-
-func main() {
- flag.Parse()
- args := flag.Args()
- if len(args) != 2 {
- fmt.Fprintf(os.Stderr, "usage: gengl <qt base include path> <output base path>\n")
- os.Exit(1)
- }
- if err := run(args[0], args[1]); err != nil {
- fmt.Fprintf(os.Stderr, "error: %v\n", err)
- os.Exit(1)
- }
-}
-
-func dirnames(path string) ([]string, error) {
- dir, err := os.Open(path)
- if err != nil {
- return nil, err
- }
- list, err := dir.Readdirnames(0)
- dir.Close()
- return list, err
-}
-
-func parseQtHeader(filename string) (*Header, error) {
- classData, err := ioutil.ReadFile(filename)
- if err != nil {
- return nil, fmt.Errorf("cannot read qt header file: %v", err)
- }
- var header Header
- err = parseQt(string(classData), &header)
- if err != nil {
- return nil, err
- }
- return &header, nil
-}
-
-func borrowFuncs(header *Header, filename string) error {
- bheader, err := parseQtHeader(filename)
- if err != nil {
- return err
- }
-
- seen := make(map[string]bool)
- for _, f := range header.Func {
- seen[f.Name] = true
- }
- for _, f := range bheader.Func {
- if !seen[f.Name] {
- f.Missing = true
- header.Func = append(header.Func, f)
- }
- }
- return nil
-}
-
-func run(qtdir, outdir string) error {
- consts, err := parseConsts("gl.xml")
- if err != nil {
- return err
- }
-
- for _, glVersion := range glVersions {
- header, err := parseQtHeader(filepath.Join(qtdir, "QtGui", glVersion.qtheader()))
- if err != nil {
- return err
- }
-
- header.GLVersionLabel = glVersion.label()
- header.GLVersionName = glVersion.name()
- header.Const = consts[glVersion]
-
- if glVersion.api == "gles2" {
- // Qt < 5.3 misses several ES2 entries in QOpenGLFunctions. As a workaround,
- // find the missing entries from the pure ES2 class and use them directly.
- err := borrowFuncs(header, filepath.Join(qtdir, "QtGui", "qopenglfunctions_es2.h"))
- if err != nil {
- return err
- }
- }
-
- err = prepareHeader(header)
- if err != nil {
- return err
- }
-
- fileContent := make(map[string][]byte)
- for _, pkgFile := range packageFiles {
- var buf bytes.Buffer
- err = pkgFile.Template.Execute(&buf, header)
- if err != nil {
- return fmt.Errorf("cannot execute template: %v", err)
- }
- data := buf.Bytes()
- if strings.HasSuffix(pkgFile.Name, ".go") {
- newdata, err := format.Source(data)
- if err != nil {
- return fmt.Errorf("\n%s\ncannot format generated Go code: %v\n", data, err)
- }
- data = newdata
- }
- fileContent[pkgFile.Name] = data
- }
-
- glDir := filepath.Join(outdir, strings.Replace(header.GLVersionLabel, "_", ".", -1))
- err = os.MkdirAll(glDir, 0755)
- if err != nil {
- return fmt.Errorf("cannot make package directory at %s: %v", glDir, err)
- }
- oldNames, err := dirnames(glDir)
- if err != nil {
- return fmt.Errorf("cannot list contents of directory %s: %v", glDir, err)
- }
- for _, oldName := range oldNames {
- oldPath := filepath.Join(glDir, oldName)
- if err := os.Remove(oldPath); err != nil {
- return fmt.Errorf("cannot remove previous file in %s: %v", glDir, err)
- }
- }
- for name, data := range fileContent {
- err = ioutil.WriteFile(filepath.Join(glDir, name), data, 0644)
- if err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-type glRegistry struct {
- Enums []glEnum `xml:"enums>enum"`
- Groups []glGroup `xml:"groups>group"`
- Features []glFeature `xml:"feature"`
-}
-
-type glFeature struct {
- API string `xml:"api,attr"`
- Number string `xml:"number,attr"`
- Requires []glChange `xml:"require"`
- Removes []glChange `xml:"remove"`
-}
-
-type glChange struct {
- Profile string `xml:"profile,attr"`
- Enums []glEnum `xml:"enum"`
-}
-
-type glGroup struct {
- Name string `xml:"name,attr"`
- Enums []glEnum `xml:"enum"`
-}
-
-type glEnum struct {
- API string `xml:"api,attr"`
- Name string `xml:"name,attr"`
- Value string `xml:"value,attr"`
-}
-
-type groupTweak struct {
- group string
- rename string
- replace []string
- append []string
- reorder bool
-}
-
-var groupTweaks = []groupTweak{{
- group: "Boolean",
- reorder: true,
- append: []string{"GL_NONE"},
-}, {
- group: "DataType",
- reorder: true,
- replace: []string{
- "GL_BYTE",
- "GL_UNSIGNED_BYTE",
- "GL_SHORT",
- "GL_UNSIGNED_SHORT",
- "GL_INT",
- "GL_UNSIGNED_INT",
- "GL_FLOAT",
- "GL_2_BYTES",
- "GL_2_BYTES_NV",
- "GL_3_BYTES",
- "GL_3_BYTES_NV",
- "GL_4_BYTES",
- "GL_4_BYTES_NV",
- "GL_DOUBLE",
- "GL_DOUBLE_EXT",
- "GL_HALF_FLOAT",
- "GL_HALF_FLOAT_ARB",
- "GL_HALF_FLOAT_NV",
- "GL_HALF_APPLE",
- "GL_FIXED",
- "GL_FIXED_OES",
- "GL_INT64_NV",
- "GL_UNSIGNED_INT64_ARB",
- "GL_UNSIGNED_INT64_NV",
- },
-}, {
- group: "BlendingFactorSrc",
- replace: []string{
- "GL_CONSTANT_ALPHA_EXT",
- "GL_CONSTANT_COLOR_EXT",
- "GL_DST_ALPHA",
- "GL_DST_COLOR",
- "GL_ONE",
- "GL_ONE_MINUS_DST_ALPHA",
- "GL_ONE_MINUS_DST_COLOR",
- "GL_ONE_MINUS_SRC_ALPHA",
- "GL_ONE_MINUS_SRC_COLOR",
- "GL_SRC_ALPHA",
- "GL_SRC_COLOR",
- "GL_SRC_ALPHA_SATURATE",
- "GL_ZERO",
- },
-}, {
- group: "AttribMask",
- append: []string{
- "GL_COVERAGE_BUFFER_BIT_NV",
- },
-}}
-
-func tweakGroups(groups []glGroup) {
- tweaks := make(map[string]groupTweak)
- reorder := make(map[string]int)
- top := 0
- for _, tweak := range groupTweaks {
- tweaks[tweak.group] = tweak
- if tweak.reorder {
- reorder[tweak.group] = top
- top++
- }
- }
-
- // Take reordered groups out, leaving space at the start.
- stash := make([]glGroup, top)
- for i, group := range groups {
- newi, ok := reorder[group.Name]
- if !ok {
- continue
- }
- stash[newi] = group
- copy(groups[1:i+1], groups[0:i])
- }
- // Put reordered groups back, in the proper order.
- copy(groups, stash)
-
- for i, group := range groups {
- tweak, ok := tweaks[group.Name]
- if !ok {
- continue
- }
- if tweak.rename != "" {
- group.Name = tweak.rename
- }
- if tweak.replace != nil {
- group.Enums = group.Enums[:0]
- for _, name := range tweak.replace {
- group.Enums = append(group.Enums, glEnum{Name: name})
- }
- }
- if tweak.append != nil {
- for _, name := range tweak.append {
- group.Enums = append(group.Enums, glEnum{Name: name})
- }
- }
- groups[i] = group
- }
-}
-
-func parseConsts(filename string) (map[glVersion][]Const, error) {
- f, err := os.Open(filename)
- if err != nil {
- return nil, fmt.Errorf("cannot open %s: %v", filename, err)
- }
- defer f.Close()
-
- var registry glRegistry
- err = xml.NewDecoder(f).Decode(&registry)
- if err != nil {
- return nil, fmt.Errorf("cannot parse %s: %v", filename, err)
- }
-
- var all = make(map[glVersion]map[string]bool)
- var last = make(map[string]map[string]bool)
- for _, feature := range registry.Features {
- for _, profile := range []string{"", "core", "compatibility"} {
- required := make(map[string]bool)
- for name := range last[feature.API+":"+profile] {
- required[name] = true
- }
- if profile != "" {
- for name := range last[feature.API+":"] {
- required[name] = true
- }
- }
-
- for _, require := range feature.Requires {
- if require.Profile == profile || require.Profile == "" {
- for _, enum := range require.Enums {
- required[enum.Name] = true
- }
- }
- }
- for _, remove := range feature.Removes {
- if remove.Profile == profile || remove.Profile == "" {
- for _, enum := range remove.Enums {
- delete(required, enum.Name)
- }
- }
- }
-
- all[glVersion{feature.API, feature.Number, profile}] = required
- last[feature.API+":"+profile] = required
- }
- }
-
- // Enums in groups and requires/removes have no values.
- enums := make(map[string]glEnum)
- for _, enum := range registry.Enums {
- enums[enum.Name] = enum
- }
-
- tweakGroups(registry.Groups)
-
- consts := make(map[glVersion][]Const)
- for _, glVersion := range glVersions {
- var required = all[glVersion]
- var done = make(map[string]bool)
- var lineblock = 0
- var vconsts []Const
- for _, group := range registry.Groups {
- for _, enum := range group.Enums {
- if required[enum.Name] && !done[enum.Name] {
- done[enum.Name] = true
- c := Const{
- Name: enum.Name,
- Value: enums[enum.Name].Value,
- LineBlock: lineblock,
- }
- vconsts = append(vconsts, c)
- }
- }
- lineblock++
- }
- // Everything else not found in groups.
- for _, enum := range registry.Enums {
- if required[enum.Name] && !done[enum.Name] {
- done[enum.Name] = true
- c := Const{
- Name: enum.Name,
- Value: enum.Value,
- LineBlock: lineblock,
- }
- vconsts = append(vconsts, c)
- }
- }
- consts[glVersion] = vconsts
- }
- // Version 1.0 has no enums. Copy from 1.1.
- consts[glVersion{"gl", "1.0", ""}] = consts[glVersion{"gl", "1.1", ""}]
- return consts, nil
-}
-
-func prepareHeader(header *Header) error {
- funcNameDocCount := make(map[string]int)
-
- for fi, f := range header.Func {
- docPrefix := funcNameDocPrefix(f.Name)
- if docPrefix != f.Name {
- funcNameDocCount[docPrefix]++
- }
- if !strings.HasPrefix(f.Name, "gl") || len(f.Name) < 3 {
- panic("unexpected C function name: " + f.Name)
- }
- f.GoName = f.Name[2:]
- if f.Type == "int" {
- // Some consistency. It's in a gl* function after all.
- f.Type = "GLint"
- }
- if f.Type != "void" {
- f.GoType = goTypeName(f.Type)
- }
- tweaks := funcTweaks[f.GoName]
- if tweaks.result != "" {
- f.GoType = tweaks.result
- }
- for pi := range f.Param {
- f.Param[pi] = prepareParam(f, pi)
- }
- header.Func[fi] = f
- }
-
- for fi, f := range header.Func {
- prefix := funcNameDocPrefix(f.Name)
- if funcNameDocCount[prefix] > 1 {
- f.DocName = prefix
- } else {
- f.DocName = f.Name
- }
- header.Func[fi] = f
- }
-
- for ti, t := range header.Type {
- t.GoName = goTypeName(t.Name)
- header.Type[ti] = t
- }
-
- for ci, c := range header.Const {
- if !strings.HasPrefix(c.Name, "GL") || len(c.Name) < 3 {
- panic("unexpected C define name: " + c.Name)
- }
- if c.Name[3] >= '0' && c.Name[3] <= '9' {
- c.GoName = "N" + c.Name[3:]
- } else {
- c.GoName = c.Name[3:]
- }
- header.Const[ci] = c
- }
-
- return nil
-}
-
-func goTypeName(ctypeName string) string {
- // These types carry very little meaning, so it's more
- // convenient to have their native counterparts instead.
- switch ctypeName {
- case "GLboolean":
- return "bool"
- case "GLbyte", "GLchar":
- return "byte"
- case "GLubyte":
- return "uint8"
- case "GLshort":
- return "int16"
- case "GLushort":
- return "uint16"
- case "GLint", "GLsizei":
- return "int32"
- case "GLuint":
- return "uint32"
- case "GLint64":
- return "int64"
- case "GLuint64":
- return "uint64"
- case "GLintptr", "GLsizeiptr":
- return "int"
- case "GLuintptr":
- return "uintptr"
- case "GLfloat":
- return "float32"
- case "GLdouble":
- return "float64"
- }
- if !strings.HasPrefix(ctypeName, "GL") || len(ctypeName) < 3 {
- panic("unexpected C type name: " + ctypeName)
- }
- return "glbase." + string(ctypeName[2]-('a'-'A')) + ctypeName[3:]
-}
-
-func prepareParam(f Func, pi int) Param {
- p := f.Param[pi]
-
- // Qt seems to have gratuitously changed some names.
- if name, ok := paramNameFixes[p.Name]; ok {
- p.Name = name
- }
- if pi > 0 && strings.HasPrefix(f.GoName, "Uniform") && p.Name != "count" && p.Name != "transpose" {
- if strings.HasSuffix(f.GoName, "v") {
- p.Name = "value"
- } else if f.Param[1].Name == "count" {
- p.Name = "v" + string('0' + pi-2)
- } else {
- p.Name = "v" + string('0' + pi-1)
- }
- }
-
- // Other names conflict with Go keywords.
- switch p.Name {
- case "type", "func", "map", "string":
- p.GoName = "gl" + p.Name
- default:
- if token.Lookup(p.Name) != token.IDENT {
- p.GoName = p.Name + "_"
- } else {
- p.GoName = p.Name
- }
- }
-
- // Some consistency. Those are a gl* function after all.
- switch p.Type {
- case "void":
- p.Type = "GLvoid"
- case "char":
- p.Type = "GLchar"
- case "qopengl_GLsizeiptr", "qopengl_GLintptr":
- p.Type = p.Type[8:]
- }
-
- // Prepare the parameter type.
- p.GoType = goTypeName(p.Type)
- switch p.GoType {
- case "uint32":
- switch p.GoName {
- case "program", "programs":
- p.GoType = "glbase.Program"
- case "shader", "shaders":
- p.GoType = "glbase.Shader"
- case "buffer", "buffers":
- p.GoType = "glbase.Buffer"
- case "texture", "textures":
- p.GoType = "glbase.Texture"
- case "framebuffer", "framebuffers":
- p.GoType = "glbase.Framebuffer"
- case "renderbuffer", "renderbuffers":
- p.GoType = "glbase.Renderbuffer"
- case "index":
- if strings.Contains(f.Name, "Attrib") {
- p.GoType = "glbase.Attrib"
- }
- }
- case "int32":
- switch p.GoName {
- case "size", "count", "stride", "offset", "xoffset", "yoffset", "order", "level":
- p.GoType = "int"
- case "n", "first", "width", "height", "border", "imageSize":
- p.GoType = "int"
- case "x", "y", "z", "w":
- if !strings.HasPrefix(f.GoName, "Uniform") {
- p.GoType = "int"
- }
- case "location":
- if strings.Contains(f.Name, "Uniform") {
- p.GoType = "glbase.Uniform"
- }
- }
- }
-
- // Save the original name so that future tweaks can still refer
- // to it, and apply the tweaks.
- p.GoNameOrig = p.GoName
- tweak := funcTweaks[f.GoName].params[p.GoNameOrig]
- if tweak.retype != "" {
- p.GoType = tweak.retype
- }
- if tweak.rename != "" {
- p.GoName = tweak.rename
- }
-
- return p
-}
-
-func funcNameDocPrefix(cfuncName string) string {
- k := len(cfuncName) - 1
- if cfuncName[k] == 'v' {
- k--
- }
- switch cfuncName[k] {
- case 'i', 'f', 'd', 's', 'b':
- k--
- if cfuncName[k] == 'u' {
- k--
- }
- switch cfuncName[k] {
- case '1', '2', '3', '4':
- k--
- }
- }
- return cfuncName[:k+1]
-}
-
-var constLineBlock = -1
-
-func constNewLine(lineBlock int) bool {
- if lineBlock == constLineBlock {
- return false
- }
- constLineBlock = lineBlock
- return true
-}
-
-func substr(s string, i ...int) string {
- switch len(i) {
- case 1:
- return s[i[0]:]
- case 2:
- return s[i[0]:i[1]]
- }
- panic("invalid number of arguments for substr")
-}
-
-var funcTweaks = make(map[string]funcTweak)
-
-func init() {
- var re = regexp.MustCompile(`\bcopy:([a-zA-Z0-9]+)\b`)
- for _, tweak := range funcTweakList {
- funcTweaks[tweak.name] = tweak
- }
- for _, tweak := range funcTweakList {
- if tweak.copy != "" {
- doc := tweak.doc
- name := tweak.name
- tweak = funcTweaks[tweak.copy]
- tweak.name = name
- if doc != "" {
- tweak.doc = doc
- }
- }
- tweak.doc = re.ReplaceAllStringFunc(tweak.doc, func(match string) string {
- return funcTweaks[match[5:]].doc
- })
- funcTweaks[tweak.name] = tweak
- }
-}
-
-func funcComment(header *Header, f Func) string {
- var doc = funcTweaks[f.GoName].doc
- doc = strings.TrimRight(execTemplate(f.GoName+":doc", doc, f), "\n\t ")
- var buf bytes.Buffer
- if doc != "" {
- var scanner = bufio.NewScanner(bytes.NewBufferString(doc))
- var started bool
- var prefix string
- for scanner.Scan() {
- line := scanner.Text()
- if !started {
- if line == "" {
- continue
- }
- started = true
- trimmed := strings.TrimLeft(line, "\t ")
- prefix = line[:len(line)-len(trimmed)]
- line = f.GoName + " " + trimmed
- } else {
- line = strings.TrimPrefix(line, prefix)
- }
- buf.WriteString("// ")
- buf.WriteString(line)
- buf.WriteByte('\n')
- }
- }
- if buf.Len() > 0 {
- return strings.TrimSuffix(buf.String(), "\n")
- }
- var manNum = 2
- if header.GLVersionName[0] >= '2' && header.GLVersionName[0] <= '4' {
- manNum = int(header.GLVersionName[0] - '0')
- }
- return fmt.Sprintf("// https://www.opengl.org/sdk/docs/man%d/xhtml/%s.xml", manNum, f.Name)
-}
-
-type paramItem struct {
- GoName string
- GoType string
-}
-
-func appendResultList(list []paramItem, f Func) []paramItem {
- var tweaks = funcTweaks[f.GoName]
- var buf bytes.Buffer
- tweak := tweaks.params["result"]
- if f.GoType != "" && !tweak.omit {
- var item paramItem
- if tweak.rename != "" {
- item.GoName = tweak.rename
- } else {
- item.GoName = "result"
- }
- if tweak.retype != "" {
- item.GoType = tweak.retype
- } else {
- for i := 0; i < f.Addr; i++ {
- buf.WriteString("[]")
- }
- buf.WriteString(f.GoType)
- item.GoType = buf.String()
- }
- list = append(list, item)
- }
- return list
-}
-
-func appendParamsList(list []paramItem, f Func, output bool) []paramItem {
- var tweaks = funcTweaks[f.GoName]
- var buf bytes.Buffer
- for _, param := range f.Param {
- tweak := tweaks.params[param.GoNameOrig]
- if tweak.omit || tweak.output != output {
- continue
- }
- item := paramItem{GoName: param.GoName}
- if tweak.retype != "" {
- item.GoType = param.GoType
- } else if param.Addr == 1 && param.Type == "GLvoid" {
- item.GoType = "interface{}"
- } else if tweak.single {
- item.GoType = param.GoType
- } else {
- buf.Truncate(0)
- for j := 0; j < param.Addr; j++ {
- buf.WriteString("[]")
- }
- if param.Array > 0 {
- buf.WriteByte('[')
- buf.WriteString(strconv.Itoa(param.Array))
- buf.WriteByte(']')
- }
- buf.WriteString(param.GoType)
- item.GoType = buf.String()
- }
- list = append(list, item)
- }
- return list
-}
-
-func formatParamsList(list []paramItem) string {
- var buf bytes.Buffer
- for i, item := range list {
- if i > 0 {
- buf.WriteString(", ")
- }
- buf.WriteString(item.GoName)
- if i == len(list)-1 || item.GoType != list[i+1].GoType {
- buf.WriteByte(' ')
- buf.WriteString(item.GoType)
- }
- }
- return buf.String()
-}
-
-func funcParams(f Func) string {
- list := appendParamsList(nil, f, false)
- return formatParamsList(list)
-}
-
-func funcResult(f Func) string {
- list := appendResultList(nil, f)
- list = appendParamsList(list, f, true)
- if len(list) == 0 {
- return ""
- }
- if len(list) == 1 && (list[0].GoName == "result" || funcTweaks[f.GoName].params[list[0].GoName].unnamed) {
- return list[0].GoType
- }
- return "(" + formatParamsList(list) + ")"
-}
-
-func funcBefore(f Func) string {
- content := funcTweaks[f.GoName].before
- return strings.TrimSpace(execTemplate(f.GoName+":before", content, f))
-}
-
-func funcAfter(f Func) string {
- content := funcTweaks[f.GoName].after
- return strings.TrimSpace(execTemplate(f.GoName+":after", content, f))
-}
-
-func funcCallParams(f Func) string {
- tweaks := funcTweaks[f.GoName]
- var buf bytes.Buffer
- for i, param := range f.Param {
- if i > 0 {
- buf.WriteString(", ")
- }
- tweak := tweaks.params[param.GoNameOrig]
- name := param.GoName
- if tweak.replace {
- name += "_c"
- }
- if param.Addr == 1 && param.Type == "GLvoid" {
- buf.WriteString(name)
- buf.WriteString("_ptr")
- } else if param.Addr == 1 && param.Type == "GLchar" && param.GoType == "string" {
- buf.WriteString("(*C.GLchar)(")
- buf.WriteString(name)
- buf.WriteString("_cstr)")
- } else if param.Addr > 0 {
- buf.WriteByte('(')
- for i := 0; i < param.Addr; i++ {
- buf.WriteByte('*')
- }
- buf.WriteString("C.")
- buf.WriteString(param.Type)
- buf.WriteString(")(unsafe.Pointer(&")
- buf.WriteString(name)
- if !tweak.single {
- buf.WriteString("[0]")
- }
- buf.WriteString("))")
-
- } else if param.Type == "GLboolean" {
- buf.WriteString("*(*C.GLboolean)(unsafe.Pointer(&")
- buf.WriteString(name)
- buf.WriteString("))")
- } else if param.Type == "GLsync" {
- buf.WriteString("C.GLsync(unsafe.Pointer(")
- buf.WriteString(name)
- buf.WriteString("))")
- } else {
- buf.WriteString("C.")
- buf.WriteString(param.Type)
- buf.WriteByte('(')
- buf.WriteString(name)
- buf.WriteByte(')')
- }
- }
- return buf.String()
-}
-
-func funcCallParamsPrep(f Func) string {
- var buf bytes.Buffer
- for _, param := range f.Param {
- name := param.GoName
- if param.Addr == 1 && param.Type == "GLchar" && param.GoType == "string" {
- fmt.Fprintf(&buf, "%s_cstr := C.CString(%s)\n", name, name)
- }
- if param.Addr == 1 && param.Type == "GLvoid" && param.GoType == "glbase.Void" {
- fmt.Fprintf(&buf, "var %s_ptr unsafe.Pointer\n", name)
- fmt.Fprintf(&buf, "var %s_v = reflect.ValueOf(%s)\n", name, name)
- fmt.Fprintf(&buf, "if %s != nil && %s_v.Kind() != reflect.Slice { panic(\"parameter %s must be a slice\") }\n", name, name, name)
- fmt.Fprintf(&buf, "if %s != nil { %s_ptr = unsafe.Pointer(%s_v.Index(0).Addr().Pointer()) }\n", name, name, name)
- }
- if plen := funcParamLen(f, param); plen > 0 {
- fmt.Fprintf(&buf, "if len(%s) != %d { panic(\"parameter %s has incorrect length\") }\n", name, plen, name)
- }
- }
- return buf.String()
-}
-
-func funcCallParamsPost(f Func) string {
- var buf bytes.Buffer
- for _, param := range f.Param {
- if param.Addr == 1 && param.Type == "GLchar" && param.GoType == "string" {
- buf.WriteString("C.free(unsafe.Pointer(")
- buf.WriteString(param.GoName)
- buf.WriteString("_cstr))\n")
- }
- }
- return buf.String()
-}
-
-func funcReturnResult(f Func) string {
- tweaks := funcTweaks[f.GoName]
- var buf bytes.Buffer
- if f.GoType != "" {
- if f.Type == "GLboolean" {
- buf.WriteString("*(*bool)(unsafe.Pointer(&glresult))")
- } else if f.Type == "GLsync" {
- buf.WriteString("glbase.Sync(unsafe.Pointer(glresult))")
- } else {
- buf.WriteString(f.GoType)
- buf.WriteString("(glresult)")
- }
- }
- for _, param := range f.Param {
- tweak := tweaks.params[param.GoNameOrig]
- if tweak.omit || !tweak.output {
- continue
- }
- if buf.Len() > 0 {
- buf.WriteString(", ")
- }
- buf.WriteString(param.GoName)
- }
- return buf.String()
-}
-
-func funcCParams(f Func) string {
- var buf bytes.Buffer
- for i, param := range f.Param {
- if i > 0 {
- buf.WriteString(", ")
- }
- if param.Const {
- buf.WriteString("const ")
- }
- buf.WriteString(param.Type)
- for j := 0; j < param.Addr; j++ {
- buf.WriteString("*")
- }
- if param.Array > 0 {
- buf.WriteByte('[')
- buf.WriteString(strconv.Itoa(param.Array))
- buf.WriteByte(']')
- }
- buf.WriteByte(' ')
- buf.WriteString(param.GoName)
- }
- return buf.String()
-}
-
-func funcCCallParams(f Func) string {
- var buf bytes.Buffer
- for i, param := range f.Param {
- if i > 0 {
- buf.WriteString(", ")
- }
- buf.WriteString(param.GoName)
- }
- return buf.String()
-}
-
-func funcParamLen(f Func, param Param) int {
- if strings.HasPrefix(f.GoName, "Uniform") {
- return 0
- }
- if param.Addr == 0 || len(f.Name) < 3 || f.Name[len(f.Name)-1] != 'v' {
- return 0
- }
- switch f.Name[len(f.Name)-2] {
- case 'i', 'f', 'd', 's':
- switch c := f.Name[len(f.Name)-3]; c {
- case '2', '3', '4':
- return int(c - '0')
- }
- }
- return 0
-}
-
-// funcSupported returns whether the given function has wrapping
-// properly implemented already.
-func funcSupported(f Func) bool {
- if _, ok := funcTweaks[f.GoName]; ok {
- return true
- }
- if f.Addr > 0 {
- return false
- }
- for _, param := range f.Param {
- if param.Array > 0 {
- return false
- }
- if param.Addr > 1 {
- return false
- }
- }
- return true
-}
-
-func copyDoc(name string) string {
- return funcTweaks[name].doc
-}
-
-func paramGoType(f Func, name string) string {
- for _, param := range f.Param {
- if param.GoName == name {
- return param.GoType
- }
- }
- panic(fmt.Sprintf("parameter %q not found in function %s", name, f.GoName))
-}
-
-func funcSince(f Func, since string) string {
- if strings.HasSuffix(since, "+") {
- return f.GoName + " is available in GL version " + since[:len(since)-1] + " or greater."
- }
- return f.GoName + " is available in GL version " + since + "."
-}
-
-func execTemplate(name, content string, dot interface{}) string {
- if !strings.Contains(content, "{{") {
- return content
- }
- var buf bytes.Buffer
- tmpl := template.Must(template.New(name).Funcs(funcs).Parse(content))
- if err := tmpl.Execute(&buf, dot); err != nil {
- panic(err)
- }
- return buf.String()
-}
-
-func buildTemplate(name, content string) *template.Template {
- return template.Must(template.New(name).Funcs(funcs).Parse(content))
-}
-
-var funcs template.FuncMap
-
-type packageFile struct {
- Name string
- Template *template.Template
-}
-
-var packageFiles []packageFile
-
-func init() {
- funcs = template.FuncMap{
- "copyDoc": copyDoc,
- "paramGoType": paramGoType,
- "funcSince": funcSince,
-
- "constNewLine": constNewLine,
- "lower": strings.ToLower,
- "substr": substr,
-
- "funcSupported": funcSupported,
- "funcComment": funcComment,
- "funcParams": funcParams,
- "funcResult": funcResult,
- "funcBefore": funcBefore,
- "funcCallParams": funcCallParams,
- "funcCallParamsPrep": funcCallParamsPrep,
- "funcCallParamsPost": funcCallParamsPost,
- "funcAfter": funcAfter,
- "funcReturnResult": funcReturnResult,
- "funcCParams": funcCParams,
- "funcCCallParams": funcCCallParams,
- }
-
- packageFiles = []packageFile{
- {"gl.go", buildTemplate("gl.go", tmplGo)},
- {"funcs.cpp", buildTemplate("funcs.cpp", tmplFuncsCpp)},
- {"funcs.h", buildTemplate("funcs.h", tmplFuncsH)},
- }
-}
-
-var tmplGo = `
-// ** file automatically generated by glgen -- do not edit manually **
-
-package GL
-
-// #cgo CXXFLAGS: -std=c++0x -pedantic-errors -Wall -fno-strict-aliasing
-// #cgo LDFLAGS: -lstdc++
-{{if eq $.GLVersionName "ES2"}}// #cgo !darwin LDFLAGS: -lGL
-// #cgo darwin LDFLAGS: -framework OpenGL
-{{end}}// #cgo pkg-config: Qt5Core Qt5OpenGL
-//
-// #include "funcs.h"
-//
-// void free(void*);
-//
-import "C"
-
-import (
- "fmt"
- "reflect"
- "unsafe"
-
- "gopkg.in/qml.v1/gl/glbase"
-)
-
-// API returns a value that offers methods matching the OpenGL version {{$.GLVersionName}} API.
-//
-// The returned API must not be used after the provided OpenGL context becomes invalid.
-func API(context glbase.Contexter) *GL {
- gl := &GL{}
- gl.funcs = C.gl{{$.GLVersionLabel}}_funcs()
- if gl.funcs == nil {
- panic(fmt.Errorf("OpenGL version {{$.GLVersionName}} is not available"))
- }
- return gl
-}
-
-// GL implements the OpenGL version {{$.GLVersionName}} API. Values of this
-// type must be created via the API function, and it must not be used after
-// the associated OpenGL context becomes invalid.
-type GL struct {
- funcs unsafe.Pointer
-}
-
-const ({{range $const := $.Const}}{{if $const.LineBlock | constNewLine}}
-{{end}}{{if $const.Heading}} // {{$const.Heading}}
-{{end}} {{if $const.Disabled}}//{{end}}{{$const.GoName}} = {{$const.Value}}{{if $const.Comment}} // {{$const.Comment}}{{end}}
-{{end}})
-
-{{ range $func := $.Func }}{{if $func | funcSupported}}
-{{funcComment $ $func}}
-func (gl *GL) {{$func.GoName}}({{funcParams $func}}) {{funcResult $func}} {
- {{funcCallParamsPrep $func}} {{/*
-*/}} {{with $code := funcBefore $func}}{{$code}}
- {{end}} {{/*
-*/}} {{if ne $func.Type "void"}}glresult := {{end}}C.gl{{$.GLVersionLabel}}_{{$func.Name}}(gl.funcs{{if $func.Param}}, {{funcCallParams $func}}{{end}})
- {{with $code := funcAfter $func}}{{$code}}
- {{end}} {{/*
-*/}} {{funcCallParamsPost $func}} {{/*
-*/}} {{with $code := funcReturnResult $func}}return {{$code}}
- {{end}} {{/*
-*/}} }
-{{end}}{{end}}
-`
-
-var tmplFuncsCpp = `
-// ** file automatically generated by glgen -- do not edit manually **
-
-#include <QOpenGLContext>
-#include <QtGui/{{lower $.Class}}.h>
-
-#include "funcs.h"
-
-void *gl{{$.GLVersionLabel}}_funcs() {
- {{$.Class}}* funcs = QOpenGLContext::currentContext()->{{if eq $.Class "QOpenGLFunctions"}}functions{{else}}versionFunctions<{{$.Class}}>{{end}}();
- if (!funcs) {
- return 0;
- }{{if ne $.Class "QOpenGLFunctions"}}
- funcs->initializeOpenGLFunctions();{{end}}
- return funcs;
-}
-
-{{ range $func := $.Func }}{{if $func | funcSupported}}
-{{$func.Type}} gl{{$.GLVersionLabel}}_{{$func.Name}}(void *_glfuncs{{if $func.Param}}, {{funcCParams $func}}{{end}})
-{
- {{if not $func.Missing}}{{$.Class}}* _qglfuncs = reinterpret_cast<{{$.Class}}*>(_glfuncs);
- {{end}}{{if $func.GoType}}return {{end}}{{if not $func.Missing}}_qglfuncs->{{end}}{{$func.Name}}({{funcCCallParams $func}});
-}
-{{end}}{{end}}
-`
-
-var tmplFuncsH = `
-// ** file automatically generated by glgen -- do not edit manually **
-
-#ifndef __cplusplus
-#include <inttypes.h>
-#include <stddef.h>
-typedef unsigned int GLenum;
-typedef unsigned char GLboolean;
-typedef unsigned int GLbitfield;
-typedef void GLvoid;
-typedef char GLchar;
-typedef signed char GLbyte; /* 1-byte signed */
-typedef short GLshort; /* 2-byte signed */
-typedef int GLint; /* 4-byte signed */
-typedef unsigned char GLubyte; /* 1-byte unsigned */
-typedef unsigned short GLushort; /* 2-byte unsigned */
-typedef unsigned int GLuint; /* 4-byte unsigned */
-typedef int GLsizei; /* 4-byte signed */
-typedef float GLfloat; /* single precision float */
-typedef float GLclampf; /* single precision float in [0,1] */
-typedef double GLdouble; /* double precision float */
-typedef double GLclampd; /* double precision float in [0,1] */
-typedef int64_t GLint64;
-typedef uint64_t GLuint64;
-typedef ptrdiff_t GLintptr;
-typedef ptrdiff_t GLsizeiptr;
-typedef ptrdiff_t GLintptrARB;
-typedef ptrdiff_t GLsizeiptrARB;
-typedef struct __GLsync *GLsync;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void *gl{{$.GLVersionLabel}}_funcs();
-
-{{ range $func := $.Func }}{{if $func | funcSupported}}{{$func.Type}} gl{{$.GLVersionLabel}}_{{$func.Name}}(void *_glfuncs{{if $func.Param}}, {{funcCParams $func}}{{end}});
-{{end}}{{end}}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-`