gls.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. package gls
  2. // // Platform build flags
  3. // #cgo freebsd CFLAGS: -DGL_GLEXT_PROTOTYPES
  4. // #cgo freebsd LDFLAGS: -ldl -lGL
  5. //
  6. // #cgo linux CFLAGS: -DGL_GLEXT_PROTOTYPES
  7. // #cgo linux LDFLAGS: -ldl -lGL
  8. //
  9. // #cgo windows CFLAGS: -DGL_GEXT_PROTOTYPES
  10. // #cgo windows LDFLAGS: -lopengl32
  11. //
  12. // #include <stdlib.h>
  13. // #include "glcorearb.h"
  14. // #include "glapi.h"
  15. import "C"
  16. import (
  17. "fmt"
  18. "math"
  19. "reflect"
  20. "unsafe"
  21. )
  22. type GLS struct {
  23. stats Stats // statistics
  24. Prog *Program // Current active program
  25. programs map[*Program]bool // Programs cache
  26. checkErrors bool // check openGL API errors flag
  27. viewportX int32 // cached last set viewport x
  28. viewportY int32 // cached last set viewport y
  29. viewportWidth int32 // cached last set viewport width
  30. viewportHeight int32 // cached last set viewport height
  31. lineWidth float32 // cached last set line width
  32. sideView int // cached last set triangle side view mode
  33. depthFunc uint32 // cached last set depth function
  34. depthMask int // cached last set depth mask
  35. capabilities map[int]int // cached capabilities (Enable/Disable)
  36. blendEquation uint32
  37. blendSrc uint32
  38. blendDst uint32
  39. blendEquationRGB uint32
  40. blendEquationAlpha uint32
  41. blendSrcRGB uint32
  42. blendSrcAlpha uint32
  43. blendDstRGB uint32
  44. blendDstAlpha uint32
  45. polygonOffsetFactor float32
  46. polygonOffsetUnits float32
  47. logBuf []byte // pre allocated buffer for program/shader logs
  48. }
  49. type Stats struct {
  50. Vaos int // Number of Vertex Array Objects
  51. Vbos int // Number of Vertex Buffer Objects
  52. Textures int // Number of Textures
  53. // Cummulative fields
  54. Caphits int // Number of hits for Enable/Disable
  55. Unisets int // Number of uniform sets
  56. Drawcalls int // Number of draw calls
  57. }
  58. const (
  59. capUndef = 0
  60. capDisabled = 1
  61. capEnabled = 2
  62. uintUndef = math.MaxUint32
  63. intFalse = 0
  64. intTrue = 1
  65. maxLogBuf = 32 * 1024
  66. )
  67. // Polygon side view.
  68. const (
  69. FrontSide = iota + 1
  70. BackSide
  71. DoubleSide
  72. )
  73. // New creates and returns a new instance of an GLS object
  74. // which encapsulates the state of an OpenGL context
  75. // This should be called only after an active OpenGL context
  76. // was established, such as by creating a new window.
  77. func New() (*GLS, error) {
  78. gs := new(GLS)
  79. gs.Reset()
  80. // Initialize GL
  81. err := C.glapiLoad()
  82. if err != 0 {
  83. return nil, fmt.Errorf("Error loading OpenGL")
  84. }
  85. gs.SetDefaultState()
  86. gs.checkErrors = true
  87. gs.logBuf = make([]byte, maxLogBuf)
  88. return gs, nil
  89. }
  90. // SetCheckErrors enables/disables checking for errors after the
  91. // call of any OpenGL function. It is enabled by default but
  92. // could be disabled after an application is stable to improve the performance.
  93. func (gs *GLS) SetCheckErrors(enable bool) {
  94. if enable {
  95. C.glapiCheckError(1)
  96. } else {
  97. C.glapiCheckError(1)
  98. }
  99. gs.checkErrors = enable
  100. }
  101. // ChecksErrors returns if error checking is enabled or not.
  102. func (gs *GLS) CheckErrors() bool {
  103. return gs.checkErrors
  104. }
  105. // Reset resets the internal state kept of the OpenGL
  106. func (gs *GLS) Reset() {
  107. gs.lineWidth = 0.0
  108. gs.sideView = uintUndef
  109. gs.depthFunc = 0
  110. gs.depthMask = uintUndef
  111. gs.capabilities = make(map[int]int)
  112. gs.programs = make(map[*Program]bool)
  113. gs.Prog = nil
  114. gs.blendEquation = uintUndef
  115. gs.blendSrc = uintUndef
  116. gs.blendDst = uintUndef
  117. gs.blendEquationRGB = 0
  118. gs.blendEquationAlpha = 0
  119. gs.blendSrcRGB = uintUndef
  120. gs.blendSrcAlpha = uintUndef
  121. gs.blendDstRGB = uintUndef
  122. gs.blendDstAlpha = uintUndef
  123. gs.polygonOffsetFactor = -1
  124. gs.polygonOffsetUnits = -1
  125. }
  126. func (gs *GLS) SetDefaultState() {
  127. C.glClearColor(0, 0, 0, 1)
  128. C.glClearDepth(1)
  129. C.glClearStencil(0)
  130. gs.Enable(DEPTH_TEST)
  131. gs.DepthFunc(LEQUAL)
  132. gs.FrontFace(CCW)
  133. gs.CullFace(BACK)
  134. gs.Enable(CULL_FACE)
  135. gs.Enable(BLEND)
  136. gs.BlendEquation(FUNC_ADD)
  137. gs.BlendFunc(SRC_ALPHA, ONE_MINUS_SRC_ALPHA)
  138. gs.Enable(VERTEX_PROGRAM_POINT_SIZE)
  139. gs.Enable(PROGRAM_POINT_SIZE)
  140. gs.Enable(MULTISAMPLE)
  141. gs.Enable(POLYGON_OFFSET_FILL)
  142. gs.Enable(POLYGON_OFFSET_LINE)
  143. gs.Enable(POLYGON_OFFSET_POINT)
  144. }
  145. func (gs *GLS) ActiveTexture(texture uint32) {
  146. C.glActiveTexture(C.GLenum(texture))
  147. }
  148. func (gs *GLS) AttachShader(program, shader uint32) {
  149. C.glAttachShader(C.GLuint(program), C.GLuint(shader))
  150. }
  151. func (gs *GLS) BindBuffer(target int, vbo uint32) {
  152. C.glBindBuffer(C.GLenum(target), C.GLuint(vbo))
  153. }
  154. func (gs *GLS) BindTexture(target int, tex uint32) {
  155. C.glBindTexture(C.GLenum(target), C.GLuint(tex))
  156. }
  157. func (gs *GLS) BindVertexArray(vao uint32) {
  158. C.glBindVertexArray(C.GLuint(vao))
  159. }
  160. func (gs *GLS) BlendEquation(mode uint32) {
  161. if gs.blendEquation == mode {
  162. return
  163. }
  164. C.glBlendEquation(C.GLenum(mode))
  165. gs.blendEquation = mode
  166. }
  167. func (gs *GLS) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
  168. if gs.blendEquationRGB == modeRGB && gs.blendEquationAlpha == modeAlpha {
  169. return
  170. }
  171. C.glBlendEquationSeparate(C.GLenum(modeRGB), C.GLenum(modeAlpha))
  172. gs.blendEquationRGB = modeRGB
  173. gs.blendEquationAlpha = modeAlpha
  174. }
  175. func (gs *GLS) BlendFunc(sfactor, dfactor uint32) {
  176. if gs.blendSrc == sfactor && gs.blendDst == dfactor {
  177. return
  178. }
  179. C.glBlendFunc(C.GLenum(sfactor), C.GLenum(dfactor))
  180. gs.blendSrc = sfactor
  181. gs.blendDst = dfactor
  182. }
  183. func (gs *GLS) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
  184. if gs.blendSrcRGB == srcRGB && gs.blendDstRGB == dstRGB &&
  185. gs.blendSrcAlpha == srcAlpha && gs.blendDstAlpha == dstAlpha {
  186. return
  187. }
  188. C.glBlendFuncSeparate(C.GLenum(srcRGB), C.GLenum(dstRGB), C.GLenum(srcAlpha), C.GLenum(dstAlpha))
  189. gs.blendSrcRGB = srcRGB
  190. gs.blendDstRGB = dstRGB
  191. gs.blendSrcAlpha = srcAlpha
  192. gs.blendDstAlpha = dstAlpha
  193. }
  194. func (gs *GLS) BufferData(target uint32, size int, data interface{}, usage uint32) {
  195. C.glBufferData(C.GLenum(target), C.GLsizeiptr(size), ptr(data), C.GLenum(usage))
  196. }
  197. func (gs *GLS) ClearColor(r, g, b, a float32) {
  198. C.glClearColor(C.GLfloat(r), C.GLfloat(g), C.GLfloat(b), C.GLfloat(a))
  199. }
  200. func (gs *GLS) Clear(mask uint) {
  201. C.glClear(C.GLbitfield(mask))
  202. }
  203. func (gs *GLS) CompileShader(shader uint32) {
  204. C.glCompileShader(C.GLuint(shader))
  205. }
  206. func (gs *GLS) CreateProgram() uint32 {
  207. p := C.glCreateProgram()
  208. return uint32(p)
  209. }
  210. func (gs *GLS) CreateShader(stype uint32) uint32 {
  211. h := C.glCreateShader(C.GLenum(stype))
  212. return uint32(h)
  213. }
  214. func (gs *GLS) DeleteBuffers(vbos ...uint32) {
  215. C.glDeleteBuffers(C.GLsizei(len(vbos)), (*C.GLuint)(&vbos[0]))
  216. }
  217. func (gs *GLS) DeleteShader(shader uint32) {
  218. C.glDeleteShader(C.GLuint(shader))
  219. }
  220. func (gs *GLS) DeleteProgram(program uint32) {
  221. C.glDeleteProgram(C.GLuint(program))
  222. }
  223. func (gs *GLS) DeleteTextures(tex ...uint32) {
  224. C.glDeleteTextures(C.GLsizei(len(tex)), (*C.GLuint)(&tex[0]))
  225. gs.stats.Textures -= len(tex)
  226. }
  227. func (gs *GLS) DeleteVertexArrays(vaos ...uint32) {
  228. C.glDeleteVertexArrays(C.GLsizei(len(vaos)), (*C.GLuint)(&vaos[0]))
  229. }
  230. func (gs *GLS) DepthFunc(mode uint32) {
  231. if gs.depthFunc == mode {
  232. return
  233. }
  234. C.glDepthFunc(C.GLenum(mode))
  235. gs.depthFunc = mode
  236. }
  237. func (gs *GLS) DepthMask(flag bool) {
  238. if gs.depthMask == intTrue && flag {
  239. return
  240. }
  241. if gs.depthMask == intFalse && !flag {
  242. return
  243. }
  244. C.glDepthMask(bool2c(flag))
  245. if flag {
  246. gs.depthMask = intTrue
  247. } else {
  248. gs.depthMask = intFalse
  249. }
  250. }
  251. func (gs *GLS) DrawArrays(mode uint32, first int32, count int32) {
  252. C.glDrawArrays(C.GLenum(mode), C.GLint(first), C.GLsizei(count))
  253. gs.stats.Drawcalls++
  254. }
  255. func (gs *GLS) DrawElements(mode uint32, count int32, itype uint32, start uint32) {
  256. C.glDrawElements(C.GLenum(mode), C.GLsizei(count), C.GLenum(itype), ptrOffset(int(start)))
  257. gs.stats.Drawcalls++
  258. }
  259. func (gs *GLS) Enable(cap int) {
  260. if gs.capabilities[cap] == capEnabled {
  261. gs.stats.Caphits++
  262. return
  263. }
  264. C.glEnable(C.GLenum(cap))
  265. gs.capabilities[cap] = capEnabled
  266. }
  267. func (gs *GLS) EnableVertexAttribArray(index uint32) {
  268. C.glEnableVertexAttribArray(C.GLuint(index))
  269. }
  270. func (gs *GLS) Disable(cap int) {
  271. if gs.capabilities[cap] == capDisabled {
  272. gs.stats.Caphits++
  273. return
  274. }
  275. C.glDisable(C.GLenum(cap))
  276. gs.capabilities[cap] = capDisabled
  277. }
  278. func (gs *GLS) CullFace(mode uint32) {
  279. C.glCullFace(C.GLenum(mode))
  280. }
  281. func (gs *GLS) FrontFace(mode uint32) {
  282. C.glFrontFace(C.GLenum(mode))
  283. }
  284. func (gs *GLS) GenBuffer() uint32 {
  285. var buf uint32
  286. C.glGenBuffers(1, (*C.GLuint)(&buf))
  287. gs.stats.Vbos++
  288. return buf
  289. }
  290. func (gs *GLS) GenerateMipmap(target uint32) {
  291. C.glGenerateMipmap(C.GLenum(target))
  292. }
  293. func (gs *GLS) GenTexture() uint32 {
  294. var tex uint32
  295. C.glGenTextures(1, (*C.GLuint)(&tex))
  296. gs.stats.Textures++
  297. return tex
  298. }
  299. func (gs *GLS) GenVertexArray() uint32 {
  300. var vao uint32
  301. C.glGenVertexArrays(1, (*C.GLuint)(&vao))
  302. gs.stats.Vaos++
  303. return vao
  304. }
  305. func (gs *GLS) GetAttribLocation(program uint32, name string) int32 {
  306. cname := C.CString(name)
  307. defer C.free(unsafe.Pointer(cname))
  308. res := C.glGetAttribLocation(C.GLuint(program), (*C.GLchar)(cname))
  309. return int32(res)
  310. }
  311. func (gs *GLS) GetProgramiv(program, pname uint32, params *int32) {
  312. C.glGetProgramiv(C.GLuint(program), C.GLenum(pname), (*C.GLint)(params))
  313. }
  314. func (gs *GLS) GetProgramInfoLog(program uint32) string {
  315. // Get length of program info log buffer
  316. var logLength int32
  317. gs.GetProgramiv(program, INFO_LOG_LENGTH, &logLength)
  318. if logLength == 0 {
  319. return ""
  320. }
  321. C.glGetProgramInfoLog(C.GLuint(program), maxLogBuf, nil, (*C.GLchar)(unsafe.Pointer(&gs.logBuf[0])))
  322. return string(gs.logBuf)
  323. }
  324. func (gs *GLS) GetShaderInfoLog(shader uint32) string {
  325. // Get length of shaderinfo log buffer
  326. var logLength int32
  327. gs.GetShaderiv(shader, INFO_LOG_LENGTH, &logLength)
  328. if logLength == 0 {
  329. return ""
  330. }
  331. buf := make([]byte, logLength)
  332. C.glGetShaderInfoLog(C.GLuint(shader), C.GLsizei(logLength), nil, (*C.GLchar)(unsafe.Pointer(&gs.logBuf[0])))
  333. return string(buf)
  334. }
  335. func (gs *GLS) GetString(name uint32) string {
  336. cstr := C.glGetString(C.GLenum(name))
  337. return goStr((*uint8)(cstr))
  338. }
  339. func (gs *GLS) GetUniformLocation(program uint32, name string) int32 {
  340. cname := C.CString(name)
  341. defer C.free(unsafe.Pointer(cname))
  342. loc := C.glGetUniformLocation(C.GLuint(program), (*C.GLchar)(cname))
  343. return int32(loc)
  344. }
  345. func (gs *GLS) GetViewport() (x, y, width, height int32) {
  346. return gs.viewportX, gs.viewportY, gs.viewportWidth, gs.viewportHeight
  347. }
  348. func (gs *GLS) LineWidth(width float32) {
  349. if gs.lineWidth == width {
  350. return
  351. }
  352. C.glLineWidth(C.GLfloat(width))
  353. gs.lineWidth = width
  354. }
  355. func (gs *GLS) LinkProgram(program uint32) {
  356. C.glLinkProgram(C.GLuint(program))
  357. }
  358. func (gs *GLS) SetDepthTest(mode bool) {
  359. if mode {
  360. gs.Enable(DEPTH_TEST)
  361. } else {
  362. gs.Disable(DEPTH_TEST)
  363. }
  364. }
  365. func (gs *GLS) SetSideView(mode int) {
  366. if gs.sideView == mode {
  367. return
  368. }
  369. switch mode {
  370. // Default: show only the front size
  371. case FrontSide:
  372. gs.Enable(CULL_FACE)
  373. C.glFrontFace(CCW)
  374. // Show only the back side
  375. case BackSide:
  376. gs.Enable(CULL_FACE)
  377. C.glFrontFace(CW)
  378. // Show both sides
  379. case DoubleSide:
  380. gs.Disable(CULL_FACE)
  381. default:
  382. panic("SetSideView() invalid mode")
  383. }
  384. gs.sideView = mode
  385. }
  386. func (gs *GLS) GetShaderiv(shader, pname uint32, params *int32) {
  387. C.glGetShaderiv(C.GLuint(shader), C.GLenum(pname), (*C.GLint)(params))
  388. }
  389. func (gs *GLS) ShaderSource(shader uint32, src string) {
  390. csource := C.CString(src)
  391. defer C.free(unsafe.Pointer(csource))
  392. C.glShaderSource(C.GLuint(shader), 1, (**C.GLchar)(unsafe.Pointer(csource)), nil)
  393. }
  394. func (gs *GLS) TexImage2D(target uint32, level int32, iformat int32, width int32, height int32, border int32, format uint32, itype uint32, data interface{}) {
  395. C.glTexImage2D(C.GLenum(target),
  396. C.GLint(level),
  397. C.GLint(iformat),
  398. C.GLsizei(width),
  399. C.GLsizei(height),
  400. C.GLint(border),
  401. C.GLenum(format),
  402. C.GLenum(itype),
  403. ptr(data))
  404. }
  405. func (gs *GLS) TexStorage2D(target int, levels int, iformat int, width, height int) {
  406. C.glTexStorage2D(C.GLenum(target), C.GLsizei(levels), C.GLenum(iformat), C.GLsizei(width), C.GLsizei(height))
  407. }
  408. func (gs *GLS) TexParameteri(target uint32, pname uint32, param int32) {
  409. C.glTexParameteri(C.GLenum(target), C.GLenum(pname), C.GLint(param))
  410. }
  411. func (gs *GLS) PolygonMode(face, mode int) {
  412. C.glPolygonMode(C.GLenum(face), C.GLenum(mode))
  413. }
  414. func (gs *GLS) PolygonOffset(factor float32, units float32) {
  415. if gs.polygonOffsetFactor == factor && gs.polygonOffsetUnits == units {
  416. return
  417. }
  418. C.glPolygonOffset(C.GLfloat(factor), C.GLfloat(units))
  419. gs.polygonOffsetFactor = factor
  420. gs.polygonOffsetUnits = units
  421. }
  422. func (gs *GLS) Uniform1i(location int32, v0 int32) {
  423. C.glUniform1i(C.GLint(location), C.GLint(v0))
  424. gs.stats.Unisets++
  425. }
  426. func (gs *GLS) Uniform1f(location int32, v0 float32) {
  427. C.glUniform1f(C.GLint(location), C.GLfloat(v0))
  428. gs.stats.Unisets++
  429. }
  430. func (gs *GLS) Uniform2f(location int32, v0, v1 float32) {
  431. C.glUniform2f(C.GLint(location), C.GLfloat(v0), C.GLfloat(v1))
  432. gs.stats.Unisets++
  433. }
  434. func (gs *GLS) Uniform3f(location int32, v0, v1, v2 float32) {
  435. C.glUniform3f(C.GLint(location), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2))
  436. gs.stats.Unisets++
  437. }
  438. func (gs *GLS) Uniform4f(location int32, v0, v1, v2, v3 float32) {
  439. C.glUniform4f(C.GLint(location), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2), C.GLfloat(v3))
  440. gs.stats.Unisets++
  441. }
  442. func (gs *GLS) UniformMatrix3fv(location int32, count int32, transpose bool, pm *float32) {
  443. C.glUniformMatrix3fv(C.GLint(location), C.GLsizei(count), bool2c(transpose), (*C.GLfloat)(pm))
  444. gs.stats.Unisets++
  445. }
  446. func (gs *GLS) UniformMatrix4fv(location int32, count int32, transpose bool, pm *float32) {
  447. C.glUniformMatrix4fv(C.GLint(location), C.GLsizei(count), bool2c(transpose), (*C.GLfloat)(pm))
  448. gs.stats.Unisets++
  449. }
  450. func (gs *GLS) Uniform1fv(location int32, count int32, v []float32) {
  451. C.glUniform1fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(&v[0]))
  452. gs.stats.Unisets++
  453. }
  454. func (gs *GLS) Uniform2fv(location int32, count int32, v []float32) {
  455. C.glUniform2fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(&v[0]))
  456. gs.stats.Unisets++
  457. }
  458. func (gs *GLS) Uniform3fv(location int32, count int32, v []float32) {
  459. C.glUniform3fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(&v[0]))
  460. gs.stats.Unisets++
  461. }
  462. func (gs *GLS) Uniform4fv(location int32, count int32, v []float32) {
  463. C.glUniform4fv(C.GLint(location), C.GLsizei(count), (*C.GLfloat)(&v[0]))
  464. gs.stats.Unisets++
  465. }
  466. func (gs *GLS) VertexAttribPointer(index uint32, size int32, xtype uint32, normalized bool, stride int32, offset uint32) {
  467. C.glVertexAttribPointer(C.GLuint(index), C.GLint(size), C.GLenum(xtype), bool2c(normalized), C.GLsizei(stride), ptrOffset(int(offset)))
  468. }
  469. func (gs *GLS) Viewport(x, y, width, height int32) {
  470. C.glViewport(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
  471. gs.viewportX = x
  472. gs.viewportY = y
  473. gs.viewportWidth = width
  474. gs.viewportHeight = height
  475. }
  476. // Use set this program as the current program.
  477. //func (gs *GLS) UseProgram(prog *Program) {
  478. //
  479. // if prog.handle == 0 {
  480. // panic("Invalid program")
  481. // }
  482. // C.glUseProgram(prog.handle)
  483. // gs.Prog = prog
  484. //
  485. // // Inserts program in cache if not already there.
  486. // if !gs.programs[prog] {
  487. // gs.programs[prog] = true
  488. // log.Debug("New Program activated. Total: %d", len(gs.programs))
  489. // }
  490. //}
  491. // Ptr takes a slice or pointer (to a singular scalar value or the first
  492. // element of an array or slice) and returns its GL-compatible address.
  493. //
  494. // For example:
  495. //
  496. // var data []uint8
  497. // ...
  498. // gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
  499. func ptr(data interface{}) unsafe.Pointer {
  500. if data == nil {
  501. return unsafe.Pointer(nil)
  502. }
  503. var addr unsafe.Pointer
  504. v := reflect.ValueOf(data)
  505. switch v.Type().Kind() {
  506. case reflect.Ptr:
  507. e := v.Elem()
  508. switch e.Kind() {
  509. case
  510. reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  511. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
  512. reflect.Float32, reflect.Float64:
  513. addr = unsafe.Pointer(e.UnsafeAddr())
  514. default:
  515. panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind()))
  516. }
  517. case reflect.Uintptr:
  518. addr = unsafe.Pointer(v.Pointer())
  519. case reflect.Slice:
  520. addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
  521. default:
  522. panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type()))
  523. }
  524. return addr
  525. }
  526. // bool2c convert a Go bool to C.GLboolean
  527. func bool2c(b bool) C.GLboolean {
  528. if b {
  529. return C.GLboolean(1)
  530. }
  531. return C.GLboolean(0)
  532. }
  533. // ptrOffset takes a pointer offset and returns a GL-compatible pointer.
  534. // Useful for functions such as glVertexAttribPointer that take pointer
  535. // parameters indicating an offset rather than an absolute memory address.
  536. func ptrOffset(offset int) unsafe.Pointer {
  537. return unsafe.Pointer(uintptr(offset))
  538. }
  539. //// Str takes a null-terminated Go string and returns its GL-compatible address.
  540. //// This function reaches into Go string storage in an unsafe way so the caller
  541. //// must ensure the string is not garbage collected.
  542. //func Str(str string) *uint8 {
  543. // if !strings.HasSuffix(str, "\x00") {
  544. // panic("str argument missing null terminator: " + str)
  545. // }
  546. // header := (*reflect.StringHeader)(unsafe.Pointer(&str))
  547. // return (*uint8)(unsafe.Pointer(header.Data))
  548. //}
  549. // goStr takes a null-terminated string returned by OpenGL and constructs a
  550. // corresponding Go string.
  551. func goStr(cstr *uint8) string {
  552. return C.GoString((*C.char)(unsafe.Pointer(cstr)))
  553. }