2022-11-13 07:37:18 +01:00
|
|
|
// Copyright 2022 The Ebitengine Authors
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2022-11-13 11:51:36 +01:00
|
|
|
//go:build darwin || windows
|
2022-11-13 07:37:18 +01:00
|
|
|
|
|
|
|
package gl
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"runtime"
|
|
|
|
"unsafe"
|
|
|
|
|
|
|
|
"github.com/ebitengine/purego"
|
|
|
|
)
|
|
|
|
|
|
|
|
type defaultContext struct {
|
|
|
|
gpActiveTexture uintptr
|
|
|
|
gpAttachShader uintptr
|
|
|
|
gpBindAttribLocation uintptr
|
|
|
|
gpBindBuffer uintptr
|
|
|
|
gpBindFramebufferEXT uintptr
|
|
|
|
gpBindRenderbufferEXT uintptr
|
|
|
|
gpBindTexture uintptr
|
|
|
|
gpBlendEquationSeparate uintptr
|
|
|
|
gpBlendFuncSeparate uintptr
|
|
|
|
gpBufferData uintptr
|
|
|
|
gpBufferSubData uintptr
|
|
|
|
gpCheckFramebufferStatusEXT uintptr
|
|
|
|
gpClear uintptr
|
|
|
|
gpColorMask uintptr
|
|
|
|
gpCompileShader uintptr
|
|
|
|
gpCreateProgram uintptr
|
|
|
|
gpCreateShader uintptr
|
|
|
|
gpDeleteBuffers uintptr
|
|
|
|
gpDeleteFramebuffersEXT uintptr
|
|
|
|
gpDeleteProgram uintptr
|
|
|
|
gpDeleteRenderbuffersEXT uintptr
|
|
|
|
gpDeleteShader uintptr
|
|
|
|
gpDeleteTextures uintptr
|
|
|
|
gpDisable uintptr
|
|
|
|
gpDisableVertexAttribArray uintptr
|
|
|
|
gpDrawElements uintptr
|
|
|
|
gpEnable uintptr
|
|
|
|
gpEnableVertexAttribArray uintptr
|
|
|
|
gpFlush uintptr
|
|
|
|
gpFramebufferRenderbufferEXT uintptr
|
|
|
|
gpFramebufferTexture2DEXT uintptr
|
|
|
|
gpGenBuffers uintptr
|
|
|
|
gpGenFramebuffersEXT uintptr
|
|
|
|
gpGenRenderbuffersEXT uintptr
|
|
|
|
gpGenTextures uintptr
|
|
|
|
gpGetError uintptr
|
|
|
|
gpGetIntegerv uintptr
|
|
|
|
gpGetProgramInfoLog uintptr
|
|
|
|
gpGetProgramiv uintptr
|
|
|
|
gpGetShaderInfoLog uintptr
|
|
|
|
gpGetShaderiv uintptr
|
|
|
|
gpGetUniformLocation uintptr
|
|
|
|
gpIsFramebufferEXT uintptr
|
|
|
|
gpIsProgram uintptr
|
|
|
|
gpIsRenderbufferEXT uintptr
|
|
|
|
gpIsTexture uintptr
|
|
|
|
gpLinkProgram uintptr
|
|
|
|
gpPixelStorei uintptr
|
|
|
|
gpReadPixels uintptr
|
|
|
|
gpRenderbufferStorageEXT uintptr
|
|
|
|
gpScissor uintptr
|
|
|
|
gpShaderSource uintptr
|
|
|
|
gpStencilFunc uintptr
|
|
|
|
gpStencilOp uintptr
|
|
|
|
gpTexImage2D uintptr
|
|
|
|
gpTexParameteri uintptr
|
|
|
|
gpTexSubImage2D uintptr
|
|
|
|
gpUniform1fv uintptr
|
|
|
|
gpUniform1i uintptr
|
|
|
|
gpUniform1iv uintptr
|
|
|
|
gpUniform2fv uintptr
|
|
|
|
gpUniform3fv uintptr
|
|
|
|
gpUniform4fv uintptr
|
|
|
|
gpUniformMatrix2fv uintptr
|
|
|
|
gpUniformMatrix3fv uintptr
|
|
|
|
gpUniformMatrix4fv uintptr
|
|
|
|
gpUseProgram uintptr
|
|
|
|
gpVertexAttribPointer uintptr
|
|
|
|
gpViewport uintptr
|
2022-11-13 19:42:37 +01:00
|
|
|
|
|
|
|
isES bool
|
2022-11-13 07:37:18 +01:00
|
|
|
}
|
|
|
|
|
2022-11-13 19:42:37 +01:00
|
|
|
func NewDefaultContext() (Context, error) {
|
|
|
|
ctx := &defaultContext{}
|
|
|
|
if err := ctx.init(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return ctx, nil
|
2022-11-13 07:37:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func boolToInt(b bool) int {
|
|
|
|
if b {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2022-11-13 18:03:36 +01:00
|
|
|
func (c *defaultContext) IsES() bool {
|
2022-11-13 19:42:37 +01:00
|
|
|
return c.isES
|
2022-11-13 18:03:36 +01:00
|
|
|
}
|
|
|
|
|
2022-11-13 07:37:18 +01:00
|
|
|
func (c *defaultContext) ActiveTexture(texture uint32) {
|
|
|
|
purego.SyscallN(c.gpActiveTexture, uintptr(texture))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) AttachShader(program uint32, shader uint32) {
|
|
|
|
purego.SyscallN(c.gpAttachShader, uintptr(program), uintptr(shader))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) BindAttribLocation(program uint32, index uint32, name string) {
|
|
|
|
cname, free := cStr(name)
|
|
|
|
defer free()
|
|
|
|
purego.SyscallN(c.gpBindAttribLocation, uintptr(program), uintptr(index), uintptr(unsafe.Pointer(cname)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) BindBuffer(target uint32, buffer uint32) {
|
|
|
|
purego.SyscallN(c.gpBindBuffer, uintptr(target), uintptr(buffer))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) BindFramebuffer(target uint32, framebuffer uint32) {
|
|
|
|
purego.SyscallN(c.gpBindFramebufferEXT, uintptr(target), uintptr(framebuffer))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) BindRenderbuffer(target uint32, renderbuffer uint32) {
|
|
|
|
purego.SyscallN(c.gpBindRenderbufferEXT, uintptr(target), uintptr(renderbuffer))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) BindTexture(target uint32, texture uint32) {
|
|
|
|
purego.SyscallN(c.gpBindTexture, uintptr(target), uintptr(texture))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
|
|
|
|
purego.SyscallN(c.gpBlendEquationSeparate, uintptr(modeRGB), uintptr(modeAlpha))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
|
|
|
|
purego.SyscallN(c.gpBlendFuncSeparate, uintptr(srcRGB), uintptr(dstRGB), uintptr(srcAlpha), uintptr(dstAlpha))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) BufferData(target uint32, size int, data []byte, usage uint32) {
|
|
|
|
var ptr *byte
|
|
|
|
if len(data) > 0 {
|
|
|
|
ptr = &data[0]
|
|
|
|
}
|
|
|
|
purego.SyscallN(c.gpBufferData, uintptr(target), uintptr(size), uintptr(unsafe.Pointer(ptr)), uintptr(usage))
|
|
|
|
runtime.KeepAlive(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) BufferSubData(target uint32, offset int, data []byte) {
|
|
|
|
purego.SyscallN(c.gpBufferSubData, uintptr(target), uintptr(offset), uintptr(len(data)), uintptr(unsafe.Pointer(&data[0])))
|
|
|
|
runtime.KeepAlive(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) CheckFramebufferStatus(target uint32) uint32 {
|
|
|
|
ret, _, _ := purego.SyscallN(c.gpCheckFramebufferStatusEXT, uintptr(target))
|
|
|
|
return uint32(ret)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Clear(mask uint32) {
|
|
|
|
purego.SyscallN(c.gpClear, uintptr(mask))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) ColorMask(red bool, green bool, blue bool, alpha bool) {
|
|
|
|
purego.SyscallN(c.gpColorMask, uintptr(boolToInt(red)), uintptr(boolToInt(green)), uintptr(boolToInt(blue)), uintptr(boolToInt(alpha)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) CompileShader(shader uint32) {
|
|
|
|
purego.SyscallN(c.gpCompileShader, uintptr(shader))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) CreateProgram() uint32 {
|
|
|
|
ret, _, _ := purego.SyscallN(c.gpCreateProgram)
|
|
|
|
return uint32(ret)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) CreateShader(xtype uint32) uint32 {
|
|
|
|
ret, _, _ := purego.SyscallN(c.gpCreateShader, uintptr(xtype))
|
|
|
|
return uint32(ret)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) DeleteBuffers(buffers []uint32) {
|
|
|
|
purego.SyscallN(c.gpDeleteBuffers, uintptr(len(buffers)), uintptr(unsafe.Pointer(&buffers[0])))
|
|
|
|
runtime.KeepAlive(buffers)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) DeleteFramebuffers(framebuffers []uint32) {
|
|
|
|
purego.SyscallN(c.gpDeleteFramebuffersEXT, uintptr(len(framebuffers)), uintptr(unsafe.Pointer(&framebuffers[0])))
|
|
|
|
runtime.KeepAlive(framebuffers)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) DeleteProgram(program uint32) {
|
|
|
|
purego.SyscallN(c.gpDeleteProgram, uintptr(program))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) DeleteRenderbuffers(renderbuffers []uint32) {
|
|
|
|
purego.SyscallN(c.gpDeleteRenderbuffersEXT, uintptr(len(renderbuffers)), uintptr(unsafe.Pointer(&renderbuffers[0])))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) DeleteShader(shader uint32) {
|
|
|
|
purego.SyscallN(c.gpDeleteShader, uintptr(shader))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) DeleteTextures(textures []uint32) {
|
|
|
|
purego.SyscallN(c.gpDeleteTextures, uintptr(len(textures)), uintptr(unsafe.Pointer(&textures[0])))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Disable(cap uint32) {
|
|
|
|
purego.SyscallN(c.gpDisable, uintptr(cap))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) DisableVertexAttribArray(index uint32) {
|
|
|
|
purego.SyscallN(c.gpDisableVertexAttribArray, uintptr(index))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) DrawElements(mode uint32, count int32, xtype uint32, offset int) {
|
|
|
|
purego.SyscallN(c.gpDrawElements, uintptr(mode), uintptr(count), uintptr(xtype), uintptr(offset))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Enable(cap uint32) {
|
|
|
|
purego.SyscallN(c.gpEnable, uintptr(cap))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) EnableVertexAttribArray(index uint32) {
|
|
|
|
purego.SyscallN(c.gpEnableVertexAttribArray, uintptr(index))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Flush() {
|
|
|
|
purego.SyscallN(c.gpFlush)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) FramebufferRenderbuffer(target uint32, attachment uint32, renderbuffertarget uint32, renderbuffer uint32) {
|
|
|
|
purego.SyscallN(c.gpFramebufferRenderbufferEXT, uintptr(target), uintptr(attachment), uintptr(renderbuffertarget), uintptr(renderbuffer))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) FramebufferTexture2D(target uint32, attachment uint32, textarget uint32, texture uint32, level int32) {
|
|
|
|
purego.SyscallN(c.gpFramebufferTexture2DEXT, uintptr(target), uintptr(attachment), uintptr(textarget), uintptr(texture), uintptr(level))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) GenBuffers(n int32) []uint32 {
|
|
|
|
buffers := make([]uint32, n)
|
|
|
|
purego.SyscallN(c.gpGenBuffers, uintptr(n), uintptr(unsafe.Pointer(&buffers[0])))
|
|
|
|
return buffers
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) GenFramebuffers(n int32) []uint32 {
|
|
|
|
framebuffers := make([]uint32, n)
|
|
|
|
purego.SyscallN(c.gpGenFramebuffersEXT, uintptr(n), uintptr(unsafe.Pointer(&framebuffers[0])))
|
|
|
|
return framebuffers
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) GenRenderbuffers(n int32) []uint32 {
|
|
|
|
renderbuffers := make([]uint32, n)
|
|
|
|
purego.SyscallN(c.gpGenRenderbuffersEXT, uintptr(n), uintptr(unsafe.Pointer(&renderbuffers[0])))
|
|
|
|
return renderbuffers
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) GenTextures(n int32) []uint32 {
|
|
|
|
textures := make([]uint32, n)
|
|
|
|
purego.SyscallN(c.gpGenTextures, uintptr(n), uintptr(unsafe.Pointer(&textures[0])))
|
|
|
|
return textures
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) GetError() uint32 {
|
|
|
|
ret, _, _ := purego.SyscallN(c.gpGetError)
|
|
|
|
return uint32(ret)
|
|
|
|
}
|
|
|
|
|
2022-11-16 15:59:28 +01:00
|
|
|
func (c *defaultContext) GetInteger(pname uint32) int {
|
|
|
|
dst := make([]int32, 1)
|
2022-11-13 07:37:18 +01:00
|
|
|
purego.SyscallN(c.gpGetIntegerv, uintptr(pname), uintptr(unsafe.Pointer(&dst[0])))
|
2022-11-16 15:59:28 +01:00
|
|
|
return int(dst[0])
|
2022-11-13 07:37:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) GetProgramInfoLog(program uint32) string {
|
|
|
|
var bufSize [1]int32
|
|
|
|
c.GetProgramiv(bufSize[:], program, INFO_LOG_LENGTH)
|
|
|
|
infoLog := make([]byte, bufSize[0])
|
|
|
|
purego.SyscallN(c.gpGetProgramInfoLog, uintptr(program), uintptr(bufSize[0]), 0, uintptr(unsafe.Pointer(&infoLog[0])))
|
|
|
|
return string(infoLog)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) GetProgramiv(dst []int32, program uint32, pname uint32) {
|
|
|
|
purego.SyscallN(c.gpGetProgramiv, uintptr(program), uintptr(pname), uintptr(unsafe.Pointer(&dst[0])))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) GetShaderInfoLog(shader uint32) string {
|
|
|
|
var bufSize [1]int32
|
|
|
|
c.GetShaderiv(bufSize[:], shader, INFO_LOG_LENGTH)
|
|
|
|
infoLog := make([]byte, bufSize[0])
|
|
|
|
purego.SyscallN(c.gpGetShaderInfoLog, uintptr(shader), uintptr(bufSize[0]), 0, uintptr(unsafe.Pointer(&infoLog[0])))
|
|
|
|
return string(infoLog)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) GetShaderiv(dst []int32, shader uint32, pname uint32) {
|
|
|
|
purego.SyscallN(c.gpGetShaderiv, uintptr(shader), uintptr(pname), uintptr(unsafe.Pointer(&dst[0])))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) GetUniformLocation(program uint32, name string) int32 {
|
|
|
|
cname, free := cStr(name)
|
|
|
|
defer free()
|
|
|
|
ret, _, _ := purego.SyscallN(c.gpGetUniformLocation, uintptr(program), uintptr(unsafe.Pointer(cname)))
|
|
|
|
return int32(ret)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) IsFramebuffer(framebuffer uint32) bool {
|
|
|
|
ret, _, _ := purego.SyscallN(c.gpIsFramebufferEXT, uintptr(framebuffer))
|
|
|
|
return byte(ret) != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) IsProgram(program uint32) bool {
|
|
|
|
ret, _, _ := purego.SyscallN(c.gpIsProgram, uintptr(program))
|
|
|
|
return byte(ret) != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) IsRenderbuffer(renderbuffer uint32) bool {
|
|
|
|
ret, _, _ := purego.SyscallN(c.gpIsRenderbufferEXT, uintptr(renderbuffer))
|
|
|
|
return byte(ret) != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) IsTexture(texture uint32) bool {
|
|
|
|
ret, _, _ := purego.SyscallN(c.gpIsTexture, uintptr(texture))
|
|
|
|
return byte(ret) != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) LinkProgram(program uint32) {
|
|
|
|
purego.SyscallN(c.gpLinkProgram, uintptr(program))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) PixelStorei(pname uint32, param int32) {
|
|
|
|
purego.SyscallN(c.gpPixelStorei, uintptr(pname), uintptr(param))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) ReadPixels(dst []byte, x int32, y int32, width int32, height int32, format uint32, xtype uint32) {
|
|
|
|
purego.SyscallN(c.gpReadPixels, uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(xtype), uintptr(unsafe.Pointer(&dst[0])))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) RenderbufferStorage(target uint32, internalformat uint32, width int32, height int32) {
|
|
|
|
purego.SyscallN(c.gpRenderbufferStorageEXT, uintptr(target), uintptr(internalformat), uintptr(width), uintptr(height))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Scissor(x int32, y int32, width int32, height int32) {
|
|
|
|
purego.SyscallN(c.gpScissor, uintptr(x), uintptr(y), uintptr(width), uintptr(height))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) ShaderSource(shader uint32, xstring string) {
|
|
|
|
cstring, free := cStr(xstring)
|
|
|
|
defer free()
|
|
|
|
purego.SyscallN(c.gpShaderSource, uintptr(shader), 1, uintptr(unsafe.Pointer(&cstring)), 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) StencilFunc(xfunc uint32, ref int32, mask uint32) {
|
|
|
|
purego.SyscallN(c.gpStencilFunc, uintptr(xfunc), uintptr(ref), uintptr(mask))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) StencilOp(fail uint32, zfail uint32, zpass uint32) {
|
|
|
|
purego.SyscallN(c.gpStencilOp, uintptr(fail), uintptr(zfail), uintptr(zpass))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) TexImage2D(target uint32, level int32, internalformat int32, width int32, height int32, format uint32, xtype uint32, pixels []byte) {
|
|
|
|
var ptr *byte
|
|
|
|
if len(pixels) > 0 {
|
|
|
|
ptr = &pixels[0]
|
|
|
|
}
|
|
|
|
purego.SyscallN(c.gpTexImage2D, uintptr(target), uintptr(level), uintptr(internalformat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(xtype), uintptr(unsafe.Pointer(ptr)))
|
|
|
|
runtime.KeepAlive(pixels)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) TexParameteri(target uint32, pname uint32, param int32) {
|
|
|
|
purego.SyscallN(c.gpTexParameteri, uintptr(target), uintptr(pname), uintptr(param))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, width int32, height int32, format uint32, xtype uint32, pixels []byte) {
|
|
|
|
purego.SyscallN(c.gpTexSubImage2D, uintptr(target), uintptr(level), uintptr(xoffset), uintptr(yoffset), uintptr(width), uintptr(height), uintptr(format), uintptr(xtype), uintptr(unsafe.Pointer(&pixels[0])))
|
|
|
|
runtime.KeepAlive(pixels)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Uniform1fv(location int32, value []float32) {
|
|
|
|
purego.SyscallN(c.gpUniform1fv, uintptr(location), uintptr(len(value)), uintptr(unsafe.Pointer(&value[0])))
|
|
|
|
runtime.KeepAlive(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Uniform1i(location int32, v0 int32) {
|
|
|
|
purego.SyscallN(c.gpUniform1i, uintptr(location), uintptr(v0))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Uniform1iv(location int32, value []int32) {
|
|
|
|
purego.SyscallN(c.gpUniform1iv, uintptr(location), uintptr(len(value)), uintptr(unsafe.Pointer(&value[0])))
|
|
|
|
runtime.KeepAlive(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Uniform2fv(location int32, value []float32) {
|
|
|
|
purego.SyscallN(c.gpUniform2fv, uintptr(location), uintptr(len(value)/2), uintptr(unsafe.Pointer(&value[0])))
|
|
|
|
runtime.KeepAlive(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Uniform3fv(location int32, value []float32) {
|
|
|
|
purego.SyscallN(c.gpUniform3fv, uintptr(location), uintptr(len(value)/3), uintptr(unsafe.Pointer(&value[0])))
|
|
|
|
runtime.KeepAlive(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Uniform4fv(location int32, value []float32) {
|
|
|
|
purego.SyscallN(c.gpUniform4fv, uintptr(location), uintptr(len(value)/4), uintptr(unsafe.Pointer(&value[0])))
|
|
|
|
runtime.KeepAlive(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) UniformMatrix2fv(location int32, transpose bool, value []float32) {
|
|
|
|
purego.SyscallN(c.gpUniformMatrix2fv, uintptr(location), uintptr(len(value)/4), uintptr(boolToInt(transpose)), uintptr(unsafe.Pointer(&value[0])))
|
|
|
|
runtime.KeepAlive(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) UniformMatrix3fv(location int32, transpose bool, value []float32) {
|
|
|
|
purego.SyscallN(c.gpUniformMatrix3fv, uintptr(location), uintptr(len(value)/9), uintptr(boolToInt(transpose)), uintptr(unsafe.Pointer(&value[0])))
|
|
|
|
runtime.KeepAlive(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) UniformMatrix4fv(location int32, transpose bool, value []float32) {
|
|
|
|
purego.SyscallN(c.gpUniformMatrix4fv, uintptr(location), uintptr(len(value)/16), uintptr(boolToInt(transpose)), uintptr(unsafe.Pointer(&value[0])))
|
|
|
|
runtime.KeepAlive(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) UseProgram(program uint32) {
|
|
|
|
purego.SyscallN(c.gpUseProgram, uintptr(program))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset int) {
|
|
|
|
purego.SyscallN(c.gpVertexAttribPointer, uintptr(index), uintptr(size), uintptr(xtype), uintptr(boolToInt(normalized)), uintptr(stride), uintptr(offset))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *defaultContext) Viewport(x int32, y int32, width int32, height int32) {
|
|
|
|
purego.SyscallN(c.gpViewport, uintptr(x), uintptr(y), uintptr(width), uintptr(height))
|
|
|
|
}
|
|
|
|
|
2022-11-13 19:42:37 +01:00
|
|
|
func (c *defaultContext) LoadFunctions() error {
|
|
|
|
c.gpActiveTexture = c.getProcAddress("glActiveTexture")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpActiveTexture == 0 {
|
|
|
|
return errors.New("gl: glActiveTexture is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpAttachShader = c.getProcAddress("glAttachShader")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpAttachShader == 0 {
|
|
|
|
return errors.New("gl: glAttachShader is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpBindAttribLocation = c.getProcAddress("glBindAttribLocation")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpBindAttribLocation == 0 {
|
|
|
|
return errors.New("gl: glBindAttribLocation is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpBindBuffer = c.getProcAddress("glBindBuffer")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpBindBuffer == 0 {
|
|
|
|
return errors.New("gl: glBindBuffer is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpBindFramebufferEXT = c.getProcAddress("glBindFramebufferEXT")
|
|
|
|
c.gpBindRenderbufferEXT = c.getProcAddress("glBindRenderbufferEXT")
|
|
|
|
c.gpBindTexture = c.getProcAddress("glBindTexture")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpBindTexture == 0 {
|
|
|
|
return errors.New("gl: glBindTexture is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpBlendEquationSeparate = c.getProcAddress("glBlendEquationSeparate")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpBlendEquationSeparate == 0 {
|
|
|
|
return errors.New("gl: glBlendEquationSeparate is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpBlendFuncSeparate = c.getProcAddress("glBlendFuncSeparate")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpBlendFuncSeparate == 0 {
|
|
|
|
return errors.New("gl: glBlendFuncSeparate is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpBufferData = c.getProcAddress("glBufferData")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpBufferData == 0 {
|
|
|
|
return errors.New("gl: glBufferData is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpBufferSubData = c.getProcAddress("glBufferSubData")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpBufferSubData == 0 {
|
|
|
|
return errors.New("gl: glBufferSubData is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpCheckFramebufferStatusEXT = c.getProcAddress("glCheckFramebufferStatusEXT")
|
|
|
|
c.gpClear = c.getProcAddress("glClear")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpClear == 0 {
|
|
|
|
return errors.New("gl: glClear is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpColorMask = c.getProcAddress("glColorMask")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpColorMask == 0 {
|
|
|
|
return errors.New("gl: glColorMask is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpCompileShader = c.getProcAddress("glCompileShader")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpCompileShader == 0 {
|
|
|
|
return errors.New("gl: glCompileShader is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpCreateProgram = c.getProcAddress("glCreateProgram")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpCreateProgram == 0 {
|
|
|
|
return errors.New("gl: glCreateProgram is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpCreateShader = c.getProcAddress("glCreateShader")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpCreateShader == 0 {
|
|
|
|
return errors.New("gl: glCreateShader is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpDeleteBuffers = c.getProcAddress("glDeleteBuffers")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpDeleteBuffers == 0 {
|
|
|
|
return errors.New("gl: glDeleteBuffers is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpDeleteFramebuffersEXT = c.getProcAddress("glDeleteFramebuffersEXT")
|
|
|
|
c.gpDeleteProgram = c.getProcAddress("glDeleteProgram")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpDeleteProgram == 0 {
|
|
|
|
return errors.New("gl: glDeleteProgram is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpDeleteRenderbuffersEXT = c.getProcAddress("glDeleteRenderbuffersEXT")
|
|
|
|
c.gpDeleteShader = c.getProcAddress("glDeleteShader")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpDeleteShader == 0 {
|
|
|
|
return errors.New("gl: glDeleteShader is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpDeleteTextures = c.getProcAddress("glDeleteTextures")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpDeleteTextures == 0 {
|
|
|
|
return errors.New("gl: glDeleteTextures is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpDisable = c.getProcAddress("glDisable")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpDisable == 0 {
|
|
|
|
return errors.New("gl: glDisable is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpDisableVertexAttribArray = c.getProcAddress("glDisableVertexAttribArray")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpDisableVertexAttribArray == 0 {
|
|
|
|
return errors.New("gl: glDisableVertexAttribArray is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpDrawElements = c.getProcAddress("glDrawElements")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpDrawElements == 0 {
|
|
|
|
return errors.New("gl: glDrawElements is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpEnable = c.getProcAddress("glEnable")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpEnable == 0 {
|
|
|
|
return errors.New("gl: glEnable is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpEnableVertexAttribArray = c.getProcAddress("glEnableVertexAttribArray")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpEnableVertexAttribArray == 0 {
|
|
|
|
return errors.New("gl: glEnableVertexAttribArray is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpFlush = c.getProcAddress("glFlush")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpFlush == 0 {
|
|
|
|
return errors.New("gl: glFlush is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpFramebufferRenderbufferEXT = c.getProcAddress("glFramebufferRenderbufferEXT")
|
|
|
|
c.gpFramebufferTexture2DEXT = c.getProcAddress("glFramebufferTexture2DEXT")
|
|
|
|
c.gpGenBuffers = c.getProcAddress("glGenBuffers")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpGenBuffers == 0 {
|
|
|
|
return errors.New("gl: glGenBuffers is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpGenFramebuffersEXT = c.getProcAddress("glGenFramebuffersEXT")
|
|
|
|
c.gpGenRenderbuffersEXT = c.getProcAddress("glGenRenderbuffersEXT")
|
|
|
|
c.gpGenTextures = c.getProcAddress("glGenTextures")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpGenTextures == 0 {
|
|
|
|
return errors.New("gl: glGenTextures is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpGetError = c.getProcAddress("glGetError")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpGetError == 0 {
|
|
|
|
return errors.New("gl: glGetError is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpGetIntegerv = c.getProcAddress("glGetIntegerv")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpGetIntegerv == 0 {
|
|
|
|
return errors.New("gl: glGetIntegerv is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpGetProgramInfoLog = c.getProcAddress("glGetProgramInfoLog")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpGetProgramInfoLog == 0 {
|
|
|
|
return errors.New("gl: glGetProgramInfoLog is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpGetProgramiv = c.getProcAddress("glGetProgramiv")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpGetProgramiv == 0 {
|
|
|
|
return errors.New("gl: glGetProgramiv is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpGetShaderInfoLog = c.getProcAddress("glGetShaderInfoLog")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpGetShaderInfoLog == 0 {
|
|
|
|
return errors.New("gl: glGetShaderInfoLog is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpGetShaderiv = c.getProcAddress("glGetShaderiv")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpGetShaderiv == 0 {
|
|
|
|
return errors.New("gl: glGetShaderiv is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpGetUniformLocation = c.getProcAddress("glGetUniformLocation")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpGetUniformLocation == 0 {
|
|
|
|
return errors.New("gl: glGetUniformLocation is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpIsFramebufferEXT = c.getProcAddress("glIsFramebufferEXT")
|
|
|
|
c.gpIsProgram = c.getProcAddress("glIsProgram")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpIsProgram == 0 {
|
|
|
|
return errors.New("gl: glIsProgram is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpIsRenderbufferEXT = c.getProcAddress("glIsRenderbufferEXT")
|
|
|
|
c.gpIsTexture = c.getProcAddress("glIsTexture")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpIsTexture == 0 {
|
|
|
|
return errors.New("gl: glIsTexture is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpLinkProgram = c.getProcAddress("glLinkProgram")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpLinkProgram == 0 {
|
|
|
|
return errors.New("gl: glLinkProgram is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpPixelStorei = c.getProcAddress("glPixelStorei")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpPixelStorei == 0 {
|
|
|
|
return errors.New("gl: glPixelStorei is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpReadPixels = c.getProcAddress("glReadPixels")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpReadPixels == 0 {
|
|
|
|
return errors.New("gl: glReadPixels is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpRenderbufferStorageEXT = c.getProcAddress("glRenderbufferStorageEXT")
|
|
|
|
c.gpScissor = c.getProcAddress("glScissor")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpScissor == 0 {
|
|
|
|
return errors.New("gl: glScissor is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpShaderSource = c.getProcAddress("glShaderSource")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpShaderSource == 0 {
|
|
|
|
return errors.New("gl: glShaderSource is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpStencilFunc = c.getProcAddress("glStencilFunc")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpStencilFunc == 0 {
|
|
|
|
return errors.New("gl: glStencilFunc is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpStencilOp = c.getProcAddress("glStencilOp")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpStencilOp == 0 {
|
|
|
|
return errors.New("gl: glStencilOp is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpTexImage2D = c.getProcAddress("glTexImage2D")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpTexImage2D == 0 {
|
|
|
|
return errors.New("gl: glTexImage2D is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpTexParameteri = c.getProcAddress("glTexParameteri")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpTexParameteri == 0 {
|
|
|
|
return errors.New("gl: glTexParameteri is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpTexSubImage2D = c.getProcAddress("glTexSubImage2D")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpTexSubImage2D == 0 {
|
|
|
|
return errors.New("gl: glTexSubImage2D is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpUniform1fv = c.getProcAddress("glUniform1fv")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpUniform1fv == 0 {
|
|
|
|
return errors.New("gl: glUniform1fv is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpUniform1i = c.getProcAddress("glUniform1i")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpUniform1i == 0 {
|
|
|
|
return errors.New("gl: glUniform1i is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpUniform1iv = c.getProcAddress("glUniform1iv")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpUniform1iv == 0 {
|
|
|
|
return errors.New("gl: glUniform1iv is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpUniform2fv = c.getProcAddress("glUniform2fv")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpUniform2fv == 0 {
|
|
|
|
return errors.New("gl: glUniform2fv is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpUniform3fv = c.getProcAddress("glUniform3fv")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpUniform3fv == 0 {
|
|
|
|
return errors.New("gl: glUniform3fv is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpUniform4fv = c.getProcAddress("glUniform4fv")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpUniform4fv == 0 {
|
|
|
|
return errors.New("gl: glUniform4fv is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpUniformMatrix2fv = c.getProcAddress("glUniformMatrix2fv")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpUniformMatrix2fv == 0 {
|
|
|
|
return errors.New("gl: glUniformMatrix2fv is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpUniformMatrix3fv = c.getProcAddress("glUniformMatrix3fv")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpUniformMatrix3fv == 0 {
|
|
|
|
return errors.New("gl: glUniformMatrix3fv is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpUniformMatrix4fv = c.getProcAddress("glUniformMatrix4fv")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpUniformMatrix4fv == 0 {
|
|
|
|
return errors.New("gl: glUniformMatrix4fv is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpUseProgram = c.getProcAddress("glUseProgram")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpUseProgram == 0 {
|
|
|
|
return errors.New("gl: glUseProgram is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpVertexAttribPointer = c.getProcAddress("glVertexAttribPointer")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpVertexAttribPointer == 0 {
|
|
|
|
return errors.New("gl: glVertexAttribPointer is missing")
|
|
|
|
}
|
2022-11-13 19:42:37 +01:00
|
|
|
c.gpViewport = c.getProcAddress("glViewport")
|
2022-11-13 07:37:18 +01:00
|
|
|
if c.gpViewport == 0 {
|
|
|
|
return errors.New("gl: glViewport is missing")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2022-11-13 14:21:45 +01:00
|
|
|
|
|
|
|
// cStr takes a Go string (with or without null-termination)
|
|
|
|
// and returns the C counterpart.
|
|
|
|
//
|
|
|
|
// The returned free function must be called once you are done using the string
|
|
|
|
// in order to free the memory.
|
|
|
|
func cStr(str string) (cstr *byte, free func()) {
|
|
|
|
bs := []byte(str)
|
|
|
|
if len(bs) == 0 || bs[len(bs)-1] != 0 {
|
|
|
|
bs = append(bs, 0)
|
|
|
|
}
|
|
|
|
return &bs[0], func() {
|
|
|
|
runtime.KeepAlive(bs)
|
|
|
|
bs = nil
|
|
|
|
}
|
|
|
|
}
|