gls.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package gls
  5. // #include <stdlib.h>
  6. // #include "glcorearb.h"
  7. // #include "glapi.h"
  8. import "C"
  9. import (
  10. "fmt"
  11. "math"
  12. "reflect"
  13. "unsafe"
  14. )
  15. // GLS encapsulates the state of an OpenGL context and contains
  16. // methods to call OpenGL functions.
  17. type GLS struct {
  18. stats Stats // statistics
  19. Prog *Program // current active program
  20. programs map[*Program]bool // programs cache
  21. checkErrors bool // check openGL API errors flag
  22. viewportX int32 // cached last set viewport x
  23. viewportY int32 // cached last set viewport y
  24. viewportWidth int32 // cached last set viewport width
  25. viewportHeight int32 // cached last set viewport height
  26. lineWidth float32 // cached last set line width
  27. sideView int // cached last set triangle side view mode
  28. depthFunc uint32 // cached last set depth function
  29. depthMask int // cached last set depth mask
  30. capabilities map[int]int // cached capabilities (Enable/Disable)
  31. blendEquation uint32 // cached last set blend equation value
  32. blendSrc uint32 // cached last set blend src value
  33. blendDst uint32 // cached last set blend equation destination value
  34. blendEquationRGB uint32 // cached last set blend equation rgb value
  35. blendEquationAlpha uint32 // cached last set blend equation alpha value
  36. blendSrcRGB uint32 // cached last set blend src rgb
  37. blendSrcAlpha uint32 // cached last set blend src alpha value
  38. blendDstRGB uint32 // cached last set blend destination rgb value
  39. blendDstAlpha uint32 // cached last set blend destination alpha value
  40. polygonOffsetFactor float32 // cached last set polygon offset factor
  41. polygonOffsetUnits float32 // cached last set polygon offset units
  42. gobuf []byte // conversion buffer with GO memory
  43. cbuf []byte // conversion buffer with C memory
  44. }
  45. // Stats contains counters of OpenGL resources being used as well
  46. // the cummulative numbers of some OpenGL calls activities for performance
  47. // evaluation.
  48. type Stats struct {
  49. Vaos int // Number of Vertex Array Objects
  50. Vbos int // Number of Vertex Buffer Objects
  51. Textures int // Number of Textures
  52. Caphits uint64 // Cummulative number of hits for Enable/Disable
  53. Unisets uint64 // Cummulative number of uniform sets
  54. Drawcalls uint64 // Cummulative number of draw calls
  55. }
  56. // Polygon side view.
  57. const (
  58. FrontSide = iota + 1
  59. BackSide
  60. DoubleSide
  61. )
  62. const (
  63. capUndef = 0
  64. capDisabled = 1
  65. capEnabled = 2
  66. uintUndef = math.MaxUint32
  67. intFalse = 0
  68. intTrue = 1
  69. )
  70. // New creates and returns a new instance of an GLS object
  71. // which encapsulates the state of an OpenGL context
  72. // This should be called only after an active OpenGL context
  73. // was established, such as by creating a new window.
  74. func New() (*GLS, error) {
  75. gs := new(GLS)
  76. gs.reset()
  77. // Load OpenGL functions
  78. err := C.glapiLoad()
  79. if err != 0 {
  80. return nil, fmt.Errorf("Error loading OpenGL")
  81. }
  82. gs.setDefaultState()
  83. gs.checkErrors = true
  84. // Preallocates conversion buffers
  85. size := 1 * 1024
  86. gs.gobuf = make([]byte, size)
  87. p := C.malloc(C.size_t(size))
  88. gs.cbuf = (*[1 << 30]byte)(unsafe.Pointer(p))[:size:size]
  89. return gs, nil
  90. }
  91. // SetCheckErrors enables/disables checking for errors after the
  92. // call of any OpenGL function. It is enabled by default but
  93. // could be disabled after an application is stable to improve the performance.
  94. func (gs *GLS) SetCheckErrors(enable bool) {
  95. if enable {
  96. C.glapiCheckError(1)
  97. } else {
  98. C.glapiCheckError(1)
  99. }
  100. gs.checkErrors = enable
  101. }
  102. // ChecksErrors returns if error checking is enabled or not.
  103. func (gs *GLS) CheckErrors() bool {
  104. return gs.checkErrors
  105. }
  106. // reset resets the internal state kept of the OpenGL
  107. func (gs *GLS) reset() {
  108. gs.lineWidth = 0.0
  109. gs.sideView = uintUndef
  110. gs.depthFunc = 0
  111. gs.depthMask = uintUndef
  112. gs.capabilities = make(map[int]int)
  113. gs.programs = make(map[*Program]bool)
  114. gs.Prog = nil
  115. gs.blendEquation = uintUndef
  116. gs.blendSrc = uintUndef
  117. gs.blendDst = uintUndef
  118. gs.blendEquationRGB = 0
  119. gs.blendEquationAlpha = 0
  120. gs.blendSrcRGB = uintUndef
  121. gs.blendSrcAlpha = uintUndef
  122. gs.blendDstRGB = uintUndef
  123. gs.blendDstAlpha = uintUndef
  124. gs.polygonOffsetFactor = -1
  125. gs.polygonOffsetUnits = -1
  126. }
  127. // setDefaultState is used internally to set the initial state of OpenGL
  128. // for this context.
  129. func (gs *GLS) setDefaultState() {
  130. C.glClearColor(0, 0, 0, 1)
  131. C.glClearDepth(1)
  132. C.glClearStencil(0)
  133. gs.Enable(DEPTH_TEST)
  134. gs.DepthFunc(LEQUAL)
  135. gs.FrontFace(CCW)
  136. gs.CullFace(BACK)
  137. gs.Enable(CULL_FACE)
  138. gs.Enable(BLEND)
  139. gs.BlendEquation(FUNC_ADD)
  140. gs.BlendFunc(SRC_ALPHA, ONE_MINUS_SRC_ALPHA)
  141. gs.Enable(VERTEX_PROGRAM_POINT_SIZE)
  142. gs.Enable(PROGRAM_POINT_SIZE)
  143. gs.Enable(MULTISAMPLE)
  144. gs.Enable(POLYGON_OFFSET_FILL)
  145. gs.Enable(POLYGON_OFFSET_LINE)
  146. gs.Enable(POLYGON_OFFSET_POINT)
  147. }
  148. // Stats copy the current values of the internal statistics structure
  149. // to the specified pointer.
  150. func (gs *GLS) Stats(s *Stats) {
  151. *s = gs.stats
  152. }
  153. func (gs *GLS) ActiveTexture(texture uint32) {
  154. C.glActiveTexture(C.GLenum(texture))
  155. }
  156. func (gs *GLS) AttachShader(program, shader uint32) {
  157. C.glAttachShader(C.GLuint(program), C.GLuint(shader))
  158. }
  159. func (gs *GLS) BindBuffer(target int, vbo uint32) {
  160. C.glBindBuffer(C.GLenum(target), C.GLuint(vbo))
  161. }
  162. func (gs *GLS) BindTexture(target int, tex uint32) {
  163. C.glBindTexture(C.GLenum(target), C.GLuint(tex))
  164. }
  165. func (gs *GLS) BindVertexArray(vao uint32) {
  166. C.glBindVertexArray(C.GLuint(vao))
  167. }
  168. func (gs *GLS) BlendEquation(mode uint32) {
  169. if gs.blendEquation == mode {
  170. return
  171. }
  172. C.glBlendEquation(C.GLenum(mode))
  173. gs.blendEquation = mode
  174. }
  175. func (gs *GLS) BlendEquationSeparate(modeRGB uint32, modeAlpha uint32) {
  176. if gs.blendEquationRGB == modeRGB && gs.blendEquationAlpha == modeAlpha {
  177. return
  178. }
  179. C.glBlendEquationSeparate(C.GLenum(modeRGB), C.GLenum(modeAlpha))
  180. gs.blendEquationRGB = modeRGB
  181. gs.blendEquationAlpha = modeAlpha
  182. }
  183. func (gs *GLS) BlendFunc(sfactor, dfactor uint32) {
  184. if gs.blendSrc == sfactor && gs.blendDst == dfactor {
  185. return
  186. }
  187. C.glBlendFunc(C.GLenum(sfactor), C.GLenum(dfactor))
  188. gs.blendSrc = sfactor
  189. gs.blendDst = dfactor
  190. }
  191. func (gs *GLS) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32, dstAlpha uint32) {
  192. if gs.blendSrcRGB == srcRGB && gs.blendDstRGB == dstRGB &&
  193. gs.blendSrcAlpha == srcAlpha && gs.blendDstAlpha == dstAlpha {
  194. return
  195. }
  196. C.glBlendFuncSeparate(C.GLenum(srcRGB), C.GLenum(dstRGB), C.GLenum(srcAlpha), C.GLenum(dstAlpha))
  197. gs.blendSrcRGB = srcRGB
  198. gs.blendDstRGB = dstRGB
  199. gs.blendSrcAlpha = srcAlpha
  200. gs.blendDstAlpha = dstAlpha
  201. }
  202. func (gs *GLS) BufferData(target uint32, size int, data interface{}, usage uint32) {
  203. C.glBufferData(C.GLenum(target), C.GLsizeiptr(size), ptr(data), C.GLenum(usage))
  204. }
  205. func (gs *GLS) ClearColor(r, g, b, a float32) {
  206. C.glClearColor(C.GLfloat(r), C.GLfloat(g), C.GLfloat(b), C.GLfloat(a))
  207. }
  208. func (gs *GLS) Clear(mask uint) {
  209. C.glClear(C.GLbitfield(mask))
  210. }
  211. func (gs *GLS) CompileShader(shader uint32) {
  212. C.glCompileShader(C.GLuint(shader))
  213. }
  214. func (gs *GLS) CreateProgram() uint32 {
  215. p := C.glCreateProgram()
  216. return uint32(p)
  217. }
  218. func (gs *GLS) CreateShader(stype uint32) uint32 {
  219. h := C.glCreateShader(C.GLenum(stype))
  220. return uint32(h)
  221. }
  222. func (gs *GLS) DeleteBuffers(vbos ...uint32) {
  223. C.glDeleteBuffers(C.GLsizei(len(vbos)), (*C.GLuint)(&vbos[0]))
  224. }
  225. func (gs *GLS) DeleteShader(shader uint32) {
  226. C.glDeleteShader(C.GLuint(shader))
  227. }
  228. func (gs *GLS) DeleteProgram(program uint32) {
  229. C.glDeleteProgram(C.GLuint(program))
  230. }
  231. func (gs *GLS) DeleteTextures(tex ...uint32) {
  232. C.glDeleteTextures(C.GLsizei(len(tex)), (*C.GLuint)(&tex[0]))
  233. gs.stats.Textures -= len(tex)
  234. }
  235. func (gs *GLS) DeleteVertexArrays(vaos ...uint32) {
  236. C.glDeleteVertexArrays(C.GLsizei(len(vaos)), (*C.GLuint)(&vaos[0]))
  237. }
  238. func (gs *GLS) DepthFunc(mode uint32) {
  239. if gs.depthFunc == mode {
  240. return
  241. }
  242. C.glDepthFunc(C.GLenum(mode))
  243. gs.depthFunc = mode
  244. }
  245. func (gs *GLS) DepthMask(flag bool) {
  246. if gs.depthMask == intTrue && flag {
  247. return
  248. }
  249. if gs.depthMask == intFalse && !flag {
  250. return
  251. }
  252. C.glDepthMask(bool2c(flag))
  253. if flag {
  254. gs.depthMask = intTrue
  255. } else {
  256. gs.depthMask = intFalse
  257. }
  258. }
  259. func (gs *GLS) DrawArrays(mode uint32, first int32, count int32) {
  260. C.glDrawArrays(C.GLenum(mode), C.GLint(first), C.GLsizei(count))
  261. gs.stats.Drawcalls++
  262. }
  263. func (gs *GLS) DrawElements(mode uint32, count int32, itype uint32, start uint32) {
  264. C.glDrawElements(C.GLenum(mode), C.GLsizei(count), C.GLenum(itype), unsafe.Pointer(uintptr(start)))
  265. gs.stats.Drawcalls++
  266. }
  267. func (gs *GLS) Enable(cap int) {
  268. if gs.capabilities[cap] == capEnabled {
  269. gs.stats.Caphits++
  270. return
  271. }
  272. C.glEnable(C.GLenum(cap))
  273. gs.capabilities[cap] = capEnabled
  274. }
  275. func (gs *GLS) EnableVertexAttribArray(index uint32) {
  276. C.glEnableVertexAttribArray(C.GLuint(index))
  277. }
  278. func (gs *GLS) Disable(cap int) {
  279. if gs.capabilities[cap] == capDisabled {
  280. gs.stats.Caphits++
  281. return
  282. }
  283. C.glDisable(C.GLenum(cap))
  284. gs.capabilities[cap] = capDisabled
  285. }
  286. func (gs *GLS) CullFace(mode uint32) {
  287. C.glCullFace(C.GLenum(mode))
  288. }
  289. func (gs *GLS) FrontFace(mode uint32) {
  290. C.glFrontFace(C.GLenum(mode))
  291. }
  292. func (gs *GLS) GenBuffer() uint32 {
  293. var buf uint32
  294. C.glGenBuffers(1, (*C.GLuint)(&buf))
  295. gs.stats.Vbos++
  296. return buf
  297. }
  298. func (gs *GLS) GenerateMipmap(target uint32) {
  299. C.glGenerateMipmap(C.GLenum(target))
  300. }
  301. func (gs *GLS) GenTexture() uint32 {
  302. var tex uint32
  303. C.glGenTextures(1, (*C.GLuint)(&tex))
  304. gs.stats.Textures++
  305. return tex
  306. }
  307. func (gs *GLS) GenVertexArray() uint32 {
  308. var vao uint32
  309. C.glGenVertexArrays(1, (*C.GLuint)(&vao))
  310. gs.stats.Vaos++
  311. return vao
  312. }
  313. func (gs *GLS) GetAttribLocation(program uint32, name string) int32 {
  314. loc := C.glGetAttribLocation(C.GLuint(program), gs.gobufStr(name))
  315. return int32(loc)
  316. }
  317. func (gs *GLS) GetProgramiv(program, pname uint32, params *int32) {
  318. C.glGetProgramiv(C.GLuint(program), C.GLenum(pname), (*C.GLint)(params))
  319. }
  320. // GetProgramInfoLog returns the information log for the specified program object.
  321. func (gs *GLS) GetProgramInfoLog(program uint32) string {
  322. var length int32
  323. gs.GetProgramiv(program, INFO_LOG_LENGTH, &length)
  324. if length == 0 {
  325. return ""
  326. }
  327. C.glGetProgramInfoLog(C.GLuint(program), C.GLsizei(length), nil, gs.gobufSize(uint32(length)))
  328. return string(gs.gobuf[:length])
  329. }
  330. // GetShaderInfoLog returns the information log for the specified shader object.
  331. func (gs *GLS) GetShaderInfoLog(shader uint32) string {
  332. var length int32
  333. gs.GetShaderiv(shader, INFO_LOG_LENGTH, &length)
  334. if length == 0 {
  335. return ""
  336. }
  337. C.glGetShaderInfoLog(C.GLuint(shader), C.GLsizei(length), nil, gs.gobufSize(uint32(length)))
  338. return string(gs.gobuf[:length])
  339. }
  340. func (gs *GLS) GetString(name uint32) string {
  341. cs := C.glGetString(C.GLenum(name))
  342. return C.GoString((*C.char)(unsafe.Pointer(cs)))
  343. }
  344. // GetUniformLocation returns the location of a uniform variable for the specified program.
  345. func (gs *GLS) GetUniformLocation(program uint32, name string) int32 {
  346. loc := C.glGetUniformLocation(C.GLuint(program), gs.gobufStr(name))
  347. return int32(loc)
  348. }
  349. func (gs *GLS) GetViewport() (x, y, width, height int32) {
  350. return gs.viewportX, gs.viewportY, gs.viewportWidth, gs.viewportHeight
  351. }
  352. func (gs *GLS) LineWidth(width float32) {
  353. if gs.lineWidth == width {
  354. return
  355. }
  356. C.glLineWidth(C.GLfloat(width))
  357. gs.lineWidth = width
  358. }
  359. func (gs *GLS) LinkProgram(program uint32) {
  360. C.glLinkProgram(C.GLuint(program))
  361. }
  362. func (gs *GLS) SetDepthTest(enable bool) {
  363. if enable {
  364. gs.Enable(DEPTH_TEST)
  365. } else {
  366. gs.Disable(DEPTH_TEST)
  367. }
  368. }
  369. func (gs *GLS) SetSideView(mode int) {
  370. if gs.sideView == mode {
  371. return
  372. }
  373. switch mode {
  374. // Default: show only the front size
  375. case FrontSide:
  376. gs.Enable(CULL_FACE)
  377. C.glFrontFace(CCW)
  378. // Show only the back side
  379. case BackSide:
  380. gs.Enable(CULL_FACE)
  381. C.glFrontFace(CW)
  382. // Show both sides
  383. case DoubleSide:
  384. gs.Disable(CULL_FACE)
  385. default:
  386. panic("SetSideView() invalid mode")
  387. }
  388. gs.sideView = mode
  389. }
  390. func (gs *GLS) GetShaderiv(shader, pname uint32, params *int32) {
  391. C.glGetShaderiv(C.GLuint(shader), C.GLenum(pname), (*C.GLint)(params))
  392. }
  393. func (gs *GLS) ShaderSource(shader uint32, src string) {
  394. csource := gs.cbufStr(src)
  395. C.glShaderSource(C.GLuint(shader), 1, (**C.GLchar)(unsafe.Pointer(&csource)), nil)
  396. }
  397. func (gs *GLS) TexImage2D(target uint32, level int32, iformat int32, width int32, height int32, border int32, format uint32, itype uint32, data interface{}) {
  398. C.glTexImage2D(C.GLenum(target),
  399. C.GLint(level),
  400. C.GLint(iformat),
  401. C.GLsizei(width),
  402. C.GLsizei(height),
  403. C.GLint(border),
  404. C.GLenum(format),
  405. C.GLenum(itype),
  406. ptr(data))
  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), unsafe.Pointer(uintptr(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. if prog.handle == 0 {
  479. panic("Invalid program")
  480. }
  481. C.glUseProgram(C.GLuint(prog.handle))
  482. gs.Prog = prog
  483. // Inserts program in cache if not already there.
  484. if !gs.programs[prog] {
  485. gs.programs[prog] = true
  486. log.Debug("New Program activated. Total: %d", len(gs.programs))
  487. }
  488. }
  489. // Ptr takes a slice or pointer (to a singular scalar value or the first
  490. // element of an array or slice) and returns its GL-compatible address.
  491. //
  492. // For example:
  493. //
  494. // var data []uint8
  495. // ...
  496. // gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
  497. func ptr(data interface{}) unsafe.Pointer {
  498. if data == nil {
  499. return unsafe.Pointer(nil)
  500. }
  501. var addr unsafe.Pointer
  502. v := reflect.ValueOf(data)
  503. switch v.Type().Kind() {
  504. case reflect.Ptr:
  505. e := v.Elem()
  506. switch e.Kind() {
  507. case
  508. reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  509. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
  510. reflect.Float32, reflect.Float64:
  511. addr = unsafe.Pointer(e.UnsafeAddr())
  512. default:
  513. 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()))
  514. }
  515. case reflect.Uintptr:
  516. addr = unsafe.Pointer(v.Pointer())
  517. case reflect.Slice:
  518. addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
  519. default:
  520. 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()))
  521. }
  522. return addr
  523. }
  524. // bool2c convert a Go bool to C.GLboolean
  525. func bool2c(b bool) C.GLboolean {
  526. if b {
  527. return C.GLboolean(1)
  528. }
  529. return C.GLboolean(0)
  530. }
  531. // gobufSize returns a pointer to static buffer with the specified size not including the terminator.
  532. // If there is available space, there is no memory allocation.
  533. func (gs *GLS) gobufSize(size uint32) *C.GLchar {
  534. if size+1 > uint32(len(gs.gobuf)) {
  535. gs.gobuf = make([]byte, size+1)
  536. }
  537. return (*C.GLchar)(unsafe.Pointer(&gs.gobuf[0]))
  538. }
  539. // gobufStr converts a Go String to a C string by copying it to a static buffer
  540. // and returning a pointer to the start of the buffer.
  541. // If there is available space, there is no memory allocation.
  542. func (gs *GLS) gobufStr(s string) *C.GLchar {
  543. p := gs.gobufSize(uint32(len(s) + 1))
  544. copy(gs.gobuf, s)
  545. gs.gobuf[len(s)] = 0
  546. return p
  547. }
  548. // cbufSize returns a pointer to static buffer with C memory
  549. // If there is available space, there is no memory allocation.
  550. func (gs *GLS) cbufSize(size uint32) *C.GLchar {
  551. if size > uint32(len(gs.cbuf)) {
  552. if len(gs.cbuf) > 0 {
  553. C.free(unsafe.Pointer(&gs.cbuf[0]))
  554. }
  555. p := C.malloc(C.size_t(size))
  556. gs.cbuf = (*[1 << 30]byte)(unsafe.Pointer(p))[:size:size]
  557. }
  558. return (*C.GLchar)(unsafe.Pointer(&gs.cbuf[0]))
  559. }
  560. // cbufStr converts a Go String to a C string by copying it to a single pre-allocated buffer
  561. // using C memory and returning a pointer to the start of the buffer.
  562. // If there is available space, there is no memory allocation.
  563. func (gs *GLS) cbufStr(s string) *C.GLchar {
  564. p := gs.cbufSize(uint32(len(s) + 1))
  565. copy(gs.cbuf, s)
  566. gs.cbuf[len(s)] = 0
  567. return p
  568. }